2021-02-22 14:32:45 +01:00
|
|
|
{ depot, lib, ... }:
|
|
|
|
|
|
|
|
let
|
|
|
|
|
|
|
|
inherit (depot.users.sterni.nix)
|
|
|
|
string
|
2023-08-05 15:39:56 +02:00
|
|
|
num
|
2021-02-22 14:32:45 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
inherit (builtins)
|
|
|
|
bitOr
|
|
|
|
bitAnd
|
|
|
|
bitXor
|
|
|
|
;
|
|
|
|
|
|
|
|
exp = base: pow:
|
|
|
|
if pow > 0
|
|
|
|
then base * (exp base (pow - 1))
|
|
|
|
else if pow < 0
|
2023-08-05 15:39:56 +02:00
|
|
|
then 1.0 / exp base (num.abs pow)
|
2021-02-22 14:32:45 +01:00
|
|
|
else 1;
|
|
|
|
|
|
|
|
bitShiftR = bit: count:
|
|
|
|
if count == 0
|
|
|
|
then bit
|
2023-08-05 17:47:22 +02:00
|
|
|
else (bitShiftR bit (count - 1)) / 2;
|
2021-02-22 14:32:45 +01:00
|
|
|
|
|
|
|
bitShiftL = bit: count:
|
|
|
|
if count == 0
|
|
|
|
then bit
|
|
|
|
else 2 * (bitShiftL bit (count - 1));
|
|
|
|
|
|
|
|
hexdigits = "0123456789ABCDEF";
|
|
|
|
|
|
|
|
toHex = int:
|
|
|
|
let
|
|
|
|
go = i:
|
|
|
|
if i == 0
|
|
|
|
then ""
|
|
|
|
else go (bitShiftR i 4)
|
2022-01-30 17:06:58 +01:00
|
|
|
+ string.charAt (bitAnd i 15) hexdigits;
|
2021-02-22 14:32:45 +01:00
|
|
|
sign = lib.optionalString (int < 0) "-";
|
|
|
|
in
|
2022-01-30 17:06:58 +01:00
|
|
|
if int == 0
|
|
|
|
then "0"
|
2023-08-05 15:39:56 +02:00
|
|
|
else "${sign}${go (num.abs int)}";
|
2021-02-22 14:32:45 +01:00
|
|
|
|
|
|
|
fromHexMap = builtins.listToAttrs
|
|
|
|
(lib.imap0 (i: c: { name = c; value = i; })
|
|
|
|
(lib.stringToCharacters hexdigits));
|
|
|
|
|
|
|
|
fromHex = literal:
|
|
|
|
let
|
|
|
|
negative = string.charAt 0 literal == "-";
|
|
|
|
start = if negative then 1 else 0;
|
|
|
|
len = builtins.stringLength literal;
|
|
|
|
# reversed list of all digits
|
|
|
|
digits = builtins.genList
|
|
|
|
(i: string.charAt (len - 1 - i) literal)
|
|
|
|
(len - start);
|
|
|
|
parsed = builtins.foldl'
|
|
|
|
(v: d: {
|
|
|
|
val = v.val + (fromHexMap."${d}" * v.mul);
|
|
|
|
mul = v.mul * 16;
|
|
|
|
})
|
2022-01-30 17:06:58 +01:00
|
|
|
{ val = 0; mul = 1; }
|
|
|
|
digits;
|
2021-02-22 14:32:45 +01:00
|
|
|
in
|
2022-01-30 17:06:58 +01:00
|
|
|
if negative
|
|
|
|
then -parsed.val
|
|
|
|
else parsed.val;
|
2021-02-22 14:32:45 +01:00
|
|
|
|
|
|
|
# A nix integer is a 64bit signed integer
|
|
|
|
maxBound = 9223372036854775807;
|
|
|
|
|
|
|
|
# fun fact: -9223372036854775808 is the lower bound
|
|
|
|
# for a nix integer (as you would expect), but you can't
|
|
|
|
# use it as an integer literal or you'll be greeted with:
|
|
|
|
# error: invalid integer '9223372036854775808'
|
|
|
|
# This is because all int literals when parsing are
|
|
|
|
# positive, negative "literals" are positive literals
|
|
|
|
# which are preceded by the arithmetric negation operator.
|
|
|
|
minBound = -9223372036854775807 - 1;
|
|
|
|
|
|
|
|
odd = x: bitAnd x 1 == 1;
|
|
|
|
even = x: bitAnd x 1 == 0;
|
|
|
|
|
2023-08-05 17:47:22 +02:00
|
|
|
quot' = builtins.div; # no typecheck
|
|
|
|
rem = a: b:
|
|
|
|
assert builtins.isInt a && builtins.isInt b;
|
|
|
|
let res = quot' a b; in a - (res * b);
|
|
|
|
quot = a: b:
|
|
|
|
assert builtins.isInt a && builtins.isInt b;
|
|
|
|
quot' a b;
|
2021-02-22 14:32:45 +01:00
|
|
|
|
2022-01-30 17:06:58 +01:00
|
|
|
in
|
|
|
|
{
|
2021-02-22 14:32:45 +01:00
|
|
|
inherit
|
|
|
|
maxBound
|
|
|
|
minBound
|
|
|
|
exp
|
|
|
|
odd
|
|
|
|
even
|
2023-08-05 17:47:22 +02:00
|
|
|
quot
|
|
|
|
rem
|
2021-02-22 14:32:45 +01:00
|
|
|
bitShiftR
|
|
|
|
bitShiftL
|
|
|
|
bitOr
|
|
|
|
bitAnd
|
|
|
|
bitXor
|
|
|
|
toHex
|
|
|
|
fromHex
|
|
|
|
;
|
|
|
|
}
|