kimchi/circuits/
serialization_helper.rs

1use crate::circuits::lookup::lookups::{JointLookup, JointLookupValue};
2use serde::{
3    de::{Error, IgnoredAny, MapAccess, SeqAccess},
4    ser::SerializeStruct,
5    Deserialize, Deserializer, Serializer,
6};
7use serde_with::{de::DeserializeAsWrap, ser::SerializeAsWrap, DeserializeAs, SerializeAs};
8use std::{fmt::Formatter, marker::PhantomData};
9
10impl<F, G> SerializeAs<JointLookupValue<F>> for JointLookupValue<G>
11where
12    G: SerializeAs<F>,
13{
14    fn serialize_as<S>(source: &JointLookupValue<F>, serializer: S) -> Result<S::Ok, S::Error>
15    where
16        S: Serializer,
17    {
18        let mut s = serializer.serialize_struct("JointLookup", 2)?;
19        s.serialize_field("table_id", &SerializeAsWrap::<F, G>::new(&source.table_id))?;
20        s.serialize_field(
21            "entry",
22            &SerializeAsWrap::<Vec<F>, Vec<G>>::new(&source.entry),
23        )?;
24        s.end()
25    }
26}
27
28impl<'de, F, G: DeserializeAs<'de, F>> DeserializeAs<'de, JointLookupValue<F>>
29    for JointLookupValue<G>
30{
31    fn deserialize_as<D>(deserializer: D) -> Result<JointLookupValue<F>, D::Error>
32    where
33        D: Deserializer<'de>,
34    {
35        #[allow(non_camel_case_types)]
36        enum Field {
37            field0,
38            field1,
39            ignore,
40        }
41        struct FieldVisitor;
42        impl<'de> serde::de::Visitor<'de> for FieldVisitor {
43            type Value = Field;
44            fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result {
45                Formatter::write_str(formatter, "field identifier")
46            }
47            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
48            where
49                E: Error,
50            {
51                match value {
52                    0u64 => Ok(Field::field0),
53                    1u64 => Ok(Field::field1),
54                    _ => Ok(Field::ignore),
55                }
56            }
57            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
58            where
59                E: Error,
60            {
61                match value {
62                    "table_id" => Ok(Field::field0),
63                    "entry" => Ok(Field::field1),
64                    _ => Ok(Field::ignore),
65                }
66            }
67            fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
68            where
69                E: Error,
70            {
71                match value {
72                    b"table_id" => Ok(Field::field0),
73                    b"entry" => Ok(Field::field1),
74                    _ => Ok(Field::ignore),
75                }
76            }
77        }
78        impl<'de> Deserialize<'de> for Field {
79            #[inline]
80            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
81            where
82                D: Deserializer<'de>,
83            {
84                Deserializer::deserialize_identifier(deserializer, FieldVisitor)
85            }
86        }
87        struct Visitor<'de, F, G>
88        where
89            G: DeserializeAs<'de, F>,
90        {
91            marker: PhantomData<JointLookupValue<F>>,
92            marker2: PhantomData<JointLookupValue<G>>,
93            lifetime: PhantomData<&'de ()>,
94        }
95        impl<'de, F, G> serde::de::Visitor<'de> for Visitor<'de, F, G>
96        where
97            G: DeserializeAs<'de, F>,
98        {
99            type Value = JointLookupValue<F>;
100            fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result {
101                Formatter::write_str(formatter, "struct JointLookup")
102            }
103            #[inline]
104            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
105            where
106                A: SeqAccess<'de>,
107            {
108                let field0 = match SeqAccess::next_element::<DeserializeAsWrap<F, G>>(&mut seq)? {
109                    Some(value) => value.into_inner(),
110                    None => {
111                        return Err(Error::invalid_length(
112                            0usize,
113                            &"struct JointLookup with 2 elements",
114                        ));
115                    }
116                };
117                let field1 =
118                    match SeqAccess::next_element::<DeserializeAsWrap<Vec<F>, Vec<G>>>(&mut seq)? {
119                        Some(value) => value.into_inner(),
120                        None => {
121                            return Err(Error::invalid_length(
122                                1usize,
123                                &"struct JointLookup with 2 elements",
124                            ));
125                        }
126                    };
127                Ok(JointLookup {
128                    table_id: field0,
129                    entry: field1,
130                })
131            }
132            #[inline]
133            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
134            where
135                A: MapAccess<'de>,
136            {
137                let mut field0: Option<F> = None;
138                let mut field1: Option<Vec<F>> = None;
139                while let Some(key) = MapAccess::next_key::<Field>(&mut map)? {
140                    match key {
141                        Field::field0 => {
142                            if Option::is_some(&field0) {
143                                return Err(A::Error::duplicate_field("table_id"));
144                            }
145                            field0 = Some(
146                                MapAccess::next_value::<DeserializeAsWrap<F, G>>(&mut map)?
147                                    .into_inner(),
148                            );
149                        }
150                        Field::field1 => {
151                            if Option::is_some(&field1) {
152                                return Err(A::Error::duplicate_field("entry"));
153                            }
154                            field1 = Some(
155                                MapAccess::next_value::<DeserializeAsWrap<Vec<F>, Vec<G>>>(
156                                    &mut map,
157                                )?
158                                .into_inner(),
159                            );
160                        }
161                        Field::ignore => {
162                            let _ = MapAccess::next_value::<IgnoredAny>(&mut map)?;
163                        }
164                    }
165                }
166                let field0 = match field0 {
167                    Some(field0) => field0,
168                    None => return Err(A::Error::missing_field("table_id")),
169                };
170                let field1 = match field1 {
171                    Some(field1) => field1,
172                    None => return Err(A::Error::missing_field("entry")),
173                };
174                Ok(JointLookup {
175                    table_id: field0,
176                    entry: field1,
177                })
178            }
179        }
180        const FIELDS: &[&str] = &["table_id", "entry"];
181        Deserializer::deserialize_struct(
182            deserializer,
183            "JointLookup",
184            FIELDS,
185            Visitor {
186                marker: PhantomData::<JointLookupValue<F>>,
187                marker2: PhantomData::<JointLookupValue<G>>,
188                lifetime: PhantomData,
189            },
190        )
191    }
192}