Skip to content

Commit 60274a9

Browse files
Added From<Vec<NonZeroU8>> for CString
Updated tracking issue number Added safeguards for transmute_vec potentially being factored out elsewhere Clarified comment about avoiding mem::forget Removed unneeded unstable guard Added back a stability annotation for CI Minor documentation improvements Thanks to @Centril's code review Co-Authored-By: Mazdak Farrokhzad <[email protected]> Improved layout checks, type annotations and removed unaccurate comment Removed unnecessary check on array layout Adapt the stability annotation to the new 1.41 milestone Co-Authored-By: Mazdak Farrokhzad <[email protected]> Simplify the implementation. Use `Vec::into_raw_parts` instead of a manual implementation of `Vec::transmute`. If `Vec::into_raw_parts` uses `NonNull` instead, then the code here will need to be adjusted to take it into account (issue rust-lang#65816) Reduce the whitespace of safety comments
1 parent 41501a6 commit 60274a9

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

src/libstd/ffi/c_str.rs

+27
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::fmt::{self, Write};
66
use crate::io;
77
use crate::mem;
88
use crate::memchr;
9+
use crate::num::NonZeroU8;
910
use crate::ops;
1011
use crate::os::raw::c_char;
1112
use crate::ptr;
@@ -741,6 +742,32 @@ impl From<Box<CStr>> for CString {
741742
}
742743
}
743744

745+
#[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")]
746+
impl From<Vec<NonZeroU8>> for CString {
747+
/// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without
748+
/// copying nor checking for inner null bytes.
749+
///
750+
/// [`CString`]: ../ffi/struct.CString.html
751+
/// [`NonZeroU8`]: ../num/struct.NonZeroU8.html
752+
/// [`Vec`]: ../vec/struct.Vec.html
753+
#[inline]
754+
fn from(v: Vec<NonZeroU8>) -> CString {
755+
unsafe {
756+
// Transmute `Vec<NonZeroU8>` to `Vec<u8>`.
757+
let v: Vec<u8> = {
758+
// Safety:
759+
// - transmuting between `NonZeroU8` and `u8` is sound;
760+
// - `alloc::Layout<NonZeroU8> == alloc::Layout<u8>`.
761+
let (ptr, len, cap): (*mut NonZeroU8, _, _) = Vec::into_raw_parts(v);
762+
Vec::from_raw_parts(ptr.cast::<u8>(), len, cap)
763+
};
764+
// Safety: `v` cannot contain null bytes, given the type-level
765+
// invariant of `NonZeroU8`.
766+
CString::from_vec_unchecked(v)
767+
}
768+
}
769+
}
770+
744771
#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
745772
impl Clone for Box<CStr> {
746773
#[inline]

src/libstd/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@
310310
#![feature(unboxed_closures)]
311311
#![feature(untagged_unions)]
312312
#![feature(unwind_attributes)]
313+
#![feature(vec_into_raw_parts)]
313314
// NB: the above list is sorted to minimize merge conflicts.
314315
#![default_lib_allocator]
315316

0 commit comments

Comments
 (0)