-
Notifications
You must be signed in to change notification settings - Fork 0
/
base32.gr
83 lines (70 loc) · 2.2 KB
/
base32.gr
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
import String, { explode, implode, UTF8 } from "string"
import { length, slice, getInt8U } from "bytes"
import { shrU, shl, lor, gtU, sub, toNumber } from "int32"
import { ceil } from "number"
import Array from "array"
export enum Encoding {
ZBase32,
Base32Hex,
Crockford,
Base32,
}
let zBase32 = explode("ybndrfg8ejkmcpqxot1uwisza345h769")
let base32Hex = explode("0123456789ABCDEFGHIJKLMNOPQRSTUV")
let crockford = explode("0123456789ABCDEFGHJKMNPQRSTVWXYZ")
let base32 = explode("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")
let (++) = (a, b) => String.concat(a, b)
let (>>) = (intA, intB) => shrU(intA, intB)
let (<<) = (intA, intB) => shl(intA, intB)
let (|) = (intA, intB) => lor(intA, intB)
let (>) = (intA, intB) => gtU(intA, intB)
let (-) = (intA, intB) => sub(intA, intB)
export let forEachByte = (fn, bytes) => {
for (let mut i = 0; i < length(bytes); i += 1) {
let byte = slice(i, 1, bytes)
fn(byte, i)
}
}
export let forEachInt8U = (fn, bytes) => {
for (let mut i = 0; i < length(bytes); i += 1) {
let int = getInt8U(i, bytes)
fn(int, i)
}
}
export let encodeBytes = (alphabet, padding, bytes) => {
let mut shift = 3l
let mut carry = 0l
let mut index = 0l
let resLength = ceil(length(bytes) / 5) * 8
let mut result = Array.make(resLength, padding)
let mut j = 0
let process = (byte, i) => {
index = carry | byte >> shift
result[j] = alphabet[toNumber(index) & 0x1f]
j += 1
if (shift > 5l) {
shift -= 5l
index = byte >> shift
result[j] = alphabet[toNumber(index) & 0x1f]
j += 1
}
shift = 5l - shift
carry = byte << shift
shift = 8l - shift
if (shift != 3l) {
result[j] = alphabet[toNumber(carry) & 0x1f]
}
}
forEachInt8U(process, bytes)
match (padding) {
'🌾' => implode(Array.slice(0, j + 1, result)),
_ => implode(result),
}
}
export let encode = (encoding: Encoding, string) =>
match (encoding) {
ZBase32 => encodeBytes(zBase32, '🌾', String.encode(string, UTF8)),
Base32Hex => encodeBytes(base32Hex, '=', String.encode(string, UTF8)),
Crockford => encodeBytes(crockford, '🌾', String.encode(string, UTF8)),
Base32 => encodeBytes(base32, '=', String.encode(string, UTF8)),
}