mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-25 02:21:37 +08:00
Remove parse_macros (fails with wrapper_ext.h)
This commit is contained in:
parent
1308cdaa9d
commit
92c536b622
@ -23,7 +23,7 @@ min_sqlite_version_3_14_0 = ["pkg-config", "vcpkg"]
|
||||
# Bundle only the bindings file. Note that this does nothing if
|
||||
# `buildtime_bindgen` is enabled.
|
||||
bundled_bindings = []
|
||||
loadable_extension = ["atomic", "prettyplease", "quote", "regex", "syn"]
|
||||
loadable_extension = ["atomic", "prettyplease", "quote", "syn"]
|
||||
# sqlite3_unlock_notify >= 3.6.12
|
||||
unlock_notify = []
|
||||
# 3.13.0
|
||||
@ -55,6 +55,4 @@ prettyplease = {version = "0.2", optional = true }
|
||||
# like bindgen
|
||||
quote = { version = "1", optional = true, default-features = false }
|
||||
# like bindgen
|
||||
regex = { version = "1.5", optional = true, default-features = false, features = ["std", "unicode"] }
|
||||
# like bindgen
|
||||
syn = { version = "2.0", optional = true, features = ["full", "extra-traits", "visit-mut"] }
|
||||
|
@ -659,31 +659,30 @@ mod bindings {
|
||||
.generate()
|
||||
.unwrap_or_else(|_| panic!("could not run bindgen on header {}", header));
|
||||
|
||||
if cfg!(feature = "loadable_extension") {
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
{
|
||||
let mut output = Vec::new();
|
||||
bindings
|
||||
.write(Box::new(&mut output))
|
||||
.expect("could not write output of bindgen");
|
||||
let mut output = String::from_utf8(output).expect("bindgen output was not UTF-8?!");
|
||||
super::loadable_extension::generate_functions(&header, &mut output);
|
||||
super::loadable_extension::generate_functions(&mut output);
|
||||
std::fs::write(out_path, output.as_bytes())
|
||||
} else {
|
||||
bindings.write_to_file(out_path)
|
||||
.unwrap_or_else(|_| panic!("Could not write to {:?}", out_path));
|
||||
}
|
||||
#[cfg(not(feature = "loadable_extension"))]
|
||||
bindings
|
||||
.write_to_file(out_path)
|
||||
.unwrap_or_else(|_| panic!("Could not write to {:?}", out_path));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "buildtime_bindgen", feature = "loadable_extension"))]
|
||||
mod loadable_extension {
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// try to generate similar rust code for all `#define sqlite3_xyz
|
||||
/// sqlite3_api->abc` macros` in sqlite3ext.h
|
||||
pub fn generate_functions(header: &str, output: &mut String) {
|
||||
// (1) parse macros in sqlite3ext.h
|
||||
let mappings = parse_macros(header);
|
||||
// (2) parse sqlite3_api_routines fields from bindgen output
|
||||
pub fn generate_functions(output: &mut String) {
|
||||
// (1) parse sqlite3_api_routines fields from bindgen output
|
||||
let ast: syn::File = syn::parse_str(output).expect("could not parse bindgen output");
|
||||
let sqlite3_api_routines: syn::ItemStruct = ast
|
||||
.items
|
||||
@ -703,7 +702,7 @@ mod loadable_extension {
|
||||
let sqlite3_api_routines_ident = sqlite3_api_routines.ident;
|
||||
let p_api = quote::format_ident!("p_api");
|
||||
let mut stores = Vec::new();
|
||||
// (3) `#define sqlite3_xyz sqlite3_api->abc` => `pub unsafe fn
|
||||
// (2) `#define sqlite3_xyz sqlite3_api->abc` => `pub unsafe fn
|
||||
// sqlite3_xyz(args) -> ty {...}` for each `abc` field:
|
||||
for field in sqlite3_api_routines.fields {
|
||||
let ident = field.ident.expect("unamed field");
|
||||
@ -712,12 +711,16 @@ mod loadable_extension {
|
||||
if name == "vmprintf" || name == "xvsnprintf" || name == "str_vappendf" {
|
||||
continue; // skip va_list
|
||||
}
|
||||
let sqlite3_name = mappings
|
||||
.get(&name)
|
||||
.unwrap_or_else(|| panic!("no mapping for {name}"));
|
||||
let sqlite3_name = match name.as_ref() {
|
||||
"xthreadsafe" => "sqlite3_threadsafe".to_owned(),
|
||||
"interruptx" => "sqlite3_interrupt".to_owned(),
|
||||
_ => {
|
||||
format!("sqlite3_{name}")
|
||||
}
|
||||
};
|
||||
let ptr_name =
|
||||
syn::Ident::new(format!("__{}", sqlite3_name.to_uppercase()).as_ref(), span);
|
||||
let sqlite3_fn_name = syn::Ident::new(sqlite3_name, span);
|
||||
let sqlite3_fn_name = syn::Ident::new(&sqlite3_name, span);
|
||||
let method =
|
||||
extract_method(&field.ty).unwrap_or_else(|| panic!("unexpected type for {name}"));
|
||||
let arg_names: syn::punctuated::Punctuated<&syn::Ident, syn::token::Comma> = method
|
||||
@ -768,7 +771,7 @@ mod loadable_extension {
|
||||
);
|
||||
});
|
||||
}
|
||||
// (4) generate rust code similar to SQLITE_EXTENSION_INIT2 macro
|
||||
// (3) generate rust code similar to SQLITE_EXTENSION_INIT2 macro
|
||||
let tokens = quote::quote! {
|
||||
/// Loadable extension initialization error
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
@ -813,29 +816,6 @@ mod loadable_extension {
|
||||
output.push('\n');
|
||||
}
|
||||
|
||||
// Load all `#define sqlite3_xyz sqlite3_api->abc` in sqlite3ext.h
|
||||
// as a map `{abc => sqlite3_xyz}`
|
||||
// See https://github.com/rust-lang/rust-bindgen/issues/2544
|
||||
fn parse_macros(header: &str) -> HashMap<String, String> {
|
||||
use regex::Regex;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
let re = Regex::new(r"^#define\s+(sqlite3_\w+)\s+sqlite3_api->(\w+)").unwrap();
|
||||
let f = File::open(header).expect("could not read sqlite3ext.h");
|
||||
let f = BufReader::new(f);
|
||||
let mut mappings = HashMap::new();
|
||||
for line in f.lines() {
|
||||
let line = line.expect("could not read line");
|
||||
if let Some(caps) = re.captures(&line) {
|
||||
mappings.insert(
|
||||
caps.get(2).unwrap().as_str().to_owned(),
|
||||
caps.get(1).unwrap().as_str().to_owned(),
|
||||
);
|
||||
}
|
||||
}
|
||||
mappings
|
||||
}
|
||||
|
||||
fn extract_method(ty: &syn::Type) -> Option<&syn::TypeBareFn> {
|
||||
match ty {
|
||||
syn::Type::Path(tp) => tp.path.segments.last(),
|
||||
|
Loading…
Reference in New Issue
Block a user