use std::borrow::{Borrow, BorrowMut}; use std::cmp; use std::convert::TryFrom; use std::fmt; use std::hash::{Hash, Hasher}; use std::mem::MaybeUninit; use std::ops::{Deref, DerefMut}; #[cfg(feature="std")] use std::path::Path; use std::ptr; use std::slice; use std::str; use std::str::FromStr; use std::str::Utf8Error;
#[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer};
/// A string with a fixed capacity. /// /// The `ArrayString` is a string backed by a fixed size array. It keeps track /// of its length, and is parameterized by `CAP` for the maximum capacity. /// /// `CAP` is of type `usize` but is range limited to `u32::MAX`; attempting to create larger /// arrayvecs with larger capacity will panic. /// /// The string is a contiguous value that you can store directly on the stack /// if needed. #[derive(Copy)] #[repr(C)] pubstruct ArrayString<const CAP: usize> { // the `len` first elements of the array are initialized
len: LenUint,
xs: [MaybeUninit<u8>; CAP],
}
impl<const CAP: usize> Default for ArrayString<CAP>
{ /// Return an empty `ArrayString` fn default() -> ArrayString<CAP> {
ArrayString::new()
}
}
impl<const CAP: usize> ArrayString<CAP>
{ /// Create a new empty `ArrayString`. /// /// Capacity is inferred from the type parameter. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<16>::new(); /// string.push_str("foo"); /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.capacity(), 16); /// ``` pubfn new() -> ArrayString<CAP> {
assert_capacity_limit!(CAP); unsafe {
ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 }
}
}
/// Create a new empty `ArrayString` (const fn). /// /// Capacity is inferred from the type parameter. /// /// ``` /// use arrayvec::ArrayString; /// /// static ARRAY: ArrayString<1024> = ArrayString::new_const(); /// ``` pubconstfn new_const() -> ArrayString<CAP> {
assert_capacity_limit_const!(CAP);
ArrayString { xs: MakeMaybeUninit::ARRAY, len: 0 }
}
/// Return the length of the string. #[inline] pubconstfn len(&self) -> usize { self.len as usize }
/// Returns whether the string is empty. #[inline] pubconstfn is_empty(&self) -> bool { self.len() == 0 }
/// Create a new `ArrayString` from a `str`. /// /// Capacity is inferred from the type parameter. /// /// **Errors** if the backing array is not large enough to fit the string. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<3>::from("foo").unwrap(); /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.len(), 3); /// assert_eq!(string.capacity(), 3); /// ``` pubfn from(s: &str) -> Result<Self, CapacityError<&str>> { letmut arraystr = Self::new();
arraystr.try_push_str(s)?;
Ok(arraystr)
}
/// Create a new `ArrayString` from a byte string literal. /// /// **Errors** if the byte string literal is not valid UTF-8. /// /// ``` /// use arrayvec::ArrayString; /// /// let string = ArrayString::from_byte_string(b"hello world").unwrap(); /// ``` pubfn from_byte_string(b: &[u8; CAP]) -> Result<Self, Utf8Error> { let len = str::from_utf8(b)?.len();
debug_assert_eq!(len, CAP); letmut vec = Self::new(); unsafe {
(b as *const [u8; CAP] as *const [MaybeUninit<u8>; CAP])
.copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit<u8>; CAP], 1);
vec.set_len(CAP);
}
Ok(vec)
}
/// Create a new `ArrayString` value fully filled with ASCII NULL characters (`\0`). Useful /// to be used as a buffer to collect external data or as a buffer for intermediate processing. /// /// ``` /// use arrayvec::ArrayString; /// /// let string = ArrayString::<16>::zero_filled(); /// assert_eq!(string.len(), 16); /// ``` #[inline] pubfn zero_filled() -> Self {
assert_capacity_limit!(CAP); // SAFETY: `assert_capacity_limit` asserts that `len` won't overflow and // `zeroed` fully fills the array with nulls. unsafe {
ArrayString {
xs: MaybeUninit::zeroed().assume_init(),
len: CAP as _
}
}
}
/// Return the capacity of the `ArrayString`. /// /// ``` /// use arrayvec::ArrayString; /// /// let string = ArrayString::<3>::new(); /// assert_eq!(string.capacity(), 3); /// ``` #[inline(always)] pubconstfn capacity(&self) -> usize { CAP }
/// Return if the `ArrayString` is completely filled. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<1>::new(); /// assert!(!string.is_full()); /// string.push_str("A"); /// assert!(string.is_full()); /// ``` pubconstfn is_full(&self) -> bool { self.len() == self.capacity() }
/// Returns the capacity left in the `ArrayString`. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<3>::from("abc").unwrap(); /// string.pop(); /// assert_eq!(string.remaining_capacity(), 1); /// ``` pubconstfn remaining_capacity(&self) -> usize { self.capacity() - self.len()
}
/// Adds the given char to the end of the string. /// /// ***Panics*** if the backing array is not large enough to fit the additional char. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<2>::new(); /// /// string.push('a'); /// string.push('b'); /// /// assert_eq!(&string[..], "ab"); /// ``` #[track_caller] pubfn push(&mutself, c: char) { self.try_push(c).unwrap();
}
/// Adds the given char to the end of the string. /// /// Returns `Ok` if the push succeeds. /// /// **Errors** if the backing array is not large enough to fit the additional char. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<2>::new(); /// /// string.try_push('a').unwrap(); /// string.try_push('b').unwrap(); /// let overflow = string.try_push('c'); /// /// assert_eq!(&string[..], "ab"); /// assert_eq!(overflow.unwrap_err().element(), 'c'); /// ``` pubfn try_push(&mutself, c: char) -> Result<(), CapacityError<char>> { let len = self.len(); unsafe { let ptr = self.as_mut_ptr().add(len); let remaining_cap = self.capacity() - len; match encode_utf8(c, ptr, remaining_cap) {
Ok(n) => { self.set_len(len + n);
Ok(())
}
Err(_) => Err(CapacityError::new(c)),
}
}
}
/// Adds the given string slice to the end of the string. /// /// ***Panics*** if the backing array is not large enough to fit the string. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<2>::new(); /// /// string.push_str("a"); /// string.push_str("d"); /// /// assert_eq!(&string[..], "ad"); /// ``` #[track_caller] pubfn push_str(&mutself, s: &str) { self.try_push_str(s).unwrap()
}
/// Adds the given string slice to the end of the string. /// /// Returns `Ok` if the push succeeds. /// /// **Errors** if the backing array is not large enough to fit the string. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<2>::new(); /// /// string.try_push_str("a").unwrap(); /// let overflow1 = string.try_push_str("bc"); /// string.try_push_str("d").unwrap(); /// let overflow2 = string.try_push_str("ef"); /// /// assert_eq!(&string[..], "ad"); /// assert_eq!(overflow1.unwrap_err().element(), "bc"); /// assert_eq!(overflow2.unwrap_err().element(), "ef"); /// ``` pubfn try_push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> { if s.len() > self.capacity() - self.len() { return Err(CapacityError::new(s));
} unsafe { let dst = self.as_mut_ptr().add(self.len()); let src = s.as_ptr();
ptr::copy_nonoverlapping(src, dst, s.len()); let newl = self.len() + s.len(); self.set_len(newl);
}
Ok(())
}
/// Removes the last character from the string and returns it. /// /// Returns `None` if this `ArrayString` is empty. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.pop(), Some('o')); /// assert_eq!(s.pop(), Some('o')); /// assert_eq!(s.pop(), Some('f')); /// /// assert_eq!(s.pop(), None); /// ``` pubfn pop(&mutself) -> Option<char> { let ch = matchself.chars().rev().next() {
Some(ch) => ch,
None => return None,
}; let new_len = self.len() - ch.len_utf8(); unsafe { self.set_len(new_len);
}
Some(ch)
}
/// Shortens this `ArrayString` to the specified length. /// /// If `new_len` is greater than the string’s current length, this has no /// effect. /// /// ***Panics*** if `new_len` does not lie on a `char` boundary. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<6>::from("foobar").unwrap(); /// string.truncate(3); /// assert_eq!(&string[..], "foo"); /// string.truncate(4); /// assert_eq!(&string[..], "foo"); /// ``` pubfn truncate(&mutself, new_len: usize) { if new_len <= self.len() {
assert!(self.is_char_boundary(new_len)); unsafe { // In libstd truncate is called on the underlying vector, // which in turns drops each element. // As we know we don't have to worry about Drop, // we can just set the length (a la clear.) self.set_len(new_len);
}
}
}
/// Removes a `char` from this `ArrayString` at a byte position and returns it. /// /// This is an `O(n)` operation, as it requires copying every element in the /// array. /// /// ***Panics*** if `idx` is larger than or equal to the `ArrayString`’s length, /// or if it does not lie on a `char` boundary. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.remove(0), 'f'); /// assert_eq!(s.remove(1), 'o'); /// assert_eq!(s.remove(0), 'o'); /// ``` pubfn remove(&mutself, idx: usize) -> char { let ch = matchself[idx..].chars().next() {
Some(ch) => ch,
None => panic!("cannot remove a char from the end of a string"),
};
let next = idx + ch.len_utf8(); let len = self.len(); let ptr = self.as_mut_ptr(); unsafe {
ptr::copy(
ptr.add(next),
ptr.add(idx),
len - next); self.set_len(len - (next - idx));
}
ch
}
/// Make the string empty. pubfn clear(&mutself) { unsafe { self.set_len(0);
}
}
/// Set the strings’s length. /// /// This function is `unsafe` because it changes the notion of the /// number of “valid” bytes in the string. Use with care. /// /// This method uses *debug assertions* to check the validity of `length` /// and may use other debug assertions. pubunsafefn set_len(&mutself, length: usize) { // type invariant that capacity always fits in LenUint
debug_assert!(length <= self.capacity()); self.len = length as LenUint;
}
/// Return a string slice of the whole `ArrayString`. pubfn as_str(&self) -> &str { self
}
/// Return a mutable string slice of the whole `ArrayString`. pubfn as_mut_str(&mutself) -> &mut str { self
}
/// Return a raw pointer to the string's buffer. pubfn as_ptr(&self) -> *const u8 { self.xs.as_ptr() as *const u8
}
/// Return a raw mutable pointer to the string's buffer. pubfn as_mut_ptr(&mutself) -> *mut u8 { self.xs.as_mut_ptr() as *mut u8
}
}
impl<const CAP: usize> Deref for ArrayString<CAP>
{ type Target = str; #[inline] fn deref(&self) -> &str { unsafe { let sl = slice::from_raw_parts(self.as_ptr(), self.len());
str::from_utf8_unchecked(sl)
}
}
}
impl<const CAP: usize> DerefMut for ArrayString<CAP>
{ #[inline] fn deref_mut(&mutself) -> &mut str { unsafe { let len = self.len(); let sl = slice::from_raw_parts_mut(self.as_mut_ptr(), len);
str::from_utf8_unchecked_mut(sl)
}
}
}
/// `Write` appends written data to the end of the string. impl<const CAP: usize> fmt::Write for ArrayString<CAP>
{ fn write_char(&mutself, c: char) -> fmt::Result { self.try_push(c).map_err(|_| fmt::Error)
}
#[cfg(feature = "borsh")] /// Requires crate feature `"borsh"` impl<const CAP: usize> borsh::BorshDeserialize for ArrayString<CAP> { fn deserialize_reader<R: borsh::io::Read>(reader: &mut R) -> borsh::io::Result<Self> { let len = <u32 as borsh::BorshDeserialize>::deserialize_reader(reader)? as usize; if len > CAP { return Err(borsh::io::Error::new(
borsh::io::ErrorKind::InvalidData,
format!("Expected a string no more than {} bytes long", CAP),
))
}
impl<'a, const CAP: usize> TryFrom<fmt::Arguments<'a>> for ArrayString<CAP>
{ type Error = CapacityError<fmt::Error>;
fn try_from(f: fmt::Arguments<'a>) -> Result<Self, Self::Error> { use fmt::Write; letmut v = Self::new();
v.write_fmt(f).map_err(|e| CapacityError::new(e))?;
Ok(v)
}
}
#[cfg(feature = "zeroize")] /// "Best efforts" zeroing of the `ArrayString`'s buffer when the `zeroize` feature is enabled. /// /// The length is set to 0, and the buffer is dropped and zeroized. /// Cannot ensure that previous moves of the `ArrayString` did not leave values on the stack. /// /// ``` /// use arrayvec::ArrayString; /// use zeroize::Zeroize; /// let mut string = ArrayString::<6>::from("foobar").unwrap(); /// string.zeroize(); /// assert_eq!(string.len(), 0); /// unsafe { string.set_len(string.capacity()) }; /// assert_eq!(&*string, "\0\0\0\0\0\0"); /// ``` impl<const CAP: usize> zeroize::Zeroize for ArrayString<CAP> { fn zeroize(&mutself) { // There are no elements to drop self.clear(); // Zeroize the backing array. self.xs.zeroize();
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.