commonware_storage/qmdb/any/
ext.rs1use super::{CleanAny, DirtyAny};
8use crate::{
9 mmr::Location,
10 qmdb::{
11 store::{Batchable, CleanStore, DirtyStore, LogStore, LogStorePrunable},
12 Error,
13 },
14 store::{Store as StoreTrait, StoreDeletable, StoreMut, StorePersistable},
15};
16
17pub struct AnyExt<A: CleanAny> {
20 inner: Option<State<A>>,
22}
23
24enum State<A: CleanAny> {
25 Clean(A),
26 Dirty(A::Dirty),
27}
28
29impl<A: CleanAny> AnyExt<A> {
30 pub const fn new(db: A) -> Self {
32 Self {
33 inner: Some(State::Clean(db)),
34 }
35 }
36
37 pub async fn close(mut self) -> Result<(), Error> {
39 self.ensure_clean().await?;
41 match self.inner.take().expect("wrapper should never be empty") {
42 State::Clean(clean) => clean.close().await,
43 _ => unreachable!("ensure_clean guarantees Clean state"),
44 }
45 }
46
47 fn ensure_dirty(&mut self) {
49 let state = self.inner.take().expect("wrapper should never be empty");
50 self.inner = Some(match state {
51 State::Clean(clean) => State::Dirty(clean.into_dirty()),
52 State::Dirty(dirty) => State::Dirty(dirty),
53 });
54 }
55
56 async fn ensure_clean(&mut self) -> Result<(), Error> {
58 let state = self.inner.take().expect("wrapper should never be empty");
59 self.inner = Some(match state {
60 State::Clean(clean) => State::Clean(clean),
61 State::Dirty(dirty) => State::Clean(dirty.merkleize().await?),
62 });
63 Ok(())
64 }
65}
66
67impl<A> StoreTrait for AnyExt<A>
68where
69 A: CleanAny,
70{
71 type Key = A::Key;
72 type Value = <A as LogStore>::Value;
73 type Error = Error;
74
75 async fn get(&self, key: &Self::Key) -> Result<Option<Self::Value>, Self::Error> {
76 match self.inner.as_ref().expect("wrapper should never be empty") {
77 State::Clean(clean) => CleanAny::get(clean, key).await,
78 State::Dirty(dirty) => DirtyAny::get(dirty, key).await,
79 }
80 }
81}
82
83impl<A> StoreMut for AnyExt<A>
84where
85 A: CleanAny,
86{
87 async fn update(&mut self, key: Self::Key, value: Self::Value) -> Result<(), Self::Error> {
88 self.ensure_dirty();
89 match self.inner.as_mut().expect("wrapper should never be empty") {
90 State::Dirty(dirty) => DirtyAny::update(dirty, key, value).await,
91 _ => unreachable!("ensure_dirty guarantees Dirty state"),
92 }
93 }
94}
95
96impl<A> StoreDeletable for AnyExt<A>
97where
98 A: CleanAny,
99{
100 async fn delete(&mut self, key: Self::Key) -> Result<bool, Self::Error> {
101 self.ensure_dirty();
102 match self.inner.as_mut().expect("wrapper should never be empty") {
103 State::Dirty(dirty) => DirtyAny::delete(dirty, key).await,
104 _ => unreachable!("ensure_dirty guarantees Dirty state"),
105 }
106 }
107}
108
109impl<A> StorePersistable for AnyExt<A>
110where
111 A: CleanAny,
112{
113 async fn commit(&mut self) -> Result<(), Self::Error> {
114 self.ensure_clean().await?;
116 match self.inner.as_mut().expect("wrapper should never be empty") {
117 State::Clean(clean) => clean.commit(None).await.map(|_| ()),
118 _ => unreachable!("ensure_clean guarantees Clean state"),
119 }
120 }
121
122 async fn destroy(mut self) -> Result<(), Self::Error> {
123 self.ensure_clean().await?;
125 match self.inner.take().expect("wrapper should never be empty") {
126 State::Clean(clean) => clean.destroy().await,
127 _ => unreachable!("ensure_clean guarantees Clean state"),
128 }
129 }
130}
131
132impl<A> LogStore for AnyExt<A>
133where
134 A: CleanAny,
135{
136 type Value = <A as LogStore>::Value;
137
138 fn is_empty(&self) -> bool {
139 match self.inner.as_ref().expect("wrapper should never be empty") {
140 State::Clean(clean) => clean.is_empty(),
141 State::Dirty(dirty) => dirty.is_empty(),
142 }
143 }
144
145 fn op_count(&self) -> Location {
146 match self.inner.as_ref().expect("wrapper should never be empty") {
147 State::Clean(clean) => clean.op_count(),
148 State::Dirty(dirty) => dirty.op_count(),
149 }
150 }
151
152 fn inactivity_floor_loc(&self) -> Location {
153 match self.inner.as_ref().expect("wrapper should never be empty") {
154 State::Clean(clean) => clean.inactivity_floor_loc(),
155 State::Dirty(dirty) => dirty.inactivity_floor_loc(),
156 }
157 }
158
159 async fn get_metadata(&self) -> Result<Option<Self::Value>, Error> {
160 match self.inner.as_ref().expect("wrapper should never be empty") {
161 State::Clean(clean) => clean.get_metadata().await,
162 State::Dirty(dirty) => dirty.get_metadata().await,
163 }
164 }
165}
166
167impl<A> LogStorePrunable for AnyExt<A>
168where
169 A: CleanAny,
170{
171 async fn prune(&mut self, prune_loc: Location) -> Result<(), Error> {
172 self.ensure_clean().await?;
174 match self.inner.as_mut().expect("wrapper should never be empty") {
175 State::Clean(clean) => clean.prune(prune_loc).await,
176 _ => unreachable!("ensure_clean guarantees Clean state"),
177 }
178 }
179}
180
181impl<A> Batchable for AnyExt<A>
182where
183 A: CleanAny,
184 <A as CleanStore>::Dirty: Batchable<Key = A::Key, Value = A::Value>,
185{
186 async fn write_batch(
187 &mut self,
188 iter: impl Iterator<Item = (Self::Key, Option<Self::Value>)>,
189 ) -> Result<(), Error> {
190 self.ensure_dirty();
191 match self.inner.as_mut().expect("wrapper should never be empty") {
192 State::Dirty(dirty) => dirty.write_batch(iter).await,
193 _ => unreachable!("ensure_dirty guarantees Dirty state"),
194 }
195 }
196}