1#![warn(missing_docs)]
2#![cfg_attr(not(doctest), doc = include_str!("../README.md"))]
3#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
4#![cfg_attr(not(feature = "use-std"), no_std)]
5
6use serde::{Deserialize, Serialize};
10
11pub mod accumulator;
12
13#[cfg(feature = "codec")]
14#[cfg_attr(docsrs, doc(cfg(feature = "codec")))]
15pub mod codec;
16
17#[cfg(not(feature = "use-std"))]
18extern crate core as std;
19
20pub type Result<T> = std::result::Result<T, Error>;
22
23#[derive(Debug)]
25#[cfg_attr(feature = "use-std", derive(thiserror::Error))]
26#[cfg_attr(feature = "use-defmt", derive(defmt::Format))]
27pub enum Error {
28 #[cfg(feature = "codec")]
30 #[cfg_attr(docsrs, doc(cfg(feature = "codec")))]
31 #[error("{0}")]
32 Io(#[from] std::io::Error),
33 #[cfg_attr(feature = "use-std", error("JSON deserialization error"))]
35 DeserializeJson,
36 #[cfg_attr(feature = "use-std", error("JSON serialization error"))]
38 SerializeJson,
39 #[cfg_attr(feature = "use-std", error("newline in JSON data"))]
41 NewlineInData,
42}
43
44pub fn from_bytes<'a, T>(s: &'a mut [u8]) -> Result<T>
46where
47 T: Deserialize<'a>,
48{
49 let (t, used) = serde_json_core::from_slice(s).map_err(|_| Error::DeserializeJson)?;
50 if used == s.len() {
51 Ok(t)
52 } else {
53 Err(Error::DeserializeJson)
54 }
55}
56
57pub fn to_slice<'a, 'b, T>(value: &'b T, buf: &'a mut [u8]) -> Result<&'a mut [u8]>
59where
60 T: Serialize + ?Sized,
61{
62 let nbytes = serde_json_core::to_slice(&value, buf).map_err(|_| Error::SerializeJson)?;
63 let encoded = &mut buf[..nbytes];
64
65 if encoded.iter().position(|&i| i == b'\n').is_some() {
66 return Err(Error::NewlineInData);
67 }
68 Ok(encoded)
69}
70
71pub fn to_slice_newline<'a, 'b, T>(value: &'b T, buf: &'a mut [u8]) -> Result<&'a mut [u8]>
74where
75 T: Serialize + ?Sized,
76{
77 let encoded = to_slice(value, buf)?;
78 let nbytes = encoded.len();
79
80 let (used, _drop) = buf.split_at_mut(nbytes + 1);
81 used[nbytes] = b'\n';
82 Ok(used)
83}