diff --git a/src/cell/builder.rs b/src/cell/builder.rs index f795d416..e8b2195a 100644 --- a/src/cell/builder.rs +++ b/src/cell/builder.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use crate::cell::finalizer::{CellParts, DefaultFinalizer, Finalizer}; use crate::cell::{ - Cell, CellDescriptor, CellSlice, CellType, DynCell, HashBytes, LevelMask, MAX_BIT_LEN, - MAX_REF_COUNT, + Cell, CellDescriptor, CellImpl, CellSlice, CellType, DynCell, HashBytes, LevelMask, + MAX_BIT_LEN, MAX_REF_COUNT, }; use crate::error::Error; use crate::util::{ArrayVec, Bitstring}; @@ -292,6 +292,14 @@ impl CellBuilder { Ok(res) } + /// Returns a slice which contains only builder data bits and no references. + /// + /// NOTE: intermediate cell hash is undefined. + pub fn as_data_slice(&self) -> CellSlice<'_> { + // SAFETY: we interpret cell builder data as ordinary cell + unsafe { CellSlice::new_unchecked(IntermediateDataCell::wrap(self)) } + } + /// Returns an underlying cell data. #[inline] pub fn raw_data(&self) -> &[u8; 128] { @@ -983,6 +991,74 @@ impl CellRefsBuilder { } } +#[repr(transparent)] +struct IntermediateDataCell(CellBuilder); + +impl IntermediateDataCell { + #[inline(always)] + const fn wrap(value: &CellBuilder) -> &Self { + // SAFETY: IntermediateDataCell is #[repr(transparent)] + unsafe { &*(value as *const CellBuilder as *const Self) } + } +} + +impl CellImpl for IntermediateDataCell { + fn descriptor(&self) -> CellDescriptor { + CellDescriptor { + d1: 0, + d2: CellDescriptor::compute_d2(self.0.bit_len), + } + } + + fn data(&self) -> &[u8] { + self.0.raw_data() + } + + fn bit_len(&self) -> u16 { + self.0.bit_len + } + + fn reference(&self, _: u8) -> Option<&DynCell> { + None + } + + fn reference_cloned(&self, _: u8) -> Option { + None + } + + fn virtualize(&self) -> &DynCell { + self + } + + fn hash(&self, _: u8) -> &HashBytes { + panic!("Hash for an intermediate data cell is not defined"); + } + + fn depth(&self, _: u8) -> u16 { + 0 + } + + fn take_first_child(&mut self) -> Option { + None + } + + fn replace_first_child(&mut self, parent: Cell) -> Result { + Err(parent) + } + + fn take_next_child(&mut self) -> Option { + None + } + + #[cfg(feature = "stats")] + fn stats(&self) -> CellTreeStats { + CellTreeStats { + bit_count: self.0.bit_len as u64, + cell_count: 1, + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/dict/aug.rs b/src/dict/aug.rs index 24fac562..1feb4815 100644 --- a/src/dict/aug.rs +++ b/src/dict/aug.rs @@ -209,14 +209,12 @@ where K: Store + DictKey, { /// Returns the value corresponding to the key. - /// - /// Key is serialized using the default finalizer. pub fn get<'a: 'b, 'b, Q>(&'a self, key: Q) -> Result, Error> where Q: Borrow + 'b, (A, V): Load<'a>, { - self.dict.get_ext(key, &mut Cell::default_finalizer()) + self.dict.get(key) } } @@ -335,22 +333,6 @@ impl AugDict where K: Store + DictKey, { - /// Returns the augmented value corresponding to the key. - /// - /// Key is serialized using the provided finalizer. - pub fn get_ext<'a: 'b, 'b, Q>( - &'a self, - key: Q, - finalizer: &mut dyn Finalizer, - ) -> Result, Error> - where - Q: Borrow + 'b, - A: Load<'a>, - V: Load<'a>, - { - self.dict.get_ext(key, finalizer) - } - /// Gets an iterator over the raw entries of the dictionary, sorted by key. /// The iterator element type is `Result<(CellBuilder, CellSlice)>`. /// diff --git a/src/dict/mod.rs b/src/dict/mod.rs index a141eb00..f9bdf37d 100644 --- a/src/dict/mod.rs +++ b/src/dict/mod.rs @@ -1209,12 +1209,6 @@ fn read_hml_same<'a>(label: &mut CellSlice<'a>, bits_for_len: u16) -> Result(entry: &T, finalizer: &mut dyn Finalizer) -> Result { - let mut builder = CellBuilder::new(); - ok!(entry.store_into(&mut builder, finalizer)); - builder.build_ext(finalizer) -} - #[derive(Debug, Clone, Copy, Eq, PartialEq)] enum Branch { // Branch for a key part that starts with bit 0 diff --git a/src/dict/raw.rs b/src/dict/raw.rs index 97567b77..3f119da6 100644 --- a/src/dict/raw.rs +++ b/src/dict/raw.rs @@ -496,6 +496,18 @@ impl<'a> RawOwnedIter<'a> { self.inner.signed = true; self } + + /// Returns whether the iterator direction was reversed. + #[inline] + pub fn is_reversed(&self) -> bool { + self.inner.reversed + } + + /// Returns whether the iterator treats keys as signed integers. + #[inline] + pub fn is_signed(&self) -> bool { + self.inner.signed + } } impl<'a> Iterator for RawOwnedIter<'a> { @@ -576,6 +588,18 @@ impl<'a> RawIter<'a> { self } + /// Returns whether the iterator direction was reversed. + #[inline] + pub fn is_reversed(&self) -> bool { + self.reversed + } + + /// Returns whether the iterator treats keys as signed integers. + #[inline] + pub fn is_signed(&self) -> bool { + self.signed + } + /// Advances the iterator and returns the next value as owned cell slice parts. pub fn next_owned( &mut self, @@ -783,6 +807,18 @@ impl<'a> RawKeys<'a> { self.inner.signed = true; self } + + /// Returns whether the iterator direction was reversed. + #[inline] + pub fn is_reversed(&self) -> bool { + self.inner.reversed + } + + /// Returns whether the iterator treats keys as signed integers. + #[inline] + pub fn is_signed(&self) -> bool { + self.inner.signed + } } impl<'a> Iterator for RawKeys<'a> { @@ -839,6 +875,18 @@ impl<'a> RawOwnedValues<'a> { self.inner.signed = true; self } + + /// Returns whether the iterator direction was reversed. + #[inline] + pub fn is_reversed(&self) -> bool { + self.inner.reversed + } + + /// Returns whether the iterator treats keys as signed integers. + #[inline] + pub fn is_signed(&self) -> bool { + self.inner.signed + } } impl<'a> Iterator for RawOwnedValues<'a> { @@ -934,6 +982,18 @@ impl<'a> RawValues<'a> { self } + /// Returns whether the iterator direction was reversed. + #[inline] + pub fn is_reversed(&self) -> bool { + self.reversed + } + + /// Returns whether the iterator treats keys as signed integers. + #[inline] + pub fn is_signed(&self) -> bool { + self.signed + } + #[inline] pub(crate) fn finish(&mut self, err: Error) -> Error { self.status = IterStatus::Broken; diff --git a/src/dict/typed.rs b/src/dict/typed.rs index ae4216ae..11dff644 100644 --- a/src/dict/typed.rs +++ b/src/dict/typed.rs @@ -7,8 +7,8 @@ use crate::error::Error; use crate::util::*; use super::{ - dict_find_bound, dict_find_owned, dict_get, dict_insert, dict_load_from_root, serialize_entry, - DictBound, DictKey, SetMode, + dict_find_bound, dict_find_owned, dict_get, dict_insert, dict_load_from_root, DictBound, + DictKey, SetMode, }; use super::{dict_remove_bound_owned, raw::*}; @@ -139,8 +139,9 @@ where where K: Store + DictKey, { - let key = ok!(serialize_entry(key, &mut Cell::default_finalizer())); - Ok(ok!(dict_get(root, K::BITS, ok!(key.as_ref().as_slice()))).is_some()) + let mut builder = CellBuilder::new(); + ok!(key.store_into(&mut builder, &mut Cell::default_finalizer())); + Ok(ok!(dict_get(root, K::BITS, builder.as_data_slice())).is_some()) } contains_key_impl(&self.root, key.borrow()) } @@ -151,30 +152,60 @@ where K: Store + DictKey, { /// Returns the value corresponding to the key. - /// - /// Key is serialized using the default finalizer. pub fn get<'a: 'b, 'b, Q>(&'a self, key: Q) -> Result, Error> where Q: Borrow + 'b, V: Load<'a>, { - self.get_ext(key, &mut Cell::default_finalizer()) + pub fn get_impl<'a: 'b, 'b, K, V>( + root: &'a Option, + key: &'b K, + ) -> Result, Error> + where + K: Store + DictKey, + V: Load<'a>, + { + let Some(mut value) = ({ + let mut builder = CellBuilder::new(); + ok!(key.store_into(&mut builder, &mut Cell::default_finalizer())); + ok!(dict_get(root, K::BITS, builder.as_data_slice())) + }) else { + return Ok(None); + }; + + match V::load_from(&mut value) { + Ok(value) => Ok(Some(value)), + Err(e) => Err(e), + } + } + + get_impl(&self.root, key.borrow()) } /// Returns the raw value corresponding to the key. - /// - /// Key is serialized using the default finalizer. pub fn get_raw<'a: 'b, 'b, Q>(&'a self, key: Q) -> Result>, Error> where Q: Borrow + 'b, { - self.get_raw_ext(key, &mut Cell::default_finalizer()) + pub fn get_raw_impl<'a: 'b, 'b, K>( + root: &'a Option, + key: &'b K, + ) -> Result>, Error> + where + K: Store + DictKey, + { + let mut builder = CellBuilder::new(); + ok!(key.store_into(&mut builder, &mut Cell::default_finalizer())); + dict_get(root, K::BITS, builder.as_data_slice()) + } + + get_raw_impl(&self.root, key.borrow()) } /// Removes the value associated with key in dictionary. /// Returns an optional removed value. /// - /// Key is serialized using the default finalizer. + /// The dict is rebuilt using the default finalizer. pub fn remove(&mut self, key: Q) -> Result, Error> where Q: Borrow, @@ -192,7 +223,7 @@ where /// Removes the value associated with key in dictionary. /// Returns an optional removed value as cell slice parts. /// - /// Key is serialized using the default finalizer. + /// The dict is rebuilt using the default finalizer. pub fn remove_raw(&mut self, key: Q) -> Result, Error> where Q: Borrow, @@ -324,126 +355,46 @@ where /// Computes the minimal key in dictionary that is lexicographically greater than `key`, /// and returns it along with associated value as cell slice parts. - /// - /// Use [`get_next_ext`] if you need to use a custom finalizer. - /// - /// [`get_next_ext`]: Dict::get_next_ext #[inline] pub fn get_next(&self, key: Q, signed: bool) -> Result, Error> where Q: Borrow, for<'a> V: Load<'a>, { - self.get_next_ext(key, signed, &mut Cell::default_finalizer()) + self.find_ext(key, DictBound::Max, false, signed) } /// Computes the maximal key in dictionary that is lexicographically smaller than `key`, /// and returns it along with associated value as cell slice parts. - /// - /// Use [`get_prev_ext`] if you need to use a custom finalizer. - /// - /// [`get_prev_ext`]: Dict::get_prev_ext #[inline] pub fn get_prev(&self, key: Q, signed: bool) -> Result, Error> where Q: Borrow, for<'a> V: Load<'a>, { - self.get_prev_ext(key, signed, &mut Cell::default_finalizer()) + self.find_ext(key, DictBound::Min, false, signed) } /// Computes the minimal key in dictionary that is lexicographically greater than `key`, /// and returns it along with associated value as cell slice parts. - /// - /// Use [`get_or_next_ext`] if you need to use a custom finalizer. - /// - /// [`get_or_next_ext`]: Dict::get_or_next_ext #[inline] pub fn get_or_next(&self, key: Q, signed: bool) -> Result, Error> where Q: Borrow, for<'a> V: Load<'a>, { - self.get_or_next_ext(key, signed, &mut Cell::default_finalizer()) + self.find_ext(key, DictBound::Max, true, signed) } /// Computes the maximal key in dictionary that is lexicographically smaller than `key`, /// and returns it along with associated value as cell slice parts. - /// - /// Use [`get_or_prev_ext`] if you need to use a custom finalizer. - /// - /// [`get_or_prev_ext`]: Dict::get_or_prev_ext #[inline] pub fn get_or_prev(&self, key: Q, signed: bool) -> Result, Error> where Q: Borrow, for<'a> V: Load<'a>, { - self.get_or_prev_ext(key, signed, &mut Cell::default_finalizer()) - } - - /// Computes the minimal key in dictionary that is lexicographically greater than `key`, - /// and returns it along with associated value as cell slice parts. - #[inline] - pub fn get_next_ext( - &self, - key: Q, - signed: bool, - finalizer: &mut dyn Finalizer, - ) -> Result, Error> - where - Q: Borrow, - for<'a> V: Load<'a>, - { - self.find_ext(key, DictBound::Max, false, signed, finalizer) - } - - /// Computes the maximal key in dictionary that is lexicographically smaller than `key`, - /// and returns it along with associated value as cell slice parts. - #[inline] - pub fn get_prev_ext( - &self, - key: Q, - signed: bool, - finalizer: &mut dyn Finalizer, - ) -> Result, Error> - where - Q: Borrow, - for<'a> V: Load<'a>, - { - self.find_ext(key, DictBound::Min, false, signed, finalizer) - } - - /// Computes the minimal key in dictionary that is lexicographically greater than `key`, - /// and returns it along with associated value as cell slice parts. - #[inline] - pub fn get_or_next_ext( - &self, - key: Q, - signed: bool, - finalizer: &mut dyn Finalizer, - ) -> Result, Error> - where - Q: Borrow, - for<'a> V: Load<'a>, - { - self.find_ext(key, DictBound::Max, true, signed, finalizer) - } - - /// Computes the maximal key in dictionary that is lexicographically smaller than `key`, - /// and returns it along with associated value as cell slice parts. - #[inline] - pub fn get_or_prev_ext( - &self, - key: Q, - signed: bool, - finalizer: &mut dyn Finalizer, - ) -> Result, Error> - where - Q: Borrow, - for<'a> V: Load<'a>, - { - self.find_ext(key, DictBound::Min, true, signed, finalizer) + self.find_ext(key, DictBound::Min, true, signed) } #[inline] @@ -453,33 +404,34 @@ where towards: DictBound, inclusive: bool, signed: bool, - finalizer: &mut dyn Finalizer, ) -> Result, Error> where Q: Borrow, for<'a> V: Load<'a>, { - fn find_ext_impl( + fn find_impl( root: &Option, key: &K, towards: DictBound, inclusive: bool, signed: bool, - finalizer: &mut dyn Finalizer, ) -> Result, Error> where K: DictKey + Store, for<'a> V: Load<'a>, { - let key = ok!(serialize_entry(key, finalizer)); - let Some((key, (cell, range))) = ok!(dict_find_owned( - root, - K::BITS, - ok!(key.as_slice()), - towards, - inclusive, - signed - )) else { + let Some((key, (cell, range))) = ({ + let mut builder = CellBuilder::new(); + ok!(key.store_into(&mut builder, &mut Cell::default_finalizer())); + ok!(dict_find_owned( + root, + K::BITS, + builder.as_data_slice(), + towards, + inclusive, + signed + )) + }) else { return Ok(None); }; let value = &mut ok!(range.apply(&cell)); @@ -489,14 +441,8 @@ where None => Err(Error::CellUnderflow), } } - find_ext_impl( - &self.root, - key.borrow(), - towards, - inclusive, - signed, - finalizer, - ) + + find_impl(&self.root, key.borrow(), towards, inclusive, signed) } } @@ -585,71 +531,10 @@ impl Dict where K: Store + DictKey, { - /// Returns the value corresponding to the key. - /// - /// Key is serialized using the provided finalizer. - pub fn get_ext<'a: 'b, 'b, Q>( - &'a self, - key: Q, - finalizer: &mut dyn Finalizer, - ) -> Result, Error> - where - Q: Borrow + 'b, - V: Load<'a>, - { - pub fn get_ext_impl<'a: 'b, 'b, K, V>( - root: &'a Option, - key: &'b K, - finalizer: &mut dyn Finalizer, - ) -> Result, Error> - where - K: Store + DictKey, - V: Load<'a>, - { - let key = ok!(serialize_entry(key, finalizer)); - let Some(mut value) = ok!(dict_get(root, K::BITS, ok!(key.as_ref().as_slice()))) else { - return Ok(None); - }; - - match V::load_from(&mut value) { - Ok(value) => Ok(Some(value)), - Err(e) => Err(e), - } - } - - get_ext_impl(&self.root, key.borrow(), finalizer) - } - - /// Returns the value corresponding to the key. - /// - /// Key is serialized using the provided finalizer. - pub fn get_raw_ext<'a: 'b, 'b, Q>( - &'a self, - key: Q, - finalizer: &mut dyn Finalizer, - ) -> Result>, Error> - where - Q: Borrow + 'b, - { - pub fn get_raw_ext_impl<'a: 'b, 'b, K>( - root: &'a Option, - key: &'b K, - finalizer: &mut dyn Finalizer, - ) -> Result>, Error> - where - K: Store + DictKey, - { - let key = ok!(serialize_entry(key, finalizer)); - dict_get(root, K::BITS, ok!(key.as_ref().as_slice())) - } - - get_raw_ext_impl(&self.root, key.borrow(), finalizer) - } - /// Removes the value associated with key in dictionary. /// Returns an optional removed value as cell slice parts. /// - /// Key is serialized using the provided finalizer. + /// Dict is rebuild using the provided finalizer. pub fn remove_raw_ext( &mut self, key: Q, @@ -666,10 +551,11 @@ where where K: Store + DictKey, { - let key = ok!(serialize_entry(key, finalizer)); + let mut builder = CellBuilder::new(); + ok!(key.store_into(&mut builder, &mut Cell::default_finalizer())); dict_remove_owned( root, - &mut ok!(key.as_ref().as_slice()), + &mut builder.as_data_slice(), K::BITS, false, finalizer, @@ -790,16 +676,19 @@ where K: Store + DictKey, V: Store, { - let key = ok!(serialize_entry(key, finalizer)); - let value = ok!(serialize_entry(value, finalizer)); - let (new_root, changed) = ok!(dict_insert( - &self.root, - &mut ok!(key.as_ref().as_slice()), - K::BITS, - &ok!(value.as_ref().as_slice()), - mode, - finalizer - )); + let (new_root, changed) = { + let mut builder = CellBuilder::new(); + ok!(key.store_into(&mut builder, &mut Cell::default_finalizer())); + let value = ok!(CellBuilder::build_from_ext(value, finalizer)); + ok!(dict_insert( + &self.root, + &mut builder.as_data_slice(), + K::BITS, + &ok!(value.as_ref().as_slice()), + mode, + finalizer + )) + }; self.root = new_root; Ok(changed) } diff --git a/src/models/shard/shard_accounts.rs b/src/models/shard/shard_accounts.rs index 1a3be9f9..b002ae19 100644 --- a/src/models/shard/shard_accounts.rs +++ b/src/models/shard/shard_accounts.rs @@ -13,32 +13,12 @@ pub struct ShardAccounts(AugDict); impl ShardAccounts { /// Returns the account state corresponding to the key. - /// - /// Key is serialized using the default finalizer. pub fn get<'a: 'b, 'b, Q>(&'a self, key: Q) -> Result, Error> where Q: Borrow + 'b, { - self.get_ext(key, &mut Cell::default_finalizer()) - } - - /// Returns the account state corresponding to the key. - /// - /// Key is serialized using the provided finalizer. - pub fn get_ext<'a: 'b, 'b, Q>( - &'a self, - key: Q, - finalizer: &mut dyn Finalizer, - ) -> Result, Error> - where - Q: Borrow + 'b, - { - fn get_ext_impl( - dict: &ShardAccounts, - key: &HashBytes, - finalizer: &mut dyn Finalizer, - ) -> Result, Error> { - match dict.get_raw_ext(key, finalizer) { + fn get_impl(dict: &ShardAccounts, key: &HashBytes) -> Result, Error> { + match dict.get_raw(key) { Ok(Some(mut value)) => { if DepthBalanceInfo::skip_value(&mut value) { match ShardAccount::load_from(&mut value) { @@ -54,33 +34,15 @@ impl ShardAccounts { } } - get_ext_impl(self, key.borrow(), finalizer) + get_impl(self, key.borrow()) } /// Returns the raw value (with augmentation) corresponding to the key. - /// - /// Key is serialized using the default finalizer. pub fn get_raw<'a: 'b, 'b, Q>(&'a self, key: Q) -> Result>, Error> where Q: Borrow + 'b, { - self.0 - .dict() - .get_raw_ext(key, &mut Cell::default_finalizer()) - } - - /// Returns the raw value (with augmentation) corresponding to the key. - /// - /// Key is serialized using the provided finalizer. - pub fn get_raw_ext<'a: 'b, 'b, Q>( - &'a self, - key: Q, - finalizer: &mut dyn Finalizer, - ) -> Result>, Error> - where - Q: Borrow, - { - self.0.dict().get_raw_ext(key, finalizer) + self.0.dict().get_raw(key) } /// Returns `true` if the dictionary contains a state for the specified account id.