1use std::{
2 collections::{BTreeMap, HashMap},
3 hash::Hash,
4};
5
6use indexmap::IndexMap;
7
8use crate::{
9 AsPlutus, BigInt, BoundedBytes, DecodeError, PlutusData, create_array, create_constr,
10 create_map, parse_constr, parse_map, parse_tuple, parse_variant, type_name,
11};
12
13impl AsPlutus for PlutusData {
14 fn from_plutus(data: PlutusData) -> Result<Self, DecodeError> {
15 Ok(data)
16 }
17
18 fn to_plutus(self) -> PlutusData {
19 self
20 }
21}
22
23impl AsPlutus for BigInt {
24 fn from_plutus(data: PlutusData) -> Result<Self, DecodeError> {
25 let PlutusData::BigInt(int) = data else {
26 return Err(DecodeError::UnexpectedType {
27 expected: "BigInt".to_string(),
28 actual: type_name(&data),
29 });
30 };
31 Ok(int)
32 }
33
34 fn to_plutus(self) -> PlutusData {
35 PlutusData::BigInt(self)
36 }
37}
38
39impl AsPlutus for BoundedBytes {
40 fn from_plutus(data: PlutusData) -> Result<Self, DecodeError> {
41 let PlutusData::BoundedBytes(bytes) = data else {
42 return Err(DecodeError::UnexpectedType {
43 expected: "BoundedBytes".to_string(),
44 actual: type_name(&data),
45 });
46 };
47 Ok(bytes)
48 }
49
50 fn to_plutus(self) -> PlutusData {
51 PlutusData::BoundedBytes(self)
52 }
53}
54
55impl AsPlutus for bool {
56 fn from_plutus(data: PlutusData) -> Result<Self, DecodeError> {
57 let (variant, fields) = parse_constr(data)?;
58 if variant == 0 {
59 let [] = parse_variant(variant, fields)?;
60 return Ok(false);
61 }
62 if variant == 1 {
63 let [] = parse_variant(variant, fields)?;
64 return Ok(true);
65 }
66 Err(DecodeError::UnexpectedVariant { variant })
67 }
68
69 fn to_plutus(self) -> PlutusData {
70 match self {
71 false => create_constr(0, vec![]),
72 true => create_constr(1, vec![]),
73 }
74 }
75}
76
77macro_rules! impl_number {
78 () => {
79 fn from_plutus(data: PlutusData) -> Result<Self, DecodeError> {
80 let PlutusData::BigInt(BigInt::Int(value)) = data else {
81 return Err(DecodeError::UnexpectedType {
82 expected: "BigInt".into(),
83 actual: type_name(&data),
84 });
85 };
86 let value: i128 = value.into();
87 Ok(value as _)
88 }
89
90 fn to_plutus(self) -> PlutusData {
91 let val = self as i128;
92 PlutusData::BigInt(BigInt::Int(val.try_into().unwrap()))
93 }
94 };
95}
96
97impl AsPlutus for u8 {
98 impl_number!();
99
100 fn vec_from_plutus(data: PlutusData) -> Result<Vec<Self>, DecodeError> {
102 let bytes = BoundedBytes::from_plutus(data)?;
103 Ok(bytes.to_vec())
104 }
105
106 fn vec_to_plutus(value: Vec<Self>) -> PlutusData {
107 let bytes = BoundedBytes::from(value);
108 PlutusData::BoundedBytes(bytes)
109 }
110}
111impl AsPlutus for u16 {
112 impl_number!();
113}
114impl AsPlutus for u32 {
115 impl_number!();
116}
117impl AsPlutus for u64 {
118 impl_number!();
119}
120impl AsPlutus for i8 {
121 impl_number!();
122}
123impl AsPlutus for i16 {
124 impl_number!();
125}
126impl AsPlutus for i32 {
127 impl_number!();
128}
129impl AsPlutus for i64 {
130 impl_number!();
131}
132
133macro_rules! impl_tuple {
134 ($($param:ident),*) => {
135 impl<$($param),*> AsPlutus for ($($param),*)
136 where
137 $($param: AsPlutus),*
138 {
139 #[allow(non_snake_case)]
140 fn from_plutus(data: PlutusData) -> Result<Self, DecodeError> {
141 let [$($param),*] = parse_tuple(data)?;
142 Ok(($(AsPlutus::from_plutus($param)?),*))
143 }
144
145 #[allow(non_snake_case)]
146 fn to_plutus(self) -> PlutusData {
147 let ($($param),*) = self;
148 create_array(vec![$($param.to_plutus()),*])
149 }
150 }
151 };
152}
153
154impl_tuple!(T1, T2);
155impl_tuple!(T1, T2, T3);
156impl_tuple!(T1, T2, T3, T4);
157impl_tuple!(T1, T2, T3, T4, T5);
158impl_tuple!(T1, T2, T3, T4, T5, T6);
159impl_tuple!(T1, T2, T3, T4, T5, T6, T7);
160impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);
161
162impl AsPlutus for String {
163 fn from_plutus(data: PlutusData) -> Result<Self, DecodeError> {
164 let bytes = BoundedBytes::from_plutus(data)?;
165 String::from_utf8(bytes.to_vec())
166 .map_err(|err| DecodeError::Custom(format!("error decoding string: {err}")))
167 }
168
169 fn to_plutus(self) -> PlutusData {
170 let bytes = BoundedBytes::from(self.into_bytes());
171 bytes.to_plutus()
172 }
173}
174
175impl<T: AsPlutus> AsPlutus for Option<T> {
176 fn from_plutus(data: PlutusData) -> Result<Self, DecodeError> {
177 let (variant, fields) = parse_constr(data)?;
178 if variant == 0 {
179 let [value] = parse_variant(variant, fields)?;
180 return Ok(Some(T::from_plutus(value)?));
181 }
182 if variant == 1 {
183 let [] = parse_variant(variant, fields)?;
184 return Ok(None);
185 }
186 Err(DecodeError::UnexpectedVariant { variant })
187 }
188
189 fn to_plutus(self) -> PlutusData {
190 match self {
191 Some(value) => create_constr(0, vec![value.to_plutus()]),
192 None => create_constr(1, vec![]),
193 }
194 }
195}
196
197impl<T: AsPlutus> AsPlutus for Vec<T> {
198 fn from_plutus(data: PlutusData) -> Result<Self, DecodeError> {
199 T::vec_from_plutus(data)
200 }
201
202 fn to_plutus(self) -> PlutusData {
203 T::vec_to_plutus(self)
204 }
205}
206
207macro_rules! impl_map {
208 () => {
209 fn from_plutus(data: PlutusData) -> Result<Self, DecodeError> {
210 let mut map = Self::new();
211 for (key, value) in parse_map(data)? {
212 map.insert(TKey::from_plutus(key)?, TVal::from_plutus(value)?);
213 }
214 Ok(map)
215 }
216
217 fn to_plutus(self) -> PlutusData {
218 let kvps = self
219 .into_iter()
220 .map(|(k, v)| (k.to_plutus(), v.to_plutus()))
221 .collect();
222 create_map(kvps)
223 }
224 };
225}
226
227impl<TKey: AsPlutus + Hash + Eq, TVal: AsPlutus> AsPlutus for IndexMap<TKey, TVal> {
228 impl_map!();
229}
230
231impl<TKey: AsPlutus + Hash + Eq, TVal: AsPlutus> AsPlutus for HashMap<TKey, TVal> {
232 impl_map!();
233}
234
235impl<TKey: AsPlutus + PartialOrd + Ord, TVal: AsPlutus> AsPlutus for BTreeMap<TKey, TVal> {
236 impl_map!();
237}