cardano_serialization_lib/serialization/plutus/
plutus_data.rs

1use crate::*;
2use std::io::SeekFrom;
3use crate::serialization::utils::{is_break_tag, skip_set_tag};
4
5impl cbor_event::se::Serialize for ConstrPlutusData {
6    fn serialize<'se, W: Write>(
7        &self,
8        serializer: &'se mut Serializer<W>,
9    ) -> cbor_event::Result<&'se mut Serializer<W>> {
10        if let Some(compact_tag) =
11            Self::alternative_to_compact_cbor_tag(self.alternative.into())
12        {
13            // compact form
14            serializer.write_tag(compact_tag as u64)?;
15            self.data.serialize(serializer)
16        } else {
17            // general form
18            serializer.write_tag(Self::GENERAL_FORM_TAG)?;
19            serializer.write_array(cbor_event::Len::Len(2))?;
20            self.alternative.serialize(serializer)?;
21            self.data.serialize(serializer)
22        }
23    }
24}
25
26impl Deserialize for ConstrPlutusData {
27    fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
28        (|| -> Result<_, DeserializeError> {
29            let (alternative, data) = match raw.tag()? {
30                // general form
31                Self::GENERAL_FORM_TAG => {
32                    let len = raw.array()?;
33                    let mut read_len = CBORReadLen::new(len);
34                    read_len.read_elems(2)?;
35                    let alternative = BigNum::deserialize(raw)?;
36                    let data =
37                        (|| -> Result<_, DeserializeError> { Ok(PlutusList::deserialize(raw)?) })()
38                            .map_err(|e| e.annotate("datas"))?;
39                    match len {
40                        cbor_event::Len::Len(_) => (),
41                        cbor_event::Len::Indefinite => match raw.special()? {
42                            CBORSpecial::Break => (),
43                            _ => return Err(DeserializeFailure::EndingBreakMissing.into()),
44                        },
45                    }
46                    (alternative, data)
47                }
48                // concise form
49                tag => {
50                    if let Some(alternative) = Self::compact_cbor_tag_to_alternative(tag) {
51                        (alternative.into(), PlutusList::deserialize(raw)?)
52                    } else {
53                        return Err(DeserializeFailure::TagMismatch {
54                            found: tag,
55                            expected: Self::GENERAL_FORM_TAG,
56                        }
57                            .into());
58                    }
59                }
60            };
61            Ok(ConstrPlutusData { alternative, data })
62        })()
63            .map_err(|e| e.annotate("ConstrPlutusData"))
64    }
65}
66
67impl cbor_event::se::Serialize for PlutusMap {
68    fn serialize<'se, W: Write>(
69        &self,
70        serializer: &'se mut Serializer<W>,
71    ) -> cbor_event::Result<&'se mut Serializer<W>> {
72        serializer.write_map(cbor_event::Len::Len(self.total_len() as u64))?;
73        for (key, values) in &self.0 {
74            for value in &values.elems {
75                key.serialize(serializer)?;
76                value.serialize(serializer)?;
77            }
78        }
79        Ok(serializer)
80    }
81}
82
83impl Deserialize for PlutusMap {
84    fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
85        let mut plutus_map = PlutusMap::new();
86        (|| -> Result<_, DeserializeError> {
87            let len = raw.map()?;
88            let mut total = 0;
89            while match len {
90                cbor_event::Len::Len(n) => total < n as usize,
91                cbor_event::Len::Indefinite => true,
92            } {
93                if is_break_tag(raw, "PlutusMap")? {
94                    break;
95                }
96                let key = PlutusData::deserialize(raw)?;
97                let value = PlutusData::deserialize(raw)?;
98                plutus_map.add_value_move(key, value);
99                total += 1;
100            }
101            Ok(())
102        })()
103            .map_err(|e| e.annotate("PlutusMap"))?;
104        Ok(plutus_map)
105    }
106}
107
108impl cbor_event::se::Serialize for PlutusDataEnum {
109    fn serialize<'se, W: Write>(
110        &self,
111        serializer: &'se mut Serializer<W>,
112    ) -> cbor_event::Result<&'se mut Serializer<W>> {
113        match self {
114            PlutusDataEnum::ConstrPlutusData(x) => x.serialize(serializer),
115            PlutusDataEnum::Map(x) => x.serialize(serializer),
116            PlutusDataEnum::List(x) => x.serialize(serializer),
117            PlutusDataEnum::Integer(x) => x.serialize(serializer),
118            PlutusDataEnum::Bytes(x) => write_bounded_bytes(serializer, &x),
119        }
120    }
121}
122
123impl Deserialize for PlutusDataEnum {
124    fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
125        (|| -> Result<_, DeserializeError> {
126            let initial_position = raw.as_mut_ref().seek(SeekFrom::Current(0)).unwrap();
127            match (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
128                Ok(ConstrPlutusData::deserialize(raw)?)
129            })(raw)
130            {
131                Ok(variant) => return Ok(PlutusDataEnum::ConstrPlutusData(variant)),
132                Err(_) => raw
133                    .as_mut_ref()
134                    .seek(SeekFrom::Start(initial_position))
135                    .unwrap(),
136            };
137            match (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
138                Ok(PlutusMap::deserialize(raw)?)
139            })(raw)
140            {
141                Ok(variant) => return Ok(PlutusDataEnum::Map(variant)),
142                Err(_) => raw
143                    .as_mut_ref()
144                    .seek(SeekFrom::Start(initial_position))
145                    .unwrap(),
146            };
147            match (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
148                Ok(PlutusList::deserialize(raw)?)
149            })(raw)
150            {
151                Ok(variant) => return Ok(PlutusDataEnum::List(variant)),
152                Err(_) => raw
153                    .as_mut_ref()
154                    .seek(SeekFrom::Start(initial_position))
155                    .unwrap(),
156            };
157            match (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
158                Ok(BigInt::deserialize(raw)?)
159            })(raw)
160            {
161                Ok(variant) => return Ok(PlutusDataEnum::Integer(variant)),
162                Err(_) => raw
163                    .as_mut_ref()
164                    .seek(SeekFrom::Start(initial_position))
165                    .unwrap(),
166            };
167            match (|raw: &mut Deserializer<_>| -> Result<_, DeserializeError> {
168                Ok(read_bounded_bytes(raw)?)
169            })(raw)
170            {
171                Ok(variant) => return Ok(PlutusDataEnum::Bytes(variant)),
172                Err(_) => raw
173                    .as_mut_ref()
174                    .seek(SeekFrom::Start(initial_position))
175                    .unwrap(),
176            };
177            Err(DeserializeError::new(
178                "PlutusDataEnum",
179                DeserializeFailure::NoVariantMatched.into(),
180            ))
181        })()
182            .map_err(|e| e.annotate("PlutusDataEnum"))
183    }
184}
185
186impl cbor_event::se::Serialize for PlutusData {
187    fn serialize<'se, W: Write>(
188        &self,
189        serializer: &'se mut Serializer<W>,
190    ) -> cbor_event::Result<&'se mut Serializer<W>> {
191        match &self.original_bytes {
192            Some(bytes) => serializer.write_raw_bytes(bytes),
193            None => self.datum.serialize(serializer),
194        }
195    }
196}
197
198impl Deserialize for PlutusData {
199    fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
200        // these unwraps are fine since we're seeking the current position
201        let before = raw.as_mut_ref().seek(SeekFrom::Current(0)).unwrap();
202        let datum = PlutusDataEnum::deserialize(raw)?;
203        let after = raw.as_mut_ref().seek(SeekFrom::Current(0)).unwrap();
204        let bytes_read = (after - before) as usize;
205        raw.as_mut_ref().seek(SeekFrom::Start(before)).unwrap();
206        // these unwraps are fine since we read the above already
207        let original_bytes = raw.as_mut_ref().fill_buf().unwrap()[..bytes_read].to_vec();
208        raw.as_mut_ref().consume(bytes_read);
209        Ok(Self {
210            datum,
211            original_bytes: Some(original_bytes),
212        })
213    }
214}
215
216impl cbor_event::se::Serialize for PlutusList {
217    fn serialize<'se, W: Write>(
218        &self,
219        serializer: &'se mut Serializer<W>,
220    ) -> cbor_event::Result<&'se mut Serializer<W>> {
221        let use_definite_encoding = match self.definite_encoding {
222            Some(definite) => definite,
223            None => self.elems.is_empty(),
224        };
225        if use_definite_encoding {
226            serializer.write_array(cbor_event::Len::Len(self.elems.len() as u64))?;
227        } else {
228            serializer.write_array(cbor_event::Len::Indefinite)?;
229        }
230        for element in &self.elems {
231            element.serialize(serializer)?;
232        }
233        if !use_definite_encoding {
234            serializer.write_special(cbor_event::Special::Break)?;
235        }
236        Ok(serializer)
237    }
238}
239
240impl PlutusList {
241    pub(crate) fn serialize_as_set<'se, W: Write>(
242        &self,
243        need_deduplication: bool,
244        serializer: &'se mut Serializer<W>,
245    ) -> cbor_event::Result<&'se mut Serializer<W>> {
246        serializer.write_tag(258)?;
247        let use_definite_encoding = match self.definite_encoding {
248            Some(definite) => definite,
249            None => self.elems.is_empty(),
250        };
251        if use_definite_encoding {
252            serializer.write_array(cbor_event::Len::Len(self.elems.len() as u64))?;
253        } else {
254            serializer.write_array(cbor_event::Len::Indefinite)?;
255        }
256        if need_deduplication {
257            for element in self.deduplicated_view() {
258                element.serialize(serializer)?;
259            }
260        } else {
261            for element in &self.elems {
262                element.serialize(serializer)?;
263            }
264        }
265        if !use_definite_encoding {
266            serializer.write_special(cbor_event::Special::Break)?;
267        }
268        Ok(serializer)
269    }
270}
271
272impl Deserialize for PlutusList {
273    fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
274        let has_set_tag = skip_set_tag(raw)?;
275        let mut arr = Vec::new();
276        let len = (|| -> Result<_, DeserializeError> {
277            let len = raw.array()?;
278            while match len {
279                cbor_event::Len::Len(n) => arr.len() < n as usize,
280                cbor_event::Len::Indefinite => true,
281            } {
282                if is_break_tag(raw, "PlutusList")? {
283                    break;
284                }
285                arr.push(PlutusData::deserialize(raw)?);
286            }
287            Ok(len)
288        })()
289            .map_err(|e| e.annotate("PlutusList"))?;
290
291        let set_tag = if has_set_tag {
292            Some(CborSetType::Tagged)
293        } else {
294            Some(CborSetType::Untagged)
295        };
296
297        Ok(Self {
298            elems: arr,
299            definite_encoding: Some(len != cbor_event::Len::Indefinite),
300            cbor_set_type: set_tag
301        })
302    }
303}