1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::Visitor;
#[derive(Clone, PartialEq, Debug)]
pub enum TonAddress {
StdShort([u8; 32]),
StdFull(i8, [u8; 32]),
Var(i32, Vec<u8>),
AnycastStd(u8, u32, i8, [u8; 32]),
AnycastVar(u8, u32, i32, Vec<u8>),
}
impl Serialize for TonAddress {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error> where
S: Serializer {
serializer.serialize_str(&self.get_account_hex_string())
}
}
struct AddressVisitor;
impl<'de> Visitor<'de> for AddressVisitor {
type Value = TonAddress;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("32 bytes written into string like a hex values without spaces")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: serde::de::Error {
let mut result = [0u8; 32];
let vec = hex::decode(v)
.map_err(|err| serde::de::Error::custom(format!("error decode hex: {}", err)))?;
if vec.len() != 32 {
return Err(serde::de::Error::custom(format!("Wrong data length")));
}
result.copy_from_slice(&vec);
Ok(TonAddress::StdShort(result))
}
}
impl<'de> Deserialize<'de> for TonAddress {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(AddressVisitor)
}
}
impl TonAddress {
pub fn get_account_hex_string(&self) -> String {
match self {
TonAddress::StdShort(a) =>
hex::encode(a),
TonAddress::StdFull(_, a) =>
hex::encode(a),
TonAddress::Var(_, a) =>
hex::encode(a),
TonAddress::AnycastStd(_, _, _, a) =>
hex::encode(a),
TonAddress::AnycastVar(_, _, _, a) =>
hex::encode(a),
}
}
}
fn fmt_addr(
f: &mut std::fmt::Formatter,
anycast: Option<(u8, u32)>,
workchain: Option<i32>,
address: Option<&[u8]>) -> Result<(), std::fmt::Error> {
if let Some((d, p)) = anycast {
write!(f, "{}:{}:", d, p)?
}
if let Some(w) = workchain {
write!(f, "{}:", w)?
}
if let Some(a) = address {
write!(f, "{}", hex::encode(a))?
}
Ok(())
}
impl std::fmt::Display for TonAddress {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
match self {
TonAddress::StdShort( a) =>
fmt_addr(f, None, None, Some(a)),
TonAddress::StdFull(w, a) =>
fmt_addr(f, None, Some(*w as i32), Some(a)),
TonAddress::Var(w, a) =>
fmt_addr(f, None, Some(*w), Some(a)),
TonAddress::AnycastStd(d, p, w, a) =>
fmt_addr(f, Some((*d, *p)), Some(*w as i32), Some(a)),
TonAddress::AnycastVar(d, p, w, a) =>
fmt_addr(f, Some((*d, *p)), Some(*w), Some(a))
}
}
}