v2 / vlib / encoding / base58 / alphabet.v
66 lines · 54 sloc · 1.61 KB · 51f4d99399f88da0abf4d48d2317eaa8f3e630f5
Raw
1module base58
2
3const impossible = 'this should never happen'
4
5pub const btc_alphabet = new_alphabet('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz') or {
6 panic(impossible)
7}
8
9pub const flickr_alphabet = new_alphabet('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ') or {
10 panic(impossible)
11}
12
13pub const ripple_alphabet = new_alphabet('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz') or {
14 panic(impossible)
15}
16
17// alphabets is a map of common base58 alphabets:
18pub const alphabets = {
19 'btc': btc_alphabet
20 'flickr': flickr_alphabet
21 'ripple': ripple_alphabet
22}
23
24// Alphabet is the series of characters that an input
25// will be encoded to and a decode table.
26struct Alphabet {
27mut:
28 decode []i8 = []i8{len: 128, init: -1}
29 encode []u8 = []u8{len: 58}
30}
31
32// str returns an Alphabet encode table byte array as a string
33pub fn (alphabet Alphabet) str() string {
34 // i guess i had a brain fart here. Why would I actually use this code?!
35 // mut str := []u8{}
36 // for entry in alphabet.encode {
37 // str << entry
38 // }
39 // return str.bytestr()
40 return alphabet.encode.bytestr()
41}
42
43// new_alphabet instantiates an Alphabet object based on
44// the provided characters
45pub fn new_alphabet(str string) !Alphabet {
46 if str.len != 58 {
47 return error(@MOD + '.' + @FN + ': string must be 58 characters in length')
48 }
49
50 mut ret := Alphabet{}
51 copy(mut ret.encode, str.bytes())
52
53 mut distinct := 0
54 for i, b in ret.encode {
55 if ret.decode[b] == -1 {
56 distinct++
57 }
58 ret.decode[b] = i8(i)
59 }
60
61 if distinct != 58 {
62 return error(@MOD + '.' + @FN + ': string must not contain repeating characters')
63 }
64
65 return ret
66}
67