|
| 1 | +//! This module contains `CachedIO`, a light wrapper over any IO instance |
| 2 | +//! which will cache the input read and output written by the underlying instance. |
| 3 | +//! It has no impact on the storage access functions of the trait. |
| 4 | +//! The purpose of this struct is to capture the input and output from the underlying |
| 5 | +//! IO instance for the purpose of passing it to `Hashchain::add_block_tx`. |
| 6 | +
|
| 7 | +use aurora_engine_sdk::io::{StorageIntermediate, IO}; |
| 8 | +use aurora_engine_types::Vec; |
| 9 | +use core::cell::RefCell; |
| 10 | + |
| 11 | +#[derive(Debug, Clone, Copy)] |
| 12 | +pub struct CachedIO<'cache, I> { |
| 13 | + inner: I, |
| 14 | + cache: &'cache RefCell<IOCache>, |
| 15 | +} |
| 16 | + |
| 17 | +#[derive(Debug, Clone, PartialEq, Eq)] |
| 18 | +pub enum WrappedInput<T> { |
| 19 | + Input(Vec<u8>), |
| 20 | + Wrapped(T), |
| 21 | +} |
| 22 | + |
| 23 | +#[derive(Debug, Clone, Default, PartialEq, Eq)] |
| 24 | +pub struct IOCache { |
| 25 | + pub input: Vec<u8>, |
| 26 | + pub output: Vec<u8>, |
| 27 | +} |
| 28 | + |
| 29 | +impl<'cache, I> CachedIO<'cache, I> { |
| 30 | + pub fn new(io: I, cache: &'cache RefCell<IOCache>) -> Self { |
| 31 | + Self { inner: io, cache } |
| 32 | + } |
| 33 | +} |
| 34 | + |
| 35 | +impl IOCache { |
| 36 | + pub fn set_input(&mut self, value: Vec<u8>) { |
| 37 | + self.input = value; |
| 38 | + } |
| 39 | + |
| 40 | + pub fn set_output(&mut self, value: Vec<u8>) { |
| 41 | + self.output = value; |
| 42 | + } |
| 43 | +} |
| 44 | + |
| 45 | +impl<T: StorageIntermediate> StorageIntermediate for WrappedInput<T> { |
| 46 | + fn len(&self) -> usize { |
| 47 | + match self { |
| 48 | + Self::Input(bytes) => bytes.len(), |
| 49 | + Self::Wrapped(x) => x.len(), |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + fn is_empty(&self) -> bool { |
| 54 | + match self { |
| 55 | + Self::Input(bytes) => bytes.is_empty(), |
| 56 | + Self::Wrapped(x) => x.is_empty(), |
| 57 | + } |
| 58 | + } |
| 59 | + |
| 60 | + fn copy_to_slice(&self, buffer: &mut [u8]) { |
| 61 | + match self { |
| 62 | + Self::Input(bytes) => buffer.copy_from_slice(bytes), |
| 63 | + Self::Wrapped(x) => x.copy_to_slice(buffer), |
| 64 | + } |
| 65 | + } |
| 66 | +} |
| 67 | + |
| 68 | +impl<'cache, I: IO> IO for CachedIO<'cache, I> { |
| 69 | + type StorageValue = WrappedInput<I::StorageValue>; |
| 70 | + |
| 71 | + fn read_input(&self) -> Self::StorageValue { |
| 72 | + let input = self.inner.read_input().to_vec(); |
| 73 | + self.cache.borrow_mut().set_input(input.clone()); |
| 74 | + WrappedInput::Input(input) |
| 75 | + } |
| 76 | + |
| 77 | + fn return_output(&mut self, value: &[u8]) { |
| 78 | + self.cache.borrow_mut().set_output(value.to_vec()); |
| 79 | + self.inner.return_output(value); |
| 80 | + } |
| 81 | + |
| 82 | + fn read_storage(&self, key: &[u8]) -> Option<Self::StorageValue> { |
| 83 | + self.inner.read_storage(key).map(WrappedInput::Wrapped) |
| 84 | + } |
| 85 | + |
| 86 | + fn storage_has_key(&self, key: &[u8]) -> bool { |
| 87 | + self.inner.storage_has_key(key) |
| 88 | + } |
| 89 | + |
| 90 | + fn write_storage(&mut self, key: &[u8], value: &[u8]) -> Option<Self::StorageValue> { |
| 91 | + self.inner |
| 92 | + .write_storage(key, value) |
| 93 | + .map(WrappedInput::Wrapped) |
| 94 | + } |
| 95 | + |
| 96 | + fn write_storage_direct( |
| 97 | + &mut self, |
| 98 | + key: &[u8], |
| 99 | + value: Self::StorageValue, |
| 100 | + ) -> Option<Self::StorageValue> { |
| 101 | + match value { |
| 102 | + WrappedInput::Wrapped(x) => self |
| 103 | + .inner |
| 104 | + .write_storage_direct(key, x) |
| 105 | + .map(WrappedInput::Wrapped), |
| 106 | + WrappedInput::Input(bytes) => self |
| 107 | + .inner |
| 108 | + .write_storage(key, &bytes) |
| 109 | + .map(WrappedInput::Wrapped), |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + fn remove_storage(&mut self, key: &[u8]) -> Option<Self::StorageValue> { |
| 114 | + self.inner.remove_storage(key).map(WrappedInput::Wrapped) |
| 115 | + } |
| 116 | +} |
0 commit comments