diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index c0f0c94a96b..c028fb80ccf 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -822,17 +822,35 @@ where false } fn abi_encode(self, buffer: Buffer) -> Buffer { - let len = self.len; - let mut buffer = len.abi_encode(buffer); + const IS_ELEM_TRIVIAL = is_encode_trivial::(); + + if IS_ELEM_TRIVIAL { + // TODO: We need to write the length of the vector, + // and then the raw memory of the vector's contents. + // Currently, we don't have a way to write the plain + // memory content without the length. E.g., writing slice + // will write the length of the vector slice in bytes, + // and then the raw memory, but not the length of the + // vector in number of elements. + // + // One possibility to solve this would be to have an intrinsic + // that would allow us to write the raw memory of a particular + // length, without the length prefix. E.g.: + // __encode_buffer_append_raw(buffer, ptr, len) + self.as_raw_slice().abi_encode(buffer) + } else { + let len = self.len; + let mut buffer = len.abi_encode(buffer); + + let mut i = 0; + while i < len { + let item = self.get_unchecked(i); + buffer = item.abi_encode(buffer); + i += 1; + } - let mut i = 0; - while i < len { - let item = self.get_unchecked(i); - buffer = item.abi_encode(buffer); - i += 1; + buffer } - - buffer } } @@ -844,18 +862,25 @@ where false } fn abi_decode(ref mut buffer: BufferReader) -> Vec { - let len = u64::abi_decode(buffer); + const IS_ELEM_TRIVIAL = is_decode_trivial::(); - let mut v = Vec::with_capacity(len); + if IS_ELEM_TRIVIAL { + // TODO: See the comment in `abi_encode` for the trivial case. + Self::from(raw_slice::abi_decode(buffer)) + } else { + let len = u64::abi_decode(buffer); - let mut i = 0; - while i < len { - let item = T::abi_decode(buffer); - v.push(item); - i += 1; - } + let mut v = Vec::with_capacity(len); + + let mut i = 0; + while i < len { + let item = T::abi_decode(buffer); + v.push(item); + i += 1; + } - v + v + } } } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/Forc.lock deleted file mode 100644 index b71b104c141..00000000000 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/Forc.lock +++ /dev/null @@ -1,8 +0,0 @@ -[[package]] -name = "std" -source = "path+from-root-D3556C503E51030C" - -[[package]] -name = "vec_ret" -source = "member" -dependencies = ["std"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/src/main.sw deleted file mode 100644 index 756f5e6070e..00000000000 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/src/main.sw +++ /dev/null @@ -1,9 +0,0 @@ -script; - -fn main() -> Vec { - let mut vec = Vec::new(); - vec.push(124); - vec.push(124); - vec.push(124); - vec -} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/test.toml deleted file mode 100644 index 1fe4a2e11a9..00000000000 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/test.toml +++ /dev/null @@ -1,3 +0,0 @@ -category = "run" -expected_result = { action = "return_data", value = "0000000003ffffc800000000000000040000000000000003" } -expected_result_new_encoding = { action = "return_data", value = "0000000000000003000000000000007c000000000000007c000000000000007c" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/raw_ptr_ret/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/Forc.lock similarity index 51% rename from test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/raw_ptr_ret/Forc.lock rename to test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/Forc.lock index 6df81d64b7e..2777f3bf57d 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/raw_ptr_ret/Forc.lock +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/Forc.lock @@ -1,8 +1,8 @@ [[package]] -name = "raw_ptr_ret" -source = "member" -dependencies = ["std"] +name = "std" +source = "path+from-root-2158C659FB34C0B1" [[package]] -name = "std" -source = "path+from-root-51D3AF48CE04FAE0" +name = "vec_encoding_decoding" +source = "member" +dependencies = ["std"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/Forc.toml similarity index 53% rename from test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/Forc.toml rename to test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/Forc.toml index edf93e2ad68..a3bab53894d 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/raw_ptr/vec_ret/Forc.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/Forc.toml @@ -2,7 +2,7 @@ authors = ["Fuel Labs "] entry = "main.sw" license = "Apache-2.0" -name = "vec_ret" +name = "vec_encoding_decoding" [dependencies] -std = { path = "../../../../../reduced_std_libs/sway-lib-std-vec" } +std = { path = "../../../../reduced_std_libs/sway-lib-std-vec" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/snapshot.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/snapshot.toml new file mode 100644 index 00000000000..1667538d60a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/snapshot.toml @@ -0,0 +1 @@ +cmds = ["forc test --path {root} --release --logs"] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/src/main.sw new file mode 100644 index 00000000000..e8500c0dcdb --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/src/main.sw @@ -0,0 +1,121 @@ +script; + +fn main(trivial: Vec, non_trivial: Vec) -> (Vec, Vec) { + assert_eq(trivial.len(), 3); + assert_eq(trivial.get(0).unwrap_or(0), 124); + assert_eq(trivial.get(1).unwrap_or(0), 124); + assert_eq(trivial.get(2).unwrap_or(0), 124); + + let mut trivial = Vec::from(trivial.as_raw_slice()); + trivial.push(124); + trivial.push(124); + trivial.push(124); + + assert_eq(non_trivial.len(), 3); + assert_eq(non_trivial.get(0).unwrap_or(0), 124); + assert_eq(non_trivial.get(1).unwrap_or(0), 124); + assert_eq(non_trivial.get(2).unwrap_or(0), 124); + + let mut non_trivial = Vec::from(non_trivial.as_raw_slice()); + non_trivial.push(124); + non_trivial.push(124); + non_trivial.push(124); + + (trivial, non_trivial) +} + +#[test] +fn vec_trivial() { + let vec = create_vec_trivial(10); + let encoded_decoded: Vec = abi_decode(encode(vec)); + assert_eq(encoded_decoded, vec); + + let encoded_as_alias = encode_allow_alias(&encoded_decoded); + let encoded_decoded: Vec = abi_decode(encoded_as_alias); + assert_eq(encoded_decoded, vec); + + log(encoded_decoded); +} + +#[test] +fn nested_vec_trivial() { + let vec = create_nested_vec_trivial(10); + let encoded_decoded: Vec> = abi_decode(encode(vec)); + assert_eq(encoded_decoded, vec); + + let encoded_as_alias = encode_allow_alias(&encoded_decoded); + let encoded_decoded: Vec> = abi_decode(encoded_as_alias); + assert_eq(encoded_decoded, vec); + + log(encoded_decoded); +} + +#[test] +fn vec_non_trivial() { + let vec = create_vec_trivial(10); + let encoded_decoded: Vec = abi_decode(encode(vec)); + assert_eq(encoded_decoded, vec); + + let encoded_as_alias = encode_allow_alias(&encoded_decoded); + let encoded_decoded: Vec = abi_decode(encoded_as_alias); + assert_eq(encoded_decoded, vec); + + log(encoded_decoded); +} + +#[test] +fn nested_vec_non_trivial() { + let vec = create_nested_vec_non_trivial(10); + let encoded_decoded: Vec> = abi_decode(encode(vec)); + assert_eq(encoded_decoded, vec); + + let encoded_as_alias = encode_allow_alias(&encoded_decoded); + let encoded_decoded: Vec> = abi_decode(encoded_as_alias); + assert_eq(encoded_decoded, vec); + + log(encoded_decoded); +} + +#[allow(dead_code)] +fn create_vec_trivial(n: u64) -> Vec { + let mut vec = Vec::::new(); + let mut i: u64 = 0; + while i < n { + vec.push(i); + i += 1; + } + vec +} + +#[allow(dead_code)] +fn create_nested_vec_trivial(n: u64) -> Vec> { + let mut vec = Vec::>::new(); + let mut i: u64 = 0; + while i < n { + vec.push(create_vec_trivial(i)); + i += 1; + } + vec +} + +#[allow(dead_code)] +fn create_vec_non_trivial(n: u32) -> Vec { + let mut vec = Vec::::new(); + let mut i: u32 = 0; + while i < n { + vec.push(i); + i += 1; + } + vec +} + +#[allow(dead_code)] +fn create_nested_vec_non_trivial(n: u32) -> Vec> { + let mut vec = Vec::>::new(); + let mut i: u32 = 0; + while i < n { + vec.push(create_vec_non_trivial(i)); + i += 1; + } + vec +} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/test.run.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/test.run.toml new file mode 100644 index 00000000000..e3e7741a9ab --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/test.run.toml @@ -0,0 +1,4 @@ +category = "run" + +script_data_new_encoding = "0000000000000003000000000000007c000000000000007c000000000000007c 00000000000000030000007c0000007c0000007c" +expected_result_new_encoding = { action = "return_data", value = "0000000000000006000000000000007c000000000000007c000000000000007c000000000000007c000000000000007c000000000000007c 00000000000000060000007c0000007c0000007c0000007c0000007c0000007c" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/test.toml new file mode 100644 index 00000000000..f1958c1b086 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/vec_encoding_decoding/test.toml @@ -0,0 +1 @@ +category = "unit_tests_pass" \ No newline at end of file