From d71f2e338f35b07a7d93833840c75903d194c2ae Mon Sep 17 00:00:00 2001 From: Marcus Liotta Date: Thu, 5 Oct 2023 19:57:46 +0200 Subject: [PATCH 1/9] added --- .tool-versions | 2 +- Scarb.toml | 2 +- src/data_structures/src/array_ext.cairo | 150 +++------ src/data_structures/src/byte_array_ext.cairo | 215 +++++++++++++ .../src/byte_array_reader.cairo | 126 ++++++++ src/data_structures/src/lib.cairo | 2 + src/data_structures/src/tests.cairo | 2 + .../src/tests/byte_array_ext_test.cairo | 299 ++++++++++++++++++ .../src/tests/byte_array_reader_test.cairo | 81 +++++ 9 files changed, 774 insertions(+), 105 deletions(-) create mode 100644 src/data_structures/src/byte_array_ext.cairo create mode 100644 src/data_structures/src/byte_array_reader.cairo create mode 100644 src/data_structures/src/tests/byte_array_ext_test.cairo create mode 100644 src/data_structures/src/tests/byte_array_reader_test.cairo diff --git a/.tool-versions b/.tool-versions index ce84f339..54917fa6 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -scarb 0.7.0 \ No newline at end of file +scarb 2.3.0-rc0 diff --git a/Scarb.toml b/Scarb.toml index c0407850..a5c36f72 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -16,7 +16,7 @@ description = "Community maintained Cairo and Starknet libraries" homepage = "https://github.com/keep-starknet-strange/alexandria/" [workspace.dependencies] -starknet = ">=2.2.0" +starknet = ">=2.3.0-rc0" [scripts] all = "scarb build && scarb test" diff --git a/src/data_structures/src/array_ext.cairo b/src/data_structures/src/array_ext.cairo index aa022d3d..2fc6f898 100644 --- a/src/data_structures/src/array_ext.cairo +++ b/src/data_structures/src/array_ext.cairo @@ -67,12 +67,8 @@ impl ArrayImpl, impl TDrop: Drop> of ArrayTraitExt break; } match self.pop_front() { - Option::Some(v) => { - n -= 1; - }, - Option::None => { - break; - }, + Option::Some(v) => { n -= 1; }, + Option::None => { break; }, }; }; } @@ -156,12 +152,8 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { break; } match self.pop_front() { - Option::Some(v) => { - n -= 1; - }, - Option::None => { - break; - }, + Option::Some(v) => { n -= 1; }, + Option::None => { break; }, }; }; } @@ -172,12 +164,8 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { break; } match self.pop_back() { - Option::Some(v) => { - n -= 1; - }, - Option::None => { - break; - }, + Option::Some(v) => { n -= 1; }, + Option::None => { break; }, }; }; } @@ -186,9 +174,7 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut response = array![]; loop { match self.pop_back() { - Option::Some(v) => { - response.append(*v); - }, + Option::Some(v) => { response.append(*v); }, Option::None => { break; // Can't `break response;` "Variable was previously moved" }, @@ -200,14 +186,10 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { fn contains>(mut self: Span, item: T) -> bool { loop { match self.pop_front() { - Option::Some(v) => { - if *v == item { - break true; - } - }, - Option::None => { - break false; - }, + Option::Some(v) => { if *v == item { + break true; + } }, + Option::None => { break false; }, }; } } @@ -244,9 +226,7 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { } index += 1; }, - Option::None => { - break Option::None; - }, + Option::None => { break Option::None; }, }; } } @@ -255,14 +235,10 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut count = 0_usize; loop { match self.pop_front() { - Option::Some(v) => { - if *v == item { - count += 1; - } - }, - Option::None => { - break count; - }, + Option::Some(v) => { if *v == item { + count += 1; + } }, + Option::None => { break count; }, }; } } @@ -272,20 +248,14 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { ) -> Option { let mut min = match self.pop_front() { Option::Some(item) => *item, - Option::None => { - return Option::None; - }, + Option::None => { return Option::None; }, }; loop { match self.pop_front() { - Option::Some(item) => { - if *item < min { - min = *item - } - }, - Option::None => { - break Option::Some(min); - }, + Option::Some(item) => { if *item < min { + min = *item + } }, + Option::None => { break Option::Some(min); }, }; } } @@ -297,21 +267,15 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut index_of_min = 0; let mut min: T = match self.pop_front() { Option::Some(item) => *item, - Option::None => { - return Option::None; - }, + Option::None => { return Option::None; }, }; loop { match self.pop_front() { - Option::Some(item) => { - if *item < min { - index_of_min = index + 1; - min = *item; - } - }, - Option::None => { - break Option::Some(index_of_min); - }, + Option::Some(item) => { if *item < min { + index_of_min = index + 1; + min = *item; + } }, + Option::None => { break Option::Some(index_of_min); }, }; index += 1; } @@ -322,20 +286,14 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { ) -> Option { let mut max = match self.pop_front() { Option::Some(item) => *item, - Option::None => { - return Option::None; - }, + Option::None => { return Option::None; }, }; loop { match self.pop_front() { - Option::Some(item) => { - if *item > max { - max = *item - } - }, - Option::None => { - break Option::Some(max); - }, + Option::Some(item) => { if *item > max { + max = *item + } }, + Option::None => { break Option::Some(max); }, }; } } @@ -347,21 +305,15 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut index_of_max = 0; let mut max = match self.pop_front() { Option::Some(item) => *item, - Option::None => { - return Option::None; - }, + Option::None => { return Option::None; }, }; loop { match self.pop_front() { - Option::Some(item) => { - if *item > max { - index_of_max = index + 1; - max = *item - } - }, - Option::None => { - break Option::Some(index_of_max); - }, + Option::Some(item) => { if *item > max { + index_of_max = index + 1; + max = *item + } }, + Option::None => { break Option::Some(index_of_max); }, }; index += 1; } @@ -377,15 +329,11 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { loop { match self.pop_front() { - Option::Some(v) => { - if (last_value != v) { - last_value = v; - ret.append(*v); - }; - }, - Option::None => { - break; - } + Option::Some(v) => { if (last_value != v) { + last_value = v; + ret.append(*v); + }; }, + Option::None => { break; } }; }; @@ -396,14 +344,10 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut ret = array![]; loop { match self.pop_front() { - Option::Some(v) => { - if !ret.contains(*v) { - ret.append(*v); - } - }, - Option::None => { - break; - } + Option::Some(v) => { if !ret.contains(*v) { + ret.append(*v); + } }, + Option::None => { break; } }; }; ret diff --git a/src/data_structures/src/byte_array_ext.cairo b/src/data_structures/src/byte_array_ext.cairo new file mode 100644 index 00000000..e93fcc71 --- /dev/null +++ b/src/data_structures/src/byte_array_ext.cairo @@ -0,0 +1,215 @@ +use alexandria_data_structures::byte_array_reader::{ByteArrayReader, ByteArrayReaderTrait}; +use array::{serialize_array_helper, deserialize_array_helper}; +use byte_array::ByteArray; +use bytes_31::{one_shift_left_bytes_felt252, one_shift_left_bytes_u128, BYTES_IN_BYTES31}; +use integer::u512; +use traits::DivRem; +use core::serde::into_felt252_based::SerdeImpl; + +trait ByteArrayTraitExt { + fn append_u16(ref self: ByteArray, word: u16); + fn append_u32(ref self: ByteArray, word: u32); + fn append_u64(ref self: ByteArray, word: u64); + fn append_u128(ref self: ByteArray, word: u128); + fn append_u256(ref self: ByteArray, word: u256); + fn append_u512(ref self: ByteArray, word: u512); + fn append_i8(ref self: ByteArray, word: i8); + fn append_i16(ref self: ByteArray, word: i16); + fn append_i32(ref self: ByteArray, word: i32); + fn append_i64(ref self: ByteArray, word: i64); + fn append_i128(ref self: ByteArray, word: i128); + fn word_u16(self: @ByteArray, offset: usize) -> Option; + fn word_u32(self: @ByteArray, offset: usize) -> Option; + fn word_u64(self: @ByteArray, offset: usize) -> Option; + fn word_u128(self: @ByteArray, offset: usize) -> Option; + fn reader(self: @ByteArray) -> ByteArrayReader; +} + +impl ByteArrayImpl of ByteArrayTraitExt { + fn append_u16(ref self: ByteArray, word: u16) { + self.append_word(word.into(), 2); + } + + fn append_u32(ref self: ByteArray, word: u32) { + self.append_word(word.into(), 4); + } + + fn append_u64(ref self: ByteArray, word: u64) { + self.append_word(word.into(), 8); + } + + fn append_u128(ref self: ByteArray, word: u128) { + self.append_word(word.into(), 16); + } + + fn append_u256(ref self: ByteArray, word: u256) { + let u256{low, high } = word; + self.append_u128(high); + self.append_u128(low); + } + + fn append_u512(ref self: ByteArray, word: u512) { + let u512{limb0, limb1, limb2, limb3 } = word; + self.append_u128(limb3); + self.append_u128(limb2); + self.append_u128(limb1); + self.append_u128(limb0); + } + + fn append_i8(ref self: ByteArray, word: i8) { + if word >= 0_i8 { + self.append_word(word.into(), 1); + } else { + self.append_word(word.into() + one_shift_left_bytes_felt252(1), 1); + } + } + + fn append_i16(ref self: ByteArray, word: i16) { + if word >= 0_i16 { + self.append_word(word.into(), 2); + } else { + self.append_word(word.into() + one_shift_left_bytes_felt252(2), 2); + } + } + + fn append_i32(ref self: ByteArray, word: i32) { + if word >= 0_i32 { + self.append_word(word.into(), 4); + } else { + self.append_word(word.into() + one_shift_left_bytes_felt252(4), 4); + } + } + + fn append_i64(ref self: ByteArray, word: i64) { + if word >= 0_i64 { + self.append_word(word.into(), 8); + } else { + self.append_word(word.into() + one_shift_left_bytes_felt252(8), 8); + } + } + + fn append_i128(ref self: ByteArray, word: i128) { + if word >= 0_i128 { + self.append_word(word.into(), 16); + } else { + self.append_word(word.into() + one_shift_left_bytes_felt252(16), 16); + } + } + + fn word_u16(self: @ByteArray, offset: usize) -> Option { + let b1 = self.at(offset)?; + let b2 = self.at(offset + 1)?; + Option::Some(b1.into() * one_shift_left_bytes_u128(1).try_into().unwrap() + b2.into()) + } + + fn word_u32(self: @ByteArray, offset: usize) -> Option { + let b1 = self.at(offset)?; + let b2 = self.at(offset + 1)?; + let b3 = self.at(offset + 2)?; + let b4 = self.at(offset + 3)?; + Option::Some( + b1.into() * one_shift_left_bytes_u128(3).try_into().unwrap() + + b2.into() * one_shift_left_bytes_u128(2).try_into().unwrap() + + b3.into() * one_shift_left_bytes_u128(1).try_into().unwrap() + + b4.into() + ) + } + + fn word_u64(self: @ByteArray, offset: usize) -> Option { + let b1 = self.at(offset)?; + let b2 = self.at(offset + 1)?; + let b3 = self.at(offset + 2)?; + let b4 = self.at(offset + 3)?; + let b5 = self.at(offset + 4)?; + let b6 = self.at(offset + 5)?; + let b7 = self.at(offset + 6)?; + let b8 = self.at(offset + 7)?; + Option::Some( + b1.into() * one_shift_left_bytes_u128(7).try_into().unwrap() + + b2.into() * one_shift_left_bytes_u128(6).try_into().unwrap() + + b3.into() * one_shift_left_bytes_u128(5).try_into().unwrap() + + b4.into() * one_shift_left_bytes_u128(4).try_into().unwrap() + + b5.into() * one_shift_left_bytes_u128(3).try_into().unwrap() + + b6.into() * one_shift_left_bytes_u128(2).try_into().unwrap() + + b7.into() * one_shift_left_bytes_u128(1).try_into().unwrap() + + b8.into() + ) + } + + fn word_u128(self: @ByteArray, offset: usize) -> Option { + let b01 = self.at(offset)?; + let b02 = self.at(offset + 1)?; + let b03 = self.at(offset + 2)?; + let b04 = self.at(offset + 3)?; + let b05 = self.at(offset + 4)?; + let b06 = self.at(offset + 5)?; + let b07 = self.at(offset + 6)?; + let b08 = self.at(offset + 7)?; + let b09 = self.at(offset + 8)?; + let b10 = self.at(offset + 9)?; + let b11 = self.at(offset + 10)?; + let b12 = self.at(offset + 11)?; + let b13 = self.at(offset + 12)?; + let b14 = self.at(offset + 13)?; + let b15 = self.at(offset + 14)?; + let b16 = self.at(offset + 15)?; + Option::Some( + b01.into() * one_shift_left_bytes_u128(15).try_into().unwrap() + + b02.into() * one_shift_left_bytes_u128(14).try_into().unwrap() + + b03.into() * one_shift_left_bytes_u128(13).try_into().unwrap() + + b04.into() * one_shift_left_bytes_u128(12).try_into().unwrap() + + b05.into() * one_shift_left_bytes_u128(11).try_into().unwrap() + + b06.into() * one_shift_left_bytes_u128(10).try_into().unwrap() + + b07.into() * one_shift_left_bytes_u128(09).try_into().unwrap() + + b08.into() * one_shift_left_bytes_u128(08).try_into().unwrap() + + b09.into() * one_shift_left_bytes_u128(07).try_into().unwrap() + + b10.into() * one_shift_left_bytes_u128(06).try_into().unwrap() + + b11.into() * one_shift_left_bytes_u128(05).try_into().unwrap() + + b12.into() * one_shift_left_bytes_u128(04).try_into().unwrap() + + b13.into() * one_shift_left_bytes_u128(03).try_into().unwrap() + + b14.into() * one_shift_left_bytes_u128(02).try_into().unwrap() + + b15.into() * one_shift_left_bytes_u128(01).try_into().unwrap() + + b16.into() + ) + } + + fn reader(self: @ByteArray) -> ByteArrayReader { + ByteArrayReaderTrait::new(self) + } +} + +impl ByteArraySerde of Serde { + fn serialize(self: @ByteArray, ref output: Array) { + let len = self.len(); + len.serialize(ref output); + let bytes31_arr = self.data.span(); + serialize_array_helper(bytes31_arr, ref output); + + if (*self.pending_word_len > 0) { + output.append(*self.pending_word); + } + } + + fn deserialize(ref serialized: Span) -> Option { + let length = *serialized.pop_front()?; + let length: usize = length.try_into().unwrap(); + let denominator: NonZero = BYTES_IN_BYTES31.try_into().unwrap(); + let (felt_length, pending_word_len) = DivRem::div_rem(length, denominator); + let mut arr: Array = array![]; + let bytes31_arr = deserialize_array_helper(ref serialized, arr, felt_length.into())?; + + let pending_word = if pending_word_len > 0 { + *serialized.pop_front()? + } else { + 0 + }; + + Option::Some( + ByteArray { + data: bytes31_arr, + pending_word: pending_word, + pending_word_len: pending_word_len.try_into().unwrap() + } + ) + } +} diff --git a/src/data_structures/src/byte_array_reader.cairo b/src/data_structures/src/byte_array_reader.cairo new file mode 100644 index 00000000..7bfad7ee --- /dev/null +++ b/src/data_structures/src/byte_array_reader.cairo @@ -0,0 +1,126 @@ +use integer::u512; +use bytes_31::one_shift_left_bytes_felt252; +use byte_array::ByteArray; +use alexandria_data_structures::byte_array_ext::ByteArrayTraitExt; +use core::clone::Clone; + +#[derive(Copy, Drop)] +struct ByteArrayReader { + data: @ByteArray, + reader_index: usize, +} + +#[generate_trait] +impl ByteArrayReaderImpl of ByteArrayReaderTrait { + fn new(from: @ByteArray) -> ByteArrayReader { + ByteArrayReader { data: from, reader_index: 0, } + } + + fn read_u8(ref self: ByteArrayReader) -> Option { + let byte = self.data.at(self.reader_index)?; + self.reader_index += 1; + Option::Some(byte) + } + + fn read_u16(ref self: ByteArrayReader) -> Option { + let result = self.data.word_u16(self.reader_index)?; + self.reader_index += 2; + Option::Some(result) + } + + fn read_u32(ref self: ByteArrayReader) -> Option { + let result = self.data.word_u32(self.reader_index)?; + self.reader_index += 4; + Option::Some(result) + } + + fn read_u64(ref self: ByteArrayReader) -> Option { + let result = self.data.word_u64(self.reader_index)?; + self.reader_index += 8; + Option::Some(result) + } + + fn read_u128(ref self: ByteArrayReader) -> Option { + let result = self.data.word_u128(self.reader_index)?; + self.reader_index += 16; + Option::Some(result) + } + + fn read_u256(ref self: ByteArrayReader) -> Option { + let result = u256 { + high: self.data.word_u128(self.reader_index)?, + low: self.data.word_u128(self.reader_index + 16)? + }; + self.reader_index += 32; + Option::Some(result) + } + + fn read_u512(ref self: ByteArrayReader) -> Option { + let result = u512 { + limb3: self.data.word_u128(self.reader_index)?, + limb2: self.data.word_u128(self.reader_index + 16)?, + limb1: self.data.word_u128(self.reader_index + 32)?, + limb0: self.data.word_u128(self.reader_index + 48)? + }; + self.reader_index += 64; + Option::Some(result) + } + + fn read_i8(ref self: ByteArrayReader) -> Option { + let felt: felt252 = self.read_u8()?.into(); + Option::Some(parse_signed(felt, 1).unwrap()) + // match felt.try_into() { + // Option::Some(pos) => Option::Some(pos), + // Option::None => { + // let negated: felt252 = felt - 0x100; + // 'negated'.print(); + // negated.print(); + // // - one_shift_left_bytes_felt252(1); + // Option::Some(negated.try_into().unwrap()) + // }, + // } + } + + fn read_i16(ref self: ByteArrayReader) -> Option { + let felt: felt252 = self.read_u16()?.into(); + Option::Some(parse_signed(felt, 2).unwrap()) + } + + fn read_i32(ref self: ByteArrayReader) -> Option { + let felt: felt252 = self.read_u32()?.into(); + Option::Some(parse_signed(felt, 4).unwrap()) + } + + fn read_i64(ref self: ByteArrayReader) -> Option { + let felt: felt252 = self.read_u64()?.into(); + Option::Some(parse_signed(felt, 8).unwrap()) + } + + fn read_i128(ref self: ByteArrayReader) -> Option { + let felt: felt252 = self.read_u128()?.into(); + Option::Some(parse_signed(felt, 16).unwrap()) + } + + // #[inline] + fn len(self: @ByteArrayReader) -> usize { + let byte_array = *self.data; + let byte_array_len = byte_array.len(); + byte_array_len - *self.reader_index + } +} + +fn parse_signed>(value: felt252, bytes: usize) -> Option { + match value.try_into() { + Option::Some(pos) => Option::Some(pos), + Option::None => { + let negated: felt252 = value - one_shift_left_bytes_felt252(bytes); + negated.try_into() + }, + } +} + +// impl ByteArrayReaderCloneImpl of Clone { +// fn clone(self: @ByteArrayReader) -> ByteArrayReader { +// ByteArrayReader { data: *self.data, reader_index: *self.reader_index } +// } +// } \ No newline at end of file diff --git a/src/data_structures/src/lib.cairo b/src/data_structures/src/lib.cairo index ea04bcd6..afdaab53 100644 --- a/src/data_structures/src/lib.cairo +++ b/src/data_structures/src/lib.cairo @@ -1,4 +1,6 @@ mod array_ext; +mod byte_array_ext; +mod byte_array_reader; mod merkle_tree; mod queue; mod stack; diff --git a/src/data_structures/src/tests.cairo b/src/data_structures/src/tests.cairo index 2f1d3e1a..8375bb05 100644 --- a/src/data_structures/src/tests.cairo +++ b/src/data_structures/src/tests.cairo @@ -1,4 +1,6 @@ mod array_ext_test; +mod byte_array_ext_test; +mod byte_array_reader_test; mod merkle_tree_test; mod queue_test; mod stack_test; diff --git a/src/data_structures/src/tests/byte_array_ext_test.cairo b/src/data_structures/src/tests/byte_array_ext_test.cairo new file mode 100644 index 00000000..361bef86 --- /dev/null +++ b/src/data_structures/src/tests/byte_array_ext_test.cairo @@ -0,0 +1,299 @@ +use alexandria_data_structures::byte_array_ext::{ByteArraySerde, ByteArrayTraitExt}; +use integer::u512; + +#[test] +#[available_gas(1000000)] +fn test_append_u16() { + let mut ba: ByteArray = Default::default(); + ba.append_u16(0x0102_u16); + ba.append_u16(0x0304_u16); + ba.append_u16(0x0506_u16); + ba.append_u16(0x0708_u16); + assert(ba == test_byte_array_8(), 'u16 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_u32() { + let mut ba: ByteArray = Default::default(); + ba.append_u32(0x01020304_u32); + ba.append_u32(0x05060708_u32); + assert(ba == test_byte_array_8(), 'u32 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_u64() { + let mut ba: ByteArray = Default::default(); + ba.append_u64(0x0102030405060708_u64); + ba.append_u64(0x090a0b0c0d0e0f10_u64); + assert(ba == test_byte_array_16(), 'u64 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_u128() { + let mut ba: ByteArray = Default::default(); + ba.append_u128(0x0102030405060708090a0b0c0d0e0f10_u128); + ba.append_u128(0x1112131415161718191a1b1c1d1e1f20_u128); + assert(ba == test_byte_array_32(), 'u128 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_u256() { + let mut ba: ByteArray = Default::default(); + let word = u256 { + high: 0x0102030405060708090a0b0c0d0e0f10_u128, low: 0x1112131415161718191a1b1c1d1e1f20_u128, + }; + ba.append_u256(word); + assert(ba == test_byte_array_32(), 'u256 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_u512() { + let test64 = u512 { + limb3: 0x0102030405060708090a0b0c0d0e0f10_u128, + limb2: 0x1112131415161718191a1b1c1d1e1f20_u128, + limb1: 0x2122232425262728292a2b2c2d2e2f30_u128, + limb0: 0x3132333435363738393a3b3c3d3e3f40_u128, + }; + + let mut ba: ByteArray = Default::default(); + ba.append_u512(test64); + assert(ba == test_byte_array_64(), 'test64 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_i8() { + let mut ba1 = Default::default(); + ba1.append_i8(127_i8); + let mut ba2 = Default::default(); + ba2.append_byte(0x7f_u8); + assert(ba1 == ba2, 'i8 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_i8_neg() { + let mut ba1 = Default::default(); + ba1.append_i8(-128_i8); + let mut ba2 = Default::default(); + ba2.append_byte(0x80_u8); + assert(ba1 == ba2, 'negative i8 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_i16() { + let mut ba1 = Default::default(); + ba1.append_i16(0x0102_i16); + ba1.append_i16(0x0304_i16); + ba1.append_i16(0x0506_i16); + ba1.append_i16(0x0708_i16); + assert(ba1 == test_byte_array_8(), 'i16 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_i16_neg() { + let mut ba1 = Default::default(); + ba1.append_i16(-1_i16); + ba1.append_i16(-1_i16); + ba1.append_i16(-1_i16); + ba1.append_i16(-1_i16); + ba1.append_i16(-1_i16); + ba1.append_i16(-1_i16); + ba1.append_i16(-1_i16); + ba1.append_i16(-2_i16); + assert(ba1 == test_byte_array_16_neg(), 'negative i16 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_i32() { + let mut ba = Default::default(); + ba.append_i32(0x01020304_i32); + ba.append_i32(0x05060708_i32); + assert(ba == test_byte_array_8(), 'i32 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_i32_neg() { + let mut ba = Default::default(); + ba.append_i32(-1_i32); + ba.append_i32(-1_i32); + ba.append_i32(-1_i32); + ba.append_i32(-2_i32); + assert(ba == test_byte_array_16_neg(), 'negative i32 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_i64() { + let mut ba: ByteArray = Default::default(); + ba.append_i64(0x0102030405060708_i64); + ba.append_i64(0x090a0b0c0d0e0f10_i64); + assert(ba == test_byte_array_16(), 'i64 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_i64_neg() { + let mut ba: ByteArray = Default::default(); + ba.append_i64(-1_i64); + ba.append_i64(-2_i64); + assert(ba == test_byte_array_16_neg(), 'negative i64 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_i128() { + let mut ba: ByteArray = Default::default(); + ba.append_i128(0x0102030405060708090a0b0c0d0e0f10_i128); + ba.append_i128(0x1112131415161718191a1b1c1d1e1f20_i128); + assert(ba == test_byte_array_32(), 'i128 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_append_i128_neg() { + let mut ba: ByteArray = Default::default(); + ba.append_i128(-2_i128); + assert(ba == test_byte_array_16_neg(), 'negative i128 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_word_u16() { + let word = test_byte_array_64().word_u16(62).unwrap(); + assert(word == 0x3f40_u16, 'word u16 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_word_u16_none() { + let is_none = test_byte_array_64().word_u16(63).is_none(); + assert(is_none, 'word u16 should be empty'); +} + +#[test] +#[available_gas(1000000)] +fn test_word_u32() { + let word = test_byte_array_64().word_u32(60).unwrap(); + assert(word == 0x3d3e3f40_u32, 'word u32 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_word_u32_none() { + let is_none = test_byte_array_64().word_u32(61).is_none(); + assert(is_none, 'word u32 should be empty'); +} + +#[test] +#[available_gas(1000000)] +fn test_word_u64() { + let word = test_byte_array_64().word_u64(56).unwrap(); + assert(word == 0x393a3b3c3d3e3f40_u64, 'word u64 differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_word_u64_none() { + let is_none = test_byte_array_64().word_u64(57).is_none(); + assert(is_none, 'word u64 should be empty'); +} + +#[test] +#[available_gas(2000000)] +fn test_word_u128() { + let word = test_byte_array_64().word_u128(48).unwrap(); + assert(word == 0x3132333435363738393a3b3c3d3e3f40_u128, 'word u128 differs'); +} + +#[test] +#[available_gas(2000000)] +fn test_word_u128_none() { + let is_none = test_byte_array_64().word_u128(49).is_none(); + assert(is_none, 'word u128 should be empty'); +} + +#[test] +#[available_gas(2000000)] +fn test_reader_helper() { + let ba = test_byte_array_64(); + let reader = ba.reader(); + assert(reader.data == @ba, 'reader failed'); +} + +#[test] +#[available_gas(1000000)] +fn test_serialize() { + let mut out = array![]; + let ba = test_byte_array_64(); + ba.serialize(ref out); + let expected = serialized_byte_array_64(); + assert(out == expected, 'serialization differs'); +} + +#[test] +#[available_gas(1000000)] +fn test_deserialize() { + let mut in = serialized_byte_array_64().span(); + let ba: ByteArray = Serde::deserialize(ref in).unwrap(); + assert(ba == test_byte_array_64(), 'deserialized ByteArray differs'); +} + +// helpers +fn test_byte_array_8() -> ByteArray { + let mut ba1 = Default::default(); + ba1.append_word(0x0102030405060708, 8); + ba1 +} + +fn test_byte_array_16() -> ByteArray { + let mut ba1 = Default::default(); + ba1.append_word(0x0102030405060708090a0b0c0d0e0f10, 16); + ba1 +} + +fn test_byte_array_32() -> ByteArray { + let mut ba1 = Default::default(); + ba1.append_word(0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f, 31); + ba1.append_word(0x20, 1); + ba1 +} + +fn test_byte_array_32_neg() -> ByteArray { + let mut ba1 = Default::default(); + ba1.append_word(0xfffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1, 31); + ba1.append_word(0xe0, 1); + ba1 +} + +fn test_byte_array_16_neg() -> ByteArray { + let mut ba1 = Default::default(); + ba1.append_word(0xfffffffffffffffffffffffffffffffe, 16); + ba1 +} + +fn test_byte_array_64() -> ByteArray { + let mut ba1 = Default::default(); + ba1.append_word(0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f, 31); + ba1.append_word(0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e, 31); + ba1.append_word(0x3f40, 2); + ba1 +} + +fn serialized_byte_array_64() -> Array { + array![ + 0x40, + 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f, + 0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e, + 0x3f40 + ] +} diff --git a/src/data_structures/src/tests/byte_array_reader_test.cairo b/src/data_structures/src/tests/byte_array_reader_test.cairo new file mode 100644 index 00000000..531a3ca5 --- /dev/null +++ b/src/data_structures/src/tests/byte_array_reader_test.cairo @@ -0,0 +1,81 @@ +use integer::u512; +use alexandria_data_structures::byte_array_ext::ByteArrayTraitExt; +use alexandria_data_structures::byte_array_reader::ByteArrayReaderTrait; +use alexandria_data_structures::tests::byte_array_ext_test::test_byte_array_64; + +#[test] +#[available_gas(10000000)] +fn test_clone_byte_array_reader() { + let ba = test_byte_array_64(); + let mut rd1 = ba.reader(); + let temp = rd1.read_u256().unwrap(); + let mut rd2 = rd1.clone(); + let a = rd1.read_u128().unwrap(); + let b = rd2.read_u128().unwrap(); + assert(a == b, 'copy ByteArrayReader failed'); +} + +#[test] +#[available_gas(20000000)] +fn test_len() { + let ba = test_byte_array_64(); + let mut rd = ba.reader(); + assert(64 == rd.len(), 'expected len 64'); + let _ = rd.read_u8().expect('some'); + assert(63 == rd.len(), 'expected len 63'); + let _ = rd.read_u256().expect('some'); + assert(31 == rd.len(), 'expected len 31'); + let _ = rd.read_u128().expect('some'); + assert(15 == rd.len(), 'expected len 15'); + let _ = rd.read_u64().expect('some'); + assert(7 == rd.len(), 'expected len 7'); + let _ = rd.read_u32().expect('some'); + assert(3 == rd.len(), 'expected len 3'); + let _ = rd.read_u16().expect('some'); + assert(1 == rd.len(), 'expected len 1'); + let _ = rd.read_i8().expect('some'); + assert(0 == rd.len(), 'expected len 0'); +} + +#[test] +#[available_gas(20000000)] +fn test_read() { + let ba = test_byte_array_64(); + let mut rd = ba.reader(); + assert(rd.read_i8() == Option::Some(1), 'expected 1'); + // rd.read_i128().unwrap().print(); + assert(rd.read_i128() == Option::Some(0x02030405060708090a0b0c0d0e0f1011), + 'not 0x0203040506...'); + assert(rd.read_u128() == Option::Some(0x12131415161718191a1b1c1d1e1f2021), + 'not 0x1213141516...'); + assert(rd.read_i64() == Option::Some(0x2223242526272829), 'not 0x22232425...'); + assert(rd.read_u128() == Option::Some(0x2a2b2c2d2e2f30313233343536373839), + 'not 0x2a2b2c2d2e...'); + assert(rd.read_u32() == Option::Some(0x3a3b3c3d), 'not 0x3a3b3c3d'); + assert(rd.read_i16() == Option::Some(0x3e3f), 'not 0x3e3f'); + assert(rd.read_u8() == Option::Some(0x40), 'not 0x40'); + assert(rd.read_u8().is_none(), 'expected none'); +} + +#[test] +#[available_gas(20000000)] +fn test_read_u256() { + let ba = test_byte_array_64(); + let mut rd = ba.reader(); + let u256{low: low1, high: high1} = rd.read_u256().unwrap(); + assert(high1 == 0x0102030405060708090a0b0c0d0e0f10_u128, 'wrong value for high1'); + assert(low1 == 0x1112131415161718191a1b1c1d1e1f20_u128, 'wrong value for low1'); +} + +#[test] +#[available_gas(20000000)] +fn test_read_u512() { + let ba = test_byte_array_64(); + let mut rd = ba.reader(); + let u512{limb0, limb1, limb2, limb3} = rd.read_u512().unwrap(); + + assert(limb3 == 0x0102030405060708090a0b0c0d0e0f10_u128, 'wrong value for limb3'); + assert(limb2 == 0x1112131415161718191a1b1c1d1e1f20_u128, 'wrong value for limb2'); + assert(limb1 == 0x2122232425262728292a2b2c2d2e2f30_u128, 'wrong value for limb1'); + assert(limb0 == 0x3132333435363738393a3b3c3d3e3f40_u128, 'wrong value for limb0'); +} \ No newline at end of file From bfc81c9cfa66a570e1c127df6858e40ec8ae59f5 Mon Sep 17 00:00:00 2001 From: Marcus Liotta Date: Thu, 5 Oct 2023 20:10:45 +0200 Subject: [PATCH 2/9] auto format revert --- src/data_structures/src/array_ext.cairo | 152 ++++++++++++++++-------- 1 file changed, 104 insertions(+), 48 deletions(-) diff --git a/src/data_structures/src/array_ext.cairo b/src/data_structures/src/array_ext.cairo index 2fc6f898..3444804c 100644 --- a/src/data_structures/src/array_ext.cairo +++ b/src/data_structures/src/array_ext.cairo @@ -67,8 +67,12 @@ impl ArrayImpl, impl TDrop: Drop> of ArrayTraitExt break; } match self.pop_front() { - Option::Some(v) => { n -= 1; }, - Option::None => { break; }, + Option::Some(v) => { + n -= 1; + }, + Option::None => { + break; + }, }; }; } @@ -152,8 +156,12 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { break; } match self.pop_front() { - Option::Some(v) => { n -= 1; }, - Option::None => { break; }, + Option::Some(v) => { + n -= 1; + }, + Option::None => { + break; + }, }; }; } @@ -164,8 +172,12 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { break; } match self.pop_back() { - Option::Some(v) => { n -= 1; }, - Option::None => { break; }, + Option::Some(v) => { + n -= 1; + }, + Option::None => { + break; + }, }; }; } @@ -174,7 +186,9 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut response = array![]; loop { match self.pop_back() { - Option::Some(v) => { response.append(*v); }, + Option::Some(v) => { + response.append(*v); + }, Option::None => { break; // Can't `break response;` "Variable was previously moved" }, @@ -186,10 +200,14 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { fn contains>(mut self: Span, item: T) -> bool { loop { match self.pop_front() { - Option::Some(v) => { if *v == item { - break true; - } }, - Option::None => { break false; }, + Option::Some(v) => { + if *v == item { + break true; + } + }, + Option::None => { + break false; + }, }; } } @@ -226,7 +244,9 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { } index += 1; }, - Option::None => { break Option::None; }, + Option::None => { + break Option::None; + }, }; } } @@ -235,10 +255,14 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut count = 0_usize; loop { match self.pop_front() { - Option::Some(v) => { if *v == item { - count += 1; - } }, - Option::None => { break count; }, + Option::Some(v) => { + if *v == item { + count += 1; + } + }, + Option::None => { + break count; + }, }; } } @@ -248,14 +272,20 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { ) -> Option { let mut min = match self.pop_front() { Option::Some(item) => *item, - Option::None => { return Option::None; }, + Option::None => { + return Option::None; + }, }; loop { match self.pop_front() { - Option::Some(item) => { if *item < min { - min = *item - } }, - Option::None => { break Option::Some(min); }, + Option::Some(item) => { + if *item < min { + min = *item + } + }, + Option::None => { + break Option::Some(min); + }, }; } } @@ -267,15 +297,21 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut index_of_min = 0; let mut min: T = match self.pop_front() { Option::Some(item) => *item, - Option::None => { return Option::None; }, + Option::None => { + return Option::None; + }, }; loop { match self.pop_front() { - Option::Some(item) => { if *item < min { - index_of_min = index + 1; - min = *item; - } }, - Option::None => { break Option::Some(index_of_min); }, + Option::Some(item) => { + if *item < min { + index_of_min = index + 1; + min = *item; + } + }, + Option::None => { + break Option::Some(index_of_min); + }, }; index += 1; } @@ -286,14 +322,20 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { ) -> Option { let mut max = match self.pop_front() { Option::Some(item) => *item, - Option::None => { return Option::None; }, + Option::None => { + return Option::None; + }, }; loop { match self.pop_front() { - Option::Some(item) => { if *item > max { - max = *item - } }, - Option::None => { break Option::Some(max); }, + Option::Some(item) => { + if *item > max { + max = *item + } + }, + Option::None => { + break Option::Some(max); + }, }; } } @@ -305,15 +347,21 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut index_of_max = 0; let mut max = match self.pop_front() { Option::Some(item) => *item, - Option::None => { return Option::None; }, + Option::None => { + return Option::None; + }, }; loop { match self.pop_front() { - Option::Some(item) => { if *item > max { - index_of_max = index + 1; - max = *item - } }, - Option::None => { break Option::Some(index_of_max); }, + Option::Some(item) => { + if *item > max { + index_of_max = index + 1; + max = *item + } + }, + Option::None => { + break Option::Some(index_of_max); + }, }; index += 1; } @@ -329,11 +377,15 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { loop { match self.pop_front() { - Option::Some(v) => { if (last_value != v) { - last_value = v; - ret.append(*v); - }; }, - Option::None => { break; } + Option::Some(v) => { + if (last_value != v) { + last_value = v; + ret.append(*v); + }; + }, + Option::None => { + break; + } }; }; @@ -344,12 +396,16 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut ret = array![]; loop { match self.pop_front() { - Option::Some(v) => { if !ret.contains(*v) { - ret.append(*v); - } }, - Option::None => { break; } + Option::Some(v) => { + if !ret.contains(*v) { + ret.append(*v); + } + }, + Option::None => { + break; + } }; }; ret } -} +} \ No newline at end of file From 6d3a60e4d48be75142ac49c5a2178aec6ede3136 Mon Sep 17 00:00:00 2001 From: Marcus Liotta Date: Thu, 5 Oct 2023 20:20:32 +0200 Subject: [PATCH 3/9] formatting --- src/data_structures/src/array_ext.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data_structures/src/array_ext.cairo b/src/data_structures/src/array_ext.cairo index 3444804c..aa022d3d 100644 --- a/src/data_structures/src/array_ext.cairo +++ b/src/data_structures/src/array_ext.cairo @@ -408,4 +408,4 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { }; ret } -} \ No newline at end of file +} From cf511adc469c4d29c9013b84adcb4e4fc3720de4 Mon Sep 17 00:00:00 2001 From: Marcus Liotta Date: Fri, 6 Oct 2023 09:13:17 +0200 Subject: [PATCH 4/9] Adds explicit ByteArrayReaderTrait --- .../src/byte_array_reader.cairo | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/data_structures/src/byte_array_reader.cairo b/src/data_structures/src/byte_array_reader.cairo index 7bfad7ee..c1081aff 100644 --- a/src/data_structures/src/byte_array_reader.cairo +++ b/src/data_structures/src/byte_array_reader.cairo @@ -10,7 +10,23 @@ struct ByteArrayReader { reader_index: usize, } -#[generate_trait] +trait ByteArrayReaderTrait { + fn new(from: @ByteArray) -> ByteArrayReader; + fn read_u8(ref self: ByteArrayReader) -> Option; + fn read_u16(ref self: ByteArrayReader) -> Option; + fn read_u32(ref self: ByteArrayReader) -> Option; + fn read_u64(ref self: ByteArrayReader) -> Option; + fn read_u128(ref self: ByteArrayReader) -> Option; + fn read_u256(ref self: ByteArrayReader) -> Option; + fn read_u512(ref self: ByteArrayReader) -> Option; + fn read_i8(ref self: ByteArrayReader) -> Option; + fn read_i16(ref self: ByteArrayReader) -> Option; + fn read_i32(ref self: ByteArrayReader) -> Option; + fn read_i64(ref self: ByteArrayReader) -> Option; + fn read_i128(ref self: ByteArrayReader) -> Option; + fn len(self: @ByteArrayReader) -> usize; +} + impl ByteArrayReaderImpl of ByteArrayReaderTrait { fn new(from: @ByteArray) -> ByteArrayReader { ByteArrayReader { data: from, reader_index: 0, } @@ -69,16 +85,6 @@ impl ByteArrayReaderImpl of ByteArrayReaderTrait { fn read_i8(ref self: ByteArrayReader) -> Option { let felt: felt252 = self.read_u8()?.into(); Option::Some(parse_signed(felt, 1).unwrap()) - // match felt.try_into() { - // Option::Some(pos) => Option::Some(pos), - // Option::None => { - // let negated: felt252 = felt - 0x100; - // 'negated'.print(); - // negated.print(); - // // - one_shift_left_bytes_felt252(1); - // Option::Some(negated.try_into().unwrap()) - // }, - // } } fn read_i16(ref self: ByteArrayReader) -> Option { @@ -101,7 +107,6 @@ impl ByteArrayReaderImpl of ByteArrayReaderTrait { Option::Some(parse_signed(felt, 16).unwrap()) } - // #[inline] fn len(self: @ByteArrayReader) -> usize { let byte_array = *self.data; let byte_array_len = byte_array.len(); @@ -118,9 +123,3 @@ fn parse_signed>(value: felt252, bytes: usize) -> Option }, } } - -// impl ByteArrayReaderCloneImpl of Clone { -// fn clone(self: @ByteArrayReader) -> ByteArrayReader { -// ByteArrayReader { data: *self.data, reader_index: *self.reader_index } -// } -// } \ No newline at end of file From 5867efa4971be0b18e6195d67192c064116b9332 Mon Sep 17 00:00:00 2001 From: Marcus Liotta Date: Fri, 6 Oct 2023 11:23:12 +0200 Subject: [PATCH 5/9] scarb fmt --- .../src/tests/byte_array_reader_test.cairo | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/data_structures/src/tests/byte_array_reader_test.cairo b/src/data_structures/src/tests/byte_array_reader_test.cairo index 531a3ca5..82709c42 100644 --- a/src/data_structures/src/tests/byte_array_reader_test.cairo +++ b/src/data_structures/src/tests/byte_array_reader_test.cairo @@ -44,13 +44,16 @@ fn test_read() { let mut rd = ba.reader(); assert(rd.read_i8() == Option::Some(1), 'expected 1'); // rd.read_i128().unwrap().print(); - assert(rd.read_i128() == Option::Some(0x02030405060708090a0b0c0d0e0f1011), - 'not 0x0203040506...'); - assert(rd.read_u128() == Option::Some(0x12131415161718191a1b1c1d1e1f2021), - 'not 0x1213141516...'); + assert( + rd.read_i128() == Option::Some(0x02030405060708090a0b0c0d0e0f1011), 'not 0x0203040506...' + ); + assert( + rd.read_u128() == Option::Some(0x12131415161718191a1b1c1d1e1f2021), 'not 0x1213141516...' + ); assert(rd.read_i64() == Option::Some(0x2223242526272829), 'not 0x22232425...'); - assert(rd.read_u128() == Option::Some(0x2a2b2c2d2e2f30313233343536373839), - 'not 0x2a2b2c2d2e...'); + assert( + rd.read_u128() == Option::Some(0x2a2b2c2d2e2f30313233343536373839), 'not 0x2a2b2c2d2e...' + ); assert(rd.read_u32() == Option::Some(0x3a3b3c3d), 'not 0x3a3b3c3d'); assert(rd.read_i16() == Option::Some(0x3e3f), 'not 0x3e3f'); assert(rd.read_u8() == Option::Some(0x40), 'not 0x40'); @@ -62,7 +65,7 @@ fn test_read() { fn test_read_u256() { let ba = test_byte_array_64(); let mut rd = ba.reader(); - let u256{low: low1, high: high1} = rd.read_u256().unwrap(); + let u256{low: low1, high: high1 } = rd.read_u256().unwrap(); assert(high1 == 0x0102030405060708090a0b0c0d0e0f10_u128, 'wrong value for high1'); assert(low1 == 0x1112131415161718191a1b1c1d1e1f20_u128, 'wrong value for low1'); } @@ -72,10 +75,10 @@ fn test_read_u256() { fn test_read_u512() { let ba = test_byte_array_64(); let mut rd = ba.reader(); - let u512{limb0, limb1, limb2, limb3} = rd.read_u512().unwrap(); + let u512{limb0, limb1, limb2, limb3 } = rd.read_u512().unwrap(); assert(limb3 == 0x0102030405060708090a0b0c0d0e0f10_u128, 'wrong value for limb3'); assert(limb2 == 0x1112131415161718191a1b1c1d1e1f20_u128, 'wrong value for limb2'); assert(limb1 == 0x2122232425262728292a2b2c2d2e2f30_u128, 'wrong value for limb1'); assert(limb0 == 0x3132333435363738393a3b3c3d3e3f40_u128, 'wrong value for limb0'); -} \ No newline at end of file +} From a31008dfda00b8822c2f22bd128221c0a04c851f Mon Sep 17 00:00:00 2001 From: Marcus Liotta Date: Sun, 8 Oct 2023 15:55:47 +0200 Subject: [PATCH 6/9] Adds documentation and applies scarb fmt to the source tree --- src/ascii/src/interger.cairo | 8 +- src/data_structures/src/array_ext.cairo | 150 ++++++------------ src/data_structures/src/byte_array_ext.cairo | 56 +++++++ .../src/byte_array_reader.cairo | 48 ++++++ src/data_structures/src/merkle_tree.cairo | 8 +- .../src/tests/merkle_tree_test.cairo | 50 +++--- .../src/tests/queue_test.cairo | 16 +- .../src/tests/stack_test.cairo | 16 +- src/linalg/src/dot.cairo | 4 +- src/math/src/gcd_of_n_numbers.cairo | 8 +- src/math/src/keccak256.cairo | 4 +- src/math/src/sha256.cairo | 8 +- src/numeric/src/cumsum.cairo | 4 +- src/numeric/src/diff.cairo | 4 +- src/searching/src/dijkstra.cairo | 8 +- src/searching/src/tests/dijkstra_test.cairo | 16 +- src/sorting/src/lib.cairo | 4 +- src/storage/src/list.cairo | 4 +- 18 files changed, 209 insertions(+), 207 deletions(-) diff --git a/src/ascii/src/interger.cairo b/src/ascii/src/interger.cairo index 2a8b0347..406e8066 100644 --- a/src/ascii/src/interger.cairo +++ b/src/ascii/src/interger.cairo @@ -78,12 +78,8 @@ impl SmallIntergerToAsciiTraitImpl< let mut ascii: felt252 = 0; loop { match inverse_ascii_arr.pop_back() { - Option::Some(val) => { - ascii = ascii * 256 + *val; - }, - Option::None(_) => { - break; - }, + Option::Some(val) => { ascii = ascii * 256 + *val; }, + Option::None(_) => { break; }, }; }; diff --git a/src/data_structures/src/array_ext.cairo b/src/data_structures/src/array_ext.cairo index aa022d3d..2fc6f898 100644 --- a/src/data_structures/src/array_ext.cairo +++ b/src/data_structures/src/array_ext.cairo @@ -67,12 +67,8 @@ impl ArrayImpl, impl TDrop: Drop> of ArrayTraitExt break; } match self.pop_front() { - Option::Some(v) => { - n -= 1; - }, - Option::None => { - break; - }, + Option::Some(v) => { n -= 1; }, + Option::None => { break; }, }; }; } @@ -156,12 +152,8 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { break; } match self.pop_front() { - Option::Some(v) => { - n -= 1; - }, - Option::None => { - break; - }, + Option::Some(v) => { n -= 1; }, + Option::None => { break; }, }; }; } @@ -172,12 +164,8 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { break; } match self.pop_back() { - Option::Some(v) => { - n -= 1; - }, - Option::None => { - break; - }, + Option::Some(v) => { n -= 1; }, + Option::None => { break; }, }; }; } @@ -186,9 +174,7 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut response = array![]; loop { match self.pop_back() { - Option::Some(v) => { - response.append(*v); - }, + Option::Some(v) => { response.append(*v); }, Option::None => { break; // Can't `break response;` "Variable was previously moved" }, @@ -200,14 +186,10 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { fn contains>(mut self: Span, item: T) -> bool { loop { match self.pop_front() { - Option::Some(v) => { - if *v == item { - break true; - } - }, - Option::None => { - break false; - }, + Option::Some(v) => { if *v == item { + break true; + } }, + Option::None => { break false; }, }; } } @@ -244,9 +226,7 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { } index += 1; }, - Option::None => { - break Option::None; - }, + Option::None => { break Option::None; }, }; } } @@ -255,14 +235,10 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut count = 0_usize; loop { match self.pop_front() { - Option::Some(v) => { - if *v == item { - count += 1; - } - }, - Option::None => { - break count; - }, + Option::Some(v) => { if *v == item { + count += 1; + } }, + Option::None => { break count; }, }; } } @@ -272,20 +248,14 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { ) -> Option { let mut min = match self.pop_front() { Option::Some(item) => *item, - Option::None => { - return Option::None; - }, + Option::None => { return Option::None; }, }; loop { match self.pop_front() { - Option::Some(item) => { - if *item < min { - min = *item - } - }, - Option::None => { - break Option::Some(min); - }, + Option::Some(item) => { if *item < min { + min = *item + } }, + Option::None => { break Option::Some(min); }, }; } } @@ -297,21 +267,15 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut index_of_min = 0; let mut min: T = match self.pop_front() { Option::Some(item) => *item, - Option::None => { - return Option::None; - }, + Option::None => { return Option::None; }, }; loop { match self.pop_front() { - Option::Some(item) => { - if *item < min { - index_of_min = index + 1; - min = *item; - } - }, - Option::None => { - break Option::Some(index_of_min); - }, + Option::Some(item) => { if *item < min { + index_of_min = index + 1; + min = *item; + } }, + Option::None => { break Option::Some(index_of_min); }, }; index += 1; } @@ -322,20 +286,14 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { ) -> Option { let mut max = match self.pop_front() { Option::Some(item) => *item, - Option::None => { - return Option::None; - }, + Option::None => { return Option::None; }, }; loop { match self.pop_front() { - Option::Some(item) => { - if *item > max { - max = *item - } - }, - Option::None => { - break Option::Some(max); - }, + Option::Some(item) => { if *item > max { + max = *item + } }, + Option::None => { break Option::Some(max); }, }; } } @@ -347,21 +305,15 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut index_of_max = 0; let mut max = match self.pop_front() { Option::Some(item) => *item, - Option::None => { - return Option::None; - }, + Option::None => { return Option::None; }, }; loop { match self.pop_front() { - Option::Some(item) => { - if *item > max { - index_of_max = index + 1; - max = *item - } - }, - Option::None => { - break Option::Some(index_of_max); - }, + Option::Some(item) => { if *item > max { + index_of_max = index + 1; + max = *item + } }, + Option::None => { break Option::Some(index_of_max); }, }; index += 1; } @@ -377,15 +329,11 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { loop { match self.pop_front() { - Option::Some(v) => { - if (last_value != v) { - last_value = v; - ret.append(*v); - }; - }, - Option::None => { - break; - } + Option::Some(v) => { if (last_value != v) { + last_value = v; + ret.append(*v); + }; }, + Option::None => { break; } }; }; @@ -396,14 +344,10 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { let mut ret = array![]; loop { match self.pop_front() { - Option::Some(v) => { - if !ret.contains(*v) { - ret.append(*v); - } - }, - Option::None => { - break; - } + Option::Some(v) => { if !ret.contains(*v) { + ret.append(*v); + } }, + Option::None => { break; } }; }; ret diff --git a/src/data_structures/src/byte_array_ext.cairo b/src/data_structures/src/byte_array_ext.cairo index e93fcc71..152c6d6c 100644 --- a/src/data_structures/src/byte_array_ext.cairo +++ b/src/data_structures/src/byte_array_ext.cairo @@ -7,21 +7,77 @@ use traits::DivRem; use core::serde::into_felt252_based::SerdeImpl; trait ByteArrayTraitExt { + /// Appends an unsigned 16 bit integer + /// # Arguments + /// * `word` - a 16 bit unsigned integer typed as u16 fn append_u16(ref self: ByteArray, word: u16); + /// Appends an unsigned 32 bit integer + /// # Arguments + /// * `word` - a 32 bit unsigned integer typed as u32 fn append_u32(ref self: ByteArray, word: u32); + /// Appends an unsigned 64 bit integer + /// # Arguments + /// * `word` - a 64 bit unsigned integer typed as u64 fn append_u64(ref self: ByteArray, word: u64); + /// Appends an unsigned 128 bit integer + /// # Arguments + /// * `word` - a 128 bit unsigned integer typed as u128 fn append_u128(ref self: ByteArray, word: u128); + /// Appends an unsigned 256 bit integer + /// # Arguments + /// * `word` - a 256 bit unsigned integer typed as u256 fn append_u256(ref self: ByteArray, word: u256); + /// Appends an unsigned 512 bit integer + /// # Arguments + /// * `word` - a 512 bit unsigned integer typed as u32 fn append_u512(ref self: ByteArray, word: u512); + /// Appends a signed 8 bit integer + /// # Arguments + /// * `word` - an 8 bit signed integer typed as i8 fn append_i8(ref self: ByteArray, word: i8); + /// Appends a signed 16 bit integer + /// # Arguments + /// * `word` - a 16 bit signed integer typed as i16 fn append_i16(ref self: ByteArray, word: i16); + /// Appends a signed 32 bit integer + /// # Arguments + /// * `word` - a 32 bit signed integer typed as i32 fn append_i32(ref self: ByteArray, word: i32); + /// Appends a signed 64 bit integer + /// # Arguments + /// * `word` - a 64 bit signed integer typed as i64 fn append_i64(ref self: ByteArray, word: i64); + /// Appends a signed 128 bit integer + /// # Arguments + /// * `word` - a 128 bit signed integer typed as i128 fn append_i128(ref self: ByteArray, word: i128); + /// Reads consecutive bytes from a specified offset as an unsigned integer + /// # Arguments + /// * `offset` - the start location of the consecutive bytes to read + /// # Returns + /// * `Option` - Returns an integer if there are enough consecutive bytes available in the ByteArray fn word_u16(self: @ByteArray, offset: usize) -> Option; + /// Reads consecutive bytes from a specified offset as an unsigned integer + /// # Arguments + /// * `offset` - the start location of the consecutive bytes to read + /// # Returns + /// * `Option` - Returns an integer if there are enough consecutive bytes available in the ByteArray fn word_u32(self: @ByteArray, offset: usize) -> Option; + /// Reads consecutive bytes from a specified offset as an unsigned integer + /// # Arguments + /// * `offset` - the start location of the consecutive bytes to read + /// # Returns + /// * `Option` - Returns an integer if there are enough consecutive bytes available in the ByteArray fn word_u64(self: @ByteArray, offset: usize) -> Option; + /// Reads consecutive bytes from a specified offset as an unsigned integer + /// # Arguments + /// * `offset` - the start location of the consecutive bytes to read + /// # Returns + /// * `Option` - Returns an integer if there are enough consecutive bytes available in the ByteArray fn word_u128(self: @ByteArray, offset: usize) -> Option; + /// Wraps the ByteArray in a ByteArrayReader for sequential consumption of integers and/or bytes + /// # Returns + /// * `ByteArrayReader` - The reader struct wrapping a read-only snapshot of this ByteArray fn reader(self: @ByteArray) -> ByteArrayReader; } diff --git a/src/data_structures/src/byte_array_reader.cairo b/src/data_structures/src/byte_array_reader.cairo index c1081aff..c2417816 100644 --- a/src/data_structures/src/byte_array_reader.cairo +++ b/src/data_structures/src/byte_array_reader.cairo @@ -4,26 +4,74 @@ use byte_array::ByteArray; use alexandria_data_structures::byte_array_ext::ByteArrayTraitExt; use core::clone::Clone; +/// A read-only snapshot of an underlying ByteArray that maintains +/// sequential access to the integers encoded in the array #[derive(Copy, Drop)] struct ByteArrayReader { + /// A snapshot of the ByteArray data: @ByteArray, + /// The `read_index` is incremented in accordance with the integers consumed reader_index: usize, } trait ByteArrayReaderTrait { + /// Creates a ByteArrayReader from a ByteArray snapshot + /// # Arguments + /// * `from` - a ByteArray snapshot to read from + /// # Returns + /// `ByteArrayReader` - a new reader starting at the beginning of the underlying ByteArray fn new(from: @ByteArray) -> ByteArrayReader; + /// Reads a u8 unsigned integer + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u8(ref self: ByteArrayReader) -> Option; + /// Reads a u16 unsigned integer + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u16(ref self: ByteArrayReader) -> Option; + /// Reads a u32 unsigned integer + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u32(ref self: ByteArrayReader) -> Option; + /// Reads a u64 unsigned integer + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u64(ref self: ByteArrayReader) -> Option; + /// Reads a u128 unsigned integer + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u128(ref self: ByteArrayReader) -> Option; + /// Reads a u256 unsigned integer + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u256(ref self: ByteArrayReader) -> Option; + /// Reads a u512 unsigned integer + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u512(ref self: ByteArrayReader) -> Option; + /// Reads an i8 signed integer in two's complement encoding from the ByteArray + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_i8(ref self: ByteArrayReader) -> Option; + /// Reads an i16 signed integer in two's complement encoding from the ByteArray + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_i16(ref self: ByteArrayReader) -> Option; + /// Reads an i32 signed integer in two's complement encoding from the ByteArray + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_i32(ref self: ByteArrayReader) -> Option; + /// Reads an i64 signed integer in two's complement encoding from the ByteArray + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_i64(ref self: ByteArrayReader) -> Option; + /// Reads an i128 signed integer in two's complement encoding from the ByteArray + /// # Returns + /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_i128(ref self: ByteArrayReader) -> Option; + /// Returns the remaining length of the ByteArrayReader + /// # Returns + /// `usize` - The number of bytes remaining considering the number of bytes that have already been consumed fn len(self: @ByteArrayReader) -> usize; } diff --git a/src/data_structures/src/merkle_tree.cairo b/src/data_structures/src/merkle_tree.cairo index 09d75f33..3edc4abd 100644 --- a/src/data_structures/src/merkle_tree.cairo +++ b/src/data_structures/src/merkle_tree.cairo @@ -130,9 +130,7 @@ impl MerkleTreeImpl< self.hasher.hash(*proof_element, current_node) }; }, - Option::None => { - break current_node; - }, + Option::None => { break current_node; }, }; } } @@ -160,9 +158,7 @@ impl MerkleTreeImpl< self.hasher.hash(*proof_element, leaf) }; }, - Option::None => { - break leaf; - }, + Option::None => { break leaf; }, }; }; computed_root == root diff --git a/src/data_structures/src/tests/merkle_tree_test.cairo b/src/data_structures/src/tests/merkle_tree_test.cairo index 28173576..b899ff96 100644 --- a/src/data_structures/src/tests/merkle_tree_test.cairo +++ b/src/data_structures/src/tests/merkle_tree_test.cairo @@ -64,20 +64,23 @@ fn merkle_tree_pedersen_test() { let leaves = array![0x1, 0x2, 0x3]; // [Assert] Compute merkle root. - let computed_root = MerkleTreeImpl::<_, - PedersenHasherImpl>::compute_root(ref merkle_tree, leaf, valid_proof); + let computed_root = MerkleTreeImpl::< + _, PedersenHasherImpl + >::compute_root(ref merkle_tree, leaf, valid_proof); assert(computed_root == root, 'compute valid root failed'); // [Assert] Compute merkle proof. let mut input_leaves = leaves; let index = 0; - let computed_proof = MerkleTreeImpl::<_, - PedersenHasherImpl>::compute_proof(ref merkle_tree, input_leaves, index); + let computed_proof = MerkleTreeImpl::< + _, PedersenHasherImpl + >::compute_proof(ref merkle_tree, input_leaves, index); assert(computed_proof == valid_proof, 'compute valid proof failed'); // [Assert] Verify a valid proof. - let result = MerkleTreeImpl::<_, - PedersenHasherImpl>::verify(ref merkle_tree, root, leaf, valid_proof); + let result = MerkleTreeImpl::< + _, PedersenHasherImpl + >::verify(ref merkle_tree, root, leaf, valid_proof); assert(result, 'verify valid proof failed'); // [Assert] Verify an invalid proof. @@ -85,14 +88,16 @@ fn merkle_tree_pedersen_test() { 0x2 + 1, 0x68ba2a188dd231112c1cb5aaa5d18be6d84f6c8683e5c3a6638dee83e727acc ] .span(); - let result = MerkleTreeImpl::<_, - PedersenHasherImpl>::verify(ref merkle_tree, root, leaf, invalid_proof); + let result = MerkleTreeImpl::< + _, PedersenHasherImpl + >::verify(ref merkle_tree, root, leaf, invalid_proof); assert(!result, 'verify invalid proof failed'); // [Assert] Verify a valid proof with an invalid leaf. let invalid_leaf = 0x1 + 1; - let result = MerkleTreeImpl::<_, - PedersenHasherImpl>::verify(ref merkle_tree, root, invalid_leaf, valid_proof); + let result = MerkleTreeImpl::< + _, PedersenHasherImpl + >::verify(ref merkle_tree, root, invalid_leaf, valid_proof); assert(!result, 'wrong result'); } @@ -108,20 +113,23 @@ fn merkle_tree_poseidon_test() { let leaves = array![0x1, 0x2, 0x3]; // [Assert] Compute merkle root. - let computed_root = MerkleTreeImpl::<_, - PoseidonHasherImpl>::compute_root(ref merkle_tree, leaf, valid_proof); + let computed_root = MerkleTreeImpl::< + _, PoseidonHasherImpl + >::compute_root(ref merkle_tree, leaf, valid_proof); assert(computed_root == root, 'compute valid root failed'); // [Assert] Compute merkle proof. let mut input_leaves = leaves; let index = 0; - let computed_proof = MerkleTreeImpl::<_, - PoseidonHasherImpl>::compute_proof(ref merkle_tree, input_leaves, index); + let computed_proof = MerkleTreeImpl::< + _, PoseidonHasherImpl + >::compute_proof(ref merkle_tree, input_leaves, index); assert(computed_proof == valid_proof, 'compute valid proof failed'); // [Assert] Verify a valid proof. - let result = MerkleTreeImpl::<_, - PoseidonHasherImpl>::verify(ref merkle_tree, root, leaf, valid_proof); + let result = MerkleTreeImpl::< + _, PoseidonHasherImpl + >::verify(ref merkle_tree, root, leaf, valid_proof); assert(result, 'verify valid proof failed'); // [Assert] Verify an invalid proof. @@ -129,13 +137,15 @@ fn merkle_tree_poseidon_test() { 0x2 + 1, 0x68ba2a188dd231112c1cb5aaa5d18be6d84f6c8683e5c3a6638dee83e727acc ] .span(); - let result = MerkleTreeImpl::<_, - PoseidonHasherImpl>::verify(ref merkle_tree, root, leaf, invalid_proof); + let result = MerkleTreeImpl::< + _, PoseidonHasherImpl + >::verify(ref merkle_tree, root, leaf, invalid_proof); assert(!result, 'verify invalid proof failed'); // [Assert] Verify a valid proof with an invalid leaf. let invalid_leaf = 0x1 + 1; - let result = MerkleTreeImpl::<_, - PoseidonHasherImpl>::verify(ref merkle_tree, root, invalid_leaf, valid_proof); + let result = MerkleTreeImpl::< + _, PoseidonHasherImpl + >::verify(ref merkle_tree, root, invalid_leaf, valid_proof); assert(!result, 'wrong result'); } diff --git a/src/data_structures/src/tests/queue_test.cairo b/src/data_structures/src/tests/queue_test.cairo index 5107a8a8..e3f1846c 100644 --- a/src/data_structures/src/tests/queue_test.cairo +++ b/src/data_structures/src/tests/queue_test.cairo @@ -42,12 +42,8 @@ fn queue_peek_front_test() { queue.enqueue(3); match queue.peek_front() { - Option::Some(result) => { - assert(*(result.unbox()) == 1, 'wrong result'); - }, - Option::None => { - assert(false, 'should return value'); - }, + Option::Some(result) => { assert(*(result.unbox()) == 1, 'wrong result'); }, + Option::None => { assert(false, 'should return value'); }, }; let result_len = queue.len(); @@ -63,12 +59,8 @@ fn queue_dequeue_test() { queue.enqueue(3); match queue.dequeue() { - Option::Some(result) => { - assert(result == 1, 'wrong result'); - }, - Option::None => { - assert(false, 'should return a value'); - }, + Option::Some(result) => { assert(result == 1, 'wrong result'); }, + Option::None => { assert(false, 'should return a value'); }, }; let result_len = queue.len(); diff --git a/src/data_structures/src/tests/stack_test.cairo b/src/data_structures/src/tests/stack_test.cairo index 643522fe..6cdda8e6 100644 --- a/src/data_structures/src/tests/stack_test.cairo +++ b/src/data_structures/src/tests/stack_test.cairo @@ -41,12 +41,8 @@ fn stack_peek_test< stack.push(val_1); stack.push(val_2); match stack.peek() { - Option::Some(result) => { - assert(result == val_2, 'wrong result'); - }, - Option::None => { - assert(false, 'should return value'); - }, + Option::Some(result) => { assert(result == val_2, 'wrong result'); }, + Option::None => { assert(false, 'should return value'); }, }; assert(stack.len() == 2, 'should not remove items'); @@ -68,12 +64,8 @@ fn stack_pop_test< let value = stack.pop(); match value { - Option::Some(result) => { - assert(result == val_2, 'wrong result'); - }, - Option::None => { - assert(false, 'should return a value'); - }, + Option::Some(result) => { assert(result == val_2, 'wrong result'); }, + Option::None => { assert(false, 'should return a value'); }, }; assert(stack.len() == 1, 'should remove item'); diff --git a/src/linalg/src/dot.cairo b/src/linalg/src/dot.cairo index b740d002..ac201047 100644 --- a/src/linalg/src/dot.cairo +++ b/src/linalg/src/dot.cairo @@ -30,9 +30,7 @@ fn dot< let y_value = ys.pop_front().unwrap(); value += *x_value * *y_value; }, - Option::None => { - break value; - }, + Option::None => { break value; }, }; } } diff --git a/src/math/src/gcd_of_n_numbers.cairo b/src/math/src/gcd_of_n_numbers.cairo index 81574d9e..81390272 100644 --- a/src/math/src/gcd_of_n_numbers.cairo +++ b/src/math/src/gcd_of_n_numbers.cairo @@ -15,12 +15,8 @@ fn gcd(mut n: Span) -> u128 { let mut a = *n.pop_front().unwrap(); loop { match n.pop_front() { - Option::Some(b) => { - a = gcd_two_numbers(a, *b); - }, - Option::None => { - break a; - }, + Option::Some(b) => { a = gcd_two_numbers(a, *b); }, + Option::None => { break a; }, }; } } diff --git a/src/math/src/keccak256.cairo b/src/math/src/keccak256.cairo index fcbd8bec..4d8b82c2 100644 --- a/src/math/src/keccak256.cairo +++ b/src/math/src/keccak256.cairo @@ -19,9 +19,7 @@ impl U64Impl of U64Trait { loop { let byte = match self.pop_back() { Option::Some(byte) => *byte, - Option::None => { - break; - }, + Option::None => { break; }, }; value = value * 0x100 + (byte.into()); }; diff --git a/src/math/src/sha256.cairo b/src/math/src/sha256.cairo index bd6aa985..a6e2c13b 100644 --- a/src/math/src/sha256.cairo +++ b/src/math/src/sha256.cairo @@ -102,9 +102,7 @@ fn from_u32Array_to_u8Array(mut data: Span) -> Array { res = *val & 0xff; result.append(res.try_into().unwrap()); }, - Option::None => { - break; - }, + Option::None => { break; }, }; }; result @@ -195,9 +193,7 @@ fn from_u8Array_to_u32Array(mut data: Span) -> Array { value = value + (*val4).into(); result.append(value); }, - Option::None => { - break; - }, + Option::None => { break; }, }; }; result diff --git a/src/numeric/src/cumsum.cairo b/src/numeric/src/cumsum.cairo index 34e07013..38ddbc7c 100644 --- a/src/numeric/src/cumsum.cairo +++ b/src/numeric/src/cumsum.cairo @@ -24,9 +24,7 @@ fn cumsum, impl TCopy: Copy, impl TDrop: Drop,>( array.append(sum); prev_value = sum; }, - Option::None => { - break; - }, + Option::None => { break; }, }; }; array diff --git a/src/numeric/src/diff.cairo b/src/numeric/src/diff.cairo index 78096be4..61a62d99 100644 --- a/src/numeric/src/diff.cairo +++ b/src/numeric/src/diff.cairo @@ -32,9 +32,7 @@ fn diff< array.append(*current_value - prev_value); prev_value = *current_value; }, - Option::None => { - break; - }, + Option::None => { break; }, }; }; array diff --git a/src/searching/src/dijkstra.cairo b/src/searching/src/dijkstra.cairo index bd06f852..ca5d2b7f 100644 --- a/src/searching/src/dijkstra.cairo +++ b/src/searching/src/dijkstra.cairo @@ -55,9 +55,7 @@ impl GraphImpl of GraphTrait { nodes.append(node); nodes.span() }, - FromNullableResult::NotNull(adj_nodes) => { - adj_nodes.unbox() - }, + FromNullableResult::NotNull(adj_nodes) => { adj_nodes.unbox() }, }; // iterate over existing array to add new node @@ -128,9 +126,7 @@ fn dijkstra(ref self: Graph>>, source: u32) -> Felt252Dict { - adj_nodes.unbox() - }, + FromNullableResult::NotNull(adj_nodes) => { adj_nodes.unbox() }, }; if !no_more_adj_node { diff --git a/src/searching/src/tests/dijkstra_test.cairo b/src/searching/src/tests/dijkstra_test.cairo index 84ba4f28..32918eba 100644 --- a/src/searching/src/tests/dijkstra_test.cairo +++ b/src/searching/src/tests/dijkstra_test.cairo @@ -26,12 +26,8 @@ fn add_edge() { let val = graph.adj_nodes.get(source.into()); let span = match match_nullable(val) { - FromNullableResult::Null => { - panic_with_felt252('No value found') - }, - FromNullableResult::NotNull(val) => { - val.unbox() - }, + FromNullableResult::Null => { panic_with_felt252('No value found') }, + FromNullableResult::NotNull(val) => { val.unbox() }, }; assert(span.len() == 4, 'wrong nb of adj edge for node 0'); @@ -47,12 +43,8 @@ fn add_edge() { let val = graph.adj_nodes.get(2.into()); let span = match match_nullable(val) { - FromNullableResult::Null => { - panic_with_felt252('No value found') - }, - FromNullableResult::NotNull(val) => { - val.unbox() - }, + FromNullableResult::Null => { panic_with_felt252('No value found') }, + FromNullableResult::NotNull(val) => { val.unbox() }, }; assert(span.len() == 2, 'wrong nb of adj edge for node 2'); diff --git a/src/sorting/src/lib.cairo b/src/sorting/src/lib.cairo index ba0d8f58..8b0042c6 100644 --- a/src/sorting/src/lib.cairo +++ b/src/sorting/src/lib.cairo @@ -24,9 +24,7 @@ fn is_equal(mut a: Span, mut b: Span) -> bool { break false; } }, - Option::None => { - break true; - }, + Option::None => { break true; }, }; } } diff --git a/src/storage/src/list.cairo b/src/storage/src/list.cairo index d8cbf765..1d7f40fc 100644 --- a/src/storage/src/list.cairo +++ b/src/storage/src/list.cairo @@ -123,9 +123,7 @@ impl ListImpl, impl TDrop: Drop, impl TStore: Store Store::write_at_offset(self.address_domain, base, offset, *v).unwrap_syscall(); index += 1; }, - Option::None => { - break; - } + Option::None => { break; } }; }; Store::write(self.address_domain, self.base, self.len); From 4581b2c5dbada63fc1ad31cc33cbddf7e874fbf0 Mon Sep 17 00:00:00 2001 From: Marcus Liotta Date: Sun, 8 Oct 2023 15:59:37 +0200 Subject: [PATCH 7/9] whitespace cleanup --- src/data_structures/src/byte_array_ext.cairo | 8 +++--- .../src/byte_array_reader.cairo | 26 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/data_structures/src/byte_array_ext.cairo b/src/data_structures/src/byte_array_ext.cairo index 152c6d6c..7418f44c 100644 --- a/src/data_structures/src/byte_array_ext.cairo +++ b/src/data_structures/src/byte_array_ext.cairo @@ -51,25 +51,25 @@ trait ByteArrayTraitExt { /// # Arguments /// * `word` - a 128 bit signed integer typed as i128 fn append_i128(ref self: ByteArray, word: i128); - /// Reads consecutive bytes from a specified offset as an unsigned integer + /// Reads consecutive bytes from a specified offset as an unsigned integer /// # Arguments /// * `offset` - the start location of the consecutive bytes to read /// # Returns /// * `Option` - Returns an integer if there are enough consecutive bytes available in the ByteArray fn word_u16(self: @ByteArray, offset: usize) -> Option; - /// Reads consecutive bytes from a specified offset as an unsigned integer + /// Reads consecutive bytes from a specified offset as an unsigned integer /// # Arguments /// * `offset` - the start location of the consecutive bytes to read /// # Returns /// * `Option` - Returns an integer if there are enough consecutive bytes available in the ByteArray fn word_u32(self: @ByteArray, offset: usize) -> Option; - /// Reads consecutive bytes from a specified offset as an unsigned integer + /// Reads consecutive bytes from a specified offset as an unsigned integer /// # Arguments /// * `offset` - the start location of the consecutive bytes to read /// # Returns /// * `Option` - Returns an integer if there are enough consecutive bytes available in the ByteArray fn word_u64(self: @ByteArray, offset: usize) -> Option; - /// Reads consecutive bytes from a specified offset as an unsigned integer + /// Reads consecutive bytes from a specified offset as an unsigned integer /// # Arguments /// * `offset` - the start location of the consecutive bytes to read /// # Returns diff --git a/src/data_structures/src/byte_array_reader.cairo b/src/data_structures/src/byte_array_reader.cairo index c2417816..53c58260 100644 --- a/src/data_structures/src/byte_array_reader.cairo +++ b/src/data_structures/src/byte_array_reader.cairo @@ -22,56 +22,56 @@ trait ByteArrayReaderTrait { /// `ByteArrayReader` - a new reader starting at the beginning of the underlying ByteArray fn new(from: @ByteArray) -> ByteArrayReader; /// Reads a u8 unsigned integer - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u8(ref self: ByteArrayReader) -> Option; /// Reads a u16 unsigned integer - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u16(ref self: ByteArrayReader) -> Option; /// Reads a u32 unsigned integer - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u32(ref self: ByteArrayReader) -> Option; /// Reads a u64 unsigned integer - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u64(ref self: ByteArrayReader) -> Option; /// Reads a u128 unsigned integer - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u128(ref self: ByteArrayReader) -> Option; /// Reads a u256 unsigned integer - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u256(ref self: ByteArrayReader) -> Option; /// Reads a u512 unsigned integer - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_u512(ref self: ByteArrayReader) -> Option; /// Reads an i8 signed integer in two's complement encoding from the ByteArray - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_i8(ref self: ByteArrayReader) -> Option; /// Reads an i16 signed integer in two's complement encoding from the ByteArray - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_i16(ref self: ByteArrayReader) -> Option; /// Reads an i32 signed integer in two's complement encoding from the ByteArray - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_i32(ref self: ByteArrayReader) -> Option; /// Reads an i64 signed integer in two's complement encoding from the ByteArray - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_i64(ref self: ByteArrayReader) -> Option; /// Reads an i128 signed integer in two's complement encoding from the ByteArray - /// # Returns + /// # Returns /// `Option` - If there are enough bytes remaining an optional integer is returned fn read_i128(ref self: ByteArrayReader) -> Option; /// Returns the remaining length of the ByteArrayReader /// # Returns - /// `usize` - The number of bytes remaining considering the number of bytes that have already been consumed + /// `usize` - The number of bytes remaining, considering the number of bytes that have already been consumed fn len(self: @ByteArrayReader) -> usize; } From 5511ac54fdcaf0c25842e6ee74c5930640890331 Mon Sep 17 00:00:00 2001 From: Marcus Liotta Date: Fri, 13 Oct 2023 13:41:48 +0200 Subject: [PATCH 8/9] adds reversible --- src/encoding/src/lib.cairo | 1 + src/encoding/src/reversible.cairo | 265 +++++++++++++++++++ src/encoding/src/tests.cairo | 1 + src/encoding/src/tests/reversible_test.cairo | 215 +++++++++++++++ 4 files changed, 482 insertions(+) create mode 100644 src/encoding/src/reversible.cairo create mode 100644 src/encoding/src/tests/reversible_test.cairo diff --git a/src/encoding/src/lib.cairo b/src/encoding/src/lib.cairo index 2853b074..e6aec3b2 100644 --- a/src/encoding/src/lib.cairo +++ b/src/encoding/src/lib.cairo @@ -1,4 +1,5 @@ mod base64; +mod reversible; #[cfg(test)] mod tests; diff --git a/src/encoding/src/reversible.cairo b/src/encoding/src/reversible.cairo new file mode 100644 index 00000000..90c8e38f --- /dev/null +++ b/src/encoding/src/reversible.cairo @@ -0,0 +1,265 @@ +use integer::u512; +use traits::DivRem; + +const SELECT_BYTE: u16 = 0x100; +const SELECT_BIT: u8 = 0b10; + +/// Implies that there is an underlying byte order for type T that can be reversed +trait ReversibleBytes { + /// Reverses the byte order or endianness of `self`. + /// For example, the word `0x1122_u16` is reversed into `0x2211_u16`. + /// # Returns + /// `T` - returns the byte reversal of `self` into the same type T + fn reverse_bytes(self: @T) -> T; +} + +/// Implies that there is an underlying bit order for type T that can be reversed +trait ReversibleBits { + /// Reverses the underlying ordering of the bit representation of `self`. + /// For example, the word `0b10111010_u8` is reversed into `0b01011101`. + /// # Returns + /// `T` - the bit-representation of `self` reversed into the same type T + fn reverse_bits(self: @T) -> T; +} + +#[inline] +fn reversing< + T, + impl TCopy: Copy, + impl TZeroable: Zeroable, + impl TTryInto: TryInto>, + impl TDivRem: DivRem, + impl TDrop: Drop, + impl TMulEq: MulEq, + impl TRem: Rem, + impl TAddEq: AddEq +>( + word: T, size: usize, step: T +) -> (T, T) { + let result = TZeroable::zero(); + reversing_partial_result(word, result, size, step) +} + +#[inline] +fn reversing_partial_result< + T, + impl TCopy: Copy, + impl TDivRem: DivRem, + impl TTryInto: TryInto>, + impl TDrop: Drop, + impl TMulEq: MulEq, + impl TRem: Rem, + impl TAddEq: AddEq +>( + mut word: T, mut onto: T, size: usize, step: T +) -> (T, T) { + let mut i: usize = 0; + loop { + if i == size { + break; + } + let (new_word, remainder) = DivRem::div_rem(word, step.try_into().unwrap()); + word = new_word; + onto *= step.into(); + onto += remainder; + i += 1; + }; + (onto, word) +} + +impl U8Reversible of ReversibleBytes { + fn reverse_bytes(self: @u8) -> u8 { + *self + } +} + +impl U8ReversibleBits of ReversibleBits { + fn reverse_bits(self: @u8) -> u8 { + let (result, _) = reversing(word: *self, size: 8, step: SELECT_BIT); + result + } +} + +impl U16Reversible of ReversibleBytes { + fn reverse_bytes(self: @u16) -> u16 { + let (result, _) = reversing(word: *self, size: 2, step: SELECT_BYTE); + result + } +} + +impl U16ReversibleBits of ReversibleBits { + fn reverse_bits(self: @u16) -> u16 { + let (result, _) = reversing(word: *self, size: 16, step: SELECT_BIT.into()); + result + } +} + +impl U32Reversible of ReversibleBytes { + fn reverse_bytes(self: @u32) -> u32 { + let (result, _) = reversing(word: *self, size: 4, step: SELECT_BYTE.into()); + result + } +} + +impl U32ReversibleBits of ReversibleBits { + fn reverse_bits(self: @u32) -> u32 { + let (result, _) = reversing(word: *self, size: 32, step: SELECT_BIT.into()); + result + } +} + +impl U64Reversible of ReversibleBytes { + fn reverse_bytes(self: @u64) -> u64 { + let (result, _) = reversing(word: *self, size: 8, step: SELECT_BYTE.into()); + result + } +} + +impl U64ReversibleBits of ReversibleBits { + fn reverse_bits(self: @u64) -> u64 { + let (result, _) = reversing(word: *self, size: 64, step: SELECT_BIT.into()); + result + } +} + +impl U128Reversible of ReversibleBytes { + fn reverse_bytes(self: @u128) -> u128 { + let (result, _) = reversing(word: *self, size: 16, step: SELECT_BYTE.into()); + result + } +} + +impl U128ReversibleBits of ReversibleBits { + fn reverse_bits(self: @u128) -> u128 { + let (result, _) = reversing(word: *self, size: 128, step: SELECT_BIT.into()); + result + } +} + +impl U256Reversible of ReversibleBytes { + fn reverse_bytes(self: @u256) -> u256 { + let u256{low, high } = *self; + let (low_reversed, _) = reversing(word: low, size: 16, step: SELECT_BYTE.into()); + let (high_reversed, _) = reversing(word: high, size: 16, step: SELECT_BYTE.into()); + u256 { low: high_reversed, high: low_reversed } + } +} + +impl U256ReversibleBits of ReversibleBits { + fn reverse_bits(self: @u256) -> u256 { + let u256{low, high } = *self; + let (low_reversed, _) = reversing(word: low, size: 128, step: SELECT_BIT.into()); + let (high_reversed, _) = reversing(word: high, size: 128, step: SELECT_BIT.into()); + u256 { low: high_reversed, high: low_reversed } + } +} + +impl U512Reversible of ReversibleBytes { + fn reverse_bytes(self: @u512) -> u512 { + let u512{limb0, limb1, limb2, limb3 } = *self; + let (limb0_reversed, _) = reversing(word: limb0, size: 16, step: SELECT_BYTE.into()); + let (limb1_reversed, _) = reversing(word: limb1, size: 16, step: SELECT_BYTE.into()); + let (limb2_reversed, _) = reversing(word: limb2, size: 16, step: SELECT_BYTE.into()); + let (limb3_reversed, _) = reversing(word: limb3, size: 16, step: SELECT_BYTE.into()); + u512 { + limb0: limb3_reversed, + limb1: limb2_reversed, + limb2: limb1_reversed, + limb3: limb0_reversed + } + } +} + +impl U512ReversibleBits of ReversibleBits { + fn reverse_bits(self: @u512) -> u512 { + let u512{limb0, limb1, limb2, limb3 } = *self; + let (limb0_reversed, _) = reversing(word: limb0, size: 128, step: SELECT_BIT.into()); + let (limb1_reversed, _) = reversing(word: limb1, size: 128, step: SELECT_BIT.into()); + let (limb2_reversed, _) = reversing(word: limb2, size: 128, step: SELECT_BIT.into()); + let (limb3_reversed, _) = reversing(word: limb3, size: 128, step: SELECT_BIT.into()); + u512 { + limb0: limb3_reversed, + limb1: limb2_reversed, + limb2: limb1_reversed, + limb3: limb0_reversed + } + } +} + +impl Bytes31Reversible of ReversibleBytes { + // Consider A and C consisting of 15 bytes each. B carries a single byte of data. + // Z is the zero padded remainder, then the following transformation is required: + // low: A B -> low_rev: C_rev B_rev + // high: C Z -> high_rev: A_rev Z + fn reverse_bytes(self: @bytes31) -> bytes31 { + let u256{low, high } = (*self).into(); + let (c_rev, _) = reversing( + word: high, size: 15, step: SELECT_BYTE.into() + ); + let (low_rev, a) = reversing_partial_result( // pushes b_rev yielding low_rev + word: low, onto: c_rev, size: 1, step: SELECT_BYTE.into() + ); + let (high_rev, _) = reversing( + word: a, size: 15, step: SELECT_BYTE.into() + ); + let felt: felt252 = u256 { low: low_rev, high: high_rev }.try_into().unwrap(); + felt.try_into().unwrap() + } +} + +impl Bytes31ReversibleBits of ReversibleBits { + fn reverse_bits(self: @bytes31) -> bytes31 { + let u256{low, high } = (*self).into(); + let (c_rev, _) = reversing( + word: high, size: 120, step: SELECT_BIT.into() + ); + let (low_rev, a) = reversing_partial_result( // pushes b_rev yielding low_rev + word: low, onto: c_rev, size: 8, step: SELECT_BIT.into() + ); + let (high_rev, _) = reversing( + word: a, size: 120, step: SELECT_BIT.into() + ); + let felt: felt252 = u256 { low: low_rev, high: high_rev }.try_into().unwrap(); + felt.try_into().unwrap() + + + // let u256{low, high } = (*self).into(); + // let (high_rev, b) = reversing( + // word: low, size: 120, step: SELECT_BIT.into() + // ); + // let (b_rev, _) = reversing(word: b, size: 8, step: SELECT_BIT.into()); + // let (low_rev, _) = reversing_partial_result( + // word: high, onto: b_rev, size: 120, step: SELECT_BIT.into() + // ); + // let felt: felt252 = u256 { low: low_rev, high: high_rev }.try_into().unwrap(); + // felt.try_into().unwrap() + } +} + +impl ArrayReversibleBytes, +Drop, +ReversibleBytes> of ReversibleBytes> { + fn reverse_bytes(self: @Array) -> Array { + let mut span = self.span(); + let mut result: Array = Default::default(); + loop { + match span.pop_back() { + Option::Some(value) => { result.append(value.reverse_bytes()); }, + Option::None => { break; } + } + }; + result + } +} + +impl ArrayReversibleBits, +Copy, +Drop> of ReversibleBits> { + fn reverse_bits(self: @Array) -> Array { + let mut span = self.span(); + let mut result: Array = Default::default(); + loop { + match span.pop_back() { + Option::Some(value) => { result.append(value.reverse_bits()); }, + Option::None => { break; } + } + }; + result + } +} diff --git a/src/encoding/src/tests.cairo b/src/encoding/src/tests.cairo index a9e8056d..6355118b 100644 --- a/src/encoding/src/tests.cairo +++ b/src/encoding/src/tests.cairo @@ -1 +1,2 @@ mod base64_test; +mod reversible_test; \ No newline at end of file diff --git a/src/encoding/src/tests/reversible_test.cairo b/src/encoding/src/tests/reversible_test.cairo new file mode 100644 index 00000000..1cd57400 --- /dev/null +++ b/src/encoding/src/tests/reversible_test.cairo @@ -0,0 +1,215 @@ +use alexandria_encoding::reversible::{ReversibleBits, ReversibleBytes}; +use integer::u512; + +use debug::PrintTrait; + +#[test] +#[available_gas(1000000)] +fn test_reverse_bytes_u8() { + let t: u8 = 0b10111010; + let rev = t.reverse_bytes(); + assert(t == rev, 'not equal'); + assert(t == rev.reverse_bytes(), 'not equal'); +} + +#[test] +#[available_gas(1000000)] +fn test_reverse_bytes_u16() { + let t: u16 = 0x1122; + let rev = t.reverse_bytes(); + assert(rev == 0x2211, 'not equal'); + assert(rev.reverse_bytes() == t, 'not equal'); +} + +#[test] +#[available_gas(1000000)] +fn test_reverse_bytes_u32() { + let t: u32 = 0x11223344; + let rev = t.reverse_bytes(); + assert(rev == 0x44332211, 'not equal'); + assert(rev.reverse_bytes() == t, 'not equal'); +} + +#[test] +#[available_gas(1000000)] +fn test_reverse_bytes_u64() { + let t: u64 = 0x1122334455667788; + let rev = t.reverse_bytes(); + assert(rev == 0x8877665544332211, 'not equal'); + assert(rev.reverse_bytes() == t, 'not equal'); +} + +#[test] +#[available_gas(1000000)] +fn test_reverse_bytes_u128() { + let t: u128 = 0x112233445566778899aabbccddeeff00; + let rev = t.reverse_bytes(); + assert(rev == 0x00ffeeddccbbaa998877665544332211, 'not equal'); + assert(rev.reverse_bytes() == t, 'not equal'); +} + +#[test] +#[available_gas(10000000)] +fn test_reverse_bytes_u256() { + let t1: u128 = 0x101112131415161718191a1b1c1d1e1f; + let t2: u128 = 0x202122232425262728292a2b2c2d2e2f; + let t = u256{low: t1, high: t2 }; + let rev = t.reverse_bytes(); + assert(rev == u256{low: t2.reverse_bytes(), high: t1.reverse_bytes()}, 'not equal'); + assert(rev.reverse_bytes() == t, 'not equal'); +} + +#[test] +#[available_gas(10000000)] +fn test_reverse_bytes_u512() { + let t0: u128 = 0x101112131415161718191a1b1c1d1e1f; + let t1: u128 = 0x202122232425262728292a2b2c2d2e2f; + let t2: u128 = 0x303132333435363738393a3b3c3d3e3f; + let t3: u128 = 0x404142434445464748494a4b4c4d4e4f; + let t = u512{limb0: t0, limb1: t1, limb2: t2, limb3: t3 }; + let t_rev = u512{limb0: t3.reverse_bytes(), limb1: t2.reverse_bytes(), limb2: t1.reverse_bytes(), limb3: t0.reverse_bytes()}; + let rev = t.reverse_bytes(); + assert(rev == t_rev, 'not equal'); + assert(rev.reverse_bytes() == t, 'not equal'); +} + +#[test] +#[available_gas(10000000)] +fn test_reverse_bytes_bytes31() { + let t1: u128 = 0x101112131415161718191a1b1c1d1e1f; + let t2: u128 = 0x202122232425262728292a2b2c2d2e; + let felt: felt252 = u256{low: t1, high: t2 }.try_into().unwrap(); + let t: bytes31 = felt.try_into().unwrap(); + let t_rev_u256 = u256 { + low: 0x2e2d2c2b2a292827262524232221201f, + high: 0x1e1d1c1b1a19181716151413121110, + }; + let t_rev_felt: felt252 = t_rev_u256.try_into().unwrap(); + let t_rev: bytes31 = t_rev_felt.try_into().unwrap(); + let rev = t.reverse_bytes(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bytes() == t, 'not equal'); +} + +#[test] +#[available_gas(10000000)] +fn test_reverse_bytes_array() { + let t: Array = array![0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee]; + let t_rev: Array = array![0xeedd, 0xccbb, 0xaa99, 0x8877, 0x6655, 0x4433, 0x2211]; + let rev = t.reverse_bytes(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bytes() == t, 'not equal'); +} + +#[test] +#[available_gas(1000000)] +fn test_reverse_bits_u8() { + let t: u8 = 0b10111010; + let t_rev: u8 = 0b01011101; + let rev = t.reverse_bits(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bits() == t, 'not equal'); +} + +#[test] +#[available_gas(1000000)] +fn test_reverse_bits_u16() { + let t: u16 = 0x11aa; + let t_rev: u16 = 0x5588; + let rev = t.reverse_bits(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bits() == t, 'not equal'); +} + +#[test] +#[available_gas(10000000)] +fn test_reverse_bits_u32() { + let t: u32 = 0x1111aaaa; + let t_rev: u32 = 0x55558888; + let rev = t.reverse_bits(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bits() == t, 'not equal'); +} + +#[test] +#[available_gas(10000000)] +fn test_reverse_bits_u64() { + let t: u64 = 0x11111111aaaaaaaa; + let t_rev: u64 = 0x5555555588888888; + let rev = t.reverse_bits(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bits() == t, 'not equal'); +} + +#[test] +#[available_gas(10000000)] +fn test_reverse_bits_u128() { + let t: u128 = 0x1111111111111111aaaaaaaaaaaaaaaa; + let t_rev: u128 = 0x55555555555555558888888888888888; + let rev = t.reverse_bits(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bits() == t, 'not equal'); +} + +#[test] +#[available_gas(100000000)] +fn test_reverse_bits_u256() { + let t1: u128 = 0x1111111111111111aaaaaaaaaaaaaaaa; + let t2: u128 = 0xcccccccccccccccc7777777777777777; + let t: u256 = u256{low: t1, high: t2}; + let t_rev: u256 = u256 { + low: 0xeeeeeeeeeeeeeeee3333333333333333, + high: 0x55555555555555558888888888888888, + }; + let rev = t.reverse_bits(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bits() == t, 'not equal'); +} + +#[test] +#[available_gas(100000000)] +fn test_reverse_bits_u512() { + let t0: u128 = 0x1111111111111111aaaaaaaaaaaaaaaa; + let t1: u128 = 0xcccccccccccccccc7777777777777777; + let t2: u128 = 0x33333333333333334444444444444444; + let t3: u128 = 0xaaaaaaaaaaaaaaaaeeeeeeeeeeeeeeee; + let t: u512 = u512{limb0: t0, limb1: t1, limb2: t2, limb3: t3}; + let t_rev = u512 { + limb0: t3.reverse_bits(), + limb1: t2.reverse_bits(), + limb2: t1.reverse_bits(), + limb3: t0.reverse_bits(), + }; + let rev = t.reverse_bits(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bits() == t, 'not equal'); +} + +#[test] +#[available_gas(100000000)] +fn test_reverse_bits_bytes31() { + let t1: u128 = 0x123457bcde123457bcde123457bcde12; + let t2: u128 = 0x84c2aed3b784c2aed3b784c2aed3b7; + let t_u256: u256 = u256{low: t1, high: t2}; + let felt: felt252 = t_u256.try_into().unwrap(); + let t: bytes31 = felt.try_into().unwrap(); + let t_rev_u256: u256 = u256 { + low: 0xedcb754321edcb754321edcb75432148, + high: 0x7b3dea2c487b3dea2c487b3dea2c48, + }; + let t_rev_felt: felt252 = t_rev_u256.try_into().unwrap(); + let t_rev: bytes31 = t_rev_felt.try_into().unwrap(); + let rev = t.reverse_bits(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bits() == t, 'not equal'); +} + +#[test] +#[available_gas(100000000)] +fn test_reverse_bits_array() { + let t: Array = array![0x1234, 0x57bc, 0xde84, 0xc2ae, 0xd3b7]; + let t_rev: Array = array![0xedcb, 0x7543, 0x217b, 0x3dea, 0x2c48]; + let rev = t.reverse_bits(); + assert(rev == t_rev, 'not equal rev'); + assert(rev.reverse_bits() == t, 'not equal'); +} From 9520d30cee688f7ac78f3aaa6c9d59241b84a03b Mon Sep 17 00:00:00 2001 From: Marcus Liotta Date: Fri, 13 Oct 2023 13:44:32 +0200 Subject: [PATCH 9/9] fmt --- src/encoding/src/reversible.cairo | 28 +++--------------- src/encoding/src/tests.cairo | 2 +- src/encoding/src/tests/reversible_test.cairo | 30 +++++++++++--------- 3 files changed, 21 insertions(+), 39 deletions(-) diff --git a/src/encoding/src/reversible.cairo b/src/encoding/src/reversible.cairo index 90c8e38f..1858d7e5 100644 --- a/src/encoding/src/reversible.cairo +++ b/src/encoding/src/reversible.cairo @@ -193,15 +193,11 @@ impl Bytes31Reversible of ReversibleBytes { // high: C Z -> high_rev: A_rev Z fn reverse_bytes(self: @bytes31) -> bytes31 { let u256{low, high } = (*self).into(); - let (c_rev, _) = reversing( - word: high, size: 15, step: SELECT_BYTE.into() - ); + let (c_rev, _) = reversing(word: high, size: 15, step: SELECT_BYTE.into()); let (low_rev, a) = reversing_partial_result( // pushes b_rev yielding low_rev word: low, onto: c_rev, size: 1, step: SELECT_BYTE.into() ); - let (high_rev, _) = reversing( - word: a, size: 15, step: SELECT_BYTE.into() - ); + let (high_rev, _) = reversing(word: a, size: 15, step: SELECT_BYTE.into()); let felt: felt252 = u256 { low: low_rev, high: high_rev }.try_into().unwrap(); felt.try_into().unwrap() } @@ -210,29 +206,13 @@ impl Bytes31Reversible of ReversibleBytes { impl Bytes31ReversibleBits of ReversibleBits { fn reverse_bits(self: @bytes31) -> bytes31 { let u256{low, high } = (*self).into(); - let (c_rev, _) = reversing( - word: high, size: 120, step: SELECT_BIT.into() - ); + let (c_rev, _) = reversing(word: high, size: 120, step: SELECT_BIT.into()); let (low_rev, a) = reversing_partial_result( // pushes b_rev yielding low_rev word: low, onto: c_rev, size: 8, step: SELECT_BIT.into() ); - let (high_rev, _) = reversing( - word: a, size: 120, step: SELECT_BIT.into() - ); + let (high_rev, _) = reversing(word: a, size: 120, step: SELECT_BIT.into()); let felt: felt252 = u256 { low: low_rev, high: high_rev }.try_into().unwrap(); felt.try_into().unwrap() - - - // let u256{low, high } = (*self).into(); - // let (high_rev, b) = reversing( - // word: low, size: 120, step: SELECT_BIT.into() - // ); - // let (b_rev, _) = reversing(word: b, size: 8, step: SELECT_BIT.into()); - // let (low_rev, _) = reversing_partial_result( - // word: high, onto: b_rev, size: 120, step: SELECT_BIT.into() - // ); - // let felt: felt252 = u256 { low: low_rev, high: high_rev }.try_into().unwrap(); - // felt.try_into().unwrap() } } diff --git a/src/encoding/src/tests.cairo b/src/encoding/src/tests.cairo index 6355118b..4959d948 100644 --- a/src/encoding/src/tests.cairo +++ b/src/encoding/src/tests.cairo @@ -1,2 +1,2 @@ mod base64_test; -mod reversible_test; \ No newline at end of file +mod reversible_test; diff --git a/src/encoding/src/tests/reversible_test.cairo b/src/encoding/src/tests/reversible_test.cairo index 1cd57400..2d1690ed 100644 --- a/src/encoding/src/tests/reversible_test.cairo +++ b/src/encoding/src/tests/reversible_test.cairo @@ -53,9 +53,9 @@ fn test_reverse_bytes_u128() { fn test_reverse_bytes_u256() { let t1: u128 = 0x101112131415161718191a1b1c1d1e1f; let t2: u128 = 0x202122232425262728292a2b2c2d2e2f; - let t = u256{low: t1, high: t2 }; + let t = u256 { low: t1, high: t2 }; let rev = t.reverse_bytes(); - assert(rev == u256{low: t2.reverse_bytes(), high: t1.reverse_bytes()}, 'not equal'); + assert(rev == u256 { low: t2.reverse_bytes(), high: t1.reverse_bytes() }, 'not equal'); assert(rev.reverse_bytes() == t, 'not equal'); } @@ -66,8 +66,13 @@ fn test_reverse_bytes_u512() { let t1: u128 = 0x202122232425262728292a2b2c2d2e2f; let t2: u128 = 0x303132333435363738393a3b3c3d3e3f; let t3: u128 = 0x404142434445464748494a4b4c4d4e4f; - let t = u512{limb0: t0, limb1: t1, limb2: t2, limb3: t3 }; - let t_rev = u512{limb0: t3.reverse_bytes(), limb1: t2.reverse_bytes(), limb2: t1.reverse_bytes(), limb3: t0.reverse_bytes()}; + let t = u512 { limb0: t0, limb1: t1, limb2: t2, limb3: t3 }; + let t_rev = u512 { + limb0: t3.reverse_bytes(), + limb1: t2.reverse_bytes(), + limb2: t1.reverse_bytes(), + limb3: t0.reverse_bytes() + }; let rev = t.reverse_bytes(); assert(rev == t_rev, 'not equal'); assert(rev.reverse_bytes() == t, 'not equal'); @@ -78,11 +83,10 @@ fn test_reverse_bytes_u512() { fn test_reverse_bytes_bytes31() { let t1: u128 = 0x101112131415161718191a1b1c1d1e1f; let t2: u128 = 0x202122232425262728292a2b2c2d2e; - let felt: felt252 = u256{low: t1, high: t2 }.try_into().unwrap(); + let felt: felt252 = u256 { low: t1, high: t2 }.try_into().unwrap(); let t: bytes31 = felt.try_into().unwrap(); let t_rev_u256 = u256 { - low: 0x2e2d2c2b2a292827262524232221201f, - high: 0x1e1d1c1b1a19181716151413121110, + low: 0x2e2d2c2b2a292827262524232221201f, high: 0x1e1d1c1b1a19181716151413121110, }; let t_rev_felt: felt252 = t_rev_u256.try_into().unwrap(); let t_rev: bytes31 = t_rev_felt.try_into().unwrap(); @@ -156,10 +160,9 @@ fn test_reverse_bits_u128() { fn test_reverse_bits_u256() { let t1: u128 = 0x1111111111111111aaaaaaaaaaaaaaaa; let t2: u128 = 0xcccccccccccccccc7777777777777777; - let t: u256 = u256{low: t1, high: t2}; + let t: u256 = u256 { low: t1, high: t2 }; let t_rev: u256 = u256 { - low: 0xeeeeeeeeeeeeeeee3333333333333333, - high: 0x55555555555555558888888888888888, + low: 0xeeeeeeeeeeeeeeee3333333333333333, high: 0x55555555555555558888888888888888, }; let rev = t.reverse_bits(); assert(rev == t_rev, 'not equal rev'); @@ -173,7 +176,7 @@ fn test_reverse_bits_u512() { let t1: u128 = 0xcccccccccccccccc7777777777777777; let t2: u128 = 0x33333333333333334444444444444444; let t3: u128 = 0xaaaaaaaaaaaaaaaaeeeeeeeeeeeeeeee; - let t: u512 = u512{limb0: t0, limb1: t1, limb2: t2, limb3: t3}; + let t: u512 = u512 { limb0: t0, limb1: t1, limb2: t2, limb3: t3 }; let t_rev = u512 { limb0: t3.reverse_bits(), limb1: t2.reverse_bits(), @@ -190,12 +193,11 @@ fn test_reverse_bits_u512() { fn test_reverse_bits_bytes31() { let t1: u128 = 0x123457bcde123457bcde123457bcde12; let t2: u128 = 0x84c2aed3b784c2aed3b784c2aed3b7; - let t_u256: u256 = u256{low: t1, high: t2}; + let t_u256: u256 = u256 { low: t1, high: t2 }; let felt: felt252 = t_u256.try_into().unwrap(); let t: bytes31 = felt.try_into().unwrap(); let t_rev_u256: u256 = u256 { - low: 0xedcb754321edcb754321edcb75432148, - high: 0x7b3dea2c487b3dea2c487b3dea2c48, + low: 0xedcb754321edcb754321edcb75432148, high: 0x7b3dea2c487b3dea2c487b3dea2c48, }; let t_rev_felt: felt252 = t_rev_u256.try_into().unwrap(); let t_rev: bytes31 = t_rev_felt.try_into().unwrap();