1use std::ffi::{c_int, CStr};
2use std::num::NonZeroU32;
3
4pub use crate::ffi::Error;
5use crate::ffi::*;
6
7pub use sqlite3_wal::{Sqlite3Wal, Sqlite3WalManager};
8
9pub mod either;
10pub(crate) mod ffi;
11mod sqlite3_wal;
12pub mod wrapper;
13
14pub type Result<T, E = Error> = std::result::Result<T, E>;
15pub use ffi::make_wal_manager;
16
17use self::wrapper::{WalWrapper, WrapWal};
18
19pub trait WalManager {
20 type Wal: Wal;
21
22 fn use_shared_memory(&self) -> bool;
23
24 fn open(
25 &self,
26 vfs: &mut Vfs,
27 file: &mut Sqlite3File,
28 no_shm_mode: c_int,
29 max_log_size: i64,
30 db_path: &CStr,
31 ) -> Result<Self::Wal>;
32
33 fn close(
34 &self,
35 wal: &mut Self::Wal,
36 db: &mut Sqlite3Db,
37 sync_flags: c_int,
38 scratch: Option<&mut [u8]>,
39 ) -> Result<()>;
40
41 fn destroy_log(&self, vfs: &mut Vfs, db_path: &CStr) -> Result<()>;
42 fn log_exists(&self, vfs: &mut Vfs, db_path: &CStr) -> Result<bool>;
43
44 fn destroy(self)
45 where
46 Self: Sized;
47
48 fn wrap<U>(self, wrapper: U) -> WalWrapper<U, Self>
49 where
50 U: WrapWal<Self::Wal> + Clone,
51 Self: Sized,
52 {
53 WalWrapper::new(wrapper, self)
54 }
55}
56
57pub struct Sqlite3Db {
59 inner: *mut sqlite3,
60}
61
62impl Sqlite3Db {
63 pub fn as_ptr(&mut self) -> *mut sqlite3 {
64 self.inner
65 }
66}
67
68#[repr(transparent)]
70pub struct Sqlite3File {
71 inner: *mut sqlite3_file,
72}
73
74impl Sqlite3File {
75 pub(crate) fn as_ptr(&mut self) -> *mut sqlite3_file {
76 self.inner
77 }
78
79 pub fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<()> {
80 unsafe {
81 assert!(!self.inner.is_null());
82 let inner = &mut *self.inner;
83 assert!(!inner.pMethods.is_null());
84 let io_methods = &*inner.pMethods;
85
86 let read = io_methods.xRead.unwrap();
87
88 let rc = read(
89 self.inner,
90 buf.as_mut_ptr() as *mut _,
91 buf.len() as _,
92 offset as _,
93 );
94
95 if rc == 0 {
96 Ok(())
97 } else {
98 Err(Error::new(rc))
99 }
100 }
101 }
102}
103
104pub struct Vfs {
106 vfs: *mut sqlite3_vfs,
107}
108
109impl Vfs {
110 pub(crate) fn as_ptr(&mut self) -> *mut sqlite3_vfs {
111 self.vfs
112 }
113}
114
115pub struct PageHeaders {
116 inner: *mut libsql_pghdr,
117}
118
119impl PageHeaders {
120 pub(crate) fn as_ptr(&self) -> *const libsql_pghdr {
121 self.inner
122 }
123
124 pub(crate) fn as_mut_ptr(&mut self) -> *mut libsql_pghdr {
125 self.inner
126 }
127
128 pub unsafe fn from_raw(inner: *mut libsql_pghdr) -> Self {
131 Self { inner }
132 }
133
134 pub fn iter(&self) -> PageHdrIter {
135 PageHdrIter::new(self.as_ptr(), 4096)
137 }
138}
139
140pub trait BusyHandler {
141 fn handle_busy(&mut self) -> bool;
143}
144
145impl<F> BusyHandler for F
146where
147 F: FnMut() -> bool,
148{
149 fn handle_busy(&mut self) -> bool {
150 (self)()
151 }
152}
153
154pub trait UndoHandler {
155 fn handle_undo(&mut self, page_no: u32) -> Result<()>;
156}
157
158#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
159#[repr(i32)]
160pub enum CheckpointMode {
161 Passive = SQLITE_CHECKPOINT_PASSIVE,
162 Full = SQLITE_CHECKPOINT_FULL,
163 Restart = SQLITE_CHECKPOINT_RESTART,
164 Truncate = SQLITE_CHECKPOINT_TRUNCATE,
165}
166
167pub trait CheckpointCallback {
168 fn frame(
169 &mut self,
170 max_safe_frame_no: u32,
171 frame: &[u8],
172 page_no: NonZeroU32,
173 frame_no: NonZeroU32,
174 ) -> Result<()>;
175 fn finish(&mut self) -> Result<()>;
176}
177
178pub trait Wal {
179 fn limit(&mut self, size: i64);
181 fn begin_read_txn(&mut self) -> Result<bool>;
183 fn end_read_txn(&mut self);
184
185 fn find_frame(&mut self, page_no: NonZeroU32) -> Result<Option<NonZeroU32>>;
187 fn read_frame(&mut self, frame_no: NonZeroU32, buffer: &mut [u8]) -> Result<()>;
189 fn read_frame_raw(&mut self, frame_no: NonZeroU32, buffer: &mut [u8]) -> Result<()>;
191
192 fn db_size(&self) -> u32;
193
194 fn begin_write_txn(&mut self) -> Result<()>;
195 fn end_write_txn(&mut self) -> Result<()>;
196
197 fn undo<U: UndoHandler>(&mut self, handler: Option<&mut U>) -> Result<()>;
198
199 fn savepoint(&mut self, rollback_data: &mut [u32]);
200 fn savepoint_undo(&mut self, rollback_data: &mut [u32]) -> Result<()>;
201
202 fn frame_count(&self, locked: i32) -> Result<u32>;
203
204 fn insert_frames(
207 &mut self,
208 page_size: c_int,
209 page_headers: &mut PageHeaders,
210 size_after: u32,
211 is_commit: bool,
212 sync_flags: c_int,
213 ) -> Result<usize>;
214
215 fn checkpoint(
217 &mut self,
218 db: &mut Sqlite3Db,
219 mode: CheckpointMode,
220 busy_handler: Option<&mut dyn BusyHandler>,
221 sync_flags: u32,
222 buf: &mut [u8],
224 checkpoint_cb: Option<&mut dyn CheckpointCallback>,
225 in_wal: Option<&mut i32>,
226 backfilled: Option<&mut i32>,
227 ) -> Result<()>;
228
229 fn exclusive_mode(&mut self, op: c_int) -> Result<()>;
230 fn uses_heap_memory(&self) -> bool;
231 fn set_db(&mut self, db: &mut Sqlite3Db);
232
233 fn callback(&self) -> i32;
238
239 fn frames_in_wal(&self) -> u32;
240}