amaru_kernel/cardano/memoized/
datum.rs1use serde::ser::SerializeStruct;
16
17use crate::{
18 Hash, Legacy, MemoizedPlutusData,
19 cbor::{self, IanaTag},
20 size::DATUM,
21};
22
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum MemoizedDatum {
25 None,
26 Hash(Hash<DATUM>),
27 Inline(MemoizedPlutusData),
28}
29
30impl serde::Serialize for MemoizedDatum {
31 fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
32 match self {
33 MemoizedDatum::None => None::<()>.serialize(serializer),
34 MemoizedDatum::Hash(hash) => {
35 let mut s = serializer.serialize_struct("MemoizedDatum::Hash", 1)?;
36 s.serialize_field("Hash", &hash)?;
37 s.end()
38 }
39 MemoizedDatum::Inline(data) => {
40 let mut s = serializer.serialize_struct("MemoizedDatum::Data", 1)?;
41 s.serialize_field("Data", &data)?;
42 s.end()
43 }
44 }
45 }
46}
47
48impl<'de> serde::Deserialize<'de> for MemoizedDatum {
49 fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<MemoizedDatum, D::Error> {
50 #[derive(serde::Deserialize)]
52 enum PlaceholderDatum {
53 Hash(Hash<DATUM>),
54 Data(MemoizedPlutusData),
55 #[serde(untagged)]
56 Unit(()),
57 }
58
59 match serde::Deserialize::deserialize(deserializer)? {
60 PlaceholderDatum::Unit(()) => Ok(MemoizedDatum::None),
61 PlaceholderDatum::Hash(bytes) => Ok(MemoizedDatum::Hash(bytes)),
62 PlaceholderDatum::Data(data) => Ok(MemoizedDatum::Inline(data)),
63 }
64 }
65}
66
67impl<'b, C> cbor::Decode<'b, C> for MemoizedDatum {
68 fn decode(d: &mut cbor::Decoder<'b>, ctx: &mut C) -> Result<Self, cbor::decode::Error> {
69 cbor::heterogeneous_array(d, |d, assert_len| {
70 assert_len(2)?;
71 let datum_option = d.u8()?;
72 match datum_option {
73 0 => {
74 let Legacy(datum) = d.decode_with(ctx)?;
75 Ok(datum)
76 }
77 1 => {
78 if d.tag()? != IanaTag::Cbor.tag() {
79 return Err(cbor::decode::Error::message("unknown tag for datum tag"));
80 }
81 let plutus_data: pallas_primitives::KeepRaw<'_, pallas_primitives::PlutusData> =
82 cbor::decode_with(d.bytes()?, ctx)?;
83 Ok(MemoizedDatum::Inline(MemoizedPlutusData::from(plutus_data)))
84 }
85 _ => Err(cbor::decode::Error::message(format!("unknown datum option: {}", datum_option))),
86 }
87 })
88 }
89}
90
91impl<'b, C> cbor::Decode<'b, C> for Legacy<MemoizedDatum> {
92 fn decode(d: &mut cbor::Decoder<'b>, _ctx: &mut C) -> Result<Self, cbor::decode::Error> {
93 let raw = d.bytes()?;
94 if raw.len() != 32 {
95 return Err(cbor::decode::Error::message(format!("expected datum hash of length 32, got {}", raw.len())));
96 }
97 Ok(Legacy(MemoizedDatum::Hash(Hash::<DATUM>::from(raw))))
98 }
99}
100
101impl<C> cbor::Encode<C> for MemoizedDatum {
102 fn encode<W: cbor::encode::Write>(
103 &self,
104 e: &mut cbor::Encoder<W>,
105 _ctx: &mut C,
106 ) -> Result<(), cbor::encode::Error<W::Error>> {
107 match &self {
108 MemoizedDatum::None => (),
109 MemoizedDatum::Hash(hash) => {
110 e.array(2)?;
111 e.u8(0)?;
112 e.bytes(&hash[..])?;
113 }
114 MemoizedDatum::Inline(data) => {
115 e.array(2)?;
116 e.u8(1)?;
117 e.tag(IanaTag::Cbor)?;
118 e.bytes(data.original_bytes())?;
119 }
120 }
121
122 Ok(())
123 }
124}
125
126impl From<Option<Hash<DATUM>>> for MemoizedDatum {
127 fn from(opt: Option<Hash<DATUM>>) -> Self {
128 opt.map(MemoizedDatum::Hash).unwrap_or(MemoizedDatum::None)
129 }
130}