diff options
author | Vincent Ambo <mail@tazj.in> | 2022-08-13T23·32+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-08-30T16·53+0000 |
commit | c4f73eecdca23ea3adaed5584224046ffdd99b4c (patch) | |
tree | 294fc80f408980f2c5dc7854db3f50c7d95310df /tvix/eval | |
parent | 2ea71aa4c39ff6b200e06f626aaacf8100c19a78 (diff) |
feat(tvix/eval): implement attribute set equality r/4536
Change-Id: Ia25f02610f2575e5e7fca81643e05b40f4a07820 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6200 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval')
-rw-r--r-- | tvix/eval/src/value/attrs.rs | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/tvix/eval/src/value/attrs.rs b/tvix/eval/src/value/attrs.rs index a6dfd383d74a..cc4c02df3841 100644 --- a/tvix/eval/src/value/attrs.rs +++ b/tvix/eval/src/value/attrs.rs @@ -95,8 +95,54 @@ impl Display for NixAttrs { } impl PartialEq for NixAttrs { - fn eq(&self, _other: &Self) -> bool { - todo!("attrset equality") + fn eq(&self, other: &Self) -> bool { + match (&self.0, &other.0) { + (AttrsRep::Empty, AttrsRep::Empty) => true, + + // It is possible to create an empty attribute set that + // has Map representation like so: ` { ${null} = 1; }`. + // + // Preventing this would incur a cost on all attribute set + // construction (we'd have to check the actual number of + // elements after key construction). In practice this + // probably does not happen, so it's better to just bite + // the bullet and implement this branch. + (AttrsRep::Empty, AttrsRep::Map(map)) | (AttrsRep::Map(map), AttrsRep::Empty) => { + map.is_empty() + } + + // Other specialised representations (KV ...) definitely + // do not match `Empty`. + (AttrsRep::Empty, _) | (_, AttrsRep::Empty) => false, + + ( + AttrsRep::KV { + name: n1, + value: v1, + }, + AttrsRep::KV { + name: n2, + value: v2, + }, + ) => n1 == n2 && v1 == v2, + + (AttrsRep::Map(map), AttrsRep::KV { name, value }) + | (AttrsRep::KV { name, value }, AttrsRep::Map(map)) => { + if map.len() != 2 { + return false; + } + + if let (Some(m_name), Some(m_value)) = + (map.get(&NixString::NAME), map.get(&NixString::VALUE)) + { + return name == m_name && value == m_value; + } + + false + } + + (AttrsRep::Map(m1), AttrsRep::Map(m2)) => m1 == m2, + } } } |