From 64aa37f474f3c772b9ce30c205799b8db6ef9453 Mon Sep 17 00:00:00 2001 From: Ivan Ukhov Date: Mon, 8 Jun 2015 21:42:34 -0400 Subject: [PATCH] =?UTF-8?q?Give=20&strs=20instead=20of=20Strings=20to=20Da?= =?UTF-8?q?tabase::process=E2=80=99=20callback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- examples/workflow.rs | 4 ++-- src/database.rs | 32 +++++++++++++++++++++++++------- tests/lib.rs | 2 +- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 50c3791..bd1d093 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ fn main() { "#).unwrap(); database.process("SELECT * FROM `users`;", |pairs| { - for (ref column, ref value) in pairs { - println!("{} = {}", column, value); + for &(column, value) in pairs.iter() { + println!("{} = {}", column, value.unwrap()); } true }).unwrap(); diff --git a/examples/workflow.rs b/examples/workflow.rs index d94c73f..5af9d0f 100644 --- a/examples/workflow.rs +++ b/examples/workflow.rs @@ -13,8 +13,8 @@ fn main() { "#).unwrap(); database.process("SELECT * FROM `users`;", |pairs| { - for (ref column, ref value) in pairs { - println!("{} = {}", column, value); + for &(column, value) in pairs.iter() { + println!("{} = {}", column, value.unwrap()); } true }).unwrap(); diff --git a/src/database.rs b/src/database.rs index 95cc2e6..aaed8d3 100644 --- a/src/database.rs +++ b/src/database.rs @@ -42,12 +42,12 @@ impl<'l> Database<'l> { /// no more rows will be processed. #[inline] pub fn process(&self, sql: &str, callback: F) -> Result<()> - where F: FnMut(Vec<(String, String)>) -> bool + where F: FnMut(&[(&str, Option<&str>)]) -> bool { unsafe { let callback = Box::new(callback); success!(self.raw, raw::sqlite3_exec(self.raw, str_to_c_str!(sql), - Some(execute_callback::), + Some(process_callback::), &*callback as *const _ as *mut _ as *mut _, 0 as *mut _)); } @@ -111,20 +111,38 @@ extern fn busy_callback(callback: *mut c_void, attempts: c_int) -> c_int unsafe { if (*(callback as *mut F))(attempts as usize) { 1 } else { 0 } } } -extern fn execute_callback(callback: *mut c_void, count: c_int, values: *mut *mut c_char, +extern fn process_callback(callback: *mut c_void, count: c_int, values: *mut *mut c_char, columns: *mut *mut c_char) -> c_int - where F: FnMut(Vec<(String, String)>) -> bool + where F: FnMut(&[(&str, Option<&str>)]) -> bool { + use std::str; + use std::ffi::CStr; + + macro_rules! c_str_to_str( + ($string:expr) => (str::from_utf8(CStr::from_ptr($string).to_bytes())); + ); + unsafe { let mut pairs = Vec::with_capacity(count as usize); for i in 0..(count as isize) { - let column = c_str_to_string!(*columns.offset(i)); - let value = c_str_to_string!(*values.offset(i)); + let column = { + let pointer = *columns.offset(i); + debug_assert!(!pointer.is_null()); + c_str_to_str!(pointer).unwrap() + }; + let value = { + let pointer = *values.offset(i); + if pointer.is_null() { + None + } else { + Some(c_str_to_str!(pointer).unwrap()) + } + }; pairs.push((column, value)); } - if (*(callback as *mut F))(pairs) { 0 } else { 1 } + if (*(callback as *mut F))(&pairs) { 0 } else { 1 } } } diff --git a/tests/lib.rs b/tests/lib.rs index 046278d..eb81377 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -14,7 +14,7 @@ fn workflow() { use sqlite::State; macro_rules! pair( - ($one:expr, $two:expr) => ((String::from($one), String::from($two))); + ($one:expr, $two:expr) => (($one, Some($two))); ); let (path, _directory) = setup();