Skip to content

Instantly share code, notes, and snippets.

@jdh30
Created November 21, 2022 16:39
Show Gist options
  • Save jdh30/4067b4e2920d051ffa1b937fc0b815c7 to your computer and use it in GitHub Desktop.
Save jdh30/4067b4e2920d051ffa1b937fc0b815c7 to your computer and use it in GitHub Desktop.
Base64 encoder
type State =
| S0
| S1 Number
| S2 Number
let charOfNumber n =
if n<26 then Char.ofNumber(n+65)
else if n<52 then Char.ofNumber(n-26+97)
else if n<62 then Char.ofNumber(n-52+48)
else if n=62 then '+' else '/'
let encode bytes =
let append = String.Unsafe.appendChar in
let emit(s, bits) = charOfNumber bits @ append s in
let div(p, q) = floor(p/q) in
Array.fold
[ (s, S0), byte -> emit(s, div(byte, 4)), mod(byte, 4) @ S1
| (s, S1 b), byte -> emit(s, b*16+div(byte,16)), mod(byte, 16) @ S2
| (s, S2 b), byte -> emit(emit(s, b*4+mod(byte/64, 4)), mod(byte, 64)), S0 ]
("", S0) bytes
@ [ s, S0 -> s
| s, S1 b -> append (append (emit(s, b*16)) '=') '='
| s, S2 b -> append (emit(s, b*4)) '=' ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment