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(cbor, &mut Ctx { arena })
58 }
59
60 pub fn unwrap_constr<V>(
61 &'a self,
62 ) -> Result<(&'a u64, &'a [&'a PlutusData<'a>]), MachineError<'a, V>>
63 where
64 V: Eval<'a>,
65 {
66 match self {
67 PlutusData::Constr { tag, fields } => Ok((tag, fields)),
68 _ => Err(MachineError::malformed_data(self)),
69 }
70 }
71
72 pub fn unwrap_map<V>(
73 &'a self,
74 ) -> Result<&'a [(&'a PlutusData<'a>, &'a PlutusData<'a>)], MachineError<'a, V>>
75 where
76 V: Eval<'a>,
77 {
78 match self {
79 PlutusData::Map(fields) => Ok(fields),
80 _ => Err(MachineError::malformed_data(self)),
81 }
82 }
83
84 pub fn unwrap_integer<V>(&'a self) -> Result<&'a Integer, MachineError<'a, V>>
85 where
86 V: Eval<'a>,
87 {
88 match self {
89 PlutusData::Integer(i) => Ok(i),
90 _ => Err(MachineError::malformed_data(self)),
91 }
92 }
93
94 pub fn unwrap_byte_string<V>(&'a self) -> Result<&'a [u8], MachineError<'a, V>>
95 where
96 V: Eval<'a>,
97 {
98 match self {
99 PlutusData::ByteString(bytes) => Ok(bytes),
100 _ => Err(MachineError::malformed_data(self)),
101 }
102 }
103
104 pub fn unwrap_list<V>(&'a self) -> Result<&'a [&'a PlutusData<'a>], MachineError<'a, V>>
105 where
106 V: Eval<'a>,
107 {
108 match self {
109 PlutusData::List(items) => Ok(items),
110 _ => Err(MachineError::malformed_data(self)),
111 }
112 }
113
114 pub fn constant(&'a self, arena: &'a Arena) -> &'a Constant<'a> {
115 Constant::data(arena, self)
116 }
117
118 pub fn to_bytes<V>(&'a self, arena: &'a Arena) -> Result<&'a [u8], MachineError<'a, V>>
119 where
120 V: Eval<'a>,
121 {
122 minicbor::to_vec(self)
123 .map(|vec| arena.alloc(vec) as &'a [u8])
124 .map_err(|_| MachineError::serialization_error(self))
125 }
126}