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 trait to convert the type into the storage transaction.
226pub trait IntoTransaction: Sized {
227    /// Converts the type into the storage transaction consuming it.
228    fn into_transaction(self) -> StorageTransaction<Self>;
229}
230
231impl<S> IntoTransaction for S
232where
233    S: KeyValueInspect,
234{
235    fn into_transaction(self) -> StorageTransaction<Self> {
236        StorageTransaction::transaction(
237            self,
238            ConflictPolicy::Overwrite,
239            Default::default(),
240        )
241    }
242}
243
244/// Creates a new instance of the storage read transaction.
245pub trait ReadTransaction {
246    /// Returns the read transaction without ability to commit the changes.
247    fn read_transaction(&self) -> StorageTransaction<&Self>;
248}
249
250impl<S> ReadTransaction for S
251where
252    S: KeyValueInspect,
253{
254    fn read_transaction(&self) -> StorageTransaction<&Self> {
255        StorageTransaction::transaction(
256            self,
257            ConflictPolicy::Overwrite,
258            Default::default(),
259        )
260    }
261}
262
263/// Creates a new instance of the storage write transaction.
264pub trait WriteTransaction {
265    /// Returns the write transaction that can commit the changes.
266    fn write_transaction(&mut self) -> StorageTransaction<&mut Self>;
267}
268
269impl<S> WriteTransaction for S {
270    fn write_transaction(&mut self) -> StorageTransaction<&mut Self> {
271        StorageTransaction::transaction(
272            self,
273            ConflictPolicy::Overwrite,
274            Default::default(),
275        )
276    }
277}
278
279impl<Storage> StorageTransaction<Storage>
280where
281    Storage: Modifiable,
282{
283    /// Commits the changes into the storage.
284    pub fn commit(mut self) -> StorageResult<Storage> {
285        let changes = core::mem::take(&mut self.inner.changes);
286        self.inner.storage.commit_changes(changes)?;
287        Ok(self.inner.storage)
288    }
289}
290
291impl<Storage> Modifiable for InMemoryTransaction<Storage> {
292    fn commit_changes(&mut self, changes: Changes) -> StorageResult<()> {
293        #[cfg(not(feature = "std"))]
294        use btree_map::Entry;
295        #[cfg(feature = "std")]
296        use std::collections::hash_map::Entry;
297
298        for (column, value) in changes.into_iter() {
299            let btree = match self.changes.entry(column) {
300                Entry::Vacant(vacant) => {
301                    vacant.insert(value);
302                    continue;
303                }
304                Entry::Occupied(occupied) => occupied.into_mut(),
305            };
306
307            for (k, v) in value {
308                match &self.policy {
309                    ConflictPolicy::Fail => {
310                        let entry = btree.entry(k);
311
312                        match entry {
313                            btree_map::Entry::Occupied(occupied) => {
314                                return Err(anyhow::anyhow!(
315                                    "Conflicting operation {v:?} for the {:?}",
316                                    occupied.key()
317                                )
318                                .into());
319                            }
320                            btree_map::Entry::Vacant(vacant) => {
321                                vacant.insert(v);
322                            }
323                        }
324                    }
325                    ConflictPolicy::Overwrite => {
326                        btree.insert(k, v);
327                    }
328                }
329            }
330        }
331        Ok(())
332    }
333}
334
335impl<Column, S> InMemoryTransaction<S>
336where
337    Column: StorageColumn,
338    S: KeyValueInspect<Column = Column>,
339{
340    fn get_from_changes(&self, key: &[u8], column: Column) -> Option<&WriteOperation> {
341        self.changes
342            .get(&column.id())
343            .and_then(|btree| btree.get(key))
344    }
345}
346
347impl<Column, S> KeyValueInspect for InMemoryTransaction<S>
348where
349    Column: StorageColumn,
350    S: KeyValueInspect<Column = Column>,
351{
352    type Column = Column;
353
354    fn exists(&self, key: &[u8], column: Self::Column) -> StorageResult<bool> {
355        if let Some(operation) = self.get_from_changes(key, column) {
356            match operation {
357                WriteOperation::Insert(_) => Ok(true),
358                WriteOperation::Remove => Ok(false),
359            }
360        } else {
361            self.storage.exists(key, column)
362        }
363    }
364
365    fn size_of_value(
366        &self,
367        key: &[u8],
368        column: Self::Column,
369    ) -> StorageResult<Option<usize>> {
370        if let Some(operation) = self.get_from_changes(key, column) {
371            match operation {
372                WriteOperation::Insert(value) => Ok(Some(value.len())),
373                WriteOperation::Remove => Ok(None),
374            }
375        } else {
376            self.storage.size_of_value(key, column)
377        }
378    }
379
380    fn get(&self, key: &[u8], column: Self::Column) -> StorageResult<Option<Value>> {
381        if let Some(operation) = self.get_from_changes(key, column) {
382            match operation {
383                WriteOperation::Insert(value) => Ok(Some(value.clone())),
384                WriteOperation::Remove => Ok(None),
385            }
386        } else {
387            self.storage.get(key, column)
388        }
389    }
390
391    fn read(
392        &self,
393        key: &[u8],
394        column: Self::Column,
395        offset: usize,
396        buf: &mut [u8],
397    ) -> StorageResult<Option<usize>> {
398        if let Some(operation) = self.get_from_changes(key, column) {
399            match operation {
400                WriteOperation::Insert(value) => {
401                    let bytes_len = value.as_ref().len();
402                    let start = offset;
403                    let buf_len = buf.len();
404                    let end = offset.saturating_add(buf.len());
405
406                    if end > bytes_len {
407                        return Err(anyhow::anyhow!(
408                            "Offset `{offset}` + buf_len `{buf_len}` read until {end} which is out of bounds `{bytes_len}` for key `{:?}`",
409                            key
410                        )
411                        .into());
412                    }
413
414                    let starting_from_offset = &value.as_ref()[start..end];
415                    buf[..].copy_from_slice(starting_from_offset);
416                    Ok(Some(buf_len))
417                }
418                WriteOperation::Remove => Ok(None),
419            }
420        } else {
421            self.storage.read(key, column, offset, buf)
422        }
423    }
424}
425
426impl<Column, S> KeyValueMutate for InMemoryTransaction<S>
427where
428    Column: StorageColumn,
429    S: KeyValueInspect<Column = Column>,
430{
431    fn put(
432        &mut self,
433        key: &[u8],
434        column: Self::Column,
435        value: Value,
436    ) -> StorageResult<()> {
437        let k = key.to_vec().into();
438        self.changes
439            .entry(column.id())
440            .or_default()
441            .insert(k, WriteOperation::Insert(value));
442        Ok(())
443    }
444
445    fn replace(
446        &mut self,
447        key: &[u8],
448        column: Self::Column,
449        value: Value,
450    ) -> StorageResult<Option<Value>> {
451        let k = key.to_vec().into();
452        let entry = self.changes.entry(column.id()).or_default().entry(k);
453
454        match entry {
455            btree_map::Entry::Occupied(mut occupied) => {
456                let old = occupied.insert(WriteOperation::Insert(value));
457
458                match old {
459                    WriteOperation::Insert(value) => Ok(Some(value)),
460                    WriteOperation::Remove => Ok(None),
461                }
462            }
463            btree_map::Entry::Vacant(vacant) => {
464                vacant.insert(WriteOperation::Insert(value));
465                self.storage.get(key, column)
466            }
467        }
468    }
469
470    fn write(
471        &mut self,
472        key: &[u8],
473        column: Self::Column,
474        buf: &[u8],
475    ) -> StorageResult<usize> {
476        let k = key.to_vec().into();
477        self.changes
478            .entry(column.id())
479            .or_default()
480            .insert(k, WriteOperation::Insert(Value::from(buf)));
481        Ok(buf.len())
482    }
483
484    fn take(&mut self, key: &[u8], column: Self::Column) -> StorageResult<Option<Value>> {
485        let k = key.to_vec().into();
486        let entry = self.changes.entry(column.id()).or_default().entry(k);
487
488        match entry {
489            btree_map::Entry::Occupied(mut occupied) => {
490                let old = occupied.insert(WriteOperation::Remove);
491
492                match old {
493                    WriteOperation::Insert(value) => Ok(Some(value)),
494                    WriteOperation::Remove => Ok(None),
495                }
496            }
497            btree_map::Entry::Vacant(vacant) => {
498                vacant.insert(WriteOperation::Remove);
499                self.storage.get(key, column)
500            }
501        }
502    }
503
504    fn delete(&mut self, key: &[u8], column: Self::Column) -> StorageResult<()> {
505        let k = key.to_vec().into();
506        self.changes
507            .entry(column.id())
508            .or_default()
509            .insert(k, WriteOperation::Remove);
510        Ok(())
511    }
512}
513
514impl<Column, S> BatchOperations for InMemoryTransaction<S>
515where
516    Column: StorageColumn,
517    S: KeyValueInspect<Column = Column>,
518{
519    fn batch_write<I>(&mut self, column: Column, entries: I) -> StorageResult<()>
520    where
521        I: Iterator<Item = (Vec<u8>, WriteOperation)>,
522    {
523        let btree = self.changes.entry(column.id()).or_default();
524        entries.for_each(|(key, operation)| {
525            btree.insert(key.into(), operation);
526        });
527        Ok(())
528    }
529}
530
531// The `IterableStore` should only be implemented for the actual storage,
532// not the storage transaction, to maximize the performance.
533//
534// Another reason is that only actual storage with finalized updates should be
535// used to iterate over its entries to avoid inconsistent results.
536//
537// We implement `IterableStore` for `StorageTransactionInner` only to allow
538// using it in the tests and benchmarks as a type(not even implementation of it).
539#[cfg(feature = "test-helpers")]
540impl<S> IterableStore for InMemoryTransaction<S>
541where
542    S: IterableStore,
543{
544    fn iter_store(
545        &self,
546        _: Self::Column,
547        _: Option<&[u8]>,
548        _: Option<&[u8]>,
549        _: IterDirection,
550    ) -> BoxedIter<KVItem> {
551        unimplemented!()
552    }
553
554    fn iter_store_keys(
555        &self,
556        _: Self::Column,
557        _: Option<&[u8]>,
558        _: Option<&[u8]>,
559        _: IterDirection,
560    ) -> BoxedIter<KeyItem> {
561        unimplemented!()
562    }
563}
564
565#[cfg(feature = "test-helpers")]
566mod test {
567    use super::*;
568    use crate::structured_storage::test::InMemoryStorage;
569    #[cfg(test)]
570    use crate::{
571        tables::Messages,
572        StorageAsMut,
573    };
574    #[allow(unused_imports)]
575    use std::sync::Arc;
576
577    impl<Column> Modifiable for InMemoryStorage<Column> {
578        fn commit_changes(&mut self, changes: Changes) -> StorageResult<()> {
579            for (column, value) in changes.into_iter() {
580                for (key, value) in value {
581                    match value {
582                        WriteOperation::Insert(value) => {
583                            self.storage.insert((column, key.into()), value);
584                        }
585                        WriteOperation::Remove => {
586                            self.storage.remove(&(column, key.into()));
587                        }
588                    }
589                }
590            }
591            Ok(())
592        }
593    }
594
595    #[test]
596    fn committing_changes_modifies_underlying_storage() {
597        let mut storage = InMemoryStorage::default();
598        let mut transaction = storage.write_transaction();
599
600        let mut sub_transaction = transaction.write_transaction();
601
602        sub_transaction
603            .storage_as_mut::<Messages>()
604            .insert(&Default::default(), &Default::default())
605            .expect("Should work");
606
607        sub_transaction.commit().unwrap();
608        transaction.commit().unwrap();
609        assert_eq!(storage.storage().len(), 1);
610    }
611
612    #[test]
613    fn committing_changes_from_concurrent_independent_transactions_works() {
614        let storage = InMemoryStorage::default();
615        let mut transactions =
616            storage.into_transaction().with_policy(ConflictPolicy::Fail);
617
618        let mut sub_transaction1 = transactions.read_transaction();
619        let mut sub_transaction2 = transactions.read_transaction();
620
621        sub_transaction1
622            .storage_as_mut::<Messages>()
623            .insert(&[0u8; 32].into(), &Default::default())
624            .expect("Should work");
625        sub_transaction2
626            .storage_as_mut::<Messages>()
627            .insert(&[1u8; 32].into(), &Default::default())
628            .expect("Should work");
629
630        let changes1 = sub_transaction1.into();
631        let changes2 = sub_transaction2.into();
632        transactions.commit_changes(changes1).unwrap();
633        transactions.commit_changes(changes2).unwrap();
634    }
635
636    #[test]
637    fn committing_changes_from_concurrent_overlapping_transactions_fails() {
638        let storage = InMemoryStorage::default();
639        let mut transactions =
640            storage.into_transaction().with_policy(ConflictPolicy::Fail);
641
642        let mut sub_transaction1 = transactions.read_transaction();
643        let mut sub_transaction2 = transactions.read_transaction();
644
645        sub_transaction1
646            .storage_as_mut::<Messages>()
647            .insert(&[0u8; 32].into(), &Default::default())
648            .expect("Should work");
649        sub_transaction2
650            .storage_as_mut::<Messages>()
651            .insert(&[0u8; 32].into(), &Default::default())
652            .expect("Should work");
653
654        let changes1 = sub_transaction1.into();
655        let changes2 = sub_transaction2.into();
656        transactions.commit_changes(changes1).unwrap();
657        transactions
658            .commit_changes(changes2)
659            .expect_err("Should fails because of the modification for the same key");
660    }
661
662    #[cfg(test)]
663    mod key_value_functionality {
664        use super::*;
665        use crate::column::Column;
666
667        #[test]
668        fn read_returns_from_view_exact_size() {
669            // setup
670            let storage = InMemoryStorage::<Column>::default();
671            let mut view = storage.read_transaction();
672            let key = vec![0xA, 0xB, 0xC];
673            let value = Value::from([1, 2, 3]);
674            view.put(&key, Column::Metadata, value).unwrap();
675            // test
676            let mut buf = [0; 3];
677            let ret = view.read(&key, Column::Metadata, 0, &mut buf).unwrap();
678            // verify
679            assert_eq!(ret, Some(3));
680            assert_eq!(buf, [1, 2, 3]);
681        }
682
683        #[test]
684        fn read_returns_from_view_buf_smaller() {
685            // setup
686            let storage = InMemoryStorage::<Column>::default();
687            let mut view = storage.read_transaction();
688            let key = vec![0xA, 0xB, 0xC];
689            let value = Value::from([1, 2, 3]);
690            view.put(&key, Column::Metadata, value).unwrap();
691            // test
692            let mut buf = [0; 2];
693            let ret = view.read(&key, Column::Metadata, 0, &mut buf).unwrap();
694            // verify
695            assert_eq!(ret, Some(2));
696            assert_eq!(buf, [1, 2]);
697        }
698
699        #[test]
700        fn read_returns_from_view_with_offset() {
701            // setup
702            let storage = InMemoryStorage::<Column>::default();
703            let mut view = storage.read_transaction();
704            let key = vec![0xA, 0xB, 0xC];
705            let value = Value::from([1, 2, 3]);
706            view.put(&key, Column::Metadata, value).unwrap();
707            // test
708            let mut buf = [0; 2];
709            let ret = view.read(&key, Column::Metadata, 1, &mut buf).unwrap();
710            // verify
711            assert_eq!(ret, Some(2));
712            assert_eq!(buf, [2, 3]);
713        }
714
715        #[test]
716        fn read_returns_from_view_buf_bigger() {
717            // setup
718            let storage = InMemoryStorage::<Column>::default();
719            let mut view = storage.read_transaction();
720            let key = vec![0xA, 0xB, 0xC];
721            let value = Value::from([1, 2, 3]);
722            view.put(&key, Column::Metadata, value).unwrap();
723            // test
724            let mut buf = [0; 4];
725            let ret = view.read(&key, Column::Metadata, 0, &mut buf).unwrap_err();
726            // verify
727            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())));
728        }
729
730        #[test]
731        fn read_returns_from_view_buf_bigger_because_offset() {
732            // setup
733            let storage = InMemoryStorage::<Column>::default();
734            let mut view = storage.read_transaction();
735            let key = vec![0xA, 0xB, 0xC];
736            let value = Value::from([1, 2, 3]);
737            view.put(&key, Column::Metadata, value).unwrap();
738            // test
739            let mut buf = [0; 3];
740            let ret = view.read(&key, Column::Metadata, 1, &mut buf).unwrap_err();
741            // verify
742            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())));
743        }
744
745        #[test]
746        fn get_returns_from_view() {
747            // setup
748            let storage = InMemoryStorage::<Column>::default();
749            let mut view = storage.read_transaction();
750            let key = vec![0xA, 0xB, 0xC];
751            let expected = Value::from([1, 2, 3]);
752            view.put(&key, Column::Metadata, expected.clone()).unwrap();
753            // test
754            let ret = view.get(&key, Column::Metadata).unwrap();
755            // verify
756            assert_eq!(ret, Some(expected))
757        }
758
759        #[test]
760        fn get_returns_from_data_store_when_key_not_in_view() {
761            // setup
762            let mut storage = InMemoryStorage::<Column>::default();
763            let mut write = storage.write_transaction();
764            let key = vec![0xA, 0xB, 0xC];
765            let expected = Value::from([1, 2, 3]);
766            write.put(&key, Column::Metadata, expected.clone()).unwrap();
767            write.commit().unwrap();
768
769            let view = storage.read_transaction();
770            // test
771            let ret = view.get(&key, Column::Metadata).unwrap();
772            // verify
773            assert_eq!(ret, Some(expected))
774        }
775
776        #[test]
777        fn get_does_not_fetch_from_datastore_if_intentionally_deleted_from_view() {
778            // setup
779            let mut storage = InMemoryStorage::<Column>::default();
780            let mut write = storage.write_transaction();
781            let key = vec![0xA, 0xB, 0xC];
782            let expected = Value::from([1, 2, 3]);
783            write.put(&key, Column::Metadata, expected.clone()).unwrap();
784            write.commit().unwrap();
785
786            let mut view = storage.read_transaction();
787            view.delete(&key, Column::Metadata).unwrap();
788            // test
789            let ret = view.get(&key, Column::Metadata).unwrap();
790            let original = storage.get(&key, Column::Metadata).unwrap();
791            // verify
792            assert_eq!(ret, None);
793            // also ensure the original value is still intact and we aren't just passing
794            // through None from the data store
795            assert_eq!(original, Some(expected))
796        }
797
798        #[test]
799        fn can_insert_value_into_view() {
800            // setup
801            let mut storage = InMemoryStorage::<Column>::default();
802            let mut write = storage.write_transaction();
803            let expected = Value::from([1, 2, 3]);
804            write
805                .put(&[0xA, 0xB, 0xC], Column::Metadata, expected.clone())
806                .unwrap();
807            // test
808            let ret = write
809                .replace(&[0xA, 0xB, 0xC], Column::Metadata, Value::from([2, 4, 6]))
810                .unwrap();
811            // verify
812            assert_eq!(ret, Some(expected))
813        }
814
815        #[test]
816        fn delete_value_from_view_returns_value() {
817            // setup
818            let mut storage = InMemoryStorage::<Column>::default();
819            let mut write = storage.write_transaction();
820            let key = vec![0xA, 0xB, 0xC];
821            let expected = Value::from([1, 2, 3]);
822            write.put(&key, Column::Metadata, expected.clone()).unwrap();
823            // test
824            let ret = write.take(&key, Column::Metadata).unwrap();
825            let get = write.get(&key, Column::Metadata).unwrap();
826            // verify
827            assert_eq!(ret, Some(expected));
828            assert_eq!(get, None)
829        }
830
831        #[test]
832        fn delete_returns_datastore_value_when_not_in_view() {
833            // setup
834            let mut storage = InMemoryStorage::<Column>::default();
835            let mut write = storage.write_transaction();
836            let key = vec![0xA, 0xB, 0xC];
837            let expected = Value::from([1, 2, 3]);
838            write.put(&key, Column::Metadata, expected.clone()).unwrap();
839            write.commit().unwrap();
840
841            let mut view = storage.read_transaction();
842            // test
843            let ret = view.take(&key, Column::Metadata).unwrap();
844            let get = view.get(&key, Column::Metadata).unwrap();
845            // verify
846            assert_eq!(ret, Some(expected));
847            assert_eq!(get, None)
848        }
849
850        #[test]
851        fn delete_does_not_return_datastore_value_when_deleted_twice() {
852            // setup
853            let mut storage = InMemoryStorage::<Column>::default();
854            let mut write = storage.write_transaction();
855            let key = vec![0xA, 0xB, 0xC];
856            let expected = Value::from([1, 2, 3]);
857            write.put(&key, Column::Metadata, expected.clone()).unwrap();
858            write.commit().unwrap();
859
860            let mut view = storage.read_transaction();
861            // test
862            let ret1 = view.take(&key, Column::Metadata).unwrap();
863            let ret2 = view.take(&key, Column::Metadata).unwrap();
864            let get = view.get(&key, Column::Metadata).unwrap();
865            // verify
866            assert_eq!(ret1, Some(expected));
867            assert_eq!(ret2, None);
868            assert_eq!(get, None)
869        }
870
871        #[test]
872        fn exists_checks_view_values() {
873            // setup
874            let mut storage = InMemoryStorage::<Column>::default();
875            let mut write = storage.write_transaction();
876            let key = vec![0xA, 0xB, 0xC];
877            let expected = Value::from([1, 2, 3]);
878            write.put(&key, Column::Metadata, expected).unwrap();
879            // test
880            let ret = write.exists(&key, Column::Metadata).unwrap();
881            // verify
882            assert!(ret)
883        }
884
885        #[test]
886        fn exists_checks_data_store_when_not_in_view() {
887            // setup
888            let mut storage = InMemoryStorage::<Column>::default();
889            let mut write = storage.write_transaction();
890            let key = vec![0xA, 0xB, 0xC];
891            let expected = Value::from([1, 2, 3]);
892            write.put(&key, Column::Metadata, expected).unwrap();
893            write.commit().unwrap();
894
895            let view = storage.read_transaction();
896            // test
897            let ret = view.exists(&key, Column::Metadata).unwrap();
898            // verify
899            assert!(ret)
900        }
901
902        #[test]
903        fn exists_does_not_check_data_store_after_intentional_removal_from_view() {
904            // setup
905            let mut storage = InMemoryStorage::<Column>::default();
906            let mut write = storage.write_transaction();
907            let key = vec![0xA, 0xB, 0xC];
908            let expected = Value::from([1, 2, 3]);
909            write.put(&key, Column::Metadata, expected).unwrap();
910            write.commit().unwrap();
911
912            let mut view = storage.read_transaction();
913            view.delete(&key, Column::Metadata).unwrap();
914            // test
915            let ret = view.exists(&key, Column::Metadata).unwrap();
916            let original = storage.exists(&key, Column::Metadata).unwrap();
917            // verify
918            assert!(!ret);
919            // also ensure the original value is still intact and we aren't just passing
920            // through None from the data store
921            assert!(original)
922        }
923
924        #[test]
925        fn commit_applies_puts() {
926            // setup
927            let mut storage = InMemoryStorage::<Column>::default();
928            let mut write = storage.write_transaction();
929            let key = vec![0xA, 0xB, 0xC];
930            let expected = Value::from([1, 2, 3]);
931            write.put(&key, Column::Metadata, expected.clone()).unwrap();
932            // test
933            write.commit().unwrap();
934            let ret = storage.get(&key, Column::Metadata).unwrap();
935            // verify
936            assert_eq!(ret, Some(expected))
937        }
938
939        #[test]
940        fn commit_applies_deletes() {
941            // setup
942            let mut storage = InMemoryStorage::<Column>::default();
943            let mut write = storage.write_transaction();
944            let key = vec![0xA, 0xB, 0xC];
945            let expected = Value::from([1, 2, 3]);
946            write.put(&key, Column::Metadata, expected).unwrap();
947            write.commit().unwrap();
948
949            let mut view = storage.write_transaction();
950            // test
951            view.delete(&key, Column::Metadata).unwrap();
952            view.commit().unwrap();
953            let ret = storage.get(&key, Column::Metadata).unwrap();
954            // verify
955            assert_eq!(ret, None)
956        }
957
958        #[test]
959        fn can_use_unit_value() {
960            let key = vec![0x00];
961
962            let mut storage = InMemoryStorage::<Column>::default();
963            let mut write = storage.write_transaction();
964            let expected = Value::from([]);
965            write.put(&key, Column::Metadata, expected.clone()).unwrap();
966
967            assert_eq!(
968                write.get(&key, Column::Metadata).unwrap().unwrap(),
969                expected
970            );
971
972            assert!(write.exists(&key, Column::Metadata).unwrap());
973
974            assert_eq!(
975                write.take(&key, Column::Metadata).unwrap().unwrap(),
976                expected
977            );
978
979            assert!(!write.exists(&key, Column::Metadata).unwrap());
980
981            write.commit().unwrap();
982
983            assert!(!storage.exists(&key, Column::Metadata).unwrap());
984
985            let mut storage = InMemoryStorage::<Column>::default();
986            let mut write = storage.write_transaction();
987            write.put(&key, Column::Metadata, expected.clone()).unwrap();
988            write.commit().unwrap();
989
990            assert_eq!(
991                storage.get(&key, Column::Metadata).unwrap().unwrap(),
992                expected
993            );
994        }
995
996        #[test]
997        fn can_use_unit_key() {
998            let key: Vec<u8> = Vec::with_capacity(0);
999
1000            let mut storage = InMemoryStorage::<Column>::default();
1001            let mut write = storage.write_transaction();
1002            let expected = Value::from([]);
1003            write.put(&key, Column::Metadata, expected.clone()).unwrap();
1004
1005            assert_eq!(
1006                write.get(&key, Column::Metadata).unwrap().unwrap(),
1007                expected
1008            );
1009
1010            assert!(write.exists(&key, Column::Metadata).unwrap());
1011
1012            assert_eq!(
1013                write.take(&key, Column::Metadata).unwrap().unwrap(),
1014                expected
1015            );
1016
1017            assert!(!write.exists(&key, Column::Metadata).unwrap());
1018
1019            write.commit().unwrap();
1020
1021            assert!(!storage.exists(&key, Column::Metadata).unwrap());
1022
1023            let mut storage = InMemoryStorage::<Column>::default();
1024            let mut write = storage.write_transaction();
1025            write.put(&key, Column::Metadata, expected.clone()).unwrap();
1026            write.commit().unwrap();
1027
1028            assert_eq!(
1029                storage.get(&key, Column::Metadata).unwrap().unwrap(),
1030                expected
1031            );
1032        }
1033
1034        #[test]
1035        fn can_use_unit_key_and_value() {
1036            let key: Vec<u8> = Vec::with_capacity(0);
1037
1038            let mut storage = InMemoryStorage::<Column>::default();
1039            let mut write = storage.write_transaction();
1040            let expected = Value::from([]);
1041            write.put(&key, Column::Metadata, expected.clone()).unwrap();
1042
1043            assert_eq!(
1044                write.get(&key, Column::Metadata).unwrap().unwrap(),
1045                expected
1046            );
1047
1048            assert!(write.exists(&key, Column::Metadata).unwrap());
1049
1050            assert_eq!(
1051                write.take(&key, Column::Metadata).unwrap().unwrap(),
1052                expected
1053            );
1054
1055            assert!(!write.exists(&key, Column::Metadata).unwrap());
1056
1057            write.commit().unwrap();
1058
1059            assert!(!storage.exists(&key, Column::Metadata).unwrap());
1060
1061            let mut storage = InMemoryStorage::<Column>::default();
1062            let mut write = storage.write_transaction();
1063            write.put(&key, Column::Metadata, expected.clone()).unwrap();
1064            write.commit().unwrap();
1065
1066            assert_eq!(
1067                storage.get(&key, Column::Metadata).unwrap().unwrap(),
1068                expected
1069            );
1070        }
1071    }
1072}