better way to store values

This commit is contained in:
Sander Hautvast 2022-10-28 14:51:50 +02:00
parent ba0c4d2b5e
commit 561580aac1

View file

@ -1,36 +1,44 @@
use byteorder::{BigEndian, ByteOrder}; use byteorder::{BigEndian, ByteOrder};
use crate::varint; use crate::varint;
pub enum Value { pub struct Value {
String(String), pub datatype: Vec<u8>,
Blob(Vec<u8>), pub data: Vec<u8>,
Integer(i64),
Float(f64),
} }
/// returns (datatype, value)
pub fn get_bytes(value: Value) -> (Vec<u8>, Vec<u8>) { impl Value {
match value { pub fn get_length(&self) -> usize {
Value::String(value) => { self.datatype.len() + self.data.len()
}
}
pub fn string(value: &str) -> Value {
let bytes = value.chars().map(|c| c as u8).collect::<Vec<_>>(); let bytes = value.chars().map(|c| c as u8).collect::<Vec<_>>();
(varint::write((bytes.len() * 2 + 13) as u64), bytes) Value { datatype: varint::write((bytes.len() * 2 + 13) as u64), data: bytes }
} }
Value::Blob(value) => {
(varint::write((value.len() * 2 + 12) as u64), value) pub fn blob(value: Vec<u8>) -> Value {
Value { datatype: varint::write((value.len() * 2 + 12) as u64), data: value }
} }
Value::Integer(value) => {
(get_int_type(value), integer_to_bytes(value)) pub fn integer(value: i64) -> Value {
Value { datatype: get_int_type(value), data: sqlite_integer_to_bytes(value) }
} }
Value::Float(value) => {
pub fn float(value: f64) -> Value {
let mut buffer = [0 as u8; 8]; let mut buffer = [0 as u8; 8];
BigEndian::write_f64(&mut buffer, value); BigEndian::write_f64(&mut buffer, value);
(vec![7], buffer.to_vec()) Value { datatype: vec![7], data: buffer.to_vec() }
}
}
} }
pub fn get_length(value: &Value) -> usize {
value.datatype.len() + value.data.len()
}
/// sqlite specific way to encode integers
/// returns a variable length Vec of u8 /// returns a variable length Vec of u8
fn integer_to_bytes(value: i64) -> Vec<u8> { fn sqlite_integer_to_bytes(value: i64) -> Vec<u8> {
if value == 0 || value == 1 { if value == 0 || value == 1 {
vec![] vec![]
} else { } else {
@ -38,7 +46,7 @@ fn integer_to_bytes(value: i64) -> Vec<u8> {
} }
} }
fn long_to_bytes(n: i64, nbytes: u8) -> Vec<u8> { fn i64_to_bytes(n: i64, nbytes: u8) -> Vec<u8> {
let mut bytes = vec![]; let mut bytes = vec![];
for i in 0..nbytes { for i in 0..nbytes {
bytes.push(((n >> (nbytes - i - 1) * 8) & 0xFF) as u8); bytes.push(((n >> (nbytes - i - 1) * 8) & 0xFF) as u8);
@ -59,7 +67,7 @@ fn get_int_type(value: i64) -> Vec<u8> {
} else if length < 7 { } else if length < 7 {
varint::write(5) varint::write(5)
} else { } else {
varint::write(5) varint::write(6)
} }
} }
} }
@ -88,62 +96,55 @@ fn get_length_of_byte_encoding(value: i64) -> u8 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::mem; use crate::values::Value;
use crate::values::{get_bytes, Value}; use super::*;
#[test] #[test]
fn test_string() { fn test_string() {
let v = Value::String("hello".to_owned()); let v = string("hello");
let byte_rep = get_bytes(v); assert_eq!(v.datatype, vec![23]);
assert_eq!(byte_rep.0, vec![23]); assert_eq!(v.data, vec![0x68, 0x65, 0x6C, 0x6C, 0x6F]);
assert_eq!(byte_rep.1, vec![0x68, 0x65, 0x6C, 0x6C, 0x6F]);
} }
#[test] #[test]
fn test_blob() { fn test_blob() {
let v = Value::Blob(vec![1, 2, 3, 4, 5]); let v = blob(vec![1, 2, 3, 4, 5]);
let byte_rep = get_bytes(v); assert_eq!(v.datatype, vec![22]);
assert_eq!(byte_rep.0, vec![22]); assert_eq!(v.data, vec![1, 2, 3, 4, 5]);
assert_eq!(byte_rep.1, vec![1, 2, 3, 4, 5]);
} }
#[test] #[test]
fn test_float() { fn test_float() {
let v = Value::Float(1.1); let v = float(1.1);
let byte_rep = get_bytes(v); assert_eq!(v.datatype, vec![7]);
assert_eq!(byte_rep.0, vec![7]); assert_eq!(v.data, vec![0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a]);
assert_eq!(byte_rep.1, vec![0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a]);
} }
#[test] #[test]
fn test_integer0() { fn test_integer0() {
let v = Value::Integer(0); let v = integer(0);
let byte_rep = get_bytes(v); assert_eq!(v.datatype, vec![8]);
assert_eq!(byte_rep.0, vec![8]); assert_eq!(v.data, vec![]);
assert_eq!(byte_rep.1, vec![]);
} }
#[test] #[test]
fn test_integer1() { fn test_integer1() {
let v = Value::Integer(1); let v = integer(1);
let byte_rep = get_bytes(v); assert_eq!(v.datatype, vec![9]);
assert_eq!(byte_rep.0, vec![9]); assert_eq!(v.data, vec![]);
assert_eq!(byte_rep.1, vec![]);
} }
#[test] #[test]
fn test_integer2() { fn test_integer2() {
let v = Value::Integer(2); let v = integer(2);
let byte_rep = get_bytes(v); assert_eq!(v.datatype, vec![1]);
assert_eq!(byte_rep.0, vec![1]); assert_eq!(v.data, vec![2]);
assert_eq!(byte_rep.1, vec![2]);
} }
#[test] #[test]
fn test_integer128() { fn test_integer128() {
let v = Value::Integer(128); let v = integer(128);
let byte_rep = get_bytes(v); assert_eq!(v.datatype, vec![2]);
assert_eq!(byte_rep.0, vec![2]); assert_eq!(v.data, vec![0, 128]);
assert_eq!(byte_rep.1, vec![0, 128]);
} }
} }