diff --git a/rust/nix-store/src/store.rs b/rust/nix-store/src/store.rs index 98fc79d..7440ff2 100644 --- a/rust/nix-store/src/store.rs +++ b/rust/nix-store/src/store.rs @@ -4,7 +4,7 @@ use nix_c_raw as raw; use nix_util::context::Context; use nix_util::result_string_init; use nix_util::string_return::{callback_get_result_string, callback_get_result_string_data}; -use std::ffi::CString; +use std::ffi::{c_char, CString}; use std::ptr::null_mut; use std::ptr::NonNull; @@ -41,7 +41,10 @@ pub struct Store { context: Context, } impl Store { - pub fn open(url: &str) -> Result { + pub fn open<'a, 'b>( + url: &str, + params: impl IntoIterator, + ) -> Result { let x = INIT.as_ref(); match x { Ok(_) => {} @@ -54,13 +57,27 @@ impl Store { let context: Context = Context::new(); let uri_ptr = CString::new(url)?; - let store = unsafe { - raw::store_open( - context.ptr(), - uri_ptr.as_ptr(), - null_mut::<*mut *const i8>(), - ) - }; + + // this intermediate value must be here and must not be moved + // because it owns the data the `*const c_char` pointers point to. + let params: Vec<(CString, CString)> = params + .into_iter() + .map(|(k, v)| Ok((CString::new(k)?, CString::new(v)?))) // to do. context + .collect::>()?; + // this intermediate value owns the data the `*mut *const c_char` pointer points to. + let mut params: Vec<_> = params + .iter() + .map(|(k, v)| [k.as_ptr(), v.as_ptr()]) + .collect(); + // this intermediate value owns the data the `*mut *mut *const c_char` pointer points to. + let mut params: Vec<*mut *const c_char> = params + .iter_mut() + .map(|t| t.as_mut_ptr()) + .chain(std::iter::once(null_mut())) // signal the end of the array + .collect(); + + let store = + unsafe { raw::store_open(context.ptr(), uri_ptr.as_ptr(), params.as_mut_ptr()) }; context.check_err()?; if store.is_null() { panic!("nix_c_store_open returned a null pointer without an error");