litl 0.6.0

A JSON dialect with support for tagged binary data
Documentation
use std::collections::HashMap;

use deepsize::DeepSizeOf;
use futures_core::Stream;
use futures_io::AsyncBufRead;
use futures_util::{future, AsyncBufReadExt, StreamExt, TryStreamExt};
use map_ordering_serializer::MapOrderingSerializer;
use serde::{de::DeserializeOwned, Serialize};
use serde_json::ser::CompactFormatter;
use thiserror::Error;

pub use zbase32;

mod map_ordering_serializer;
pub mod raw_data_serde;
mod tagged_data;

pub use tagged_data::*;

#[inline]
pub fn to_writer<W, T>(writer: W, value: &T) -> std::io::Result<()>
where
    W: std::io::Write,
    T: ?Sized + Serialize,
{
    let mut ser = serde_json::Serializer::with_formatter(writer, CompactFormatter {});
    value.serialize(&mut ser)?;
    Ok(())
}

#[inline]
pub fn to_writer_canonical<W, T>(writer: W, value: &T) -> std::io::Result<()>
where
    W: std::io::Write,
    T: ?Sized + Serialize,
{
    let mut ser = MapOrderingSerializer::new(writer);
    value.serialize(&mut ser)?;
    Ok(())
}

#[inline]
pub fn to_vec<T>(value: &T) -> std::io::Result<Vec<u8>>
where
    T: ?Sized + Serialize,
{
    let mut writer = Vec::new();
    to_writer(&mut writer, value)?;
    Ok(writer)
}

#[inline]
pub fn to_vec_canonical<T>(value: &T) -> std::io::Result<Vec<u8>>
where
    T: ?Sized + Serialize,
{
    let mut writer = Vec::new();
    to_writer_canonical(&mut writer, value)?;
    Ok(writer)
}

#[inline]
pub fn to_string<T>(value: &T) -> std::io::Result<String>
where
    T: ?Sized + Serialize,
{
    let vec = to_vec(value)?;

    Ok(unsafe {
        // We do not emit invalid UTF-8.
        String::from_utf8_unchecked(vec)
    })
}

#[inline]
pub fn to_string_canonical<T>(value: &T) -> std::io::Result<String>
where
    T: ?Sized + Serialize,
{
    let vec = to_vec_canonical(value)?;

    Ok(unsafe {
        // We do not emit invalid UTF-8.
        String::from_utf8_unchecked(vec)
    })
}

#[inline]
pub fn from_slice_owned<T: DeserializeOwned>(sl: &[u8]) -> Result<T, self::Error> {
    serde_json::from_reader(sl)
}

#[inline]
pub fn val_from_str(s: &str) -> Result<litl_val::Val, self::Error> {
    serde_json::from_str(s)
}

pub use serde_json::{
    from_reader, from_slice, from_str, from_value, json, to_string_pretty, to_value, Error, Value,
};

pub use litl_val::{from_val, to_val, Key, Map, Val, ValDeserializerError, ValE, ValRef};

pub struct MeasureValue(pub Value);

impl DeepSizeOf for MeasureValue {
    fn deep_size_of_children(&self, context: &mut deepsize::Context) -> usize {
        match self.0.clone() {
            Value::Null => std::mem::size_of::<Value>(),
            Value::Bool(_) => std::mem::size_of::<Value>(),
            Value::Number(_) => std::mem::size_of::<Value>(),
            Value::String(s) => {
                s.deep_size_of_children(context) + std::mem::size_of::<Value>()
                    - std::mem::size_of::<String>()
            }
            Value::Array(a) => {
                a.into_iter()
                    .map(MeasureValue)
                    .collect::<Vec<_>>()
                    .deep_size_of_children(context)
                    + std::mem::size_of::<Value>()
                    - std::mem::size_of::<Vec<Value>>()
            }
            Value::Object(o) => {
                o.into_iter()
                    .map(|(k, v)| (k, MeasureValue(v)))
                    .collect::<HashMap<_, _>>()
                    .deep_size_of_children(context)
                    + std::mem::size_of::<Value>()
                    - std::mem::size_of::<serde_json::map::Map<String, Value>>()
            }
        }
    }
}

#[macro_export]
macro_rules! impl_debug_as_litl {
    ($t:ty) => {
        impl std::fmt::Debug for $t {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                f.write_str(&litl::to_string_pretty(&self).unwrap())
            }
        }
    };
}

pub fn from_newln_sep_slice<T: DeserializeOwned>(s: &[u8]) -> Result<Vec<T>, Error> {
    let mut result = Vec::new();
    for line in s.split(|b| *b == b'\n') {
        if !line.is_empty() {
            result.push(from_slice(line)?);
        }
    }
    Ok(result)
}

pub fn read_newln_sep_stream<R: AsyncBufRead, T: DeserializeOwned>(
    reader: R,
) -> impl Stream<Item = Result<T, ReadNewlnSepStreamError>> {
    reader
        .lines()
        .map_err(ReadNewlnSepStreamError::Io)
        .and_then(|line| {
            future::ready(from_str(&line).map_err(ReadNewlnSepStreamError::Deserialize))
        })
}

#[derive(Error, Debug)]
pub enum ReadNewlnSepStreamError {
    #[error(transparent)]
    Io(#[from] std::io::Error),
    #[error(transparent)]
    Deserialize(#[from] crate::Error),
}

pub fn to_newln_sep_vec<'a, T: Serialize + 'a, I: IntoIterator<Item = &'a T>>(
    iter: I,
) -> Result<Vec<u8>, std::io::Error> {
    let mut buf = Vec::new();
    for item in iter {
        let item_str = to_string(item)?;
        buf.extend_from_slice(item_str.as_bytes());
        buf.push(b'\n');
    }
    Ok(buf)
}

pub fn to_newln_sep_stream<T: Serialize, S: Stream<Item = T>>(
    stream: S,
) -> impl Stream<Item = Result<Vec<u8>, std::io::Error>> {
    stream.map(|val| {
        let mut bytes = crate::to_vec(&val)?;
        bytes.push(b'\n');
        Ok(bytes)
    })
}