nixos-config/lib/trivial.nix

191 lines
4.4 KiB
Nix
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ pkgs, lib, self }:
rec {
/* Force a numerical value to be a floating value.
Example:
toFloat 5698
=> 5698.0
toFloat 9859.55
=> 9859.55
*/
toFloat = x: x / 1.0;
/* 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)
(lib.mapAttrsToList lib.nameValuePair attrs);
/* Filters and groups the attribute set into two separate attribute where it
either accepted or denied from a given predicate function.
Example:
filterAttrs' (n: v: v == 4) { a = 4; b = 2; c = 6; }
=> { ok = { a = 4; }; notOk = { b = 2; c = 6; }; }
*/
filterAttrs' = f: attrs:
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;
/* 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;
};
in prefixes.${c};
/* Gives the multiplier for the metric units.
Example:
metricPrefixMultiplier "M"
=> 1000000
metricPrefixMultiplier "G"
=> 1000000000
*/
metricPrefixMultiplier = c: self.math.pow 10 (SIPrefixExponent c);
/* 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;
};
in prefixes.${c};
/* 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¹²
*/
binaryPrefixMultiplier = c: self.math.pow 2 (binaryPrefixExponent c);
/* 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
matches =
builtins.match "([[:digit:]]+)[[:space:]]*([[:alpha:]]{1})(i?[B|b])"
str;
numeral = lib.toInt (lib.lists.head matches);
prefix = lib.lists.elemAt matches 1;
suffix = lib.lists.last matches;
isBinary = lib.hasPrefix "i" suffix;
multiplier = let
multiplierFn =
if isBinary then binaryPrefixMultiplier else metricPrefixMultiplier;
in multiplierFn prefix;
bitDivider = if lib.hasSuffix "b" suffix then 8 else 1;
in numeral * multiplier / bitDivider;
/* Given an attrset of unit size object, return the size in bytes.
Example:
unitsToInt { size = 4; prefix = "G"; type = "binary"; }
=> 4294967296
unitsToInt { size = 4; prefix = "G"; type = "metric"; }
=> 4000000000
*/
unitsToInt = { size, prefix, type ? "binary" }:
let
multiplierFn = if type == "binary" then
binaryPrefixMultiplier
else if type == "metric" then
metricPrefixMultiplier
else
builtins.throw "no multiplier type ${type}";
in size * (multiplierFn prefix);
}