antelope/chain/
block_id.rs1use crate::chain::{Decoder, Encoder, Packer};
2use antelope_client_macros::StructPacker;
3use serde::{
4 de::{self, Visitor},
5 Deserializer,
6};
7use serde::{Deserialize, Serialize};
8use std::fmt;
9use std::fmt::{Display, Formatter};
10
11#[derive(Clone, Default, Eq, PartialEq, StructPacker, Serialize, Deserialize, Debug)]
12pub struct BlockId {
13 pub bytes: Vec<u8>,
14}
15
16impl BlockId {
17 pub fn from_bytes(bytes: &[u8]) -> Result<Self, String> {
18 if bytes.len() != 32 {
19 return Err(String::from(
20 "BlockId.from_bytes expected bytes length of 32",
21 ));
22 }
23 Ok(Self {
24 bytes: bytes.to_vec(),
25 })
26 }
27
28 pub fn block_num(&self) -> u32 {
29 let num_bytes = &self.bytes[0..4];
30 (u32::from(num_bytes[0]) << 24)
31 | (u32::from(num_bytes[1]) << 16)
32 | (u32::from(num_bytes[2]) << 8)
33 | u32::from(num_bytes[3])
34 }
35
36 pub fn as_string(&self) -> String {
37 self.block_num().to_string()
38 }
39}
40
41impl Display for BlockId {
42 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
43 write!(f, "{}", self.as_string())
44 }
45}
46
47pub(crate) fn deserialize_block_id<'de, D>(deserializer: D) -> Result<BlockId, D::Error>
48where
49 D: Deserializer<'de>,
50{
51 struct BlockIdVisitor;
52
53 impl<'de> Visitor<'de> for BlockIdVisitor {
54 type Value = BlockId;
55
56 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
57 formatter.write_str("a hex string for BlockId")
58 }
59
60 fn visit_str<E>(self, value: &str) -> Result<BlockId, E>
61 where
62 E: de::Error,
63 {
64 if value.len() != 64 {
65 return Err(E::custom(
67 "BlockId hex string must be exactly 64 characters long",
68 ));
69 }
70
71 let mut bytes = Vec::new();
72 for i in 0..32 {
73 let byte_slice = &value[i * 2..i * 2 + 2];
75 match u8::from_str_radix(byte_slice, 16) {
76 Ok(byte) => bytes.push(byte),
77 Err(_) => return Err(E::custom("Invalid hex string for BlockId")),
78 }
79 }
80
81 Ok(BlockId { bytes })
82 }
83 }
84
85 deserializer.deserialize_str(BlockIdVisitor)
86}
87
88pub(crate) fn deserialize_optional_block_id<'de, D>(
89 deserializer: D,
90) -> Result<Option<BlockId>, D::Error>
91where
92 D: Deserializer<'de>,
93{
94 let opt: Option<String> = Option::deserialize(deserializer)?;
96 let result = match opt {
98 Some(str_val) => {
99 let mut bytes = Vec::new();
100 for i in 0..(str_val.len() / 2) {
101 let byte_slice = &str_val[i * 2..i * 2 + 2];
102 match u8::from_str_radix(byte_slice, 16) {
103 Ok(byte) => bytes.push(byte),
104 Err(_) => {
105 return Err(serde::de::Error::custom("Invalid hex string for BlockId"))
106 }
107 }
108 }
109 BlockId::from_bytes(&bytes)
111 .map(Some)
112 .map_err(serde::de::Error::custom)?
113 }
114 None => None,
115 };
116 Ok(result)
117}