nixos-config/lib/trivial.nix

327 lines
6.3 KiB
Nix
Raw 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.
# Arguments
x
: The (numerical) value to be converted.
# Type
```
toFloat :: Number -> Float
```
# Examples
```nix
toFloat 5698
=> 5698.0
toFloat 9859.55
=> 9859.55
```
*/
toFloat = x: x / 1.0;
/**
Count the attributes with the given predicate.
# Arguments
pred
: The predicate function to be used per-attribute key-value. Its expected
arguments are the attribute key and the attribute value in that order.
attrs
: The attribute set to be used.
# Type
```
countAttrs :: Function -> Attr -> Integer
```
# Examples
```nix
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.
# Arguments
f
: The filter function to be used per-attribute. Its expected arguments are
the attribute key and the attribute value, in that order.
attrs
: The attribute set to be used.
# Type
```
filterAttrs :: Function -> Attr -> Attr
```
# Example
```nix
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.
# Arguments
x
: An integer value expected to be the number of bits.
# Type
```
bitsToBytes :: Integer -> Integer
```
# Example
```nix
bitsToBytes 1600
=> 200
```
*/
bitsToBytes = x: x / 8.0;
/**
Gives the exponent with the associated SI prefix.
# Arguments
c
: The SI prefix itself.
# Type
```
SIPrefixExponent :: String -> Integer
```
# Example
```nix
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.
# Arguments
It has a similar argument to `foodogsquaredLib.trivial.SIPrefixExponent`.
# Examples
```nix
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.
# Arguments
Similar argument to `foodogsquaredLib.trivial.SIPrefixExponent` but only
for select SI prefixes instead.
# Examples
```nix
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.
# Argument
Similar argument to `foodogsquaredLib.trivial.binaryPrefixExponent`.
# Examples
```nix
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.
# Arguments
str
: The string expecting to contain an integer and its suffix (e.g., `4GiB`,
`2 Mb`). Whitespace characters in between them is accepted.
# Examples
```nix
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.
# Arguments
It is a sole attribute set with the following attributes:
size
: An integer value representing the numerical value of the unit.
prefix
: The SI prefix similar to `foodogsquaredLib.trivial.SIPrefixExponent`.
type
: Indicates the type of multiplier to be used. Only accepts `binary` and
`metric` as the value.
# Examples
```nix
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);
}