Skip to main content

sark_json/
parse.rs

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