Skip to content

Commit

Permalink
feat: Introduce IntoCStr trait
Browse files Browse the repository at this point in the history
Make public interface more ergonomic by accepting more than just `&str`
in public interface.

Closes #18
  • Loading branch information
andoriyu committed Jan 15, 2023
1 parent 363ff57 commit 59d103a
Show file tree
Hide file tree
Showing 6 changed files with 319 additions and 180 deletions.
7 changes: 7 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
workspace := "~/libnv-rs"
ubuntu_host := "zetta-ubuntu"
freebsd_host := "zetta-freebsd13"
rsync_exclude := "--exclude .git --exclude .idea --exclude target --exclude libzfs_core-sys/target"

set positional-arguments

test-ubuntu args='':
just copy-code-to {{ubuntu_host}}
ssh {{ubuntu_host}} '. "$HOME/.cargo/env";cd {{workspace}} && cargo test --no-default-features --features nvpair {{args}}'


test-freebsd args='':
just copy-code-to {{freebsd_host}}
ssh {{freebsd_host}} '. "$HOME/.cargo/env";cd {{workspace}} && cargo test --no-default-features --features libnv {{args}}'

copy-code-to host:
rsync -az -e "ssh" {{rsync_exclude}} --progress ./ {{host}}:{{workspace}}

Expand Down
19 changes: 6 additions & 13 deletions libnv-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@ extern crate regex;

#[cfg(target_os = "freebsd")]
fn main() {

use regex::Regex;
use std::{
env,
fs::File,
io::Write,
path::PathBuf,
};
use std::{env, fs::File, io::Write, path::PathBuf};

println!("cargo:rerun-if-env-changed=LLVM_CONFIG_PATH");
println!("cargo:rustc-link-lib=nv");
Expand Down Expand Up @@ -44,17 +38,16 @@ fn main() {
let new_fragment = match cap.get(1).unwrap().as_str() {
"fn" => {
let funcname = cap.get(2).unwrap().as_str();
fixed_bindings.push_str(
&format!("#[link_name = \"FreeBSD_{}\"]\n", funcname));
fixed_bindings.push_str(&format!("#[link_name = \"FreeBSD_{}\"]\n", funcname));
format!("pub fn {}", funcname)
},
"type" => {
let typename = cap.get(2).unwrap().as_str();
fixed_bindings.push_str(&format!("pub type FreeBSD_{} = {};\n",
typename, typename));
fixed_bindings
.push_str(&format!("pub type FreeBSD_{} = {};\n", typename, typename));
format!("pub type {}", typename)
}
_ => unreachable!()
},
_ => unreachable!(),
};
fixed_bindings.push_str(&new_fragment);
prev_index = index + new_fragment.len() + "FreeBSD_".len();
Expand Down
5 changes: 2 additions & 3 deletions libnv-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
//! These are raw, `unsafe` FFI bindings. Here be dragons! You probably
//! shouldn't use this crate directly. Instead, you should use the
//! [`libnv`](https://crates.io/crates/libnv) crate.
#![cfg_attr(crossdocs, doc="")]
#![cfg_attr(crossdocs, doc="These docs are just stubs! Don't trust them.")]

#![cfg_attr(crossdocs, doc = "")]
#![cfg_attr(crossdocs, doc = "These docs are just stubs! Don't trust them.")]
// bindgen generates some unconventional type names
#![allow(non_camel_case_types)]

Expand Down
44 changes: 40 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,23 @@
//! [nvpair]: https://github.com/zfsonlinux/zfs/tree/master/module/nvpair
extern crate libc;
#[macro_use] extern crate quick_error;
#[macro_use]
extern crate quick_error;

#[cfg(feature = "libnv")] extern crate libnv_sys;
#[cfg(feature = "libnv")]
extern crate libnv_sys;

#[cfg(feature = "nvpair")]
extern crate nvpair_sys;

#[cfg(feature = "libnv")] pub mod libnv;
#[cfg(feature = "libnv")]
pub mod libnv;

#[cfg(feature = "nvpair")] pub mod nvpair;
#[cfg(feature = "nvpair")]
pub mod nvpair;

use std::borrow::Cow;
use std::ffi::{CStr, CString};
use std::{ffi::NulError, io};
quick_error! {
#[derive(Debug)]
Expand Down Expand Up @@ -61,3 +67,33 @@ impl NvError {

/// Short-cut to Result<T, NvError>.
pub type NvResult<T> = Result<T, NvError>;

/// Trait to keep public interface friendly (i.e. support rust types like `&str`) and at the same time
/// allow using lower level types like `CString` & `CStr`.
pub trait IntoCStr<'a> {
fn into_c_str(self) -> NvResult<Cow<'a, CStr>>;
}

impl<'a> IntoCStr<'a> for &'a CStr {
fn into_c_str(self) -> NvResult<Cow<'a, CStr>> {
Ok(Cow::from(self))
}
}

impl<'a> IntoCStr<'a> for CString {
fn into_c_str(self) -> NvResult<Cow<'a, CStr>> {
Ok(Cow::from(self))
}
}

impl<'a> IntoCStr<'a> for &str {
fn into_c_str(self) -> NvResult<Cow<'a, CStr>> {
CString::new(self).map(Cow::from).map_err(NvError::from)
}
}

impl<'a> IntoCStr<'a> for String {
fn into_c_str(self) -> NvResult<Cow<'a, CStr>> {
CString::new(self).map(Cow::from).map_err(NvError::from)
}
}
Loading

0 comments on commit 59d103a

Please sign in to comment.