aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/lib
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2020-08-07 12:29:39 +0200
committerKatharina Fey <kookie@spacekookie.de>2020-08-07 12:29:39 +0200
commit5581b5521e14317c3507a6e8451a3f14996e5c4d (patch)
tree7aadee5a9ef5d6e2acc8929818c6eb2d2099e2ae /nixpkgs/lib
parentde94c6c62e2f86b3667386a42690d6bb376a2f58 (diff)
parent8e2b14aceb1d40c7e8b84c03a7c78955359872bb (diff)
Merge commit '8e2b14aceb1d40c7e8b84c03a7c78955359872bb'
Diffstat (limited to 'nixpkgs/lib')
-rw-r--r--nixpkgs/lib/attrsets.nix3
-rw-r--r--nixpkgs/lib/default.nix4
-rw-r--r--nixpkgs/lib/generators.nix6
-rw-r--r--nixpkgs/lib/kernel.nix8
-rw-r--r--nixpkgs/lib/licenses.nix61
-rw-r--r--nixpkgs/lib/sources.nix10
-rw-r--r--nixpkgs/lib/strings.nix16
-rw-r--r--nixpkgs/lib/systems/default.nix2
-rw-r--r--nixpkgs/lib/systems/doubles.nix3
-rw-r--r--nixpkgs/lib/systems/examples.nix9
-rw-r--r--nixpkgs/lib/systems/inspect.nix3
-rw-r--r--nixpkgs/lib/systems/parse.nix3
-rw-r--r--nixpkgs/lib/tests/misc.nix10
-rw-r--r--nixpkgs/lib/tests/modules/define-option-dependently.nix2
-rw-r--r--nixpkgs/lib/tests/systems.nix7
-rw-r--r--nixpkgs/lib/trivial.nix51
16 files changed, 172 insertions, 26 deletions
diff --git a/nixpkgs/lib/attrsets.nix b/nixpkgs/lib/attrsets.nix
index 7d84c25de77..d91d7a0cd47 100644
--- a/nixpkgs/lib/attrsets.nix
+++ b/nixpkgs/lib/attrsets.nix
@@ -253,7 +253,7 @@ rec {
/* Like `mapAttrsRecursive', but it takes an additional predicate
function that tells it whether to recursive into an attribute
set. If it returns false, `mapAttrsRecursiveCond' does not
- recurse, but does apply the map function. It is returns true, it
+ recurse, but does apply the map function. If it returns true, it
does recurse, and does not apply the map function.
Type:
@@ -469,6 +469,7 @@ rec {
getBin = getOutput "bin";
getLib = getOutput "lib";
getDev = getOutput "dev";
+ getMan = getOutput "man";
/* Pick the outputs of packages to place in buildInputs */
chooseDevOutputs = drvs: builtins.map getDev drvs;
diff --git a/nixpkgs/lib/default.nix b/nixpkgs/lib/default.nix
index e7f59a67abb..43b9ab5930c 100644
--- a/nixpkgs/lib/default.nix
+++ b/nixpkgs/lib/default.nix
@@ -67,7 +67,7 @@ let
inherit (trivial) id const pipe concat or and bitAnd bitOr bitXor
bitNot boolToString mergeAttrs flip mapNullable inNixShell min max
importJSON warn info showWarnings nixpkgsVersion version mod compare
- splitByAndCompare functionArgs setFunctionArgs isFunction;
+ splitByAndCompare functionArgs setFunctionArgs isFunction toHexString toBaseDigits;
inherit (fixedPoints) fix fix' converge extends composeExtensions
makeExtensible makeExtensibleWithCustomName;
inherit (attrsets) attrByPath hasAttrByPath setAttrByPath
@@ -77,7 +77,7 @@ let
genAttrs isDerivation toDerivation optionalAttrs
zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
recursiveUpdate matchAttrs overrideExisting getOutput getBin
- getLib getDev chooseDevOutputs zipWithNames zip
+ getLib getDev getMan chooseDevOutputs zipWithNames zip
recurseIntoAttrs dontRecurseIntoAttrs;
inherit (lists) singleton forEach foldr fold foldl foldl' imap0 imap1
concatMap flatten remove findSingle findFirst any all count
diff --git a/nixpkgs/lib/generators.nix b/nixpkgs/lib/generators.nix
index efe6ea6031d..abd237eb7d3 100644
--- a/nixpkgs/lib/generators.nix
+++ b/nixpkgs/lib/generators.nix
@@ -48,8 +48,10 @@ rec {
else if isAttrs v then err "attrsets" v
# functions can’t be printed of course
else if isFunction v then err "functions" v
- # let’s not talk about floats. There is no sensible `toString` for them.
- else if isFloat v then err "floats" v
+ # Floats currently can't be converted to precise strings,
+ # condition warning on nix version once this isn't a problem anymore
+ # See https://github.com/NixOS/nix/pull/3480
+ else if isFloat v then libStr.floatToString v
else err "this value is" (toString v);
diff --git a/nixpkgs/lib/kernel.nix b/nixpkgs/lib/kernel.nix
index 8045a228d05..ffcbc268b76 100644
--- a/nixpkgs/lib/kernel.nix
+++ b/nixpkgs/lib/kernel.nix
@@ -8,10 +8,10 @@ with lib;
option = x:
x // { optional = true; };
- yes = { tristate = "y"; };
- no = { tristate = "n"; };
- module = { tristate = "m"; };
- freeform = x: { freeform = x; };
+ yes = { tristate = "y"; optional = false; };
+ no = { tristate = "n"; optional = false; };
+ module = { tristate = "m"; optional = false; };
+ freeform = x: { freeform = x; optional = false; };
/*
Common patterns/legacy used in common-config/hardened/config.nix
diff --git a/nixpkgs/lib/licenses.nix b/nixpkgs/lib/licenses.nix
index 4c07797b16c..2f9fc04cb7c 100644
--- a/nixpkgs/lib/licenses.nix
+++ b/nixpkgs/lib/licenses.nix
@@ -28,7 +28,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "Academic Free License v3.0";
};
- agpl3 = spdx {
+ agpl3Only = spdx {
spdxId = "AGPL-3.0-only";
fullName = "GNU Affero General Public License v3.0 only";
};
@@ -95,6 +95,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = ''BSD 2-clause "Simplified" License'';
};
+ bsd2Patent = spdx {
+ spdxId = "BSD-2-Clause-Patent";
+ fullName = ''BSD-2-Clause Plus Patent License'';
+ };
+
bsd3 = spdx {
spdxId = "BSD-3-Clause";
fullName = ''BSD 3-clause "New" or "Revised" License'';
@@ -105,6 +110,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = ''BSD 4-clause "Original" or "Old" License'';
};
+ bsdProtection = spdx {
+ spdxId = "BSD-Protection";
+ fullName = "BSD Protection License";
+ };
+
bsl11 = {
fullName = "Business Source License 1.1";
url = "https://mariadb.com/bsl11";
@@ -276,7 +286,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "European Union Public License 1.2";
};
- fdl12 = spdx {
+ fdl11Only = spdx {
+ spdxId = "GFDL-1.1-only";
+ fullName = "GNU Free Documentation License v1.1 only";
+ };
+
+ fdl12Only = spdx {
spdxId = "GFDL-1.2-only";
fullName = "GNU Free Documentation License v1.2 only";
};
@@ -286,7 +301,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU Free Documentation License v1.2 or later";
};
- fdl13 = spdx {
+ fdl13Only = spdx {
spdxId = "GFDL-1.3-only";
fullName = "GNU Free Documentation License v1.3 only";
};
@@ -317,7 +332,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
free = false;
};
- gpl1 = spdx {
+ gpl1Only = spdx {
spdxId = "GPL-1.0-only";
fullName = "GNU General Public License v1.0 only";
};
@@ -327,7 +342,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU General Public License v1.0 or later";
};
- gpl2 = spdx {
+ gpl2Only = spdx {
spdxId = "GPL-2.0-only";
fullName = "GNU General Public License v2.0 only";
};
@@ -352,7 +367,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU General Public License v2.0 or later";
};
- gpl3 = spdx {
+ gpl3Only = spdx {
spdxId = "GPL-3.0-only";
fullName = "GNU General Public License v3.0 only";
};
@@ -427,7 +442,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "JasPer License";
};
- lgpl2 = spdx {
+ lgpl2Only = spdx {
spdxId = "LGPL-2.0-only";
fullName = "GNU Library General Public License v2 only";
};
@@ -437,7 +452,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU Library General Public License v2 or later";
};
- lgpl21 = spdx {
+ lgpl21Only = spdx {
spdxId = "LGPL-2.1-only";
fullName = "GNU Lesser General Public License v2.1 only";
};
@@ -447,7 +462,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU Lesser General Public License v2.1 or later";
};
- lgpl3 = spdx {
+ lgpl3Only = spdx {
spdxId = "LGPL-3.0-only";
fullName = "GNU Lesser General Public License v3.0 only";
};
@@ -457,6 +472,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU Lesser General Public License v3.0 or later";
};
+ lgpllr = spdx {
+ spdxId = "LGPLLR";
+ fullName = "Lesser General Public License For Linguistic Resources";
+ };
+
libpng = spdx {
spdxId = "Libpng";
fullName = "libpng License";
@@ -477,6 +497,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
url = "https://opensource.franz.com/preamble.html";
};
+ llvm-exception = spdx {
+ spdxId = "LLVM-exception";
+ fullName = "LLVM Exception"; # LLVM exceptions to the Apache 2.0 License
+ };
+
lppl12 = spdx {
spdxId = "LPPL-1.2";
fullName = "LaTeX Project Public License v1.2";
@@ -540,6 +565,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "Non-Profit Open Software License 3.0";
};
+ obsidian = {
+ fullName = "Obsidian End User Agreement";
+ url = "https://obsidian.md/eula";
+ free = false;
+ };
+
ocamlpro_nc = {
fullName = "OCamlPro Non Commercial license version 1";
url = "https://alt-ergo.ocamlpro.com/http/alt-ergo-2.2.0/OCamlPro-Non-Commercial-License.pdf";
@@ -756,4 +787,16 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
spdxId = "ZPL-2.1";
fullName = "Zope Public License 2.1";
};
+} // {
+ # TODO: remove legacy aliases
+ agpl3 = lib.licenses.agpl3Only;
+ fdl11 = lib.licenses.fdl11Only;
+ fdl12 = lib.licenses.fdl12Only;
+ fdl13 = lib.licenses.fdl13Only;
+ gpl1 = lib.licenses.gpl1Only;
+ gpl2 = lib.licenses.gpl2Only;
+ gpl3 = lib.licenses.gpl3Only;
+ lgpl2 = lib.licenses.lgpl2Only;
+ lgpl21 = lib.licenses.lgpl21Only;
+ lgpl3 = lib.licenses.lgpl3Only;
}
diff --git a/nixpkgs/lib/sources.nix b/nixpkgs/lib/sources.nix
index ed9bce48530..776fcc32052 100644
--- a/nixpkgs/lib/sources.nix
+++ b/nixpkgs/lib/sources.nix
@@ -145,10 +145,14 @@ rec {
# packed-refs file, so we have to grep through it:
then
let fileContent = readFile packedRefsName;
- matchRef = match (".*\n([^\n ]*) " + file + "\n.*") fileContent;
- in if matchRef == null
+ matchRef = builtins.match "([a-z0-9]+) ${file}";
+ isRef = s: builtins.isString s && (matchRef s) != null;
+ # there is a bug in libstdc++ leading to stackoverflow for long strings:
+ # https://github.com/NixOS/nix/issues/2147#issuecomment-659868795
+ refs = builtins.filter isRef (builtins.split "\n" fileContent);
+ in if refs == []
then throw ("Could not find " + file + " in " + packedRefsName)
- else lib.head matchRef
+ else lib.head (matchRef (lib.head refs))
else throw ("Not a .git directory: " + path);
in readCommitFromFile "HEAD";
diff --git a/nixpkgs/lib/strings.nix b/nixpkgs/lib/strings.nix
index 74e3eaa0722..0baa942355c 100644
--- a/nixpkgs/lib/strings.nix
+++ b/nixpkgs/lib/strings.nix
@@ -612,6 +612,22 @@ rec {
*/
fixedWidthNumber = width: n: fixedWidthString width "0" (toString n);
+ /* Convert a float to a string, but emit a warning when precision is lost
+ during the conversion
+
+ Example:
+ floatToString 0.000001
+ => "0.000001"
+ floatToString 0.0000001
+ => trace: warning: Imprecise conversion from float to string 0.000000
+ "0.000000"
+ */
+ floatToString = float: let
+ result = toString float;
+ precise = float == builtins.fromJSON result;
+ in if precise then result
+ else lib.warn "Imprecise conversion from float to string ${result}" result;
+
/* Check whether a value can be coerced to a string */
isCoercibleToString = x:
builtins.elem (builtins.typeOf x) [ "path" "string" "null" "int" "float" "bool" ] ||
diff --git a/nixpkgs/lib/systems/default.nix b/nixpkgs/lib/systems/default.nix
index 210674cc639..c929781dd8f 100644
--- a/nixpkgs/lib/systems/default.nix
+++ b/nixpkgs/lib/systems/default.nix
@@ -32,6 +32,7 @@ rec {
/**/ if final.isDarwin then "libSystem"
else if final.isMinGW then "msvcrt"
else if final.isWasi then "wasilibc"
+ else if final.isRedox then "relibc"
else if final.isMusl then "musl"
else if final.isUClibc then "uclibc"
else if final.isAndroid then "bionic"
@@ -65,6 +66,7 @@ rec {
freebsd = "FreeBSD";
openbsd = "OpenBSD";
wasi = "Wasi";
+ redox = "Redox";
genode = "Genode";
}.${final.parsed.kernel.name} or null;
diff --git a/nixpkgs/lib/systems/doubles.nix b/nixpkgs/lib/systems/doubles.nix
index a839b3d3d57..c0e78595d85 100644
--- a/nixpkgs/lib/systems/doubles.nix
+++ b/nixpkgs/lib/systems/doubles.nix
@@ -22,6 +22,8 @@ let
"wasm64-wasi" "wasm32-wasi"
+ "x86_64-redox"
+
"powerpc64le-linux"
"riscv32-linux" "riscv64-linux"
@@ -69,6 +71,7 @@ in {
openbsd = filterDoubles predicates.isOpenBSD;
unix = filterDoubles predicates.isUnix;
wasi = filterDoubles predicates.isWasi;
+ redox = filterDoubles predicates.isRedox;
windows = filterDoubles predicates.isWindows;
genode = filterDoubles predicates.isGenode;
diff --git a/nixpkgs/lib/systems/examples.nix b/nixpkgs/lib/systems/examples.nix
index 19b3790ecbe..ca562d2e456 100644
--- a/nixpkgs/lib/systems/examples.nix
+++ b/nixpkgs/lib/systems/examples.nix
@@ -164,6 +164,15 @@ rec {
};
#
+ # Redox
+ #
+
+ x86_64-unknown-redox = {
+ config = "x86_64-unknown-redox";
+ libc = "relibc";
+ };
+
+ #
# Darwin
#
diff --git a/nixpkgs/lib/systems/inspect.nix b/nixpkgs/lib/systems/inspect.nix
index 90a1fb6d80c..8fa63057250 100644
--- a/nixpkgs/lib/systems/inspect.nix
+++ b/nixpkgs/lib/systems/inspect.nix
@@ -33,7 +33,7 @@ rec {
isBSD = { kernel = { families = { inherit (kernelFamilies) bsd; }; }; };
isDarwin = { kernel = { families = { inherit (kernelFamilies) darwin; }; }; };
- isUnix = [ isBSD isDarwin isLinux isSunOS isCygwin ];
+ isUnix = [ isBSD isDarwin isLinux isSunOS isCygwin isRedox ];
isMacOS = { kernel = kernels.macos; };
isiOS = { kernel = kernels.ios; };
@@ -46,6 +46,7 @@ rec {
isCygwin = { kernel = kernels.windows; abi = abis.cygnus; };
isMinGW = { kernel = kernels.windows; abi = abis.gnu; };
isWasi = { kernel = kernels.wasi; };
+ isRedox = { kernel = kernels.redox; };
isGhcjs = { kernel = kernels.ghcjs; };
isGenode = { kernel = kernels.genode; };
isNone = { kernel = kernels.none; };
diff --git a/nixpkgs/lib/systems/parse.nix b/nixpkgs/lib/systems/parse.nix
index 648e7c27024..6bd44a00746 100644
--- a/nixpkgs/lib/systems/parse.nix
+++ b/nixpkgs/lib/systems/parse.nix
@@ -277,6 +277,7 @@ rec {
openbsd = { execFormat = elf; families = { inherit bsd; }; };
solaris = { execFormat = elf; families = { }; };
wasi = { execFormat = wasm; families = { }; };
+ redox = { execFormat = elf; families = { }; };
windows = { execFormat = pe; families = { }; };
ghcjs = { execFormat = unknown; families = { }; };
genode = { execFormat = elf; families = { }; };
@@ -390,6 +391,8 @@ rec {
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "windows"; }
else if (elemAt l 2 == "wasi")
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "wasi"; }
+ else if (elemAt l 2 == "redox")
+ then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "redox"; }
else if hasPrefix "netbsd" (elemAt l 2)
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; }
else if (elem (elemAt l 2) ["eabi" "eabihf" "elf"])
diff --git a/nixpkgs/lib/tests/misc.nix b/nixpkgs/lib/tests/misc.nix
index 36ddd186d7b..b066f577f32 100644
--- a/nixpkgs/lib/tests/misc.nix
+++ b/nixpkgs/lib/tests/misc.nix
@@ -102,6 +102,16 @@ runTests {
expected = 9;
};
+ testToHexString = {
+ expr = toHexString 250;
+ expected = "FA";
+ };
+
+ testToBaseDigits = {
+ expr = toBaseDigits 2 6;
+ expected = [ 1 1 0 ];
+ };
+
# STRINGS
testConcatMapStrings = {
diff --git a/nixpkgs/lib/tests/modules/define-option-dependently.nix b/nixpkgs/lib/tests/modules/define-option-dependently.nix
index 6abce29366a..ad85f99a919 100644
--- a/nixpkgs/lib/tests/modules/define-option-dependently.nix
+++ b/nixpkgs/lib/tests/modules/define-option-dependently.nix
@@ -7,7 +7,7 @@
# Always defined, but the value depends on the presence of an option.
config = {
value = if options ? enable then 360 else 7;
- }
+ }
# Only define if possible.
// lib.optionalAttrs (options ? enable) {
enable = true;
diff --git a/nixpkgs/lib/tests/systems.nix b/nixpkgs/lib/tests/systems.nix
index ea6e337937f..ea8ceedd43f 100644
--- a/nixpkgs/lib/tests/systems.nix
+++ b/nixpkgs/lib/tests/systems.nix
@@ -12,22 +12,23 @@ let
expected = lib.sort lib.lessThan y;
};
in with lib.systems.doubles; lib.runTests {
- testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded ++ js ++ genode);
+ testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded ++ js ++ genode ++ redox);
testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv6l-none" "armv7a-linux" "armv7l-linux" "arm-none" "armv7a-darwin" ];
testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
testmips = mseteq mips [ "mipsel-linux" ];
- testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-genode" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ];
+ testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-genode" "x86_64-redox" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ];
testcygwin = mseteq cygwin [ "i686-cygwin" "x86_64-cygwin" ];
testdarwin = mseteq darwin [ "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin" ];
testfreebsd = mseteq freebsd [ "i686-freebsd" "x86_64-freebsd" ];
testgenode = mseteq genode [ "aarch64-genode" "x86_64-genode" ];
+ testredox = mseteq redox [ "x86_64-redox" ];
testgnu = mseteq gnu (linux /* ++ kfreebsd ++ ... */);
testillumos = mseteq illumos [ "x86_64-solaris" ];
testlinux = mseteq linux [ "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux" "i686-linux" "mipsel-linux" "riscv32-linux" "riscv64-linux" "x86_64-linux" "powerpc64le-linux" ];
testnetbsd = mseteq netbsd [ "i686-netbsd" "x86_64-netbsd" ];
testopenbsd = mseteq openbsd [ "i686-openbsd" "x86_64-openbsd" ];
testwindows = mseteq windows [ "i686-cygwin" "x86_64-cygwin" "i686-windows" "x86_64-windows" ];
- testunix = mseteq unix (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ cygwin);
+ testunix = mseteq unix (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ cygwin ++ redox);
}
diff --git a/nixpkgs/lib/trivial.nix b/nixpkgs/lib/trivial.nix
index 5788dd435e5..6eb1fb3a5b1 100644
--- a/nixpkgs/lib/trivial.nix
+++ b/nixpkgs/lib/trivial.nix
@@ -332,4 +332,55 @@ rec {
*/
isFunction = f: builtins.isFunction f ||
(f ? __functor && isFunction (f.__functor f));
+
+ /* Convert the given positive integer to a string of its hexadecimal
+ representation. For example:
+
+ toHexString 0 => "0"
+
+ toHexString 16 => "10"
+
+ toHexString 250 => "FA"
+ */
+ toHexString = i:
+ let
+ toHexDigit = d:
+ if d < 10
+ then toString d
+ else
+ {
+ "10" = "A";
+ "11" = "B";
+ "12" = "C";
+ "13" = "D";
+ "14" = "E";
+ "15" = "F";
+ }.${toString d};
+ in
+ lib.concatMapStrings toHexDigit (toBaseDigits 16 i);
+
+ /* `toBaseDigits base i` converts the positive integer i to a list of its
+ digits in the given base. For example:
+
+ toBaseDigits 10 123 => [ 1 2 3 ]
+
+ toBaseDigits 2 6 => [ 1 1 0 ]
+
+ toBaseDigits 16 250 => [ 15 10 ]
+ */
+ toBaseDigits = base: i:
+ let
+ go = i:
+ if i < base
+ then [i]
+ else
+ let
+ r = i - ((i / base) * base);
+ q = (i - r) / base;
+ in
+ [r] ++ go q;
+ in
+ assert (base >= 2);
+ assert (i >= 0);
+ lib.reverseList (go i);
}