flow-value 0.3.0

Value type for flow inputs and outputs.
Documentation
use crate::{Value, value_type::Variant};
use base64::prelude::*;
use serde::de::VariantAccess;
use std::borrow::Cow;

pub struct TextRepr(Value);

impl From<TextRepr> for Value {
    fn from(v: TextRepr) -> Value {
        v.0
    }
}

struct EnumVisitor;

impl<'de> serde::de::Visitor<'de> for EnumVisitor {
    type Value = Value;

    fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("any valid value")
    }

    fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
    where
        A: serde::de::EnumAccess<'de>,
    {
        let (ty, a) = data.variant::<Variant>()?;
        match ty {
            Variant::Null => {
                let num = a.newtype_variant::<u64>()?;
                if num != 0 {
                    return Err(serde::de::Error::invalid_value(
                        serde::de::Unexpected::Unsigned(num),
                        &"0",
                    ));
                }
                Ok(Value::Null)
            }
            Variant::String => Ok(Value::String(a.newtype_variant()?)),
            Variant::Bool => Ok(Value::Bool(a.newtype_variant()?)),
            Variant::U64 => Ok(Value::U64(number_from_str(a)?)),
            Variant::I64 => Ok(Value::I64(number_from_str(a)?)),
            Variant::F64 => Ok(Value::F64(number_from_str(a)?)),
            Variant::Decimal => Ok(Value::Decimal(number_from_str(a)?)),
            Variant::I128 => Ok(Value::I128(number_from_str(a)?)),
            Variant::U128 => Ok(Value::U128(number_from_str(a)?)),
            Variant::B32 => Ok(Value::B32(b58_str_32(a)?)),
            Variant::B64 => Ok(Value::B64(b58_str_64(a)?)),
            Variant::Bytes => Ok(Value::Bytes(b64_str(a)?)),
            Variant::Array => Ok(Value::Array(a.newtype_variant::<Array>()?.0)),
            Variant::Map => Ok(Value::Map(a.newtype_variant::<Map>()?.0)),
        }
    }
}

struct MapVisitor;

impl<'de> serde::de::Visitor<'de> for MapVisitor {
    type Value = crate::Map;

    fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("map")
    }

    fn visit_map<A>(self, mut a: A) -> Result<Self::Value, A::Error>
    where
        A: serde::de::MapAccess<'de>,
    {
        let mut map = crate::Map::new();
        if let Some(len) = a.size_hint() {
            map.reserve(len);
        }
        while let Some((k, v)) = a.next_entry::<crate::Key, TextRepr>()? {
            map.insert(k, v.into());
        }
        Ok(map)
    }
}

struct Map(crate::Map);

impl<'de> serde::Deserialize<'de> for Map {
    fn deserialize<D>(d: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        Ok(Map(d.deserialize_map(MapVisitor)?))
    }
}

struct ArrayVisitor;

impl<'de> serde::de::Visitor<'de> for ArrayVisitor {
    type Value = Vec<Value>;

    fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("array")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
    where
        A: serde::de::SeqAccess<'de>,
    {
        let mut vec = Vec::new();
        if let Some(len) = a.size_hint() {
            vec.reserve(len);
        }
        while let Some(v) = a.next_element::<TextRepr>()? {
            vec.push(v.into());
        }
        Ok(vec)
    }
}

struct Array(Vec<Value>);

impl<'de> serde::Deserialize<'de> for Array {
    fn deserialize<D>(d: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        Ok(Array(d.deserialize_seq(ArrayVisitor)?))
    }
}

fn number_from_str<'de, A, T>(a: A) -> Result<T, A::Error>
where
    A: VariantAccess<'de>,
    T: std::str::FromStr,
{
    let s = a.newtype_variant::<Cow<'_, str>>()?;
    s.parse::<T>()
        .map_err(|_| serde::de::Error::custom(format!("invalid number: {s}")))
}

fn b58_str_32<'de, A>(a: A) -> Result<[u8; 32], A::Error>
where
    A: VariantAccess<'de>,
{
    let s = a.newtype_variant::<Cow<'_, str>>()?;
    let mut data = [0u8; 32];
    five8::decode_32(s.as_bytes(), &mut data)
        .map_err(|_| serde::de::Error::custom("invalid base58"))?;
    Ok(data)
}

fn b58_str_64<'de, A>(a: A) -> Result<[u8; 64], A::Error>
where
    A: VariantAccess<'de>,
{
    let s = a.newtype_variant::<Cow<'_, str>>()?;
    let mut data = [0u8; 64];
    five8::decode_64(s.as_bytes(), &mut data)
        .map_err(|_| serde::de::Error::custom("invalid base58"))?;
    Ok(data)
}

fn b64_str<'de, A>(a: A) -> Result<bytes::Bytes, A::Error>
where
    A: VariantAccess<'de>,
{
    let s = a.newtype_variant::<Cow<'_, str>>()?;
    BASE64_STANDARD
        .decode(s.as_bytes())
        .map_err(|_| serde::de::Error::custom("invalid base64"))
        .map(Into::into)
}

impl<'de> serde::Deserialize<'de> for TextRepr {
    fn deserialize<D>(d: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let value = d.deserialize_enum(crate::TOKEN, crate::value_type::keys::ALL, EnumVisitor)?;
        Ok(TextRepr(value))
    }
}