dezoomify_rs/
json_utils.rs

1use std::fmt::Display;
2use std::str::FromStr;
3
4use serde::{Deserialize, Deserializer};
5
6/// An iterator over pairs of matching '{' and '}'
7struct IterJson<'a> {
8    s: &'a [u8],
9    start_pos: Vec<usize>,
10    current_pos: usize,
11}
12
13impl<'a> IterJson<'a> {
14    fn new(s: &'a [u8]) -> Self {
15        let start_pos = Vec::with_capacity(8);
16        IterJson { s, start_pos, current_pos: 0 }
17    }
18}
19
20impl<'a> Iterator for IterJson<'a> {
21    type Item = &'a [u8];
22
23    fn next(&mut self) -> Option<Self::Item> {
24        while let Some(c) = self.s.get(self.current_pos) {
25            match c {
26                b'{' => { self.start_pos.push(self.current_pos) }
27                b'}' => {
28                    if let Some(start) = self.start_pos.pop() {
29                        self.current_pos += 1;
30                        return Some(&self.s[start..self.current_pos]);
31                    }
32                }
33                _ => {}
34            }
35            self.current_pos += 1;
36        }
37        None
38    }
39}
40
41/// Return an iterator over all JSON values that can be deserialized in the given byte buffer
42pub fn all_json<'a, T>(bytes: &'a [u8]) -> impl Iterator<Item=T> + 'a
43    where T: Deserialize<'a> + 'a {
44    IterJson::new(bytes)
45        .flat_map(|bytes| std::str::from_utf8(bytes).into_iter())
46        .flat_map(|x| json5::from_str(x).into_iter())
47}
48
49
50/// Deserializer for fields that can be a number or a string representation of the number
51pub fn number_or_string<'de, T, D>(deserializer: D) -> Result<T, D::Error>
52    where
53        D: Deserializer<'de>,
54        T: FromStr + serde::Deserialize<'de>,
55        <T as FromStr>::Err: Display,
56{
57    #[derive(Deserialize)]
58    #[serde(untagged)]
59    enum StringOrInt<T> {
60        String(String),
61        Number(T),
62    }
63
64    match StringOrInt::<T>::deserialize(deserializer)? {
65        StringOrInt::String(s) => s.parse::<T>().map_err(serde::de::Error::custom),
66        StringOrInt::Number(i) => Ok(i),
67    }
68}
69
70#[test]
71fn test_iterjson() {
72    fn f(s: &str) -> Vec<String> {
73        IterJson::new(s.as_bytes())
74            .map(|s| String::from_utf8_lossy(s).to_string())
75            .collect()
76    }
77    assert_eq!(f(" { a { b { c } d { e } f {{ g }}   "), vec!["{ c }", "{ e }", "{ g }", "{{ g }}"]);
78    assert_eq!(f(r#"{"k":{"k":"v"}}"#), vec![r#"{"k":"v"}"#, r#"{"k":{"k":"v"}}"#]);
79    assert_eq!(f(r#"xxx}}xx{{xxx{a}"#), vec!["{a}"]);
80    let only_open = String::from_utf8(vec![b'{'; 1000000]).unwrap();
81    assert_eq!(f(&only_open), Vec::<String>::new());
82}
83
84#[test]
85fn test_alljson() {
86    #[derive(Deserialize, Debug, PartialEq, Eq)]
87    struct S { x: u8 }
88    let actual: Vec<S> = all_json(&br#"{{  "x":1}{-}--{{{"x":2}}"#[..]).collect();
89    assert_eq!(actual, vec![S { x: 1 }, S { x: 2 }]);
90}