Skip to main content

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