1use crate::KeyValuePairs;
2use pallas_codec::utils::Int;
3use pallas_codec::{
4 minicbor::{
5 self,
6 data::{IanaTag, Tag},
7 Encode,
8 },
9 utils::MaybeIndefArray,
10};
11use serde::{Deserialize, Serialize};
12use std::{fmt, ops::Deref};
13
14#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
15pub enum PlutusData {
16 Constr(Constr<PlutusData>),
17 Map(KeyValuePairs<PlutusData, PlutusData>),
18 BigInt(BigInt),
19 BoundedBytes(BoundedBytes),
20 Array(MaybeIndefArray<PlutusData>),
21}
22
23impl<'b, C> minicbor::decode::Decode<'b, C> for PlutusData {
24 fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
25 let type_ = d.datatype()?;
26
27 match type_ {
28 minicbor::data::Type::Tag => {
29 let mut probe = d.probe();
30 let tag = probe.tag()?;
31
32 if tag == IanaTag::PosBignum.tag() || tag == IanaTag::NegBignum.tag() {
33 Ok(Self::BigInt(d.decode_with(ctx)?))
34 } else {
35 match tag.as_u64() {
36 (121..=127) | (1280..=1400) | 102 => Ok(Self::Constr(d.decode_with(ctx)?)),
37 _ => Err(minicbor::decode::Error::message(
38 "unknown tag for plutus data tag",
39 )),
40 }
41 }
42 }
43 minicbor::data::Type::U8
44 | minicbor::data::Type::U16
45 | minicbor::data::Type::U32
46 | minicbor::data::Type::U64
47 | minicbor::data::Type::I8
48 | minicbor::data::Type::I16
49 | minicbor::data::Type::I32
50 | minicbor::data::Type::I64
51 | minicbor::data::Type::Int => Ok(Self::BigInt(d.decode_with(ctx)?)),
52 minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
53 Ok(Self::Map(d.decode_with(ctx)?))
54 }
55 minicbor::data::Type::Bytes => Ok(Self::BoundedBytes(d.decode_with(ctx)?)),
56 minicbor::data::Type::BytesIndef => {
57 let mut full = Vec::new();
58
59 for slice in d.bytes_iter()? {
60 full.extend(slice?);
61 }
62
63 Ok(Self::BoundedBytes(BoundedBytes::from(full)))
64 }
65 minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
66 Ok(Self::Array(d.decode_with(ctx)?))
67 }
68
69 any => Err(minicbor::decode::Error::message(format!(
70 "bad cbor data type ({any:?}) for plutus data"
71 ))),
72 }
73 }
74}
75
76impl<C> minicbor::encode::Encode<C> for PlutusData {
77 fn encode<W: minicbor::encode::Write>(
78 &self,
79 e: &mut minicbor::Encoder<W>,
80 ctx: &mut C,
81 ) -> Result<(), minicbor::encode::Error<W::Error>> {
82 match self {
83 Self::Constr(a) => {
84 e.encode_with(a, ctx)?;
85 }
86 Self::Map(a) => {
87 e.map(a.len().try_into().unwrap())?;
90 for (k, v) in a.iter() {
91 k.encode(e, ctx)?;
92 v.encode(e, ctx)?;
93 }
94 }
95 Self::BigInt(a) => {
96 e.encode_with(a, ctx)?;
97 }
98 Self::BoundedBytes(a) => {
99 e.encode_with(a, ctx)?;
100 }
101 Self::Array(a) => {
102 e.encode_with(a, ctx)?;
103 }
104 };
105
106 Ok(())
107 }
108}
109
110#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
117pub enum BigInt {
118 Int(Int),
119 BigUInt(BoundedBytes),
120 BigNInt(BoundedBytes),
121}
122
123impl<'b, C> minicbor::decode::Decode<'b, C> for BigInt {
124 fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
125 let datatype = d.datatype()?;
126
127 match datatype {
128 minicbor::data::Type::U8
129 | minicbor::data::Type::U16
130 | minicbor::data::Type::U32
131 | minicbor::data::Type::U64
132 | minicbor::data::Type::I8
133 | minicbor::data::Type::I16
134 | minicbor::data::Type::I32
135 | minicbor::data::Type::I64
136 | minicbor::data::Type::Int => Ok(Self::Int(d.decode_with(ctx)?)),
137 minicbor::data::Type::Tag => {
138 let tag = d.tag()?;
139 if tag == IanaTag::PosBignum.tag() {
140 Ok(Self::BigUInt(d.decode_with(ctx)?))
141 } else if tag == IanaTag::NegBignum.tag() {
142 Ok(Self::BigNInt(d.decode_with(ctx)?))
143 } else {
144 Err(minicbor::decode::Error::message(
145 "invalid cbor tag for big int",
146 ))
147 }
148 }
149 _ => Err(minicbor::decode::Error::message(
150 "invalid cbor data type for big int",
151 )),
152 }
153 }
154}
155
156impl<C> minicbor::encode::Encode<C> for BigInt {
157 fn encode<W: minicbor::encode::Write>(
158 &self,
159 e: &mut minicbor::Encoder<W>,
160 ctx: &mut C,
161 ) -> Result<(), minicbor::encode::Error<W::Error>> {
162 match self {
163 BigInt::Int(x) => {
164 e.encode_with(x, ctx)?;
165 }
166 BigInt::BigUInt(x) => {
167 e.tag(IanaTag::PosBignum)?;
168 e.encode_with(x, ctx)?;
169 }
170 BigInt::BigNInt(x) => {
171 e.tag(IanaTag::NegBignum)?;
172 e.encode_with(x, ctx)?;
173 }
174 };
175
176 Ok(())
177 }
178}
179
180#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
181pub struct Constr<A> {
182 pub tag: u64,
183 pub any_constructor: Option<u64>,
184 pub fields: MaybeIndefArray<A>,
185}
186
187impl<'b, C, A> minicbor::decode::Decode<'b, C> for Constr<A>
188where
189 A: minicbor::decode::Decode<'b, C>,
190{
191 fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
192 let tag = d.tag()?;
193 let x = tag.as_u64();
194 match x {
195 121..=127 | 1280..=1400 => Ok(Constr {
196 tag: x,
197 fields: d.decode_with(ctx)?,
198 any_constructor: None,
199 }),
200 102 => {
201 d.array()?;
202
203 Ok(Constr {
204 tag: x,
205 any_constructor: Some(d.decode_with(ctx)?),
206 fields: d.decode_with(ctx)?,
207 })
208 }
209 _ => Err(minicbor::decode::Error::message(
210 "bad tag code for plutus data",
211 )),
212 }
213 }
214}
215
216impl<C, A> minicbor::encode::Encode<C> for Constr<A>
217where
218 A: minicbor::encode::Encode<C>,
219{
220 fn encode<W: minicbor::encode::Write>(
221 &self,
222 e: &mut minicbor::Encoder<W>,
223 ctx: &mut C,
224 ) -> Result<(), minicbor::encode::Error<W::Error>> {
225 e.tag(Tag::new(self.tag))?;
226
227 match self.tag {
228 102 => {
229 let x = (self.any_constructor.unwrap_or_default(), &self.fields);
230 e.encode_with(x, ctx)?;
231 Ok(())
232 }
233 _ => {
234 e.encode_with(&self.fields, ctx)?;
235 Ok(())
236 }
237 }
238 }
239}
240
241#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
244#[serde(into = "String")]
245#[serde(try_from = "String")]
246pub struct BoundedBytes(Vec<u8>);
247
248impl From<Vec<u8>> for BoundedBytes {
249 fn from(xs: Vec<u8>) -> Self {
250 BoundedBytes(xs)
251 }
252}
253
254impl From<BoundedBytes> for Vec<u8> {
255 fn from(b: BoundedBytes) -> Self {
256 b.0
257 }
258}
259
260impl Deref for BoundedBytes {
261 type Target = Vec<u8>;
262
263 fn deref(&self) -> &Self::Target {
264 &self.0
265 }
266}
267
268impl TryFrom<String> for BoundedBytes {
269 type Error = hex::FromHexError;
270
271 fn try_from(value: String) -> Result<Self, Self::Error> {
272 let v = hex::decode(value)?;
273 Ok(BoundedBytes(v))
274 }
275}
276
277impl From<BoundedBytes> for String {
278 fn from(b: BoundedBytes) -> Self {
279 hex::encode(b.deref())
280 }
281}
282
283impl fmt::Display for BoundedBytes {
284 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285 let bytes: Vec<u8> = self.clone().into();
286
287 f.write_str(&hex::encode(bytes))
288 }
289}
290
291impl<C> Encode<C> for BoundedBytes {
292 fn encode<W: minicbor::encode::Write>(
293 &self,
294 e: &mut minicbor::Encoder<W>,
295 _: &mut C,
296 ) -> Result<(), minicbor::encode::Error<W::Error>> {
297 const CHUNK_SIZE: usize = 64;
300 let bs: &Vec<u8> = self.deref();
301 if bs.len() <= 64 {
302 e.bytes(bs)?;
303 } else {
304 e.begin_bytes()?;
305 for b in bs.chunks(CHUNK_SIZE) {
306 e.bytes(b)?;
307 }
308 e.end()?;
309 }
310 Ok(())
311 }
312}
313
314impl<'b, C> minicbor::decode::Decode<'b, C> for BoundedBytes {
315 fn decode(d: &mut minicbor::Decoder<'b>, _: &mut C) -> Result<Self, minicbor::decode::Error> {
316 let mut res = Vec::new();
317 for chunk in d.bytes_iter()? {
318 let bs = chunk?;
319 res.extend_from_slice(bs);
320 }
321 Ok(BoundedBytes::from(res))
322 }
323}