Skip to main content

dynamic/
json.rs

1use crate::assert_err;
2
3use super::Dynamic;
4use anyhow::{Result, anyhow};
5
6macro_rules! vec_to_json {
7    ($buf:expr, $vec:expr, $variant:ident) => {{
8        $buf.push('[');
9        let mut once = ZOnce::new("", ",");
10        for value in $vec.iter() {
11            $buf.push_str(once.take());
12            Dynamic::$variant(value.clone()).to_json($buf);
13        }
14        $buf.push(']');
15    }};
16}
17
18pub(crate) fn skip_white(buf: &[u8]) -> Result<usize> {
19    let mut pos = 0usize;
20    while pos < buf.len() && (buf[pos] == b' ' || buf[pos] == b'\r' || buf[pos] == b'\t' || buf[pos] == b'\n') {
21        pos += 1;
22    }
23    if pos < buf.len() { Ok(pos) } else { Err(anyhow!("no more data")) }
24}
25
26const TOKEN: &[u8] = b"01234567890.-+truefalsenull"; //合法的数字和其他 json token
27pub trait FromJson: Sized {
28    fn from_json(buf: &[u8]) -> Result<(Self, usize)>;
29    fn get_token(buf: &[u8]) -> Result<(&str, usize)> {
30        let mut pos = 0usize;
31        while pos < buf.len() && TOKEN.contains(&buf[pos]) {
32            pos += 1;
33        }
34        Ok((std::str::from_utf8(&buf[..pos])?, pos))
35    }
36
37    fn get_string(buf: &[u8]) -> Result<(String, usize)> {
38        let mut pos = 1usize;
39        let mut vec = Vec::new();
40        while pos < buf.len() && buf[pos] != b'"' {
41            if buf[pos] == b'\\' {
42                pos += 1;
43                if pos == buf.len() {
44                    return Err(anyhow!("uncomplete string"));
45                }
46                match buf[pos] {
47                    b'\\' => vec.push(b'\\'),
48                    b'"' => vec.push(b'\"'),
49                    b'r' => vec.push(b'\r'),
50                    b'n' => vec.push(b'\n'),
51                    b't' => vec.push(b'\t'),
52                    b'u' => {
53                        let unicode_str = unsafe { std::str::from_utf8_unchecked(&buf[(pos + 1)..(pos + 5)]) };
54                        if let Ok(unicode) = u32::from_str_radix(unicode_str, 16) {
55                            if unicode < 0x80 {
56                                vec.push(unicode as u8);
57                            } else {
58                                if let Some(unicode_char) = char::from_u32(unicode) {
59                                    unicode_char.encode_utf8(&mut vec);
60                                }
61                            }
62                        }
63                        pos += 4;
64                    }
65                    _ => {
66                        return Err(anyhow!("unknow escape {}", buf[pos]));
67                    }
68                }
69            } else {
70                vec.push(buf[pos]);
71            }
72            pos += 1;
73        }
74        if pos < buf.len() {
75            pos += 1;
76        }
77        Ok(String::from_utf8(vec).map(|s| (s, pos))?)
78    }
79}
80
81pub trait ToJson {
82    fn to_json(&self, buf: &mut String);
83}
84
85use smol_str::SmolStr;
86use std::{
87    collections::BTreeMap,
88    sync::{Arc, RwLock},
89};
90
91impl FromJson for Dynamic {
92    fn from_json(buf: &[u8]) -> Result<(Self, usize)> {
93        let mut pos = skip_white(buf)?;
94        if buf[pos] == b'[' {
95            pos += 1;
96            pos += skip_white(&buf[pos..])?;
97            let mut vec = Vec::<Self>::new();
98            while buf[pos] != b']' {
99                let (item, size) = Self::from_json(&buf[pos..])?;
100                vec.push(item);
101                pos += size;
102                pos += skip_white(&buf[pos..])?;
103                if buf[pos] == b',' {
104                    pos += 1;
105                    pos += skip_white(&buf[pos..])?;
106                }
107            }
108            Ok((Dynamic::List(Arc::new(RwLock::new(vec))), pos + 1))
109        } else if buf[pos] == b'{' {
110            pos += 1;
111            pos += skip_white(&buf[pos..])?;
112            let mut map = BTreeMap::new();
113            while buf[pos] != b'}' {
114                assert_err!(buf[pos] != b'"', anyhow!("need a string key {:?}", String::from_utf8_lossy(&buf[pos..])));
115                let (key, size) = Self::get_string(&buf[pos..])?;
116                pos += size;
117                pos += skip_white(&buf[pos..])?;
118                assert_err!(buf[pos] != b':', anyhow!("need a :"));
119                pos += 1;
120                pos += skip_white(&buf[pos..])?;
121                let (item, size) = Self::from_json(&buf[pos..])?;
122                map.insert(SmolStr::from(key), item);
123                pos += size;
124                pos += skip_white(&buf[pos..])?;
125                if buf[pos] == b',' {
126                    pos += 1;
127                    pos += skip_white(&buf[pos..])?;
128                }
129            }
130            Ok((Dynamic::Map(Arc::new(RwLock::new(map))), pos + 1))
131        } else if buf[pos] == b'"' {
132            let (s, size) = Self::get_string(&buf[pos..])?;
133            Ok((SmolStr::from(s).into(), size))
134        } else {
135            let (token, size) = Self::get_token(&buf[pos..])?;
136            if token == "true" {
137                Ok((Dynamic::from(true), size))
138            } else if token == "false" {
139                Ok((Dynamic::from(false), size))
140            } else if token == "null" {
141                Ok((Dynamic::Null, size))
142            } else if token.contains('.') {
143                let v = token.parse::<f64>()?;
144                Ok((Dynamic::from(v), size))
145            } else {
146                let v = token.parse::<i64>()?;
147                Ok((Dynamic::from(v), size))
148            }
149        }
150    }
151}
152
153impl ToJson for &str {
154    fn to_json(&self, buf: &mut String) {
155        let mut formatted = self.as_bytes().iter().fold(vec![b'\"'], |mut vec, ch| match ch {
156            b'\"' => {
157                vec.extend_from_slice(&[0x5c, 0x22]);
158                vec
159            }
160            b'\\' => {
161                vec.extend_from_slice(&[0x5c, 0x5c]);
162                vec
163            }
164            b'\n' => {
165                vec.extend_from_slice(&[0x5c, 0x6e]);
166                vec
167            }
168            b'\r' => {
169                vec.extend_from_slice(&[0x5c, 0x72]);
170                vec
171            }
172            b'\t' => {
173                vec.extend_from_slice(&[0x5c, 0x74]);
174                vec
175            }
176            _ => {
177                vec.push(*ch);
178                vec
179            }
180        });
181        formatted.push(b'\"');
182        buf.push_str(unsafe { std::str::from_utf8_unchecked(&formatted) });
183    }
184}
185
186impl ToJson for i64 {
187    fn to_json(&self, buf: &mut String) {
188        buf.push_str(&self.to_string());
189    }
190}
191
192use super::ZOnce;
193
194impl ToJson for Dynamic {
195    fn to_json(&self, buf: &mut String) {
196        match self {
197            Self::Iter { idx: _, keys: _, value: _ } => {}
198            Self::Bool(b) => {
199                if *b {
200                    buf.push_str("true")
201                } else {
202                    buf.push_str("false")
203                }
204            }
205            Self::F32(f) => buf.push_str(&f.to_string()),
206            Self::F64(f) => buf.push_str(&f.to_string()),
207            Self::I8(i) => buf.push_str(&i.to_string()),
208            Self::I16(i) => buf.push_str(&i.to_string()),
209            Self::I32(i) => buf.push_str(&i.to_string()),
210            Self::I64(i) => buf.push_str(&i.to_string()),
211            Self::U8(i) => buf.push_str(&i.to_string()),
212            Self::U16(i) => buf.push_str(&i.to_string()),
213            Self::U32(i) => buf.push_str(&i.to_string()),
214            Self::U64(i) => buf.push_str(&i.to_string()),
215            Self::Null => buf.push_str("null"),
216            Self::String(s) => s.as_str().to_json(buf),
217            Self::Bytes(vec) => vec_to_json!(buf, vec, U8),
218            Self::VecI8(vec) => vec_to_json!(buf, vec, I8),
219            Self::VecU16(vec) => vec_to_json!(buf, vec, U16),
220            Self::VecI16(vec) => vec_to_json!(buf, vec, I16),
221            Self::VecU32(vec) => vec_to_json!(buf, vec, U32),
222            Self::VecI32(vec) => vec_to_json!(buf, vec, I32),
223            Self::VecF32(vec) => vec_to_json!(buf, vec, F32),
224            Self::VecU64(vec) => vec_to_json!(buf, vec, U64),
225            Self::VecI64(vec) => vec_to_json!(buf, vec, I64),
226            Self::VecF64(vec) => vec_to_json!(buf, vec, F64),
227            Self::List(a) => {
228                buf.push('[');
229                let mut once = ZOnce::new("", ",\n");
230                a.read().unwrap().iter().for_each(|item| {
231                    buf.push_str(once.take());
232                    item.to_json(buf);
233                });
234                buf.push(']');
235            }
236            Self::Map(map) => {
237                buf.push('{');
238                let mut once = ZOnce::new("", ",\n");
239                map.read().unwrap().iter().for_each(|(k, v)| {
240                    buf.push_str(once.take());
241                    k.as_str().to_json(buf);
242                    buf.push_str(": ");
243                    v.to_json(buf);
244                });
245                buf.push_str("}\n");
246            }
247            Self::Struct { .. } => {
248                buf.push('{');
249                let mut once = ZOnce::new("", ",\n");
250                self.keys().iter().for_each(|k| {
251                    buf.push_str(once.take());
252                    k.as_str().to_json(buf);
253                    buf.push_str(": ");
254                    self.get_dynamic(k).unwrap_or(Dynamic::Null).to_json(buf);
255                });
256                buf.push_str("}\n");
257            }
258        }
259    }
260}