Skip to main content

icydb_core/value/
wire.rs

1//! Module: value::wire
2//! Defines serde-only decode helpers that rebuild public runtime value wrappers
3//! from the stable `Value` enum wire shape.
4
5use crate::value::{VALUE_WIRE_TYPE_NAME, VALUE_WIRE_VARIANT_LABELS, Value, ValueWireVariant};
6
7use serde::{
8    Deserialize, Deserializer,
9    de::{self, EnumAccess, VariantAccess, Visitor},
10};
11use serde_bytes::ByteBuf;
12use std::{fmt, marker::PhantomData};
13
14///
15/// ValueWireVisitor
16///
17/// ValueWireVisitor decodes the stable externally tagged `Value` wire shape
18/// directly through serde enum access and re-applies runtime map invariants.
19///
20
21struct ValueWireVisitor(PhantomData<()>);
22
23impl ValueWireVisitor {
24    fn decode_map_entries<E>(entries: Vec<(Value, Value)>) -> Result<Value, E>
25    where
26        E: de::Error,
27    {
28        Value::from_map(entries).map_err(E::custom)
29    }
30}
31
32impl<'de> Visitor<'de> for ValueWireVisitor {
33    type Value = Value;
34
35    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
36        formatter.write_str("the stable Value enum wire shape")
37    }
38
39    fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
40    where
41        A: EnumAccess<'de>,
42    {
43        let (variant, payload) = data.variant::<String>()?;
44
45        let Some(variant_tag) = ValueWireVariant::from_label(variant.as_str()) else {
46            return Err(de::Error::unknown_variant(
47                variant.as_str(),
48                VALUE_WIRE_VARIANT_LABELS,
49            ));
50        };
51
52        match variant_tag {
53            ValueWireVariant::Account => Ok(Value::Account(payload.newtype_variant()?)),
54            ValueWireVariant::Blob => Ok(Value::Blob(
55                payload.newtype_variant::<ByteBuf>()?.into_vec(),
56            )),
57            ValueWireVariant::Bool => Ok(Value::Bool(payload.newtype_variant()?)),
58            ValueWireVariant::Date => Ok(Value::Date(payload.newtype_variant()?)),
59            ValueWireVariant::Decimal => Ok(Value::Decimal(payload.newtype_variant()?)),
60            ValueWireVariant::Duration => Ok(Value::Duration(payload.newtype_variant()?)),
61            ValueWireVariant::Enum => Ok(Value::Enum(payload.newtype_variant()?)),
62            ValueWireVariant::Float32 => Ok(Value::Float32(payload.newtype_variant()?)),
63            ValueWireVariant::Float64 => Ok(Value::Float64(payload.newtype_variant()?)),
64            ValueWireVariant::Int64 => Ok(Value::Int64(payload.newtype_variant()?)),
65            ValueWireVariant::Int128 => Ok(Value::Int128(payload.newtype_variant()?)),
66            ValueWireVariant::List => Ok(Value::List(payload.newtype_variant()?)),
67            ValueWireVariant::Map => {
68                let entries = payload.newtype_variant::<Vec<(Value, Value)>>()?;
69                Self::decode_map_entries(entries)
70            }
71            ValueWireVariant::Null => {
72                payload.unit_variant()?;
73                Ok(Value::Null)
74            }
75            ValueWireVariant::Principal => Ok(Value::Principal(payload.newtype_variant()?)),
76            ValueWireVariant::Subaccount => Ok(Value::Subaccount(payload.newtype_variant()?)),
77            ValueWireVariant::Text => Ok(Value::Text(payload.newtype_variant()?)),
78            ValueWireVariant::Timestamp => Ok(Value::Timestamp(payload.newtype_variant()?)),
79            ValueWireVariant::Nat64 => Ok(Value::Nat64(payload.newtype_variant()?)),
80            ValueWireVariant::Nat128 => Ok(Value::Nat128(payload.newtype_variant()?)),
81            ValueWireVariant::Ulid => Ok(Value::Ulid(payload.newtype_variant()?)),
82            ValueWireVariant::Unit => {
83                payload.unit_variant()?;
84                Ok(Value::Unit)
85            }
86            ValueWireVariant::U256 => Ok(Value::U256(payload.newtype_variant()?)),
87        }
88    }
89}
90
91impl<'de> Deserialize<'de> for Value {
92    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
93    where
94        D: Deserializer<'de>,
95    {
96        deserializer.deserialize_enum(
97            VALUE_WIRE_TYPE_NAME,
98            VALUE_WIRE_VARIANT_LABELS,
99            ValueWireVisitor(PhantomData),
100        )
101    }
102}