From 3b41e837835f9661b231aa1b17d238b9a67b011d Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Mon, 26 May 2025 16:04:48 +0200 Subject: [PATCH 01/16] cleanup --- src/storable/tuples.rs | 68 ++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index 180d5c88..ad01a04a 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -81,26 +81,24 @@ where } } - const BOUND: Bound = { - match (A::BOUND, B::BOUND) { - (Bound::Bounded { .. }, Bound::Bounded { .. }) => { - let a_bounds = bounds::(); - let b_bounds = bounds::(); + const BOUND: Bound = match (A::BOUND, B::BOUND) { + (Bound::Bounded { .. }, Bound::Bounded { .. }) => { + let a_bounds = bounds::(); + let b_bounds = bounds::(); - let max_size = a_bounds.max_size - + b_bounds.max_size - + bytes_to_store_size_bounded(&a_bounds) - + bytes_to_store_size_bounded(&b_bounds); + let max_size = a_bounds.max_size + + b_bounds.max_size + + bytes_to_store_size_bounded(&a_bounds) + + bytes_to_store_size_bounded(&b_bounds); - let is_fixed_size = a_bounds.is_fixed_size && b_bounds.is_fixed_size; + let is_fixed_size = a_bounds.is_fixed_size && b_bounds.is_fixed_size; - Bound::Bounded { - max_size, - is_fixed_size, - } + Bound::Bounded { + max_size, + is_fixed_size, } - _ => Bound::Unbounded, } + _ => Bound::Unbounded, }; } @@ -331,28 +329,26 @@ where (a, b, c) } - const BOUND: Bound = { - match (A::BOUND, B::BOUND, C::BOUND) { - (Bound::Bounded { .. }, Bound::Bounded { .. }, Bound::Bounded { .. }) => { - let a_bounds = bounds::(); - let b_bounds = bounds::(); - let c_bounds = bounds::(); - - let sizes_overhead = - sizes_overhead::(a_bounds.max_size as usize, b_bounds.max_size as usize) - as u32; - - Bound::Bounded { - max_size: a_bounds.max_size - + b_bounds.max_size - + c_bounds.max_size - + sizes_overhead, - is_fixed_size: a_bounds.is_fixed_size - && b_bounds.is_fixed_size - && c_bounds.is_fixed_size, - } + const BOUND: Bound = match (A::BOUND, B::BOUND, C::BOUND) { + (Bound::Bounded { .. }, Bound::Bounded { .. }, Bound::Bounded { .. }) => { + let a_bounds = bounds::(); + let b_bounds = bounds::(); + let c_bounds = bounds::(); + + let sizes_overhead = + sizes_overhead::(a_bounds.max_size as usize, b_bounds.max_size as usize) + as u32; + + Bound::Bounded { + max_size: a_bounds.max_size + + b_bounds.max_size + + c_bounds.max_size + + sizes_overhead, + is_fixed_size: a_bounds.is_fixed_size + && b_bounds.is_fixed_size + && c_bounds.is_fixed_size, } - _ => Bound::Unbounded, } + _ => Bound::Unbounded, }; } From 986cd0476735414e480070eb24b2320ba746684f Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Mon, 26 May 2025 16:13:04 +0200 Subject: [PATCH 02/16] cleanup --- src/storable/tuples.rs | 304 +++++++++++++++-------------------------- 1 file changed, 110 insertions(+), 194 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index ad01a04a..eb0bb42d 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -11,26 +11,19 @@ where fn to_bytes(&self) -> Cow<[u8]> { match Self::BOUND { Bound::Bounded { max_size, .. } => { - let mut bytes = vec![0; max_size as usize]; let a_bytes = self.0.to_bytes(); let b_bytes = self.1.to_bytes(); - let a_bounds = bounds::(); let b_bounds = bounds::(); - - let a_max_size = a_bounds.max_size as usize; - let b_max_size = b_bounds.max_size as usize; - - debug_assert!(a_bytes.len() <= a_max_size); - debug_assert!(b_bytes.len() <= b_max_size); - - bytes[0..a_bytes.len()].copy_from_slice(a_bytes.borrow()); - bytes[a_max_size..a_max_size + b_bytes.len()].copy_from_slice(b_bytes.borrow()); - + let a_max = a_bounds.max_size as usize; + let b_max = b_bounds.max_size as usize; let a_size_len = bytes_to_store_size_bounded(&a_bounds) as usize; let b_size_len = bytes_to_store_size_bounded(&b_bounds) as usize; + let sizes_offset = a_max + b_max; - let sizes_offset: usize = a_max_size + b_max_size; + let mut bytes = vec![0; max_size as usize]; + bytes[..a_bytes.len()].copy_from_slice(a_bytes.borrow()); + bytes[a_max..a_max + b_bytes.len()].copy_from_slice(b_bytes.borrow()); encode_size_of_bound( &mut bytes[sizes_offset..sizes_offset + a_size_len], @@ -54,15 +47,14 @@ where match Self::BOUND { Bound::Bounded { max_size, .. } => { assert_eq!(bytes.len(), max_size as usize); - let a_bounds = bounds::(); let b_bounds = bounds::(); - let a_max_size = a_bounds.max_size as usize; - let b_max_size = b_bounds.max_size as usize; - let sizes_offset = a_max_size + b_max_size; - + let a_max = a_bounds.max_size as usize; + let b_max = b_bounds.max_size as usize; + let sizes_offset = a_max + b_max; let a_size_len = bytes_to_store_size_bounded(&a_bounds) as usize; let b_size_len = bytes_to_store_size_bounded(&b_bounds) as usize; + let a_len = decode_size_of_bound( &bytes[sizes_offset..sizes_offset + a_size_len], &a_bounds, @@ -72,9 +64,8 @@ where &b_bounds, ); - let a = A::from_bytes(Cow::Borrowed(&bytes[0..a_len])); - let b = B::from_bytes(Cow::Borrowed(&bytes[a_max_size..a_max_size + b_len])); - + let a = A::from_bytes(Cow::Borrowed(&bytes[..a_len])); + let b = B::from_bytes(Cow::Borrowed(&bytes[a_max..a_max + b_len])); (a, b) } _ => todo!("Deserializing tuples with unbounded types is not yet supported."), @@ -85,17 +76,12 @@ where (Bound::Bounded { .. }, Bound::Bounded { .. }) => { let a_bounds = bounds::(); let b_bounds = bounds::(); - - let max_size = a_bounds.max_size - + b_bounds.max_size - + bytes_to_store_size_bounded(&a_bounds) - + bytes_to_store_size_bounded(&b_bounds); - - let is_fixed_size = a_bounds.is_fixed_size && b_bounds.is_fixed_size; - Bound::Bounded { - max_size, - is_fixed_size, + max_size: a_bounds.max_size + + b_bounds.max_size + + bytes_to_store_size_bounded(&a_bounds) + + bytes_to_store_size_bounded(&b_bounds), + is_fixed_size: a_bounds.is_fixed_size && b_bounds.is_fixed_size, } } _ => Bound::Unbounded, @@ -111,10 +97,9 @@ fn decode_size_of_bound(src: &[u8], bounds: &Bounds) -> usize { } fn encode_size_of_bound(dst: &mut [u8], n: usize, bounds: &Bounds) { - if bounds.is_fixed_size { - return; + if !bounds.is_fixed_size { + encode_size(dst, n, bytes_to_store_size(bounds.max_size as usize)); } - encode_size(dst, n, bytes_to_store_size(bounds.max_size as usize)); } /// Decodes size from the beginning of `src` of length `size_len` and returns it. @@ -127,124 +112,12 @@ fn decode_size(src: &[u8], size_len: usize) -> usize { } /// Encodes `size` at the beginning of `dst` of length `bytes_to_store_size` bytes. -fn encode_size(dst: &mut [u8], size: usize, bytes_to_store_size: usize) { - match bytes_to_store_size { +fn encode_size(dst: &mut [u8], size: usize, bytes: usize) { + match bytes { 1 => dst[0] = size as u8, - 2 => dst[0..2].copy_from_slice(&(size as u16).to_be_bytes()), - _ => dst[0..4].copy_from_slice(&(size as u32).to_be_bytes()), - }; -} - -fn encode_size_lengths(sizes: Vec) -> u8 { - assert!(sizes.len() <= 4); - - let mut size_lengths_byte: u8 = 0; - - for size in sizes.iter() { - let size_length = bytes_to_store_size(*size); - // Number of bytes required to store the size of every - // element is represented with 2 bits. - size_lengths_byte <<= 2; - // `size_length` can take value in {1, 2, 4}, but to - // compress it into 2 bit we will decrement its value. - size_lengths_byte += (size_length - 1) as u8; - } - - size_lengths_byte -} - -fn decode_size_lengths(mut encoded_bytes_to_store: u8, number_of_encoded_lengths: u8) -> Vec { - assert!(number_of_encoded_lengths <= 4); - - let mut bytes_to_store_sizes = vec![]; - - for _ in 0..number_of_encoded_lengths { - // The number of bytes required to store the size of every - // element is represented with 2 bits. Hence we use - // mask `11`, equivalent to 3 in the decimal system. - let mask: u8 = 3; - // The number of bytes required to store size can take value - // in {1, 2, 4}, but to compress it to 2-bit, - // when encoding we decreased the value, hence now we need - // to do inverse. - let bytes_to_store: u8 = (encoded_bytes_to_store & mask) + 1; - bytes_to_store_sizes.push(bytes_to_store); - encoded_bytes_to_store >>= 2; - } - - // Because encoding and decoding are started on the same - // end of the byte, we need to reverse `bytes_to_store_sizes` - // to get sizes in order. - bytes_to_store_sizes.reverse(); - - bytes_to_store_sizes -} - -// Encodes a serialized element `T` in a tuple. -// The element is assumed to be at the beginning of `dst`. -// Returns the number of bytes written to `dst`. -fn encode_tuple_element(dst: &mut [u8], bytes: &[u8], last: bool) -> usize { - let mut bytes_written: usize = 0; - let size = bytes.len(); - - if !last && !T::BOUND.is_fixed_size() { - encode_size(&mut dst[bytes_written..], size, bytes_to_store_size(size)); - bytes_written += bytes_to_store_size(size); - } - - dst[bytes_written..bytes_written + size].copy_from_slice(bytes); - bytes_written + size -} - -// Decodes an element `T` from a tuple. -// -// The element is assumed to be at the beginning of `src`. -// The length of the size of the element should be provided if the element is *not* fixed in size. -// -// Returns the element `T` and the number of bytes read from `src`. -fn decode_tuple_element(src: &[u8], size_len: Option, last: bool) -> (T, usize) { - let mut bytes_read: usize = 0; - - let size = if let Some(size_len) = size_len { - let size = decode_size(&src[bytes_read..], size_len as usize); - bytes_read += size_len as usize; - size - } else if let Bound::Bounded { - max_size, - is_fixed_size: true, - } = T::BOUND - { - max_size as usize - } else { - // This case should only happen for the last element. - assert!(last); - src.len() - }; - - ( - T::from_bytes(Cow::Borrowed(&src[bytes_read..bytes_read + size])), - bytes_read + size, - ) -} - -// Returns number of bytes required to store encoding of sizes for elements of type A and B. -const fn sizes_overhead(a_size: usize, b_size: usize) -> usize { - let mut sizes_overhead = 0; - - if !(A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size()) { - // 1B for size lengths encoding - sizes_overhead += 1; - - if !A::BOUND.is_fixed_size() { - sizes_overhead += bytes_to_store_size(a_size); - } - - if !B::BOUND.is_fixed_size() { - sizes_overhead += bytes_to_store_size(b_size); - } + 2 => dst[..2].copy_from_slice(&(size as u16).to_be_bytes()), + _ => dst[..4].copy_from_slice(&(size as u32).to_be_bytes()), } - - sizes_overhead } impl Storable for (A, B, C) @@ -253,79 +126,59 @@ where B: Storable, C: Storable, { - // Tuple (A, B, C) will be serialized in the following form: - // If A and B have fixed size - // - // Otherwise - // + // Tuple (A, B, C) serialization: + // If A and B have fixed size: + // Otherwise: fn to_bytes(&self) -> Cow<[u8]> { let a_bytes = self.0.to_bytes(); - let a_size = a_bytes.len(); - let b_bytes = self.1.to_bytes(); - let b_size = b_bytes.len(); - let c_bytes = self.2.to_bytes(); + let a_size = a_bytes.len(); + let b_size = b_bytes.len(); let c_size = c_bytes.len(); let sizes_overhead = sizes_overhead::(a_size, b_size); - let output_size = a_size + b_size + c_size + sizes_overhead; - - let mut bytes_written = 0; - let mut bytes = vec![0; output_size]; + let mut offset = 0; if sizes_overhead != 0 { - bytes[bytes_written] = encode_size_lengths(vec![a_size, b_size]); - bytes_written += 1; + bytes[0] = encode_size_lengths(vec![a_size, b_size]); + offset += 1; } - bytes_written += - encode_tuple_element::(&mut bytes[bytes_written..], a_bytes.borrow(), false); - bytes_written += - encode_tuple_element::(&mut bytes[bytes_written..], b_bytes.borrow(), false); - bytes_written += - encode_tuple_element::(&mut bytes[bytes_written..], c_bytes.borrow(), true); - - assert_eq!(bytes_written, output_size); + offset += encode_tuple_element::(&mut bytes[offset..], a_bytes.borrow(), false); + offset += encode_tuple_element::(&mut bytes[offset..], b_bytes.borrow(), false); + offset += encode_tuple_element::(&mut bytes[offset..], c_bytes.borrow(), true); + debug_assert_eq!(offset, output_size); Cow::Owned(bytes) } #[inline] fn from_bytes(bytes: Cow<[u8]>) -> Self { - let mut bytes_read_total = 0; - + let mut offset = 0; let mut size_lengths = [None, None]; if !(A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size()) { - let lengths = decode_size_lengths(bytes[bytes_read_total], 2); - bytes_read_total += 1; - + let lengths = decode_size_lengths(bytes[0], 2); + offset += 1; if !A::BOUND.is_fixed_size() { size_lengths[0] = Some(lengths[0]); } - if !B::BOUND.is_fixed_size() { size_lengths[1] = Some(lengths[1]); } } - let (a, bytes_read) = - decode_tuple_element::(&bytes[bytes_read_total..], size_lengths[0], false); - bytes_read_total += bytes_read; - - let (b, bytes_read) = - decode_tuple_element::(&bytes[bytes_read_total..], size_lengths[1], false); - bytes_read_total += bytes_read; - - let (c, bytes_read) = decode_tuple_element::(&bytes[bytes_read_total..], None, true); - - bytes_read_total += bytes_read; - - assert_eq!(bytes_read_total, bytes.len()); + let (a, read) = decode_tuple_element::(&bytes[offset..], size_lengths[0], false); + offset += read; + let (b, read) = decode_tuple_element::(&bytes[offset..], size_lengths[1], false); + offset += read; + let (c, read) = decode_tuple_element::(&bytes[offset..], None, true); + offset += read; + debug_assert_eq!(offset, bytes.len()); (a, b, c) } @@ -334,11 +187,9 @@ where let a_bounds = bounds::(); let b_bounds = bounds::(); let c_bounds = bounds::(); - let sizes_overhead = sizes_overhead::(a_bounds.max_size as usize, b_bounds.max_size as usize) as u32; - Bound::Bounded { max_size: a_bounds.max_size + b_bounds.max_size @@ -352,3 +203,68 @@ where _ => Bound::Unbounded, }; } + +const fn sizes_overhead(a_size: usize, b_size: usize) -> usize { + if A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size() { + 0 + } else { + 1 + if !A::BOUND.is_fixed_size() { + bytes_to_store_size(a_size) + } else { + 0 + } + if !B::BOUND.is_fixed_size() { + bytes_to_store_size(b_size) + } else { + 0 + } + } +} + +fn encode_size_lengths(sizes: Vec) -> u8 { + sizes.iter().fold(0, |acc, &size| { + (acc << 2) + (bytes_to_store_size(size) - 1) as u8 + }) +} + +fn decode_size_lengths(mut encoded: u8, count: u8) -> Vec { + let mut sizes = vec![]; + for _ in 0..count { + sizes.push((encoded & 3) + 1); + encoded >>= 2; + } + sizes.reverse(); + sizes +} + +fn encode_tuple_element(dst: &mut [u8], bytes: &[u8], last: bool) -> usize { + let mut written = 0; + if !last && !T::BOUND.is_fixed_size() { + let size_len = bytes_to_store_size(bytes.len()); + encode_size(&mut dst[written..], bytes.len(), size_len); + written += size_len; + } + dst[written..written + bytes.len()].copy_from_slice(bytes); + written + bytes.len() +} + +fn decode_tuple_element(src: &[u8], size_len: Option, last: bool) -> (T, usize) { + let mut read = 0; + let size = if let Some(len) = size_len { + let s = decode_size(&src[read..], len as usize); + read += len as usize; + s + } else if let Bound::Bounded { + max_size, + is_fixed_size: true, + } = T::BOUND + { + max_size as usize + } else { + assert!(last); + src.len() + }; + ( + T::from_bytes(Cow::Borrowed(&src[read..read + size])), + read + size, + ) +} From 59d5f622de16a719541cf77534d28cfaa6f82a06 Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Mon, 26 May 2025 16:17:12 +0200 Subject: [PATCH 03/16] . --- src/storable/tuples.rs | 58 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index eb0bb42d..7a54cd1f 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -221,21 +221,53 @@ const fn sizes_overhead(a_size: usize, b_size: usize) } fn encode_size_lengths(sizes: Vec) -> u8 { - sizes.iter().fold(0, |acc, &size| { - (acc << 2) + (bytes_to_store_size(size) - 1) as u8 - }) + assert!(sizes.len() <= 4); + + let mut size_lengths_byte: u8 = 0; + + for size in sizes.iter() { + let size_length = bytes_to_store_size(*size); + // Number of bytes required to store the size of every + // element is represented with 2 bits. + size_lengths_byte <<= 2; + // `size_length` can take value in {1, 2, 4}, but to + // compress it into 2 bit we will decrement its value. + size_lengths_byte += (size_length - 1) as u8; + } + + size_lengths_byte } -fn decode_size_lengths(mut encoded: u8, count: u8) -> Vec { - let mut sizes = vec![]; - for _ in 0..count { - sizes.push((encoded & 3) + 1); - encoded >>= 2; +fn decode_size_lengths(mut encoded_bytes_to_store: u8, number_of_encoded_lengths: u8) -> Vec { + assert!(number_of_encoded_lengths <= 4); + + let mut bytes_to_store_sizes = vec![]; + + for _ in 0..number_of_encoded_lengths { + // The number of bytes required to store the size of every + // element is represented with 2 bits. Hence we use + // mask `11`, equivalent to 3 in the decimal system. + let mask: u8 = 3; + // The number of bytes required to store size can take value + // in {1, 2, 4}, but to compress it to 2-bit, + // when encoding we decreased the value, hence now we need + // to do inverse. + let bytes_to_store: u8 = (encoded_bytes_to_store & mask) + 1; + bytes_to_store_sizes.push(bytes_to_store); + encoded_bytes_to_store >>= 2; } - sizes.reverse(); - sizes + + // Because encoding and decoding are started on the same + // end of the byte, we need to reverse `bytes_to_store_sizes` + // to get sizes in order. + bytes_to_store_sizes.reverse(); + + bytes_to_store_sizes } +// Encodes a serialized element `T` in a tuple. +// The element is assumed to be at the beginning of `dst`. +// Returns the number of bytes written to `dst`. fn encode_tuple_element(dst: &mut [u8], bytes: &[u8], last: bool) -> usize { let mut written = 0; if !last && !T::BOUND.is_fixed_size() { @@ -247,6 +279,12 @@ fn encode_tuple_element(dst: &mut [u8], bytes: &[u8], last: bool) - written + bytes.len() } +// Decodes an element `T` from a tuple. +// +// The element is assumed to be at the beginning of `src`. +// The length of the size of the element should be provided if the element is *not* fixed in size. +// +// Returns the element `T` and the number of bytes read from `src`. fn decode_tuple_element(src: &[u8], size_len: Option, last: bool) -> (T, usize) { let mut read = 0; let size = if let Some(len) = size_len { From 58f6fd4c9ad0e528a791b9b4dc58805f237277cd Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Mon, 26 May 2025 16:18:21 +0200 Subject: [PATCH 04/16] . --- src/storable/tuples.rs | 200 ++++++++++++++++++++--------------------- 1 file changed, 100 insertions(+), 100 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index 7a54cd1f..fdae8b9c 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -120,106 +120,6 @@ fn encode_size(dst: &mut [u8], size: usize, bytes: usize) { } } -impl Storable for (A, B, C) -where - A: Storable, - B: Storable, - C: Storable, -{ - // Tuple (A, B, C) serialization: - // If A and B have fixed size: - // Otherwise: - fn to_bytes(&self) -> Cow<[u8]> { - let a_bytes = self.0.to_bytes(); - let b_bytes = self.1.to_bytes(); - let c_bytes = self.2.to_bytes(); - let a_size = a_bytes.len(); - let b_size = b_bytes.len(); - let c_size = c_bytes.len(); - - let sizes_overhead = sizes_overhead::(a_size, b_size); - let output_size = a_size + b_size + c_size + sizes_overhead; - let mut bytes = vec![0; output_size]; - let mut offset = 0; - - if sizes_overhead != 0 { - bytes[0] = encode_size_lengths(vec![a_size, b_size]); - offset += 1; - } - - offset += encode_tuple_element::(&mut bytes[offset..], a_bytes.borrow(), false); - offset += encode_tuple_element::(&mut bytes[offset..], b_bytes.borrow(), false); - offset += encode_tuple_element::(&mut bytes[offset..], c_bytes.borrow(), true); - - debug_assert_eq!(offset, output_size); - Cow::Owned(bytes) - } - - #[inline] - fn from_bytes(bytes: Cow<[u8]>) -> Self { - let mut offset = 0; - let mut size_lengths = [None, None]; - - if !(A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size()) { - let lengths = decode_size_lengths(bytes[0], 2); - offset += 1; - if !A::BOUND.is_fixed_size() { - size_lengths[0] = Some(lengths[0]); - } - if !B::BOUND.is_fixed_size() { - size_lengths[1] = Some(lengths[1]); - } - } - - let (a, read) = decode_tuple_element::(&bytes[offset..], size_lengths[0], false); - offset += read; - let (b, read) = decode_tuple_element::(&bytes[offset..], size_lengths[1], false); - offset += read; - let (c, read) = decode_tuple_element::(&bytes[offset..], None, true); - offset += read; - - debug_assert_eq!(offset, bytes.len()); - (a, b, c) - } - - const BOUND: Bound = match (A::BOUND, B::BOUND, C::BOUND) { - (Bound::Bounded { .. }, Bound::Bounded { .. }, Bound::Bounded { .. }) => { - let a_bounds = bounds::(); - let b_bounds = bounds::(); - let c_bounds = bounds::(); - let sizes_overhead = - sizes_overhead::(a_bounds.max_size as usize, b_bounds.max_size as usize) - as u32; - Bound::Bounded { - max_size: a_bounds.max_size - + b_bounds.max_size - + c_bounds.max_size - + sizes_overhead, - is_fixed_size: a_bounds.is_fixed_size - && b_bounds.is_fixed_size - && c_bounds.is_fixed_size, - } - } - _ => Bound::Unbounded, - }; -} - -const fn sizes_overhead(a_size: usize, b_size: usize) -> usize { - if A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size() { - 0 - } else { - 1 + if !A::BOUND.is_fixed_size() { - bytes_to_store_size(a_size) - } else { - 0 - } + if !B::BOUND.is_fixed_size() { - bytes_to_store_size(b_size) - } else { - 0 - } - } -} - fn encode_size_lengths(sizes: Vec) -> u8 { assert!(sizes.len() <= 4); @@ -306,3 +206,103 @@ fn decode_tuple_element(src: &[u8], size_len: Option, last: boo read + size, ) } + +const fn sizes_overhead(a_size: usize, b_size: usize) -> usize { + if A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size() { + 0 + } else { + 1 + if !A::BOUND.is_fixed_size() { + bytes_to_store_size(a_size) + } else { + 0 + } + if !B::BOUND.is_fixed_size() { + bytes_to_store_size(b_size) + } else { + 0 + } + } +} + +impl Storable for (A, B, C) +where + A: Storable, + B: Storable, + C: Storable, +{ + // Tuple (A, B, C) serialization: + // If A and B have fixed size: + // Otherwise: + fn to_bytes(&self) -> Cow<[u8]> { + let a_bytes = self.0.to_bytes(); + let b_bytes = self.1.to_bytes(); + let c_bytes = self.2.to_bytes(); + let a_size = a_bytes.len(); + let b_size = b_bytes.len(); + let c_size = c_bytes.len(); + + let sizes_overhead = sizes_overhead::(a_size, b_size); + let output_size = a_size + b_size + c_size + sizes_overhead; + let mut bytes = vec![0; output_size]; + let mut offset = 0; + + if sizes_overhead != 0 { + bytes[0] = encode_size_lengths(vec![a_size, b_size]); + offset += 1; + } + + offset += encode_tuple_element::(&mut bytes[offset..], a_bytes.borrow(), false); + offset += encode_tuple_element::(&mut bytes[offset..], b_bytes.borrow(), false); + offset += encode_tuple_element::(&mut bytes[offset..], c_bytes.borrow(), true); + + debug_assert_eq!(offset, output_size); + Cow::Owned(bytes) + } + + #[inline] + fn from_bytes(bytes: Cow<[u8]>) -> Self { + let mut offset = 0; + let mut size_lengths = [None, None]; + + if !(A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size()) { + let lengths = decode_size_lengths(bytes[0], 2); + offset += 1; + if !A::BOUND.is_fixed_size() { + size_lengths[0] = Some(lengths[0]); + } + if !B::BOUND.is_fixed_size() { + size_lengths[1] = Some(lengths[1]); + } + } + + let (a, read) = decode_tuple_element::(&bytes[offset..], size_lengths[0], false); + offset += read; + let (b, read) = decode_tuple_element::(&bytes[offset..], size_lengths[1], false); + offset += read; + let (c, read) = decode_tuple_element::(&bytes[offset..], None, true); + offset += read; + + debug_assert_eq!(offset, bytes.len()); + (a, b, c) + } + + const BOUND: Bound = match (A::BOUND, B::BOUND, C::BOUND) { + (Bound::Bounded { .. }, Bound::Bounded { .. }, Bound::Bounded { .. }) => { + let a_bounds = bounds::(); + let b_bounds = bounds::(); + let c_bounds = bounds::(); + let sizes_overhead = + sizes_overhead::(a_bounds.max_size as usize, b_bounds.max_size as usize) + as u32; + Bound::Bounded { + max_size: a_bounds.max_size + + b_bounds.max_size + + c_bounds.max_size + + sizes_overhead, + is_fixed_size: a_bounds.is_fixed_size + && b_bounds.is_fixed_size + && c_bounds.is_fixed_size, + } + } + _ => Bound::Unbounded, + }; +} From 4d883c920578814d0c26b576c92bb2bc90a0f400 Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Mon, 26 May 2025 16:19:57 +0200 Subject: [PATCH 05/16] . --- src/storable/tuples.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index fdae8b9c..811300df 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -198,6 +198,7 @@ fn decode_tuple_element(src: &[u8], size_len: Option, last: boo { max_size as usize } else { + // This case should only happen for the last element. assert!(last); src.len() }; @@ -207,20 +208,24 @@ fn decode_tuple_element(src: &[u8], size_len: Option, last: boo ) } +// Returns number of bytes required to store encoding of sizes for elements of type A and B. const fn sizes_overhead(a_size: usize, b_size: usize) -> usize { - if A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size() { - 0 - } else { - 1 + if !A::BOUND.is_fixed_size() { - bytes_to_store_size(a_size) - } else { - 0 - } + if !B::BOUND.is_fixed_size() { - bytes_to_store_size(b_size) - } else { - 0 + let mut sizes_overhead = 0; + + if !(A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size()) { + // 1B for size lengths encoding + sizes_overhead += 1; + + if !A::BOUND.is_fixed_size() { + sizes_overhead += bytes_to_store_size(a_size); + } + + if !B::BOUND.is_fixed_size() { + sizes_overhead += bytes_to_store_size(b_size); } } + + sizes_overhead } impl Storable for (A, B, C) From d4336ec77021863861c7c186d3500d44fb0f8c35 Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Mon, 26 May 2025 16:21:11 +0200 Subject: [PATCH 06/16] . --- src/storable/tuples.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index 811300df..72ac5b61 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -235,8 +235,10 @@ where C: Storable, { // Tuple (A, B, C) serialization: - // If A and B have fixed size: - // Otherwise: + // If A and B have fixed size: + // + // Otherwise: + // fn to_bytes(&self) -> Cow<[u8]> { let a_bytes = self.0.to_bytes(); let b_bytes = self.1.to_bytes(); From cd0fba985fc2ca20095f45b660d4710c24861aa7 Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Mon, 26 May 2025 16:23:17 +0200 Subject: [PATCH 07/16] . --- src/storable/tuples.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index 72ac5b61..16f0522a 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -235,10 +235,10 @@ where C: Storable, { // Tuple (A, B, C) serialization: - // If A and B have fixed size: - // - // Otherwise: - // + // If A and B have fixed size: + // + // Otherwise: + // fn to_bytes(&self) -> Cow<[u8]> { let a_bytes = self.0.to_bytes(); let b_bytes = self.1.to_bytes(); From 1ed5683e6a41a89cc38f53b328236f896f88b6a9 Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Mon, 26 May 2025 16:27:32 +0200 Subject: [PATCH 08/16] add debug_assert --- src/storable/tuples.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index 16f0522a..87eaf075 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -21,6 +21,9 @@ where let b_size_len = bytes_to_store_size_bounded(&b_bounds) as usize; let sizes_offset = a_max + b_max; + debug_assert!(a_bytes.len() <= a_max); + debug_assert!(b_bytes.len() <= b_max); + let mut bytes = vec![0; max_size as usize]; bytes[..a_bytes.len()].copy_from_slice(a_bytes.borrow()); bytes[a_max..a_max + b_bytes.len()].copy_from_slice(b_bytes.borrow()); From a122fbac51eecf5d1320ff926c588d16b8c47aff Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Mon, 26 May 2025 16:33:04 +0200 Subject: [PATCH 09/16] &[usize] --- src/storable/tuples.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index 87eaf075..42395fc8 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -123,7 +123,7 @@ fn encode_size(dst: &mut [u8], size: usize, bytes: usize) { } } -fn encode_size_lengths(sizes: Vec) -> u8 { +fn encode_size_lengths(sizes: &[usize]) -> u8 { assert!(sizes.len() <= 4); let mut size_lengths_byte: u8 = 0; @@ -256,7 +256,7 @@ where let mut offset = 0; if sizes_overhead != 0 { - bytes[0] = encode_size_lengths(vec![a_size, b_size]); + bytes[0] = encode_size_lengths(&[a_size, b_size]); offset += 1; } From dad3fe0374789a78b132d5185fe0c38c4b7f0edf Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Mon, 26 May 2025 16:33:57 +0200 Subject: [PATCH 10/16] as_ref --- src/storable/tuples.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index 42395fc8..e54326fc 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -25,8 +25,8 @@ where debug_assert!(b_bytes.len() <= b_max); let mut bytes = vec![0; max_size as usize]; - bytes[..a_bytes.len()].copy_from_slice(a_bytes.borrow()); - bytes[a_max..a_max + b_bytes.len()].copy_from_slice(b_bytes.borrow()); + bytes[..a_bytes.len()].copy_from_slice(a_bytes.as_ref()); + bytes[a_max..a_max + b_bytes.len()].copy_from_slice(b_bytes.as_ref()); encode_size_of_bound( &mut bytes[sizes_offset..sizes_offset + a_size_len], @@ -260,9 +260,9 @@ where offset += 1; } - offset += encode_tuple_element::(&mut bytes[offset..], a_bytes.borrow(), false); - offset += encode_tuple_element::(&mut bytes[offset..], b_bytes.borrow(), false); - offset += encode_tuple_element::(&mut bytes[offset..], c_bytes.borrow(), true); + offset += encode_tuple_element::(&mut bytes[offset..], a_bytes.as_ref(), false); + offset += encode_tuple_element::(&mut bytes[offset..], b_bytes.as_ref(), false); + offset += encode_tuple_element::(&mut bytes[offset..], c_bytes.as_ref(), true); debug_assert_eq!(offset, output_size); Cow::Owned(bytes) From eebfcdf33de122fdcda7b7e07f69501c89a2aba3 Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Tue, 27 May 2025 21:38:44 +0200 Subject: [PATCH 11/16] . --- src/storable/tuples.rs | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index e54326fc..12c2a34c 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -15,18 +15,18 @@ where let b_bytes = self.1.to_bytes(); let a_bounds = bounds::(); let b_bounds = bounds::(); - let a_max = a_bounds.max_size as usize; - let b_max = b_bounds.max_size as usize; + let a_max_size = a_bounds.max_size as usize; + let b_max_size = b_bounds.max_size as usize; let a_size_len = bytes_to_store_size_bounded(&a_bounds) as usize; let b_size_len = bytes_to_store_size_bounded(&b_bounds) as usize; - let sizes_offset = a_max + b_max; + let sizes_offset = a_max_size + b_max_size; - debug_assert!(a_bytes.len() <= a_max); - debug_assert!(b_bytes.len() <= b_max); + debug_assert!(a_bytes.len() <= a_max_size); + debug_assert!(b_bytes.len() <= b_max_size); let mut bytes = vec![0; max_size as usize]; bytes[..a_bytes.len()].copy_from_slice(a_bytes.as_ref()); - bytes[a_max..a_max + b_bytes.len()].copy_from_slice(b_bytes.as_ref()); + bytes[a_max_size..a_max_size + b_bytes.len()].copy_from_slice(b_bytes.as_ref()); encode_size_of_bound( &mut bytes[sizes_offset..sizes_offset + a_size_len], @@ -52,9 +52,9 @@ where assert_eq!(bytes.len(), max_size as usize); let a_bounds = bounds::(); let b_bounds = bounds::(); - let a_max = a_bounds.max_size as usize; - let b_max = b_bounds.max_size as usize; - let sizes_offset = a_max + b_max; + let a_max_size = a_bounds.max_size as usize; + let b_max_size = b_bounds.max_size as usize; + let sizes_offset = a_max_size + b_max_size; let a_size_len = bytes_to_store_size_bounded(&a_bounds) as usize; let b_size_len = bytes_to_store_size_bounded(&b_bounds) as usize; @@ -68,7 +68,7 @@ where ); let a = A::from_bytes(Cow::Borrowed(&bytes[..a_len])); - let b = B::from_bytes(Cow::Borrowed(&bytes[a_max..a_max + b_len])); + let b = B::from_bytes(Cow::Borrowed(&bytes[a_max_size..a_max_size + b_len])); (a, b) } _ => todo!("Deserializing tuples with unbounded types is not yet supported."), @@ -115,11 +115,11 @@ fn decode_size(src: &[u8], size_len: usize) -> usize { } /// Encodes `size` at the beginning of `dst` of length `bytes_to_store_size` bytes. -fn encode_size(dst: &mut [u8], size: usize, bytes: usize) { +fn encode_size(dst: &mut [u8], size_len: usize, bytes: usize) { match bytes { - 1 => dst[0] = size as u8, - 2 => dst[..2].copy_from_slice(&(size as u16).to_be_bytes()), - _ => dst[..4].copy_from_slice(&(size as u32).to_be_bytes()), + 1 => dst[0] = size_len as u8, + 2 => dst[..2].copy_from_slice(&(size_len as u16).to_be_bytes()), + _ => dst[..4].copy_from_slice(&(size_len as u32).to_be_bytes()), } } @@ -172,14 +172,14 @@ fn decode_size_lengths(mut encoded_bytes_to_store: u8, number_of_encoded_lengths // The element is assumed to be at the beginning of `dst`. // Returns the number of bytes written to `dst`. fn encode_tuple_element(dst: &mut [u8], bytes: &[u8], last: bool) -> usize { - let mut written = 0; + let mut offset = 0; if !last && !T::BOUND.is_fixed_size() { let size_len = bytes_to_store_size(bytes.len()); - encode_size(&mut dst[written..], bytes.len(), size_len); - written += size_len; + encode_size(&mut dst[offset..], bytes.len(), size_len); + offset += size_len; } - dst[written..written + bytes.len()].copy_from_slice(bytes); - written + bytes.len() + dst[offset..offset + bytes.len()].copy_from_slice(bytes); + offset + bytes.len() } // Decodes an element `T` from a tuple. From 1dd467684e4434baf129547574da40b974144370 Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Tue, 27 May 2025 21:43:55 +0200 Subject: [PATCH 12/16] . --- src/storable/tuples.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index 12c2a34c..fe3f65f8 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -256,7 +256,7 @@ where let mut offset = 0; if sizes_overhead != 0 { - bytes[0] = encode_size_lengths(&[a_size, b_size]); + bytes[offset] = encode_size_lengths(&[a_size, b_size]); offset += 1; } From b50aa2c0c6b797301d5228708384e5336ed03548 Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Tue, 27 May 2025 21:44:55 +0200 Subject: [PATCH 13/16] . --- src/storable/tuples.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index fe3f65f8..e4d8fc8b 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -1,7 +1,7 @@ use crate::storable::{ bounds, bytes_to_store_size, bytes_to_store_size_bounded, Bound, Bounds, Storable, }; -use std::borrow::{Borrow, Cow}; +use std::borrow::Cow; impl Storable for (A, B) where From b2cb960416ba3e39e809809d2c1bd92c15d307f1 Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Tue, 27 May 2025 21:59:28 +0200 Subject: [PATCH 14/16] rev arr vs vec --- benchmarks/compare/canbench_results.yml | 123 +----------------------- src/storable/tuples.rs | 4 +- 2 files changed, 4 insertions(+), 123 deletions(-) diff --git a/benchmarks/compare/canbench_results.yml b/benchmarks/compare/canbench_results.yml index add6fc9e..5d9f10ae 100644 --- a/benchmarks/compare/canbench_results.yml +++ b/benchmarks/compare/canbench_results.yml @@ -1,128 +1,9 @@ benches: - read_chunks_btreemap_1: - total: - calls: 1 - instructions: 1219162597 - heap_increase: 3233 - stable_memory_increase: 1665 - scopes: {} - read_chunks_btreemap_1k: - total: - calls: 1 - instructions: 5414908676 - heap_increase: 1604 - stable_memory_increase: 1665 - scopes: {} - read_chunks_btreemap_1m: - total: - calls: 1 - instructions: 133588820086 - heap_increase: 1892 - stable_memory_increase: 3201 - scopes: {} - read_chunks_stable_1: - total: - calls: 1 - instructions: 812767514 - heap_increase: 1601 - stable_memory_increase: 1665 - scopes: {} - read_chunks_stable_1k: - total: - calls: 1 - instructions: 525926853 - heap_increase: 1600 - stable_memory_increase: 1665 - scopes: {} - read_chunks_stable_1m: - total: - calls: 1 - instructions: 1307625987 - heap_increase: 1892 - stable_memory_increase: 1665 - scopes: {} - read_chunks_vec_1: - total: - calls: 1 - instructions: 1363286727 - heap_increase: 3202 - stable_memory_increase: 1665 - scopes: {} - read_chunks_vec_1k: - total: - calls: 1 - instructions: 1378054827 - heap_increase: 1602 - stable_memory_increase: 1665 - scopes: {} - read_chunks_vec_1m: - total: - calls: 1 - instructions: 4584728190 - heap_increase: 1892 - stable_memory_increase: 1665 - scopes: {} - write_chunks_btreemap_1: - total: - calls: 1 - instructions: 1069803049 - heap_increase: 3233 - stable_memory_increase: 1665 - scopes: {} - write_chunks_btreemap_1k: - total: - calls: 1 - instructions: 4914919689 - heap_increase: 1604 - stable_memory_increase: 1665 - scopes: {} - write_chunks_btreemap_1m: - total: - calls: 1 - instructions: 89822427791 - heap_increase: 1892 - stable_memory_increase: 3201 - scopes: {} - write_chunks_stable_1: - total: - calls: 1 - instructions: 418914609 - heap_increase: 1601 - stable_memory_increase: 1665 - scopes: {} - write_chunks_stable_1k: - total: - calls: 1 - instructions: 420017351 - heap_increase: 1600 - stable_memory_increase: 1665 - scopes: {} - write_chunks_stable_1m: - total: - calls: 1 - instructions: 1076987632 - heap_increase: 1892 - stable_memory_increase: 1665 - scopes: {} - write_chunks_vec_1: - total: - calls: 1 - instructions: 1257791168 - heap_increase: 3202 - stable_memory_increase: 1665 - scopes: {} - write_chunks_vec_1k: - total: - calls: 1 - instructions: 1271592530 - heap_increase: 1602 - stable_memory_increase: 1665 - scopes: {} write_chunks_vec_1m: total: calls: 1 - instructions: 3575186447 - heap_increase: 1892 + instructions: 3739427314 + heap_increase: 3784 stable_memory_increase: 1665 scopes: {} version: 0.1.15 diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index e4d8fc8b..167532d6 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -123,7 +123,7 @@ fn encode_size(dst: &mut [u8], size_len: usize, bytes: usize) { } } -fn encode_size_lengths(sizes: &[usize]) -> u8 { +fn encode_size_lengths(sizes: Vec) -> u8 { assert!(sizes.len() <= 4); let mut size_lengths_byte: u8 = 0; @@ -256,7 +256,7 @@ where let mut offset = 0; if sizes_overhead != 0 { - bytes[offset] = encode_size_lengths(&[a_size, b_size]); + bytes[offset] = encode_size_lengths(vec![a_size, b_size]); offset += 1; } From 813c2725c3fe933d4307075c43dcf9c540d79ebd Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Tue, 27 May 2025 22:01:56 +0200 Subject: [PATCH 15/16] --persist --- benchmarks/compare/canbench_results.yml | 119 ++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/benchmarks/compare/canbench_results.yml b/benchmarks/compare/canbench_results.yml index 5d9f10ae..bdf415a3 100644 --- a/benchmarks/compare/canbench_results.yml +++ b/benchmarks/compare/canbench_results.yml @@ -1,4 +1,123 @@ benches: + read_chunks_btreemap_1: + total: + calls: 1 + instructions: 1219162653 + heap_increase: 3233 + stable_memory_increase: 1665 + scopes: {} + read_chunks_btreemap_1k: + total: + calls: 1 + instructions: 5414908732 + heap_increase: 1604 + stable_memory_increase: 1665 + scopes: {} + read_chunks_btreemap_1m: + total: + calls: 1 + instructions: 133588820142 + heap_increase: 1892 + stable_memory_increase: 3201 + scopes: {} + read_chunks_stable_1: + total: + calls: 1 + instructions: 812767514 + heap_increase: 1601 + stable_memory_increase: 1665 + scopes: {} + read_chunks_stable_1k: + total: + calls: 1 + instructions: 525926853 + heap_increase: 1600 + stable_memory_increase: 1665 + scopes: {} + read_chunks_stable_1m: + total: + calls: 1 + instructions: 1307625987 + heap_increase: 1892 + stable_memory_increase: 1665 + scopes: {} + read_chunks_vec_1: + total: + calls: 1 + instructions: 1363286555 + heap_increase: 3202 + stable_memory_increase: 1665 + scopes: {} + read_chunks_vec_1k: + total: + calls: 1 + instructions: 1378501974 + heap_increase: 3200 + stable_memory_increase: 1665 + scopes: {} + read_chunks_vec_1m: + total: + calls: 1 + instructions: 4748969057 + heap_increase: 3784 + stable_memory_increase: 1665 + scopes: {} + write_chunks_btreemap_1: + total: + calls: 1 + instructions: 1069803070 + heap_increase: 3233 + stable_memory_increase: 1665 + scopes: {} + write_chunks_btreemap_1k: + total: + calls: 1 + instructions: 4914919710 + heap_increase: 1604 + stable_memory_increase: 1665 + scopes: {} + write_chunks_btreemap_1m: + total: + calls: 1 + instructions: 89822427812 + heap_increase: 1892 + stable_memory_increase: 3201 + scopes: {} + write_chunks_stable_1: + total: + calls: 1 + instructions: 418914609 + heap_increase: 1601 + stable_memory_increase: 1665 + scopes: {} + write_chunks_stable_1k: + total: + calls: 1 + instructions: 420017351 + heap_increase: 1600 + stable_memory_increase: 1665 + scopes: {} + write_chunks_stable_1m: + total: + calls: 1 + instructions: 1076987632 + heap_increase: 1892 + stable_memory_increase: 1665 + scopes: {} + write_chunks_vec_1: + total: + calls: 1 + instructions: 1257790996 + heap_increase: 3202 + stable_memory_increase: 1665 + scopes: {} + write_chunks_vec_1k: + total: + calls: 1 + instructions: 1272039677 + heap_increase: 3200 + stable_memory_increase: 1665 + scopes: {} write_chunks_vec_1m: total: calls: 1 From 1cb9f3d8dba30947e04a65b7c601f653448e6db5 Mon Sep 17 00:00:00 2001 From: Maksym Arutyunyan Date: Wed, 28 May 2025 07:28:06 +0200 Subject: [PATCH 16/16] &[usize] --- src/storable/tuples.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storable/tuples.rs b/src/storable/tuples.rs index 167532d6..e4d8fc8b 100644 --- a/src/storable/tuples.rs +++ b/src/storable/tuples.rs @@ -123,7 +123,7 @@ fn encode_size(dst: &mut [u8], size_len: usize, bytes: usize) { } } -fn encode_size_lengths(sizes: Vec) -> u8 { +fn encode_size_lengths(sizes: &[usize]) -> u8 { assert!(sizes.len() <= 4); let mut size_lengths_byte: u8 = 0; @@ -256,7 +256,7 @@ where let mut offset = 0; if sizes_overhead != 0 { - bytes[offset] = encode_size_lengths(vec![a_size, b_size]); + bytes[offset] = encode_size_lengths(&[a_size, b_size]); offset += 1; }