Skip to content

Commit

Permalink
Remove ZStr and ZString. (#337)
Browse files Browse the repository at this point in the history
* Remove `ZStr` and `ZString`.

Use `CStr` and `CString` instead, now that nightly has then in core and
alloc, respectively.

Fixes #336.

* Enable "core_c_str" on nightly to use core::ffi::CStr.

* Don't test --no-default-features on stable.

--no-default-features disables "std", and building without "std" will
require nightly now.

* `CString` and `NulError` are in alloc.

* Add comments to the relevant Cargo.toml features.

* rustfmt
  • Loading branch information
sunfishcode authored May 27, 2022
1 parent ea0f3b0 commit b437157
Show file tree
Hide file tree
Showing 46 changed files with 497 additions and 2,308 deletions.
5 changes: 1 addition & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,8 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
build: [stable, nightly]
build: [nightly]
include:
- build: stable
os: ubuntu-latest
rust: stable
- build: nightly
os: ubuntu-latest
rust: nightly
Expand Down
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,12 @@ targets = [

[features]
default = ["std"]

# This enables use of std. Disabling this enables no_std, and
# requires nightly Rust.
std = ["io-lifetimes"]

# This is used in the port of std to rustix.
rustc-dep-of-std = [
"core",
"alloc",
Expand Down
4 changes: 2 additions & 2 deletions benches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ mod suite {
assert_eq!(
libc::fstatat(
libc::AT_FDCWD,
rustix::zstr!("/").as_ptr() as _,
rustix::cstr!("/").as_ptr() as _,
s.as_mut_ptr(),
0
),
Expand All @@ -78,7 +78,7 @@ mod suite {

c.bench_function("simple statat cstr", |b| {
b.iter(|| {
statat(cwd(), rustix::zstr!("/"), AtFlags::empty()).unwrap();
statat(cwd(), rustix::cstr!("/"), AtFlags::empty()).unwrap();
})
});
}
Expand Down
6 changes: 2 additions & 4 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ fn main() {
// Features only used in no-std configurations.
#[cfg(not(feature = "std"))]
{
use_feature_or_nothing("vec_into_raw_parts");
use_feature_or_nothing("toowned_clone_into");
use_feature_or_nothing("specialization");
use_feature_or_nothing("slice_internals");
use_feature_or_nothing("const_raw_ptr_deref");
use_feature_or_nothing("core_c_str");
use_feature_or_nothing("alloc_c_string");
}

// Gather target information.
Expand Down
36 changes: 18 additions & 18 deletions src/zstr.rs → src/cstr.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
/// A macro for [`ZStr`] literals.
/// A macro for [`CStr`] literals.
///
/// This can make passing string literals to rustix APIs more efficient, since
/// most underlying system calls with string arguments expect NUL-terminated
/// strings, and passing strings to rustix as `ZStr`s means that rustix doesn't
/// strings, and passing strings to rustix as `CStr`s means that rustix doesn't
/// need to copy them into a separate buffer to NUL-terminate them.
///
/// [`ZStr`]: crate::ffi::ZStr
/// [`CStr`]: crate::ffi::CStr
///
/// # Examples
///
/// ```rust,no_run
/// # #[cfg(feature = "fs")]
/// # fn main() -> rustix::io::Result<()> {
/// use rustix::cstr;
/// use rustix::fs::{cwd, statat, AtFlags};
/// use rustix::zstr;
///
/// let metadata = statat(cwd(), zstr!("test.txt"), AtFlags::empty())?;
/// let metadata = statat(cwd(), cstr!("test.txt"), AtFlags::empty())?;
/// # Ok(())
/// # }
/// # #[cfg(not(feature = "fs"))]
/// # fn main() {}
/// ```
#[allow(unused_macros)]
#[macro_export]
macro_rules! zstr {
macro_rules! cstr {
($str:literal) => {{
// Check for NUL manually, to ensure safety.
//
Expand All @@ -35,7 +35,7 @@ macro_rules! zstr {
// constant-fold away.
assert!(
!$str.bytes().any(|b| b == b'\0'),
"zstr argument contains embedded NUL bytes",
"cstr argument contains embedded NUL bytes",
);

#[allow(unsafe_code, unused_unsafe)]
Expand All @@ -47,30 +47,30 @@ macro_rules! zstr {
// Safety: We have manually checked that the string does not contain
// embedded NULs above, and we append or own NUL terminator here.
unsafe {
$crate::ffi::ZStr::from_bytes_with_nul_unchecked(concat!($str, "\0").as_bytes())
$crate::ffi::CStr::from_bytes_with_nul_unchecked(concat!($str, "\0").as_bytes())
}
}
}};
}

#[test]
fn test_zstr() {
use crate::ffi::ZString;
fn test_cstr() {
use crate::ffi::CString;
use alloc::borrow::ToOwned;
assert_eq!(zstr!(""), &*ZString::new("").unwrap());
assert_eq!(zstr!("").to_owned(), ZString::new("").unwrap());
assert_eq!(zstr!("hello"), &*ZString::new("hello").unwrap());
assert_eq!(zstr!("hello").to_owned(), ZString::new("hello").unwrap());
assert_eq!(cstr!(""), &*CString::new("").unwrap());
assert_eq!(cstr!("").to_owned(), CString::new("").unwrap());
assert_eq!(cstr!("hello"), &*CString::new("hello").unwrap());
assert_eq!(cstr!("hello").to_owned(), CString::new("hello").unwrap());
}

#[test]
#[should_panic]
fn test_invalid_zstr() {
let _ = zstr!("hello\0world");
fn test_invalid_cstr() {
let _ = cstr!("hello\0world");
}

#[test]
#[should_panic]
fn test_invalid_empty_zstr() {
let _ = zstr!("\0");
fn test_invalid_empty_cstr() {
let _ = cstr!("\0");
}
21 changes: 3 additions & 18 deletions src/ffi/mod.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,9 @@
//! Utilities related to FFI bindings.
/// Minimal and unoptimized `strlen` implementation.
///
/// TODO: Optimize this by reading a `usize` at a time.
#[cfg(not(feature = "std"))]
#[allow(unsafe_code)]
unsafe fn strlen(mut s: *const u8) -> usize {
let mut len = 0;
while *s != b'\0' {
len += 1;
s = s.add(1);
}
len
}

#[cfg(not(feature = "std"))]
mod z_str;

pub use alloc::ffi::{CString, NulError};
#[cfg(not(feature = "std"))]
pub use z_str::{FromBytesWithNulError, FromVecWithNulError, NulError, ZStr, ZString};
pub use core::ffi::{CStr, FromBytesWithNulError};

#[cfg(feature = "std")]
pub use std::ffi::{CStr as ZStr, CString as ZString, FromBytesWithNulError, NulError};
pub use std::ffi::{CStr, CString, FromBytesWithNulError, NulError};
Loading

0 comments on commit b437157

Please sign in to comment.