microsandbox_control_client/
json_value.rs1use std::collections::BTreeMap;
4use std::fmt;
5
6use serde::Deserializer;
7use serde::de::{MapAccess, Visitor};
8use serde_json::value::RawValue;
9use zeroize::Zeroize;
10
11#[derive(Clone, PartialEq, Eq)]
17pub struct JsonNumber(String);
18
19#[derive(Clone, PartialEq, Eq)]
21pub enum JsonValue {
22 Null,
24 Bool(bool),
26 Number(JsonNumber),
28 String(String),
30 Array(Vec<JsonValue>),
32 Object(BTreeMap<String, JsonValue>),
34}
35
36struct ObjectVisitor {
37 depth: usize,
38}
39
40impl JsonNumber {
45 pub fn as_str(&self) -> &str {
47 &self.0
48 }
49
50 pub fn as_u64(&self) -> Option<u64> {
53 if self.0.starts_with('-') {
54 return None;
55 }
56 self.0.parse().ok()
57 }
58}
59
60impl JsonValue {
61 pub fn parse(bytes: &[u8]) -> Result<Self, &'static str> {
64 let raw: &RawValue = serde_json::from_slice(bytes).map_err(|_| "invalid JSON")?;
65 parse_value(raw.get(), 0).map_err(|_| "invalid JSON")
66 }
67
68 pub fn get(&self, name: &str) -> Option<&Self> {
70 self.as_object()?.get(name)
71 }
72
73 pub fn as_object(&self) -> Option<&BTreeMap<String, Self>> {
75 match self {
76 Self::Object(fields) => Some(fields),
77 _ => None,
78 }
79 }
80
81 pub fn as_array(&self) -> Option<&[Self]> {
83 match self {
84 Self::Array(values) => Some(values),
85 _ => None,
86 }
87 }
88
89 pub fn as_str(&self) -> Option<&str> {
91 match self {
92 Self::String(value) => Some(value),
93 _ => None,
94 }
95 }
96
97 pub fn as_bool(&self) -> Option<bool> {
99 match self {
100 Self::Bool(value) => Some(*value),
101 _ => None,
102 }
103 }
104
105 pub fn as_u64(&self) -> Option<u64> {
107 match self {
108 Self::Number(value) => value.as_u64(),
109 _ => None,
110 }
111 }
112}
113
114impl<'de> Visitor<'de> for ObjectVisitor {
119 type Value = JsonValue;
120
121 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
122 formatter.write_str("a JSON object")
123 }
124
125 fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
126 let mut fields = BTreeMap::new();
127 while let Some(name) = access.next_key::<String>()? {
128 if fields.contains_key(&name) {
131 return Err(serde::de::Error::custom("duplicate JSON field"));
132 }
133 let raw: &'de RawValue = access.next_value()?;
134 let value = parse_value(raw.get(), self.depth + 1)
135 .map_err(|_| serde::de::Error::custom("invalid JSON field"))?;
136 fields.insert(name, value);
137 }
138 Ok(JsonValue::Object(fields))
139 }
140}
141
142impl fmt::Debug for JsonValue {
143 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
144 formatter.write_str("JsonValue { .. }")
147 }
148}
149
150impl fmt::Debug for JsonNumber {
151 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
152 formatter.write_str("JsonNumber { .. }")
153 }
154}
155
156impl Drop for JsonValue {
157 fn drop(&mut self) {
158 match self {
159 Self::String(text) => text.zeroize(),
160 Self::Number(number) => number.0.zeroize(),
161 _ => {} }
163 }
164}
165
166fn parse_value(raw: &str, depth: usize) -> Result<JsonValue, serde_json::Error> {
171 if depth > 128 {
172 return Err(<serde_json::Error as serde::de::Error>::custom(
173 "JSON nesting limit",
174 ));
175 }
176 Ok(match raw.as_bytes().first() {
177 Some(b'{') => {
178 let mut decoder = serde_json::Deserializer::from_str(raw);
179 let value = decoder.deserialize_map(ObjectVisitor { depth })?;
180 decoder.end()?;
181 value
182 }
183 Some(b'[') => {
184 let entries: Vec<&RawValue> = serde_json::from_str(raw)?;
185 JsonValue::Array(
186 entries
187 .iter()
188 .map(|entry| parse_value(entry.get(), depth + 1))
189 .collect::<Result<_, _>>()?,
190 )
191 }
192 Some(b'"') => JsonValue::String(serde_json::from_str(raw)?),
193 Some(b't' | b'f') => JsonValue::Bool(serde_json::from_str(raw)?),
194 Some(b'n') => JsonValue::Null,
195 _ => JsonValue::Number(JsonNumber(raw.to_owned())),
196 })
197}