lib/trivial: add metric and binary unit conversion functions

This commit is contained in:
Gabriel Arazas 2024-09-13 17:07:27 +08:00
parent 6ffba900eb
commit 0989888179
No known key found for this signature in database
GPG Key ID: 62104B43D00AA360
2 changed files with 121 additions and 0 deletions

View File

@ -1,6 +1,17 @@
{ 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:
@ -130,4 +141,53 @@ rec {
*/
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);
}

View File

@ -1,6 +1,16 @@
{ pkgs, lib, self }:
lib.runTests {
testToFloat = {
expr = self.trivial.toFloat 4;
expected = 4.0;
};
testToFloat2 = {
expr = self.trivial.toFloat 5.5;
expected = 5.5;
};
testCountAttrs = {
expr = self.trivial.countAttrs (n: v: v?enable && v.enable) {
hello.enable = true;
@ -69,4 +79,55 @@ lib.runTests {
expr = self.trivial.binaryPrefixMultiplier "G";
expected = 1073741824;
};
testParseBytesSizeIntoInt = {
expr = self.trivial.parseBytesSizeIntoInt "3GB";
expected = 3 * (self.trivial.metricPrefixMultiplier "G");
};
testParseBytesSizeIntoInt2 = {
expr = self.trivial.parseBytesSizeIntoInt "5MiB";
expected = 5 * (self.trivial.binaryPrefixMultiplier "M");
};
testParseBytesSizeIntoInt3 = {
expr = self.trivial.parseBytesSizeIntoInt "5MB";
expected = 5 * (self.trivial.metricPrefixMultiplier "M");
};
testParseBytesSizeIntoInt4 = {
expr = self.trivial.parseBytesSizeIntoInt "2 TiB";
expected = 2 * (self.trivial.binaryPrefixMultiplier "T");
};
testParseBytesSizeIntoInt5 = {
expr = self.trivial.parseBytesSizeIntoInt "2 Tib";
expected = 2 * (self.trivial.binaryPrefixMultiplier "T") / 8;
};
testUnitsToInt = {
expr = self.trivial.unitsToInt {
size = 4.5;
prefix = "G";
type = "metric";
};
expected = 4500000000;
};
testUnitsToInt2 = {
expr = self.trivial.unitsToInt {
size = 4.5;
prefix = "G";
};
expected = 4831838208;
};
testUnitsToInt3 = {
expr = self.trivial.unitsToInt {
size = 532;
prefix = "M";
type = "metric";
};
expected = 532000000;
};
}