Skip to content

Commit 0d893cb

Browse files
committed
Manual PlutusData Json implementation
1 parent 93aff32 commit 0d893cb

File tree

1 file changed

+123
-2
lines changed

1 file changed

+123
-2
lines changed

src/plutus_data.rs

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
//! Plutus Data related types and traits
22
#[cfg(feature = "lbf")]
3-
use lbr_prelude::json::Json;
3+
use data_encoding::HEXLOWER;
4+
#[cfg(feature = "lbf")]
5+
use lbr_prelude::error::Error;
6+
#[cfg(feature = "lbf")]
7+
use lbr_prelude::json::{
8+
case_json_constructor, case_json_object, json_constructor, json_object, Json,
9+
};
410
use num_bigint::BigInt;
511
use std::collections::{BTreeMap, BTreeSet};
612

@@ -9,7 +15,6 @@ use serde::{Deserialize, Serialize};
915

1016
/// Data representation of on-chain data such as Datums and Redeemers
1117
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
12-
#[cfg_attr(feature = "lbf", derive(Json))]
1318
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1419
pub enum PlutusData {
1520
Constr(BigInt, Vec<PlutusData>),
@@ -19,6 +24,122 @@ pub enum PlutusData {
1924
Bytes(Vec<u8>),
2025
}
2126

27+
#[cfg(feature = "lbf")]
28+
impl Json for PlutusData {
29+
fn to_json(&self) -> serde_json::Value {
30+
match self {
31+
PlutusData::Constr(index, fields) => json_constructor(
32+
"Constr",
33+
vec![json_object(vec![
34+
("index".to_string(), index.to_json()),
35+
("fields".to_string(), fields.to_json()),
36+
])],
37+
),
38+
PlutusData::Map(map) => json_constructor("Map", vec![map.to_json()]),
39+
PlutusData::List(list) => json_constructor("List", vec![list.to_json()]),
40+
PlutusData::Integer(int) => json_constructor("Integer", vec![int.to_json()]),
41+
PlutusData::Bytes(bytes) => {
42+
json_constructor("Bytes", vec![String::to_json(&HEXLOWER.encode(bytes))])
43+
}
44+
}
45+
}
46+
47+
fn from_json(value: &serde_json::Value) -> Result<PlutusData, Error> {
48+
case_json_constructor(
49+
"PlutusV1.PlutusData",
50+
vec![
51+
(
52+
"Constr",
53+
Box::new(|ctor_fields| match &ctor_fields[..] {
54+
[val] => case_json_object(
55+
|obj| {
56+
let index = obj.get("index").ok_or(Error::UnexpectedFieldName {
57+
wanted: "index".to_owned(),
58+
got: obj.keys().cloned().collect(),
59+
parser: "PlutusV1.PlutusData".to_owned(),
60+
})?;
61+
62+
let fields =
63+
obj.get("fields").ok_or(Error::UnexpectedFieldName {
64+
wanted: "fields".to_owned(),
65+
got: obj.keys().cloned().collect(),
66+
parser: "PlutusV1.PlutusData".to_owned(),
67+
})?;
68+
Ok(PlutusData::Constr(
69+
BigInt::from_json(index)?,
70+
<Vec<PlutusData>>::from_json(fields)?,
71+
))
72+
},
73+
val,
74+
),
75+
_ => Err(Error::UnexpectedArrayLength {
76+
wanted: 1,
77+
got: ctor_fields.len(),
78+
parser: "Prelude.Maybe".to_owned(),
79+
}),
80+
}),
81+
),
82+
(
83+
"Map",
84+
Box::new(|ctor_fields| match &ctor_fields[..] {
85+
[val] => Ok(PlutusData::Map(Json::from_json(val)?)),
86+
_ => Err(Error::UnexpectedArrayLength {
87+
wanted: 1,
88+
got: ctor_fields.len(),
89+
parser: "Prelude.Maybe".to_owned(),
90+
}),
91+
}),
92+
),
93+
(
94+
"List",
95+
Box::new(|ctor_fields| match &ctor_fields[..] {
96+
[val] => Ok(PlutusData::List(Json::from_json(val)?)),
97+
_ => Err(Error::UnexpectedArrayLength {
98+
wanted: 1,
99+
got: ctor_fields.len(),
100+
parser: "Prelude.Maybe".to_owned(),
101+
}),
102+
}),
103+
),
104+
(
105+
"Integer",
106+
Box::new(|ctor_fields| match &ctor_fields[..] {
107+
[val] => Ok(PlutusData::Integer(Json::from_json(val)?)),
108+
_ => Err(Error::UnexpectedArrayLength {
109+
wanted: 1,
110+
got: ctor_fields.len(),
111+
parser: "Prelude.Maybe".to_owned(),
112+
}),
113+
}),
114+
),
115+
(
116+
"Bytes",
117+
Box::new(|ctor_fields| match &ctor_fields[..] {
118+
[val] => {
119+
let bytes = String::from_json(val).and_then(|str| {
120+
HEXLOWER.decode(&str.into_bytes()).map_err(|_| {
121+
Error::UnexpectedJsonInvariant {
122+
wanted: "base16 string".to_owned(),
123+
got: "unexpected string".to_owned(),
124+
parser: "Plutus.V1.Bytes".to_owned(),
125+
}
126+
})
127+
})?;
128+
Ok(PlutusData::Bytes(bytes))
129+
}
130+
_ => Err(Error::UnexpectedArrayLength {
131+
wanted: 1,
132+
got: ctor_fields.len(),
133+
parser: "Prelude.Maybe".to_owned(),
134+
}),
135+
}),
136+
),
137+
],
138+
value,
139+
)
140+
}
141+
}
142+
22143
impl PlutusData {
23144
pub fn constr(tag: u32, fields: Vec<PlutusData>) -> Self {
24145
PlutusData::Constr(BigInt::from(tag), fields)

0 commit comments

Comments
 (0)