From 3f2bbd77d46faa049d751c6d56adf5716ef031d6 Mon Sep 17 00:00:00 2001 From: Ori Ziv Date: Sun, 19 May 2024 10:44:22 +0300 Subject: [PATCH] High level support and testsing for span-to-fixed-sized array. commit-id:d131660d --- corelib/src/array.cairo | 26 +++++++++++++++++++++ corelib/src/test/array_test.cairo | 17 ++++++++++++++ corelib/src/traits.cairo | 38 +++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/corelib/src/array.cairo b/corelib/src/array.cairo index 034d2f4b732..8380558cfeb 100644 --- a/corelib/src/array.cairo +++ b/corelib/src/array.cairo @@ -256,6 +256,32 @@ impl EmptyFixedSizeArrayImpl> of ToSpanTrait<[T; 0], T> { } } +/// Returns a box of struct of members of the same type from a span. +/// The additional `+Copy<@T>` arg is to prevent later stages from propagating the `S` type Sierra +/// level, where it is deduced by the `T` type. +extern fn tuple_from_span, S>(span: @Array) -> Option<@Box> nopanic; + +/// Implements `TryInto` for only copyable types +impl SpanTryIntoFixedSizedArray< + T, const SIZE: usize, -TypeEqual<[T; SIZE], [T; 0]> +> of TryInto, @Box<[T; SIZE]>> { + #[inline(always)] + fn try_into(self: Span) -> Option<@Box<[T; SIZE]>> { + tuple_from_span(self.snapshot) + } +} + +impl SpanTryIntoEmptyFixedSizedArray> of TryInto, @Box<[T; 0]>> { + #[inline(always)] + fn try_into(self: Span) -> Option<@Box<[T; 0]>> { + if self.is_empty() { + Option::Some(@BoxTrait::new([])) + } else { + Option::None + } + } +} + // TODO(spapini): Remove TDrop. It is necessary to get rid of response in case of panic. impl ArrayTCloneImpl, +Drop> of Clone> { fn clone(self: @Array) -> Array { diff --git a/corelib/src/test/array_test.cairo b/corelib/src/test/array_test.cairo index 9a5a00077d7..a2e5fd10d28 100644 --- a/corelib/src/test/array_test.cairo +++ b/corelib/src/test/array_test.cairo @@ -145,3 +145,20 @@ fn test_fixed_size_array_copy() { consume(arr); consume(arr); } + +/// Helper for tests removing the box wrapping a fixed sized array wrapped by an option. +fn debox(value: Option<@Box<[T; SIZE]>>) -> Option<@[T; SIZE]> { + Option::Some(value?.as_snapshot().unbox()) +} + +#[test] +fn test_span_into_fixed_size_array() { + assert!(debox::([10, 11, 12].span().try_into()).is_none()); + assert!(debox::([10, 11, 12].span().try_into()) == Option::Some(@[10, 11, 12])); + assert!(debox::([10, 11, 12].span().try_into()).is_none()); + assert!(debox::([10, 11, 12].span().try_into()).is_none()); + assert!(debox::([10, 11, 12].span().try_into()) == Option::Some(@[10, 11, 12])); + assert!(debox::([10, 11, 12].span().try_into()).is_none()); + assert!(debox::([].span().try_into()).is_none()); + assert!(debox::([].span().try_into()) == Option::Some(@[])); +} diff --git a/corelib/src/traits.cairo b/corelib/src/traits.cairo index 215983add3d..fc147c0d5bb 100644 --- a/corelib/src/traits.cairo +++ b/corelib/src/traits.cairo @@ -296,3 +296,41 @@ impl TupleSize4Default< impl FixedSizedArrayDrop, const N: u32> of Drop<[T; N]>; impl FixedSizedArrayCopy, const N: u32> of Copy<[T; N]>; + +impl FixedSizedArraySize0PartialEq> of PartialEq<[T; 0]> { + fn eq(lhs: @[T; 0], rhs: @[T; 0]) -> bool { + true + } +} + +impl FixedSizedArraySize1PartialEq> of PartialEq<[T; 1]> { + fn eq(lhs: @[T; 1], rhs: @[T; 1]) -> bool { + let [lhs] = lhs; + let [rhs] = rhs; + rhs == lhs + } +} + +impl FixedSizedArraySize2PartialEq> of PartialEq<[T; 2]> { + fn eq(lhs: @[T; 2], rhs: @[T; 2]) -> bool { + let [lhs0, lhs1] = lhs; + let [rhs0, rhs1] = rhs; + (lhs0, lhs1) == (rhs0, rhs1) + } +} + +impl FixedSizedArraySize3PartialEq> of PartialEq<[T; 3]> { + fn eq(lhs: @[T; 3], rhs: @[T; 3]) -> bool { + let [lhs0, lhs1, lhs2] = lhs; + let [rhs0, rhs1, rhs2] = rhs; + (lhs0, lhs1, lhs2) == (rhs0, rhs1, rhs2) + } +} + +impl FixedSizedArraySize4PartialEq> of PartialEq<[T; 4]> { + fn eq(lhs: @[T; 4], rhs: @[T; 4]) -> bool { + let [lhs0, lhs1, lhs2, lhs3] = lhs; + let [rhs0, rhs1, rhs2, rhs3] = rhs; + (lhs0, lhs1, lhs2, lhs3) == (rhs0, rhs1, rhs2, rhs3) + } +}