Skip to content

Commit 4f7119c

Browse files
bors[bot]rtzoeller
andauthored
Merge #1583
1583: Remove unsafe in with_nix_path() for [u8] r=asomers a=rtzoeller Remove use of `unsafe` in the implementation of `with_nix_path()` for `[u8]`. This also comes with a nice determinism win across input sizes, and is fairly performance neutral (slightly slower for small strings, much faster for large strings). I suspect the performance degradation in the existing implementation is related to the following note in the `CStr::from_ptr()` documentation: > Note: This operation is intended to be a 0-cost cast but it is currently implemented with an up-front calculation of the length of the string. This is not guaranteed to always be the case. --- Tested with `cargo 1.57.0-nightly (7fbbf4e8f 2021-10-19)`, with variations of the following benchmarking code: ```rs #[bench] fn bench_with_nix_path_1024(b: &mut test::Bencher) { let bytes = std::hint::black_box([70u8; 1024]); b.iter(|| { bytes.with_nix_path(|cstr| { std::hint::black_box(&cstr); }).unwrap(); }) } ``` | Length | Before Change | After Change | |--------|-----------------------|-----------------------| | 16 | 37 ns/iter (+/- 0) | 44 ns/iter (+/- 0) | | 64 | 39 ns/iter (+/- 0) | 44 ns/iter (+/- 0) | | 256 | 84 ns/iter (+/- 0) | 48 ns/iter (+/- 0) | | 1024 | 232 ns/iter (+/- 1) | 50 ns/iter (+/- 1) | | 4095 | 796 ns/iter (+/- 8) | 62 ns/iter (+/- 2) | Co-authored-by: Ryan Zoeller <[email protected]>
2 parents 1dcc582 + 644d36c commit 4f7119c

File tree

1 file changed

+6
-12
lines changed

1 file changed

+6
-12
lines changed

src/lib.rs

+6-12
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,9 @@ pub mod unistd;
161161
*
162162
*/
163163

164-
use libc::{c_char, PATH_MAX};
164+
use libc::PATH_MAX;
165165

166-
use std::{ptr, result};
166+
use std::result;
167167
use std::ffi::{CStr, OsStr};
168168
use std::os::unix::ffi::OsStrExt;
169169
use std::path::{Path, PathBuf};
@@ -267,16 +267,10 @@ impl NixPath for [u8] {
267267
return Err(Errno::ENAMETOOLONG)
268268
}
269269

270-
match self.iter().position(|b| *b == 0) {
271-
Some(_) => Err(Errno::EINVAL),
272-
None => {
273-
unsafe {
274-
// TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
275-
ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
276-
Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
277-
}
278-
279-
}
270+
buf[..self.len()].copy_from_slice(self);
271+
match CStr::from_bytes_with_nul(&buf[..=self.len()]) {
272+
Ok(s) => Ok(f(s)),
273+
Err(_) => Err(Errno::EINVAL),
280274
}
281275
}
282276
}

0 commit comments

Comments
 (0)