libsql_sys/wal/
wrapper.rs

1use std::ffi::{c_int, CStr};
2use std::marker::PhantomData;
3use std::num::NonZeroU32;
4
5use super::{BusyHandler, CheckpointCallback, Sqlite3File, Vfs, Wal, WalManager};
6
7/// A convenient wrapper struct that implement WAL with a `wrapper` where the wrapper needs to
8/// implement `WrapWal` instead of `Wal`, where all methods delegate to wrapped by default.
9#[derive(Clone)]
10pub struct WalWrapper<T, W> {
11    wrapper: T,
12    wrapped: W,
13}
14
15impl<T, W> WalWrapper<T, W>
16where
17    T: WrapWal<W::Wal> + Clone,
18    W: WalManager,
19{
20    pub fn new(wrapper: T, wrapped: W) -> Self {
21        Self { wrapper, wrapped }
22    }
23
24    pub fn wrapped(&self) -> &W {
25        &self.wrapped
26    }
27
28    pub fn wrapper(&self) -> &T {
29        &self.wrapper
30    }
31}
32
33pub struct WrappedWal<T, W> {
34    wrapper: T,
35    wrapped: W,
36}
37
38pub struct WalRef<T, W> {
39    wrapper: *mut T,
40    wrapped: *mut W,
41}
42
43impl<T: WrapWal<W>, W: Wal> Wal for WalRef<T, W> {
44    fn limit(&mut self, size: i64) {
45        unsafe { (*self.wrapper).limit(&mut *self.wrapped, size) }
46    }
47
48    fn begin_read_txn(&mut self) -> super::Result<bool> {
49        unsafe { (*self.wrapper).begin_read_txn(&mut *self.wrapped) }
50    }
51
52    fn end_read_txn(&mut self) {
53        unsafe { (*self.wrapper).end_read_txn(&mut *self.wrapped) }
54    }
55
56    fn find_frame(&mut self, page_no: NonZeroU32) -> super::Result<Option<NonZeroU32>> {
57        unsafe { (*self.wrapper).find_frame(&mut *self.wrapped, page_no) }
58    }
59
60    fn read_frame(&mut self, frame_no: NonZeroU32, buffer: &mut [u8]) -> super::Result<()> {
61        unsafe { (*self.wrapper).read_frame(&mut *self.wrapped, frame_no, buffer) }
62    }
63
64    fn read_frame_raw(&mut self, frame_no: NonZeroU32, buffer: &mut [u8]) -> super::Result<()> {
65        unsafe { (*self.wrapper).read_frame_raw(&mut *self.wrapped, frame_no, buffer) }
66    }
67
68    fn db_size(&self) -> u32 {
69        unsafe { (*self.wrapper).db_size(&*self.wrapped) }
70    }
71
72    fn begin_write_txn(&mut self) -> super::Result<()> {
73        unsafe { (*self.wrapper).begin_write_txn(&mut *self.wrapped) }
74    }
75
76    fn end_write_txn(&mut self) -> super::Result<()> {
77        unsafe { (*self.wrapper).end_write_txn(&mut *self.wrapped) }
78    }
79
80    fn undo<U: super::UndoHandler>(&mut self, handler: Option<&mut U>) -> super::Result<()> {
81        unsafe { (*self.wrapper).undo(&mut *self.wrapped, handler) }
82    }
83
84    fn savepoint(&mut self, rollback_data: &mut [u32]) {
85        unsafe { (*self.wrapper).savepoint(&mut *self.wrapped, rollback_data) }
86    }
87
88    fn savepoint_undo(&mut self, rollback_data: &mut [u32]) -> super::Result<()> {
89        unsafe { (*self.wrapper).savepoint_undo(&mut *self.wrapped, rollback_data) }
90    }
91
92    fn frame_count(&self, locked: i32) -> super::Result<u32> {
93        unsafe { (*self.wrapper).frame_count(&*self.wrapped, locked) }
94    }
95
96    fn insert_frames(
97        &mut self,
98        page_size: c_int,
99        page_headers: &mut super::PageHeaders,
100        size_after: u32,
101        is_commit: bool,
102        sync_flags: c_int,
103    ) -> super::Result<usize> {
104        unsafe {
105            (*self.wrapper).insert_frames(
106                &mut *self.wrapped,
107                page_size,
108                page_headers,
109                size_after,
110                is_commit,
111                sync_flags,
112            )
113        }
114    }
115
116    fn checkpoint(
117        &mut self,
118        db: &mut super::Sqlite3Db,
119        mode: super::CheckpointMode,
120        busy_handler: Option<&mut dyn BusyHandler>,
121        sync_flags: u32,
122        // temporary scratch buffer
123        buf: &mut [u8],
124        checkpoint_cb: Option<&mut dyn CheckpointCallback>,
125        in_wal: Option<&mut i32>,
126        backfilled: Option<&mut i32>,
127    ) -> super::Result<()> {
128        unsafe {
129            (*self.wrapper).checkpoint(
130                &mut *self.wrapped,
131                db,
132                mode,
133                busy_handler,
134                sync_flags,
135                buf,
136                checkpoint_cb,
137                in_wal,
138                backfilled,
139            )
140        }
141    }
142
143    fn exclusive_mode(&mut self, op: c_int) -> super::Result<()> {
144        unsafe { (*self.wrapper).exclusive_mode(&mut *self.wrapped, op) }
145    }
146
147    fn uses_heap_memory(&self) -> bool {
148        unsafe { (*self.wrapper).uses_heap_memory(&*self.wrapped) }
149    }
150
151    fn set_db(&mut self, db: &mut super::Sqlite3Db) {
152        unsafe { (*self.wrapper).set_db(&mut *self.wrapped, db) }
153    }
154
155    fn callback(&self) -> i32 {
156        unsafe { (*self.wrapper).callback(&*self.wrapped) }
157    }
158
159    fn frames_in_wal(&self) -> u32 {
160        unsafe { (*self.wrapper).frames_in_wal(&*self.wrapped) }
161    }
162}
163
164impl<T, U> WalManager for WalWrapper<T, U>
165where
166    T: WrapWal<U::Wal> + Clone,
167    U: WalManager,
168{
169    type Wal = WrappedWal<T, U::Wal>;
170
171    fn use_shared_memory(&self) -> bool {
172        self.wrapped.use_shared_memory()
173    }
174
175    fn open(
176        &self,
177        vfs: &mut super::Vfs,
178        file: &mut super::Sqlite3File,
179        no_shm_mode: std::ffi::c_int,
180        max_log_size: i64,
181        db_path: &std::ffi::CStr,
182    ) -> super::Result<Self::Wal> {
183        let wrapped =
184            self.wrapper
185                .open(&self.wrapped, vfs, file, no_shm_mode, max_log_size, db_path)?;
186        Ok(Self::Wal {
187            wrapper: self.wrapper.clone(),
188            wrapped,
189        })
190    }
191
192    fn close(
193        &self,
194        wal: &mut Self::Wal,
195        db: &mut super::Sqlite3Db,
196        sync_flags: std::ffi::c_int,
197        scratch: Option<&mut [u8]>,
198    ) -> super::Result<()> {
199        self.wrapper
200            .clone()
201            .close(&self.wrapped, &mut wal.wrapped, db, sync_flags, scratch)
202    }
203
204    fn destroy_log(&self, vfs: &mut super::Vfs, db_path: &std::ffi::CStr) -> super::Result<()> {
205        self.wrapped.destroy_log(vfs, db_path)
206    }
207
208    fn log_exists(&self, vfs: &mut super::Vfs, db_path: &std::ffi::CStr) -> super::Result<bool> {
209        self.wrapped.log_exists(vfs, db_path)
210    }
211
212    fn destroy(self)
213    where
214        Self: Sized,
215    {
216        self.wrapped.destroy()
217    }
218}
219
220impl<T, W> Wal for WrappedWal<T, W>
221where
222    T: WrapWal<W>,
223    W: Wal,
224{
225    fn limit(&mut self, size: i64) {
226        self.wrapper.limit(&mut self.wrapped, size)
227    }
228
229    fn begin_read_txn(&mut self) -> super::Result<bool> {
230        self.wrapper.begin_read_txn(&mut self.wrapped)
231    }
232
233    fn end_read_txn(&mut self) {
234        self.wrapper.end_read_txn(&mut self.wrapped)
235    }
236
237    fn find_frame(&mut self, page_no: NonZeroU32) -> super::Result<Option<NonZeroU32>> {
238        self.wrapper.find_frame(&mut self.wrapped, page_no)
239    }
240
241    fn read_frame(&mut self, frame_no: NonZeroU32, buffer: &mut [u8]) -> super::Result<()> {
242        self.wrapper.read_frame(&mut self.wrapped, frame_no, buffer)
243    }
244
245    fn read_frame_raw(&mut self, frame_no: NonZeroU32, buffer: &mut [u8]) -> super::Result<()> {
246        self.wrapper
247            .read_frame_raw(&mut self.wrapped, frame_no, buffer)
248    }
249
250    fn db_size(&self) -> u32 {
251        self.wrapper.db_size(&self.wrapped)
252    }
253
254    fn begin_write_txn(&mut self) -> super::Result<()> {
255        self.wrapper.begin_write_txn(&mut self.wrapped)
256    }
257
258    fn end_write_txn(&mut self) -> super::Result<()> {
259        self.wrapper.end_write_txn(&mut self.wrapped)
260    }
261
262    fn undo<U: super::UndoHandler>(&mut self, handler: Option<&mut U>) -> super::Result<()> {
263        self.wrapper.undo(&mut self.wrapped, handler)
264    }
265
266    fn savepoint(&mut self, rollback_data: &mut [u32]) {
267        self.wrapper.savepoint(&mut self.wrapped, rollback_data)
268    }
269
270    fn savepoint_undo(&mut self, rollback_data: &mut [u32]) -> super::Result<()> {
271        self.wrapper
272            .savepoint_undo(&mut self.wrapped, rollback_data)
273    }
274
275    fn frame_count(&self, locked: i32) -> super::Result<u32> {
276        self.wrapper.frame_count(&self.wrapped, locked)
277    }
278
279    fn insert_frames(
280        &mut self,
281        page_size: std::ffi::c_int,
282        page_headers: &mut super::PageHeaders,
283        size_after: u32,
284        is_commit: bool,
285        sync_flags: std::ffi::c_int,
286    ) -> super::Result<usize> {
287        self.wrapper.insert_frames(
288            &mut self.wrapped,
289            page_size,
290            page_headers,
291            size_after,
292            is_commit,
293            sync_flags,
294        )
295    }
296
297    fn checkpoint(
298        &mut self,
299        db: &mut super::Sqlite3Db,
300        mode: super::CheckpointMode,
301        busy_handler: Option<&mut dyn BusyHandler>,
302        sync_flags: u32,
303        // temporary scratch buffer
304        buf: &mut [u8],
305        checkpoint_cb: Option<&mut dyn CheckpointCallback>,
306        in_wal: Option<&mut i32>,
307        backfilled: Option<&mut i32>,
308    ) -> super::Result<()> {
309        self.wrapper.checkpoint(
310            &mut self.wrapped,
311            db,
312            mode,
313            busy_handler,
314            sync_flags,
315            buf,
316            checkpoint_cb,
317            in_wal,
318            backfilled,
319        )
320    }
321
322    fn exclusive_mode(&mut self, op: std::ffi::c_int) -> super::Result<()> {
323        self.wrapper.exclusive_mode(&mut self.wrapped, op)
324    }
325
326    fn uses_heap_memory(&self) -> bool {
327        self.wrapper.uses_heap_memory(&self.wrapped)
328    }
329
330    fn set_db(&mut self, db: &mut super::Sqlite3Db) {
331        self.wrapper.set_db(&mut self.wrapped, db)
332    }
333
334    fn callback(&self) -> i32 {
335        self.wrapper.callback(&self.wrapped)
336    }
337
338    fn frames_in_wal(&self) -> u32 {
339        self.wrapper.frames_in_wal(&self.wrapped)
340    }
341}
342
343/// Trait implemented by implementor that only need to wrap around another Wal implementation.
344/// By default, all methods delegate to the wrapped wal.
345pub trait WrapWal<W: Wal> {
346    fn limit(&mut self, wrapped: &mut W, size: i64) {
347        wrapped.limit(size)
348    }
349
350    fn begin_read_txn(&mut self, wrapped: &mut W) -> super::Result<bool> {
351        wrapped.begin_read_txn()
352    }
353
354    fn end_read_txn(&mut self, wrapped: &mut W) {
355        wrapped.end_read_txn()
356    }
357
358    fn find_frame(
359        &mut self,
360        wrapped: &mut W,
361        page_no: NonZeroU32,
362    ) -> super::Result<Option<NonZeroU32>> {
363        wrapped.find_frame(page_no)
364    }
365
366    fn read_frame(
367        &mut self,
368        wrapped: &mut W,
369        frame_no: NonZeroU32,
370        buffer: &mut [u8],
371    ) -> super::Result<()> {
372        wrapped.read_frame(frame_no, buffer)
373    }
374
375    fn read_frame_raw(
376        &mut self,
377        wrapped: &mut W,
378        frame_no: NonZeroU32,
379        buffer: &mut [u8],
380    ) -> super::Result<()> {
381        wrapped.read_frame_raw(frame_no, buffer)
382    }
383
384    fn db_size(&self, wrapped: &W) -> u32 {
385        wrapped.db_size()
386    }
387
388    fn begin_write_txn(&mut self, wrapped: &mut W) -> super::Result<()> {
389        wrapped.begin_write_txn()
390    }
391
392    fn end_write_txn(&mut self, wrapped: &mut W) -> super::Result<()> {
393        wrapped.end_write_txn()
394    }
395
396    fn undo<U: super::UndoHandler>(
397        &mut self,
398        wrapped: &mut W,
399        handler: Option<&mut U>,
400    ) -> super::Result<()> {
401        wrapped.undo(handler)
402    }
403
404    fn savepoint(&mut self, wrapped: &mut W, rollback_data: &mut [u32]) {
405        wrapped.savepoint(rollback_data)
406    }
407
408    fn savepoint_undo(&mut self, wrapped: &mut W, rollback_data: &mut [u32]) -> super::Result<()> {
409        wrapped.savepoint_undo(rollback_data)
410    }
411
412    fn frame_count(&self, wrapped: &W, locked: i32) -> super::Result<u32> {
413        wrapped.frame_count(locked)
414    }
415
416    fn insert_frames(
417        &mut self,
418        wrapped: &mut W,
419        page_size: std::ffi::c_int,
420        page_headers: &mut super::PageHeaders,
421        size_after: u32,
422        is_commit: bool,
423        sync_flags: std::ffi::c_int,
424    ) -> super::Result<usize> {
425        wrapped.insert_frames(page_size, page_headers, size_after, is_commit, sync_flags)
426    }
427
428    fn checkpoint(
429        &mut self,
430        wrapped: &mut W,
431        db: &mut super::Sqlite3Db,
432        mode: super::CheckpointMode,
433        busy_handler: Option<&mut dyn BusyHandler>,
434        sync_flags: u32,
435        // temporary scratch buffer
436        buf: &mut [u8],
437        checkpoint_cb: Option<&mut dyn CheckpointCallback>,
438        in_wal: Option<&mut i32>,
439        backfilled: Option<&mut i32>,
440    ) -> super::Result<()> {
441        wrapped.checkpoint(
442            db,
443            mode,
444            busy_handler,
445            sync_flags,
446            buf,
447            checkpoint_cb,
448            in_wal,
449            backfilled,
450        )
451    }
452
453    fn exclusive_mode(&mut self, wrapped: &mut W, op: std::ffi::c_int) -> super::Result<()> {
454        wrapped.exclusive_mode(op)
455    }
456
457    fn uses_heap_memory(&self, wrapped: &W) -> bool {
458        wrapped.uses_heap_memory()
459    }
460
461    fn set_db(&mut self, wrapped: &mut W, db: &mut super::Sqlite3Db) {
462        wrapped.set_db(db)
463    }
464
465    fn callback(&self, wrapped: &W) -> i32 {
466        wrapped.callback()
467    }
468
469    fn frames_in_wal(&self, wrapped: &W) -> u32 {
470        wrapped.frames_in_wal()
471    }
472
473    fn open<M: WalManager<Wal = W>>(
474        &self,
475        manager: &M,
476        vfs: &mut Vfs,
477        file: &mut Sqlite3File,
478        no_shm_mode: c_int,
479        max_log_size: i64,
480        db_path: &CStr,
481    ) -> super::Result<W> {
482        manager.open(vfs, file, no_shm_mode, max_log_size, db_path)
483    }
484
485    fn close<M: WalManager<Wal = W>>(
486        &mut self,
487        manager: &M,
488        wrapped: &mut W,
489        db: &mut super::Sqlite3Db,
490        sync_flags: c_int,
491        scratch: Option<&mut [u8]>,
492    ) -> super::Result<()> {
493        manager.close(wrapped, db, sync_flags, scratch)
494    }
495
496    fn then<T>(self, other: T) -> Then<Self, T, W>
497    where
498        Self: Sized,
499    {
500        Then(self, other, PhantomData)
501    }
502}
503
504/// Safety: we don't own a W
505unsafe impl<A: Send, B: Send, W> Send for Then<A, B, W> {}
506
507/// Safety: we don't own a W
508unsafe impl<A: Sync, B: Sync, W> Sync for Then<A, B, W> {}
509
510pub struct Then<A, B, W>(A, B, PhantomData<W>);
511
512impl<A: Clone, B: Clone, W> Clone for Then<A, B, W> {
513    fn clone(&self) -> Self {
514        Self(self.0.clone(), self.1.clone(), PhantomData)
515    }
516}
517
518impl<A, B, W> Then<A, B, W> {
519    pub fn wrapped(&self) -> &B {
520        &self.1
521    }
522
523    pub fn wrapper(&self) -> &A {
524        &self.0
525    }
526
527    pub fn map_wal<T>(self) -> Then<A, B, T> {
528        Then(self.0, self.1, PhantomData)
529    }
530}
531
532/// A Wrapper implementation that delegates everything to the wrapped wal
533#[derive(Debug, Clone, Copy)]
534pub struct PassthroughWalWrapper;
535
536impl<W: Wal> WrapWal<W> for PassthroughWalWrapper {}
537
538impl<A, B, W> WrapWal<W> for Then<A, B, W>
539where
540    A: WrapWal<WalRef<B, W>>,
541    B: WrapWal<W>,
542    W: Wal,
543{
544    fn limit(&mut self, wrapped: &mut W, size: i64) {
545        let mut r = WalRef {
546            wrapper: &mut self.1,
547            wrapped,
548        };
549
550        self.0.limit(&mut r, size)
551    }
552
553    fn begin_read_txn(&mut self, wrapped: &mut W) -> super::Result<bool> {
554        let mut r = WalRef {
555            wrapper: &mut self.1,
556            wrapped,
557        };
558
559        self.0.begin_read_txn(&mut r)
560    }
561
562    fn end_read_txn(&mut self, wrapped: &mut W) {
563        let mut r = WalRef {
564            wrapper: &mut self.1,
565            wrapped,
566        };
567        self.0.end_read_txn(&mut r)
568    }
569
570    fn find_frame(
571        &mut self,
572        wrapped: &mut W,
573        page_no: NonZeroU32,
574    ) -> super::Result<Option<NonZeroU32>> {
575        let mut r = WalRef {
576            wrapper: &mut self.1,
577            wrapped,
578        };
579        self.0.find_frame(&mut r, page_no)
580    }
581
582    fn read_frame(
583        &mut self,
584        wrapped: &mut W,
585        frame_no: NonZeroU32,
586        buffer: &mut [u8],
587    ) -> super::Result<()> {
588        let mut r = WalRef {
589            wrapper: &mut self.1,
590            wrapped,
591        };
592        self.0.read_frame(&mut r, frame_no, buffer)
593    }
594
595    fn read_frame_raw(
596        &mut self,
597        wrapped: &mut W,
598        frame_no: NonZeroU32,
599        buffer: &mut [u8],
600    ) -> super::Result<()> {
601        let mut r = WalRef {
602            wrapper: &mut self.1,
603            wrapped,
604        };
605        self.0.read_frame_raw(&mut r, frame_no, buffer)
606    }
607
608    fn db_size(&self, wrapped: &W) -> u32 {
609        let r = WalRef {
610            wrapper: &self.1 as *const B as *mut B,
611            wrapped: wrapped as *const W as *mut W,
612        };
613        self.0.db_size(&r)
614    }
615
616    fn begin_write_txn(&mut self, wrapped: &mut W) -> super::Result<()> {
617        let mut r = WalRef {
618            wrapper: &mut self.1,
619            wrapped,
620        };
621        self.0.begin_write_txn(&mut r)
622    }
623
624    fn end_write_txn(&mut self, wrapped: &mut W) -> super::Result<()> {
625        let mut r = WalRef {
626            wrapper: &mut self.1,
627            wrapped,
628        };
629        self.0.end_write_txn(&mut r)
630    }
631
632    fn undo<U: super::UndoHandler>(
633        &mut self,
634        wrapped: &mut W,
635        handler: Option<&mut U>,
636    ) -> super::Result<()> {
637        let mut r = WalRef {
638            wrapper: &mut self.1,
639            wrapped,
640        };
641        self.0.undo(&mut r, handler)
642    }
643
644    fn savepoint(&mut self, wrapped: &mut W, rollback_data: &mut [u32]) {
645        let mut r = WalRef {
646            wrapper: &mut self.1,
647            wrapped,
648        };
649        self.0.savepoint(&mut r, rollback_data)
650    }
651
652    fn savepoint_undo(&mut self, wrapped: &mut W, rollback_data: &mut [u32]) -> super::Result<()> {
653        let mut r = WalRef {
654            wrapper: &mut self.1,
655            wrapped,
656        };
657        self.0.savepoint_undo(&mut r, rollback_data)
658    }
659
660    fn insert_frames(
661        &mut self,
662        wrapped: &mut W,
663        page_size: std::ffi::c_int,
664        page_headers: &mut super::PageHeaders,
665        size_after: u32,
666        is_commit: bool,
667        sync_flags: std::ffi::c_int,
668    ) -> super::Result<usize> {
669        let mut r = WalRef {
670            wrapper: &mut self.1,
671            wrapped,
672        };
673        self.0.insert_frames(
674            &mut r,
675            page_size,
676            page_headers,
677            size_after,
678            is_commit,
679            sync_flags,
680        )
681    }
682
683    fn checkpoint(
684        &mut self,
685        wrapped: &mut W,
686        db: &mut super::Sqlite3Db,
687        mode: super::CheckpointMode,
688        busy_handler: Option<&mut dyn BusyHandler>,
689        sync_flags: u32,
690        // temporary scratch buffer
691        buf: &mut [u8],
692        checkpoint_cb: Option<&mut dyn CheckpointCallback>,
693        in_wal: Option<&mut i32>,
694        backfilled: Option<&mut i32>,
695    ) -> super::Result<()> {
696        let mut r = WalRef {
697            wrapper: &mut self.1,
698            wrapped,
699        };
700        self.0.checkpoint(
701            &mut r,
702            db,
703            mode,
704            busy_handler,
705            sync_flags,
706            buf,
707            checkpoint_cb,
708            in_wal,
709            backfilled,
710        )
711    }
712
713    fn exclusive_mode(&mut self, wrapped: &mut W, op: std::ffi::c_int) -> super::Result<()> {
714        let mut r = WalRef {
715            wrapper: &mut self.1,
716            wrapped,
717        };
718        self.0.exclusive_mode(&mut r, op)
719    }
720
721    fn uses_heap_memory(&self, wrapped: &W) -> bool {
722        let r = WalRef {
723            wrapper: &self.1 as *const B as *mut B,
724            wrapped: wrapped as *const W as *mut W,
725        };
726        self.0.uses_heap_memory(&r)
727    }
728
729    fn set_db(&mut self, wrapped: &mut W, db: &mut super::Sqlite3Db) {
730        let mut r = WalRef {
731            wrapper: &mut self.1,
732            wrapped,
733        };
734        self.0.set_db(&mut r, db)
735    }
736
737    fn callback(&self, wrapped: &W) -> i32 {
738        let r = WalRef {
739            wrapper: &self.1 as *const B as *mut B,
740            wrapped: wrapped as *const W as *mut W,
741        };
742        self.0.callback(&r)
743    }
744
745    fn frames_in_wal(&self, wrapped: &W) -> u32 {
746        let r = WalRef {
747            wrapper: &self.1 as *const B as *mut B,
748            wrapped: wrapped as *const W as *mut W,
749        };
750        self.0.frames_in_wal(&r)
751    }
752
753    fn open<M: WalManager<Wal = W>>(
754        &self,
755        manager: &M,
756        vfs: &mut Vfs,
757        file: &mut Sqlite3File,
758        no_shm_mode: c_int,
759        max_log_size: i64,
760        db_path: &CStr,
761    ) -> super::Result<W> {
762        // FIXME: this is bypassing the wrappers
763        manager.open(vfs, file, no_shm_mode, max_log_size, db_path)
764    }
765
766    fn close<M: WalManager<Wal = W>>(
767        &mut self,
768        manager: &M,
769        wrapped: &mut W,
770        db: &mut super::Sqlite3Db,
771        sync_flags: c_int,
772        scratch: Option<&mut [u8]>,
773    ) -> super::Result<()> {
774        // FIXME: this is bypassing the wrappers
775        manager.close(wrapped, db, sync_flags, scratch)
776    }
777}
778
779impl<T: WrapWal<W>, W: Wal> WrapWal<W> for Option<T> {
780    fn limit(&mut self, wrapped: &mut W, size: i64) {
781        match self {
782            Some(t) => t.limit(wrapped, size),
783            None => wrapped.limit(size),
784        }
785    }
786
787    fn begin_read_txn(&mut self, wrapped: &mut W) -> super::Result<bool> {
788        match self {
789            Some(t) => t.begin_read_txn(wrapped),
790            None => wrapped.begin_read_txn(),
791        }
792    }
793
794    fn end_read_txn(&mut self, wrapped: &mut W) {
795        match self {
796            Some(t) => t.end_read_txn(wrapped),
797            None => wrapped.end_read_txn(),
798        }
799    }
800
801    fn find_frame(
802        &mut self,
803        wrapped: &mut W,
804        page_no: NonZeroU32,
805    ) -> super::Result<Option<NonZeroU32>> {
806        match self {
807            Some(t) => t.find_frame(wrapped, page_no),
808            None => wrapped.find_frame(page_no),
809        }
810    }
811
812    fn read_frame(
813        &mut self,
814        wrapped: &mut W,
815        frame_no: NonZeroU32,
816        buffer: &mut [u8],
817    ) -> super::Result<()> {
818        match self {
819            Some(t) => t.read_frame(wrapped, frame_no, buffer),
820            None => wrapped.read_frame(frame_no, buffer),
821        }
822    }
823
824    fn read_frame_raw(
825        &mut self,
826        wrapped: &mut W,
827        frame_no: NonZeroU32,
828        buffer: &mut [u8],
829    ) -> super::Result<()> {
830        match self {
831            Some(t) => t.read_frame_raw(wrapped, frame_no, buffer),
832            None => wrapped.read_frame_raw(frame_no, buffer),
833        }
834    }
835
836    fn db_size(&self, wrapped: &W) -> u32 {
837        match self {
838            Some(t) => t.db_size(wrapped),
839            None => wrapped.db_size(),
840        }
841    }
842
843    fn begin_write_txn(&mut self, wrapped: &mut W) -> super::Result<()> {
844        match self {
845            Some(t) => t.begin_write_txn(wrapped),
846            None => wrapped.begin_write_txn(),
847        }
848    }
849
850    fn end_write_txn(&mut self, wrapped: &mut W) -> super::Result<()> {
851        match self {
852            Some(t) => t.end_write_txn(wrapped),
853            None => wrapped.end_write_txn(),
854        }
855    }
856
857    fn undo<U: super::UndoHandler>(
858        &mut self,
859        wrapped: &mut W,
860        handler: Option<&mut U>,
861    ) -> super::Result<()> {
862        match self {
863            Some(t) => t.undo(wrapped, handler),
864            None => wrapped.undo(handler),
865        }
866    }
867
868    fn savepoint(&mut self, wrapped: &mut W, rollback_data: &mut [u32]) {
869        match self {
870            Some(t) => t.savepoint(wrapped, rollback_data),
871            None => wrapped.savepoint(rollback_data),
872        }
873    }
874
875    fn savepoint_undo(&mut self, wrapped: &mut W, rollback_data: &mut [u32]) -> super::Result<()> {
876        match self {
877            Some(t) => t.savepoint_undo(wrapped, rollback_data),
878            None => wrapped.savepoint_undo(rollback_data),
879        }
880    }
881
882    fn insert_frames(
883        &mut self,
884        wrapped: &mut W,
885        page_size: std::ffi::c_int,
886        page_headers: &mut super::PageHeaders,
887        size_after: u32,
888        is_commit: bool,
889        sync_flags: std::ffi::c_int,
890    ) -> super::Result<usize> {
891        match self {
892            Some(t) => t.insert_frames(
893                wrapped,
894                page_size,
895                page_headers,
896                size_after,
897                is_commit,
898                sync_flags,
899            ),
900            None => {
901                wrapped.insert_frames(page_size, page_headers, size_after, is_commit, sync_flags)
902            }
903        }
904    }
905
906    fn checkpoint(
907        &mut self,
908        wrapped: &mut W,
909        db: &mut super::Sqlite3Db,
910        mode: super::CheckpointMode,
911        busy_handler: Option<&mut dyn BusyHandler>,
912        sync_flags: u32,
913        // temporary scratch buffer
914        buf: &mut [u8],
915        checkpoint_cb: Option<&mut dyn CheckpointCallback>,
916        in_wal: Option<&mut i32>,
917        backfilled: Option<&mut i32>,
918    ) -> super::Result<()> {
919        match self {
920            Some(t) => t.checkpoint(
921                wrapped,
922                db,
923                mode,
924                busy_handler,
925                sync_flags,
926                buf,
927                checkpoint_cb,
928                in_wal,
929                backfilled,
930            ),
931            None => wrapped.checkpoint(
932                db,
933                mode,
934                busy_handler,
935                sync_flags,
936                buf,
937                checkpoint_cb,
938                in_wal,
939                backfilled,
940            ),
941        }
942    }
943
944    fn exclusive_mode(&mut self, wrapped: &mut W, op: std::ffi::c_int) -> super::Result<()> {
945        match self {
946            Some(t) => t.exclusive_mode(wrapped, op),
947            None => wrapped.exclusive_mode(op),
948        }
949    }
950
951    fn uses_heap_memory(&self, wrapped: &W) -> bool {
952        match self {
953            Some(t) => t.uses_heap_memory(wrapped),
954            None => wrapped.uses_heap_memory(),
955        }
956    }
957
958    fn set_db(&mut self, wrapped: &mut W, db: &mut super::Sqlite3Db) {
959        match self {
960            Some(t) => t.set_db(wrapped, db),
961            None => wrapped.set_db(db),
962        }
963    }
964
965    fn callback(&self, wrapped: &W) -> i32 {
966        match self {
967            Some(t) => t.callback(wrapped),
968            None => wrapped.callback(),
969        }
970    }
971
972    fn frames_in_wal(&self, wrapped: &W) -> u32 {
973        match self {
974            Some(t) => t.frames_in_wal(wrapped),
975            None => wrapped.frames_in_wal(),
976        }
977    }
978
979    fn close<M: WalManager<Wal = W>>(
980        &mut self,
981        manager: &M,
982        wrapped: &mut W,
983        db: &mut super::Sqlite3Db,
984        sync_flags: c_int,
985        scratch: Option<&mut [u8]>,
986    ) -> super::Result<()> {
987        match self {
988            Some(t) => t.close(manager, wrapped, db, sync_flags, scratch),
989            None => manager.close(wrapped, db, sync_flags, scratch),
990        }
991    }
992}