nson 0.14.0

NSON is a lightweight data-interchange format like JSON or BSON
Documentation
//! Decode

use core::fmt;

use alloc::format;
use alloc::string::{FromUtf8Error, String};

#[cfg(feature = "std")]
use std::io::{self, Cursor, Read};

#[cfg(not(feature = "std"))]
use crate::io::{self, Cursor, Read};

#[cfg(feature = "serde")]
use crate::serde::decode::Decoder;
#[cfg(feature = "serde")]
use serde::de::Deserialize;

use crate::array::Array;
use crate::id::Id;
use crate::map::Map;
use crate::spec::DataType;
use crate::value::{Binary, Value};

#[derive(Debug)]
pub enum DecodeError {
    IoError(io::Error),
    FromUtf8Error(FromUtf8Error),
    UnrecognizedElementType(u8),
    InvalidLength(usize, String),
    Unknown(String),
    #[cfg(feature = "serde")]
    Serde(crate::serde::DecodeError),
}

impl From<io::Error> for DecodeError {
    fn from(err: io::Error) -> DecodeError {
        DecodeError::IoError(err)
    }
}

impl From<FromUtf8Error> for DecodeError {
    fn from(err: FromUtf8Error) -> DecodeError {
        DecodeError::FromUtf8Error(err)
    }
}

#[cfg(feature = "serde")]
impl From<crate::serde::DecodeError> for DecodeError {
    fn from(err: crate::serde::DecodeError) -> DecodeError {
        DecodeError::Serde(err)
    }
}

impl fmt::Display for DecodeError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            DecodeError::IoError(ref inner) => inner.fmt(fmt),
            DecodeError::FromUtf8Error(ref inner) => inner.fmt(fmt),
            DecodeError::UnrecognizedElementType(tag) => {
                write!(fmt, "Unrecognized element type `{}`", tag)
            }
            DecodeError::InvalidLength(ref len, ref desc) => {
                write!(fmt, "Expecting length {}, {}", len, desc)
            }
            DecodeError::Unknown(ref inner) => inner.fmt(fmt),
            #[cfg(feature = "serde")]
            DecodeError::Serde(ref inner) => inner.fmt(fmt),
        }
    }
}

impl core::error::Error for DecodeError {
    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
        match *self {
            DecodeError::IoError(ref inner) => Some(inner),
            DecodeError::FromUtf8Error(ref inner) => Some(inner),
            #[cfg(feature = "serde")]
            DecodeError::Serde(ref inner) => Some(inner),
            _ => None,
        }
    }
}

pub type DecodeResult<T> = Result<T, DecodeError>;

#[inline]
pub(crate) fn read_u8(reader: &mut impl Read) -> DecodeResult<u8> {
    let mut buf = [0; 1];
    reader.read_exact(&mut buf)?;
    Ok(u8::from_le_bytes(buf))
}

#[inline]
pub(crate) fn read_i8(reader: &mut impl Read) -> DecodeResult<i8> {
    let mut buf = [0; 1];
    reader.read_exact(&mut buf)?;
    Ok(i8::from_le_bytes(buf))
}

#[inline]
pub(crate) fn read_i16(reader: &mut impl Read) -> DecodeResult<i16> {
    let mut buf = [0; 2];
    reader.read_exact(&mut buf)?;
    Ok(i16::from_le_bytes(buf))
}

#[inline]
pub(crate) fn read_u16(reader: &mut impl Read) -> DecodeResult<u16> {
    let mut buf = [0; 2];
    reader.read_exact(&mut buf)?;
    Ok(u16::from_le_bytes(buf))
}

#[inline]
pub(crate) fn read_i32(reader: &mut impl Read) -> DecodeResult<i32> {
    let mut buf = [0; 4];
    reader.read_exact(&mut buf)?;
    Ok(i32::from_le_bytes(buf))
}

#[inline]
pub(crate) fn read_i64(reader: &mut impl Read) -> DecodeResult<i64> {
    let mut buf = [0; 8];
    reader.read_exact(&mut buf)?;
    Ok(i64::from_le_bytes(buf))
}

#[inline]
pub(crate) fn read_u32(reader: &mut impl Read) -> DecodeResult<u32> {
    let mut buf = [0; 4];
    reader.read_exact(&mut buf)?;
    Ok(u32::from_le_bytes(buf))
}

#[inline]
pub(crate) fn read_u64(reader: &mut impl Read) -> DecodeResult<u64> {
    let mut buf = [0; 8];
    reader.read_exact(&mut buf)?;
    Ok(u64::from_le_bytes(buf))
}

#[inline]
pub(crate) fn read_f32(reader: &mut impl Read) -> DecodeResult<f32> {
    let mut buf = [0; 4];
    reader.read_exact(&mut buf)?;
    Ok(f32::from_le_bytes(buf))
}

#[inline]
pub(crate) fn read_f64(reader: &mut impl Read) -> DecodeResult<f64> {
    let mut buf = [0; 8];
    reader.read_exact(&mut buf)?;
    Ok(f64::from_le_bytes(buf))
}

pub(crate) fn read_string(reader: &mut impl Read) -> DecodeResult<String> {
    let len = read_u32(reader)?;

    if len < crate::MIN_NSON_SIZE - 1 {
        return Err(DecodeError::InvalidLength(
            len as usize,
            format!("Invalid string length of {}", len),
        ));
    }

    if len > crate::MAX_NSON_SIZE {
        return Err(DecodeError::InvalidLength(
            len as usize,
            format!("Invalid string length of {}", len),
        ));
    }

    let len = len - 4;

    let mut buf = alloc::vec![0u8; len as usize];
    reader.read_exact(&mut buf)?;

    let s = String::from_utf8(buf)?;

    Ok(s)
}

