Skip to content

Commit

Permalink
Added From<Vec<NonZeroU8>> for CString
Browse files Browse the repository at this point in the history
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 <twingoow@gmail.com>

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 <twingoow@gmail.com>

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 #65816)

Reduce the whitespace of safety comments
  • Loading branch information
danielhenrymantilla committed Feb 4, 2020
1 parent 41501a6 commit 60274a9
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/libstd/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::fmt::{self, Write};
use crate::io;
use crate::mem;
use crate::memchr;
use crate::num::NonZeroU8;
use crate::ops;
use crate::os::raw::c_char;
use crate::ptr;
Expand Down Expand Up @@ -741,6 +742,32 @@ impl From<Box<CStr>> for CString {
}
}

#[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")]
impl From<Vec<NonZeroU8>> for CString {
/// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without
/// copying nor checking for inner null bytes.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`NonZeroU8`]: ../num/struct.NonZeroU8.html
/// [`Vec`]: ../vec/struct.Vec.html
#[inline]
fn from(v: Vec<NonZeroU8>) -> CString {
unsafe {
// Transmute `Vec<NonZeroU8>` to `Vec<u8>`.
let v: Vec<u8> = {
// Safety:
// - transmuting between `NonZeroU8` and `u8` is sound;
// - `alloc::Layout<NonZeroU8> == alloc::Layout<u8>`.
let (ptr, len, cap): (*mut NonZeroU8, _, _) = Vec::into_raw_parts(v);
Vec::from_raw_parts(ptr.cast::<u8>(), len, cap)
};
// Safety: `v` cannot contain null bytes, given the type-level
// invariant of `NonZeroU8`.
CString::from_vec_unchecked(v)
}
}
}

#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
impl Clone for Box<CStr> {
#[inline]
Expand Down
1 change: 1 addition & 0 deletions src/libstd/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@
#![feature(unboxed_closures)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(vec_into_raw_parts)]
// NB: the above list is sorted to minimize merge conflicts.
#![default_lib_allocator]

Expand Down

0 comments on commit 60274a9

Please sign in to comment.