at 25.11-pre 22 kB view raw
1{ lib }: 2 3let 4 inherit (lib.trivial) 5 isFunction 6 isInt 7 functionArgs 8 pathExists 9 release 10 setFunctionArgs 11 toBaseDigits 12 version 13 versionSuffix 14 warn 15 ; 16 inherit (lib) 17 isString 18 ; 19in 20{ 21 22 ## Simple (higher order) functions 23 24 /** 25 The identity function 26 For when you need a function that does nothing. 27 28 # Inputs 29 30 `x` 31 32 : The value to return 33 34 # Type 35 36 ``` 37 id :: a -> a 38 ``` 39 */ 40 id = x: x; 41 42 /** 43 The constant function 44 45 Ignores the second argument. If called with only one argument, 46 constructs a function that always returns a static value. 47 48 # Inputs 49 50 `x` 51 52 : Value to return 53 54 `y` 55 56 : Value to ignore 57 58 # Type 59 60 ``` 61 const :: a -> b -> a 62 ``` 63 64 # Examples 65 :::{.example} 66 ## `lib.trivial.const` usage example 67 68 ```nix 69 let f = const 5; in f 10 70 => 5 71 ``` 72 73 ::: 74 */ 75 const = x: y: x; 76 77 /** 78 Pipes a value through a list of functions, left to right. 79 80 # Inputs 81 82 `value` 83 84 : Value to start piping. 85 86 `fns` 87 88 : List of functions to apply sequentially. 89 90 # Type 91 92 ``` 93 pipe :: a -> [<functions>] -> <return type of last function> 94 ``` 95 96 # Examples 97 :::{.example} 98 ## `lib.trivial.pipe` usage example 99 100 ```nix 101 pipe 2 [ 102 (x: x + 2) # 2 + 2 = 4 103 (x: x * 2) # 4 * 2 = 8 104 ] 105 => 8 106 107 # ideal to do text transformations 108 pipe [ "a/b" "a/c" ] [ 109 110 # create the cp command 111 (map (file: ''cp "${src}/${file}" $out\n'')) 112 113 # concatenate all commands into one string 114 lib.concatStrings 115 116 # make that string into a nix derivation 117 (pkgs.runCommand "copy-to-out" {}) 118 119 ] 120 => <drv which copies all files to $out> 121 122 The output type of each function has to be the input type 123 of the next function, and the last function returns the 124 final value. 125 ``` 126 127 ::: 128 */ 129 pipe = builtins.foldl' (x: f: f x); 130 131 # note please don’t add a function like `compose = flip pipe`. 132 # This would confuse users, because the order of the functions 133 # in the list is not clear. With pipe, it’s obvious that it 134 # goes first-to-last. With `compose`, not so much. 135 136 ## Named versions corresponding to some builtin operators. 137 138 /** 139 Concatenate two lists 140 141 # Inputs 142 143 `x` 144 145 : 1\. Function argument 146 147 `y` 148 149 : 2\. Function argument 150 151 # Type 152 153 ``` 154 concat :: [a] -> [a] -> [a] 155 ``` 156 157 # Examples 158 :::{.example} 159 ## `lib.trivial.concat` usage example 160 161 ```nix 162 concat [ 1 2 ] [ 3 4 ] 163 => [ 1 2 3 4 ] 164 ``` 165 166 ::: 167 */ 168 concat = x: y: x ++ y; 169 170 /** 171 boolean or 172 173 # Inputs 174 175 `x` 176 177 : 1\. Function argument 178 179 `y` 180 181 : 2\. Function argument 182 */ 183 or = x: y: x || y; 184 185 /** 186 boolean and 187 188 # Inputs 189 190 `x` 191 192 : 1\. Function argument 193 194 `y` 195 196 : 2\. Function argument 197 */ 198 and = x: y: x && y; 199 200 /** 201 boolean exclusive or 202 203 # Inputs 204 205 `x` 206 207 : 1\. Function argument 208 209 `y` 210 211 : 2\. Function argument 212 */ 213 # We explicitly invert the arguments purely as a type assertion. 214 # This is invariant under XOR, so it does not affect the result. 215 xor = x: y: (!x) != (!y); 216 217 /** 218 bitwise not 219 */ 220 bitNot = builtins.sub (-1); 221 222 /** 223 Convert a boolean to a string. 224 225 This function uses the strings "true" and "false" to represent 226 boolean values. Calling `toString` on a bool instead returns "1" 227 and "" (sic!). 228 229 # Inputs 230 231 `b` 232 233 : 1\. Function argument 234 235 # Type 236 237 ``` 238 boolToString :: bool -> string 239 ``` 240 */ 241 boolToString = b: if b then "true" else "false"; 242 243 /** 244 Merge two attribute sets shallowly, right side trumps left 245 246 mergeAttrs :: attrs -> attrs -> attrs 247 248 # Inputs 249 250 `x` 251 252 : Left attribute set 253 254 `y` 255 256 : Right attribute set (higher precedence for equal keys) 257 258 # Examples 259 :::{.example} 260 ## `lib.trivial.mergeAttrs` usage example 261 262 ```nix 263 mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; } 264 => { a = 1; b = 3; c = 4; } 265 ``` 266 267 ::: 268 */ 269 mergeAttrs = x: y: x // y; 270 271 /** 272 Flip the order of the arguments of a binary function. 273 274 # Inputs 275 276 `f` 277 278 : 1\. Function argument 279 280 `a` 281 282 : 2\. Function argument 283 284 `b` 285 286 : 3\. Function argument 287 288 # Type 289 290 ``` 291 flip :: (a -> b -> c) -> (b -> a -> c) 292 ``` 293 294 # Examples 295 :::{.example} 296 ## `lib.trivial.flip` usage example 297 298 ```nix 299 flip concat [1] [2] 300 => [ 2 1 ] 301 ``` 302 303 ::: 304 */ 305 flip = 306 f: a: b: 307 f b a; 308 309 /** 310 Return `maybeValue` if not null, otherwise return `default`. 311 312 # Inputs 313 314 `default` 315 316 : 1\. Function argument 317 318 `maybeValue` 319 320 : 2\. Function argument 321 322 # Examples 323 :::{.example} 324 ## `lib.trivial.defaultTo` usage example 325 326 ```nix 327 defaultTo "default" null 328 => "default" 329 defaultTo "default" "foo" 330 => "foo" 331 defaultTo "default" false 332 => false 333 ``` 334 335 ::: 336 */ 337 defaultTo = default: maybeValue: if maybeValue != null then maybeValue else default; 338 339 /** 340 Apply function if the supplied argument is non-null. 341 342 # Inputs 343 344 `f` 345 346 : Function to call 347 348 `a` 349 350 : Argument to check for null before passing it to `f` 351 352 # Examples 353 :::{.example} 354 ## `lib.trivial.mapNullable` usage example 355 356 ```nix 357 mapNullable (x: x+1) null 358 => null 359 mapNullable (x: x+1) 22 360 => 23 361 ``` 362 363 ::: 364 */ 365 mapNullable = f: a: if a == null then a else f a; 366 367 # Pull in some builtins not included elsewhere. 368 inherit (builtins) 369 pathExists 370 readFile 371 isBool 372 isInt 373 isFloat 374 add 375 sub 376 lessThan 377 seq 378 deepSeq 379 genericClosure 380 bitAnd 381 bitOr 382 bitXor 383 ; 384 385 ## nixpkgs version strings 386 387 /** 388 Returns the current full nixpkgs version number. 389 */ 390 version = release + versionSuffix; 391 392 /** 393 Returns the current nixpkgs release number as string. 394 */ 395 release = lib.strings.fileContents ./.version; 396 397 /** 398 The latest release that is supported, at the time of release branch-off, 399 if applicable. 400 401 Ideally, out-of-tree modules should be able to evaluate cleanly with all 402 supported Nixpkgs versions (master, release and old release until EOL). 403 So if possible, deprecation warnings should take effect only when all 404 out-of-tree expressions/libs/modules can upgrade to the new way without 405 losing support for supported Nixpkgs versions. 406 407 This release number allows deprecation warnings to be implemented such that 408 they take effect as soon as the oldest release reaches end of life. 409 */ 410 oldestSupportedRelease = 411 # Update on master only. Do not backport. 412 2411; 413 414 /** 415 Whether a feature is supported in all supported releases (at the time of 416 release branch-off, if applicable). See `oldestSupportedRelease`. 417 418 # Inputs 419 420 `release` 421 422 : Release number of feature introduction as an integer, e.g. 2111 for 21.11. 423 Set it to the upcoming release, matching the nixpkgs/.version file. 424 */ 425 isInOldestRelease = 426 lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2411) 427 "lib.isInOldestRelease is deprecated. Use lib.oldestSupportedReleaseIsAtLeast instead." 428 lib.oldestSupportedReleaseIsAtLeast; 429 430 /** 431 Alias for `isInOldestRelease` introduced in 24.11. 432 Use `isInOldestRelease` in expressions outside of Nixpkgs for greater compatibility. 433 */ 434 oldestSupportedReleaseIsAtLeast = release: release <= lib.trivial.oldestSupportedRelease; 435 436 /** 437 Returns the current nixpkgs release code name. 438 439 On each release the first letter is bumped and a new animal is chosen 440 starting with that new letter. 441 */ 442 codeName = "Xantusia"; 443 444 /** 445 Returns the current nixpkgs version suffix as string. 446 */ 447 versionSuffix = 448 let 449 suffixFile = ../.version-suffix; 450 in 451 if pathExists suffixFile then lib.strings.fileContents suffixFile else "pre-git"; 452 453 /** 454 Attempts to return the the current revision of nixpkgs and 455 returns the supplied default value otherwise. 456 457 # Inputs 458 459 `default` 460 461 : Default value to return if revision can not be determined 462 463 # Type 464 465 ``` 466 revisionWithDefault :: string -> string 467 ``` 468 */ 469 revisionWithDefault = 470 default: 471 let 472 revisionFile = "${toString ./..}/.git-revision"; 473 gitRepo = "${toString ./..}/.git"; 474 in 475 if lib.pathIsGitRepo gitRepo then 476 lib.commitIdFromGitRepo gitRepo 477 else if lib.pathExists revisionFile then 478 lib.fileContents revisionFile 479 else 480 default; 481 482 nixpkgsVersion = warn "lib.nixpkgsVersion is a deprecated alias of lib.version." version; 483 484 /** 485 Determine whether the function is being called from inside a Nix 486 shell. 487 488 # Type 489 490 ``` 491 inNixShell :: bool 492 ``` 493 */ 494 inNixShell = builtins.getEnv "IN_NIX_SHELL" != ""; 495 496 /** 497 Determine whether the function is being called from inside pure-eval mode 498 by seeing whether `builtins` contains `currentSystem`. If not, we must be in 499 pure-eval mode. 500 501 # Type 502 503 ``` 504 inPureEvalMode :: bool 505 ``` 506 */ 507 inPureEvalMode = !builtins ? currentSystem; 508 509 ## Integer operations 510 511 /** 512 Return minimum of two numbers. 513 514 # Inputs 515 516 `x` 517 518 : 1\. Function argument 519 520 `y` 521 522 : 2\. Function argument 523 */ 524 min = x: y: if x < y then x else y; 525 526 /** 527 Return maximum of two numbers. 528 529 # Inputs 530 531 `x` 532 533 : 1\. Function argument 534 535 `y` 536 537 : 2\. Function argument 538 */ 539 max = x: y: if x > y then x else y; 540 541 /** 542 Integer modulus 543 544 # Inputs 545 546 `base` 547 548 : 1\. Function argument 549 550 `int` 551 552 : 2\. Function argument 553 554 # Examples 555 :::{.example} 556 ## `lib.trivial.mod` usage example 557 558 ```nix 559 mod 11 10 560 => 1 561 mod 1 10 562 => 1 563 ``` 564 565 ::: 566 */ 567 mod = base: int: base - (int * (builtins.div base int)); 568 569 ## Comparisons 570 571 /** 572 C-style comparisons 573 574 a < b, compare a b => -1 575 a == b, compare a b => 0 576 a > b, compare a b => 1 577 578 # Inputs 579 580 `a` 581 582 : 1\. Function argument 583 584 `b` 585 586 : 2\. Function argument 587 */ 588 compare = 589 a: b: 590 if a < b then 591 -1 592 else if a > b then 593 1 594 else 595 0; 596 597 /** 598 Split type into two subtypes by predicate `p`, take all elements 599 of the first subtype to be less than all the elements of the 600 second subtype, compare elements of a single subtype with `yes` 601 and `no` respectively. 602 603 # Inputs 604 605 `p` 606 607 : Predicate 608 609 `yes` 610 611 : Comparison function if predicate holds for both values 612 613 `no` 614 615 : Comparison function if predicate holds for neither value 616 617 `a` 618 619 : First value to compare 620 621 `b` 622 623 : Second value to compare 624 625 # Type 626 627 ``` 628 (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int) 629 ``` 630 631 # Examples 632 :::{.example} 633 ## `lib.trivial.splitByAndCompare` usage example 634 635 ```nix 636 let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in 637 638 cmp "a" "z" => -1 639 cmp "fooa" "fooz" => -1 640 641 cmp "f" "a" => 1 642 cmp "fooa" "a" => -1 643 # while 644 compare "fooa" "a" => 1 645 ``` 646 647 ::: 648 */ 649 splitByAndCompare = 650 p: yes: no: a: b: 651 if p a then 652 if p b then yes a b else -1 653 else if p b then 654 1 655 else 656 no a b; 657 658 /** 659 Reads a JSON file. 660 661 # Examples 662 :::{.example} 663 ## `lib.trivial.importJSON` usage example 664 665 example.json 666 ```json 667 { 668 "title": "Example JSON", 669 "hello": { 670 "world": "foo", 671 "bar": { 672 "foobar": true 673 } 674 } 675 } 676 ``` 677 678 ```nix 679 importJSON ./example.json 680 => { 681 title = "Example JSON"; 682 hello = { 683 world = "foo"; 684 bar = { 685 foobar = true; 686 }; 687 }; 688 } 689 ``` 690 691 ::: 692 693 # Inputs 694 695 `path` 696 697 : 1\. Function argument 698 699 # Type 700 701 ``` 702 importJSON :: path -> any 703 ``` 704 */ 705 importJSON = path: builtins.fromJSON (builtins.readFile path); 706 707 /** 708 Reads a TOML file. 709 710 # Examples 711 :::{.example} 712 ## `lib.trivial.importTOML` usage example 713 714 example.toml 715 ```toml 716 title = "TOML Example" 717 718 [hello] 719 world = "foo" 720 721 [hello.bar] 722 foobar = true 723 ``` 724 725 ```nix 726 importTOML ./example.toml 727 => { 728 title = "TOML Example"; 729 hello = { 730 world = "foo"; 731 bar = { 732 foobar = true; 733 }; 734 }; 735 } 736 ``` 737 738 ::: 739 740 # Inputs 741 742 `path` 743 744 : 1\. Function argument 745 746 # Type 747 748 ``` 749 importTOML :: path -> any 750 ``` 751 */ 752 importTOML = path: builtins.fromTOML (builtins.readFile path); 753 754 /** 755 `warn` *`message`* *`value`* 756 757 Print a warning before returning the second argument. 758 759 See [`builtins.warn`](https://nix.dev/manual/nix/latest/language/builtins.html#builtins-warn) (Nix >= 2.23). 760 On older versions, the Nix 2.23 behavior is emulated with [`builtins.trace`](https://nix.dev/manual/nix/latest/language/builtins.html#builtins-warn), including the [`NIX_ABORT_ON_WARN`](https://nix.dev/manual/nix/latest/command-ref/conf-file#conf-abort-on-warn) behavior, but not the `nix.conf` setting or command line option. 761 762 # Inputs 763 764 *`message`* (String) 765 766 : Warning message to print before evaluating *`value`*. 767 768 *`value`* (any value) 769 770 : Value to return as-is. 771 772 # Type 773 774 ``` 775 String -> a -> a 776 ``` 777 */ 778 warn = 779 # Since Nix 2.23, https://github.com/NixOS/nix/pull/10592 780 builtins.warn or ( 781 let 782 mustAbort = lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") [ 783 "1" 784 "true" 785 "yes" 786 ]; 787 in 788 # Do not eta reduce v, so that we have the same strictness as `builtins.warn`. 789 msg: v: 790 # `builtins.warn` requires a string message, so we enforce that in our implementation, so that callers aren't accidentally incompatible with newer Nix versions. 791 assert isString msg; 792 if mustAbort then 793 builtins.trace "evaluation warning: ${msg}" ( 794 abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors." 795 ) 796 else 797 builtins.trace "evaluation warning: ${msg}" v 798 ); 799 800 /** 801 `warnIf` *`condition`* *`message`* *`value`* 802 803 Like `warn`, but only warn when the first argument is `true`. 804 805 # Inputs 806 807 *`condition`* (Boolean) 808 809 : `true` to trigger the warning before continuing with *`value`*. 810 811 *`message`* (String) 812 813 : Warning message to print before evaluating 814 815 *`value`* (any value) 816 817 : Value to return as-is. 818 819 # Type 820 821 ``` 822 Bool -> String -> a -> a 823 ``` 824 */ 825 warnIf = cond: msg: if cond then warn msg else x: x; 826 827 /** 828 `warnIfNot` *`condition`* *`message`* *`value`* 829 830 Like `warnIf`, but negated: warn if the first argument is `false`. 831 832 # Inputs 833 834 *`condition`* 835 836 : `false` to trigger the warning before continuing with `val`. 837 838 *`message`* 839 840 : Warning message to print before evaluating *`value`*. 841 842 *`value`* 843 844 : Value to return as-is. 845 846 # Type 847 848 ``` 849 Boolean -> String -> a -> a 850 ``` 851 */ 852 warnIfNot = cond: msg: if cond then x: x else warn msg; 853 854 /** 855 Like the `assert b; e` expression, but with a custom error message and 856 without the semicolon. 857 858 If true, return the identity function, `r: r`. 859 860 If false, throw the error message. 861 862 Calls can be juxtaposed using function application, as `(r: r) a = a`, so 863 `(r: r) (r: r) a = a`, and so forth. 864 865 # Inputs 866 867 `cond` 868 869 : 1\. Function argument 870 871 `msg` 872 873 : 2\. Function argument 874 875 # Type 876 877 ``` 878 bool -> string -> a -> a 879 ``` 880 881 # Examples 882 :::{.example} 883 ## `lib.trivial.throwIfNot` usage example 884 885 ```nix 886 throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list." 887 lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays 888 pkgs 889 ``` 890 891 ::: 892 */ 893 throwIfNot = cond: msg: if cond then x: x else throw msg; 894 895 /** 896 Like throwIfNot, but negated (throw if the first argument is `true`). 897 898 # Inputs 899 900 `cond` 901 902 : 1\. Function argument 903 904 `msg` 905 906 : 2\. Function argument 907 908 # Type 909 910 ``` 911 bool -> string -> a -> a 912 ``` 913 */ 914 throwIf = cond: msg: if cond then throw msg else x: x; 915 916 /** 917 Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise. 918 919 # Inputs 920 921 `msg` 922 923 : 1\. Function argument 924 925 `valid` 926 927 : 2\. Function argument 928 929 `given` 930 931 : 3\. Function argument 932 933 # Type 934 935 ``` 936 String -> List ComparableVal -> List ComparableVal -> a -> a 937 ``` 938 939 # Examples 940 :::{.example} 941 ## `lib.trivial.checkListOfEnum` usage example 942 943 ```nix 944 let colorVariants = ["bright" "dark" "black"] 945 in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants; 946 => 947 error: color variants: bright, black unexpected; valid ones: standard, light, dark 948 ``` 949 950 ::: 951 */ 952 checkListOfEnum = 953 msg: valid: given: 954 let 955 unexpected = lib.subtractLists valid given; 956 in 957 lib.throwIfNot (unexpected == [ ]) 958 "${msg}: ${builtins.concatStringsSep ", " (builtins.map builtins.toString unexpected)} unexpected; valid ones: ${builtins.concatStringsSep ", " (builtins.map builtins.toString valid)}"; 959 960 info = msg: builtins.trace "INFO: ${msg}"; 961 962 showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings; 963 964 ## Function annotations 965 966 /** 967 Add metadata about expected function arguments to a function. 968 The metadata should match the format given by 969 builtins.functionArgs, i.e. a set from expected argument to a bool 970 representing whether that argument has a default or not. 971 setFunctionArgs : (a b) Map String Bool (a b) 972 973 This function is necessary because you can't dynamically create a 974 function of the { a, b ? foo, ... }: format, but some facilities 975 like callPackage expect to be able to query expected arguments. 976 977 # Inputs 978 979 `f` 980 981 : 1\. Function argument 982 983 `args` 984 985 : 2\. Function argument 986 */ 987 setFunctionArgs = f: args: { 988 # TODO: Should we add call-time "type" checking like built in? 989 __functor = self: f; 990 __functionArgs = args; 991 }; 992 993 /** 994 Extract the expected function arguments from a function. 995 This works both with nix-native { a, b ? foo, ... }: style 996 functions and functions with args set with 'setFunctionArgs'. It 997 has the same return type and semantics as builtins.functionArgs. 998 setFunctionArgs : (a b) Map String Bool. 999 1000 # Inputs 1001 1002 `f` 1003 1004 : 1\. Function argument 1005 */ 1006 functionArgs = 1007 f: 1008 if f ? __functor then 1009 f.__functionArgs or (functionArgs (f.__functor f)) 1010 else 1011 builtins.functionArgs f; 1012 1013 /** 1014 Check whether something is a function or something 1015 annotated with function args. 1016 1017 # Inputs 1018 1019 `f` 1020 1021 : 1\. Function argument 1022 */ 1023 isFunction = f: builtins.isFunction f || (f ? __functor && isFunction (f.__functor f)); 1024 1025 /** 1026 `mirrorFunctionArgs f g` creates a new function `g'` with the same behavior as `g` (`g' x == g x`) 1027 but its function arguments mirroring `f` (`lib.functionArgs g' == lib.functionArgs f`). 1028 1029 # Inputs 1030 1031 `f` 1032 1033 : Function to provide the argument metadata 1034 1035 `g` 1036 1037 : Function to set the argument metadata to 1038 1039 # Type 1040 1041 ``` 1042 mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c) 1043 ``` 1044 1045 # Examples 1046 :::{.example} 1047 ## `lib.trivial.mirrorFunctionArgs` usage example 1048 1049 ```nix 1050 addab = {a, b}: a + b 1051 addab { a = 2; b = 4; } 1052 => 6 1053 lib.functionArgs addab 1054 => { a = false; b = false; } 1055 addab1 = attrs: addab attrs + 1 1056 addab1 { a = 2; b = 4; } 1057 => 7 1058 lib.functionArgs addab1 1059 => { } 1060 addab1' = lib.mirrorFunctionArgs addab addab1 1061 addab1' { a = 2; b = 4; } 1062 => 7 1063 lib.functionArgs addab1' 1064 => { a = false; b = false; } 1065 ``` 1066 1067 ::: 1068 */ 1069 mirrorFunctionArgs = 1070 f: 1071 let 1072 fArgs = functionArgs f; 1073 in 1074 g: setFunctionArgs g fArgs; 1075 1076 /** 1077 Turns any non-callable values into constant functions. 1078 Returns callable values as is. 1079 1080 # Inputs 1081 1082 `v` 1083 1084 : Any value 1085 1086 # Examples 1087 :::{.example} 1088 ## `lib.trivial.toFunction` usage example 1089 1090 ```nix 1091 nix-repl> lib.toFunction 1 2 1092 1 1093 1094 nix-repl> lib.toFunction (x: x + 1) 2 1095 3 1096 ``` 1097 1098 ::: 1099 */ 1100 toFunction = v: if isFunction v then v else k: v; 1101 1102 /** 1103 Convert a hexadecimal string to it's integer representation. 1104 1105 # Type 1106 1107 ``` 1108 fromHexString :: String -> [ String ] 1109 ``` 1110 1111 # Examples 1112 1113 ```nix 1114 fromHexString "FF" 1115 => 255 1116 1117 fromHexString (builtins.hashString "sha256" "test") 1118 => 9223372036854775807 1119 ``` 1120 */ 1121 fromHexString = 1122 value: 1123 let 1124 noPrefix = lib.strings.removePrefix "0x" (lib.strings.toLower value); 1125 in 1126 let 1127 parsed = builtins.fromTOML "v=0x${noPrefix}"; 1128 in 1129 parsed.v; 1130 1131 /** 1132 Convert the given positive integer to a string of its hexadecimal 1133 representation. For example: 1134 1135 toHexString 0 => "0" 1136 1137 toHexString 16 => "10" 1138 1139 toHexString 250 => "FA" 1140 */ 1141 toHexString = 1142 let 1143 hexDigits = { 1144 "10" = "A"; 1145 "11" = "B"; 1146 "12" = "C"; 1147 "13" = "D"; 1148 "14" = "E"; 1149 "15" = "F"; 1150 }; 1151 toHexDigit = d: if d < 10 then toString d else hexDigits.${toString d}; 1152 in 1153 i: lib.concatMapStrings toHexDigit (toBaseDigits 16 i); 1154 1155 /** 1156 `toBaseDigits base i` converts the positive integer i to a list of its 1157 digits in the given base. For example: 1158 1159 toBaseDigits 10 123 => [ 1 2 3 ] 1160 1161 toBaseDigits 2 6 => [ 1 1 0 ] 1162 1163 toBaseDigits 16 250 => [ 15 10 ] 1164 1165 # Inputs 1166 1167 `base` 1168 1169 : 1\. Function argument 1170 1171 `i` 1172 1173 : 2\. Function argument 1174 */ 1175 toBaseDigits = 1176 base: i: 1177 let 1178 go = 1179 i: 1180 if i < base then 1181 [ i ] 1182 else 1183 let 1184 r = i - ((i / base) * base); 1185 q = (i - r) / base; 1186 in 1187 [ r ] ++ go q; 1188 in 1189 assert (isInt base); 1190 assert (isInt i); 1191 assert (base >= 2); 1192 assert (i >= 0); 1193 lib.reverseList (go i); 1194}