From 17b99a8aeafdae9ea78ff73cd61882216526b817 Mon Sep 17 00:00:00 2001 From: b3hr4d Date: Thu, 21 Sep 2023 12:43:31 +0300 Subject: [PATCH 1/5] add missing Display impl for InitError --- src/btreemap.rs | 6 +++--- src/cell.rs | 21 +++++++++++++++++++++ src/log.rs | 25 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/btreemap.rs b/src/btreemap.rs index ec4a8e72..9c45ec13 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -36,9 +36,9 @@ use allocator::Allocator; pub use iter::Iter; use iter::{Cursor, Index}; use node::{DerivedPageSize, Entry, Node, NodeType, PageSize, Version}; -use std::borrow::Cow; use std::marker::PhantomData; use std::ops::{Bound, RangeBounds}; +use std::{borrow::Cow, fmt}; #[cfg(test)] mod proptests; @@ -1194,8 +1194,8 @@ pub enum InsertError { ValueTooLarge { given: usize, max: usize }, } -impl std::fmt::Display for InsertError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Display for InsertError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::KeyTooLarge { given, max } => { write!( diff --git a/src/cell.rs b/src/cell.rs index f569b6eb..47b09a37 100644 --- a/src/cell.rs +++ b/src/cell.rs @@ -2,6 +2,7 @@ use crate::storable::Storable; use crate::{Memory, WASM_PAGE_SIZE}; use std::borrow::{Borrow, Cow}; +use std::fmt; #[cfg(test)] mod tests; @@ -45,6 +46,26 @@ pub enum InitError { ValueTooLarge { value_size: u64 }, } +impl fmt::Display for InitError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + InitError::IncompatibleVersion { + last_supported_version, + decoded_version, + } => write!( + f, + "Incompatible version: last supported version is {}, but the memory contains version {}", + last_supported_version, decoded_version + ), + InitError::ValueTooLarge { value_size } => write!( + f, + "The initial value is too large to fit into the memory: {} bytes", + value_size + ), + } + } +} + /// Indicates a failure to set cell's value. #[derive(Debug, PartialEq, Eq)] pub enum ValueError { diff --git a/src/log.rs b/src/log.rs index 03b8f1b3..9a273f0a 100644 --- a/src/log.rs +++ b/src/log.rs @@ -57,6 +57,7 @@ use crate::{read_u64, safe_write, write_u64, Address, GrowFailed, Memory, Storable}; use std::borrow::Cow; use std::cell::RefCell; +use std::fmt; use std::marker::PhantomData; use std::thread::LocalKey; @@ -98,6 +99,30 @@ pub enum InitError { InvalidIndex, } +impl fmt::Display for InitError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + InitError::IncompatibleDataVersion { + last_supported_version, + decoded_version, + } => write!( + f, + "Incompatible data version: last supported version is {}, but decoded version is {}", + last_supported_version, decoded_version + ), + InitError::IncompatibleIndexVersion { + last_supported_version, + decoded_version, + } => write!( + f, + "Incompatible index version: last supported version is {}, but decoded version is {}", + last_supported_version, decoded_version + ), + InitError::InvalidIndex => write!(f, "Invalid index"), + } + } +} + #[derive(Debug, PartialEq, Eq)] pub enum WriteError { GrowFailed { current_size: u64, delta: u64 }, From 70a6548c997f5fd8ab847570668cd79f28b45f31 Mon Sep 17 00:00:00 2001 From: b3hr4d Date: Thu, 21 Sep 2023 15:02:33 +0300 Subject: [PATCH 2/5] add impl for Bound enum --- src/storable.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/storable.rs b/src/storable.rs index edbd3f12..ee729d14 100644 --- a/src/storable.rs +++ b/src/storable.rs @@ -70,6 +70,22 @@ pub enum Bound { }, } +impl Bound { + /// Returns true if the type is bounded, false otherwise. + pub const fn is_bounded(&self) -> bool { + matches!(self, Bound::Bounded { .. }) + } + + /// Returns the maximum size of the type if bounded, panics if unbounded. + pub const fn max_size(&self) -> u32 { + if let Bound::Bounded { max_size, .. } = self { + *max_size + } else { + panic!("Cannot get max size of unbounded type."); + } + } +} + /// Variable-size, but limited in capacity byte array. #[derive(Eq, Copy, Clone)] pub struct Blob { From acfdb5219446f2e9cbea46ecbafd05ee78a1ff98 Mon Sep 17 00:00:00 2001 From: b3hr4d Date: Thu, 21 Sep 2023 15:53:07 +0300 Subject: [PATCH 3/5] add helper function inot Bound --- src/storable.rs | 51 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/storable.rs b/src/storable.rs index ee729d14..e8dd7bb5 100644 --- a/src/storable.rs +++ b/src/storable.rs @@ -23,22 +23,20 @@ pub trait Storable { /// are within the element's bounds. fn to_bytes_checked(&self) -> Cow<[u8]> { let bytes = self.to_bytes(); - if let Bound::Bounded { - max_size, - is_fixed_size, - } = Self::BOUND - { - if is_fixed_size { - assert_eq!( - bytes.len(), - max_size as usize, + let bound = Self::BOUND; + + if bound.is_bounded() { + let max_size = bound.max_size(); + let is_fixed_size = bound.is_fixed_size(); + + if is_fixed_size && !bound.verify_fixed_size(bytes.len()) { + panic!( "expected a fixed-size element with length {} bytes, but found {} bytes", max_size, bytes.len() ); - } else { - assert!( - bytes.len() <= max_size as usize, + } else if !bound.is_within_bounds(bytes.len()) { + panic!( "expected an element with length <= {} bytes, but found {} bytes", max_size, bytes.len() @@ -84,6 +82,35 @@ impl Bound { panic!("Cannot get max size of unbounded type."); } } + + /// Returns true if the type is fixed in size, false otherwise. + /// Panics if unbounded. + pub const fn is_fixed_size(&self) -> bool { + if let Bound::Bounded { is_fixed_size, .. } = self { + *is_fixed_size + } else { + panic!("Cannot get fixed size of unbounded type."); + } + } + + /// Checks if the given size is within the bounds defined. + pub const fn is_within_bounds(&self, size: usize) -> bool { + match self { + Self::Unbounded => true, + Self::Bounded { max_size, .. } => size <= *max_size as usize, + } + } + + /// Checks if the given size matches the fixed size defined. + pub const fn verify_fixed_size(&self, size: usize) -> bool { + match self { + Self::Unbounded => false, + Self::Bounded { + max_size, + is_fixed_size, + } => *is_fixed_size && size == *max_size as usize, + } + } } /// Variable-size, but limited in capacity byte array. From 4980e9a157bb6c1bca44f6a31e47cbd5bf7c0873 Mon Sep 17 00:00:00 2001 From: Behrad Deylami Date: Fri, 22 Sep 2023 14:33:17 +0300 Subject: [PATCH 4/5] Updated Bound enum and reverted to_bytes_checked method --- src/storable.rs | 48 +++++++++++++----------------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/src/storable.rs b/src/storable.rs index e8dd7bb5..b0381423 100644 --- a/src/storable.rs +++ b/src/storable.rs @@ -23,20 +23,22 @@ pub trait Storable { /// are within the element's bounds. fn to_bytes_checked(&self) -> Cow<[u8]> { let bytes = self.to_bytes(); - let bound = Self::BOUND; - - if bound.is_bounded() { - let max_size = bound.max_size(); - let is_fixed_size = bound.is_fixed_size(); - - if is_fixed_size && !bound.verify_fixed_size(bytes.len()) { - panic!( + if let Bound::Bounded { + max_size, + is_fixed_size, + } = Self::BOUND + { + if is_fixed_size { + assert_eq!( + bytes.len(), + max_size as usize, "expected a fixed-size element with length {} bytes, but found {} bytes", max_size, bytes.len() ); - } else if !bound.is_within_bounds(bytes.len()) { - panic!( + } else { + assert!( + bytes.len() <= max_size as usize, "expected an element with length <= {} bytes, but found {} bytes", max_size, bytes.len() @@ -69,11 +71,6 @@ pub enum Bound { } impl Bound { - /// Returns true if the type is bounded, false otherwise. - pub const fn is_bounded(&self) -> bool { - matches!(self, Bound::Bounded { .. }) - } - /// Returns the maximum size of the type if bounded, panics if unbounded. pub const fn max_size(&self) -> u32 { if let Bound::Bounded { max_size, .. } = self { @@ -89,26 +86,7 @@ impl Bound { if let Bound::Bounded { is_fixed_size, .. } = self { *is_fixed_size } else { - panic!("Cannot get fixed size of unbounded type."); - } - } - - /// Checks if the given size is within the bounds defined. - pub const fn is_within_bounds(&self, size: usize) -> bool { - match self { - Self::Unbounded => true, - Self::Bounded { max_size, .. } => size <= *max_size as usize, - } - } - - /// Checks if the given size matches the fixed size defined. - pub const fn verify_fixed_size(&self, size: usize) -> bool { - match self { - Self::Unbounded => false, - Self::Bounded { - max_size, - is_fixed_size, - } => *is_fixed_size && size == *max_size as usize, + false } } } From a418acce03dd7a61f3a67994ed47e5f9b1566e8a Mon Sep 17 00:00:00 2001 From: b3hr4d Date: Fri, 22 Sep 2023 14:50:54 +0300 Subject: [PATCH 5/5] Update the description --- src/storable.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/storable.rs b/src/storable.rs index b0381423..228b20be 100644 --- a/src/storable.rs +++ b/src/storable.rs @@ -81,7 +81,6 @@ impl Bound { } /// Returns true if the type is fixed in size, false otherwise. - /// Panics if unbounded. pub const fn is_fixed_size(&self) -> bool { if let Bound::Bounded { is_fixed_size, .. } = self { *is_fixed_size