1#![allow(unused_macros)]
2
3use std::{fmt::Debug, ops::Bound, str::FromStr};
4
5use massa_serialization::{
6 DeserializeError, Deserializer, SerializeError, Serializer, U64VarIntDeserializer,
7 U64VarIntSerializer,
8};
9use nom::{
10 error::{ContextError, ParseError},
11 IResult,
12};
13use transition::Versioned;
14
15use crate::{
16 config::THREAD_COUNT,
17 error::ModelsError,
18 serialization::{VecU8Deserializer, VecU8Serializer},
19 slot::{Slot, SlotDeserializer, SlotSerializer},
20};
21
22const DEFERRED_CALL_ID_PREFIX: &str = "D";
23
24#[allow(missing_docs)]
25#[transition::versioned(versions("0"))]
26#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
27pub struct DeferredCallId(Vec<u8>);
28
29#[derive(Default, Clone)]
31pub struct DeferredCallIdSerializer {
32 bytes_serializer: VecU8Serializer,
33}
34
35impl DeferredCallIdSerializer {
36 pub fn new() -> Self {
38 Self {
39 bytes_serializer: VecU8Serializer::new(),
40 }
41 }
42}
43
44impl Serializer<DeferredCallId> for DeferredCallIdSerializer {
45 fn serialize(
46 &self,
47 value: &DeferredCallId,
48 buffer: &mut Vec<u8>,
49 ) -> Result<(), SerializeError> {
50 match value {
51 DeferredCallId::DeferredCallIdV0(id) => {
52 self.bytes_serializer.serialize(&id.0, buffer)?;
53 }
54 }
55 Ok(())
56 }
57}
58
59#[derive(Clone)]
61pub struct DeferredCallIdDeserializer {
62 bytes_deserializer: VecU8Deserializer,
63}
64
65impl DeferredCallIdDeserializer {
66 pub fn new() -> Self {
68 Self {
69 bytes_deserializer: VecU8Deserializer::new(
70 std::ops::Bound::Included(0),
71 std::ops::Bound::Included(128),
72 ),
73 }
74 }
75}
76
77impl Default for DeferredCallIdDeserializer {
78 fn default() -> Self {
79 Self::new()
80 }
81}
82
83impl Deserializer<DeferredCallId> for DeferredCallIdDeserializer {
84 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
85 &self,
86 buffer: &'a [u8],
87 ) -> IResult<&'a [u8], DeferredCallId, E> {
88 let (rest, bytes) = self.bytes_deserializer.deserialize(buffer)?;
89 Ok((
90 rest,
91 DeferredCallId::DeferredCallIdV0(DeferredCallIdV0(bytes)),
92 ))
93 }
94}
95
96impl FromStr for DeferredCallId {
97 type Err = ModelsError;
98
99 fn from_str(s: &str) -> Result<Self, Self::Err> {
100 if !s.starts_with(DEFERRED_CALL_ID_PREFIX) {
101 return Err(ModelsError::DeserializeError(format!(
102 "Invalid prefix for DeferredCallId: {}",
103 s
104 )));
105 }
106 let s = &s[DEFERRED_CALL_ID_PREFIX.len()..];
107 let bytes = bs58::decode(s).with_check(None).into_vec().map_err(|_| {
108 ModelsError::DeserializeError(format!(
109 "Invalid base58 string for DeferredCallId: {}",
110 s
111 ))
112 })?;
113 DeferredCallId::from_bytes(&bytes)
114 }
115}
116
117impl std::fmt::Display for DeferredCallId {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 write!(
120 f,
121 "{}{}",
122 DEFERRED_CALL_ID_PREFIX,
123 bs58::encode(self.as_bytes()).with_check().into_string()
124 )
125 }
126}
127
128impl ::serde::Serialize for DeferredCallId {
129 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
130 where
131 S: ::serde::Serializer,
132 {
133 if serializer.is_human_readable() {
134 serializer.collect_str(&self.to_string())
135 } else {
136 serializer.serialize_bytes(self.as_bytes())
137 }
138 }
139}
140
141impl<'de> ::serde::Deserialize<'de> for DeferredCallId {
142 fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<DeferredCallId, D::Error> {
143 if d.is_human_readable() {
144 struct DeferredCallIdVisitor;
145
146 impl<'de> ::serde::de::Visitor<'de> for DeferredCallIdVisitor {
147 type Value = DeferredCallId;
148
149 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
150 formatter.write_str("ASC + base58::encode(bytes)")
151 }
152
153 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
154 where
155 E: ::serde::de::Error,
156 {
157 if let Ok(v_str) = std::str::from_utf8(v) {
158 DeferredCallId::from_str(v_str).map_err(E::custom)
159 } else {
160 Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
161 }
162 }
163
164 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
165 where
166 E: ::serde::de::Error,
167 {
168 DeferredCallId::from_str(v).map_err(E::custom)
169 }
170 }
171 d.deserialize_str(DeferredCallIdVisitor)
172 } else {
173 struct BytesVisitor;
174
175 impl<'de> ::serde::de::Visitor<'de> for BytesVisitor {
176 type Value = DeferredCallId;
177
178 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
179 formatter.write_str("[u64varint-of-addr-variant][u64varint-of-version][bytes]")
180 }
181
182 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
183 where
184 E: ::serde::de::Error,
185 {
186 DeferredCallId::from_bytes(v).map_err(E::custom)
187 }
188 }
189
190 d.deserialize_bytes(BytesVisitor)
191 }
192 }
193}
194
195impl DeferredCallId {
196 pub fn get_slot(&self) -> Result<Slot, ModelsError> {
198 let version_deserializer = U64VarIntDeserializer::new(
199 std::ops::Bound::Included(0),
200 std::ops::Bound::Included(u64::MAX),
201 );
202
203 let slot_deser = SlotDeserializer::new(
204 (Bound::Included(0), Bound::Included(u64::MAX)),
205 (Bound::Included(0), Bound::Excluded(THREAD_COUNT)),
206 );
207
208 let (rest, _version) = version_deserializer
209 .deserialize::<DeserializeError>(self.as_bytes())
210 .map_err(|_e| ModelsError::DeferredCallIdParseError)?;
211 let (_rest, slot) = slot_deser
212 .deserialize::<DeserializeError>(rest)
213 .map_err(|_e| ModelsError::DeferredCallIdParseError)?;
214 Ok(slot)
215 }
216
217 pub fn new(
219 version: u64,
220 target_slot: Slot,
221 index: u64,
222 trail_hash: &[u8],
223 ) -> Result<Self, ModelsError> {
224 let mut id: Vec<u8> = Vec::new();
225 match version {
226 0 => {
227 let version_serializer = U64VarIntSerializer::new();
228 let slot_serializer = SlotSerializer::new();
229 version_serializer.serialize(&version, &mut id)?;
230 slot_serializer.serialize(&target_slot, &mut id)?;
231 id.extend(index.to_be_bytes());
232 id.extend(trail_hash);
233 Ok(DeferredCallId::DeferredCallIdV0(DeferredCallIdV0(id)))
234 }
235 _ => Err(ModelsError::InvalidVersionError(format!(
236 "Invalid version to create an DeferredCallId: {}",
237 version
238 ))),
239 }
240 }
241
242 pub fn as_bytes(&self) -> &[u8] {
244 match self {
245 DeferredCallId::DeferredCallIdV0(block_id) => block_id.as_bytes(),
246 }
247 }
248
249 pub fn from_bytes(bytes: &[u8]) -> Result<Self, ModelsError> {
251 if bytes.is_empty() {
252 return Err(ModelsError::SerializeError("Empty bytes".to_string()));
253 }
254 let version = U64VarIntDeserializer::new(
255 std::ops::Bound::Included(0),
256 std::ops::Bound::Included(u64::MAX),
257 );
258 let (_, version) = version.deserialize(bytes)?;
259 match version {
260 0 => {
261 let id = DeferredCallIdV0::from_bytes(bytes)?;
262 Ok(DeferredCallId::DeferredCallIdV0(id))
263 }
264 _ => Err(ModelsError::InvalidVersionError(format!(
265 "Invalid version to create an DeferredCallId: {}",
266 version
267 ))),
268 }
269 }
270}
271
272#[transition::impl_version(versions("0"))]
273impl DeferredCallId {
274 pub fn as_bytes(&self) -> &[u8] {
276 &self.0
277 }
278
279 pub fn from_bytes(bytes: &[u8]) -> Result<Self, ModelsError> {
281 Ok(DeferredCallId(bytes.to_vec()))
282 }
283}
284
285#[cfg(test)]
286mod tests {
287 use massa_serialization::DeserializeError;
288
289 use super::*;
290 use crate::slot::Slot;
291
292 #[test]
293 fn test_deferred_call_id_ser_deser() {
294 let slot = Slot::new(1, 2);
295 let index = 3;
296 let trail_hash = [4, 5, 6];
297 let id = DeferredCallId::new(0, slot, index, &trail_hash).unwrap();
298 let serializer = DeferredCallIdSerializer::new();
299 let mut buffer = Vec::new();
300 serializer.serialize(&id, &mut buffer).unwrap();
301 let deserializer = DeferredCallIdDeserializer::new();
302 let (rest, deserialized_id) = deserializer
303 .deserialize::<DeserializeError>(&buffer)
304 .unwrap();
305 assert_eq!(deserialized_id, id);
306 assert!(rest.is_empty());
307 }
308
309 #[test]
310 fn test_deferred_call_id_from_str() {
311 let slot = Slot::new(1, 2);
312 let index = 3;
313 let trail_hash = [4, 5, 6];
314 let id = DeferredCallId::new(0, slot, index, &trail_hash).unwrap();
315 let id_str = id.to_string();
316 let deserialized_id = DeferredCallId::from_str(&id_str).unwrap();
317 assert_eq!(deserialized_id, id);
318 }
319
320 #[test]
321 fn test_get_slot() {
322 let slot = Slot::new(1, 2);
323 let index = 3;
324 let trail_hash = [4, 5, 6];
325 let id = DeferredCallId::new(0, slot, index, &trail_hash).unwrap();
326 assert_eq!(id.get_slot().unwrap(), slot);
327 }
328}