musli_json/parser/
slice_parser.rs1use musli::{Buf, Context};
2
3use crate::error::ErrorMessage;
4use crate::parser::{Parser, StringReference, Token};
5
6use lexical::parse_float_options::JSON;
7
8const FORMAT: u128 = lexical::format::STANDARD;
9
10pub(crate) struct SliceParser<'de> {
12 pub(crate) slice: &'de [u8],
13 pub(crate) index: usize,
14}
15
16impl<'de> SliceParser<'de> {
17 #[inline]
19 pub(crate) fn new(slice: &'de [u8]) -> Self {
20 Self { slice, index: 0 }
21 }
22}
23
24impl<'de> Parser<'de> for SliceParser<'de> {
25 type Mut<'this> = &'this mut SliceParser<'de> where Self: 'this;
26
27 #[inline]
28 fn borrow_mut(&mut self) -> Self::Mut<'_> {
29 self
30 }
31
32 #[inline]
33 fn parse_string<'scratch, C, S>(
34 &mut self,
35 cx: &C,
36 validate: bool,
37 scratch: &'scratch mut S,
38 ) -> Result<StringReference<'de, 'scratch>, C::Error>
39 where
40 C: ?Sized + Context,
41 S: ?Sized + Buf,
42 {
43 let start = cx.mark();
44 let actual = self.peek(cx)?;
45
46 if !matches!(actual, Token::String) {
47 return Err(cx.marked_message(start, format_args!("Expected string, found {actual}")));
48 }
49
50 self.skip(cx, 1)?;
51 let out =
52 crate::parser::string::parse_string_slice_reader(cx, self, validate, start, scratch);
53 out
54 }
55
56 #[inline]
57 fn read_byte<C>(&mut self, cx: &C) -> Result<u8, C::Error>
58 where
59 C: ?Sized + Context,
60 {
61 let mut byte = [0];
62 self.read(cx, &mut byte[..])?;
63 Ok(byte[0])
64 }
65
66 #[inline]
67 fn skip<C>(&mut self, cx: &C, n: usize) -> Result<(), C::Error>
68 where
69 C: ?Sized + Context,
70 {
71 let outcome = self.index.wrapping_add(n);
72
73 if outcome > self.slice.len() || outcome < self.index {
74 return Err(cx.message("Buffer underflow"));
75 }
76
77 self.index = outcome;
78 cx.advance(n);
79 Ok(())
80 }
81
82 #[inline]
83 fn read<C>(&mut self, cx: &C, buf: &mut [u8]) -> Result<(), C::Error>
84 where
85 C: ?Sized + Context,
86 {
87 let outcome = self.index.wrapping_add(buf.len());
88
89 if outcome > self.slice.len() || outcome < self.index {
90 return Err(cx.message("Buffer underflow"));
91 }
92
93 buf.copy_from_slice(&self.slice[self.index..outcome]);
94 self.index = outcome;
95 cx.advance(buf.len());
96 Ok(())
97 }
98
99 #[inline]
100 fn skip_whitespace<C>(&mut self, cx: &C) -> Result<(), C::Error>
101 where
102 C: ?Sized + Context,
103 {
104 while matches!(
105 self.slice.get(self.index),
106 Some(b' ' | b'\n' | b'\t' | b'\r')
107 ) {
108 self.index = self.index.wrapping_add(1);
109 cx.advance(1);
110 }
111
112 Ok(())
113 }
114
115 #[inline]
116 fn pos(&self) -> u32 {
117 self.index as u32
118 }
119
120 #[inline]
121 fn peek_byte<C>(&mut self, _: &C) -> Result<Option<u8>, C::Error>
122 where
123 C: ?Sized + Context,
124 {
125 Ok(self.slice.get(self.index).copied())
126 }
127
128 fn parse_f32<C>(&mut self, cx: &C) -> Result<f32, C::Error>
129 where
130 C: ?Sized + Context,
131 {
132 let (value, read) = match lexical::parse_partial_with_options::<f32, _, FORMAT>(
133 &self.slice[self.index..],
134 &JSON,
135 ) {
136 Ok(out) => out,
137 Err(error) => {
138 return Err(cx.custom(ErrorMessage::ParseFloat(error)));
139 }
140 };
141
142 self.index += read;
143 cx.advance(read);
144 Ok(value)
145 }
146
147 fn parse_f64<C>(&mut self, cx: &C) -> Result<f64, C::Error>
148 where
149 C: ?Sized + Context,
150 {
151 let (value, read) = match lexical::parse_partial_with_options::<f64, _, FORMAT>(
152 &self.slice[self.index..],
153 &JSON,
154 ) {
155 Ok(out) => out,
156 Err(error) => {
157 return Err(cx.custom(ErrorMessage::ParseFloat(error)));
158 }
159 };
160
161 self.index += read;
162 cx.advance(read);
163 Ok(value)
164 }
165}