@@ -11,6 +11,8 @@ use async_trait::async_trait;
1111use core:: convert:: Infallible ;
1212use core:: fmt:: { Debug , Display } ;
1313
14+ use crate :: Append ;
15+
1416/// A changeset containing [`crate`] structures typically persisted together.
1517#[ derive( Debug , Clone , PartialEq ) ]
1618#[ cfg( feature = "miniscript" ) ]
@@ -87,7 +89,6 @@ impl<K, A> From<crate::indexed_tx_graph::ChangeSet<A, crate::keychain::ChangeSet
8789 }
8890 }
8991}
90-
9192/// A persistence backend for writing and loading changesets.
9293///
9394/// `C` represents the changeset; a datatype that records changes made to in-memory data structures
@@ -167,3 +168,98 @@ impl<C> PersistBackendAsync<C> for () {
167168 Ok ( None )
168169 }
169170}
171+
172+ /// Extends a changeset so that it acts as a convenient staging area for any [`PersistBackend`].
173+ ///
174+ /// Not all changes to the in-memory representation needs to be written to disk right away.
175+ /// [`Append::append`] can be used to *stage* changes first and then [`StageExt::commit_to`] can be
176+ /// used to write changes to disk.
177+ pub trait StageExt : Append + Default + Sized {
178+ /// Commit the staged changes to the persistence `backend`.
179+ ///
180+ /// Changes that are committed (if any) are returned.
181+ ///
182+ /// # Error
183+ ///
184+ /// Returns a backend-defined error if this fails.
185+ fn commit_to < B > ( & mut self , backend : & mut B ) -> Result < Option < Self > , B :: WriteError >
186+ where
187+ B : PersistBackend < Self > ,
188+ {
189+ // do not do anything if changeset is empty
190+ if self . is_empty ( ) {
191+ return Ok ( None ) ;
192+ }
193+ backend. write_changes ( & * self ) ?;
194+ // only clear if changes are written successfully to backend
195+ Ok ( Some ( core:: mem:: take ( self ) ) )
196+ }
197+
198+ /// Stages a new `changeset` and commits it (alongside any other previously staged changes) to
199+ /// the persistence `backend`.
200+ ///
201+ /// Convenience method for calling [`Append::append`] and then [`StageExt::commit_to`].
202+ fn append_and_commit_to < B > (
203+ & mut self ,
204+ changeset : Self ,
205+ backend : & mut B ,
206+ ) -> Result < Option < Self > , B :: WriteError >
207+ where
208+ B : PersistBackend < Self > ,
209+ {
210+ Append :: append ( self , changeset) ;
211+ self . commit_to ( backend)
212+ }
213+ }
214+
215+ impl < C : Append + Default > StageExt for C { }
216+
217+ /// Extends a changeset so that it acts as a convenient staging area for any
218+ /// [`PersistBackendAsync`].
219+ ///
220+ /// Not all changes to the in-memory representation needs to be written to disk right away.
221+ /// [`Append::append`] can be used to *stage* changes first and then [`StageExtAsync::commit_to`]
222+ /// can be used to write changes to disk.
223+ #[ cfg( feature = "async" ) ]
224+ #[ async_trait]
225+ pub trait StageExtAsync : Append + Default + Sized + Send + Sync {
226+ /// Commit the staged changes to the persistence `backend`.
227+ ///
228+ /// Changes that are committed (if any) are returned.
229+ ///
230+ /// # Error
231+ ///
232+ /// Returns a backend-defined error if this fails.
233+ async fn commit_to < B > ( & mut self , backend : & mut B ) -> Result < Option < Self > , B :: WriteError >
234+ where
235+ B : PersistBackendAsync < Self > + Send + Sync ,
236+ {
237+ // do not do anything if changeset is empty
238+ if self . is_empty ( ) {
239+ return Ok ( None ) ;
240+ }
241+ backend. write_changes ( & * self ) . await ?;
242+ // only clear if changes are written successfully to backend
243+ Ok ( Some ( core:: mem:: take ( self ) ) )
244+ }
245+
246+ /// Stages a new `changeset` and commits it (alongside any other previously staged changes) to
247+ /// the persistence `backend`.
248+ ///
249+ /// Convenience method for calling [`Append::append`] and then [`StageExtAsync::commit_to`].
250+ async fn append_and_commit_to < B > (
251+ & mut self ,
252+ changeset : Self ,
253+ backend : & mut B ,
254+ ) -> Result < Option < Self > , B :: WriteError >
255+ where
256+ B : PersistBackendAsync < Self > + Send + Sync ,
257+ {
258+ Append :: append ( self , changeset) ;
259+ self . commit_to ( backend) . await
260+ }
261+ }
262+
263+ #[ cfg( feature = "async" ) ]
264+ #[ async_trait]
265+ impl < C : Append + Default + Send + Sync > StageExtAsync for C { }
0 commit comments