Skip to main content

nodedb_types/json_msgpack/
reader.rs

1//! Cursor-based msgpack → `serde_json::Value` and `nodedb_types::Value` readers.
2//!
3//! Deterministic raw byte parser — the first byte of each msgpack value
4//! unambiguously identifies its type per the msgpack specification.
5
6pub(crate) struct Cursor<'a> {
7    pub(crate) data: &'a [u8],
8    pub(crate) pos: usize,
9    pub(crate) depth: usize,
10}
11
12impl<'a> Cursor<'a> {
13    pub(crate) fn new(data: &'a [u8]) -> Self {
14        Self {
15            data,
16            pos: 0,
17            depth: 0,
18        }
19    }
20
21    #[inline]
22    pub(crate) fn peek(&self) -> zerompk::Result<u8> {
23        self.data
24            .get(self.pos)
25            .copied()
26            .ok_or(zerompk::Error::BufferTooSmall)
27    }
28
29    #[inline]
30    pub(crate) fn take(&mut self) -> zerompk::Result<u8> {
31        let b = self.peek()?;
32        self.pos += 1;
33        Ok(b)
34    }
35
36    #[inline]
37    pub(crate) fn take_n(&mut self, n: usize) -> zerompk::Result<&'a [u8]> {
38        if self.pos + n > self.data.len() {
39            return Err(zerompk::Error::BufferTooSmall);
40        }
41        let slice = &self.data[self.pos..self.pos + n];
42        self.pos += n;
43        Ok(slice)
44    }
45
46    pub(crate) fn read_u16_be(&mut self) -> zerompk::Result<u16> {
47        let b = self.take_n(2)?;
48        Ok(u16::from_be_bytes([b[0], b[1]]))
49    }
50
51    pub(crate) fn read_u32_be(&mut self) -> zerompk::Result<u32> {
52        let b = self.take_n(4)?;
53        Ok(u32::from_be_bytes([b[0], b[1], b[2], b[3]]))
54    }
55}
56
57/// Deserialize a `serde_json::Value` from MessagePack bytes.
58pub fn json_from_msgpack(bytes: &[u8]) -> zerompk::Result<serde_json::Value> {
59    let mut cursor = Cursor::new(bytes);
60    read_json_value(&mut cursor)
61}
62
63/// Deserialize a `nodedb_types::Value` from standard MessagePack bytes.
64pub fn value_from_msgpack(bytes: &[u8]) -> zerompk::Result<crate::Value> {
65    let mut cursor = Cursor::new(bytes);
66    read_native_value(&mut cursor)
67}
68
69// ── JSON value reader ──
70
71fn read_json_value(c: &mut Cursor<'_>) -> zerompk::Result<serde_json::Value> {
72    if c.depth > 500 {
73        return Err(zerompk::Error::DepthLimitExceeded { max: 500 });
74    }
75
76    let marker = c.take()?;
77    match marker {
78        0xC0 => Ok(serde_json::Value::Null),
79        0xC2 => Ok(serde_json::Value::Bool(false)),
80        0xC3 => Ok(serde_json::Value::Bool(true)),
81
82        0x00..=0x7F => Ok(serde_json::Value::Number((marker as i64).into())),
83        0xE0..=0xFF => Ok(serde_json::Value::Number((marker as i8 as i64).into())),
84
85        0xCC => Ok(serde_json::Value::Number(c.take()?.into())),
86        0xCD => Ok(serde_json::Value::Number(c.read_u16_be()?.into())),
87        0xCE => Ok(serde_json::Value::Number(c.read_u32_be()?.into())),
88        0xCF => {
89            let b = c.take_n(8)?;
90            let v = u64::from_be_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]);
91            Ok(serde_json::Value::Number(v.into()))
92        }
93
94        0xD0 => Ok(serde_json::Value::Number((c.take()? as i8 as i64).into())),
95        0xD1 => {
96            let b = c.take_n(2)?;
97            Ok(serde_json::Value::Number(
98                (i16::from_be_bytes([b[0], b[1]]) as i64).into(),
99            ))
100        }
101        0xD2 => {
102            let b = c.take_n(4)?;
103            Ok(serde_json::Value::Number(
104                (i32::from_be_bytes([b[0], b[1], b[2], b[3]]) as i64).into(),
105            ))
106        }
107        0xD3 => {
108            let b = c.take_n(8)?;
109            Ok(serde_json::Value::Number(
110                i64::from_be_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]).into(),
111            ))
112        }
113
114        0xCA => {
115            let b = c.take_n(4)?;
116            Ok(serde_json::json!(
117                f32::from_be_bytes([b[0], b[1], b[2], b[3]]) as f64
118            ))
119        }
120        0xCB => {
121            let b = c.take_n(8)?;
122            Ok(serde_json::json!(f64::from_be_bytes([
123                b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]
124            ])))
125        }
126
127        m @ 0xA0..=0xBF => read_json_str(c, (m & 0x1F) as usize),
128        0xD9 => {
129            let l = c.take()? as usize;
130            read_json_str(c, l)
131        }
132        0xDA => {
133            let l = c.read_u16_be()? as usize;
134            read_json_str(c, l)
135        }
136        0xDB => {
137            let l = c.read_u32_be()? as usize;
138            read_json_str(c, l)
139        }
140
141        0xC4 => {
142            let l = c.take()? as usize;
143            Ok(serde_json::Value::String(base64_encode(c.take_n(l)?)))
144        }
145        0xC5 => {
146            let l = c.read_u16_be()? as usize;
147            Ok(serde_json::Value::String(base64_encode(c.take_n(l)?)))
148        }
149        0xC6 => {
150            let l = c.read_u32_be()? as usize;
151            Ok(serde_json::Value::String(base64_encode(c.take_n(l)?)))
152        }
153
154        m @ 0x90..=0x9F => read_json_array(c, (m & 0x0F) as usize),
155        0xDC => {
156            let l = c.read_u16_be()? as usize;
157            read_json_array(c, l)
158        }
159        0xDD => {
160            let l = c.read_u32_be()? as usize;
161            read_json_array(c, l)
162        }
163
164        m @ 0x80..=0x8F => read_json_map(c, (m & 0x0F) as usize),
165        0xDE => {
166            let l = c.read_u16_be()? as usize;
167            read_json_map(c, l)
168        }
169        0xDF => {
170            let l = c.read_u32_be()? as usize;
171            read_json_map(c, l)
172        }
173
174        // ext types — skip
175        0xD4 => {
176            c.take_n(2)?;
177            Ok(serde_json::Value::Null)
178        }
179        0xD5 => {
180            c.take_n(3)?;
181            Ok(serde_json::Value::Null)
182        }
183        0xD6 => {
184            c.take_n(5)?;
185            Ok(serde_json::Value::Null)
186        }
187        0xD7 => {
188            c.take_n(9)?;
189            Ok(serde_json::Value::Null)
190        }
191        0xD8 => {
192            c.take_n(17)?;
193            Ok(serde_json::Value::Null)
194        }
195        0xC7 => {
196            let l = c.take()? as usize;
197            c.take_n(1 + l)?;
198            Ok(serde_json::Value::Null)
199        }
200        0xC8 => {
201            let l = c.read_u16_be()? as usize;
202            c.take_n(1 + l)?;
203            Ok(serde_json::Value::Null)
204        }
205        0xC9 => {
206            let l = c.read_u32_be()? as usize;
207            c.take_n(1 + l)?;
208            Ok(serde_json::Value::Null)
209        }
210
211        _ => Err(zerompk::Error::InvalidMarker(marker)),
212    }
213}
214
215fn read_json_str(c: &mut Cursor<'_>, len: usize) -> zerompk::Result<serde_json::Value> {
216    let bytes = c.take_n(len)?;
217    let s = String::from_utf8(bytes.to_vec()).map_err(|_| zerompk::Error::InvalidMarker(0))?;
218    Ok(serde_json::Value::String(s))
219}
220
221fn read_json_array(c: &mut Cursor<'_>, len: usize) -> zerompk::Result<serde_json::Value> {
222    c.depth += 1;
223    let mut arr = Vec::with_capacity(len.min(4096));
224    for _ in 0..len {
225        arr.push(read_json_value(c)?);
226    }
227    c.depth -= 1;
228    Ok(serde_json::Value::Array(arr))
229}
230
231fn read_json_map(c: &mut Cursor<'_>, len: usize) -> zerompk::Result<serde_json::Value> {
232    c.depth += 1;
233    let mut map = serde_json::Map::with_capacity(len.min(4096));
234    for _ in 0..len {
235        let key_marker = c.peek()?;
236        let key = if (0xA0..=0xBF).contains(&key_marker)
237            || key_marker == 0xD9
238            || key_marker == 0xDA
239            || key_marker == 0xDB
240        {
241            match read_json_value(c)? {
242                serde_json::Value::String(s) => s,
243                other => other.to_string(),
244            }
245        } else {
246            read_json_value(c)?.to_string()
247        };
248        let val = read_json_value(c)?;
249        map.insert(key, val);
250    }
251    c.depth -= 1;
252    Ok(serde_json::Value::Object(map))
253}
254
255// ── Native value reader ──
256
257fn read_native_value(c: &mut Cursor<'_>) -> zerompk::Result<crate::Value> {
258    if c.depth > 500 {
259        return Err(zerompk::Error::DepthLimitExceeded { max: 500 });
260    }
261
262    let marker = c.take()?;
263    match marker {
264        0xC0 => Ok(crate::Value::Null),
265        0xC2 => Ok(crate::Value::Bool(false)),
266        0xC3 => Ok(crate::Value::Bool(true)),
267
268        0x00..=0x7F => Ok(crate::Value::Integer(marker as i64)),
269        0xE0..=0xFF => Ok(crate::Value::Integer(marker as i8 as i64)),
270
271        0xCC => Ok(crate::Value::Integer(c.take()? as i64)),
272        0xCD => Ok(crate::Value::Integer(c.read_u16_be()? as i64)),
273        0xCE => Ok(crate::Value::Integer(c.read_u32_be()? as i64)),
274        0xCF => {
275            let b = c.take_n(8)?;
276            Ok(crate::Value::Integer(u64::from_be_bytes([
277                b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
278            ]) as i64))
279        }
280
281        0xD0 => Ok(crate::Value::Integer(c.take()? as i8 as i64)),
282        0xD1 => {
283            let b = c.take_n(2)?;
284            Ok(crate::Value::Integer(
285                i16::from_be_bytes([b[0], b[1]]) as i64
286            ))
287        }
288        0xD2 => {
289            let b = c.take_n(4)?;
290            Ok(crate::Value::Integer(
291                i32::from_be_bytes([b[0], b[1], b[2], b[3]]) as i64,
292            ))
293        }
294        0xD3 => {
295            let b = c.take_n(8)?;
296            Ok(crate::Value::Integer(i64::from_be_bytes([
297                b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
298            ])))
299        }
300
301        0xCA => {
302            let b = c.take_n(4)?;
303            Ok(crate::Value::Float(
304                f32::from_be_bytes([b[0], b[1], b[2], b[3]]) as f64,
305            ))
306        }
307        0xCB => {
308            let b = c.take_n(8)?;
309            Ok(crate::Value::Float(f64::from_be_bytes([
310                b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
311            ])))
312        }
313
314        m @ 0xA0..=0xBF => read_native_str(c, (m & 0x1F) as usize),
315        0xD9 => {
316            let l = c.take()? as usize;
317            read_native_str(c, l)
318        }
319        0xDA => {
320            let l = c.read_u16_be()? as usize;
321            read_native_str(c, l)
322        }
323        0xDB => {
324            let l = c.read_u32_be()? as usize;
325            read_native_str(c, l)
326        }
327
328        0xC4 => {
329            let l = c.take()? as usize;
330            Ok(crate::Value::Bytes(c.take_n(l)?.to_vec()))
331        }
332        0xC5 => {
333            let l = c.read_u16_be()? as usize;
334            Ok(crate::Value::Bytes(c.take_n(l)?.to_vec()))
335        }
336        0xC6 => {
337            let l = c.read_u32_be()? as usize;
338            Ok(crate::Value::Bytes(c.take_n(l)?.to_vec()))
339        }
340
341        m @ 0x90..=0x9F => read_native_array(c, (m & 0x0F) as usize),
342        0xDC => {
343            let l = c.read_u16_be()? as usize;
344            read_native_array(c, l)
345        }
346        0xDD => {
347            let l = c.read_u32_be()? as usize;
348            read_native_array(c, l)
349        }
350
351        m @ 0x80..=0x8F => read_native_map(c, (m & 0x0F) as usize),
352        0xDE => {
353            let l = c.read_u16_be()? as usize;
354            read_native_map(c, l)
355        }
356        0xDF => {
357            let l = c.read_u32_be()? as usize;
358            read_native_map(c, l)
359        }
360
361        // ext types — skip
362        0xD4 => {
363            c.take_n(2)?;
364            Ok(crate::Value::Null)
365        }
366        0xD5 => {
367            c.take_n(3)?;
368            Ok(crate::Value::Null)
369        }
370        0xD6 => {
371            c.take_n(5)?;
372            Ok(crate::Value::Null)
373        }
374        0xD7 => {
375            c.take_n(9)?;
376            Ok(crate::Value::Null)
377        }
378        0xD8 => {
379            c.take_n(17)?;
380            Ok(crate::Value::Null)
381        }
382        0xC7 => {
383            let l = c.take()? as usize;
384            c.take_n(1 + l)?;
385            Ok(crate::Value::Null)
386        }
387        0xC8 => {
388            let l = c.read_u16_be()? as usize;
389            c.take_n(1 + l)?;
390            Ok(crate::Value::Null)
391        }
392        0xC9 => {
393            let l = c.read_u32_be()? as usize;
394            c.take_n(1 + l)?;
395            Ok(crate::Value::Null)
396        }
397
398        _ => Err(zerompk::Error::InvalidMarker(marker)),
399    }
400}
401
402fn read_native_str(c: &mut Cursor<'_>, len: usize) -> zerompk::Result<crate::Value> {
403    let bytes = c.take_n(len)?;
404    let s = String::from_utf8(bytes.to_vec()).map_err(|_| zerompk::Error::InvalidMarker(0))?;
405    Ok(crate::Value::String(s))
406}
407
408fn read_native_array(c: &mut Cursor<'_>, len: usize) -> zerompk::Result<crate::Value> {
409    c.depth += 1;
410    let mut arr = Vec::with_capacity(len.min(4096));
411    for _ in 0..len {
412        arr.push(read_native_value(c)?);
413    }
414    c.depth -= 1;
415    Ok(crate::Value::Array(arr))
416}
417
418fn read_native_map(c: &mut Cursor<'_>, len: usize) -> zerompk::Result<crate::Value> {
419    c.depth += 1;
420    let mut map = std::collections::HashMap::with_capacity(len.min(4096));
421    for _ in 0..len {
422        let key_marker = c.peek()?;
423        let key = if (0xA0..=0xBF).contains(&key_marker)
424            || key_marker == 0xD9
425            || key_marker == 0xDA
426            || key_marker == 0xDB
427        {
428            match read_native_value(c)? {
429                crate::Value::String(s) => s,
430                other => format!("{other:?}"),
431            }
432        } else {
433            let v = read_native_value(c)?;
434            format!("{v:?}")
435        };
436        let val = read_native_value(c)?;
437        map.insert(key, val);
438    }
439    c.depth -= 1;
440    Ok(crate::Value::Object(map))
441}
442
443// ── Shared helpers ──
444
445pub(crate) fn base64_encode(data: &[u8]) -> String {
446    use std::fmt::Write;
447    const CHARS: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
448    let mut out = String::with_capacity(data.len().div_ceil(3) * 4);
449    for chunk in data.chunks(3) {
450        let b0 = chunk[0] as u32;
451        let b1 = chunk.get(1).copied().unwrap_or(0) as u32;
452        let b2 = chunk.get(2).copied().unwrap_or(0) as u32;
453        let triple = (b0 << 16) | (b1 << 8) | b2;
454        let _ = write!(out, "{}", CHARS[((triple >> 18) & 0x3F) as usize] as char);
455        let _ = write!(out, "{}", CHARS[((triple >> 12) & 0x3F) as usize] as char);
456        if chunk.len() > 1 {
457            let _ = write!(out, "{}", CHARS[((triple >> 6) & 0x3F) as usize] as char);
458        }
459        if chunk.len() > 2 {
460            let _ = write!(out, "{}", CHARS[(triple & 0x3F) as usize] as char);
461        }
462    }
463    out
464}