types: refactor serialtype again to make it faster

This commit is contained in:
Jussi Saurio
2025-04-24 17:28:31 +03:00
parent 2ffeefe165
commit 7921d7c2e0
2 changed files with 223 additions and 162 deletions

View File

@@ -47,7 +47,9 @@ 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, SerialType, TextRef, TextSubtype};
use crate::types::{
ImmutableRecord, RawSlice, RefValue, SerialType, SerialTypeKind, TextRef, TextSubtype,
};
use crate::{File, Result};
use std::cell::RefCell;
use std::mem::MaybeUninit;
@@ -1117,16 +1119,16 @@ 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)> {
match serial_type {
SerialType::Null => Ok((RefValue::Null, 0)),
SerialType::I8 => {
match serial_type.kind() {
SerialTypeKind::Null => Ok((RefValue::Null, 0)),
SerialTypeKind::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))
}
SerialType::I16 => {
SerialTypeKind::I16 => {
if buf.len() < 2 {
crate::bail_corrupt_error!("Invalid BEInt16 value");
}
@@ -1135,7 +1137,7 @@ pub fn read_value(buf: &[u8], serial_type: SerialType) -> Result<(RefValue, usiz
2,
))
}
SerialType::I24 => {
SerialTypeKind::I24 => {
if buf.len() < 3 {
crate::bail_corrupt_error!("Invalid BEInt24 value");
}
@@ -1147,7 +1149,7 @@ pub fn read_value(buf: &[u8], serial_type: SerialType) -> Result<(RefValue, usiz
3,
))
}
SerialType::I32 => {
SerialTypeKind::I32 => {
if buf.len() < 4 {
crate::bail_corrupt_error!("Invalid BEInt32 value");
}
@@ -1156,7 +1158,7 @@ pub fn read_value(buf: &[u8], serial_type: SerialType) -> Result<(RefValue, usiz
4,
))
}
SerialType::I48 => {
SerialTypeKind::I48 => {
if buf.len() < 6 {
crate::bail_corrupt_error!("Invalid BEInt48 value");
}
@@ -1175,7 +1177,7 @@ pub fn read_value(buf: &[u8], serial_type: SerialType) -> Result<(RefValue, usiz
6,
))
}
SerialType::I64 => {
SerialTypeKind::I64 => {
if buf.len() < 8 {
crate::bail_corrupt_error!("Invalid BEInt64 value");
}
@@ -1186,7 +1188,7 @@ pub fn read_value(buf: &[u8], serial_type: SerialType) -> Result<(RefValue, usiz
8,
))
}
SerialType::F64 => {
SerialTypeKind::F64 => {
if buf.len() < 8 {
crate::bail_corrupt_error!("Invalid BEFloat64 value");
}
@@ -1197,9 +1199,10 @@ pub fn read_value(buf: &[u8], serial_type: SerialType) -> Result<(RefValue, usiz
8,
))
}
SerialType::ConstInt0 => Ok((RefValue::Integer(0), 0)),
SerialType::ConstInt1 => Ok((RefValue::Integer(1), 0)),
SerialType::Blob { content_size } => {
SerialTypeKind::ConstInt0 => Ok((RefValue::Integer(0), 0)),
SerialTypeKind::ConstInt1 => Ok((RefValue::Integer(1), 0)),
SerialTypeKind::Blob => {
let content_size = serial_type.size();
if buf.len() < content_size {
crate::bail_corrupt_error!("Invalid Blob value");
}
@@ -1211,7 +1214,8 @@ pub fn read_value(buf: &[u8], serial_type: SerialType) -> Result<(RefValue, usiz
Ok((RefValue::Blob(slice), content_size))
}
}
SerialType::Text { content_size } => {
SerialTypeKind::Text => {
let content_size = serial_type.size();
if buf.len() < content_size {
crate::bail_corrupt_error!(
"Invalid String value, length {} < expected length {}",
@@ -1567,32 +1571,32 @@ mod tests {
use rstest::rstest;
#[rstest]
#[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))]
#[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::const_int0(), OwnedValue::Integer(0))]
#[case(&[65, 66], SerialType::const_int1(), OwnedValue::Integer(1))]
#[case(&[1, 2, 3], SerialType::blob(3), OwnedValue::Blob(vec![1, 2, 3].into()))]
#[case(&[], SerialType::blob(0), OwnedValue::Blob(vec![].into()))] // empty blob
#[case(&[65, 66, 67], SerialType::text(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,
@@ -1606,45 +1610,45 @@ mod tests {
fn test_serial_type_helpers() {
assert_eq!(
TryInto::<SerialType>::try_into(12u64).unwrap(),
SerialType::Blob { content_size: 0 }
SerialType::blob(0)
);
assert_eq!(
TryInto::<SerialType>::try_into(14u64).unwrap(),
SerialType::Blob { content_size: 1 }
SerialType::blob(1)
);
assert_eq!(
TryInto::<SerialType>::try_into(13u64).unwrap(),
SerialType::Text { content_size: 0 }
SerialType::text(0)
);
assert_eq!(
TryInto::<SerialType>::try_into(15u64).unwrap(),
SerialType::Text { content_size: 1 }
SerialType::text(1)
);
assert_eq!(
TryInto::<SerialType>::try_into(16u64).unwrap(),
SerialType::Blob { content_size: 2 }
SerialType::blob(2)
);
assert_eq!(
TryInto::<SerialType>::try_into(17u64).unwrap(),
SerialType::Text { content_size: 2 }
SerialType::text(2)
);
}
#[rstest]
#[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 })]
#[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::const_int0())]
#[case(9, SerialType::const_int1())]
#[case(12, SerialType::blob(0))]
#[case(13, SerialType::text(0))]
#[case(14, SerialType::blob(1))]
#[case(15, SerialType::text(1))]
fn test_parse_serial_type(#[case] input: u64, #[case] expected: SerialType) {
let result = SerialType::try_from(input).unwrap();
assert_eq!(result, expected);

View File

@@ -171,13 +171,13 @@ impl OwnedValue {
OwnedValue::Null => {}
OwnedValue::Integer(i) => {
let serial_type = SerialType::from(self);
match serial_type {
SerialType::I8 => out.extend_from_slice(&(*i as i8).to_be_bytes()),
SerialType::I16 => out.extend_from_slice(&(*i as i16).to_be_bytes()),
SerialType::I24 => out.extend_from_slice(&(*i as i32).to_be_bytes()[1..]), // remove most significant byte
SerialType::I32 => out.extend_from_slice(&(*i as i32).to_be_bytes()),
SerialType::I48 => out.extend_from_slice(&i.to_be_bytes()[2..]), // remove 2 most significant bytes
SerialType::I64 => out.extend_from_slice(&i.to_be_bytes()),
match serial_type.kind() {
SerialTypeKind::I8 => out.extend_from_slice(&(*i as i8).to_be_bytes()),
SerialTypeKind::I16 => out.extend_from_slice(&(*i as i16).to_be_bytes()),
SerialTypeKind::I24 => out.extend_from_slice(&(*i as i32).to_be_bytes()[1..]), // remove most significant byte
SerialTypeKind::I32 => out.extend_from_slice(&(*i as i32).to_be_bytes()),
SerialTypeKind::I48 => out.extend_from_slice(&i.to_be_bytes()[2..]), // remove 2 most significant bytes
SerialTypeKind::I64 => out.extend_from_slice(&i.to_be_bytes()),
_ => unreachable!(),
}
}
@@ -786,18 +786,7 @@ impl ImmutableRecord {
let n = write_varint(&mut serial_type_buf[0..], serial_type.into());
serials.push((serial_type_buf, n));
let value_size = match serial_type {
SerialType::Null | SerialType::ConstInt0 | SerialType::ConstInt1 => 0,
SerialType::I8 => 1,
SerialType::I16 => 2,
SerialType::I24 => 3,
SerialType::I32 => 4,
SerialType::I48 => 6,
SerialType::I64 => 8,
SerialType::F64 => 8,
SerialType::Text { content_size } => content_size,
SerialType::Blob { content_size } => content_size,
};
let value_size = serial_type.size();
size_header += n;
size_values += value_size;
@@ -844,16 +833,16 @@ impl ImmutableRecord {
OwnedValue::Integer(i) => {
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 => {
match serial_type.kind() {
SerialTypeKind::ConstInt0 | SerialTypeKind::ConstInt1 => {}
SerialTypeKind::I8 => writer.extend_from_slice(&(*i as i8).to_be_bytes()),
SerialTypeKind::I16 => writer.extend_from_slice(&(*i as i16).to_be_bytes()),
SerialTypeKind::I24 => {
writer.extend_from_slice(&(*i as i32).to_be_bytes()[1..])
} // remove most significant byte
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()),
SerialTypeKind::I32 => writer.extend_from_slice(&(*i as i32).to_be_bytes()),
SerialTypeKind::I48 => writer.extend_from_slice(&i.to_be_bytes()[2..]), // remove 2 most significant bytes
SerialTypeKind::I64 => writer.extend_from_slice(&i.to_be_bytes()),
other => panic!("Serial type is not an integer: {:?}", other),
}
}
@@ -1114,7 +1103,11 @@ const I48_HIGH: i64 = 140737488355327;
/// Sqlite Serial Types
/// https://www.sqlite.org/fileformat.html#record_format
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum SerialType {
#[repr(transparent)]
pub struct SerialType(u64);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum SerialTypeKind {
Null,
I8,
I16,
@@ -1125,8 +1118,8 @@ pub enum SerialType {
F64,
ConstInt0,
ConstInt1,
Text { content_size: usize },
Blob { content_size: usize },
Text,
Blob,
}
impl SerialType {
@@ -1134,81 +1127,143 @@ impl SerialType {
pub fn u64_is_valid_serial_type(n: u64) -> bool {
n != 10 && n != 11
}
const NULL: Self = Self(0);
const I8: Self = Self(1);
const I16: Self = Self(2);
const I24: Self = Self(3);
const I32: Self = Self(4);
const I48: Self = Self(5);
const I64: Self = Self(6);
const F64: Self = Self(7);
const CONST_INT0: Self = Self(8);
const CONST_INT1: Self = Self(9);
pub fn null() -> Self {
Self::NULL
}
pub fn i8() -> Self {
Self::I8
}
pub fn i16() -> Self {
Self::I16
}
pub fn i24() -> Self {
Self::I24
}
pub fn i32() -> Self {
Self::I32
}
pub fn i48() -> Self {
Self::I48
}
pub fn i64() -> Self {
Self::I64
}
pub fn f64() -> Self {
Self::F64
}
pub fn const_int0() -> Self {
Self::CONST_INT0
}
pub fn const_int1() -> Self {
Self::CONST_INT1
}
pub fn blob(size: u64) -> Self {
Self(12 + size * 2)
}
pub fn text(size: u64) -> Self {
Self(13 + size * 2)
}
pub fn kind(&self) -> SerialTypeKind {
match self.0 {
0 => SerialTypeKind::Null,
1 => SerialTypeKind::I8,
2 => SerialTypeKind::I16,
3 => SerialTypeKind::I24,
4 => SerialTypeKind::I32,
5 => SerialTypeKind::I48,
6 => SerialTypeKind::I64,
7 => SerialTypeKind::F64,
8 => SerialTypeKind::ConstInt0,
9 => SerialTypeKind::ConstInt1,
n if n >= 12 => match n % 2 {
0 => SerialTypeKind::Blob,
1 => SerialTypeKind::Text,
_ => unreachable!(),
},
_ => unreachable!(),
}
}
pub fn size(&self) -> usize {
match self.kind() {
SerialTypeKind::Null => 0,
SerialTypeKind::I8 => 1,
SerialTypeKind::I16 => 2,
SerialTypeKind::I24 => 3,
SerialTypeKind::I32 => 4,
SerialTypeKind::I48 => 6,
SerialTypeKind::I64 => 8,
SerialTypeKind::F64 => 8,
SerialTypeKind::ConstInt0 => 0,
SerialTypeKind::ConstInt1 => 0,
SerialTypeKind::Text => (self.0 as usize - 13) / 2,
SerialTypeKind::Blob => (self.0 as usize - 12) / 2,
}
}
}
impl From<&OwnedValue> for SerialType {
fn from(value: &OwnedValue) -> Self {
match value {
OwnedValue::Null => SerialType::Null,
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,
i if *i >= I32_LOW && *i <= I32_HIGH => SerialType::I32,
i if *i >= I48_LOW && *i <= I48_HIGH => SerialType::I48,
_ => SerialType::I64,
},
OwnedValue::Float(_) => SerialType::F64,
OwnedValue::Text(t) => SerialType::Text {
content_size: t.value.len(),
},
OwnedValue::Blob(b) => SerialType::Blob {
content_size: b.len(),
0 => SerialType::const_int0(),
1 => SerialType::const_int1(),
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(),
i if *i >= I32_LOW && *i <= I32_HIGH => SerialType::i32(),
i if *i >= I48_LOW && *i <= I48_HIGH => SerialType::i48(),
_ => SerialType::i64(),
},
OwnedValue::Float(_) => SerialType::f64(),
OwnedValue::Text(t) => SerialType::text(t.value.len() as u64),
OwnedValue::Blob(b) => SerialType::blob(b.len() as u64),
}
}
}
impl From<SerialType> for u64 {
fn from(serial_type: SerialType) -> Self {
match serial_type {
SerialType::Null => 0,
SerialType::I8 => 1,
SerialType::I16 => 2,
SerialType::I24 => 3,
SerialType::I32 => 4,
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,
}
serial_type.0
}
}
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!(
fn try_from(uint: u64) -> Result<Self> {
if uint == 10 || uint == 11 {
return Err(LimboError::Corrupt(format!(
"Invalid serial type: {}",
serial_type
))),
uint
)));
}
Ok(SerialType(uint))
}
}
@@ -1236,13 +1291,15 @@ impl Record {
OwnedValue::Null => {}
OwnedValue::Integer(i) => {
let serial_type = SerialType::from(value);
match serial_type {
SerialType::I8 => buf.extend_from_slice(&(*i as i8).to_be_bytes()),
SerialType::I16 => buf.extend_from_slice(&(*i as i16).to_be_bytes()),
SerialType::I24 => buf.extend_from_slice(&(*i as i32).to_be_bytes()[1..]), // remove most significant byte
SerialType::I32 => buf.extend_from_slice(&(*i as i32).to_be_bytes()),
SerialType::I48 => buf.extend_from_slice(&i.to_be_bytes()[2..]), // remove 2 most significant bytes
SerialType::I64 => buf.extend_from_slice(&i.to_be_bytes()),
match serial_type.kind() {
SerialTypeKind::I8 => buf.extend_from_slice(&(*i as i8).to_be_bytes()),
SerialTypeKind::I16 => buf.extend_from_slice(&(*i as i16).to_be_bytes()),
SerialTypeKind::I24 => {
buf.extend_from_slice(&(*i as i32).to_be_bytes()[1..])
} // remove most significant byte
SerialTypeKind::I32 => buf.extend_from_slice(&(*i as i32).to_be_bytes()),
SerialTypeKind::I48 => buf.extend_from_slice(&i.to_be_bytes()[2..]), // remove 2 most significant bytes
SerialTypeKind::I64 => buf.extend_from_slice(&i.to_be_bytes()),
_ => unreachable!(),
}
}
@@ -1397,7 +1454,7 @@ mod tests {
// First byte should be header size
assert_eq!(header[0], header_length as u8);
// Second byte should be serial type for NULL
assert_eq!(header[1] as u64, u64::from(SerialType::Null));
assert_eq!(header[1] as u64, u64::from(SerialType::null()));
// Check that the buffer is empty after the header
assert_eq!(buf.len(), header_length);
}
@@ -1421,12 +1478,12 @@ mod tests {
assert_eq!(header[0], header_length as u8); // Header should be larger than number of values
// Check that correct serial types were chosen
assert_eq!(header[1] as u64, u64::from(SerialType::I8));
assert_eq!(header[2] as u64, u64::from(SerialType::I16));
assert_eq!(header[3] as u64, u64::from(SerialType::I24));
assert_eq!(header[4] as u64, u64::from(SerialType::I32));
assert_eq!(header[5] as u64, u64::from(SerialType::I48));
assert_eq!(header[6] as u64, u64::from(SerialType::I64));
assert_eq!(header[1] as u64, u64::from(SerialType::i8()));
assert_eq!(header[2] as u64, u64::from(SerialType::i16()));
assert_eq!(header[3] as u64, u64::from(SerialType::i24()));
assert_eq!(header[4] as u64, u64::from(SerialType::i32()));
assert_eq!(header[5] as u64, u64::from(SerialType::i48()));
assert_eq!(header[6] as u64, u64::from(SerialType::i64()));
// test that the bytes after the header can be interpreted as the correct values
let mut cur_offset = header_length;
@@ -1489,7 +1546,7 @@ mod tests {
// First byte should be header size
assert_eq!(header[0], header_length as u8);
// Second byte should be serial type for FLOAT
assert_eq!(header[1] as u64, u64::from(SerialType::F64));
assert_eq!(header[1] as u64, u64::from(SerialType::f64()));
// Check that the bytes after the header can be interpreted as the float
let float_bytes = &buf[header_length..header_length + size_of::<f64>()];
let float = f64::from_be_bytes(float_bytes.try_into().unwrap());
@@ -1553,11 +1610,11 @@ mod tests {
// First byte should be header size
assert_eq!(header[0], header_length as u8);
// Second byte should be serial type for NULL
assert_eq!(header[1] as u64, u64::from(SerialType::Null));
assert_eq!(header[1] as u64, u64::from(SerialType::null()));
// Third byte should be serial type for I8
assert_eq!(header[2] as u64, u64::from(SerialType::I8));
assert_eq!(header[2] as u64, u64::from(SerialType::i8()));
// Fourth byte should be serial type for F64
assert_eq!(header[3] as u64, u64::from(SerialType::F64));
assert_eq!(header[3] as u64, u64::from(SerialType::f64()));
// Fifth byte should be serial type for TEXT, which is (len * 2 + 13)
assert_eq!(header[4] as u64, (4 * 2 + 13) as u64);