fuel_core_storage/
transactional.rs

1//! The primitives to work with storage in transactional mode.
2
3use crate::{
4    kv_store::{
5        BatchOperations,
6        KeyValueInspect,
7        KeyValueMutate,
8        StorageColumn,
9        Value,
10        WriteOperation,
11    },
12    structured_storage::StructuredStorage,
13    Result as StorageResult,
14};
15use core::borrow::Borrow;
16
17#[cfg(feature = "alloc")]
18use alloc::{
19    boxed::Box,
20    collections::{
21        btree_map,
22        BTreeMap,
23    },
24    vec::Vec,
25};
26
27#[cfg(feature = "test-helpers")]
28use crate::{
29    iter::{
30        BoxedIter,
31        IterDirection,
32        IterableStore,
33    },
34    kv_store::{
35        KVItem,
36        KeyItem,
37    },
38};
39
40/// Provides an atomic view of the storage at the latest height at
41/// the moment of view instantiation. All modifications to the storage
42/// after this point will not affect the view.
43pub trait AtomicView: Send + Sync {
44    /// The type of the latest storage view.
45    type LatestView;
46
47    /// Returns current the view of the storage.
48    fn latest_view(&self) -> StorageResult<Self::LatestView>;
49}
50
51/// Provides an atomic view of the storage at the given height.
52/// The view is guaranteed to be unmodifiable for the given height.
53pub trait HistoricalView: AtomicView {
54    /// The type used by the storage to track the commitments at a specific height.
55    type Height;
56    /// The type of the storage view at `Self::Height`.
57    type ViewAtHeight;
58
59    /// Returns the latest height.
60    fn latest_height(&self) -> Option<Self::Height>;
61
62    /// Returns the view of the storage at the given `height`.
63    fn view_at(&self, height: &Self::Height) -> StorageResult<Self::ViewAtHeight>;
64}
65
66/// Storage transaction on top of the storage.
67pub type StorageTransaction<S> = StructuredStorage<InMemoryTransaction<S>>;
68
69/// In memory transaction accumulates `Changes` over the storage.
70#[derive(Default, Debug, Clone)]
71pub struct InMemoryTransaction<S> {
72    pub(crate) changes: Changes,
73    pub(crate) policy: ConflictPolicy,
74    pub(crate) storage: S,
75}
76
77impl<S> StorageTransaction<S> {
78    /// Creates a new instance of the storage transaction.
79    pub fn transaction(storage: S, policy: ConflictPolicy, changes: Changes) -> Self {
80        StructuredStorage::new(InMemoryTransaction {
81            changes,
82            policy,
83            storage,
84        })
85    }
86
87    /// Creates a new instance of the structured storage with a `ConflictPolicy`.
88    pub fn with_policy(self, policy: ConflictPolicy) -> Self {
89        StructuredStorage::new(InMemoryTransaction {
90            changes: self.inner.changes,
91            policy,
92            storage: self.inner.storage,
93        })
94    }
95
96    /// Creates a new instance of the structured storage with a `Changes`.
97    pub fn with_changes(self, changes: Changes) -> Self {
98        StructuredStorage::new(InMemoryTransaction {
99            changes,
100            policy: self.inner.policy,
101            storage: self.inner.storage,
102        })
103    }
104
105    /// Getter to the changes.
106    pub fn changes(&self) -> &Changes {
107        &self.inner.changes
108    }
109
110    /// Returns the changes to the storage.
111    pub fn into_changes(self) -> Changes {
112        self.inner.changes
113    }
114
115    /// Returns the storage and changes to it.
116    pub fn into_inner(self) -> (S, Changes) {
117        let storage = self.inner.storage;
118        let changes = self.inner.changes;
119        (storage, changes)
120    }
121
122    /// Resets the changes to the storage.
123    pub fn reset_changes(&mut self) {
124        self.inner.changes = Default::default();
125    }
126}
127
128/// The policy to resolve the conflict during committing of the changes.
129#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
130pub enum ConflictPolicy {
131    /// The transaction will fail if there is a conflict.
132    Fail,
133    /// The transaction will overwrite the conflicting data.
134    #[default]
135    Overwrite,
136}
137
138/// The type is modifiable and may commit the changes into the storage.
139#[impl_tools::autoimpl(for<T: trait> &mut T, Box<T>)]
140pub trait Modifiable {
141    /// Commits the changes into the storage.
142    fn commit_changes(&mut self, changes: Changes) -> StorageResult<()>;
143}
144
145/// The wrapper around the `Vec<u8>` that supports `Borrow<[u8]>`.
146/// It allows the use of bytes slices to do lookups in the collections.
147#[derive(
148    Debug,
149    Clone,
150    PartialEq,
151    Eq,
152    Ord,
153    PartialOrd,
154    Hash,
155    serde::Serialize,
156    serde::Deserialize,
157)]
158pub struct ReferenceBytesKey(Vec<u8>);
159
160impl From<Vec<u8>> for ReferenceBytesKey {
161    fn from(value: Vec<u8>) -> Self {
162        ReferenceBytesKey(value)
163    }
164}
165
166impl From<ReferenceBytesKey> for Vec<u8> {
167    fn from(value: ReferenceBytesKey) -> Self {
168        value.0
169    }
170}
171
172impl Borrow<[u8]> for ReferenceBytesKey {
173    fn borrow(&self) -> &[u8] {
174        self.0.as_slice()
175    }
176}
177
178impl Borrow<Vec<u8>> for ReferenceBytesKey {
179    fn borrow(&self) -> &Vec<u8> {
180        &self.0
181    }
182}
183
184impl AsRef<[u8]> for ReferenceBytesKey {
185    fn as_ref(&self) -> &[u8] {
186        self.0.as_slice()
187    }
188}
189
190impl AsMut<[u8]> for ReferenceBytesKey {
191    fn as_mut(&mut self) -> &mut [u8] {
192        self.0.as_mut_slice()
193    }
194}
195
196impl core::ops::Deref for ReferenceBytesKey {
197    type Target = Vec<u8>;
198
199    fn deref(&self) -> &Self::Target {
200        &self.0
201    }
202}
203
204impl core::ops::DerefMut for ReferenceBytesKey {
205    fn deref_mut(&mut self) -> &mut Self::Target {
206        &mut self.0
207    }
208}
209
210#[cfg(not(feature = "std"))]
211/// The type describing the list of changes to the storage.
212pub type Changes = BTreeMap<u32, BTreeMap<ReferenceBytesKey, WriteOperation>>;
213
214#[cfg(feature = "std")]
215/// The type describing the list of changes to the storage.
216pub type Changes =
217    std::collections::HashMap<u32, BTreeMap<ReferenceBytesKey, WriteOperation>>;
218
219impl<Storage> From<StorageTransaction<Storage>> for Changes {
220    fn from(transaction: StorageTransaction<Storage>) -> Self {
221        transaction.into_changes()
222    }
223}
224
225/// The type describing the list of changes to the storage.
226pub enum StorageChanges {
227    /// A single batch of changes.
228    Changes(Changes),
229    /// A list of changes.
230    ChangesList(Vec<Changes>),
231}
232
233impl Default for StorageChanges {
234    fn default() -> Self {
235        StorageChanges::Changes(Default::default())
236    }
237}
238
239impl From<Changes> for StorageChanges {
240    fn from(value: Changes) -> Self {
241        StorageChanges::Changes(value)
242    }
243}
244
245/// The trait to convert the type into the storage transaction.
246pub trait IntoTransaction: Sized {
247    /// Converts the type into the storage transaction consuming it.
248    fn into_transaction(self) -> StorageTransaction<Self>;
249}
250
251impl<S> IntoTransaction for S
252where
253    S: KeyValueInspect,
254{
255    fn into_transaction(self) -> StorageTransaction<Self> {
256        StorageTransaction::transaction(
257            self,
258            ConflictPolicy::Overwrite,
259            Default::default(),
260        )
261    }
262}
263
264/// Creates a new instance of the storage read transaction.
265pub trait ReadTransaction {
266    /// Returns the read transaction without ability to commit the changes.
267    fn read_transaction(&self) -> StorageTransaction<&Self>;
268}
269
270impl<S> ReadTransaction for S
271where
272    S: KeyValueInspect,
273{
274    fn read_transaction(&self) -> StorageTransaction<&Self> {
275        StorageTransaction::transaction(
276            self,
277            ConflictPolicy::Overwrite,
278            Default::default(),
279        )
280    }
281}
282
283/// Creates a new instance of the storage write transaction.
284pub trait WriteTransaction {
285    /// Returns the write transaction that can commit the changes.
286    fn write_transaction(&mut self) -> StorageTransaction<&mut Self>;
287}
288
289impl<S> WriteTransaction for S {
290    fn write_transaction(&mut self) -> StorageTransaction<&mut Self> {
291        StorageTransaction::transaction(
292            self,
293            ConflictPolicy::Overwrite,
294            Default::default(),
295        )
296    }
297}
298
299impl<Storage> StorageTransaction<Storage>
300where
301    Storage: Modifiable,
302{
303    /// Commits the changes into the storage.
304    pub fn commit(mut self) -> StorageResult<Storage> {
305        let changes = core::mem::take(&mut self.inner.changes);
306        self.inner.storage.commit_changes(changes)?;
307        Ok(self.inner.storage)
308    }
309}
310
311impl<Storage> Modifiable for InMemoryTransaction<Storage> {
312    fn commit_changes(&mut self, changes: Changes) -> StorageResult<()> {
313        #[cfg(not(feature = "std"))]
314        use btree_map::Entry;
315        #[cfg(feature = "std")]
316        use std::collections::hash_map::Entry;
317
318        for (column, value) in changes.into_iter() {
319            let btree = match self.changes.entry(column) {
320                Entry::Vacant(vacant) => {
321                    vacant.insert(value);
322                    continue;
323                }
324                Entry::Occupied(occupied) => occupied.into_mut(),
325            };
326
327            for (k, v) in value {
328                match &self.policy {
329                    ConflictPolicy::Fail => {
330                        let entry = btree.entry(k);
331
332                        match entry {
333                            btree_map::Entry::Occupied(occupied) => {
334                                return Err(anyhow::anyhow!(
335                                    "Conflicting operation {v:?} for the {:?}",
336                                    occupied.key()
337                                )
338                                .into());
339                            }
340                            btree_map::Entry::Vacant(vacant) => {
341                                vacant.insert(v);
342                            }
343                        }
344                    }
345                    ConflictPolicy::Overwrite => {
346                        btree.insert(k, v);
347                    }
348                }
349            }
350        }
351        Ok(())
352    }
353}
354
355impl<Column, S> InMemoryTransaction<S>
356where
357    Column: StorageColumn,
358    S: KeyValueInspect<Column = Column>,
359{
360    fn get_from_changes(&self, key: &[u8], column: Column) -> Option<&WriteOperation> {
361        self.changes
362            .get(&column.id())
363            .and_then(|btree| btree.get(key))
364    }
365}
366
367impl<Column, S> KeyValueInspect for InMemoryTransaction<S>
368where
369    Column: StorageColumn,
370    S: KeyValueInspect<Column = Column>,
371{
372    type Column = Column;
373
374    fn exists(&self, key: &[u8], column: Self::Column) -> StorageResult<bool> {
375        if let Some(operation) = self.get_from_changes(key, column) {
376            match operation {
377                WriteOperation::Insert(_) => Ok(true),
378                WriteOperation::Remove => Ok(false),
379            }
380        } else {
381            self.storage.exists(key, column)
382        }
383    }
384
385    fn size_of_value(
386        &self,
387        key: &[u8],
388        column: Self::Column,
389    ) -> StorageResult<Option<usize>> {
390        if let Some(operation) = self.get_from_changes(key, column) {
391            match operation {
392                WriteOperation::Insert(value) => Ok(Some(value.len())),
393                WriteOperation::Remove => Ok(None),
394            }
395        } else {
396            self.storage.size_of_value(key, column)
397        }
398    }
399
400    fn get(&self, key: &[u8], column: Self::Column) -> StorageResult<Option<Value>> {
401        if let Some(operation) = self.get_from_changes(key, column) {
402            match operation {
403                WriteOperation::Insert(value) => Ok(Some(value.clone())),
404                WriteOperation::Remove => Ok(None),
405            }
406        } else {
407            self.storage.get(key, column)
408        }
409    }
410
411    fn read(
412        &self,
413        key: &[u8],
414        column: Self::Column,
415        offset: usize,
416        buf: &mut [u8],
417    ) -> StorageResult<bool> {
418        if let Some(operation) = self.get_from_changes(key, column) {
419            match operation {
420                WriteOperation::Insert(value) => {
421                    let bytes_len = value.as_ref().len();
422                    let start = offset;
423                    let buf_len = buf.len();
424                    let end = offset.saturating_add(buf.len());
425
426                    if end > bytes_len {
427                        return Err(anyhow::anyhow!(
428                            "Offset `{offset}` + buf_len `{buf_len}` read until {end} which is out of bounds `{bytes_len}` for key `{:?}`",
429                            key
430                        )
431                        .into());
432                    }
433
434                    let starting_from_offset = &value.as_ref()[start..end];
435                    buf[..].copy_from_slice(starting_from_offset);
436                    Ok(true)
437                }
438                WriteOperation::Remove => Ok(false),
439            }
440        } else {
441            self.storage.read(key, column, offset, buf)
442        }
443    }
444}
445
446impl<Column, S> KeyValueMutate for InMemoryTransaction<S>
447where
448    Column: StorageColumn,
449    S: KeyValueInspect<Column = Column>,
450{
451    fn put(
452        &mut self,
453        key: &[u8],
454        column: Self::Column,
455        value: Value,
456    ) -> StorageResult<()> {
457        let k = key.to_vec().into();
458        self.changes
459            .entry(column.id())
460            .or_default()
461            .insert(k, WriteOperation::Insert(value));
462        Ok(())
463    }
464
465    fn replace(
466        &mut self,
467        key: &[u8],
468        column: Self::Column,
469        value: Value,
470    ) -> StorageResult<Option<Value>> {
471        let k = key.to_vec().into();
472        let entry = self.changes.entry(column.id()).or_default().entry(k);
473
474        match entry {
475            btree_map::Entry::Occupied(mut occupied) => {
476                let old = occupied.insert(WriteOperation::Insert(value));
477
478                match old {
479                    WriteOperation::Insert(value) => Ok(Some(value)),
480                    WriteOperation::Remove => Ok(None),
481                }
482            }
483            btree_map::Entry::Vacant(vacant) => {
484                vacant.insert(WriteOperation::Insert(value));
485                self.storage.get(key, column)
486            }
487        }
488    }
489
490    fn write(
491        &mut self,
492        key: &[u8],
493        column: Self::Column,
494        buf: &[u8],
495    ) -> StorageResult<usize> {
496        let k = key.to_vec().into();
497        self.changes
498            .entry(column.id())
499            .or_default()
500            .insert(k, WriteOperation::Insert(Value::from(buf)));
501        Ok(buf.len())
502    }
503
504    fn take(&mut self, key: &[u8], column: Self::Column) -> StorageResult<Option<Value>> {
505        let k = key.to_vec().into();
506        let entry = self.changes.entry(column.id()).or_default().entry(k);
507
508        match entry {
509            btree_map::Entry::Occupied(mut occupied) => {
510                let old = occupied.insert(WriteOperation::Remove);
511
512                match old {
513                    WriteOperation::Insert(value) => Ok(Some(value)),
514                    WriteOperation::Remove => Ok(None),
515                }
516            }
517            btree_map::Entry::Vacant(vacant) => {
518                vacant.insert(WriteOperation::Remove);
519                self.storage.get(key, column)
520            }
521        }
522    }
523
524    fn delete(&mut self, key: &[u8], column: Self::Column) -> StorageResult<()> {
525        let k = key.to_vec().into();
526        self.changes
527            .entry(column.id())
528            .or_default()
529            .insert(k, WriteOperation::Remove);
530        Ok(())
531    }
532}
533
534impl<Column, S> BatchOperations for InMemoryTransaction<S>
535where
536    Column: StorageColumn,
537    S: KeyValueInspect<Column = Column>,
538{
539    fn batch_write<I>(&mut self, column: Column, entries: I) -> StorageResult<()>
540    where
541        I: Iterator<Item = (Vec<u8>, WriteOperation)>,
542    {
543        let btree = self.changes.entry(column.id()).or_default();
544        entries.for_each(|(key, operation)| {
545            btree.insert(key.into(), operation);
546        });
547        Ok(())
548    }
549}
550
551// The `IterableStore` should only be implemented for the actual storage,
552// not the storage transaction, to maximize the performance.
553//
554// Another reason is that only actual storage with finalized updates should be
555// used to iterate over its entries to avoid inconsistent results.
556//
557// We implement `IterableStore` for `StorageTransactionInner` only to allow
558// using it in the tests and benchmarks as a type(not even implementation of it).
559#[cfg(feature = "test-helpers")]
560impl<S> IterableStore for InMemoryTransaction<S>
561where
562    S: IterableStore,
563{
564    fn iter_store(
565        &self,
566        _: Self::Column,
567        _: Option<&[u8]>,
568        _: Option<&[u8]>,
569        _: IterDirection,
570    ) -> BoxedIter<KVItem> {
571        unimplemented!()
572    }
573
574    fn iter_store_keys(
575        &self,
576        _: Self::Column,
577        _: Option<&[u8]>,
578        _: Option<&[u8]>,
579        _: IterDirection,
580    ) -> BoxedIter<KeyItem> {
581        unimplemented!()
582    }
583}
584
585#[cfg(feature = "test-helpers")]
586mod test {
587    use super::*;
588    use crate::structured_storage::test::InMemoryStorage;
589    #[cfg(test)]
590    use crate::{
591        tables::Messages,
592        StorageAsMut,
593    };
594    #[allow(unused_imports)]
595    use std::sync::Arc;
596
597    impl<Column> Modifiable for InMemoryStorage<Column> {
598        fn commit_changes(&mut self, changes: Changes) -> StorageResult<()> {
599            for (column, value) in changes.into_iter() {
600                for (key, value) in value {
601                    match value {
602                        WriteOperation::Insert(value) => {
603                            self.storage.insert((column, key.into()), value);
604                        }
605                        WriteOperation::Remove => {
606                            self.storage.remove(&(column, key.into()));
607                        }
608                    }
609                }
610            }
611            Ok(())
612        }
613    }
614
615    #[test]
616    fn committing_changes_modifies_underlying_storage() {
617        let mut storage = InMemoryStorage::default();
618        let mut transaction = storage.write_transaction();
619
620        let mut sub_transaction = transaction.write_transaction();
621
622        sub_transaction
623            .storage_as_mut::<Messages>()
624            .insert(&Default::default(), &Default::default())
625            .expect("Should work");
626
627        sub_transaction.commit().unwrap();
628        transaction.commit().unwrap();
629        assert_eq!(storage.storage().len(), 1);
630    }
631
632    #[test]
633    fn committing_changes_from_concurrent_independent_transactions_works() {
634        let storage = InMemoryStorage::default();
635        let mut transactions =
636            storage.into_transaction().with_policy(ConflictPolicy::Fail);
637
638        let mut sub_transaction1 = transactions.read_transaction();
639        let mut sub_transaction2 = transactions.read_transaction();
640
641        sub_transaction1
642            .storage_as_mut::<Messages>()
643            .insert(&[0u8; 32].into(), &Default::default())
644            .expect("Should work");
645        sub_transaction2
646            .storage_as_mut::<Messages>()
647            .insert(&[1u8; 32].into(), &Default::default())
648            .expect("Should work");
649
650        let changes1 = sub_transaction1.into();
651        let changes2 = sub_transaction2.into();
652        transactions.commit_changes(changes1).unwrap();
653        transactions.commit_changes(changes2).unwrap();
654    }
655
656    #[test]
657    fn committing_changes_from_concurrent_overlapping_transactions_fails() {
658        let storage = InMemoryStorage::default();
659        let mut transactions =
660            storage.into_transaction().with_policy(ConflictPolicy::Fail);
661
662        let mut sub_transaction1 = transactions.read_transaction();
663        let mut sub_transaction2 = transactions.read_transaction();
664
665        sub_transaction1
666            .storage_as_mut::<Messages>()
667            .insert(&[0u8; 32].into(), &Default::default())
668            .expect("Should work");
669        sub_transaction2
670            .storage_as_mut::<Messages>()
671            .insert(&[0u8; 32].into(), &Default::default())
672            .expect("Should work");
673
674        let changes1 = sub_transaction1.into();
675        let changes2 = sub_transaction2.into();
676        transactions.commit_changes(changes1).unwrap();
677        transactions
678            .commit_changes(changes2)
679            .expect_err("Should fails because of the modification for the same key");
680    }
681
682    #[cfg(test)]
683    mod key_value_functionality {
684        use super::*;
685        use crate::column::Column;
686
687        #[test]
688        fn read_returns_from_view_exact_size() {
689            // setup
690            let storage = InMemoryStorage::<Column>::default();
691            let mut view = storage.read_transaction();
692            let key = vec![0xA, 0xB, 0xC];
693            let value = Value::from([1, 2, 3]);
694            view.put(&key, Column::Metadata, value).unwrap();
695            // test
696            let mut buf = [0; 3];
697            let ret = view.read(&key, Column::Metadata, 0, &mut buf).unwrap();
698            // verify
699            assert!(ret);
700            assert_eq!(buf, [1, 2, 3]);
701        }
702
703        #[test]
704        fn read_returns_from_view_buf_smaller() {
705            // setup
706            let storage = InMemoryStorage::<Column>::default();
707            let mut view = storage.read_transaction();
708            let key = vec![0xA, 0xB, 0xC];
709            let value = Value::from([1, 2, 3]);
710            view.put(&key, Column::Metadata, value).unwrap();
711            // test
712            let mut buf = [0; 2];
713            let ret = view.read(&key, Column::Metadata, 0, &mut buf).unwrap();
714            // verify
715            assert!(ret);
716            assert_eq!(buf, [1, 2]);
717        }
718
719        #[test]
720        fn read_returns_from_view_with_offset() {
721            // setup
722            let storage = InMemoryStorage::<Column>::default();
723            let mut view = storage.read_transaction();
724            let key = vec![0xA, 0xB, 0xC];
725            let value = Value::from([1, 2, 3]);
726            view.put(&key, Column::Metadata, value).unwrap();
727            // test
728            let mut buf = [0; 2];
729            let ret = view.read(&key, Column::Metadata, 1, &mut buf).unwrap();
730            // verify
731            assert!(ret);
732            assert_eq!(buf, [2, 3]);
733        }
734
735        #[test]
736        fn read_returns_from_view_buf_bigger() {
737            // setup
738            let storage = InMemoryStorage::<Column>::default();
739            let mut view = storage.read_transaction();
740            let key = vec![0xA, 0xB, 0xC];
741            let value = Value::from([1, 2, 3]);
742            view.put(&key, Column::Metadata, value).unwrap();
743            // test
744            let mut buf = [0; 4];
745            let ret = view.read(&key, Column::Metadata, 0, &mut buf).unwrap_err();
746            // verify
747            assert_eq!(ret, crate::Error::Other(anyhow::anyhow!("Offset `0` + buf_len `4` read until 4 which is out of bounds `3` for key `[10, 11, 12]`".to_string())));
748        }
749
750        #[test]
751        fn read_returns_from_view_buf_bigger_because_offset() {
752            // setup
753            let storage = InMemoryStorage::<Column>::default();
754            let mut view = storage.read_transaction();
755            let key = vec![0xA, 0xB, 0xC];
756            let value = Value::from([1, 2, 3]);
757            view.put(&key, Column::Metadata, value).unwrap();
758            // test
759            let mut buf = [0; 3];
760            let ret = view.read(&key, Column::Metadata, 1, &mut buf).unwrap_err();
761            // verify
762            assert_eq!(ret, crate::Error::Other(anyhow::anyhow!("Offset `1` + buf_len `3` read until 4 which is out of bounds `3` for key `[10, 11, 12]`".to_string())));
763        }
764
765        #[test]
766        fn get_returns_from_view() {
767            // setup
768            let storage = InMemoryStorage::<Column>::default();
769            let mut view = storage.read_transaction();
770            let key = vec![0xA, 0xB, 0xC];
771            let expected = Value::from([1, 2, 3]);
772            view.put(&key, Column::Metadata, expected.clone()).unwrap();
773            // test
774            let ret = view.get(&key, Column::Metadata).unwrap();
775            // verify
776            assert_eq!(ret, Some(expected))
777        }
778
779        #[test]
780        fn get_returns_from_data_store_when_key_not_in_view() {
781            // setup
782            let mut storage = InMemoryStorage::<Column>::default();
783            let mut write = storage.write_transaction();
784            let key = vec![0xA, 0xB, 0xC];
785            let expected = Value::from([1, 2, 3]);
786            write.put(&key, Column::Metadata, expected.clone()).unwrap();
787            write.commit().unwrap();
788
789            let view = storage.read_transaction();
790            // test
791            let ret = view.get(&key, Column::Metadata).unwrap();
792            // verify
793            assert_eq!(ret, Some(expected))
794        }
795
796        #[test]
797        fn get_does_not_fetch_from_datastore_if_intentionally_deleted_from_view() {
798            // setup
799            let mut storage = InMemoryStorage::<Column>::default();
800            let mut write = storage.write_transaction();
801            let key = vec![0xA, 0xB, 0xC];
802            let expected = Value::from([1, 2, 3]);
803            write.put(&key, Column::Metadata, expected.clone()).unwrap();
804            write.commit().unwrap();
805
806            let mut view = storage.read_transaction();
807            view.delete(&key, Column::Metadata).unwrap();
808            // test
809            let ret = view.get(&key, Column::Metadata).unwrap();
810            let original = storage.get(&key, Column::Metadata).unwrap();
811            // verify
812            assert_eq!(ret, None);
813            // also ensure the original value is still intact and we aren't just passing
814            // through None from the data store
815            assert_eq!(original, Some(expected))
816        }
817
818        #[test]
819        fn can_insert_value_into_view() {
820            // setup
821            let mut storage = InMemoryStorage::<Column>::default();
822            let mut write = storage.write_transaction();
823            let expected = Value::from([1, 2, 3]);
824            write
825                .put(&[0xA, 0xB, 0xC], Column::Metadata, expected.clone())
826                .unwrap();
827            // test
828            let ret = write
829                .replace(&[0xA, 0xB, 0xC], Column::Metadata, Value::from([2, 4, 6]))
830                .unwrap();
831            // verify
832            assert_eq!(ret, Some(expected))
833        }
834
835        #[test]
836        fn delete_value_from_view_returns_value() {
837            // setup
838            let mut storage = InMemoryStorage::<Column>::default();
839            let mut write = storage.write_transaction();
840            let key = vec![0xA, 0xB, 0xC];
841            let expected = Value::from([1, 2, 3]);
842            write.put(&key, Column::Metadata, expected.clone()).unwrap();
843            // test
844            let ret = write.take(&key, Column::Metadata).unwrap();
845            let get = write.get(&key, Column::Metadata).unwrap();
846            // verify
847            assert_eq!(ret, Some(expected));
848            assert_eq!(get, None)
849        }
850
851        #[test]
852        fn delete_returns_datastore_value_when_not_in_view() {
853            // setup
854            let mut storage = InMemoryStorage::<Column>::default();
855            let mut write = storage.write_transaction();
856            let key = vec![0xA, 0xB, 0xC];
857            let expected = Value::from([1, 2, 3]);
858            write.put(&key, Column::Metadata, expected.clone()).unwrap();
859            write.commit().unwrap();
860
861            let mut view = storage.read_transaction();
862            // test
863            let ret = view.take(&key, Column::Metadata).unwrap();
864            let get = view.get(&key, Column::Metadata).unwrap();
865            // verify
866            assert_eq!(ret, Some(expected));
867            assert_eq!(get, None)
868        }
869
870        #[test]
871        fn delete_does_not_return_datastore_value_when_deleted_twice() {
872            // setup
873            let mut storage = InMemoryStorage::<Column>::default();
874            let mut write = storage.write_transaction();
875            let key = vec![0xA, 0xB, 0xC];
876            let expected = Value::from([1, 2, 3]);
877            write.put(&key, Column::Metadata, expected.clone()).unwrap();
878            write.commit().unwrap();
879
880            let mut view = storage.read_transaction();
881            // test
882            let ret1 = view.take(&key, Column::Metadata).unwrap();
883            let ret2 = view.take(&key, Column::Metadata).unwrap();
884            let get = view.get(&key, Column::Metadata).unwrap();
885            // verify
886            assert_eq!(ret1, Some(expected));
887            assert_eq!(ret2, None);
888            assert_eq!(get, None)
889        }
890
891        #[test]
892        fn exists_checks_view_values() {
893            // setup
894            let mut storage = InMemoryStorage::<Column>::default();
895            let mut write = storage.write_transaction();
896            let key = vec![0xA, 0xB, 0xC];
897            let expected = Value::from([1, 2, 3]);
898            write.put(&key, Column::Metadata, expected).unwrap();
899            // test
900            let ret = write.exists(&key, Column::Metadata).unwrap();
901            // verify
902            assert!(ret)
903        }
904
905        #[test]
906        fn exists_checks_data_store_when_not_in_view() {
907            // setup
908            let mut storage = InMemoryStorage::<Column>::default();
909            let mut write = storage.write_transaction();
910            let key = vec![0xA, 0xB, 0xC];
911            let expected = Value::from([1, 2, 3]);
912            write.put(&key, Column::Metadata, expected).unwrap();
913            write.commit().unwrap();
914
915            let view = storage.read_transaction();
916            // test
917            let ret = view.exists(&key, Column::Metadata).unwrap();
918            // verify
919            assert!(ret)
920        }
921
922        #[test]
923        fn exists_does_not_check_data_store_after_intentional_removal_from_view() {
924            // setup
925            let mut storage = InMemoryStorage::<Column>::default();
926            let mut write = storage.write_transaction();
927            let key = vec![0xA, 0xB, 0xC];
928            let expected = Value::from([1, 2, 3]);
929            write.put(&key, Column::Metadata, expected).unwrap();
930            write.commit().unwrap();
931
932            let mut view = storage.read_transaction();
933            view.delete(&key, Column::Metadata).unwrap();
934            // test
935            let ret = view.exists(&key, Column::Metadata).unwrap();
936            let original = storage.exists(&key, Column::Metadata).unwrap();
937            // verify
938            assert!(!ret);
939            // also ensure the original value is still intact and we aren't just passing
940            // through None from the data store
941            assert!(original)
942        }
943
944        #[test]
945        fn commit_applies_puts() {
946            // setup
947            let mut storage = InMemoryStorage::<Column>::default();
948            let mut write = storage.write_transaction();
949            let key = vec![0xA, 0xB, 0xC];
950            let expected = Value::from([1, 2, 3]);
951            write.put(&key, Column::Metadata, expected.clone()).unwrap();
952            // test
953            write.commit().unwrap();
954            let ret = storage.get(&key, Column::Metadata).unwrap();
955            // verify
956            assert_eq!(ret, Some(expected))
957        }
958
959        #[test]
960        fn commit_applies_deletes() {
961            // setup
962            let mut storage = InMemoryStorage::<Column>::default();
963            let mut write = storage.write_transaction();
964            let key = vec![0xA, 0xB, 0xC];
965            let expected = Value::from([1, 2, 3]);
966            write.put(&key, Column::Metadata, expected).unwrap();
967            write.commit().unwrap();
968
969            let mut view = storage.write_transaction();
970            // test
971            view.delete(&key, Column::Metadata).unwrap();
972            view.commit().unwrap();
973            let ret = storage.get(&key, Column::Metadata).unwrap();
974            // verify
975            assert_eq!(ret, None)
976        }
977
978        #[test]
979        fn can_use_unit_value() {
980            let key = vec![0x00];
981
982            let mut storage = InMemoryStorage::<Column>::default();
983            let mut write = storage.write_transaction();
984            let expected = Value::from([]);
985            write.put(&key, Column::Metadata, expected.clone()).unwrap();
986
987            assert_eq!(
988                write.get(&key, Column::Metadata).unwrap().unwrap(),
989                expected
990            );
991
992            assert!(write.exists(&key, Column::Metadata).unwrap());
993
994            assert_eq!(
995                write.take(&key, Column::Metadata).unwrap().unwrap(),
996                expected
997            );
998
999            assert!(!write.exists(&key, Column::Metadata).unwrap());
1000
1001            write.commit().unwrap();
1002
1003            assert!(!storage.exists(&key, Column::Metadata).unwrap());
1004
1005            let mut storage = InMemoryStorage::<Column>::default();
1006            let mut write = storage.write_transaction();
1007            write.put(&key, Column::Metadata, expected.clone()).unwrap();
1008            write.commit().unwrap();
1009
1010            assert_eq!(
1011                storage.get(&key, Column::Metadata).unwrap().unwrap(),
1012                expected
1013            );
1014        }
1015
1016        #[test]
1017        fn can_use_unit_key() {
1018            let key: Vec<u8> = Vec::with_capacity(0);
1019
1020            let mut storage = InMemoryStorage::<Column>::default();
1021            let mut write = storage.write_transaction();
1022            let expected = Value::from([]);
1023            write.put(&key, Column::Metadata, expected.clone()).unwrap();
1024
1025            assert_eq!(
1026                write.get(&key, Column::Metadata).unwrap().unwrap(),
1027                expected
1028            );
1029
1030            assert!(write.exists(&key, Column::Metadata).unwrap());
1031
1032            assert_eq!(
1033                write.take(&key, Column::Metadata).unwrap().unwrap(),
1034                expected
1035            );
1036
1037            assert!(!write.exists(&key, Column::Metadata).unwrap());
1038
1039            write.commit().unwrap();
1040
1041            assert!(!storage.exists(&key, Column::Metadata).unwrap());
1042
1043            let mut storage = InMemoryStorage::<Column>::default();
1044            let mut write = storage.write_transaction();
1045            write.put(&key, Column::Metadata, expected.clone()).unwrap();
1046            write.commit().unwrap();
1047
1048            assert_eq!(
1049                storage.get(&key, Column::Metadata).unwrap().unwrap(),
1050                expected
1051            );
1052        }
1053
1054        #[test]
1055        fn can_use_unit_key_and_value() {
1056            let key: Vec<u8> = Vec::with_capacity(0);
1057
1058            let mut storage = InMemoryStorage::<Column>::default();
1059            let mut write = storage.write_transaction();
1060            let expected = Value::from([]);
1061            write.put(&key, Column::Metadata, expected.clone()).unwrap();
1062
1063            assert_eq!(
1064                write.get(&key, Column::Metadata).unwrap().unwrap(),
1065                expected
1066            );
1067
1068            assert!(write.exists(&key, Column::Metadata).unwrap());
1069
1070            assert_eq!(
1071                write.take(&key, Column::Metadata).unwrap().unwrap(),
1072                expected
1073            );
1074
1075            assert!(!write.exists(&key, Column::Metadata).unwrap());
1076
1077            write.commit().unwrap();
1078
1079            assert!(!storage.exists(&key, Column::Metadata).unwrap());
1080
1081            let mut storage = InMemoryStorage::<Column>::default();
1082            let mut write = storage.write_transaction();
1083            write.put(&key, Column::Metadata, expected.clone()).unwrap();
1084            write.commit().unwrap();
1085
1086            assert_eq!(
1087                storage.get(&key, Column::Metadata).unwrap().unwrap(),
1088                expected
1089            );
1090        }
1091    }
1092}