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
|
# Bundle only the bindings file. Note that this does nothing if
|
||||||
# `buildtime_bindgen` is enabled.
|
# `buildtime_bindgen` is enabled.
|
||||||
bundled_bindings = []
|
bundled_bindings = []
|
||||||
loadable_extension = ["atomic", "prettyplease", "quote", "regex", "syn"]
|
loadable_extension = ["atomic", "prettyplease", "quote", "syn"]
|
||||||
# sqlite3_unlock_notify >= 3.6.12
|
# sqlite3_unlock_notify >= 3.6.12
|
||||||
unlock_notify = []
|
unlock_notify = []
|
||||||
# 3.13.0
|
# 3.13.0
|
||||||
@ -55,6 +55,4 @@ prettyplease = {version = "0.2", optional = true }
|
|||||||
# like bindgen
|
# like bindgen
|
||||||
quote = { version = "1", optional = true, default-features = false }
|
quote = { version = "1", optional = true, default-features = false }
|
||||||
# like bindgen
|
# 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"] }
|
syn = { version = "2.0", optional = true, features = ["full", "extra-traits", "visit-mut"] }
|
||||||
|
@ -659,31 +659,30 @@ mod bindings {
|
|||||||
.generate()
|
.generate()
|
||||||
.unwrap_or_else(|_| panic!("could not run bindgen on header {}", header));
|
.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();
|
let mut output = Vec::new();
|
||||||
bindings
|
bindings
|
||||||
.write(Box::new(&mut output))
|
.write(Box::new(&mut output))
|
||||||
.expect("could not write output of bindgen");
|
.expect("could not write output of bindgen");
|
||||||
let mut output = String::from_utf8(output).expect("bindgen output was not UTF-8?!");
|
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())
|
std::fs::write(out_path, output.as_bytes())
|
||||||
} else {
|
.unwrap_or_else(|_| panic!("Could not write to {:?}", out_path));
|
||||||
bindings.write_to_file(out_path)
|
|
||||||
}
|
}
|
||||||
|
#[cfg(not(feature = "loadable_extension"))]
|
||||||
|
bindings
|
||||||
|
.write_to_file(out_path)
|
||||||
.unwrap_or_else(|_| panic!("Could not write to {:?}", out_path));
|
.unwrap_or_else(|_| panic!("Could not write to {:?}", out_path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "buildtime_bindgen", feature = "loadable_extension"))]
|
#[cfg(all(feature = "buildtime_bindgen", feature = "loadable_extension"))]
|
||||||
mod loadable_extension {
|
mod loadable_extension {
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
/// try to generate similar rust code for all `#define sqlite3_xyz
|
/// try to generate similar rust code for all `#define sqlite3_xyz
|
||||||
/// sqlite3_api->abc` macros` in sqlite3ext.h
|
/// sqlite3_api->abc` macros` in sqlite3ext.h
|
||||||
pub fn generate_functions(header: &str, output: &mut String) {
|
pub fn generate_functions(output: &mut String) {
|
||||||
// (1) parse macros in sqlite3ext.h
|
// (1) parse sqlite3_api_routines fields from bindgen output
|
||||||
let mappings = parse_macros(header);
|
|
||||||
// (2) parse sqlite3_api_routines fields from bindgen output
|
|
||||||
let ast: syn::File = syn::parse_str(output).expect("could not parse bindgen output");
|
let ast: syn::File = syn::parse_str(output).expect("could not parse bindgen output");
|
||||||
let sqlite3_api_routines: syn::ItemStruct = ast
|
let sqlite3_api_routines: syn::ItemStruct = ast
|
||||||
.items
|
.items
|
||||||
@ -703,7 +702,7 @@ mod loadable_extension {
|
|||||||
let sqlite3_api_routines_ident = sqlite3_api_routines.ident;
|
let sqlite3_api_routines_ident = sqlite3_api_routines.ident;
|
||||||
let p_api = quote::format_ident!("p_api");
|
let p_api = quote::format_ident!("p_api");
|
||||||
let mut stores = Vec::new();
|
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:
|
// sqlite3_xyz(args) -> ty {...}` for each `abc` field:
|
||||||
for field in sqlite3_api_routines.fields {
|
for field in sqlite3_api_routines.fields {
|
||||||
let ident = field.ident.expect("unamed field");
|
let ident = field.ident.expect("unamed field");
|
||||||
@ -712,12 +711,16 @@ mod loadable_extension {
|
|||||||
if name == "vmprintf" || name == "xvsnprintf" || name == "str_vappendf" {
|
if name == "vmprintf" || name == "xvsnprintf" || name == "str_vappendf" {
|
||||||
continue; // skip va_list
|
continue; // skip va_list
|
||||||
}
|
}
|
||||||
let sqlite3_name = mappings
|
let sqlite3_name = match name.as_ref() {
|
||||||
.get(&name)
|
"xthreadsafe" => "sqlite3_threadsafe".to_owned(),
|
||||||
.unwrap_or_else(|| panic!("no mapping for {name}"));
|
"interruptx" => "sqlite3_interrupt".to_owned(),
|
||||||
|
_ => {
|
||||||
|
format!("sqlite3_{name}")
|
||||||
|
}
|
||||||
|
};
|
||||||
let ptr_name =
|
let ptr_name =
|
||||||
syn::Ident::new(format!("__{}", sqlite3_name.to_uppercase()).as_ref(), span);
|
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 =
|
let method =
|
||||||
extract_method(&field.ty).unwrap_or_else(|| panic!("unexpected type for {name}"));
|
extract_method(&field.ty).unwrap_or_else(|| panic!("unexpected type for {name}"));
|
||||||
let arg_names: syn::punctuated::Punctuated<&syn::Ident, syn::token::Comma> = method
|
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! {
|
let tokens = quote::quote! {
|
||||||
/// Loadable extension initialization error
|
/// Loadable extension initialization error
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
@ -813,29 +816,6 @@ mod loadable_extension {
|
|||||||
output.push('\n');
|
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> {
|
fn extract_method(ty: &syn::Type) -> Option<&syn::TypeBareFn> {
|
||||||
match ty {
|
match ty {
|
||||||
syn::Type::Path(tp) => tp.path.segments.last(),
|
syn::Type::Path(tp) => tp.path.segments.last(),
|
||||||
|
Loading…
Reference in New Issue
Block a user