tpack-core 0.1.0

Core wire codec, schema AST, validation, and native traits for TPACK
Documentation
use alloc::{boxed::Box, vec::Vec};

use crate::{Result, Schema, TpackValue};

use super::helpers::{deserialize_via_from_value, list_schema, optional_schema, type_mismatch};
use super::{FromTpackValue, TpackDeserialize, TpackSerialize};

impl<T> TpackSerialize for Option<T>
where
    T: TpackSerialize,
{
    fn schema() -> Schema {
        optional_schema(T::schema())
    }

    fn to_value(&self) -> TpackValue<'_> {
        TpackValue::Optional(self.as_ref().map(|value| Box::new(value.to_value())))
    }
}

impl<'de, T> TpackDeserialize<'de> for Option<T>
where
    T: TpackDeserialize<'de>,
    Option<T>: FromTpackValue<'de>,
{
    fn schema() -> Schema {
        optional_schema(T::schema())
    }

    fn from_value(value: TpackValue<'de>) -> Result<Self> {
        deserialize_via_from_value(value)
    }
}

impl<'de, T> FromTpackValue<'de> for Option<T>
where
    T: TpackDeserialize<'de>,
{
    fn from_value(value: TpackValue<'de>) -> Result<Self> {
        match value {
            TpackValue::Optional(None) => Ok(None),
            TpackValue::Optional(Some(value)) => {
                Ok(Some(<T as TpackDeserialize<'de>>::from_value(*value)?))
            }
            _ => Err(type_mismatch("Optional")),
        }
    }
}

impl<T> TpackSerialize for Vec<T>
where
    T: TpackSerialize,
{
    fn schema() -> Schema {
        list_schema(T::schema())
    }

    fn to_value(&self) -> TpackValue<'_> {
        TpackValue::List(self.iter().map(TpackSerialize::to_value).collect())
    }
}

impl<'de, T> TpackDeserialize<'de> for Vec<T>
where
    T: TpackDeserialize<'de>,
    Vec<T>: FromTpackValue<'de>,
{
    fn schema() -> Schema {
        list_schema(T::schema())
    }

    fn from_value(value: TpackValue<'de>) -> Result<Self> {
        deserialize_via_from_value(value)
    }
}

impl<'de, T> FromTpackValue<'de> for Vec<T>
where
    T: TpackDeserialize<'de>,
{
    fn from_value(value: TpackValue<'de>) -> Result<Self> {
        match value {
            TpackValue::List(values) => values
                .into_iter()
                .map(<T as TpackDeserialize<'de>>::from_value)
                .collect(),
            _ => Err(type_mismatch("List")),
        }
    }
}