json_lines/
lib.rs

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
6// The code in this module is based on
7// [postcard](https://crates.io/crates/postcard).
8
9use 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
20/// This is the result type used by json-lines
21pub type Result<T> = std::result::Result<T, Error>;
22
23/// This is the error type used by json-lines
24#[derive(Debug)]
25#[cfg_attr(feature = "use-std", derive(thiserror::Error))]
26#[cfg_attr(feature = "use-defmt", derive(defmt::Format))]
27pub enum Error {
28    /// An input-output error
29    #[cfg(feature = "codec")]
30    #[cfg_attr(docsrs, doc(cfg(feature = "codec")))]
31    #[error("{0}")]
32    Io(#[from] std::io::Error),
33    /// A deserialization error
34    #[cfg_attr(feature = "use-std", error("JSON deserialization error"))]
35    DeserializeJson,
36    /// A serialization error
37    #[cfg_attr(feature = "use-std", error("JSON serialization error"))]
38    SerializeJson,
39    /// A newline character was present in the JSON data
40    #[cfg_attr(feature = "use-std", error("newline in JSON data"))]
41    NewlineInData,
42}
43
44/// Deserialize a message of type `T` from a byte slice.
45pub 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
57/// Serialize a `T` to the given slice.
58pub 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
71/// Serialize a `T` to the given slice. The terminating newline is included in
72/// the output buffer.
73pub 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}