mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-04 15:54:23 +01:00
types: refactor serialtype again to make it faster
This commit is contained in:
@@ -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);
|
||||
|
||||
261
core/types.rs
261
core/types.rs
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user