1#![no_std]
2
3use embedded_io::Write;
4use numtoa::base10;
5
6#[derive(Debug,PartialEq,Eq,Clone,Copy)]
8pub enum JsonValue<'a> {
9 String(&'a str),
11 Boolean(bool),
13 Number(i64),
15}
16
17#[derive(Debug,PartialEq,Eq,Clone,Copy)]
19pub struct JsonField<'a,'b> {
20 pub key: &'a str,
21 pub value: JsonValue<'b>,
22}
23
24impl <'a,'b> JsonField<'a,'b> {
25 pub fn new(key: &'a str, value: JsonValue<'b>) -> Self {
27 JsonField { key, value }
28 }
29 pub fn new_string(key: &'a str, value: &'b str) -> Self {
31 Self::new(key, JsonValue::String(value))
32 }
33 pub fn new_number(key: &'a str, value: i64) -> Self {
35 Self::new(key, JsonValue::Number(value))
36 }
37 pub fn new_boolean(key: &'a str, value: bool) -> Self {
39 Self::new(key, JsonValue::Boolean(value))
40 }
41}
42
43#[derive(Debug)]
45pub struct JsonObject<Fields> {
46 fields: Fields,
47 num_fields: usize,
48}
49
50#[derive(Debug)]
52pub enum JsonParseFailure {
53 Incomplete,
55 TooManyFields,
57 InvalidStructure,
59 InvalidStringField,
61 InvalidNumericField,
63 InvalidBooleanField,
65}
66
67pub const EMPTY_FIELD: JsonField<'static,'static> = JsonField{ key: "", value: JsonValue::Number(0)};
69
70impl <'a,'b> Default for JsonField<'a,'b> {
71 fn default() -> Self {
72 EMPTY_FIELD
73 }
74}
75
76impl<'a,T: FieldBuffer<'a> + Default + ?Sized> Default for JsonObject<T> {
77 fn default() -> Self {
78 JsonObject { fields: T::default(), num_fields: 0 }
79 }
80}
81
82pub trait FieldBuffer<'data>: AsRef<[JsonField<'data,'data>]> {
84
85 fn into_json_object(self) -> JsonObject<Self> where Self: Sized {
87 let len = self.as_ref().len();
88 JsonObject::wrap(self, len)
89 }
90
91 fn as_json_object(&self) -> JsonObject<&Self> {
93 JsonObject::wrap(self, self.as_ref().len())
94 }
95
96}
97pub trait FieldBufferMut<'a>: FieldBuffer<'a> + AsMut<[JsonField<'a,'a>]> {
99
100 fn as_json_object_mut(&mut self) -> JsonObject<&mut Self> {
102 let len = self.as_ref().len();
103 JsonObject::wrap(self, len)
104 }
105
106}
107
108impl <'a,T: AsRef<[JsonField<'a,'a>]>> FieldBuffer<'a> for T {}
109impl <'a,T: FieldBuffer<'a> + AsMut<[JsonField<'a,'a>]>> FieldBufferMut<'a> for T {}
110
111impl <'a,T: FieldBuffer<'a>> JsonObject<T> {
112 pub const fn wrap(fields: T, num_fields: usize) -> Self {
113 JsonObject { fields, num_fields }
114 }
115
116 pub const fn len(&self) -> usize {
117 self.num_fields
118 }
119
120 pub fn capacity(&self) -> usize {
121 self.fields.as_ref().len()
122 }
123
124 pub fn fields(&self) -> &[JsonField<'a,'a>] {
125 self.fields.as_ref().split_at(self.num_fields).0
126 }
127
128 pub fn serialize<Output: Write>(&self, output: Output) -> Result<usize,Output::Error> {
129 serialize_json_object(output, self.fields().as_ref())
130 }
131}
132
133impl<'a,T: FieldBuffer<'a>> From<T> for JsonObject<T> {
134 fn from(field_buffer: T) -> Self {
135 let num_headers = field_buffer.as_ref().len();
136 JsonObject::wrap(field_buffer, num_headers)
137 }
138}
139
140impl <'a,T: FieldBufferMut<'a>> JsonObject<T> {
141
142 pub fn fields_mut(&mut self) -> &mut [JsonField<'a,'a>] {
144 self.fields.as_mut().split_at_mut(self.num_fields).0
145 }
146
147 pub fn push<'x: 'a,'y: 'a>(&mut self, field: JsonField<'x,'y>) -> Result<(),JsonField<'x,'y>> {
149 if self.num_fields == self.fields.as_ref().len(){
150 return Err(field);
151 }
152 self.fields.as_mut()[self.num_fields] = field;
153 self.num_fields += 1;
154 Ok(())
155 }
156
157 pub fn pop(&mut self) -> Option<JsonField<'a,'a>> {
159 if self.num_fields == 0 {
160 return None;
161 }
162 self.num_fields -= 1;
163 Some(core::mem::take(&mut self.fields.as_mut()[self.num_fields+1]))
164 }
165
166 pub fn push_field<'x: 'a,'y: 'a>(&mut self, key: &'x str, value: JsonValue<'y>) -> Result<(),()> {
168 if self.num_fields == self.fields.as_ref().len(){
169 return Err(());
170 }
171 self.fields.as_mut()[self.num_fields] = JsonField { key, value };
172 self.num_fields += 1;
173 Ok(())
174 }
175
176 pub fn parse(&mut self, data: &'a [u8]) -> Result<(usize,usize),JsonParseFailure> {
178 let (data_end, parsed_fields) = parse_json_object(data, self.fields.as_mut())?;
179 let new_num_fields = parsed_fields.len();
180 self.num_fields = new_num_fields;
181 Ok((data_end,new_num_fields))
182 }
183
184}
185
186
187pub type ArrayJsonObject<'a,const N: usize> = JsonObject<[JsonField<'a,'a>; N]>;
189
190impl<'a,const N: usize> ArrayJsonObject<'a,N> {
191
192 pub const fn new() -> Self {
194 JsonObject::wrap([EMPTY_FIELD; N], 0)
195 }
196
197 pub const fn push_const(&mut self, key: &'a str, value: JsonValue<'a>) -> Result<(),()> {
199 if self.num_fields == N {
200 return Err(());
201 }
202 self.fields[self.num_fields] = JsonField { key, value: value };
203 self.num_fields += 1;
204 Ok(())
205 }
206
207 pub const fn pop_const(&mut self) -> Option<&JsonField<'a,'a>> {
209 match self.fields_const().split_last() {
210 None => return None,
211 Some((split,_remaining)) => return Some(split),
212 }
213 }
214
215 pub fn new_parsed(data: &'a [u8]) -> Result<(usize,Self),JsonParseFailure> {
217 let mut ret = Self::new();
218 let (data_end,_num_headers) = ret.parse(data)?;
219 Ok((data_end,ret))
220 }
221
222 pub const fn fields_const(&self) -> &[JsonField<'a,'a>] {
224 self.fields.split_at(self.num_fields).0
225 }
226
227 pub const fn fields_mut_const(&mut self) -> &mut [JsonField<'a,'a>] {
229 self.fields.split_at_mut(self.num_fields).0
230 }
231
232}
233
234pub fn parse_json_object<'data,'field_buffer>(data: &'data [u8], field_buffer: &'field_buffer mut [JsonField<'data,'data>]) -> Result<(usize,&'field_buffer[JsonField<'data,'data>]),JsonParseFailure> {
236 let mut current_data_index = 0;
237 let mut current_field_index = 0;
238 let mut map_entry_needs_comma = false;
239 skip_whitespace(&mut current_data_index, data)?;
240 if data[current_data_index] != b'{' {
241 return Err(JsonParseFailure::InvalidStructure);
242 }
243 let _map_start_index = current_data_index;
244 current_data_index += 1;
245 while current_data_index < data.len() {
246 skip_whitespace(&mut current_data_index, data)?;
247 if data[current_data_index] == b'}' {
248 return Ok((current_data_index+1,field_buffer.split_at(current_field_index).0))
249 } else if map_entry_needs_comma {
250 if data[current_data_index] != b',' {
251 return Err(JsonParseFailure::InvalidStructure);
252 }
253 current_data_index += 1;
254 map_entry_needs_comma = false;
255 } else {
256 map_entry_needs_comma = true;
257 let key_start_quote_index = current_data_index;
258 current_data_index += 1;
259 skip_json_string(&mut current_data_index, data)?;
260 let key_end_quote_index = current_data_index;
261 let string_key = core::str::from_utf8(&data[key_start_quote_index+1..key_end_quote_index]).expect("skipped json object key string");
262 current_data_index += 1;
263 skip_whitespace(&mut current_data_index, data)?;
264 if data[current_data_index] != b':' {
265 return Err(JsonParseFailure::InvalidStructure);
266 }
267 current_data_index += 1;
268 skip_whitespace(&mut current_data_index, data)?;
269
270 if data[current_data_index] == b'"' {
271 let value_start_quote_index = current_data_index;
272 current_data_index += 1;
273 skip_json_string(&mut current_data_index, data)?;
274 let value_end_quote_index = current_data_index;
275 current_data_index += 1;
276 let string_value = core::str::from_utf8(&data[value_start_quote_index+1..value_end_quote_index]).expect("skipped json object value string");
277 if current_field_index >= field_buffer.len() {
278 return Err(JsonParseFailure::TooManyFields);
279 }
280 field_buffer[current_field_index] = JsonField::new(string_key, JsonValue::String(string_value));
281 current_field_index += 1;
282 } else if data[current_data_index] == b't' || data[current_data_index] == b'f' {
283 let expect_true = data[current_data_index] == b't';
284 skip_json_boolean(&mut current_data_index, data, expect_true)?;
285 if current_field_index >= field_buffer.len() {
286 return Err(JsonParseFailure::TooManyFields);
287 }
288 field_buffer[current_field_index] = JsonField::new(string_key, JsonValue::Boolean(expect_true));
289 current_field_index += 1;
290 } else if (data[current_data_index] >= b'0' && data[current_data_index] < b'9') || data[current_data_index] == b'-' {
291 let numeric_start_index = current_data_index;
292 current_data_index += 1;
293 skip_json_numeric(&mut current_data_index, data)?;
294 let numeric_after_index = current_data_index;
295 let numeric_string = core::str::from_utf8(&data[numeric_start_index..numeric_after_index]).expect("skipped numeric digits");
296 let numeric_value: i64 = match numeric_string.parse() {
297 Ok(i) => i,
298 Err(_) => return Err(JsonParseFailure::InvalidNumericField),
299 };
300 if current_field_index >= field_buffer.len() {
301 return Err(JsonParseFailure::TooManyFields);
302 }
303 field_buffer[current_field_index] = JsonField::new(string_key, JsonValue::Number(numeric_value));
304 current_field_index += 1;
305 } else {
306 return Err(JsonParseFailure::InvalidStructure);
307 }
308 }
309 }
310 Err(JsonParseFailure::Incomplete)
311}
312
313fn skip_json_string(index: &mut usize, data: &[u8]) -> Result<(),JsonParseFailure> {
314 let mut last_char_escape = false;
315 while *index < data.len() {
316 if data[*index] == b'\\' && !last_char_escape {
317 last_char_escape = true;
318 } else if data[*index] == b'"' && !last_char_escape {
319 return Ok(());
320 } else if !data[*index].is_ascii() {
321 return Err(JsonParseFailure::InvalidStringField);
322 } else {
323 last_char_escape = false
324 }
325 *index += 1;
326 }
327 Err(JsonParseFailure::Incomplete)
328}
329
330fn skip_json_numeric(index: &mut usize, data: &[u8]) -> Result<(),JsonParseFailure> {
331 while *index < data.len() && data[*index] <= b'9' && data[*index] >= b'0' {
332 *index += 1;
333 }
334 if *index == data.len() {
335 Err(JsonParseFailure::Incomplete)
336 } else if data[*index].is_ascii_whitespace() || data[*index] == b',' || data[*index] == b'}' {
337 Ok(())
338 } else {
339 Err(JsonParseFailure::InvalidNumericField)
340 }
341}
342
343fn skip_json_boolean(index: &mut usize, data: &[u8], value: bool) -> Result<(),JsonParseFailure> {
344 let start = *index;
345 let target = if value { "true" } else { "false" };
346 while (*index - start) < target.len() {
347 if *index >= data.len() {
348 return Err(JsonParseFailure::Incomplete)
349 }
350 if data[*index] != target.as_bytes()[*index-start] {
351 return Err(JsonParseFailure::InvalidBooleanField);
352 }
353 *index += 1;
354 }
355 Ok(())
356}
357
358fn skip_whitespace(index: &mut usize, data: &[u8]) -> Result<(),JsonParseFailure> {
359 while *index < data.len() && data[*index].is_ascii_whitespace() {
360 *index += 1;
361 }
362 if *index == data.len() {
363 Err(JsonParseFailure::Incomplete)
364 } else {
365 Ok(())
366 }
367}
368
369pub fn serialize_json_object<
371'data,
372Output: Write,
373>(
374 mut output: Output,
375 fields: &[JsonField<'data,'data>],
376) -> Result<usize, Output::Error> {
377 let mut ret = 0;
378 tracked_write(&mut output,&mut ret , "{")?;
379 let mut field_needs_comma = false;
380 for field in fields.as_ref().iter() {
381 if field_needs_comma {
382 tracked_write(&mut output,&mut ret , ",")?;
383 } else {
384 field_needs_comma = true;
385 }
386 write_escaped_json_string(&mut output, &mut ret , field.key)?;
387 tracked_write(&mut output, &mut ret , ":")?;
388 match field.value {
389 JsonValue::String(s) => {
390 write_escaped_json_string(&mut output, &mut ret , s)?;
391 },
392 JsonValue::Boolean(false) => {
393 tracked_write(&mut output,&mut ret , "false")?;
394 },
395 JsonValue::Boolean(true) => {
396 tracked_write(&mut output,&mut ret , "true")?;
397 },
398 JsonValue::Number(n) => {
399 tracked_write(&mut output,&mut ret , &base10::i64(n))?;
400 },
401 }
402 }
403 tracked_write(&mut output, &mut ret , "}")?;
404 Ok(ret)
405}
406
407
408fn tracked_write<T: Write>(mut output: T, counter: &mut usize, data: &str) -> Result<(), T::Error> {
409 output.write_all(data.as_bytes())?;
410 *counter += data.len();
411 Ok(())
412}
413
414fn write_escaped_json_string<T: Write>(mut output: T, counter: &mut usize, data: &str) -> Result<(), T::Error> {
415 tracked_write(&mut output, &mut *counter, "\"")?;
416 for field_character in data.chars() {
417 if field_character == '"' {
418 tracked_write(&mut output, &mut *counter, unsafe { core::str::from_utf8_unchecked(&[b'\\', field_character as u8]) })?;
419 } else {
420 tracked_write(&mut output, &mut *counter, unsafe { core::str::from_utf8_unchecked(&[field_character as u8]) })?;
421 }
422 }
423 tracked_write(&mut output, &mut *counter, "\"")?;
424 Ok(())
425}
426
427#[cfg(test)]
428mod tests {
429
430 use super::*;
431
432 #[test]
433 fn test_serialize_object_empty() {
434 let mut buffer = [0_u8; 1000];
435 let test_map = ArrayJsonObject::<50>::new();
436 let n = test_map.serialize(buffer.as_mut_slice()).unwrap();
437 assert_eq!(b"{}", buffer.split_at(n).0)
438 }
439
440 #[test]
441 fn test_serialize_object_simple() {
442 let mut buffer = [0_u8; 1000];
443 let mut test_map = ArrayJsonObject::<50>::new();
444 test_map.push_field("sub", JsonValue::String("1234567890")).unwrap();
445 test_map.push_field("name", JsonValue::String("John Doe")).unwrap();
446 test_map.push_field("iat", JsonValue::Number(1516239022)).unwrap();
447 test_map.push_field("something", JsonValue::Boolean(false)).unwrap();
448 let n = test_map.serialize(buffer.as_mut_slice()).unwrap();
449 assert_eq!(b"{\"sub\":\"1234567890\",\"name\":\"John Doe\",\"iat\":1516239022,\"something\":false}", buffer.split_at(n).0)
450 }
451
452 #[test]
453 fn test_parse_object_success_empty() {
454 let (bytes_consumed,json_object) = ArrayJsonObject::<0>::new_parsed(b"{}").unwrap();
455 assert!(json_object.fields().is_empty());
456 assert_eq!(bytes_consumed, 2);
457 }
458
459 #[test]
460 fn test_parse_object_success_simple() {
461 let data = b"{\"sub\":\"1234567890\",\"name\":\"John Doe\",\"iat\":1516239022,\"something\":false}";
462 let (data_end,json_object) = ArrayJsonObject::<50>::new_parsed(data).unwrap();
463 let test_fields = json_object.fields();
464 assert_eq!(4, test_fields.len());
465 assert_eq!(JsonField { key: "sub", value: JsonValue::String("1234567890")}, test_fields[0]);
466 assert_eq!(JsonField { key: "name", value: JsonValue::String("John Doe")}, test_fields[1]);
467 assert_eq!(JsonField { key: "iat", value: JsonValue::Number(1516239022)}, test_fields[2]);
468 assert_eq!(JsonField { key: "something", value: JsonValue::Boolean(false)}, test_fields[3]);
469 }
470
471 #[test]
472 fn test_parse_object_failure_incomplete_simple() {
473 match ArrayJsonObject::<50>::new_parsed(b"{") {
474 Err(JsonParseFailure::Incomplete) => {},
475 _ => panic!("incomplete json")
476 }
477 }
478
479 #[test]
480 fn test_parse_object_failure_incomplete_brace() {
481 match ArrayJsonObject::<50>::new_parsed(b"{\"sub\":\"1234567890\",\"name\":\"John Doe\",\"iat\":1516239022,\"something\":false") {
482 Err(JsonParseFailure::Incomplete) => {},
483 other => panic!("{:?}", other)
484 }
485 }
486
487 #[test]
488 fn test_parse_object_failure_too_many_fields() {
489 match ArrayJsonObject::<0>::new_parsed(b"{\"some\":\"thing\"}") {
490 Err(JsonParseFailure::TooManyFields) => {},
491 other => panic!("{:?}", other)
492 }
493 }
494
495}