amadeus_utils/vecpak/
mod.rs

1use serde::{Serialize, Deserialize};
2
3mod error;
4mod ser;
5mod de;
6mod ext;
7
8pub use error::Error;
9pub use ser::to_vec;
10pub use de::from_slice;
11pub use ext::{VecpakExt, PropListMap, parse_list};
12
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
14pub enum Term {
15    Nil(),
16    Bool(bool),
17    VarInt(i128),
18    Binary(Vec<u8>),
19    List(Vec<Term>),
20    PropList(Vec<(Term,Term)>),
21    //Map(HashMap<Term,Term>),
22}
23
24//TODO: varint should support any size not limited to RUST i128
25#[inline(always)]
26pub fn encode_varint(buf: &mut Vec<u8>, v: i128) {
27    if v == 0 {
28        buf.push(0);
29        return;
30    }
31
32    let sign = (v < 0) as u8;
33    let mag = v.unsigned_abs();
34    let lz = mag.leading_zeros() as usize; //bitsize (128 for i128)
35    let first = lz / 8;
36    let len = 16 - first;
37    buf.push((sign << 7) | (len as u8));
38    let be = mag.to_be_bytes();
39    buf.extend_from_slice(&be[first..]);
40}
41
42#[inline(always)]
43pub fn decode_varint(buf: &[u8], i: &mut usize) -> Result<i128, &'static str> {
44    if *i >= buf.len() { return Err("eof"); }
45    let b0 = buf[*i]; *i += 1;
46    if b0 == 0 {
47        return Ok(0);
48    }
49    if b0 == 0x80 { return Err("noncanonical_zero"); }
50
51    let sign = (b0 & 0x80) != 0;
52    let len  = (b0 & 0x7F) as usize;
53    if len == 0 || len > 16 { return Err("bad_varint_length"); }
54    if buf.len().saturating_sub(*i) < len { return Err("eof"); }
55
56    if buf[*i] == 0 { return Err("varint_leading_zero"); }
57
58    // read big-endian magnitude
59    let mut be = [0u8; 16];
60    be[16 - len..].copy_from_slice(&buf[*i..*i + len]);
61    *i += len;
62
63    let mag = u128::from_be_bytes(be);
64    if mag > i128::MAX as u128 { return Err("varint_underflow"); }
65
66    if sign {
67        Ok(-(mag as i128))
68    } else {
69        Ok(mag as i128)
70    }
71}
72
73#[inline]
74fn decode_varint_gte_zero(buf: &[u8], i: &mut usize) -> Result<usize, &'static str> {
75    let n = decode_varint(buf, i)?;
76    if n < 0 { return Err("length_is_negative"); }
77    usize::try_from(n).map_err(|_| "length_overflow")
78}
79
80pub fn encode_term(buf: &mut Vec<u8>, term: Term) {
81    match term {
82        Term::Nil() => { buf.push(0); }
83        Term::Bool(true) => { buf.push(1); }
84        Term::Bool(false) => { buf.push(2); }
85        Term::VarInt(varint) => {
86            buf.push(3);
87            encode_varint(buf, varint);
88        }
89        Term::Binary(bin) => {
90            buf.push(5);
91            encode_varint(buf, bin.len() as i128);
92            buf.extend_from_slice(bin.as_slice());
93        }
94        Term::List(list) => {
95            buf.push(6);
96            encode_varint(buf, list.len() as i128);
97            for member in list {
98                encode_term(buf, member);
99            }
100        }
101        Term::PropList(proplist) => {
102            buf.push(7);
103            encode_varint(buf, proplist.len() as i128);
104
105            let mut keyed: Vec<(Vec<u8>, Term)> = Vec::with_capacity(proplist.len());
106            for (k, v) in proplist {
107                let mut kbytes = Vec::with_capacity(64);
108                encode_term(&mut kbytes, k);
109                keyed.push((kbytes, v));
110            }
111            keyed.sort_unstable_by(|a, b| a.0.cmp(&b.0));
112            for (kbytes, v) in keyed {
113                buf.extend_from_slice(&kbytes);
114                encode_term(buf, v);
115            }
116        }
117        /*Term::Map(map) => {
118            buf.push(7);
119            encode_varint(buf, map.len() as i128);
120
121            let mut keyed: Vec<(Vec<u8>, Term)> = Vec::with_capacity(map.len());
122            for (k, v) in map {
123                let mut kbytes = Vec::with_capacity(64);
124                encode_term(&mut kbytes, k);
125                keyed.push((kbytes, v));
126            }
127            keyed.sort_unstable_by(|a, b| a.0.cmp(&b.0));
128            for (kbytes, v) in keyed {
129                buf.extend_from_slice(&kbytes);
130                encode_term(buf, v);
131            }
132        }*/
133    }
134}
135
136pub fn encode(term: Term) -> Vec<u8> {
137    let mut buf = Vec::with_capacity(1024);
138    encode_term(&mut buf, term);
139    buf
140}
141
142#[inline]
143fn read_u8(buf: &[u8], i: &mut usize) -> Result<u8, &'static str> {
144    if *i >= buf.len() { return Err("eof"); }
145    let b = buf[*i];
146    *i += 1;
147    Ok(b)
148}
149
150#[inline]
151fn read_exact<'a>(buf: &'a [u8], i: &mut usize, n: usize) -> Result<&'a [u8], &'static str> {
152    if buf.len().saturating_sub(*i) < n { return Err("eof"); }
153    let s = &buf[*i..*i + n];
154    *i += n;
155    Ok(s)
156}
157
158pub fn decode_term(buf: &[u8], i: &mut usize) -> Result<Term, &'static str> {
159    let tag = read_u8(buf, i)?;
160    match tag {
161        0 => { Ok(Term::Nil()) }
162        1 => { Ok(Term::Bool(true)) }
163        2 => { Ok(Term::Bool(false)) }
164        3 => {
165            let v = decode_varint(buf, i)?;
166            Ok(Term::VarInt(v))
167        }
168        5 => {
169            let len = decode_varint_gte_zero(buf, i)?;
170            let bytes = read_exact(buf, i, len as usize)?.to_vec();
171            Ok(Term::Binary(bytes))
172        }
173        6 => {
174            let count = decode_varint_gte_zero(buf, i)?;
175            let mut items = Vec::with_capacity(count);
176            for _ in 0..count {
177                items.push(decode_term(buf, i)?);
178            }
179            Ok(Term::List(items))
180        }
181        7 => {
182            let count = decode_varint_gte_zero(buf, i)?;
183            let mut pairs = Vec::with_capacity(count);
184
185            //Canonical check
186            let mut prev_key_bytes: Option<&[u8]> = None;
187
188            for _ in 0..count {
189                let k_start = *i;
190                let k = decode_term(buf, i)?;
191                let k_bytes = &buf[k_start..*i];
192
193                if let Some(prev) = prev_key_bytes {
194                    if k_bytes <= prev { return Err("map_not_canonical"); }
195                }
196                prev_key_bytes = Some(k_bytes);
197
198                let v = decode_term(buf, i)?;
199                pairs.push((k, v));
200            }
201            Ok(Term::PropList(pairs))
202        }
203        _ => Err("unknown_tag"),
204    }
205}
206
207pub fn decode(buf: &[u8]) -> Result<Term, &'static str> {
208    let mut i = 0;
209    let term = decode_term(buf, &mut i)?;
210    if i != buf.len() { return Err("trailing_bytes"); }
211    Ok(term)
212}