1use std::fmt::Debug;
16
17use base64ct::Encoding as _;
18use bech32::{FromBase32, Variant};
19use serde;
20use serde::de::{Deserializer, Error};
21use serde::ser::Serializer;
22use serde::Deserialize;
23use serde::Serialize;
24use serde_with::{DeserializeAs, SerializeAs};
25
26use crate::error::FastCryptoError::InvalidInput;
27use crate::error::{FastCryptoError, FastCryptoResult};
28
29pub trait Encoding {
31 fn decode(s: &str) -> FastCryptoResult<Vec<u8>>;
33
34 fn encode<T: AsRef<[u8]>>(data: T) -> String;
36}
37
38macro_rules! impl_serde_as_for_encoding {
41 ($encoding:ty) => {
42 impl<'de> DeserializeAs<'de, Vec<u8>> for $encoding {
43 fn deserialize_as<D>(deserializer: D) -> Result<Vec<u8>, D::Error>
44 where
45 D: Deserializer<'de>,
46 {
47 let s = String::deserialize(deserializer)?;
48 Self::decode(&s).map_err(|_| Error::custom("Deserialization failed"))
49 }
50 }
51
52 impl<T> SerializeAs<T> for $encoding
53 where
54 T: AsRef<[u8]>,
55 {
56 fn serialize_as<S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
57 where
58 S: Serializer,
59 {
60 let encoded_string = Self::encode(value);
61 Self(encoded_string).serialize(serializer)
62 }
63 }
64
65 impl<'de, const N: usize> DeserializeAs<'de, [u8; N]> for $encoding {
66 fn deserialize_as<D>(deserializer: D) -> Result<[u8; N], D::Error>
67 where
68 D: Deserializer<'de>,
69 {
70 let value: Vec<u8> = <$encoding>::deserialize_as(deserializer)?;
71 value
72 .try_into()
73 .map_err(|_| Error::custom(format!("Invalid array length, expecting {}", N)))
74 }
75 }
76 };
77}
78
79macro_rules! impl_try_from_string {
81 ($encoding:ty) => {
82 impl TryFrom<String> for $encoding {
83 type Error = FastCryptoError;
84 fn try_from(value: String) -> Result<Self, Self::Error> {
85 <$encoding>::decode(&value)?;
87 Ok(Self(value))
88 }
89 }
90 };
91}
92
93#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
95#[serde(try_from = "String")]
96pub struct Base64(String);
97
98impl_serde_as_for_encoding!(Base64);
99impl_try_from_string!(Base64);
100
101impl Base64 {
102 pub fn to_vec(&self) -> FastCryptoResult<Vec<u8>> {
104 Self::decode(&self.0)
105 }
106 pub fn from_bytes(bytes: &[u8]) -> Self {
108 Self(Self::encode(bytes))
109 }
110 pub fn encoded(&self) -> String {
112 self.0.clone()
113 }
114}
115
116#[derive(Deserialize, Debug, Clone, PartialEq)]
118#[serde(try_from = "String")]
119pub struct Hex(String);
120
121impl TryFrom<String> for Hex {
122 type Error = FastCryptoError;
123 fn try_from(value: String) -> Result<Self, Self::Error> {
124 let s = value.strip_prefix("0x").unwrap_or(&value);
125 Ok(Self(s.to_string()))
126 }
127}
128
129impl Serialize for Hex {
130 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
131 where
132 S: Serializer,
133 {
134 String::serialize(&self.encoded_with_format(), serializer)
136 }
137}
138
139impl_serde_as_for_encoding!(Hex);
140
141impl Hex {
142 #[cfg(test)]
144 pub fn from_string(s: &str) -> Self {
145 Hex(s.to_string())
146 }
147 pub fn to_vec(&self) -> FastCryptoResult<Vec<u8>> {
149 Self::decode(&self.0)
150 }
151 pub fn from_bytes(bytes: &[u8]) -> Self {
153 Self(Self::encode(bytes))
154 }
155 pub fn encode_with_format<T: AsRef<[u8]>>(bytes: T) -> String {
157 Self::format(&Self::encode(bytes))
158 }
159 pub fn encoded_with_format(&self) -> String {
161 Self::format(&self.0)
162 }
163 fn format(hex_string: &str) -> String {
165 format!("0x{}", hex_string)
166 }
167}
168
169pub fn decode_bytes_hex<T: for<'a> TryFrom<&'a [u8]>>(s: &str) -> FastCryptoResult<T> {
171 let value = Hex::decode(s)?;
172 T::try_from(&value[..]).map_err(|_| InvalidInput)
173}
174
175impl Encoding for Hex {
176 fn decode(s: &str) -> FastCryptoResult<Vec<u8>> {
179 let s = s.strip_prefix("0x").unwrap_or(s);
180 hex::decode(s).map_err(|_| InvalidInput)
181 }
182
183 fn encode<T: AsRef<[u8]>>(data: T) -> String {
185 hex::encode(data.as_ref())
186 }
187}
188
189impl Encoding for Base64 {
190 fn decode(s: &str) -> FastCryptoResult<Vec<u8>> {
191 base64ct::Base64::decode_vec(s).map_err(|_| InvalidInput)
192 }
193
194 fn encode<T: AsRef<[u8]>>(data: T) -> String {
195 base64ct::Base64::encode_string(data.as_ref())
196 }
197}
198
199#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
200#[serde(try_from = "String")]
201pub struct Base58(String);
202
203impl_serde_as_for_encoding!(Base58);
204impl_try_from_string!(Base58);
205
206impl Encoding for Base58 {
207 fn decode(s: &str) -> FastCryptoResult<Vec<u8>> {
208 bs58::decode(s).into_vec().map_err(|_| InvalidInput)
209 }
210
211 fn encode<T: AsRef<[u8]>>(data: T) -> String {
212 bs58::encode(data).into_string()
213 }
214}
215
216pub struct Bech32;
218
219impl Bech32 {
220 pub fn decode(s: &str, hrp: &str) -> FastCryptoResult<Vec<u8>> {
228 let (parsed, data, variant) = bech32::decode(s).map_err(|_| InvalidInput)?;
229 if parsed != hrp || variant != Variant::Bech32 {
230 Err(InvalidInput)
231 } else {
232 Vec::<u8>::from_base32(&data).map_err(|_| InvalidInput)
233 }
234 }
235
236 pub fn encode<T: AsRef<[u8]>>(data: T, hrp: &str) -> FastCryptoResult<String> {
244 use bech32::ToBase32;
245 bech32::encode(hrp, data.to_base32(), Variant::Bech32).map_err(|_| InvalidInput)
246 }
247}