1use std::{
2 collections::HashMap,
3 iter::Peekable,
4 str::{CharIndices, FromStr},
5};
6
7use crate::{error::SerDeJsonError, Number, Value};
8
9enum Ident {
10 True,
11 False,
12 Null,
13}
14
15pub trait Deserialize {
16 fn deserialize(value: Value) -> Result<Self, SerDeJsonError>
17 where
18 Self: Sized;
19}
20
21impl Deserialize for Value {
22 fn deserialize(value: Value) -> Result<Self, SerDeJsonError>
23 where
24 Self: Sized,
25 {
26 Ok(value)
27 }
28}
29
30pub fn from_str<T: Deserialize>(value: &str) -> Result<T, SerDeJsonError> {
31 let value = Value::from_str(value)?;
32 T::deserialize(value)
33}
34
35impl FromStr for Value {
36 type Err = SerDeJsonError;
37
38 fn from_str(value: &str) -> Result<Self, Self::Err> {
39 let value = value.trim();
40 let value = value.char_indices().peekable();
41 let mut tokens = JsonParser::new(value);
42 let value = tokens.parse()?;
43 Ok(value)
44 }
45}
46
47struct JsonParser<'a> {
48 reader: Peekable<CharIndices<'a>>,
49 index: usize,
50}
51
52impl<'a> JsonParser<'a> {
53 pub fn new(reader: Peekable<CharIndices<'a>>) -> Self {
54 Self { reader, index: 0 }
55 }
56
57 pub fn parse(&mut self) -> Result<Value, SerDeJsonError> {
59 let value = match self.skip_whitespaces()? {
60 '{' => self.parse_object()?,
61 '[' => self.parse_array()?,
62 _ => return Err(SerDeJsonError::InvalidJson { index: self.index }),
63 };
64
65 match self.skip_whitespaces() {
66 Ok('\0') | Err(..) => (),
67 _ => return Err(SerDeJsonError::InvalidJson { index: self.index }),
68 }
69
70 Ok(value)
71 }
72
73 pub fn skip_whitespaces(&mut self) -> Result<char, SerDeJsonError> {
77 loop {
78 let Some((i, c)) = self.reader.peek() else {
79 return Err(SerDeJsonError::UnexpectedEnd { index: self.index });
80 };
81 self.index = *i;
82 if c.is_ascii_whitespace() {
83 self.reader.next();
84 continue;
85 }
86 break Ok(*c);
87 }
88 }
89
90 pub fn parse_object(&mut self) -> Result<Value, SerDeJsonError> {
92 self.reader.next();
93 let mut final_value = HashMap::new();
94 loop {
95 match self.skip_whitespaces()? {
96 '"' => (),
97 _ => return Err(SerDeJsonError::InvalidJson { index: self.index }),
98 }
99 let key = self.parse_string()?;
100 match self.skip_whitespaces()? {
101 ':' => {
102 self.reader.next();
103 }
104 _ => return Err(SerDeJsonError::InvalidJson { index: self.index }),
105 }
106
107 let c = self.skip_whitespaces()?;
108 let value = self.parse_value(c)?;
109
110 if final_value.insert(key.clone(), value).is_some() {
111 return Err(SerDeJsonError::DupplicateKey {
112 key,
113 index: self.index,
114 });
115 }
116
117 match self.skip_whitespaces()? {
118 ',' => {
119 self.reader.next();
120 continue;
121 }
122 '}' => break,
123 _ => return Err(SerDeJsonError::InvalidJson { index: self.index }),
124 }
125 }
126
127 self.reader.next();
128
129 Ok(Value::Object(final_value))
130 }
131
132 pub fn parse_array(&mut self) -> Result<Value, SerDeJsonError> {
134 self.reader.next();
135
136 let mut final_value = Vec::new();
137
138 loop {
139 let c = self.skip_whitespaces()?;
140 let value = self.parse_value(c)?;
141
142 final_value.push(value);
143
144 match self.skip_whitespaces()? {
145 ',' => {
146 self.reader.next();
147 continue;
148 }
149 ']' => break,
150 _ => return Err(SerDeJsonError::InvalidJson { index: self.index }),
151 }
152 }
153
154 self.reader.next();
155
156 Ok(Value::Array(final_value))
157 }
158
159 pub fn parse_value(&mut self, next_char: char) -> Result<Value, SerDeJsonError> {
161 let value = match next_char {
162 '"' => Value::String(self.parse_string()?),
163 '-' | '0'..='9' => self.parse_number()?,
164 '{' => self.parse_object()?,
165 '[' => self.parse_array()?,
166 't' => self.parse_ident(Ident::True)?,
167 'f' => self.parse_ident(Ident::False)?,
168 'n' => self.parse_ident(Ident::Null)?,
169 _ => return Err(SerDeJsonError::InvalidJson { index: self.index }),
170 };
171
172 Ok(value)
173 }
174
175 pub fn parse_number(&mut self) -> Result<Value, SerDeJsonError> {
176 let Some((i, c)) = self.reader.peek() else {
178 return Err(SerDeJsonError::UnexpectedEnd { index: self.index });
179 };
180
181 self.index = *i;
182
183 let (c, is_positive) = if *c == '-' {
185 self.reader.next();
186 let Some((i, c)) = self.reader.peek() else {
187 return Err(SerDeJsonError::UnexpectedEnd { index: self.index });
188 };
189 self.index = *i;
190 (c, false)
191 } else {
192 (c, true)
193 };
194
195 let full_number = match c {
197 '0' => {
198 self.reader.next();
199 '0'.to_string()
200 }
201 '1'..='9' => self.parse_integer()?,
202 _ => return Err(SerDeJsonError::InvalidJson { index: self.index }),
203 };
204
205 let Some((i, c)) = self.reader.peek() else {
207 return Err(SerDeJsonError::UnexpectedEnd { index: self.index });
208 };
209 self.index = *i;
210 let (full_number, is_decimal) = match *c {
211 '.' => {
212 self.reader.next();
213 (full_number + &self.parse_integer()?, true)
214 }
215 _ => (full_number, false),
216 };
217
218 let Some((i, c)) = self.reader.peek() else {
220 return Err(SerDeJsonError::UnexpectedEnd { index: self.index });
221 };
222 self.index = *i;
223
224 let final_number = match *c {
225 'e' | 'E' => {
226 let full_number: f64 = match full_number.parse() {
227 Ok(full_number) => full_number,
228 Err(e) => {
229 return Err(SerDeJsonError::NumberError {
230 number: full_number,
231 index: self.index,
232 error: e.to_string(),
233 })
234 }
235 };
236 self.reader.next();
237 let Some((i, c)) = self.reader.peek() else {
238 return Err(SerDeJsonError::UnexpectedEnd { index: self.index });
239 };
240 self.index = *i;
241 let mut full_exponent_part = String::new();
242 let c = *c;
243 if c == '+' || c == '-' {
244 self.reader.next();
245 full_exponent_part.push(c);
246 }
247 let full_exponent_part = full_exponent_part + &self.parse_integer()?;
248 let full_exponent_part: i32 = match full_exponent_part.parse() {
249 Ok(full_exponent_part) => full_exponent_part,
250 Err(e) => {
251 return Err(SerDeJsonError::NumberError {
252 number: full_exponent_part,
253 index: self.index,
254 error: e.to_string(),
255 })
256 }
257 };
258 let final_number = full_number * 10f64.powi(full_exponent_part);
259 Number::Decimal(final_number)
260 }
261 _ => {
262 if is_decimal {
263 let nb: f64 = match full_number.parse() {
264 Ok(nb) => nb,
265 Err(e) => {
266 return Err(SerDeJsonError::NumberError {
267 number: full_number,
268 index: self.index,
269 error: e.to_string(),
270 })
271 }
272 };
273 Number::Decimal(nb)
274 } else {
275 if is_positive {
276 let nb: u128 = match full_number.parse() {
277 Ok(nb) => nb,
278 Err(e) => {
279 return Err(SerDeJsonError::NumberError {
280 number: full_number,
281 index: self.index,
282 error: e.to_string(),
283 })
284 }
285 };
286 Number::Integer(nb)
287 } else {
288 let nb: i128 = match full_number.parse() {
289 Ok(nb) => nb,
290 Err(e) => {
291 return Err(SerDeJsonError::NumberError {
292 number: full_number,
293 index: self.index,
294 error: e.to_string(),
295 })
296 }
297 };
298 Number::SignedInteger(nb)
299 }
300 }
301 }
302 };
303
304 Ok(Value::Number(final_number))
305 }
306
307 fn parse_integer(&mut self) -> Result<String, SerDeJsonError> {
311 let mut integer_part = String::new();
312
313 loop {
314 let Some((i, c)) = self.reader.peek() else {
315 return Err(SerDeJsonError::UnexpectedEnd { index: self.index });
316 };
317 self.index = *i;
318 let c = *c;
319 match c {
320 '0'..='9' => {
321 self.reader.next();
322 integer_part.push(c);
323 }
324 _ => break,
325 }
326 }
327
328 if integer_part.is_empty() {
329 return Err(SerDeJsonError::InvalidJson { index: self.index });
330 }
331
332 Ok(integer_part)
333 }
334
335 pub fn parse_string(&mut self) -> Result<String, SerDeJsonError> {
337 self.reader.next();
338
339 let mut chars: Vec<char> = Vec::new();
340
341 loop {
342 let Some((i, c)) = self.reader.next() else {
343 return Err(SerDeJsonError::InvalidJson { index: self.index });
344 };
345 self.index = i;
346 match c {
347 '"' => break,
348 '\\' => {
349 let Some((i, c)) = self.reader.next() else {
350 return Err(SerDeJsonError::InvalidJson { index: self.index });
351 };
352 self.index = i;
353 let c = match c {
354 '"' => '\"',
355 '\\' => '\\',
356 'n' => '\n',
357 'r' => '\r',
358 't' => '\t',
359 'u' => {
360 let mut hex_digits = String::new();
361 for _ in 0..4 {
362 let Some((i, c)) = self.reader.next() else {
363 return Err(SerDeJsonError::InvalidJson { index: self.index });
364 };
365 self.index = i;
366 hex_digits.push(c);
367 }
368 let code_point = u32::from_str_radix(&hex_digits, 16).unwrap();
369 match char::from_u32(code_point) {
370 Some(c) => c,
371 None => {
372 return Err(SerDeJsonError::InvalidJson { index: self.index })
373 }
374 }
375 }
376 _ => return Err(SerDeJsonError::InvalidJson { index: self.index }),
377 };
378 chars.push(c);
379 }
380 c => chars.push(c),
381 }
382 }
383
384 Ok(String::from_iter(chars))
385 }
386
387 pub fn parse_ident(&mut self, ident: Ident) -> Result<Value, SerDeJsonError> {
389 let (value, ident) = match ident {
390 Ident::True => (Value::Boolean(true), "true"),
391 Ident::False => (Value::Boolean(false), "false"),
392 Ident::Null => (Value::Null, "null"),
393 };
394
395 for c_in_pattern in ident.chars() {
396 let Some((i, c)) = self.reader.peek() else {
397 return Err(SerDeJsonError::UnexpectedEnd { index: self.index });
398 };
399 self.index = *i;
400 if *c == ',' || c.is_ascii_whitespace() {
401 break;
402 }
403 if *c != c_in_pattern {
404 return Err(SerDeJsonError::InvalidJson { index: self.index });
405 }
406 self.reader.next();
407 }
408
409 Ok(value)
410 }
411}
412
413#[cfg(test)]
414mod tests {
415 use crate::{error::SerDeJsonError, Value};
416
417 #[test]
418 fn test() {
419 let truc = r#"[
420 {
421 "_id": "666895f3d593468af0ab2235",
422 "index": 0,
423 "guid": "d1f9ebea-c276-4617-90aa-3cd30edc3ae9",
424 "isActive": true,
425 "balance": "$2,310.49",
426 "picture": "http://placehold.it/32x32",
427 "age": 29,
428 "eyeColor": "green",
429 "name": "Kidd Sykes",
430 "gender": "male",
431 "company": "TRASOLA",
432 "email": "kiddsykes@trasola.com",
433 "phone": "+1 (823) 468-2410",
434 "address": "778 Alton Place, Allamuchy, Delaware, 6398",
435 "about": "Labore consequat laborum nisi deserunt nisi nisi dolore fugiat commodo voluptate minim est qui dolore. Aliqua elit est nostrud eu ad excepteur. Esse incididunt laboris enim culpa commodo.\r\n",
436 "registered": "2022-08-31T07:11:46 -02:00",
437 "latitude": 29.07863,
438 "longitude": -118.387919,
439 "tags": [
440 "nulla",
441 "voluptate",
442 "ut",
443 "voluptate",
444 "sunt",
445 "labore",
446 "sunt"
447 ],
448 "friends": [
449 {
450 "id": 0,
451 "name": "Rosario Britt"
452 },
453 {
454 "id": 1,
455 "name": "Maribel Fowler"
456 },
457 {
458 "id": 2,
459 "name": "Jenkins Church"
460 }
461 ],
462 "greeting": "Hello, Kidd Sykes! You have 9 unread messages.",
463 "favoriteFruit": "strawberry"
464 },
465 {
466 "_id": "666895f371fbd3e96171e666",
467 "index": 1,
468 "guid": "da698537-f194-43b5-b270-bceb89a793dc",
469 "isActive": false,
470 "balance": "$3,446.47",
471 "picture": "http://placehold.it/32x32",
472 "age": 34,
473 "eyeColor": "brown",
474 "name": "Tyler Frank",
475 "gender": "male",
476 "company": "BITENDREX",
477 "email": "tylerfrank@bitendrex.com",
478 "phone": "+1 (835) 435-2740",
479 "address": "548 Bergen Street, Downsville, American Samoa, 2917",
480 "about": "Occaecat et Lorem magna ea. Sit in ullamco commodo qui et est in duis mollit sunt exercitation aute aliquip. Occaecat laboris incididunt anim esse ea id magna. Cupidatat eu do enim cupidatat esse amet elit in aliqua. Enim duis cupidatat proident eu adipisicing amet tempor non ullamco aute nostrud excepteur cupidatat.\r\n",
481 "registered": "2022-07-18T09:13:24 -02:00",
482 "latitude": -31.405638,
483 "longitude": 113.128241,
484 "tags": [
485 "officia",
486 "qui",
487 "eiusmod",
488 "magna",
489 "velit",
490 "commodo",
491 "officia"
492 ],
493 "friends": [
494 {
495 "id": 0,
496 "name": "Saundra Grant"
497 },
498 {
499 "id": 1,
500 "name": "Burt Craft"
501 },
502 {
503 "id": 2,
504 "name": "Vinson Vega"
505 }
506 ],
507 "greeting": "Hello, Tyler Frank! You have 2 unread messages.",
508 "favoriteFruit": "banana"
509 }
510]"#;
511
512 let value: Value = match crate::from_str(truc) {
513 Ok(value) => value,
514 Err(e) => match e {
515 SerDeJsonError::InvalidJson { index }
516 | SerDeJsonError::UnexpectedEnd { index }
517 | SerDeJsonError::DupplicateKey { index, .. }
518 | SerDeJsonError::NumberError { index, .. } => {
519 let begin = index - 10;
520 let end = index + 10;
521 let char = truc.get(index..=index).unwrap();
522 let truc_extract = truc.get(begin..=end).unwrap();
523 panic!(
524 "From index {begin} to index {end} : `{}`, character `{char}` : {e:?}",
525 truc_extract
526 );
527 }
528 _ => unimplemented!(),
529 },
530 };
531
532 println!("{value:?}\n\n\n{}", value.to_string());
533 }
534}