1use rust_base58::{ToBase58, FromBase58};
2
3const TO_SIZE: usize = 8;
4const FROM_SIZE: usize = 11;
5
6#[derive(Debug)]
7pub enum Base58Error {
8 InvalidChunkData,
9 InvalidChunkLength(usize),
10}
11
12pub fn to_base58(bytes: Vec<u8>) -> Result<String, Base58Error> {
13 let mut base58 = String::new();
14 for chunk in bytes.as_slice().chunks(TO_SIZE) {
15 let mut part = chunk.to_base58();
16 let exp_len = match chunk.len() {
17 8 => 11,
18 6 => 9,
19 5 => 7,
20 len => return Err(Base58Error::InvalidChunkLength(len)),
21 };
22 let missing = exp_len - part.len();
23 if missing > 0 {
24 part.insert_str(0, &"11111111111"[..missing]);
25 }
26 base58.push_str(&part);
27 }
28 Ok(base58)
29}
30
31pub fn from_base58(base58: String) -> Result<Vec<u8>, Base58Error> {
32 let mut extracted: Vec<u8> = vec![];
33 let bytes = base58.as_bytes();
34 for chunk in bytes.chunks(FROM_SIZE) {
35 let idx = chunk.iter().position(|&c| c != b'1')
36 .ok_or(Base58Error::InvalidChunkData)?;
37 let part = std::str::from_utf8(&chunk[idx..]).unwrap();
38 let exp_len = match chunk.len() {
39 11 => 8,
40 9 => 6,
41 7 => 5,
42 len => return Err(Base58Error::InvalidChunkLength(len)),
43 };
44
45 let mut base58_chunk:Vec<u8> = part.from_base58().unwrap();
46 if exp_len != base58_chunk.len() {
47 return Err(Base58Error::InvalidChunkLength(chunk.len()));
48 }
49 extracted.append(&mut base58_chunk);
50 }
51 Ok(extracted)
52}
53
54#[cfg(test)]
55mod tests {
56 use super::{to_base58, from_base58};
57 #[test]
58 fn it_works() {
59 let original_data = "BMv8aSohtktbARXdSBrVRkgJhyoNBmxmjHWJaVhFx31gjHRqzxXH5G7DRy6uPdPJhkdrfNpF1K5Di3Cfr78ZuEA3PiaUPG9";
60 let expected_decoded = vec![
61 0x3d, 0xf1, 0x2e, 0x7, 0xad, 0x81, 0xf0, 0x9d, 0xcc, 0x3e, 0x78,
62 0x7b, 0x68, 0xc6, 0xdc, 0x73, 0xea, 0xfd, 0xae, 0xa6, 0x43, 0x33,
63 0x6d, 0xfe, 0x62, 0xad, 0xa4, 0xab, 0x3c, 0xc4, 0x9d, 0x67, 0xfc,
64 0xcb, 0x86, 0x6f, 0xf0, 0xba, 0xc3, 0xfc, 0x4a, 0x51, 0x22, 0xa,
65 0x47, 0x82, 0xcb, 0x8f, 0xdc, 0x59, 0x5a, 0x56, 0xba, 0x90, 0xf,
66 0x41, 0xd, 0x28, 0xfe, 0x70, 0xb8, 0x4d, 0x8a, 0x60, 0xc9, 0x5a,
67 0x22, 0xb5, 0xee
68 ];
69
70 let decoded = from_base58(String::from(original_data))
71 .expect("Error decoding from base 58");
72 assert_eq!(expected_decoded, decoded);
73
74 let encoded = to_base58(expected_decoded)
75 .expect("Error encoding to base 58");
76 assert_eq!(encoded, original_data);
77 }
78}