defuse_serde_utils/
base58.rs

1use near_sdk::{
2    bs58,
3    serde::{Deserialize, Deserializer, Serialize, Serializer, de},
4    serde_with::{DeserializeAs, SerializeAs},
5};
6
7pub struct Base58;
8
9impl<T> SerializeAs<T> for Base58
10where
11    T: AsRef<[u8]>,
12{
13    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
14    where
15        S: Serializer,
16    {
17        bs58::encode(source).into_string().serialize(serializer)
18    }
19}
20
21impl<'de, T> DeserializeAs<'de, T> for Base58
22where
23    T: TryFrom<Vec<u8>>,
24{
25    fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
26    where
27        D: Deserializer<'de>,
28    {
29        let s = <&str as Deserialize>::deserialize(deserializer)?;
30
31        let bytes = bs58::decode(s).into_vec().map_err(de::Error::custom)?;
32
33        let length = bytes.len();
34        bytes.try_into().map_err(|_| {
35            de::Error::custom(format_args!(
36                "can't convert a byte vector of length {length} into the output type"
37            ))
38        })
39    }
40}
41
42#[cfg(feature = "abi")]
43const _: () = {
44    use near_sdk::{
45        schemars::{
46            JsonSchema,
47            r#gen::SchemaGenerator,
48            schema::{InstanceType, Schema, SchemaObject},
49        },
50        serde_with::schemars_0_8::JsonSchemaAs,
51    };
52
53    impl<T> JsonSchemaAs<T> for Base58 {
54        fn schema_name() -> String {
55            String::schema_name()
56        }
57
58        fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
59            // TODO: use #[schemars(extend(...))] when released
60            SchemaObject {
61                instance_type: Some(InstanceType::String.into()),
62                extensions: [("contentEncoding", "base58".into())]
63                    .into_iter()
64                    .map(|(k, v)| (k.to_string(), v))
65                    .collect(),
66                ..Default::default()
67            }
68            .into()
69        }
70
71        fn is_referenceable() -> bool {
72            false
73        }
74    }
75};