pub(crate) fn read_binary(reader: &mut impl Read) -> DecodeResult<Binary> {
    let len = read_u32(reader)?;

    if len < crate::MIN_NSON_SIZE - 1 {
        return Err(DecodeError::InvalidLength(
            len as usize,
            format!("Invalid binary length of {}", len),
        ));
    }

    if len > crate::MAX_NSON_SIZE {
        return Err(DecodeError::InvalidLength(
            len as usize,
            format!("Invalid binary length of {}", len),
        ));
    }

    let len = len - 4;

    let mut data = alloc::vec![0u8; len as usize];
    reader.read_exact(&mut data)?;

    Ok(Binary(data))
}

pub fn decode_array(reader: &mut impl Read) -> DecodeResult<Array> {
    let mut arr = Array::new();

    let len = read_u32(reader)?;

    if len < crate::MIN_NSON_SIZE {
        return Err(DecodeError::InvalidLength(
            len as usize,
            format!("Invalid array length of {}", len),
        ));
    }

    if len > crate::MAX_NSON_SIZE {
        return Err(DecodeError::InvalidLength(
            len as usize,
            format!("Invalid array length of {}", len),
        ));
    }

    loop {
        let tag = read_u8(reader)?;
        if tag == 0 {
            break;
        }

        let val = decode_value_with_tag(reader, tag)?;
        arr.push(val)
    }

    Ok(arr)
}

pub fn decode_map(reader: &mut impl Read) -> DecodeResult<Map> {
    let mut map = Map::new();

    // disregard the length: using Read::take causes infinite type recursion
    let len = read_u32(reader)?;

    if len < crate::MIN_NSON_SIZE {
        return Err(DecodeError::InvalidLength(
            len as usize,
            format!("Invalid map length of {}", len),
        ));
    }

    if len > crate::MAX_NSON_SIZE {
        return Err(DecodeError::InvalidLength(
            len as usize,
            format!("Invalid map length of {}", len),
        ));
    }

    loop {
        let key = {
            let len = read_u8(reader)?;
            if len == 0 {
                break;
            }

            let len = len - 1;

            let mut buf = alloc::vec![0u8; len as usize];
            reader.read_exact(&mut buf)?;

            String::from_utf8(buf)?
        };

        let val = decode_value(reader)?;

        map.insert(key, val);
    }

    Ok(map)
}

pub fn decode_value(reader: &mut impl Read) -> DecodeResult<Value> {
    let tag = read_u8(reader)?;
    decode_value_with_tag(reader, tag)
}

fn decode_value_with_tag(reader: &mut impl Read, tag: u8) -> DecodeResult<Value> {
    match DataType::from(tag) {
        Some(DataType::F32) => read_f32(reader).map(Value::F32),
        Some(DataType::F64) => read_f64(reader).map(Value::F64),
        Some(DataType::I32) => read_i32(reader).map(Value::I32),
        Some(DataType::I64) => read_i64(reader).map(Value::I64),
        Some(DataType::U32) => read_u32(reader).map(Value::U32),
        Some(DataType::U64) => read_u64(reader).map(Value::U64),
        Some(DataType::I8) => read_i8(reader).map(Value::I8),
        Some(DataType::U8) => read_u8(reader).map(Value::U8),
        Some(DataType::I16) => read_i16(reader).map(Value::I16),
        Some(DataType::U16) => read_u16(reader).map(Value::U16),
        Some(DataType::String) => read_string(reader).map(Value::String),
        Some(DataType::Map) => decode_map(reader).map(Value::Map),
        Some(DataType::Array) => decode_array(reader).map(Value::Array),
        Some(DataType::Binary) => read_binary(reader).map(Value::Binary),
        Some(DataType::Bool) => Ok(Value::Bool(crate::decode::read_u8(reader)? != 0)),
        Some(DataType::Null) => Ok(Value::Null),
        Some(DataType::TimeStamp) => read_u64(reader).map(|v| Value::TimeStamp(v.into())),
        Some(DataType::Id) => {
            let mut buf = [0; 12];
            reader.read_exact(&mut buf)?;

            Ok(Value::Id(Id::with_bytes(buf)))
        }
        None => Err(DecodeError::UnrecognizedElementType(tag)),
    }
}

#[cfg(feature = "serde")]
pub fn from_nson<'de, T: Deserialize<'de>>(value: Value) -> DecodeResult<T> {
    let de = Decoder::new(value);
    Deserialize::deserialize(de).map_err(DecodeError::Serde)
}

#[cfg(feature = "serde")]
pub fn from_bytes<'de, T: Deserialize<'de>>(bytes: &[u8]) -> DecodeResult<T> {
    let value = Value::from_bytes(bytes)?;
    from_nson(value)
}

impl Value {
    pub fn from_bytes(bytes: &[u8]) -> DecodeResult<Value> {
        let mut reader = Cursor::new(bytes);
        decode_value(&mut reader)
    }
}

impl Map {
    pub fn from_bytes(slice: &[u8]) -> DecodeResult<Map> {
        let mut reader = Cursor::new(slice);
        decode_map(&mut reader)
    }
}

impl Array {
    pub fn from_bytes(slice: &[u8]) -> DecodeResult<Array> {
        let mut reader = Cursor::new(slice);
        decode_array(&mut reader)
    }
}