strings: implement CappedString::new using CappedString::from_raw_ptr
This patch replaces the logic in `CappedString::new` for copying the string data into a `[MaybeUninit<u8>]` buffer with a call to `CappedString::from_raw_ptr`, which performs the same task.
This commit is contained in:
1 parent
4917be0963
commit
c50b3c7daa
1 file changed
+14
-33
+14
-33
@@ -146,32 +146,20 @@ impl<const N: usize> CappedString<N> {
|
||||
{
|
||||
// Convert the string to a byte slice, which is guaranteed to be valid UTF-8 since this is
|
||||
// an invariant of `str`.
|
||||
let src = <S as AsRef<str>>::as_ref(src).as_bytes();
|
||||
let src = <S as AsRef<str>>::as_ref(src);
|
||||
|
||||
// If the length of the string is greater than `Self::MAX_LEN`, it will not fit in the
|
||||
// buffer so return an error.
|
||||
let len = Self::bound_to_max_len(src.len())
|
||||
.ok_or(CapacityError)?;
|
||||
// If the length of the `src` string does not fit into a `u8` or is greater than
|
||||
// `Self::MAX_LEN`, we can't fit it into the new `CappedString` so return an error.
|
||||
let len = match u8::try_from(src.len()) {
|
||||
Ok(len) if len <= Self::MAX_LEN => len,
|
||||
_ => return Err(CapacityError),
|
||||
};
|
||||
|
||||
// SAFETY:
|
||||
// `MaybeUninit::uninit()` is a valid value for `[MaybeUninit<u8>; N]`, since each element
|
||||
// of the array is allowed to be uninitialised.
|
||||
let mut buf = unsafe { MaybeUninit::<[MaybeUninit<u8>; N]>::uninit().assume_init() };
|
||||
|
||||
let src_ptr = src.as_ptr() as *const MaybeUninit<u8>;
|
||||
|
||||
// SAFETY:
|
||||
// The source and destination to not overlap, since `buf` is a new local variable which is
|
||||
// completely separate from the provided source string `s`. The source is valid for reads of
|
||||
// `len` bytes since `len == src.len()`, and the destination is valid for writes of `len`
|
||||
// bytes since `len <= N`. The source and destination are both trivially properly aligned,
|
||||
// since they both have an alignment of 1.
|
||||
unsafe { ptr::copy_nonoverlapping(src_ptr, buf.as_mut_ptr(), usize::from(len)) }
|
||||
|
||||
// SAFETY:
|
||||
// The first `len` bytes of the buffer are valid UTF-8 because the first `len` bytes of
|
||||
// the buffer contain data copied from a `&str`, and `&str` is always valid UTF-8.
|
||||
unsafe { Ok(Self::from_raw_parts(buf, len)) }
|
||||
// `src.as_ptr()` points to `len` bytes of valid UTF-8 string data since `src` is a `&str`
|
||||
// and `len` is its length. `len` is less than or equal to `Self::MAX_LEN`, which is equal
|
||||
// to `N`.
|
||||
unsafe { Ok(Self::from_raw_ptr(src.as_ptr(), len)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -180,7 +168,9 @@ impl<const N: usize> CappedString<N> {
|
||||
where
|
||||
S: AsRef<str> + ?Sized,
|
||||
{
|
||||
let (src, len) = truncate_str(<S as AsRef<str>>::as_ref(src), Self::MAX_LEN);
|
||||
let src = <S as AsRef<str>>::as_ref(src);
|
||||
|
||||
let (src, len) = truncate_str(src, Self::MAX_LEN);
|
||||
|
||||
// SAFETY:
|
||||
// It is part of the contract of `truncate_str` that it returns a pointer to a valid UTF-8
|
||||
@@ -189,15 +179,6 @@ impl<const N: usize> CappedString<N> {
|
||||
unsafe { Self::from_raw_ptr(src, len) }
|
||||
}
|
||||
|
||||
/// Returns the length as a `u8` if it is less than or equal to `Self::MAX_LEN` (which is the
|
||||
/// `u8` representation of `N`). Otherwise, returns `None`.
|
||||
#[inline]
|
||||
fn bound_to_max_len(len: usize) -> Option<u8> {
|
||||
u8::try_from(len)
|
||||
.ok()
|
||||
.and_then(|len| (len <= Self::MAX_LEN).then_some(len))
|
||||
}
|
||||
|
||||
pub fn push(&mut self, c: char) -> Result<(), CapacityError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user