2024-03-03 08:39:32 +00:00
|
|
|
|
{ pkgs, lib, self }:
|
|
|
|
|
|
2024-09-12 07:49:56 +00:00
|
|
|
|
rec {
|
2024-09-13 09:07:27 +00:00
|
|
|
|
/* Force a numerical value to be a floating value.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
toFloat 5698
|
|
|
|
|
=> 5698.0
|
|
|
|
|
|
|
|
|
|
toFloat 9859.55
|
|
|
|
|
=> 9859.55
|
|
|
|
|
*/
|
|
|
|
|
toFloat = x: x / 1.0;
|
|
|
|
|
|
2024-03-03 08:39:32 +00:00
|
|
|
|
/* Count the attributes with the given predicate.
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
countAttrs (name: value: value) { d = true; f = true; a = false; }
|
|
|
|
|
=> 2
|
|
|
|
|
|
|
|
|
|
countAttrs (name: value: value.enable) { d = { enable = true; }; f = { enable = false; package = [ ]; }; }
|
|
|
|
|
=> 1
|
|
|
|
|
*/
|
|
|
|
|
countAttrs = pred: attrs:
|
|
|
|
|
lib.count (attr: pred attr.name attr.value)
|
2025-01-12 09:57:14 +00:00
|
|
|
|
(lib.mapAttrsToList lib.nameValuePair attrs);
|
2024-03-03 08:39:32 +00:00
|
|
|
|
|
2024-08-08 03:19:03 +00:00
|
|
|
|
/* Filters and groups the attribute set into two separate attribute where it
|
|
|
|
|
either accepted or denied from a given predicate function.
|
2024-03-03 08:39:32 +00:00
|
|
|
|
|
|
|
|
|
Example:
|
2024-06-14 15:45:07 +00:00
|
|
|
|
filterAttrs' (n: v: v == 4) { a = 4; b = 2; c = 6; }
|
2024-08-08 03:19:03 +00:00
|
|
|
|
=> { ok = { a = 4; }; notOk = { b = 2; c = 6; }; }
|
2024-03-03 08:39:32 +00:00
|
|
|
|
*/
|
2024-08-08 03:19:03 +00:00
|
|
|
|
filterAttrs' = f: attrs:
|
2025-01-12 09:57:14 +00:00
|
|
|
|
lib.foldlAttrs (acc: name: value:
|
|
|
|
|
let isOk = f name value;
|
|
|
|
|
in {
|
|
|
|
|
ok = acc.ok // lib.optionalAttrs isOk { ${name} = value; };
|
|
|
|
|
notOk = acc.notOk // lib.optionalAttrs (!isOk) { ${name} = value; };
|
|
|
|
|
}) {
|
|
|
|
|
ok = { };
|
|
|
|
|
notOk = { };
|
|
|
|
|
} attrs;
|
2024-09-12 07:49:56 +00:00
|
|
|
|
|
|
|
|
|
/* Convenient function for converting bits to bytes.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
bitsToBytes 1600
|
|
|
|
|
=> 200
|
|
|
|
|
*/
|
|
|
|
|
bitsToBytes = x: x / 8.0;
|
|
|
|
|
|
|
|
|
|
/* Gives the exponent with the associated SI prefix.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
SIPrefixExponent "M"
|
|
|
|
|
=> 6
|
|
|
|
|
|
|
|
|
|
SIPrefixExponent "Q"
|
|
|
|
|
=> 30
|
|
|
|
|
*/
|
|
|
|
|
SIPrefixExponent = c:
|
|
|
|
|
let
|
|
|
|
|
prefixes = {
|
|
|
|
|
Q = 30;
|
|
|
|
|
R = 27;
|
|
|
|
|
Y = 24;
|
|
|
|
|
Z = 21;
|
|
|
|
|
E = 18;
|
|
|
|
|
P = 15;
|
|
|
|
|
T = 12;
|
|
|
|
|
G = 9;
|
|
|
|
|
M = 6;
|
|
|
|
|
k = 3;
|
|
|
|
|
h = 2;
|
|
|
|
|
da = 1;
|
|
|
|
|
d = -1;
|
|
|
|
|
c = -2;
|
|
|
|
|
m = -3;
|
|
|
|
|
"μ" = -6;
|
|
|
|
|
n = -9;
|
|
|
|
|
p = -12;
|
|
|
|
|
f = -15;
|
|
|
|
|
a = -18;
|
|
|
|
|
z = -21;
|
|
|
|
|
y = -24;
|
|
|
|
|
r = -27;
|
|
|
|
|
q = -30;
|
|
|
|
|
};
|
2025-01-12 09:57:14 +00:00
|
|
|
|
in prefixes.${c};
|
2024-09-12 07:49:56 +00:00
|
|
|
|
|
|
|
|
|
/* Gives the multiplier for the metric units.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
metricPrefixMultiplier "M"
|
|
|
|
|
=> 1000000
|
|
|
|
|
|
|
|
|
|
metricPrefixMultiplier "G"
|
|
|
|
|
=> 1000000000
|
|
|
|
|
*/
|
2025-01-12 09:57:14 +00:00
|
|
|
|
metricPrefixMultiplier = c: self.math.pow 10 (SIPrefixExponent c);
|
2024-09-12 07:49:56 +00:00
|
|
|
|
|
|
|
|
|
/* Gives the exponent with the associated binary prefix.
|
|
|
|
|
|
|
|
|
|
As an implementation detail, we don't follow the proper IEC unit prefixes
|
|
|
|
|
and instead mapping this to the SI prefix for convenience.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
SIPrefixExponent "M"
|
|
|
|
|
=> 6
|
|
|
|
|
|
|
|
|
|
SIPrefixExponent "Q"
|
|
|
|
|
=> 30
|
|
|
|
|
*/
|
|
|
|
|
binaryPrefixExponent = c:
|
|
|
|
|
let
|
|
|
|
|
prefixes = {
|
|
|
|
|
Y = 80;
|
|
|
|
|
Z = 70;
|
|
|
|
|
E = 60;
|
|
|
|
|
P = 50;
|
|
|
|
|
T = 40;
|
|
|
|
|
G = 30;
|
|
|
|
|
M = 20;
|
|
|
|
|
K = 10;
|
|
|
|
|
};
|
2025-01-12 09:57:14 +00:00
|
|
|
|
in prefixes.${c};
|
2024-09-12 07:49:56 +00:00
|
|
|
|
|
|
|
|
|
/* Gives the multiplier for the given byte unit. Essentially returns the
|
|
|
|
|
value in number of bytes.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
binaryPrefixMultiplier "M"
|
|
|
|
|
=> 1048576
|
|
|
|
|
|
|
|
|
|
binaryPrefixMultiplier "G"
|
|
|
|
|
=> 1.099511628×10¹²
|
|
|
|
|
*/
|
2025-01-12 09:57:14 +00:00
|
|
|
|
binaryPrefixMultiplier = c: self.math.pow 2 (binaryPrefixExponent c);
|
2024-09-13 09:07:27 +00:00
|
|
|
|
|
|
|
|
|
/* Parse the given string containing the size into its appropriate value.
|
|
|
|
|
Returns the value in number of bytes.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
parseBytesSizeIntoInt "4GiB"
|
|
|
|
|
=> 4294967296
|
|
|
|
|
|
|
|
|
|
parseBytesSizeIntoInt "2 MB"
|
|
|
|
|
=> 2000000
|
|
|
|
|
|
|
|
|
|
parseBytesSizeIntoInt "2 Mb"
|
|
|
|
|
=> 250000
|
|
|
|
|
*/
|
|
|
|
|
parseBytesSizeIntoInt = str:
|
|
|
|
|
let
|
2025-01-12 09:57:14 +00:00
|
|
|
|
matches =
|
|
|
|
|
builtins.match "([[:digit:]]+)[[:space:]]*([[:alpha:]]{1})(i?[B|b])"
|
|
|
|
|
str;
|
2024-09-13 09:07:27 +00:00
|
|
|
|
numeral = lib.toInt (lib.lists.head matches);
|
|
|
|
|
prefix = lib.lists.elemAt matches 1;
|
|
|
|
|
suffix = lib.lists.last matches;
|
|
|
|
|
isBinary = lib.hasPrefix "i" suffix;
|
|
|
|
|
|
2025-01-12 09:57:14 +00:00
|
|
|
|
multiplier = let
|
|
|
|
|
multiplierFn =
|
|
|
|
|
if isBinary then binaryPrefixMultiplier else metricPrefixMultiplier;
|
|
|
|
|
in multiplierFn prefix;
|
2024-09-13 09:07:27 +00:00
|
|
|
|
bitDivider = if lib.hasSuffix "b" suffix then 8 else 1;
|
2025-01-12 09:57:14 +00:00
|
|
|
|
in numeral * multiplier / bitDivider;
|
2024-09-13 09:07:27 +00:00
|
|
|
|
|
2025-01-12 09:57:14 +00:00
|
|
|
|
/* Given an attrset of unit size object, return the size in bytes.
|
2024-09-13 09:07:27 +00:00
|
|
|
|
|
2025-01-12 09:57:14 +00:00
|
|
|
|
Example:
|
|
|
|
|
unitsToInt { size = 4; prefix = "G"; type = "binary"; }
|
|
|
|
|
=> 4294967296
|
2024-09-13 09:07:27 +00:00
|
|
|
|
|
2025-01-12 09:57:14 +00:00
|
|
|
|
unitsToInt { size = 4; prefix = "G"; type = "metric"; }
|
|
|
|
|
=> 4000000000
|
2024-09-13 09:07:27 +00:00
|
|
|
|
*/
|
|
|
|
|
unitsToInt = { size, prefix, type ? "binary" }:
|
|
|
|
|
let
|
2025-01-12 09:57:14 +00:00
|
|
|
|
multiplierFn = if type == "binary" then
|
|
|
|
|
binaryPrefixMultiplier
|
|
|
|
|
else if type == "metric" then
|
|
|
|
|
metricPrefixMultiplier
|
|
|
|
|
else
|
|
|
|
|
builtins.throw "no multiplier type ${type}";
|
|
|
|
|
in size * (multiplierFn prefix);
|
2024-03-03 08:39:32 +00:00
|
|
|
|
}
|