Skip to main content

amaru_uplc/
data.rs

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}