Skip to main content

thruput_sdk/storage/
bytestring.rs

1use super::keypath::{Keypath, LeafKey};
2use crate::sys_exn::bytestring::*;
3use core::fmt::Debug;
4
5#[derive(Debug)]
6pub struct Bytestring {
7    key: LeafKey,
8}
9
10impl From<Keypath> for Bytestring {
11    fn from(keypath: Keypath) -> Self {
12        Self {
13            key: LeafKey::from(keypath),
14        }
15    }
16}
17
18impl Bytestring {
19    /// Returns the number of bytes stored at this key.
20    ///
21    /// **Aborts** the transaction (throws a syscall exception) if nothing is
22    /// stored here, or if a value of another type occupies the key. Use
23    /// [`exists`](Self::exists) to test for presence without aborting, or
24    /// [`try_get`](Self::try_get) to read an optional value.
25    pub fn len(&self) -> usize {
26        bytestring_get_len(&self.key) as usize
27    }
28
29    /// Returns `true` if the stored bytestring has zero length (`len() == 0`).
30    ///
31    /// Shares [`len`](Self::len)'s abort behavior exactly: this **aborts** the
32    /// transaction on a never-set key rather than reporting "empty". An empty
33    /// bytestring and a missing key are distinct states here — use
34    /// [`exists`](Self::exists) to tell them apart without aborting. (This
35    /// differs deliberately from [`Vector::is_empty`](super::vector::Vector::is_empty),
36    /// which treats a never-set vector as empty.)
37    pub fn is_empty(&self) -> bool {
38        self.len() == 0
39    }
40
41    /// Returns `true` if a bytestring is stored at this key, `false` if nothing
42    /// is.
43    ///
44    /// Unlike [`len`](Self::len)/[`is_empty`](Self::is_empty)/[`get`](Self::get)/[`get_sized`](Self::get_sized),
45    /// this does not abort on a missing key — it is the way to distinguish a
46    /// missing key from a present-but-empty bytestring. (It still throws if a
47    /// value of another type occupies the key.)
48    pub fn exists(&self) -> bool {
49        bytestring_exists(&self.key)
50    }
51
52    /// Stores `buf` at this key, overwriting any existing value (including one
53    /// of another type). If this key's keypath is exclusive, the write then
54    /// requests an exclusive lock; otherwise the key's storage flags stay as
55    /// they are.
56    pub fn set(&mut self, buf: &[u8]) {
57        if self.key.is_exclusive() {
58            bytestring_set_exclusive(&self.key, buf);
59        } else {
60            bytestring_set(&self.key, buf);
61        }
62    }
63
64    /// Reads the stored bytestring into a fixed-size array.
65    ///
66    /// **Aborts** if the key is missing, holds a value of another type, or
67    /// holds a bytestring whose length is not exactly `N`
68    /// (`LibraryExn::BytestringWrongSize`). Beware that large `N` may overflow
69    /// the execution stack.
70    pub fn get_sized<const N: usize>(&self) -> [u8; N] {
71        bytestring_get_sized(&self.key)
72    }
73
74    /// Reads the stored bytestring.
75    ///
76    /// **Aborts** if the key is missing or holds a value of another type. Use
77    /// [`try_get`](Self::try_get) to handle those cases gracefully.
78    #[cfg(feature = "alloc")]
79    pub fn get(&self) -> alloc::boxed::Box<[u8]> {
80        bytestring_get(&self.key)
81    }
82
83    /// Reads the stored bytestring, reporting failure as `Err` instead of
84    /// aborting (the `try_` law; see the [`exn`](mod@crate::exn) module
85    /// docs).
86    ///
87    /// A missing key is an `Err` for which
88    /// [`is_storage_missing`](crate::exn::LibraryExn::is_storage_missing)
89    /// is true — use
90    /// [`none_if_missing`](crate::exn::NoneIfMissing::none_if_missing) to
91    /// treat just that case as an ordinary `None`. A value of another
92    /// storage type or any other syscall failure is a `LibraryExn::Syscall`.
93    #[cfg(feature = "alloc")]
94    pub fn try_get(
95        &self,
96    ) -> Result<alloc::boxed::Box<[u8]>, crate::exn::LibraryExn> {
97        bytestring_try_get(&self.key)
98    }
99}
100
101impl super::sealed::Sealed for Bytestring {}
102impl super::node::StorageType for Bytestring {}
103
104impl super::flags::Flaggable for Bytestring {
105    fn storage_key(&self) -> &crate::types::StorageKey {
106        self.key.get()
107    }
108}
109
110impl super::deletable::Deletable for Bytestring {
111    fn delete_internal(&mut self, exclusive: bool) {
112        let exclusive = exclusive || self.key.is_exclusive();
113        crate::sys_exn::delete::delete(self.key.get(), exclusive);
114    }
115}