dharitri_sc/types/managed/wrapped/builder/
managed_buffer_builder_impl_cached.rs

1use crate::{
2    api::ManagedTypeApi,
3    types::{ManagedBuffer, StaticBufferRef},
4};
5
6use super::ManagedBufferBuilderImpl;
7
8/// A ManagedBuffer builder implementation that caches data to the static cache locally in the contract.
9pub struct ManagedBufferBuilderImplCached<M>
10where
11    M: ManagedTypeApi,
12{
13    managed_buffer: ManagedBuffer<M>,
14    static_cache: Option<StaticBufferRef<M>>,
15}
16
17impl<M> ManagedBufferBuilderImplCached<M>
18where
19    M: ManagedTypeApi,
20{
21    fn flush_to_managed_buffer(&mut self) {
22        let old_static_cache = core::mem::take(&mut self.static_cache);
23        if let Some(static_cache) = &old_static_cache {
24            static_cache.with_buffer_contents(|bytes| {
25                self.managed_buffer.append_bytes(bytes);
26            });
27        }
28    }
29}
30
31impl<M> ManagedBufferBuilderImpl<M> for ManagedBufferBuilderImplCached<M>
32where
33    M: ManagedTypeApi,
34{
35    /// Creates instance as lazily as possible.
36    /// If possible, the slice is loaded into the static buffer.
37    /// If not, it is saved into the managed buffer so that the data is not lost.
38    /// Use `flush_to_managed_buffer` after this to ensure that the managed buffer is populated.
39    fn new_from_slice(slice: &[u8]) -> Self {
40        let static_cache = StaticBufferRef::try_new(slice);
41        if static_cache.is_some() {
42            ManagedBufferBuilderImplCached {
43                managed_buffer: ManagedBuffer::new(),
44                static_cache,
45            }
46        } else {
47            ManagedBufferBuilderImplCached {
48                managed_buffer: slice.into(),
49                static_cache: None,
50            }
51        }
52    }
53
54    fn into_managed_buffer(mut self) -> ManagedBuffer<M> {
55        self.flush_to_managed_buffer();
56        self.managed_buffer
57    }
58
59    fn append_bytes(&mut self, bytes: &[u8]) {
60        if let Some(static_cache) = &mut self.static_cache {
61            let success = static_cache.try_extend_from_slice(bytes);
62            if !success {
63                self.flush_to_managed_buffer();
64                self.managed_buffer.append_bytes(bytes);
65            }
66        } else {
67            self.managed_buffer.append_bytes(bytes);
68        }
69    }
70
71    fn append_managed_buffer(&mut self, item: &ManagedBuffer<M>) {
72        if let Some(static_cache) = &mut self.static_cache {
73            let success = static_cache.try_extend_from_copy_bytes(item.len(), |dest_slice| {
74                let _ = item.load_slice(0, dest_slice);
75            });
76            if !success {
77                self.flush_to_managed_buffer();
78                self.managed_buffer.append(item);
79            }
80        } else {
81            self.managed_buffer.append(item);
82        }
83    }
84}