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