1use crate::{
2 arena::Arena,
3 binder::Eval,
4 constant::{integer_from, Constant, Integer},
5 flat::Ctx,
6 machine::MachineError,
7};
8
9#[derive(Debug, PartialEq)]
10pub enum PlutusData<'a> {
11 Constr {
12 tag: u64,
13 fields: &'a [&'a PlutusData<'a>],
14 },
15 Map(&'a [(&'a PlutusData<'a>, &'a PlutusData<'a>)]),
16 Integer(&'a Integer),
17 ByteString(&'a [u8]),
18 List(&'a [&'a PlutusData<'a>]),
19}
20
21impl<'a> PlutusData<'a> {
22 pub fn constr(
23 arena: &'a Arena,
24 tag: u64,
25 fields: &'a [&'a PlutusData<'a>],
26 ) -> &'a PlutusData<'a> {
27 arena.alloc(PlutusData::Constr { tag, fields })
28 }
29
30 pub fn list(arena: &'a Arena, items: &'a [&'a PlutusData<'a>]) -> &'a PlutusData<'a> {
31 arena.alloc(PlutusData::List(items))
32 }
33
34 pub fn map(
35 arena: &'a Arena,
36 items: &'a [(&'a PlutusData<'a>, &'a PlutusData<'a>)],
37 ) -> &'a PlutusData<'a> {
38 arena.alloc(PlutusData::Map(items))
39 }
40
41 pub fn integer(arena: &'a Arena, i: &'a Integer) -> &'a PlutusData<'a> {
42 arena.alloc(PlutusData::Integer(i))
43 }
44
45 pub fn integer_from(arena: &'a Arena, i: i128) -> &'a PlutusData<'a> {
46 arena.alloc(PlutusData::Integer(integer_from(arena, i)))
47 }
48
49 pub fn byte_string(arena: &'a Arena, bytes: &'a [u8]) -> &'a PlutusData<'a> {
50 arena.alloc(PlutusData::ByteString(bytes))
51 }
52
53 pub fn from_cbor(
54 arena: &'a Arena,
55 cbor: &'_ [u8],
56 ) -> Result<&'a PlutusData<'a>, minicbor::decode::Error> {
57 minicbor::decode_with(
58 cbor,
59 &mut Ctx {
60 arena,
61 version: None,
62 plutus_version: None,
63 protocol_version: None,
64 },
65 )
66 }
67
68 pub fn unwrap_constr<V>(
69 &'a self,
70 ) -> Result<(&'a u64, &'a [&'a PlutusData<'a>]), MachineError<'a, V>>
71 where
72 V: Eval<'a>,
73 {
74 match self {
75 PlutusData::Constr { tag, fields } => Ok((tag, fields)),
76 _ => Err(MachineError::malformed_data(self)),
77 }
78 }
79
80 pub fn unwrap_map<V>(
81 &'a self,
82 ) -> Result<&'a [(&'a PlutusData<'a>, &'a PlutusData<'a>)], MachineError<'a, V>>
83 where
84 V: Eval<'a>,
85 {
86 match self {
87 PlutusData::Map(fields) => Ok(fields),
88 _ => Err(MachineError::malformed_data(self)),
89 }
90 }
91
92 pub fn unwrap_integer<V>(&'a self) -> Result<&'a Integer, MachineError<'a, V>>
93 where
94 V: Eval<'a>,
95 {
96 match self {
97 PlutusData::Integer(i) => Ok(i),
98 _ => Err(MachineError::malformed_data(self)),
99 }
100 }
101
102 pub fn unwrap_byte_string<V>(&'a self) -> Result<&'a [u8], MachineError<'a, V>>
103 where
104 V: Eval<'a>,
105 {
106 match self {
107 PlutusData::ByteString(bytes) => Ok(bytes),
108 _ => Err(MachineError::malformed_data(self)),
109 }
110 }
111
112 pub fn unwrap_list<V>(&'a self) -> Result<&'a [&'a PlutusData<'a>], MachineError<'a, V>>
113 where
114 V: Eval<'a>,
115 {
116 match self {
117 PlutusData::List(items) => Ok(items),
118 _ => Err(MachineError::malformed_data(self)),
119 }
120 }
121
122 pub fn constant(&'a self, arena: &'a Arena) -> &'a Constant<'a> {
123 Constant::data(arena, self)
124 }
125
126 pub fn to_bytes<V>(&'a self, arena: &'a Arena) -> Result<&'a [u8], MachineError<'a, V>>
127 where
128 V: Eval<'a>,
129 {
130 minicbor::to_vec(self)
131 .map(|vec| arena.alloc(vec) as &'a [u8])
132 .map_err(|_| MachineError::serialization_error(self))
133 }
134}