1
1
//! Plutus Data related types and traits
2
2
#[ 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
+ } ;
4
10
use num_bigint:: BigInt ;
5
11
use std:: collections:: { BTreeMap , BTreeSet } ;
6
12
@@ -9,7 +15,6 @@ use serde::{Deserialize, Serialize};
9
15
10
16
/// Data representation of on-chain data such as Datums and Redeemers
11
17
#[ derive( Clone , Debug , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
12
- #[ cfg_attr( feature = "lbf" , derive( Json ) ) ]
13
18
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
14
19
pub enum PlutusData {
15
20
Constr ( BigInt , Vec < PlutusData > ) ,
@@ -19,6 +24,122 @@ pub enum PlutusData {
19
24
Bytes ( Vec < u8 > ) ,
20
25
}
21
26
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
+
22
143
impl PlutusData {
23
144
pub fn constr ( tag : u32 , fields : Vec < PlutusData > ) -> Self {
24
145
PlutusData :: Constr ( BigInt :: from ( tag) , fields)
0 commit comments