1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use std::ops::Deref;

use base58_monero as b58m;
use bytes::Bytes;
use serde::Deserialize;
use serde::Serialize;

use crate::error::Error;
use crate::error::Result;

pub trait Encoder {
    fn encode(&self) -> Result<Encoded>;
}

pub trait Decoder: Sized {
    fn from_encoded(encoded: &Encoded) -> Result<Self>;
}

#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq, Hash)]
pub struct Encoded(String);

impl Encoded {
    pub fn value(&self) -> &String {
        &self.0
    }
}

impl Deref for Encoded {
    type Target = String;
    fn deref(&self) -> &Self::Target {
        self.value()
    }
}

impl Encoder for String {
    fn encode(&self) -> Result<Encoded> {
        Ok(Encoded(
            b58m::encode_check(self.as_bytes()).map_err(|_| Error::Encode)?,
        ))
    }
}

impl Decoder for String {
    fn from_encoded(encoded: &Encoded) -> Result<String> {
        let d = Vec::from_encoded(encoded)?;
        String::from_utf8(d).map_err(|_| Error::Decode)
    }
}

impl Encoder for &str {
    fn encode(&self) -> Result<Encoded> {
        self.as_bytes().encode()
    }
}

impl Encoder for &[u8] {
    fn encode(&self) -> Result<Encoded> {
        Ok(Encoded(
            b58m::encode_check(self).map_err(|_| Error::Encode)?,
        ))
    }
}

impl Encoder for Vec<u8> {
    fn encode(&self) -> Result<Encoded> {
        Ok(Encoded(
            b58m::encode_check(self).map_err(|_| Error::Encode)?,
        ))
    }
}

impl Encoder for Bytes {
    fn encode(&self) -> Result<Encoded> {
        self.as_ref().encode()
    }
}

impl Decoder for Vec<u8> {
    fn from_encoded(encoded: &Encoded) -> Result<Self> {
        b58m::decode_check(encoded.deref()).map_err(|_| Error::Decode)
    }
}

impl Decoder for Bytes {
    fn from_encoded(encoded: &Encoded) -> Result<Self> {
        let d = Vec::from_encoded(encoded)?;
        Ok(Bytes::from(d))
    }
}

impl ToString for Encoded {
    fn to_string(&self) -> String {
        self.deref().to_owned()
    }
}

impl From<String> for Encoded {
    fn from(v: String) -> Self {
        Self(v)
    }
}

impl From<&str> for Encoded {
    fn from(v: &str) -> Self {
        Self(v.to_owned())
    }
}

impl From<Encoded> for Vec<u8> {
    fn from(a: Encoded) -> Self {
        a.to_string().as_bytes().to_vec()
    }
}

impl TryFrom<Vec<u8>> for Encoded {
    type Error = Error;
    fn try_from(a: Vec<u8>) -> Result<Self> {
        let s: String = String::from_utf8(a)?;
        Ok(s.into())
    }
}

impl Encoded {
    pub fn from_encoded_str(str: &str) -> Self {
        Self(str.to_owned())
    }

    pub fn decode<T>(&self) -> Result<T>
    where T: Decoder {
        T::from_encoded(self)
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_encode_decode() {
        let test1 = vec![1, 2, 3, 4];

        let encoded1 = test1.encode().unwrap();
        let result1: Vec<u8> = encoded1.decode().unwrap();
        assert_eq!(test1, result1);

        let test1 = test1.as_slice();
        let encoded1 = test1.encode().unwrap();
        let result1: Vec<u8> = encoded1.decode().unwrap();
        assert_eq!(test1, result1);

        let test2 = "abc";
        let encoded2 = test2.encode().unwrap();
        let result2: String = encoded2.decode().unwrap();
        assert_eq!(test2, result2);

        let test3 = String::from("abc");
        let encoded3 = test3.encode().unwrap();
        let result3: String = encoded3.decode().unwrap();
        assert_eq!(test3, result3);
    }

    #[test]
    fn test_from_encoded() {
        let source = [1u8; 32].to_vec();
        let encoded = source.encode().unwrap();
        let v = encoded.to_string();
        let v2 = Encoded::from_encoded_str(&v);
        assert_eq!(encoded, v2);
    }
}