Skip to main content

kimchi/circuits/
serialization_helper.rs

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