blazingly-json 0.1.0

A focused, Tokio-free JSON engine for small protocol and API payloads
Documentation
use crate::{Error, Result, Value};
use serde::de::{
    self, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, VariantAccess,
    Visitor,
};
use std::collections::btree_map;
use std::vec;

impl<'de> de::Deserializer<'de> for Value {
    type Error = Error;

    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        match self {
            Self::Null => visitor.visit_unit(),
            Self::Bool(value) => visitor.visit_bool(value),
            Self::Number(value) if value.is_u64() => visitor.visit_u64(
                value
                    .as_u64()
                    .expect("a u64 JSON number must contain a u64"),
            ),
            Self::Number(value) if value.is_i64() => visitor.visit_i64(
                value
                    .as_i64()
                    .expect("an i64 JSON number must contain an i64"),
            ),
            Self::Number(value) => visitor.visit_f64(
                value
                    .as_f64()
                    .expect("a JSON number must be representable as f64"),
            ),
            Self::String(value) => visitor.visit_string(value),
            Self::Array(values) => visitor.visit_seq(ValueSeqAccess {
                values: values.into_iter(),
            }),
            Self::Object(values) => visitor.visit_map(ValueMapAccess {
                values: values.into_iter(),
                pending: None,
            }),
        }
    }

    fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        match self {
            Self::Bool(value) => visitor.visit_bool(value),
            other => Err(type_error("boolean", &other)),
        }
    }

    fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_i8(integer(&self)?)
    }

    fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_i16(integer(&self)?)
    }

    fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_i32(integer(&self)?)
    }

    fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_i64(integer(&self)?)
    }

    fn deserialize_i128<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_i128(integer(&self)?)
    }

    fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_u8(unsigned(&self)?)
    }

    fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_u16(unsigned(&self)?)
    }

    fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_u32(unsigned(&self)?)
    }

    fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_u64(unsigned(&self)?)
    }

    fn deserialize_u128<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_u128(unsigned(&self)?)
    }

    fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        #[allow(clippy::cast_possible_truncation)]
        let value = float(&self)? as f32;
        visitor.visit_f32(value)
    }

    fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_f64(float(&self)?)
    }

    fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        match self {
            Self::String(value) => {
                let mut characters = value.chars();
                let character = characters
                    .next()
                    .ok_or_else(|| Error::message("expected one character"))?;
                if characters.next().is_some() {
                    return Err(Error::message("expected one character"));
                }
                visitor.visit_char(character)
            }
            other => Err(type_error("string", &other)),
        }
    }

    fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        match self {
            Self::String(value) => visitor.visit_string(value),
            other => Err(type_error("string", &other)),
        }
    }

    fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        self.deserialize_str(visitor)
    }

    fn deserialize_bytes<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        self.deserialize_seq(visitor)
    }

    fn deserialize_byte_buf<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        self.deserialize_seq(visitor)
    }

    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        if self.is_null() {
            visitor.visit_none()
        } else {
            visitor.visit_some(self)
        }
    }

    fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        if self.is_null() {
            visitor.visit_unit()
        } else {
            Err(type_error("null", &self))
        }
    }

    fn deserialize_unit_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        visitor: V,
    ) -> Result<V::Value> {
        self.deserialize_unit(visitor)
    }

    fn deserialize_newtype_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        visitor: V,
    ) -> Result<V::Value> {
        visitor.visit_newtype_struct(self)
    }

    fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        match self {
            Self::Array(values) => visitor.visit_seq(ValueSeqAccess {
                values: values.into_iter(),
            }),
            other => Err(type_error("array", &other)),
        }
    }

    fn deserialize_tuple<V: Visitor<'de>>(self, _length: usize, visitor: V) -> Result<V::Value> {
        self.deserialize_seq(visitor)
    }

    fn deserialize_tuple_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        length: usize,
        visitor: V,
    ) -> Result<V::Value> {
        self.deserialize_tuple(length, visitor)
    }

    fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        match self {
            Self::Object(values) => visitor.visit_map(ValueMapAccess {
                values: values.into_iter(),
                pending: None,
            }),
            other => Err(type_error("object", &other)),
        }
    }

    fn deserialize_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        _fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value> {
        self.deserialize_map(visitor)
    }

    fn deserialize_enum<V: Visitor<'de>>(
        self,
        _name: &'static str,
        _variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value> {
        match self {
            Self::String(variant) => visitor.visit_enum(variant.into_deserializer()),
            Self::Object(mut values) if values.len() == 1 => {
                let (variant, value) = values.pop_first().expect("length was checked");
                visitor.visit_enum(ValueEnumAccess { variant, value })
            }
            other => Err(type_error("enum string or one-entry object", &other)),
        }
    }

    fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        self.deserialize_string(visitor)
    }

    fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_unit()
    }
}

