diff options
author | Alyssa Ross <hi@alyssa.is> | 2023-12-01 19:00:09 +0100 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2023-12-01 19:00:09 +0100 |
commit | 9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d (patch) | |
tree | 4368f9e4cb2d5b93a956c085337e45cb70f1e331 /nixpkgs/lib/attrsets.nix | |
parent | a9cbfb6941b47d6f50129e6e36927882392daed7 (diff) | |
parent | 2344fe1da14cb08b0c18743b207995f9b8597915 (diff) | |
download | nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar.gz nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar.bz2 nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar.lz nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar.xz nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar.zst nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.zip |
Merge https://github.com/NixOS/nixpkgs
Diffstat (limited to 'nixpkgs/lib/attrsets.nix')
-rw-r--r-- | nixpkgs/lib/attrsets.nix | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/nixpkgs/lib/attrsets.nix b/nixpkgs/lib/attrsets.nix index b0460ab139e8..3d4366ce1814 100644 --- a/nixpkgs/lib/attrsets.nix +++ b/nixpkgs/lib/attrsets.nix @@ -1,5 +1,5 @@ +/* Operations on attribute sets. */ { lib }: -# Operations on attribute sets. let inherit (builtins) head tail length; @@ -34,12 +34,20 @@ rec { default: # The nested attribute set to select values from set: - let attr = head attrPath; + let + lenAttrPath = length attrPath; + attrByPath' = n: s: ( + if n == lenAttrPath then s + else ( + let + attr = elemAt attrPath n; + in + if s ? ${attr} then attrByPath' (n + 1) s.${attr} + else default + ) + ); in - if attrPath == [] then set - else if set ? ${attr} - then attrByPath (tail attrPath) default set.${attr} - else default; + attrByPath' 0 set; /* Return if an attribute from nested attribute set exists. @@ -58,13 +66,19 @@ rec { attrPath: # The nested attribute set to check e: - let attr = head attrPath; + let + lenAttrPath = length attrPath; + hasAttrByPath' = n: s: ( + n == lenAttrPath || ( + let + attr = elemAt attrPath n; + in + if s ? ${attr} then hasAttrByPath' (n + 1) s.${attr} + else false + ) + ); in - if attrPath == [] then true - else if e ? ${attr} - then hasAttrByPath (tail attrPath) e.${attr} - else false; - + hasAttrByPath' 0 e; /* Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`. @@ -883,7 +897,10 @@ rec { recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs; - /* Returns true if the pattern is contained in the set. False otherwise. + /* + Recurse into every attribute set of the first argument and check that: + - Each attribute path also exists in the second argument. + - If the attribute's value is not a nested attribute set, it must have the same value in the right argument. Example: matchAttrs { cpu = {}; } { cpu = { bits = 64; }; } @@ -895,16 +912,24 @@ rec { matchAttrs = # Attribute set structure to match pattern: - # Attribute set to find patterns in + # Attribute set to check attrs: assert isAttrs pattern; - all id (attrValues (zipAttrsWithNames (attrNames pattern) (n: values: - let pat = head values; val = elemAt values 1; in - if length values == 1 then false - else if isAttrs pat then isAttrs val && matchAttrs pat val - else pat == val - ) [pattern attrs])); - + all + ( # Compare equality between `pattern` & `attrs`. + attr: + # Missing attr, not equal. + attrs ? ${attr} && ( + let + lhs = pattern.${attr}; + rhs = attrs.${attr}; + in + # If attrset check recursively + if isAttrs lhs then isAttrs rhs && matchAttrs lhs rhs + else lhs == rhs + ) + ) + (attrNames pattern); /* Override only the attributes that are already present in the old set useful for deep-overriding. |