Merge pull request #269552 from adisbladis/lib-matchattrs-list-allocs
lib.attrsets.matchAttrs: Avoid some list allocations when walking structure
This commit is contained in:
commit
51357572f2
2 changed files with 40 additions and 9 deletions
|
@ -897,7 +897,10 @@ rec {
|
||||||
recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs;
|
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:
|
Example:
|
||||||
matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
|
matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
|
||||||
|
@ -909,16 +912,24 @@ rec {
|
||||||
matchAttrs =
|
matchAttrs =
|
||||||
# Attribute set structure to match
|
# Attribute set structure to match
|
||||||
pattern:
|
pattern:
|
||||||
# Attribute set to find patterns in
|
# Attribute set to check
|
||||||
attrs:
|
attrs:
|
||||||
assert isAttrs pattern;
|
assert isAttrs pattern;
|
||||||
all id (attrValues (zipAttrsWithNames (attrNames pattern) (n: values:
|
all
|
||||||
let pat = head values; val = elemAt values 1; in
|
( # Compare equality between `pattern` & `attrs`.
|
||||||
if length values == 1 then false
|
attr:
|
||||||
else if isAttrs pat then isAttrs val && matchAttrs pat val
|
# Missing attr, not equal.
|
||||||
else pat == val
|
attrs ? ${attr} && (
|
||||||
) [pattern attrs]));
|
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
|
/* Override only the attributes that are already present in the old set
|
||||||
useful for deep-overriding.
|
useful for deep-overriding.
|
||||||
|
|
|
@ -831,6 +831,26 @@ runTests {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
testMatchAttrsMatchingExact = {
|
||||||
|
expr = matchAttrs { cpu = { bits = 64; }; } { cpu = { bits = 64; }; };
|
||||||
|
expected = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMatchAttrsMismatch = {
|
||||||
|
expr = matchAttrs { cpu = { bits = 128; }; } { cpu = { bits = 64; }; };
|
||||||
|
expected = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMatchAttrsMatchingImplicit = {
|
||||||
|
expr = matchAttrs { cpu = { }; } { cpu = { bits = 64; }; };
|
||||||
|
expected = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMatchAttrsMissingAttrs = {
|
||||||
|
expr = matchAttrs { cpu = {}; } { };
|
||||||
|
expected = false;
|
||||||
|
};
|
||||||
|
|
||||||
testOverrideExistingEmpty = {
|
testOverrideExistingEmpty = {
|
||||||
expr = overrideExisting {} { a = 1; };
|
expr = overrideExisting {} { a = 1; };
|
||||||
expected = {};
|
expected = {};
|
||||||
|
|
Loading…
Reference in a new issue