amadeus_utils/vecpak/
mod.rs1use 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 }
23
24#[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; 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 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 }
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 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}