core/types: remove duplicate serialtype implementation

This commit is contained in:
Jussi Saurio 2025-04-24 15:36:54 +03:00
parent 0c800524af
commit af6a783f4d
2 changed files with 221 additions and 294 deletions

View file

@ -47,7 +47,7 @@ use crate::io::{Buffer, Completion, ReadCompletion, SyncCompletion, WriteComplet
use crate::storage::buffer_pool::BufferPool;
use crate::storage::database::DatabaseStorage;
use crate::storage::pager::Pager;
use crate::types::{ImmutableRecord, RawSlice, RefValue, TextRef, TextSubtype};
use crate::types::{ImmutableRecord, RawSlice, RefValue, SerialType, TextRef, TextSubtype};
use crate::{File, Result};
use std::cell::RefCell;
use std::mem::MaybeUninit;
@ -985,107 +985,8 @@ fn read_payload(unread: &'static [u8], payload_size: usize) -> (&'static [u8], O
}
}
pub type SerialType = u64;
pub const SERIAL_TYPE_NULL: SerialType = 0;
pub const SERIAL_TYPE_INT8: SerialType = 1;
pub const SERIAL_TYPE_BEINT16: SerialType = 2;
pub const SERIAL_TYPE_BEINT24: SerialType = 3;
pub const SERIAL_TYPE_BEINT32: SerialType = 4;
pub const SERIAL_TYPE_BEINT48: SerialType = 5;
pub const SERIAL_TYPE_BEINT64: SerialType = 6;
pub const SERIAL_TYPE_BEFLOAT64: SerialType = 7;
pub const SERIAL_TYPE_CONSTINT0: SerialType = 8;
pub const SERIAL_TYPE_CONSTINT1: SerialType = 9;
pub trait SerialTypeExt {
fn is_null(self) -> bool;
fn is_int8(self) -> bool;
fn is_beint16(self) -> bool;
fn is_beint24(self) -> bool;
fn is_beint32(self) -> bool;
fn is_beint48(self) -> bool;
fn is_beint64(self) -> bool;
fn is_befloat64(self) -> bool;
fn is_constint0(self) -> bool;
fn is_constint1(self) -> bool;
fn is_blob(self) -> bool;
fn is_string(self) -> bool;
fn blob_size(self) -> usize;
fn string_size(self) -> usize;
fn is_valid(self) -> bool;
}
impl SerialTypeExt for u64 {
fn is_null(self) -> bool {
self == SERIAL_TYPE_NULL
}
fn is_int8(self) -> bool {
self == SERIAL_TYPE_INT8
}
fn is_beint16(self) -> bool {
self == SERIAL_TYPE_BEINT16
}
fn is_beint24(self) -> bool {
self == SERIAL_TYPE_BEINT24
}
fn is_beint32(self) -> bool {
self == SERIAL_TYPE_BEINT32
}
fn is_beint48(self) -> bool {
self == SERIAL_TYPE_BEINT48
}
fn is_beint64(self) -> bool {
self == SERIAL_TYPE_BEINT64
}
fn is_befloat64(self) -> bool {
self == SERIAL_TYPE_BEFLOAT64
}
fn is_constint0(self) -> bool {
self == SERIAL_TYPE_CONSTINT0
}
fn is_constint1(self) -> bool {
self == SERIAL_TYPE_CONSTINT1
}
fn is_blob(self) -> bool {
self >= 12 && self % 2 == 0
}
fn is_string(self) -> bool {
self >= 13 && self % 2 == 1
}
fn blob_size(self) -> usize {
debug_assert!(self.is_blob());
((self - 12) / 2) as usize
}
fn string_size(self) -> usize {
debug_assert!(self.is_string());
((self - 13) / 2) as usize
}
fn is_valid(self) -> bool {
self <= 9 || self.is_blob() || self.is_string()
}
}
pub fn validate_serial_type(value: u64) -> Result<SerialType> {
if value.is_valid() {
Ok(value)
} else {
crate::bail_corrupt_error!("Invalid serial type: {}", value)
}
value.try_into()
}
pub struct SmallVec<T, const N: usize = 64> {
@ -1180,7 +1081,7 @@ pub fn read_record(payload: &[u8], reuse_immutable: &mut ImmutableRecord) -> Res
let mut serial_types = SmallVec::<u64, 64>::new();
while header_size > 0 {
let (serial_type, nr) = read_varint(&reuse_immutable.get_payload()[pos..])?;
let serial_type = validate_serial_type(serial_type)?;
let _ = validate_serial_type(serial_type)?;
serial_types.push(serial_type);
pos += nr;
assert!(header_size >= nr);
@ -1189,14 +1090,17 @@ pub fn read_record(payload: &[u8], reuse_immutable: &mut ImmutableRecord) -> Res
for &serial_type in &serial_types.data[..serial_types.len.min(serial_types.data.len())] {
let (value, n) = read_value(&reuse_immutable.get_payload()[pos..], unsafe {
*serial_type.as_ptr()
serial_type.assume_init().try_into()?
})?;
pos += n;
reuse_immutable.add_value(value);
}
if let Some(extra) = serial_types.extra_data.as_ref() {
for serial_type in extra {
let (value, n) = read_value(&reuse_immutable.get_payload()[pos..], *serial_type)?;
let (value, n) = read_value(
&reuse_immutable.get_payload()[pos..],
(*serial_type).try_into()?,
)?;
pos += n;
reuse_immutable.add_value(value);
}
@ -1209,140 +1113,123 @@ pub fn read_record(payload: &[u8], reuse_immutable: &mut ImmutableRecord) -> Res
/// always.
#[inline(always)]
pub fn read_value(buf: &[u8], serial_type: SerialType) -> Result<(RefValue, usize)> {
if serial_type.is_null() {
return Ok((RefValue::Null, 0));
}
if serial_type.is_int8() {
if buf.is_empty() {
crate::bail_corrupt_error!("Invalid UInt8 value");
match serial_type {
SerialType::Null => Ok((RefValue::Null, 0)),
SerialType::I8 => {
if buf.is_empty() {
crate::bail_corrupt_error!("Invalid UInt8 value");
}
let val = buf[0] as i8;
Ok((RefValue::Integer(val as i64), 1))
}
let val = buf[0] as i8;
return Ok((RefValue::Integer(val as i64), 1));
}
if serial_type.is_beint16() {
if buf.len() < 2 {
crate::bail_corrupt_error!("Invalid BEInt16 value");
SerialType::I16 => {
if buf.len() < 2 {
crate::bail_corrupt_error!("Invalid BEInt16 value");
}
Ok((
RefValue::Integer(i16::from_be_bytes([buf[0], buf[1]]) as i64),
2,
))
}
return Ok((
RefValue::Integer(i16::from_be_bytes([buf[0], buf[1]]) as i64),
2,
));
}
if serial_type.is_beint24() {
if buf.len() < 3 {
crate::bail_corrupt_error!("Invalid BEInt24 value");
SerialType::I24 => {
if buf.len() < 3 {
crate::bail_corrupt_error!("Invalid BEInt24 value");
}
let sign_extension = if buf[0] <= 127 { 0 } else { 255 };
Ok((
RefValue::Integer(
i32::from_be_bytes([sign_extension, buf[0], buf[1], buf[2]]) as i64
),
3,
))
}
let sign_extension = if buf[0] <= 127 { 0 } else { 255 };
return Ok((
RefValue::Integer(i32::from_be_bytes([sign_extension, buf[0], buf[1], buf[2]]) as i64),
3,
));
}
if serial_type.is_beint32() {
if buf.len() < 4 {
crate::bail_corrupt_error!("Invalid BEInt32 value");
SerialType::I32 => {
if buf.len() < 4 {
crate::bail_corrupt_error!("Invalid BEInt32 value");
}
Ok((
RefValue::Integer(i32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]) as i64),
4,
))
}
return Ok((
RefValue::Integer(i32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]) as i64),
4,
));
}
if serial_type.is_beint48() {
if buf.len() < 6 {
crate::bail_corrupt_error!("Invalid BEInt48 value");
SerialType::I48 => {
if buf.len() < 6 {
crate::bail_corrupt_error!("Invalid BEInt48 value");
}
let sign_extension = if buf[0] <= 127 { 0 } else { 255 };
Ok((
RefValue::Integer(i64::from_be_bytes([
sign_extension,
sign_extension,
buf[0],
buf[1],
buf[2],
buf[3],
buf[4],
buf[5],
])),
6,
))
}
let sign_extension = if buf[0] <= 127 { 0 } else { 255 };
return Ok((
RefValue::Integer(i64::from_be_bytes([
sign_extension,
sign_extension,
buf[0],
buf[1],
buf[2],
buf[3],
buf[4],
buf[5],
])),
6,
));
}
if serial_type.is_beint64() {
if buf.len() < 8 {
crate::bail_corrupt_error!("Invalid BEInt64 value");
SerialType::I64 => {
if buf.len() < 8 {
crate::bail_corrupt_error!("Invalid BEInt64 value");
}
Ok((
RefValue::Integer(i64::from_be_bytes([
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
])),
8,
))
}
return Ok((
RefValue::Integer(i64::from_be_bytes([
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
])),
8,
));
}
if serial_type.is_befloat64() {
if buf.len() < 8 {
crate::bail_corrupt_error!("Invalid BEFloat64 value");
SerialType::F64 => {
if buf.len() < 8 {
crate::bail_corrupt_error!("Invalid BEFloat64 value");
}
Ok((
RefValue::Float(f64::from_be_bytes([
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
])),
8,
))
}
return Ok((
RefValue::Float(f64::from_be_bytes([
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
])),
8,
));
}
if serial_type.is_constint0() {
return Ok((RefValue::Integer(0), 0));
}
if serial_type.is_constint1() {
return Ok((RefValue::Integer(1), 0));
}
if serial_type.is_blob() {
let n = serial_type.blob_size();
if buf.len() < n {
crate::bail_corrupt_error!("Invalid Blob value");
SerialType::ConstInt0 => Ok((RefValue::Integer(0), 0)),
SerialType::ConstInt1 => Ok((RefValue::Integer(1), 0)),
SerialType::Blob { content_size } => {
if buf.len() < content_size {
crate::bail_corrupt_error!("Invalid Blob value");
}
if content_size == 0 {
Ok((RefValue::Blob(RawSlice::new(std::ptr::null(), 0)), 0))
} else {
let ptr = &buf[0] as *const u8;
let slice = RawSlice::new(ptr, content_size);
Ok((RefValue::Blob(slice), content_size))
}
}
if n == 0 {
return Ok((RefValue::Blob(RawSlice::new(std::ptr::null(), 0)), 0));
SerialType::Text { content_size } => {
if buf.len() < content_size {
crate::bail_corrupt_error!(
"Invalid String value, length {} < expected length {}",
buf.len(),
content_size
);
}
let slice = if content_size == 0 {
RawSlice::new(std::ptr::null(), 0)
} else {
let ptr = &buf[0] as *const u8;
RawSlice::new(ptr, content_size)
};
Ok((
RefValue::Text(TextRef {
value: slice,
subtype: TextSubtype::Text,
}),
content_size,
))
}
let ptr = &buf[0] as *const u8;
let slice = RawSlice::new(ptr, n);
return Ok((RefValue::Blob(slice), n));
}
if serial_type.is_string() {
let n = serial_type.string_size();
if buf.len() < n {
crate::bail_corrupt_error!(
"Invalid String value, length {} < expected length {}",
buf.len(),
n
);
}
let slice = if n == 0 {
RawSlice::new(std::ptr::null(), 0)
} else {
let ptr = &buf[0] as *const u8;
RawSlice::new(ptr, n)
};
return Ok((
RefValue::Text(TextRef {
value: slice,
subtype: TextSubtype::Text,
}),
n,
));
}
// This should never happen if validate_serial_type is used correctly
crate::bail_corrupt_error!("Invalid serial type: {}", serial_type)
}
#[inline(always)]
@ -1676,32 +1563,32 @@ mod tests {
use rstest::rstest;
#[rstest]
#[case(&[], SERIAL_TYPE_NULL, OwnedValue::Null)]
#[case(&[255], SERIAL_TYPE_INT8, OwnedValue::Integer(-1))]
#[case(&[0x12, 0x34], SERIAL_TYPE_BEINT16, OwnedValue::Integer(0x1234))]
#[case(&[0xFE], SERIAL_TYPE_INT8, OwnedValue::Integer(-2))]
#[case(&[0x12, 0x34, 0x56], SERIAL_TYPE_BEINT24, OwnedValue::Integer(0x123456))]
#[case(&[0x12, 0x34, 0x56, 0x78], SERIAL_TYPE_BEINT32, OwnedValue::Integer(0x12345678))]
#[case(&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC], SERIAL_TYPE_BEINT48, OwnedValue::Integer(0x123456789ABC))]
#[case(&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF], SERIAL_TYPE_BEINT64, OwnedValue::Integer(0x123456789ABCDEFF))]
#[case(&[0x40, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18], SERIAL_TYPE_BEFLOAT64, OwnedValue::Float(std::f64::consts::PI))]
#[case(&[1, 2], SERIAL_TYPE_CONSTINT0, OwnedValue::Integer(0))]
#[case(&[65, 66], SERIAL_TYPE_CONSTINT1, OwnedValue::Integer(1))]
#[case(&[1, 2, 3], 18, OwnedValue::Blob(vec![1, 2, 3].into()))]
#[case(&[], 12, OwnedValue::Blob(vec![].into()))] // empty blob
#[case(&[65, 66, 67], 19, OwnedValue::build_text("ABC"))]
#[case(&[0x80], SERIAL_TYPE_INT8, OwnedValue::Integer(-128))]
#[case(&[0x80, 0], SERIAL_TYPE_BEINT16, OwnedValue::Integer(-32768))]
#[case(&[0x80, 0, 0], SERIAL_TYPE_BEINT24, OwnedValue::Integer(-8388608))]
#[case(&[0x80, 0, 0, 0], SERIAL_TYPE_BEINT32, OwnedValue::Integer(-2147483648))]
#[case(&[0x80, 0, 0, 0, 0, 0], SERIAL_TYPE_BEINT48, OwnedValue::Integer(-140737488355328))]
#[case(&[0x80, 0, 0, 0, 0, 0, 0, 0], SERIAL_TYPE_BEINT64, OwnedValue::Integer(-9223372036854775808))]
#[case(&[0x7f], SERIAL_TYPE_INT8, OwnedValue::Integer(127))]
#[case(&[0x7f, 0xff], SERIAL_TYPE_BEINT16, OwnedValue::Integer(32767))]
#[case(&[0x7f, 0xff, 0xff], SERIAL_TYPE_BEINT24, OwnedValue::Integer(8388607))]
#[case(&[0x7f, 0xff, 0xff, 0xff], SERIAL_TYPE_BEINT32, OwnedValue::Integer(2147483647))]
#[case(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff], SERIAL_TYPE_BEINT48, OwnedValue::Integer(140737488355327))]
#[case(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], SERIAL_TYPE_BEINT64, OwnedValue::Integer(9223372036854775807))]
#[case(&[], SerialType::Null, OwnedValue::Null)]
#[case(&[255], SerialType::I8, OwnedValue::Integer(-1))]
#[case(&[0x12, 0x34], SerialType::I16, OwnedValue::Integer(0x1234))]
#[case(&[0xFE], SerialType::I8, OwnedValue::Integer(-2))]
#[case(&[0x12, 0x34, 0x56], SerialType::I24, OwnedValue::Integer(0x123456))]
#[case(&[0x12, 0x34, 0x56, 0x78], SerialType::I32, OwnedValue::Integer(0x12345678))]
#[case(&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC], SerialType::I48, OwnedValue::Integer(0x123456789ABC))]
#[case(&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF], SerialType::I64, OwnedValue::Integer(0x123456789ABCDEFF))]
#[case(&[0x40, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18], SerialType::F64, OwnedValue::Float(std::f64::consts::PI))]
#[case(&[1, 2], SerialType::ConstInt0, OwnedValue::Integer(0))]
#[case(&[65, 66], SerialType::ConstInt1, OwnedValue::Integer(1))]
#[case(&[1, 2, 3], SerialType::Blob { content_size: 3 }, OwnedValue::Blob(vec![1, 2, 3].into()))]
#[case(&[], SerialType::Blob { content_size: 0 }, OwnedValue::Blob(vec![].into()))] // empty blob
#[case(&[65, 66, 67], SerialType::Text { content_size: 3 }, OwnedValue::build_text("ABC"))]
#[case(&[0x80], SerialType::I8, OwnedValue::Integer(-128))]
#[case(&[0x80, 0], SerialType::I16, OwnedValue::Integer(-32768))]
#[case(&[0x80, 0, 0], SerialType::I24, OwnedValue::Integer(-8388608))]
#[case(&[0x80, 0, 0, 0], SerialType::I32, OwnedValue::Integer(-2147483648))]
#[case(&[0x80, 0, 0, 0, 0, 0], SerialType::I48, OwnedValue::Integer(-140737488355328))]
#[case(&[0x80, 0, 0, 0, 0, 0, 0, 0], SerialType::I64, OwnedValue::Integer(-9223372036854775808))]
#[case(&[0x7f], SerialType::I8, OwnedValue::Integer(127))]
#[case(&[0x7f, 0xff], SerialType::I16, OwnedValue::Integer(32767))]
#[case(&[0x7f, 0xff, 0xff], SerialType::I24, OwnedValue::Integer(8388607))]
#[case(&[0x7f, 0xff, 0xff, 0xff], SerialType::I32, OwnedValue::Integer(2147483647))]
#[case(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff], SerialType::I48, OwnedValue::Integer(140737488355327))]
#[case(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], SerialType::I64, OwnedValue::Integer(9223372036854775807))]
fn test_read_value(
#[case] buf: &[u8],
#[case] serial_type: SerialType,
@ -1713,46 +1600,47 @@ mod tests {
#[test]
fn test_serial_type_helpers() {
assert!(SERIAL_TYPE_NULL.is_null());
assert!(SERIAL_TYPE_INT8.is_int8());
assert!(SERIAL_TYPE_BEINT16.is_beint16());
assert!(SERIAL_TYPE_BEINT24.is_beint24());
assert!(SERIAL_TYPE_BEINT32.is_beint32());
assert!(SERIAL_TYPE_BEINT48.is_beint48());
assert!(SERIAL_TYPE_BEINT64.is_beint64());
assert!(SERIAL_TYPE_BEFLOAT64.is_befloat64());
assert!(SERIAL_TYPE_CONSTINT0.is_constint0());
assert!(SERIAL_TYPE_CONSTINT1.is_constint1());
assert!(12u64.is_blob());
assert!(14u64.is_blob());
assert!(13u64.is_string());
assert!(15u64.is_string());
assert_eq!(12u64.blob_size(), 0);
assert_eq!(14u64.blob_size(), 1);
assert_eq!(16u64.blob_size(), 2);
assert_eq!(13u64.string_size(), 0);
assert_eq!(15u64.string_size(), 1);
assert_eq!(17u64.string_size(), 2);
assert_eq!(
TryInto::<SerialType>::try_into(12u64).unwrap(),
SerialType::Blob { content_size: 0 }
);
assert_eq!(
TryInto::<SerialType>::try_into(14u64).unwrap(),
SerialType::Blob { content_size: 1 }
);
assert_eq!(
TryInto::<SerialType>::try_into(13u64).unwrap(),
SerialType::Text { content_size: 0 }
);
assert_eq!(
TryInto::<SerialType>::try_into(15u64).unwrap(),
SerialType::Text { content_size: 1 }
);
assert_eq!(
TryInto::<SerialType>::try_into(16u64).unwrap(),
SerialType::Blob { content_size: 2 }
);
assert_eq!(
TryInto::<SerialType>::try_into(17u64).unwrap(),
SerialType::Text { content_size: 2 }
);
}
#[rstest]
#[case(0, SERIAL_TYPE_NULL)]
#[case(1, SERIAL_TYPE_INT8)]
#[case(2, SERIAL_TYPE_BEINT16)]
#[case(3, SERIAL_TYPE_BEINT24)]
#[case(4, SERIAL_TYPE_BEINT32)]
#[case(5, SERIAL_TYPE_BEINT48)]
#[case(6, SERIAL_TYPE_BEINT64)]
#[case(7, SERIAL_TYPE_BEFLOAT64)]
#[case(8, SERIAL_TYPE_CONSTINT0)]
#[case(9, SERIAL_TYPE_CONSTINT1)]
#[case(12, 12)] // Blob(0)
#[case(13, 13)] // String(0)
#[case(14, 14)] // Blob(1)
#[case(15, 15)] // String(1)
#[case(0, SerialType::Null)]
#[case(1, SerialType::I8)]
#[case(2, SerialType::I16)]
#[case(3, SerialType::I24)]
#[case(4, SerialType::I32)]
#[case(5, SerialType::I48)]
#[case(6, SerialType::I64)]
#[case(7, SerialType::F64)]
#[case(8, SerialType::ConstInt0)]
#[case(9, SerialType::ConstInt1)]
#[case(12, SerialType::Blob { content_size: 0 })]
#[case(13, SerialType::Text { content_size: 0 })]
#[case(14, SerialType::Blob { content_size: 1 })]
#[case(15, SerialType::Text { content_size: 1 })]
fn test_validate_serial_type(#[case] input: u64, #[case] expected: SerialType) {
let result = validate_serial_type(input).unwrap();
assert_eq!(result, expected);

View file

@ -787,7 +787,7 @@ impl ImmutableRecord {
serials.push((serial_type_buf, n));
let value_size = match serial_type {
SerialType::Null => 0,
SerialType::Null | SerialType::ConstInt0 | SerialType::ConstInt1 => 0,
SerialType::I8 => 1,
SerialType::I16 => 2,
SerialType::I24 => 3,
@ -845,6 +845,7 @@ impl ImmutableRecord {
values.push(RefValue::Integer(*i));
let serial_type = SerialType::from(value);
match serial_type {
SerialType::ConstInt0 | SerialType::ConstInt1 => {}
SerialType::I8 => writer.extend_from_slice(&(*i as i8).to_be_bytes()),
SerialType::I16 => writer.extend_from_slice(&(*i as i16).to_be_bytes()),
SerialType::I24 => {
@ -853,7 +854,7 @@ impl ImmutableRecord {
SerialType::I32 => writer.extend_from_slice(&(*i as i32).to_be_bytes()),
SerialType::I48 => writer.extend_from_slice(&i.to_be_bytes()[2..]), // remove 2 most significant bytes
SerialType::I64 => writer.extend_from_slice(&i.to_be_bytes()),
_ => unreachable!(),
other => panic!("Serial type is not an integer: {:?}", other),
}
}
OwnedValue::Float(f) => {
@ -1113,7 +1114,7 @@ const I48_HIGH: i64 = 140737488355327;
/// Sqlite Serial Types
/// https://www.sqlite.org/fileformat.html#record_format
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum SerialType {
pub enum SerialType {
Null,
I8,
I16,
@ -1122,6 +1123,8 @@ enum SerialType {
I48,
I64,
F64,
ConstInt0,
ConstInt1,
Text { content_size: usize },
Blob { content_size: usize },
}
@ -1131,6 +1134,8 @@ impl From<&OwnedValue> for SerialType {
match value {
OwnedValue::Null => SerialType::Null,
OwnedValue::Integer(i) => match i {
0 => SerialType::ConstInt0,
1 => SerialType::ConstInt1,
i if *i >= I8_LOW && *i <= I8_HIGH => SerialType::I8,
i if *i >= I16_LOW && *i <= I16_HIGH => SerialType::I16,
i if *i >= I24_LOW && *i <= I24_HIGH => SerialType::I24,
@ -1160,12 +1165,46 @@ impl From<SerialType> for u64 {
SerialType::I48 => 5,
SerialType::I64 => 6,
SerialType::F64 => 7,
SerialType::ConstInt0 => 8,
SerialType::ConstInt1 => 9,
SerialType::Text { content_size } => (content_size * 2 + 13) as u64,
SerialType::Blob { content_size } => (content_size * 2 + 12) as u64,
}
}
}
impl TryFrom<u64> for SerialType {
type Error = LimboError;
fn try_from(serial_type: u64) -> Result<Self> {
match serial_type {
0 => Ok(SerialType::Null),
1 => Ok(SerialType::I8),
2 => Ok(SerialType::I16),
3 => Ok(SerialType::I24),
4 => Ok(SerialType::I32),
5 => Ok(SerialType::I48),
6 => Ok(SerialType::I64),
7 => Ok(SerialType::F64),
8 => Ok(SerialType::ConstInt0),
9 => Ok(SerialType::ConstInt1),
n if n >= 12 => match n % 2 {
0 => Ok(SerialType::Blob {
content_size: (n as usize - 12) / 2,
}),
1 => Ok(SerialType::Text {
content_size: (n as usize - 13) / 2,
}),
_ => unreachable!(),
},
_ => Err(LimboError::Corrupt(format!(
"Invalid serial type: {}",
serial_type
))),
}
}
}
impl Record {
pub fn new(values: Vec<OwnedValue>) -> Self {
Self { values }