pancake_db_core/encoding/
encoder.rs1use std::marker::PhantomData;
2
3use pancake_db_idl::dml::FieldValue;
4use pancake_db_idl::dml::field_value::Value;
5
6use crate::errors::{CoreResult, CoreError};
7use crate::primitives::{Atom, Primitive};
8use super::{NULL_BYTE, ESCAPE_BYTE, COUNT_BYTE};
9
10pub trait Encoder: Send + Sync {
11 fn encode(&self, values: &[FieldValue]) -> CoreResult<Vec<u8>>;
12 fn encode_count(&self, count: u32) -> Vec<u8>;
13}
14
15#[derive(Clone, Debug)]
16pub struct EncoderImpl<P: Primitive> {
17 nested_list_depth: u8,
18 _phantom: PhantomData<P>,
19}
20
21fn escape_bytes(bytes: &[u8]) -> Vec<u8> {
22 let mut res = Vec::new();
23 for &b in bytes {
24 if b >= NULL_BYTE {
25 res.push(ESCAPE_BYTE);
26 res.push(!b);
30 } else {
31 res.push(b);
32 }
33 }
34 res
35}
36
37impl<P: Primitive> Encoder for EncoderImpl<P> {
38 fn encode(&self, fvs: &[FieldValue]) -> CoreResult<Vec<u8>> {
39 let mut res = Vec::new();
40
41 for fv in fvs {
42 let maybe_err: CoreResult<()> = match &fv.value {
43 Some(value) => {
44 let bytes = self.value_bytes(value, 0)?;
45 res.extend(bytes);
46 Ok(())
47 },
48 None => {
49 res.push(NULL_BYTE);
50 Ok(())
51 }
52 };
53 maybe_err?;
54 }
55 Ok(res)
56 }
57
58 fn encode_count(&self, count: u32) -> Vec<u8> {
59 let mut res = vec![COUNT_BYTE];
60 res.extend(&escape_bytes(&count.to_be_bytes()));
61 res
62 }
63}
64
65impl<P: Primitive> EncoderImpl<P> {
66 pub fn new(escape_depth: u8) -> Self {
67 Self {
68 nested_list_depth: escape_depth,
69 _phantom: PhantomData,
70 }
71 }
72
73 fn value_bytes(&self, v: &Value, traverse_depth: u8) -> CoreResult<Vec<u8>> {
74 if traverse_depth == self.nested_list_depth {
75 let atoms = P::try_from_value(v)?.to_atoms();
76 if P::IS_ATOMIC {
77 Ok(escape_bytes(&atoms[0].to_bytes()))
78 } else {
79 let mut res = Vec::with_capacity(2 + P::A::BYTE_SIZE * atoms.len());
80 res.extend((atoms.len() as u16).to_be_bytes());
81 for atom in &atoms {
82 res.extend(atom.to_bytes());
83 }
84 Ok(escape_bytes(&res))
85 }
86 } else {
87 match v {
88 Value::ListVal(l) => {
89 let mut res = Vec::new();
90 res.extend(escape_bytes(&(l.vals.len() as u16).to_be_bytes()));
91 for val in &l.vals {
92 let bytes = self.value_bytes(val.value.as_ref().unwrap(), traverse_depth + 1)?;
93 res.extend(bytes);
94 }
95 Ok(res)
96 },
97 _ => Err(CoreError::invalid("expected a list to traverse but found atomic type"))
98 }
99 }
100 }
101}