Skip to main content

miden_protocol/account/component/storage/toml/
serde_impls.rs

1use alloc::string::{String, ToString};
2
3use serde::de::Error as _;
4use serde::ser::{Error as SerError, SerializeStruct};
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6
7use super::super::type_registry::SCHEMA_TYPE_REGISTRY;
8use super::super::{FeltSchema, SchemaType, WordValue};
9
10// FELT SCHEMA SERIALIZATION
11// ================================================================================================
12
13impl Serialize for FeltSchema {
14    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
15    where
16        S: Serializer,
17    {
18        if self.felt_type() == SchemaType::void() {
19            let mut state = serializer.serialize_struct("FeltSchema", 2)?;
20            state.serialize_field("type", &SchemaType::void())?;
21            if let Some(description) = self.description() {
22                state.serialize_field("description", description)?;
23            }
24            return state.end();
25        }
26
27        let name = self.name().ok_or_else(|| {
28            SerError::custom("invalid FeltSchema: non-void elements must have a name")
29        })?;
30
31        let mut state = serializer.serialize_struct("FeltSchema", 4)?;
32        state.serialize_field("name", name)?;
33        if let Some(description) = self.description() {
34            state.serialize_field("description", description)?;
35        }
36        if self.felt_type() != SchemaType::native_felt() {
37            state.serialize_field("type", &self.felt_type())?;
38        }
39        if let Some(default_value) = self.default_value() {
40            state.serialize_field(
41                "default-value",
42                &SCHEMA_TYPE_REGISTRY.display_felt(&self.felt_type(), default_value),
43            )?;
44        }
45        state.end()
46    }
47}
48
49impl<'de> Deserialize<'de> for FeltSchema {
50    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
51    where
52        D: Deserializer<'de>,
53    {
54        #[derive(Deserialize)]
55        #[serde(rename_all = "kebab-case", deny_unknown_fields)]
56        struct RawFeltSchema {
57            #[serde(default)]
58            name: Option<String>,
59            #[serde(default)]
60            description: Option<String>,
61            #[serde(default, rename = "default-value")]
62            default_value: Option<String>,
63            #[serde(default, rename = "type")]
64            r#type: Option<SchemaType>,
65        }
66
67        let raw = RawFeltSchema::deserialize(deserializer)?;
68
69        let felt_type = raw.r#type.unwrap_or_else(SchemaType::native_felt);
70
71        let description = raw.description.filter(|description| !description.trim().is_empty());
72
73        if felt_type == SchemaType::void() {
74            if raw.name.is_some() {
75                return Err(D::Error::custom("`type = \"void\"` elements must omit `name`"));
76            }
77            if raw.default_value.is_some() {
78                return Err(D::Error::custom(
79                    "`type = \"void\"` elements cannot define `default-value`",
80                ));
81            }
82
83            let schema = FeltSchema::new_void();
84            return Ok(match description {
85                Some(description) => schema.with_description(description),
86                None => schema,
87            });
88        }
89
90        let Some(name) = raw.name else {
91            return Err(D::Error::custom("non-void elements must define `name`"));
92        };
93
94        let default_value = raw
95            .default_value
96            .map(|default_value| {
97                SCHEMA_TYPE_REGISTRY.try_parse_felt(&felt_type, &default_value).map_err(|err| {
98                    D::Error::custom(format!(
99                        "failed to parse {felt_type} as Felt for `default-value`: {err}"
100                    ))
101                })
102            })
103            .transpose()?;
104
105        let mut schema = FeltSchema::new_typed(felt_type, name);
106        if let Some(default_value) = default_value {
107            schema = schema.with_default(default_value);
108        }
109        Ok(match description {
110            Some(description) => schema.with_description(description),
111            None => schema,
112        })
113    }
114}
115
116// WORD VALUE SERIALIZATION
117// ================================================================================================
118
119impl Serialize for WordValue {
120    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
121    where
122        S: Serializer,
123    {
124        match self {
125            WordValue::Atomic(value) => serializer.serialize_str(value),
126            WordValue::Elements(elements) => elements.serialize(serializer),
127            WordValue::FullyTyped(word) => serializer.serialize_str(&word.to_string()),
128        }
129    }
130}
131
132impl<'de> Deserialize<'de> for WordValue {
133    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
134    where
135        D: Deserializer<'de>,
136    {
137        #[derive(Deserialize)]
138        #[serde(untagged)]
139        enum RawWordValue {
140            Atomic(String),
141            Elements([String; 4]),
142        }
143
144        match RawWordValue::deserialize(deserializer)? {
145            RawWordValue::Atomic(value) => Ok(WordValue::Atomic(value)),
146            RawWordValue::Elements(elements) => Ok(WordValue::Elements(elements)),
147        }
148    }
149}