Introduce macro to avoid code duplication

This commit is contained in:
gwenn 2022-03-20 08:47:01 +01:00 committed by Thom Chiovoloni
parent f04bec2fd5
commit 762321c15e

View File

@ -97,36 +97,26 @@ const ZERO_MODULE: ffi::sqlite3_module = unsafe {
.module .module
}; };
/// Create an modifiable virtual table implementation. macro_rules! module {
/// ($lt:lifetime, $vt:ty, $ct:ty, $xc:expr, $xd:expr, $xu:expr) => {
/// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
#[must_use]
pub fn update_module<'vtab, T: UpdateVTab<'vtab>>() -> &'static Module<'vtab, T> {
#[allow(clippy::needless_update)] #[allow(clippy::needless_update)]
&Module { &Module {
base: ffi::sqlite3_module { base: ffi::sqlite3_module {
// We don't use V3
iVersion: 2, iVersion: 2,
xCreate: match T::KIND { xCreate: $xc,
VTabKind::EponymousOnly => None, xConnect: Some(rust_connect::<$vt>),
VTabKind::Eponymous => Some(rust_connect::<T>), xBestIndex: Some(rust_best_index::<$vt>),
_ => Some(rust_create::<T>), xDisconnect: Some(rust_disconnect::<$vt>),
}, xDestroy: $xd,
xConnect: Some(rust_connect::<T>), xOpen: Some(rust_open::<$vt>),
xBestIndex: Some(rust_best_index::<T>), xClose: Some(rust_close::<$ct>),
xDisconnect: Some(rust_disconnect::<T>), xFilter: Some(rust_filter::<$ct>),
xDestroy: match T::KIND { xNext: Some(rust_next::<$ct>),
VTabKind::EponymousOnly => None, xEof: Some(rust_eof::<$ct>),
VTabKind::Eponymous => Some(rust_disconnect::<T>), xColumn: Some(rust_column::<$ct>),
_ => Some(rust_destroy::<T>), xRowid: Some(rust_rowid::<$ct>), // FIXME optional
}, xUpdate: $xu,
xOpen: Some(rust_open::<T>),
xClose: Some(rust_close::<T::Cursor>),
xFilter: Some(rust_filter::<T::Cursor>),
xNext: Some(rust_next::<T::Cursor>),
xEof: Some(rust_eof::<T::Cursor>),
xColumn: Some(rust_column::<T::Cursor>),
xRowid: Some(rust_rowid::<T::Cursor>),
xUpdate: Some(rust_update::<T>),
xBegin: None, xBegin: None,
xSync: None, xSync: None,
xCommit: None, xCommit: None,
@ -138,7 +128,26 @@ pub fn update_module<'vtab, T: UpdateVTab<'vtab>>() -> &'static Module<'vtab, T>
xRollbackTo: None, xRollbackTo: None,
..ZERO_MODULE ..ZERO_MODULE
}, },
phantom: PhantomData::<&'vtab T>, phantom: PhantomData::<&$lt $vt>,
}
};
}
/// Create an modifiable virtual table implementation.
///
/// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
#[must_use]
pub fn update_module<'vtab, T: UpdateVTab<'vtab>>() -> &'static Module<'vtab, T> {
match T::KIND {
VTabKind::EponymousOnly => {
module!('vtab, T, T::Cursor, None, None, Some(rust_update::<T>))
}
VTabKind::Eponymous => {
module!('vtab, T, T::Cursor, Some(rust_connect::<T>), Some(rust_disconnect::<T>), Some(rust_update::<T>))
}
_ => {
module!('vtab, T, T::Cursor, Some(rust_create::<T>), Some(rust_destroy::<T>), Some(rust_update::<T>))
}
} }
} }
@ -147,46 +156,18 @@ pub fn update_module<'vtab, T: UpdateVTab<'vtab>>() -> &'static Module<'vtab, T>
/// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations). /// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
#[must_use] #[must_use]
pub fn read_only_module<'vtab, T: CreateVTab<'vtab>>() -> &'static Module<'vtab, T> { pub fn read_only_module<'vtab, T: CreateVTab<'vtab>>() -> &'static Module<'vtab, T> {
// The xConnect and xCreate methods do the same thing, but they must be match T::KIND {
VTabKind::EponymousOnly => eponymous_only_module(),
VTabKind::Eponymous => {
// A virtual table is eponymous if its xCreate method is the exact same function
// as the xConnect method
module!('vtab, T, T::Cursor, Some(rust_connect::<T>), Some(rust_disconnect::<T>), None)
}
_ => {
// The xConnect and xCreate methods may do the same thing, but they must be
// different so that the virtual table is not an eponymous virtual table. // different so that the virtual table is not an eponymous virtual table.
#[allow(clippy::needless_update)] module!('vtab, T, T::Cursor, Some(rust_create::<T>), Some(rust_destroy::<T>), None)
&Module { }
base: ffi::sqlite3_module {
// We don't use V3
iVersion: 2, // We don't use V2 or V3 features in read_only_module types
xCreate: match T::KIND {
VTabKind::EponymousOnly => None,
VTabKind::Eponymous => Some(rust_connect::<T>),
_ => Some(rust_create::<T>),
},
xConnect: Some(rust_connect::<T>),
xBestIndex: Some(rust_best_index::<T>),
xDisconnect: Some(rust_disconnect::<T>),
xDestroy: match T::KIND {
VTabKind::EponymousOnly => None,
VTabKind::Eponymous => Some(rust_disconnect::<T>),
_ => Some(rust_destroy::<T>),
},
xOpen: Some(rust_open::<T>),
xClose: Some(rust_close::<T::Cursor>),
xFilter: Some(rust_filter::<T::Cursor>),
xNext: Some(rust_next::<T::Cursor>),
xEof: Some(rust_eof::<T::Cursor>),
xColumn: Some(rust_column::<T::Cursor>),
xRowid: Some(rust_rowid::<T::Cursor>),
xUpdate: None,
xBegin: None,
xSync: None,
xCommit: None,
xRollback: None,
xFindFunction: None,
xRename: None,
xSavepoint: None,
xRelease: None,
xRollbackTo: None,
..ZERO_MODULE
},
phantom: PhantomData::<&'vtab T>,
} }
} }
@ -195,40 +176,8 @@ pub fn read_only_module<'vtab, T: CreateVTab<'vtab>>() -> &'static Module<'vtab,
/// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations). /// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
#[must_use] #[must_use]
pub fn eponymous_only_module<'vtab, T: VTab<'vtab>>() -> &'static Module<'vtab, T> { pub fn eponymous_only_module<'vtab, T: VTab<'vtab>>() -> &'static Module<'vtab, T> {
// A virtual table is eponymous if its xCreate method is the exact same function // For eponymous-only virtual tables, the xCreate method is NULL
// as the xConnect method For eponymous-only virtual tables, the xCreate module!('vtab, T, T::Cursor, None, None, None)
// method is NULL
#[allow(clippy::needless_update)]
&Module {
base: ffi::sqlite3_module {
// We don't use V3
iVersion: 2,
xCreate: None,
xConnect: Some(rust_connect::<T>),
xBestIndex: Some(rust_best_index::<T>),
xDisconnect: Some(rust_disconnect::<T>),
xDestroy: None,
xOpen: Some(rust_open::<T>),
xClose: Some(rust_close::<T::Cursor>),
xFilter: Some(rust_filter::<T::Cursor>),
xNext: Some(rust_next::<T::Cursor>),
xEof: Some(rust_eof::<T::Cursor>),
xColumn: Some(rust_column::<T::Cursor>),
xRowid: Some(rust_rowid::<T::Cursor>),
xUpdate: None,
xBegin: None,
xSync: None,
xCommit: None,
xRollback: None,
xFindFunction: None,
xRename: None,
xSavepoint: None,
xRelease: None,
xRollbackTo: None,
..ZERO_MODULE
},
phantom: PhantomData::<&'vtab T>,
}
} }
/// Virtual table configuration options /// Virtual table configuration options
@ -350,7 +299,7 @@ pub trait CreateVTab<'vtab>: VTab<'vtab> {
} }
} }
/// Non-read-only virtual table instance trait. /// Writable virtual table instance trait.
/// ///
/// (See [SQLite doc](https://sqlite.org/vtab.html#xupdate)) /// (See [SQLite doc](https://sqlite.org/vtab.html#xupdate))
pub trait UpdateVTab<'vtab>: CreateVTab<'vtab> { pub trait UpdateVTab<'vtab>: CreateVTab<'vtab> {