1#![no_std]
2
3use embedded_io::{ErrorType, 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<T> JsonObject<T> {
77 pub fn into_inner(self) -> (T,usize) {
79 (self.fields,self.num_fields)
80 }
81}
82
83impl<'a,T: FieldBuffer<'a> + Default + ?Sized> Default for JsonObject<T> {
84 fn default() -> Self {
85 JsonObject { fields: T::default(), num_fields: 0 }
86 }
87}
88
89pub trait FieldBuffer<'data>: AsRef<[JsonField<'data,'data>]> {
91
92 fn into_json_object(self) -> JsonObject<Self> where Self: Sized {
94 JsonObject::wrap_init(self)
95 }
96
97 fn as_json_object(&self) -> JsonObject<&Self> {
99 JsonObject::wrap_init(self)
100 }
101
102}
103
104impl <'a,T: AsRef<[JsonField<'a,'a>]>> FieldBuffer<'a> for T {}
106
107pub trait FieldBufferMut<'a>: FieldBuffer<'a> + AsMut<[JsonField<'a,'a>]> {
109
110 fn as_json_object_mut(&mut self) -> JsonObject<&mut Self> {
112 JsonObject::wrap_init(self)
113 }
114
115}
116
117impl <'a,T: FieldBuffer<'a> + AsMut<[JsonField<'a,'a>]>> FieldBufferMut<'a> for T {}
119
120pub trait StringWrite: ErrorType {
121 fn write_string(&mut self, data: &str) -> (usize,Result<(), <Self as ErrorType>::Error>);
122}
123
124impl<T: Write> StringWrite for T {
125 fn write_string(&mut self, mut data: &str) -> (usize,Result<(), <Self as ErrorType>::Error>) {
126 let mut written = 0_usize;
127 loop {
128 if data.is_empty() {
129 return (written,Ok(()));
130 }
131 let n = match self.write(data.as_bytes()) {
132 Ok(0) => panic!(),
133 Err(e) => return (written, Err(e)),
134 Ok(n) => n,
135 };
136 written += n;
137 data = data.split_at(n).1
138 }
139 }
140}
141
142impl <'a,T: FieldBuffer<'a>> JsonObject<T> {
153
154 pub const fn wrap(fields: T) -> Self {
156 JsonObject { fields, num_fields: 0 }
157 }
158
159 pub fn wrap_init(fields: T) -> Self {
161 let num_fields = fields.as_ref().len();
162 JsonObject { fields, num_fields }
163 }
164
165 pub const fn len(&self) -> usize {
167 self.num_fields
168 }
169
170 pub fn capacity(&self) -> usize {
172 self.fields.as_ref().len()
173 }
174
175 pub fn fields(&self) -> &[JsonField<'a,'a>] {
177 self.fields.as_ref().split_at(self.num_fields).0
178 }
179
180
181
182 pub fn serialize_into<Output: Write>(&self, output: Output) -> Result<usize,Output::Error> {
197 serialize_json_object(output, self.fields().as_ref())
198 }
199}
200
201impl<'a,T: FieldBuffer<'a>> From<T> for JsonObject<T> {
202 fn from(field_buffer: T) -> Self {
203 JsonObject::wrap_init(field_buffer)
204 }
205}
206
207impl <'a,T: FieldBufferMut<'a>> JsonObject<T> {
208
209 pub fn fields_mut(&mut self) -> &mut [JsonField<'a,'a>] {
211 self.fields.as_mut().split_at_mut(self.num_fields).0
212 }
213
214 pub fn push<'x: 'a,'y: 'a>(&mut self, field: JsonField<'x,'y>) -> Result<(),JsonField<'x,'y>> {
216 if self.num_fields == self.fields.as_ref().len(){
217 return Err(field);
218 }
219 self.fields.as_mut()[self.num_fields] = field;
220 self.num_fields += 1;
221 Ok(())
222 }
223
224 pub fn pop(&mut self) -> Option<JsonField<'a,'a>> {
226 if self.num_fields == 0 {
227 return None;
228 }
229 self.num_fields -= 1;
230 Some(core::mem::take(&mut self.fields.as_mut()[self.num_fields+1]))
231 }
232
233 pub fn push_field<'x: 'a,'y: 'a>(&mut self, key: &'x str, value: JsonValue<'y>) -> Result<(),()> {
235 if self.num_fields == self.fields.as_ref().len(){
236 return Err(());
237 }
238 self.fields.as_mut()[self.num_fields] = JsonField { key, value };
239 self.num_fields += 1;
240 Ok(())
241 }
242
243 pub fn parse(&mut self, data: &'a [u8]) -> Result<(usize,usize),JsonParseFailure> {
245 let (data_end, parsed_fields) = parse_json_object(data, self.fields.as_mut())?;
246 let new_num_fields = parsed_fields.len();
247 self.num_fields = new_num_fields;
248 Ok((data_end,new_num_fields))
249 }
250
251}
252
253impl <'a,T: FieldBufferMut<'a> + Default> JsonObject<T> {
254
255 pub fn default_parsed(data: &'a [u8]) -> Result<(usize,Self),JsonParseFailure> {
257 let mut ret = Self::default();
258 let (num_bytes,_num_fields) = ret.parse(data)?;
259 Ok((num_bytes,ret))
260 }
261
262}
263
264
265pub type ArrayJsonObject<'a,const N: usize> = JsonObject<[JsonField<'a,'a>; N]>;
267
268impl<'a,const N: usize> ArrayJsonObject<'a,N> {
269
270 pub const fn new() -> Self {
272 JsonObject::wrap([EMPTY_FIELD; N])
273 }
274
275 pub fn new_parsed(data: &'a [u8]) -> Result<(usize,Self),JsonParseFailure> {
277 let mut ret = Self::new();
278 let (data_end,_num_headers) = ret.parse(data)?;
279 Ok((data_end,ret))
280 }
281
282 pub const fn push_const(&mut self, key: &'a str, value: JsonValue<'a>) -> Result<(),()> {
284 if self.num_fields == N {
285 return Err(());
286 }
287 self.fields[self.num_fields] = JsonField { key, value: value };
288 self.num_fields += 1;
289 Ok(())
290 }
291
292 pub const fn pop_const(&mut self) -> Option<&JsonField<'a,'a>> {
294 match self.fields_const().split_last() {
295 None => return None,
296 Some((split,_remaining)) => return Some(split),
297 }
298 }
299
300 pub const fn fields_const(&self) -> &[JsonField<'a,'a>] {
302 self.fields.split_at(self.num_fields).0
303 }
304
305 pub const fn fields_mut_const(&mut self) -> &mut [JsonField<'a,'a>] {
307 self.fields.split_at_mut(self.num_fields).0
308 }
309
310}
311
312pub 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> {
314 let mut current_data_index = 0;
315 let mut current_field_index = 0;
316 let mut map_entry_needs_comma = false;
317 skip_whitespace(&mut current_data_index, data)?;
318 if data[current_data_index] != b'{' {
319 return Err(JsonParseFailure::InvalidStructure);
320 }
321 let _map_start_index = current_data_index;
322 current_data_index += 1;
323 while current_data_index < data.len() {
324 skip_whitespace(&mut current_data_index, data)?;
325 if data[current_data_index] == b'}' {
326 return Ok((current_data_index+1,field_buffer.split_at(current_field_index).0))
327 } else if map_entry_needs_comma {
328 if data[current_data_index] != b',' {
329 return Err(JsonParseFailure::InvalidStructure);
330 }
331 current_data_index += 1;
332 map_entry_needs_comma = false;
333 } else {
334 map_entry_needs_comma = true;
335 let key_start_quote_index = current_data_index;
336 current_data_index += 1;
337 skip_json_string(&mut current_data_index, data)?;
338 let key_end_quote_index = current_data_index;
339 let string_key = core::str::from_utf8(&data[key_start_quote_index+1..key_end_quote_index]).expect("skipped json object key string");
340 current_data_index += 1;
341 skip_whitespace(&mut current_data_index, data)?;
342 if data[current_data_index] != b':' {
343 return Err(JsonParseFailure::InvalidStructure);
344 }
345 current_data_index += 1;
346 skip_whitespace(&mut current_data_index, data)?;
347
348 if data[current_data_index] == b'"' {
349 let value_start_quote_index = current_data_index;
350 current_data_index += 1;
351 skip_json_string(&mut current_data_index, data)?;
352 let value_end_quote_index = current_data_index;
353 current_data_index += 1;
354 let string_value = core::str::from_utf8(&data[value_start_quote_index+1..value_end_quote_index]).expect("skipped json object value string");
355 if current_field_index >= field_buffer.len() {
356 return Err(JsonParseFailure::TooManyFields);
357 }
358 field_buffer[current_field_index] = JsonField::new(string_key, JsonValue::String(string_value));
359 current_field_index += 1;
360 } else if data[current_data_index] == b't' || data[current_data_index] == b'f' {
361 let expect_true = data[current_data_index] == b't';
362 skip_json_boolean(&mut current_data_index, data, expect_true)?;
363 if current_field_index >= field_buffer.len() {
364 return Err(JsonParseFailure::TooManyFields);
365 }
366 field_buffer[current_field_index] = JsonField::new(string_key, JsonValue::Boolean(expect_true));
367 current_field_index += 1;
368 } else if (data[current_data_index] >= b'0' && data[current_data_index] < b'9') || data[current_data_index] == b'-' {
369 let numeric_start_index = current_data_index;
370 current_data_index += 1;
371 skip_json_numeric(&mut current_data_index, data)?;
372 let numeric_after_index = current_data_index;
373 let numeric_string = core::str::from_utf8(&data[numeric_start_index..numeric_after_index]).expect("skipped numeric digits");
374 let numeric_value: i64 = match numeric_string.parse() {
375 Ok(i) => i,
376 Err(_) => return Err(JsonParseFailure::InvalidNumericField),
377 };
378 if current_field_index >= field_buffer.len() {
379 return Err(JsonParseFailure::TooManyFields);
380 }
381 field_buffer[current_field_index] = JsonField::new(string_key, JsonValue::Number(numeric_value));
382 current_field_index += 1;
383 } else {
384 return Err(JsonParseFailure::InvalidStructure);
385 }
386 }
387 }
388 Err(JsonParseFailure::Incomplete)
389}
390
391fn skip_json_string(index: &mut usize, data: &[u8]) -> Result<(),JsonParseFailure> {
392 let mut last_char_escape = false;
393 while *index < data.len() {
394 if data[*index] == b'\\' && !last_char_escape {
395 last_char_escape = true;
396 } else if data[*index] == b'"' && !last_char_escape {
397 return Ok(());
398 } else if !data[*index].is_ascii() {
399 return Err(JsonParseFailure::InvalidStringField);
400 } else {
401 last_char_escape = false
402 }
403 *index += 1;
404 }
405 Err(JsonParseFailure::Incomplete)
406}
407
408fn skip_json_numeric(index: &mut usize, data: &[u8]) -> Result<(),JsonParseFailure> {
409 while *index < data.len() && data[*index] <= b'9' && data[*index] >= b'0' {
410 *index += 1;
411 }
412 if *index == data.len() {
413 Err(JsonParseFailure::Incomplete)
414 } else if data[*index].is_ascii_whitespace() || data[*index] == b',' || data[*index] == b'}' {
415 Ok(())
416 } else {
417 Err(JsonParseFailure::InvalidNumericField)
418 }
419}
420
421fn skip_json_boolean(index: &mut usize, data: &[u8], value: bool) -> Result<(),JsonParseFailure> {
422 let start = *index;
423 let target = if value { "true" } else { "false" };
424 while (*index - start) < target.len() {
425 if *index >= data.len() {
426 return Err(JsonParseFailure::Incomplete)
427 }
428 if data[*index] != target.as_bytes()[*index-start] {
429 return Err(JsonParseFailure::InvalidBooleanField);
430 }
431 *index += 1;
432 }
433 Ok(())
434}
435
436fn skip_whitespace(index: &mut usize, data: &[u8]) -> Result<(),JsonParseFailure> {
437 while *index < data.len() && data[*index].is_ascii_whitespace() {
438 *index += 1;
439 }
440 if *index == data.len() {
441 Err(JsonParseFailure::Incomplete)
442 } else {
443 Ok(())
444 }
445}
446
447pub fn serialize_json_object<
449'data,
450Output: Write,
451>(
452 mut output: Output,
453 fields: &[JsonField<'data,'data>],
454) -> Result<usize, Output::Error> {
455 let mut ret = 0;
456 tracked_write(&mut output,&mut ret , "{")?;
457 let mut field_needs_comma = false;
458 for field in fields.as_ref().iter() {
459 if field_needs_comma {
460 tracked_write(&mut output,&mut ret , ",")?;
461 } else {
462 field_needs_comma = true;
463 }
464 write_escaped_json_string(&mut output, &mut ret , field.key)?;
465 tracked_write(&mut output, &mut ret , ":")?;
466 match field.value {
467 JsonValue::String(s) => {
468 write_escaped_json_string(&mut output, &mut ret , s)?;
469 },
470 JsonValue::Boolean(false) => {
471 tracked_write(&mut output,&mut ret , "false")?;
472 },
473 JsonValue::Boolean(true) => {
474 tracked_write(&mut output,&mut ret , "true")?;
475 },
476 JsonValue::Number(n) => {
477 tracked_write(&mut output,&mut ret , &base10::i64(n))?;
478 },
479 }
480 }
481 tracked_write(&mut output, &mut ret , "}")?;
482 Ok(ret)
483}
484
485
486fn tracked_write<T: Write>(mut output: T, counter: &mut usize, data: &str) -> Result<(), T::Error> {
487 output.write_all(data.as_bytes())?;
488 *counter += data.len();
489 Ok(())
490}
491
492fn write_escaped_json_string<T: Write>(mut output: T, counter: &mut usize, data: &str) -> Result<(), T::Error> {
493 tracked_write(&mut output, &mut *counter, "\"")?;
494 for field_character in data.chars() {
495 if field_character == '"' {
496 tracked_write(&mut output, &mut *counter, unsafe { core::str::from_utf8_unchecked(&[b'\\', field_character as u8]) })?;
497 } else {
498 tracked_write(&mut output, &mut *counter, unsafe { core::str::from_utf8_unchecked(&[field_character as u8]) })?;
499 }
500 }
501 tracked_write(&mut output, &mut *counter, "\"")?;
502 Ok(())
503}
504
505
506#[cfg(feature = "alloc")]
507mod alloc {
508
509 extern crate alloc as alloclib;
510 use core::convert::Infallible;
511
512 use alloclib::string::String;
513 use embedded_io::ErrorType;
514
515 use crate::StringWrite;
516
517 struct _StringWrapper<T: ?Sized> {
518 inner: T
519 }
520
521 impl<T: AsMut<String>> ErrorType for _StringWrapper<T> {
522 type Error = Infallible;
523 }
524
525 impl<T: AsMut<String>> StringWrite for _StringWrapper<T> {
526 fn write_string(&mut self, data: &str) -> (usize,Result<(), <Self as ErrorType>::Error>) {
527 self.inner.as_mut().push_str(data);
528 (data.len(), Ok(()))
529 }
530 }
531}
532
533#[cfg(feature = "std")]
534mod std {
535 extern crate std as stdlib;
536 use embedded_io_adapters::std::FromStd as StdIoAdapter;
537 use stdlib::io::Error as StandardLibIoError;
538 use stdlib::io::Write as StandardLibIoWrite;
539
540 use crate::FieldBuffer;
541 use crate::JsonObject;
542
543 impl <'a,T: FieldBuffer<'a>> JsonObject<T> {
544 pub fn serialize_std<Output: StandardLibIoWrite>(&self, output: Output) -> Result<usize,StandardLibIoError> {
546 self.serialize_into(StdIoAdapter::new(output))
547 }
548 }
549}
550
551#[cfg(test)]
552mod tests {
553
554 use super::*;
555
556 #[test]
557 fn test_serialize_object_empty() {
558 let mut buffer = [0_u8; 1000];
559 let test_map = ArrayJsonObject::<50>::new();
560 let n = test_map.serialize_into(buffer.as_mut_slice()).unwrap();
561 assert_eq!(b"{}", buffer.split_at(n).0)
562 }
563
564 #[test]
565 fn test_serialize_object_simple() {
566 let mut buffer = [0_u8; 1000];
567 let mut test_map = ArrayJsonObject::<50>::new();
568 test_map.push_field("sub", JsonValue::String("1234567890")).unwrap();
569 test_map.push_field("name", JsonValue::String("John Doe")).unwrap();
570 test_map.push_field("iat", JsonValue::Number(1516239022)).unwrap();
571 test_map.push_field("something", JsonValue::Boolean(false)).unwrap();
572 let n = test_map.serialize_into(buffer.as_mut_slice()).unwrap();
573 assert_eq!(br#"{"sub":"1234567890","name":"John Doe","iat":1516239022,"something":false}"#, buffer.split_at(n).0)
574 }
575
576 #[test]
577 fn test_parse_object_success_empty() {
578 let (bytes_consumed,json_object) = ArrayJsonObject::<0>::new_parsed(b"{}").unwrap();
579 assert!(json_object.fields().is_empty());
580 assert_eq!(bytes_consumed, 2);
581 }
582
583 #[test]
584 fn test_parse_object_success_simple() {
585 let data = br#"{"sub":"1234567890","name":"John Doe","iat":1516239022,"something":false}"#;
586 let (data_end,json_object) = ArrayJsonObject::<50>::new_parsed(data).unwrap();
587 assert_eq!(data_end, data.len());
588 let test_fields = json_object.fields();
589 assert_eq!(4, test_fields.len());
590 assert_eq!(JsonField { key: "sub", value: JsonValue::String("1234567890")}, test_fields[0]);
591 assert_eq!(JsonField { key: "name", value: JsonValue::String("John Doe")}, test_fields[1]);
592 assert_eq!(JsonField { key: "iat", value: JsonValue::Number(1516239022)}, test_fields[2]);
593 assert_eq!(JsonField { key: "something", value: JsonValue::Boolean(false)}, test_fields[3]);
594 }
595
596 #[test]
597 fn test_parse_object_failure_incomplete_simple() {
598 match ArrayJsonObject::<50>::new_parsed(b"{") {
599 Err(JsonParseFailure::Incomplete) => {},
600 _ => panic!("incomplete json")
601 }
602 }
603
604 #[test]
605 fn test_parse_object_failure_incomplete_brace() {
606 match ArrayJsonObject::<50>::new_parsed(br#"{"sub":"1234567890","name":"John Doe","iat":1516239022,"something":false"#) {
607 Err(JsonParseFailure::Incomplete) => {},
608 other => panic!("{:?}", other)
609 }
610 }
611
612 #[test]
613 fn test_parse_object_failure_too_many_fields() {
614 match ArrayJsonObject::<0>::new_parsed(br#"{"some":"thing"}"#) {
615 Err(JsonParseFailure::TooManyFields) => {},
616 other => panic!("{:?}", other)
617 }
618 }
619
620}