1use base64::Engine;
6use base64::engine::GeneralPurpose;
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8use serde_with::base64::Base64;
9use serde_with::{DeserializeAs, SerializeAs, formats};
10use sui_sdk_types::bcs::{FromBcs, ToBcs};
11
12pub(crate) const BASE64_DEFAULT_ENGINE: GeneralPurpose = GeneralPurpose::new(
14 &base64::alphabet::STANDARD,
15 base64::engine::general_purpose::PAD,
16);
17
18pub fn decode_base64_default(value: impl AsRef<[u8]>) -> Result<Vec<u8>, base64::DecodeError> {
20 BASE64_DEFAULT_ENGINE.decode(value)
21}
22
23pub fn encode_base64_default(value: impl AsRef<[u8]>) -> String {
25 BASE64_DEFAULT_ENGINE.encode(value)
26}
27
28pub struct Base64Bcs<Alphabet = serde_with::base64::Standard, Padding = formats::Padded>(
37 std::marker::PhantomData<(Alphabet, Padding)>,
38)
39where
40 Alphabet: serde_with::base64::Alphabet,
41 Padding: formats::Format;
42
43impl<'de, T, Alphabet, Padding> DeserializeAs<'de, T> for Base64Bcs<Alphabet, Padding>
44where
45 Alphabet: serde_with::base64::Alphabet,
46 Padding: formats::Format,
47 T: for<'a> Deserialize<'a>,
48{
49 fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
50 where
51 D: Deserializer<'de>,
52 {
53 let bytes: Vec<u8> = Base64::<Alphabet, Padding>::deserialize_as(deserializer)?;
54 FromBcs::from_bcs(&bytes).map_err(serde::de::Error::custom)
55 }
56}
57
58impl<T, Alphabet> SerializeAs<T> for Base64Bcs<Alphabet, formats::Padded>
59where
60 Alphabet: serde_with::base64::Alphabet,
61 T: Serialize,
62{
63 fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
64 where
65 S: Serializer,
66 {
67 let bytes = source.to_bcs().map_err(serde::ser::Error::custom)?;
68 Base64::<Alphabet, formats::Padded>::serialize_as(&bytes, serializer)
69 }
70}
71
72impl<T, Alphabet> SerializeAs<T> for Base64Bcs<Alphabet, formats::Unpadded>
73where
74 Alphabet: serde_with::base64::Alphabet,
75 T: Serialize,
76{
77 fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
78 where
79 S: Serializer,
80 {
81 let bytes = source.to_bcs().map_err(serde::ser::Error::custom)?;
82 Base64::<Alphabet, formats::Unpadded>::serialize_as(&bytes, serializer)
83 }
84}
85
86pub struct Base58;
92
93impl Base58 {
94 pub fn decode(data: impl AsRef<[u8]>) -> Result<Vec<u8>, bs58::decode::Error> {
95 bs58::decode(data).into_vec()
96 }
97
98 pub fn encode(data: impl AsRef<[u8]>) -> String {
99 bs58::encode(data).into_string()
100 }
101}
102
103impl<'de, T> DeserializeAs<'de, T> for Base58
104where
105 T: TryFrom<Vec<u8>>,
106 T::Error: std::fmt::Debug,
107{
108 fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
109 where
110 D: Deserializer<'de>,
111 {
112 let s = String::deserialize(deserializer)?;
113 let value = Self::decode(&s).map_err(serde::de::Error::custom)?;
114 let length = value.len();
115 value
116 .try_into()
117 .map_err(|error| serde::de::Error::custom(BytesConversionError { length, error }))
118 }
119}
120
121#[derive(thiserror::Error, Debug)]
122#[error("Converting from a Byte Vector of length {length}: {error:?}")]
123pub struct BytesConversionError<E> {
124 pub length: usize,
125 pub error: E,
126}
127
128impl<T> SerializeAs<T> for Base58
129where
130 T: AsRef<[u8]>,
131{
132 fn serialize_as<S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
133 where
134 S: Serializer,
135 {
136 Self::encode(value).serialize(serializer)
137 }
138}