From ff28c6f13f8c90966bc036ee73a59b713f922f34 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Wed, 25 Mar 2026 09:47:51 +1000 Subject: [PATCH] ok nvm *mut was im stupid --- nixide/src/errors/context.rs | 21 ++++++++-- nixide/src/stdext/cchar_ptr_ext.rs | 28 -------------- nixide/src/store/mod.rs | 46 ++++++++++++++-------- nixide/src/store/path.rs | 26 +++++++------ nixide/src/util/wrap.rs | 62 ++++++++++++++++++++---------- 5 files changed, 103 insertions(+), 80 deletions(-) diff --git a/nixide/src/errors/context.rs b/nixide/src/errors/context.rs index 404eee5..d425b38 100644 --- a/nixide/src/errors/context.rs +++ b/nixide/src/errors/context.rs @@ -22,6 +22,7 @@ // }; use std::ffi::c_uint; +use std::ffi::c_void; use std::ptr::NonNull; use super::{NixError, NixideResult}; @@ -269,10 +270,16 @@ impl ErrorContext { /// } /// ``` pub(super) fn get_nix_err_name(&self) -> Option { + #[allow(unused_unsafe)] // XXX: TODO: remove this `unused_unsafe` unsafe { // NOTE: an Err here only occurs when "Last error was not a nix error" - wrap::nix_string_callback!(|callback, userdata: &mut __UserData, ctx: &ErrorContext| { - sys::nix_err_name(ctx.as_ptr(), self.as_ptr(), Some(callback), userdata) + wrap::nix_string_callback!(|callback, userdata: *mut __UserData, ctx: &ErrorContext| { + sys::nix_err_name( + ctx.as_ptr(), + self.as_ptr(), + Some(callback), + userdata as *mut c_void, + ) }) .ok() } @@ -314,10 +321,16 @@ impl ErrorContext { /// } /// ``` pub(super) fn get_nix_err_info_msg(&self) -> Option { + #[allow(unused_unsafe)] // XXX: TODO: remove this `unused_unsafe` unsafe { // NOTE: an Err here only occurs when "Last error was not a nix error" - wrap::nix_string_callback!(|callback, user_data, ctx: &ErrorContext| { - sys::nix_err_info_msg(ctx.as_ptr(), self.as_ptr(), Some(callback), user_data) + wrap::nix_string_callback!(|callback, userdata, ctx: &ErrorContext| { + sys::nix_err_info_msg( + ctx.as_ptr(), + self.as_ptr(), + Some(callback), + userdata as *mut c_void, + ) }) .ok() } diff --git a/nixide/src/stdext/cchar_ptr_ext.rs b/nixide/src/stdext/cchar_ptr_ext.rs index a4af4fe..5d506a9 100644 --- a/nixide/src/stdext/cchar_ptr_ext.rs +++ b/nixide/src/stdext/cchar_ptr_ext.rs @@ -34,31 +34,3 @@ impl CCharPtrExt for *const c_char { } } } - -// XXX: TODO: remove if unused -// pub trait CCharPtrExt { -// fn to_utf8_string(self) -> Result>; -// -// fn to_utf8_string_n(self, n: usize) -> Result>; -// } -// -// impl CCharPtrExt for *const c_char { -// fn to_utf8_string(self) -> Result> { -// if self.is_null() { -// return Err(None); -// } -// let cstr = unsafe { CStr::from_ptr(self) }; -// match cstr.to_str() { -// Ok(s) => Ok(s.to_owned()), -// Err(err) => Err(Some(err)), -// } -// } -// -// fn to_utf8_string_n(self, n: usize) -> Result> { -// if self.is_null() || n == 0 { -// return Err(None); -// } -// let bytes = unsafe { from_raw_parts(self.cast::(), n as usize) }; -// from_utf8(bytes).map(str::to_string).map_err(Some) -// } -// } diff --git a/nixide/src/store/mod.rs b/nixide/src/store/mod.rs index 09ba32e..96b29b5 100644 --- a/nixide/src/store/mod.rs +++ b/nixide/src/store/mod.rs @@ -162,7 +162,7 @@ impl Store { })?; let store_path = StorePath { inner }; - let callback = userdata.inner; + let callback = unsafe { (*userdata).inner }; callback(output_name.as_ref(), &store_path); Ok((output_name, store_path)) @@ -213,27 +213,43 @@ impl Store { /// /// If the store doesn't have a version (like the dummy store), returns None pub fn version(&self) -> Result { - wrap::nix_string_callback(|callback, user_data, ctx| unsafe { - sys::nix_store_get_version(ctx.as_ptr(), self.inner.as_ptr(), Some(callback), user_data) - }) + wrap::nix_string_callback!( + |callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe { + sys::nix_store_get_version( + ctx.as_ptr(), + self.inner.as_ptr(), + Some(callback), + userdata as *mut c_void, + ) + } + ) } /// Get the URI of a Nix store pub fn uri(&self) -> Result { - wrap::nix_string_callback(|callback, user_data, ctx| unsafe { - sys::nix_store_get_uri(ctx.as_ptr(), self.inner.as_ptr(), Some(callback), user_data) - }) + wrap::nix_string_callback!( + |callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe { + sys::nix_store_get_uri( + ctx.as_ptr(), + self.inner.as_ptr(), + Some(callback), + userdata as *mut c_void, + ) + } + ) } pub fn store_dir(&self) -> Result { - wrap::nix_pathbuf_callback(|callback, user_data, ctx| unsafe { - sys::nix_store_get_storedir( - ctx.as_ptr(), - self.inner.as_ptr(), - Some(callback), - user_data, - ) - }) + wrap::nix_pathbuf_callback!( + |callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe { + sys::nix_store_get_storedir( + ctx.as_ptr(), + self.inner.as_ptr(), + Some(callback), + userdata as *mut c_void, + ) + } + ) } pub fn copy_closure_to( diff --git a/nixide/src/store/path.rs b/nixide/src/store/path.rs index 9696481..5d18865 100644 --- a/nixide/src/store/path.rs +++ b/nixide/src/store/path.rs @@ -1,4 +1,4 @@ -use std::ffi::CString; +use std::ffi::{c_void, CString}; use std::path::PathBuf; use std::ptr::NonNull; @@ -56,8 +56,8 @@ impl StorePath { /// Returns an error if the name cannot be retrieved. /// pub fn name(&self) -> Result { - wrap::nix_string_callback(|callback, user_data, _| unsafe { - sys::nix_store_path_name(self.inner.as_ptr(), Some(callback), user_data); + wrap::nix_string_callback!(|callback, userdata: *mut __UserData, _| unsafe { + sys::nix_store_path_name(self.inner.as_ptr(), Some(callback), userdata as *mut c_void); // NOTE: nix_store_path_name doesn't return nix_err, so we force it to return successfully nix_err_NIX_OK }) @@ -85,15 +85,17 @@ impl StorePath { /// * `store` - The store containing the path /// pub fn real_path(&self, store: &Store) -> Result { - wrap::nix_pathbuf_callback(|callback, user_data, ctx| unsafe { - sys::nix_store_real_path( - ctx.as_ptr(), - store.inner.as_ptr(), - self.as_ptr(), - Some(callback), - user_data, - ) - }) + wrap::nix_pathbuf_callback!( + |callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe { + sys::nix_store_real_path( + ctx.as_ptr(), + store.inner.as_ptr(), + self.as_ptr(), + Some(callback), + userdata as *mut c_void, + ) + } + ) } /// Check if a [StorePath] is valid (i.e. that its corresponding store object diff --git a/nixide/src/util/wrap.rs b/nixide/src/util/wrap.rs index e4bdb4c..f26a2ac 100644 --- a/nixide/src/util/wrap.rs +++ b/nixide/src/util/wrap.rs @@ -11,6 +11,22 @@ impl AsMut> for UserData { } } +// pub(crate) trait VoidPtrIsomorphism { +// fn as_void_ptr(self) -> *mut c_void; + +// fn from_void_ptr(ptr: *mut c_void) -> Self; +// } + +// impl VoidPtrIsomorphism for *mut UserData { +// fn as_void_ptr(self) -> *mut c_void { +// self as *mut c_void +// } + +// fn from_void_ptr(ptr: *mut c_void) -> Self { +// ptr as Self +// } +// } + impl UserData { /// # Warning /// @@ -46,6 +62,8 @@ macro_rules! nonnull { } }}; } +use std::ffi::c_void; + pub(crate) use nonnull; macro_rules! nix_fn { @@ -80,6 +98,7 @@ macro_rules! __nix_callback { __return }}; } +#[allow(unused_imports)] // XXX: TODO: replace the tail of `nix_callback!` with this macro pub(crate) use __nix_callback; /// `libnix` functions consistently either expect the `userdata`/`user_data` (inconsistently named in the API...) @@ -95,36 +114,37 @@ macro_rules! nix_callback { ( | $( $($pre:ident : $pre_ty:ty),+ $(,)? )? ; $userdata:ident : $userdata_type:ty ; $( $($post:ident : $post_ty:ty),+ $(,)? )? | -> $ret:ty $body:block, $function:expr $(,)? ) => {{ type __UserData = $crate::util::wrap::UserData<$userdata_type, $ret>; // create a function item that wraps the closure body (so it has a concrete type) + #[allow(unused_variables)] unsafe extern "C" fn __captured_fn( $($( $pre: $pre_ty, )*)? - $userdata: &mut __UserData, + $userdata: *mut __UserData, $($( $post: $post_ty, )*)? - ) -> $ret $body + ) -> $ret { $body } unsafe extern "C" fn __wrapper_callback( $($( $pre: $pre_ty, )*)? - $userdata: &mut __UserData, + $userdata: *mut ::std::ffi::c_void, $($( $post: $post_ty, )*)? ) { - let stored_retval = &raw mut $userdata.retval; - - let retval = unsafe { - __captured_fn( - $($( $pre, )*)? - $userdata, - $($( $post, )*)? - ) - }; - unsafe { + let userdata_ = $userdata as *mut __UserData; + let stored_retval = &raw mut (*userdata_).retval; + + let retval = + __captured_fn( + $($( $pre, )*)? + userdata_, + $($( $post, )*)? + ); + stored_retval.write(retval) - }; + } } let mut __ctx: $crate::errors::ErrorContext = $crate::errors::ErrorContext::new(); - let mut __state: ::std::mem::MaybeUninit<__UserData> = ::std::mem::MaybeUninit::uninit(); + let mut __state: ::std::mem::MaybeUninit<__UserData> = ::std::mem::MaybeUninit::zeroed(); - $function(__wrapper_callback, &mut __state, &__ctx); + $function(__wrapper_callback, __state.as_mut_ptr(), &__ctx); __ctx.pop().and_then(|_| unsafe { __state.assume_init().retval }) }}; @@ -133,20 +153,20 @@ pub(crate) use nix_callback; // XXX: TODO: convert these to declarative macros macro_rules! nix_string_callback { - ($callback:expr $(,)?) => {{ + ($function:expr $(,)?) => {{ $crate::util::wrap::nix_callback!( |start: *const ::std::ffi::c_char, n: ::std::ffi::c_uint; userdata: ();| -> $crate::NixideResult { - start.to_utf8_string_n(n as usize) + $crate::stdext::CCharPtrExt::to_utf8_string_n(start, n as usize) }, - $callback + $function ) }}; } pub(crate) use nix_string_callback; macro_rules! nix_pathbuf_callback { - ($callback:expr $(,)?) => {{ - $crate::util::wrap::nix_string_callback!($callback).map(::std::path::PathBuf::from) + ($function:expr $(,)?) => {{ + $crate::util::wrap::nix_string_callback!($function).map(::std::path::PathBuf::from) }}; } pub(crate) use nix_pathbuf_callback;