{ 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); }