Skip to content

Commit

Permalink
feat: implement {ItemAccess, ColumnAccess}::try_get
Browse files Browse the repository at this point in the history
  • Loading branch information
uint committed Sep 11, 2024
1 parent 4714b91 commit 0658a25
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 1 deletion.
30 changes: 30 additions & 0 deletions packages/storey/src/containers/column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::encoding::{DecodableWith, EncodableWith};
use crate::storage::{IterableStorage, StorageBranch};
use crate::storage::{Storage, StorageMut};

use super::common::TryGetError;
use super::{BoundFor, BoundedIterableAccessor, IterableAccessor, NonTerminal, Storable};

const META_LAST_IX: &[u8] = &[0];
Expand Down Expand Up @@ -158,6 +159,8 @@ where
{
/// Get the value associated with the given key.
///
/// Returns `Ok(None)` if the entry doesn't exist (has not been set yet).
///
/// # Example
/// ```
/// # use mocks::encoding::TestEncoding;
Expand All @@ -179,6 +182,33 @@ where
.transpose()
}

/// Get the value associated with the given key.
///
/// Returns [`TryGetError::Empty`] if the entry doesn't exist (has not been
/// set yet).
///
/// This is similar to [`get`](Self::get), but removes one level of nesting
/// so that you can get to your data faster, without having to unpack the
/// [`Option`].
///
/// # Example
/// ```
/// # use mocks::encoding::TestEncoding;
/// # use mocks::backend::TestStorage;
/// use storey::containers::Column;
///
/// let mut storage = TestStorage::new();
/// let column = Column::<u64, TestEncoding>::new(0);
/// let mut access = column.access(&mut storage);
///
/// access.push(&1337).unwrap();
/// assert_eq!(access.try_get(0).unwrap(), 1337);
/// assert!(access.try_get(1).is_err());
/// ```
pub fn try_get(&self, key: u32) -> Result<T, TryGetError<E::DecodeError>> {
self.get(key)?.ok_or(TryGetError::Empty)
}

/// Get the length of the column. This is the number of elements actually stored,
/// taking the possibility of removed elements into account.
///
Expand Down
7 changes: 7 additions & 0 deletions packages/storey/src/containers/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[derive(Debug, PartialEq, Eq, Clone, Copy, thiserror::Error)]
pub enum TryGetError<E> {
#[error("item is empty")]
Empty,
#[error(transparent)]
DecodeError(#[from] E),
}
40 changes: 39 additions & 1 deletion packages/storey/src/containers/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::encoding::{DecodableWith, EncodableWith, Encoding};
use crate::storage::StorageBranch;
use crate::storage::{Storage, StorageMut};

use super::common::TryGetError;
use super::{Storable, Terminal};

/// A single item in the storage.
Expand Down Expand Up @@ -117,7 +118,7 @@ where
{
/// Get the value of the item.
///
/// Returns `None` if the item doesn't exist (has not been set yet).
/// Returns `Ok(None)` if the item doesn't exist (has not been set yet).
///
/// # Examples
/// ```
Expand Down Expand Up @@ -149,6 +150,43 @@ where
.map(|bytes| T::decode(&bytes))
.transpose()
}

/// Get the value of the item.
///
/// Returns [`TryGetError::Empty`] if the item doesn't exist (has not been
/// set yet).
///
/// This is similar to [`get`](Self::get), but removes one level of nesting
/// so that you can get to your data faster, without having to unpack the
/// [`Option`].
///
/// # Examples
/// ```
/// # use mocks::encoding::TestEncoding;
/// # use mocks::backend::TestStorage;
/// use storey::containers::Item;
///
/// let mut storage = TestStorage::new();
/// let item = Item::<u64, TestEncoding>::new(0);
///
/// item.access(&mut storage).set(&42).unwrap();
/// assert_eq!(item.access(&storage).try_get().unwrap(), 42);
/// ```
///
/// ```
/// # use mocks::encoding::TestEncoding;
/// # use mocks::backend::TestStorage;
/// use storey::containers::Item;
///
/// let storage = TestStorage::new();
/// let item = Item::<u64, TestEncoding>::new(0);
/// let access = item.access(&storage);
///
/// assert!(access.try_get().is_err());
/// ```
pub fn try_get(&self) -> Result<T, TryGetError<E::DecodeError>> {
self.get()?.ok_or_else(|| TryGetError::Empty)
}
}

impl<E, T, S> ItemAccess<E, T, S>
Expand Down
1 change: 1 addition & 0 deletions packages/storey/src/containers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! few fundamental collections/containers themselves.
mod column;
pub mod common;
mod item;
pub mod map;

Expand Down

0 comments on commit 0658a25

Please sign in to comment.