2021-02-22 14:32:45 +01:00
|
|
|
{ depot, lib, ... }:
|
|
|
|
|
|
|
|
let
|
|
|
|
|
|
|
|
inherit (depot.users.sterni.nix)
|
|
|
|
char
|
|
|
|
int
|
|
|
|
string
|
2021-04-01 11:15:57 +02:00
|
|
|
flow
|
2021-02-22 14:32:45 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2021-04-01 11:15:57 +02:00
|
|
|
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;
|
|
|
|
|
2021-02-22 14:32:45 +01:00
|
|
|
in {
|
|
|
|
inherit
|
|
|
|
encode
|
2021-04-01 11:15:57 +02:00
|
|
|
decode
|
2021-02-22 14:32:45 +01:00
|
|
|
;
|
|
|
|
}
|