maint: Update get_uri to be callback based
(cherry picked from commit 1aaf9b4d764da5aa8c1297d87ad1002bf1d7a7ea)
This commit is contained in:
parent
032a23c306
commit
759577526d
3 changed files with 60 additions and 10 deletions
|
|
@ -2,8 +2,8 @@ use anyhow::{bail, Result};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use nix_c_raw as raw;
|
use nix_c_raw as raw;
|
||||||
use nix_util::context::Context;
|
use nix_util::context::Context;
|
||||||
|
use nix_util::string_return::callback_get_vec_u8;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
|
|
@ -78,22 +78,17 @@ impl Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_uri(&self) -> Result<String> {
|
pub fn get_uri(&self) -> Result<String> {
|
||||||
const N: usize = 1024;
|
let mut raw_buffer: Vec<u8> = Vec::new();
|
||||||
let mut buffer: [MaybeUninit<u8>; N] = unsafe { MaybeUninit::uninit().assume_init() };
|
|
||||||
unsafe {
|
unsafe {
|
||||||
raw::nix_store_get_uri(
|
raw::nix_store_get_uri(
|
||||||
self.context.ptr(),
|
self.context.ptr(),
|
||||||
self.inner.ptr(),
|
self.inner.ptr(),
|
||||||
buffer.as_mut_ptr() as *mut i8,
|
callback_get_vec_u8 as *mut std::ffi::c_void,
|
||||||
N as u32,
|
&mut raw_buffer as *mut Vec<u8> as *mut std::ffi::c_void,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
self.context.check_err()?;
|
self.context.check_err()?;
|
||||||
unsafe {
|
String::from_utf8(raw_buffer).map_err(|e| e.into())
|
||||||
// copy the c string from buffer
|
|
||||||
let cstr = core::ffi::CStr::from_ptr(buffer.as_ptr() as *const i8);
|
|
||||||
cstr.to_str().map(|s| s.to_string()).map_err(|e| e.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
pub mod context;
|
pub mod context;
|
||||||
|
pub mod string_return;
|
||||||
|
|
|
||||||
54
rust/nix-util/src/string_return.rs
Normal file
54
rust/nix-util/src/string_return.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/// Callback for nix_store_get_uri and other functions that return a string.
|
||||||
|
///
|
||||||
|
/// This function is used by the other nix_* crates, and you should never need to call it yourself.
|
||||||
|
pub unsafe extern "C" fn callback_get_vec_u8(
|
||||||
|
start: *const ::std::os::raw::c_char,
|
||||||
|
n: std::os::raw::c_uint,
|
||||||
|
user_data: *mut std::os::raw::c_void,
|
||||||
|
) {
|
||||||
|
let ret = user_data as *mut Vec<u8>;
|
||||||
|
let slice = std::slice::from_raw_parts(start as *const u8, n as usize);
|
||||||
|
if !(*ret).is_empty() {
|
||||||
|
panic!("callback_get_vec_u8: slice must be empty. Were we called twice?");
|
||||||
|
}
|
||||||
|
(*ret).extend_from_slice(slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use nix_c_raw as raw;
|
||||||
|
|
||||||
|
/// Typecheck the function signature against the generated bindings in nix_c_raw.
|
||||||
|
static _CALLBACK_GET_VEC_U8: raw::nix_get_string_callback = Some(callback_get_vec_u8);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_callback_get_vec_u8_empty() {
|
||||||
|
let mut ret: Vec<u8> = Vec::new();
|
||||||
|
let start: *const std::os::raw::c_char = std::ptr::null();
|
||||||
|
let n: std::os::raw::c_uint = 0;
|
||||||
|
let user_data: *mut std::os::raw::c_void =
|
||||||
|
&mut ret as *mut Vec<u8> as *mut std::os::raw::c_void;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
callback_get_vec_u8(start, n, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(ret, vec![]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_callback_get_vec_u8() {
|
||||||
|
let mut ret: Vec<u8> = Vec::new();
|
||||||
|
let start: *const std::os::raw::c_char = b"helloGARBAGE".as_ptr() as *const i8;
|
||||||
|
let n: std::os::raw::c_uint = 5;
|
||||||
|
let user_data: *mut std::os::raw::c_void =
|
||||||
|
&mut ret as *mut Vec<u8> as *mut std::os::raw::c_void;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
callback_get_vec_u8(start, n, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(ret, b"hello".to_vec());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue