pub const BITCOIN: Base58 =
Base58::new_unchecked(*b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
pub const RIPPLE: Base58 =
Base58::new_unchecked(*b"rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz");
pub const FLICKR: Base58 =
Base58::new_unchecked(*b"123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ");
pub const MONERO: Base58 =
Base58::new_unchecked(*b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
pub const IPFS: Base58 =
Base58::new_unchecked(*b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
const DECODE_MAP_INITIALIZE: [u8; 128] = [255; 128];
pub const BASE: usize = 58;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Error {
DuplicateCharacter {
character: u8,
first: usize,
second: usize,
},
InvalidCharacter(u8),
}
impl core::fmt::Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::DuplicateCharacter {
character,
first,
second,
} => write!(
f,
"encoding/base58: duplicate character `{}` at index {} and {}",
*character as char, first, second
),
Self::InvalidCharacter(c) => write!(
f,
"encoding/base58: invalid character `{}` is not an ASCII character",
*c as char
),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct Base58 {
encode: [u8; BASE],
decode: [u8; 128],
}
impl Base58 {
pub const fn new(encoder: [u8; BASE]) -> Result<Self, Error> {
let mut decode = DECODE_MAP_INITIALIZE;
let mut idx = 0;
while idx < encoder.len() {
let c = encoder[idx];
if c >= 128 {
return Err(Error::InvalidCharacter(c));
}
if decode[c as usize] != 255 {
return Err(Error::DuplicateCharacter {
character: c,
first: decode[c as usize] as usize,
second: idx,
});
}
decode[c as usize] = idx as u8;
idx += 1;
}
Ok(Self {
encode: encoder,
decode,
})
}
pub const fn new_unchecked(encoder: [u8; 58]) -> Self {
let mut decode = DECODE_MAP_INITIALIZE;
let mut idx = 0;
while idx < encoder.len() {
let c = encoder[idx];
if c >= 128 {
panic!("encoding/base58: character is not an ASCII character");
}
if decode[c as usize] != 255 {
panic!("encoding/base58: duplicate character is not allowed");
}
decode[c as usize] = idx as u8;
idx += 1;
}
Self {
encode: encoder,
decode,
}
}
#[inline]
pub fn encode(&self, src: &[u8], dst: &mut [u8]) {
let mut index = 0;
for &val in src {
let mut carry = val as usize;
for byte in &mut dst[..index] {
carry += (*byte as usize) << 8;
*byte = (carry % BASE) as u8;
carry /= BASE;
}
while carry > 0 {
dst[index] = (carry % BASE) as u8;
index += 1;
carry /= BASE;
}
}
for _ in src.iter().take_while(|v| **v == 0) {
dst[index] = 0;
index += 1;
}
for val in &mut dst[..index] {
*val = self.encode[*val as usize];
}
dst[..index].reverse();
}
#[inline]
pub const fn max_encoded_len(n: usize) -> usize {
n + (n + 1) / 2
}
#[inline]
pub const fn max_decoded_len(n: usize) -> usize {
((2 * n) - 1) / 3 + 1
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode() {}
}