Skip to main content

rings_core/message/encoder/
mod.rs

1use std::ops::Deref;
2
3use base58_monero as b58m;
4use bytes::Bytes;
5use serde::Deserialize;
6use serde::Serialize;
7
8use crate::error::Error;
9use crate::error::Result;
10
11/// Encodes values into the base58-check wire representation.
12pub trait Encoder {
13    /// Encode this value into an [`Encoded`] wrapper.
14    fn encode(&self) -> Result<Encoded>;
15}
16
17/// Decodes values from the base58-check wire representation.
18pub trait Decoder: Sized {
19    /// Decode `Self` from an [`Encoded`] wrapper.
20    fn from_encoded(encoded: &Encoded) -> Result<Self>;
21}
22
23/// Base58-check encoded message data.
24#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
25pub struct Encoded(String);
26
27impl Encoded {
28    /// Borrow the encoded string value.
29    pub fn value(&self) -> &String {
30        &self.0
31    }
32}
33
34impl Deref for Encoded {
35    type Target = String;
36    fn deref(&self) -> &Self::Target {
37        self.value()
38    }
39}
40
41impl Encoder for String {
42    fn encode(&self) -> Result<Encoded> {
43        Ok(Encoded(
44            b58m::encode_check(self.as_bytes()).map_err(|_| Error::Encode)?,
45        ))
46    }
47}
48
49impl Decoder for String {
50    fn from_encoded(encoded: &Encoded) -> Result<String> {
51        let d = Vec::from_encoded(encoded)?;
52        String::from_utf8(d).map_err(|_| Error::Decode)
53    }
54}
55
56impl Encoder for &str {
57    fn encode(&self) -> Result<Encoded> {
58        self.as_bytes().encode()
59    }
60}
61
62impl Encoder for &[u8] {
63    fn encode(&self) -> Result<Encoded> {
64        Ok(Encoded(
65            b58m::encode_check(self).map_err(|_| Error::Encode)?,
66        ))
67    }
68}
69
70impl Encoder for Vec<u8> {
71    fn encode(&self) -> Result<Encoded> {
72        Ok(Encoded(
73            b58m::encode_check(self).map_err(|_| Error::Encode)?,
74        ))
75    }
76}
77
78impl Encoder for Bytes {
79    fn encode(&self) -> Result<Encoded> {
80        self.as_ref().encode()
81    }
82}
83
84impl Decoder for Vec<u8> {
85    fn from_encoded(encoded: &Encoded) -> Result<Self> {
86        b58m::decode_check(encoded.deref()).map_err(|_| Error::Decode)
87    }
88}
89
90impl Decoder for Bytes {
91    fn from_encoded(encoded: &Encoded) -> Result<Self> {
92        let d = Vec::from_encoded(encoded)?;
93        Ok(Bytes::from(d))
94    }
95}
96
97#[allow(clippy::to_string_trait_impl)]
98impl ToString for Encoded {
99    fn to_string(&self) -> String {
100        self.deref().to_owned()
101    }
102}
103
104impl From<String> for Encoded {
105    fn from(v: String) -> Self {
106        Self(v)
107    }
108}
109
110impl From<&str> for Encoded {
111    fn from(v: &str) -> Self {
112        Self(v.to_owned())
113    }
114}
115
116impl From<Encoded> for Vec<u8> {
117    fn from(a: Encoded) -> Self {
118        a.to_string().as_bytes().to_vec()
119    }
120}
121
122impl TryFrom<Vec<u8>> for Encoded {
123    type Error = Error;
124    fn try_from(a: Vec<u8>) -> Result<Self> {
125        let s: String = String::from_utf8(a)?;
126        Ok(s.into())
127    }
128}
129
130impl Encoded {
131    /// Create an [`Encoded`] value from a string that is already encoded.
132    pub fn from_encoded_str(str: &str) -> Self {
133        Self(str.to_owned())
134    }
135
136    /// Decode this value into a target type implementing [`Decoder`].
137    pub fn decode<T>(&self) -> Result<T>
138    where T: Decoder {
139        T::from_encoded(self)
140    }
141}
142
143#[cfg(test)]
144mod test_encoder;