fn integer<T: TryFrom<i64>>(value: &Value) -> Result<T> {
    let value = value
        .as_i64()
        .ok_or_else(|| type_error("signed integer", value))?;
    T::try_from(value).map_err(|_| Error::message("integer is out of range"))
}

fn unsigned<T: TryFrom<u64>>(value: &Value) -> Result<T> {
    let value = value
        .as_u64()
        .ok_or_else(|| type_error("unsigned integer", value))?;
    T::try_from(value).map_err(|_| Error::message("integer is out of range"))
}

fn float(value: &Value) -> Result<f64> {
    value.as_f64().ok_or_else(|| type_error("number", value))
}

fn type_error(expected: &str, value: &Value) -> Error {
    let actual = match value {
        Value::Null => "null",
        Value::Bool(_) => "boolean",
        Value::Number(_) => "number",
        Value::String(_) => "string",
        Value::Array(_) => "array",
        Value::Object(_) => "object",
    };
    Error::message(format!("expected {expected}, found {actual}"))
}

struct ValueSeqAccess {
    values: vec::IntoIter<Value>,
}

impl<'de> SeqAccess<'de> for ValueSeqAccess {
    type Error = Error;

    fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T) -> Result<Option<T::Value>> {
        self.values
            .next()
            .map(|value| seed.deserialize(value))
            .transpose()
    }

    fn size_hint(&self) -> Option<usize> {
        Some(self.values.len())
    }
}

struct ValueMapAccess {
    values: btree_map::IntoIter<String, Value>,
    pending: Option<Value>,
}

impl<'de> MapAccess<'de> for ValueMapAccess {
    type Error = Error;

    fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>> {
        let Some((key, value)) = self.values.next() else {
            return Ok(None);
        };
        self.pending = Some(value);
        seed.deserialize(key.into_deserializer()).map(Some)
    }

    fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value> {
        seed.deserialize(
            self.pending
                .take()
                .ok_or_else(|| Error::message("map value has no key"))?,
        )
    }

    fn size_hint(&self) -> Option<usize> {
        Some(self.values.len())
    }
}

struct ValueEnumAccess {
    variant: String,
    value: Value,
}

impl<'de> EnumAccess<'de> for ValueEnumAccess {
    type Error = Error;
    type Variant = ValueVariantAccess;

    fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self::Variant)> {
        let variant = seed.deserialize(serde::de::value::StringDeserializer::<Error>::new(
            self.variant,
        ))?;
        Ok((variant, ValueVariantAccess { value: self.value }))
    }
}

struct ValueVariantAccess {
    value: Value,
}

impl<'de> VariantAccess<'de> for ValueVariantAccess {
    type Error = Error;

    fn unit_variant(self) -> Result<()> {
        de::Deserialize::deserialize(self.value)
    }

    fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value> {
        seed.deserialize(self.value)
    }

    fn tuple_variant<V: Visitor<'de>>(self, length: usize, visitor: V) -> Result<V::Value> {
        de::Deserializer::deserialize_tuple(self.value, length, visitor)
    }

    fn struct_variant<V: Visitor<'de>>(
        self,
        fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value> {
        de::Deserializer::deserialize_struct(self.value, "", fields, visitor)
    }
}