diff options
author | Roman Perehonchuk <romanp@meta.com> | 2024-10-01 02:42:33 -0700 |
---|---|---|
committer | Facebook GitHub Bot <facebook-github-bot@users.noreply.github.com> | 2024-10-01 02:42:33 -0700 |
commit | 35ea4c97b0ea05f41835b1c0ddb28ba6e96a9429 (patch) | |
tree | 5b46e697e775134f16158b3ecd64a476f3503ed1 | |
parent | 34930ceea65028fe0947d35228b6119634c0cd24 (diff) |
bit and
Summary: this diff was split from the next one
Reviewed By: stepancheg
Differential Revision: D63526160
fbshipit-source-id: e08cc0be755597afdd301181953a2e81e665db05
-rw-r--r-- | starlark/src/values/types/set/value.rs | 46 | ||||
-rw-r--r-- | starlark/testcases/eval/go/set.star | 6 |
2 files changed, 49 insertions, 3 deletions
diff --git a/starlark/src/values/types/set/value.rs b/starlark/src/values/types/set/value.rs index 3158e7f8..2212a406 100644 --- a/starlark/src/values/types/set/value.rs +++ b/starlark/src/values/types/set/value.rs @@ -258,6 +258,24 @@ where } Ok(heap.alloc(SetData { content: items })) } + + // Set intersection + fn bit_and(&self, rhs: Value<'v>, heap: &'v Heap) -> crate::Result<Value<'v>> { + let mut items = SmallSet::new(); + if self.0.content().is_empty() { + return Ok(heap.alloc(SetData { content: items })); + } + let rhs = SetRef::from_value(rhs) + .map_or_else(|| ValueError::unsupported_with(self, "&", rhs), Ok)?; + + for h in rhs.iter_hashed() { + if self.0.content().contains_hashed(h.as_ref()) { + items.insert_hashed_unique_unchecked(h); + } + } + + Ok(heap.alloc(SetData { content: items })) + } } impl<'v, T: SetLike<'v>> Serialize for SetGen<T> { @@ -306,4 +324,32 @@ mod tests { fn test_bit_or_ord() { assert::eq("list(set([5, 1, 3]) | set([4, 5, 2]))", "[5, 1, 3, 4, 2]") } + + #[test] + fn test_bit_and() { + assert::eq("set([1, 2, 3]) & set([3, 4])", "set([3])") + } + + #[test] + fn test_bit_and_lhs_empty() { + assert::eq("set() & set([3, 4])", "set([])") + } + + #[test] + fn test_bit_and_rhs_empty() { + assert::eq("set([1, 2, 3]) & set()", "set([])") + } + + #[test] + fn test_bit_and_ord() { + assert::eq("list(set([1, 2, 3]) & set([4, 3, 1]))", "[3, 1]") + } + + #[test] + fn test_bit_and_fail_iter() { + assert::fail( + "set([1, 2, 3]) & []", + "Operation `&` not supported for types `set` and `list`", + ); + } } diff --git a/starlark/testcases/eval/go/set.star b/starlark/testcases/eval/go/set.star index 77ca85a0..0945b643 100644 --- a/starlark/testcases/eval/go/set.star +++ b/starlark/testcases/eval/go/set.star @@ -67,9 +67,9 @@ asserts.eq(list(x.union([5, 1])), [1, 2, 3, 5]) asserts.eq(list(x.union((6, 5, 4))), [1, 2, 3, 6, 5, 4]) asserts.fails(lambda : x.union([1, 2, {}]), "unhashable type: dict") -# # intersection, set & set or set.intersection(iterable) -# asserts.eq(list(set("a".elems()) & set("b".elems())), []) -# asserts.eq(list(set("ab".elems()) & set("bc".elems())), ["b"]) +# intersection, set & set or set.intersection(iterable) +asserts.eq(list(set("a".elems()) & set("b".elems())), []) +asserts.eq(list(set("ab".elems()) & set("bc".elems())), ["b"]) # asserts.eq(list(set("a".elems()).intersection("b".elems())), []) # asserts.eq(list(set("ab".elems()).intersection("bc".elems())), ["b"]) |