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
let decode_table = lazy (
let alphabet =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" in
let table = Array.make 256 0xff in
String.iteri (fun i ch -> table.(Char.code ch) <- i) alphabet;
table
)
let (.%[]) = String.unsafe_get
let (.%()) = Array.unsafe_get
external bytes_unsafe_set_int8 : bytes -> int -> int -> unit = "%bytes_unsafe_set"
let[@inline] count_len str =
let i = ref (String.length str - 1) in
while !i >= 0 && str.%[!i] = '=' do decr i done;
!i + 1
exception Error of string
let[@inline] error descr = raise (Error descr)
let decode input =
let table = Lazy.force decode_table in
let real_len = count_len input in
let padding = (4 - real_len land 3) land 3 in
if padding = 3 then
error "Invalid base64: a padding of 3 sextets is invalid";
let out_len = (real_len + padding) / 4 * 3 - padding in
let out = Bytes.create out_len in
let i = ref 0 and j = ref 0 in
while !i < real_len do
let ch1 = input.%[!i] in
let ch2 = input.%[!i + 1] in
let sextet1 = table.%(Char.code ch1) in
let sextet2 = table.%(Char.code ch2) in
if sextet1 = 0xff || sextet2 = 0xff then error "Invalid base64 character";
let octet1 = sextet1 lsl 2
lor sextet2 lsr 4 in
bytes_unsafe_set_int8 out !j octet1;
incr j;
if !i + 2 < real_len then begin
let ch3 = input.%[!i + 2] in
let sextet3 = table.%(Char.code ch3) in
if sextet3 = 0xff then error "Invalid base64 character";
let octet2 = (sextet2 land 0b1111) lsl 4
lor sextet3 lsr 2 in
bytes_unsafe_set_int8 out !j octet2;
incr j;
if !i + 3 < real_len then begin
let ch4 = input.%[!i + 3] in
let sextet4 = table.%(Char.code ch4) in
if sextet4 = 0xff then error "Invalid base64 character";
let octet3 = (sextet3 land 0b11) lsl 6
lor sextet4 in
bytes_unsafe_set_int8 out !j octet3;
incr j
end
end;
i := !i + 4
done;
assert (!j = Bytes.length out);
out