diff options
Diffstat (limited to 'users/sterni/nix/url/default.nix')
-rw-r--r-- | users/sterni/nix/url/default.nix | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/users/sterni/nix/url/default.nix b/users/sterni/nix/url/default.nix new file mode 100644 index 000000000000..4a401873a1f2 --- /dev/null +++ b/users/sterni/nix/url/default.nix @@ -0,0 +1,100 @@ +{ depot, lib, ... }: + +let + + inherit (depot.users.sterni.nix) + char + int + string + flow + ; + + reserved = c: builtins.elem c [ + "!" + "#" + "$" + "&" + "'" + "(" + ")" + "*" + "+" + "," + "/" + ":" + ";" + "=" + "?" + "@" + "[" + "]" + ]; + + unreserved = c: char.asciiAlphaNum c + || builtins.elem c [ "-" "_" "." "~" ]; + + percentEncode = c: + if unreserved c + then c + else "%" + (string.fit + { + width = 2; + char = "0"; + side = "left"; + } + (int.toHex (char.ord c))); + + encode = { leaveReserved ? false }: s: + let + chars = lib.stringToCharacters s; + tr = c: + if leaveReserved && reserved c + then c + else percentEncode c; + in + lib.concatStrings (builtins.map tr chars); + + decode = s: + let + tokens = builtins.split "%" s; + decodeStep = + { result ? "" + , inPercent ? false + }: s: + flow.cond [ + [ + (builtins.isList s) + { + inherit result; + inPercent = true; + } + ] + [ + inPercent + { + inPercent = false; + # first two characters came after an % + # the rest is the string until the next % + result = result + + char.chr (int.fromHex (string.take 2 s)) + + (string.drop 2 s); + } + ] + [ + (!inPercent) + { + result = result + s; + } + ] + ]; + + in + (builtins.foldl' decodeStep { } tokens).result; + +in +{ + inherit + encode + decode + ; +} |