Skip to main content

sark_json/
parse.rs

1use o3::buffer::{Bytes, Retained, Shared};
2
3use crate::Result;
4use crate::body::InlineToken;
5use crate::error::Fail;
6use crate::scan::Scan;
7
8pub struct Parse;
9
10impl Parse {
11    pub fn frame(owner: &Shared, idx: &mut usize) -> Result<Bytes<Retained>> {
12        let input = owner.as_slice();
13        if *idx >= input.len() {
14            return Err(Fail::bad());
15        }
16        if input[*idx] == b'"' {
17            let start = *idx;
18            let _ = Scan::str_slice(input, idx)?;
19            let raw_start = start.saturating_add(1);
20            let raw_end = idx.saturating_sub(1);
21            if raw_end < raw_start {
22                return Err(Fail::bad());
23            }
24            let mut esc = raw_start;
25            while esc < raw_end {
26                if input[esc] == b'\\' {
27                    let decoded = Shared::from(Scan::decode_str(&input[raw_start..raw_end])?);
28                    return Ok(Bytes::<Retained>::from(decoded));
29                }
30                esc += 1;
31            }
32            return Ok(Bytes::<Retained>::from(owner.slice(raw_start..raw_end)));
33        }
34        let start = *idx;
35        Scan::skip_value(input, idx)?;
36        let end = *idx;
37        if end <= start {
38            return Err(Fail::bad());
39        }
40        Ok(Bytes::<Retained>::from(owner.slice(start..end)))
41    }
42
43    pub fn empty_frame() -> Bytes<Retained> {
44        Bytes::<Retained>::from(Shared::new())
45    }
46
47    pub fn frame_plain(owner: &Shared, idx: &mut usize) -> Result<Bytes<Retained>> {
48        let input = owner.as_slice();
49        Scan::expect_byte(input, idx, b'"')?;
50        let start = *idx;
51        while *idx < input.len() {
52            match input[*idx] {
53                b'"' => {
54                    let end = *idx;
55                    *idx += 1;
56                    return Ok(Bytes::<Retained>::from(owner.slice(start..end)));
57                }
58                b'\\' => return Err(Fail::bad()),
59                _ => *idx += 1,
60            }
61        }
62        Err(Fail::bad())
63    }
64
65    pub fn inline_plain<const N: usize>(input: &[u8], idx: &mut usize) -> Result<InlineToken<N>> {
66        Scan::expect_byte(input, idx, b'"')?;
67        let mut out = InlineToken::<N>::new();
68        while *idx < input.len() {
69            match input[*idx] {
70                b'"' => {
71                    *idx += 1;
72                    return Ok(out);
73                }
74                b'\\' => return Err(Fail::bad()),
75                b => {
76                    out.push(b)?;
77                    *idx += 1;
78                }
79            }
80        }
81        Err(Fail::bad())
82    }
83
84    pub fn frame_raw(owner: &Shared, idx: &mut usize) -> Result<Bytes<Retained>> {
85        let input = owner.as_slice();
86        let start = *idx;
87        while *idx < input.len() {
88            match input[*idx] {
89                b',' | b'}' | b']' => break,
90                _ => *idx += 1,
91            }
92        }
93        let end = *idx;
94        if end <= start {
95            return Err(Fail::bad());
96        }
97        Ok(Bytes::<Retained>::from(owner.slice(start..end)))
98    }
99
100    pub fn inline_raw<const N: usize>(input: &[u8], idx: &mut usize) -> Result<InlineToken<N>> {
101        let mut out = InlineToken::<N>::new();
102        while *idx < input.len() {
103            match input[*idx] {
104                b',' | b'}' | b']' => break,
105                b => {
106                    out.push(b)?;
107                    *idx += 1;
108                }
109            }
110        }
111        if out.is_empty() {
112            return Err(Fail::bad());
113        }
114        Ok(out)
115    }
116
117    pub fn u64(input: &[u8], idx: &mut usize) -> Result<u64> {
118        if *idx >= input.len() {
119            return Err(Fail::bad());
120        }
121        let mut value = 0u64;
122        let mut seen = false;
123        while *idx < input.len() {
124            let b = input[*idx];
125            if !b.is_ascii_digit() {
126                break;
127            }
128            value = value
129                .checked_mul(10)
130                .and_then(|v| v.checked_add((b - b'0') as u64))
131                .ok_or_else(Fail::bad)?;
132            *idx += 1;
133            seen = true;
134        }
135        if !seen {
136            return Err(Fail::bad());
137        }
138        Ok(value)
139    }
140
141    pub fn bool(input: &[u8], idx: &mut usize) -> Result<bool> {
142        if input.get(*idx..(*idx + 4)) == Some(b"true") {
143            *idx += 4;
144            return Ok(true);
145        }
146        if input.get(*idx..(*idx + 5)) == Some(b"false") {
147            *idx += 5;
148            return Ok(false);
149        }
150        Err(Fail::bad())
151    }
152}