Skip to content

Instantly share code, notes, and snippets.

@manveru
Created September 6, 2023 03:19
Show Gist options
  • Save manveru/74eb41d850bc146b7e78c4cb059507e2 to your computer and use it in GitHub Desktop.
Save manveru/74eb41d850bc146b7e78c4cb059507e2 to your computer and use it in GitHub Desktop.
Encode to base 64 in pure Nix
{lib, ...}: {
toBase64 = text: let
inherit (lib) sublist mod stringToCharacters concatMapStrings;
inherit (lib.strings) charToInt;
inherit (builtins) substring foldl' genList elemAt length concatStringsSep stringLength;
lookup = stringToCharacters "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
sliceN = size: list: n: sublist (n * size) size list;
pows = [(64 * 64 * 64) (64 * 64) 64 1];
intSextets = i: map (j: mod (i / j) 64) pows;
compose = f: g: x: f (g x);
intToChar = elemAt lookup;
convertTripletInt = sliceInt: concatMapStrings intToChar (intSextets sliceInt);
sliceToInt = foldl' (acc: val: acc * 256 + val) 0;
convertTriplet = compose convertTripletInt sliceToInt;
join = concatStringsSep "";
convertLastSlice = slice: let
len = length slice;
in
if len == 1
then (substring 0 2 (convertTripletInt ((sliceToInt slice) * 256 * 256))) + "=="
else if len == 2
then (substring 0 3 (convertTripletInt ((sliceToInt slice) * 256))) + "="
else "";
len = stringLength text;
nFullSlices = len / 3;
bytes = map charToInt (stringToCharacters text);
tripletAt = sliceN 3 bytes;
head = genList (compose convertTriplet tripletAt) nFullSlices;
tail = convertLastSlice (tripletAt nFullSlices);
in
join (head ++ [tail]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment