whisky_common/data/
mod.rs1mod aliases;
2pub mod blueprint; mod credentials;
4mod primitives;
5mod value;
6use std::fmt::Debug;
7
8pub use aliases::*;
9pub use credentials::*;
12pub use primitives::*;
13pub use value::*;
14
15use crate::WError;
16
17pub trait PlutusDataJson: Clone + Debug + Sized {
18 fn to_json(&self) -> serde_json::Value;
19 fn to_json_string(&self) -> String {
20 self.to_json().to_string()
21 }
22 fn to_constr_field(&self) -> Vec<serde_json::Value> {
23 vec![self.to_json()]
24 }
25
26 fn from_json(value: &serde_json::Value) -> Result<Self, WError>;
27 fn from_json_string(json_str: &str) -> Result<Self, WError> {
28 let value: serde_json::Value = serde_json::from_str(json_str)
29 .map_err(WError::from_err("PlutusDataJson::from_json_string"))?;
30 Self::from_json(&value)
31 }
32
33 fn from_constr_field(fields: &serde_json::Value) -> Result<Self, WError> {
36 let arr = fields
37 .as_array()
38 .ok_or_else(|| WError::new("from_constr_field", "expected array"))?;
39 if arr.len() == 1 {
40 Self::from_json(&arr[0])
41 } else if arr.is_empty() {
42 Self::from_json(fields)
43 } else {
44 Self::from_json(fields)
46 }
47 }
48}
49
50#[derive(Clone, Debug)]
51pub enum PlutusData {
52 Integer(Int),
53 ByteString(ByteString),
54 List(List<PlutusData>),
55 Map(Map<PlutusData, PlutusData>),
56 Bool(Bool),
57 Constr(Constr<Box<PlutusData>>),
58}
59
60impl PlutusDataJson for PlutusData {
61 fn to_json(&self) -> serde_json::Value {
62 match self {
63 PlutusData::Integer(int) => int.to_json(),
64 PlutusData::ByteString(bytes) => bytes.to_json(),
65 PlutusData::List(list) => list.to_json(),
66 PlutusData::Map(map) => map.to_json(),
67 PlutusData::Bool(bool) => bool.to_json(),
68 PlutusData::Constr(constr) => constr.to_json(),
69 }
70 }
71
72 fn to_json_string(&self) -> String {
73 self.to_json().to_string()
74 }
75
76 fn to_constr_field(&self) -> Vec<serde_json::Value> {
77 match self {
78 PlutusData::Integer(int) => vec![int.to_json()],
79 PlutusData::ByteString(bytes) => vec![bytes.to_json()],
80 PlutusData::List(list) => vec![list.to_json()],
81 PlutusData::Map(map) => vec![map.to_json()],
82 PlutusData::Bool(bool) => vec![bool.to_json()],
83 PlutusData::Constr(constr) => constr.fields.to_constr_field(),
84 }
85 }
86
87 fn from_json(value: &serde_json::Value) -> Result<Self, WError> {
88 if value.get("int").is_some() {
90 Int::from_json(value).map(PlutusData::Integer)
91 } else if value.get("bytes").is_some() {
92 ByteString::from_json(value).map(PlutusData::ByteString)
93 } else if value.get("list").is_some() {
94 List::<PlutusData>::from_json(value).map(PlutusData::List)
95 } else if value.get("map").is_some() {
96 Map::<PlutusData, PlutusData>::from_json(value).map(PlutusData::Map)
97 } else if value.get("constructor").is_some() {
98 let constructor = value.get("constructor").and_then(|c| c.as_u64());
100 let fields = value.get("fields").and_then(|f| f.as_array());
101 if let (Some(tag), Some(f)) = (constructor, fields) {
102 if (tag == 0 || tag == 1) && f.is_empty() {
103 return Bool::from_json(value).map(PlutusData::Bool);
104 }
105 }
106 Constr::<Box<PlutusData>>::from_json(value).map(PlutusData::Constr)
108 } else {
109 Err(WError::new("PlutusData::from_json", "unrecognized JSON format"))
110 }
111 }
112}
113
114impl PlutusDataJson for Box<PlutusData> {
116 fn to_json(&self) -> serde_json::Value {
117 self.as_ref().to_json()
118 }
119
120 fn to_json_string(&self) -> String {
121 self.to_json().to_string()
122 }
123
124 fn to_constr_field(&self) -> Vec<serde_json::Value> {
125 self.as_ref().to_constr_field()
126 }
127
128 fn from_json(value: &serde_json::Value) -> Result<Self, WError> {
129 PlutusData::from_json(value).map(Box::new)
130 }
131}
132
133impl<T: PlutusDataJson + Clone> PlutusDataJson for Box<List<T>> {
135 fn to_json(&self) -> serde_json::Value {
136 self.as_ref().to_json()
137 }
138
139 fn to_json_string(&self) -> String {
140 self.to_json().to_string()
141 }
142
143 fn to_constr_field(&self) -> Vec<serde_json::Value> {
144 vec![self.to_json()]
145 }
146
147 fn from_json(value: &serde_json::Value) -> Result<Self, WError> {
148 List::<T>::from_json(value).map(Box::new)
149 }
150}
151
152macro_rules! impl_box_plutus_data {
154 ($($ty:ty),+) => {
155 $(
156 impl PlutusDataJson for Box<$ty> {
157 fn to_json(&self) -> serde_json::Value {
158 self.as_ref().to_json()
159 }
160
161 fn to_json_string(&self) -> String {
162 self.to_json().to_string()
163 }
164
165 fn to_constr_field(&self) -> Vec<serde_json::Value> {
166 vec![self.to_json()]
167 }
168
169 fn from_json(value: &serde_json::Value) -> Result<Self, WError> {
170 <$ty>::from_json(value).map(Box::new)
171 }
172 }
173 )+
174 };
175}
176
177impl_box_plutus_data!(
179 ByteString,
180 Int,
181 Bool
182);