Files
arrayvec/src/array_string.rs
T
2021-03-23 18:22:12 +01:00

586 lines
16 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use std::borrow::Borrow;
use std::cmp;
use std::convert::TryFrom;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem::MaybeUninit;
use std::ops::{Deref, DerefMut};
use std::ptr;
use std::slice;
use std::str;
use std::str::FromStr;
use std::str::Utf8Error;
use crate::CapacityError;
use crate::char::encode_utf8;
#[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.
///
/// The string is a contiguous value that you can store directly on the stack
/// if needed.
#[derive(Copy)]
pub struct ArrayString<const CAP: usize> {
// the `len` first elements of the array are initialized
xs: [MaybeUninit<u8>; CAP],
len: usize,
}
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);
/// ```
#[cfg(not(feature="unstable-const-fn"))]
pub fn new() -> ArrayString<CAP> {
unsafe {
ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 }
}
}
#[cfg(feature="unstable-const-fn")]
pub const fn new() -> ArrayString<CAP> {
unsafe {
ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 }
}
}
/// Return the length of the string.
#[inline]
pub fn len(&self) -> usize { self.len }
/// Returns whether the string is empty.
#[inline]
pub fn 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);
/// ```
pub fn from(s: &str) -> Result<Self, CapacityError<&str>> {
let mut 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();
/// ```
pub fn from_byte_string(b: &[u8; CAP]) -> Result<Self, Utf8Error> {
let len = str::from_utf8(b)?.len();
debug_assert_eq!(len, CAP);
let mut 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)
}
/// Return the capacity of the `ArrayString`.
///
/// ```
/// use arrayvec::ArrayString;
///
/// let string = ArrayString::<3>::new();
/// assert_eq!(string.capacity(), 3);
/// ```
#[inline(always)]
pub fn 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());
/// ```
pub fn is_full(&self) -> bool { self.len() == self.capacity() }
/// 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");
/// ```
pub fn push(&mut self, 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');
/// ```
pub fn try_push(&mut self, 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");
/// ```
pub fn push_str(&mut self, 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");
/// ```
pub fn 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);
/// ```
pub fn pop(&mut self) -> Option<char> {
let ch = match self.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 strings 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");
/// ```
pub fn truncate(&mut self, 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');
/// ```
pub fn remove(&mut self, idx: usize) -> char {
let ch = match self[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();
unsafe {
ptr::copy(self.as_ptr().add(next),
self.as_mut_ptr().add(idx),
len - next);
self.set_len(len - (next - idx));
}
ch
}
/// Make the string empty.
pub fn clear(&mut self) {
unsafe {
self.set_len(0);
}
}
/// Set the stringss 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.
pub unsafe fn set_len(&mut self, length: usize) {
debug_assert!(length <= self.capacity());
self.len = length;
}
/// Return a string slice of the whole `ArrayString`.
pub fn as_str(&self) -> &str {
self
}
fn as_ptr(&self) -> *const u8 {
self.xs.as_ptr() as *const u8
}
fn as_mut_ptr(&mut self) -> *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(&mut self) -> &mut str {
unsafe {
let sl = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len);
str::from_utf8_unchecked_mut(sl)
}
}
}
impl<const CAP: usize> PartialEq for ArrayString<CAP>
{
fn eq(&self, rhs: &Self) -> bool {
**self == **rhs
}
}
impl<const CAP: usize> PartialEq<str> for ArrayString<CAP>
{
fn eq(&self, rhs: &str) -> bool {
&**self == rhs
}
}
impl<const CAP: usize> PartialEq<ArrayString<CAP>> for str
{
fn eq(&self, rhs: &ArrayString<CAP>) -> bool {
self == &**rhs
}
}
impl<const CAP: usize> Eq for ArrayString<CAP>
{ }
impl<const CAP: usize> Hash for ArrayString<CAP>
{
fn hash<H: Hasher>(&self, h: &mut H) {
(**self).hash(h)
}
}
impl<const CAP: usize> Borrow<str> for ArrayString<CAP>
{
fn borrow(&self) -> &str { self }
}
impl<const CAP: usize> AsRef<str> for ArrayString<CAP>
{
fn as_ref(&self) -> &str { self }
}
impl<const CAP: usize> fmt::Debug for ArrayString<CAP>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
}
impl<const CAP: usize> fmt::Display for ArrayString<CAP>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
}
/// `Write` appends written data to the end of the string.
impl<const CAP: usize> fmt::Write for ArrayString<CAP>
{
fn write_char(&mut self, c: char) -> fmt::Result {
self.try_push(c).map_err(|_| fmt::Error)
}
fn write_str(&mut self, s: &str) -> fmt::Result {
self.try_push_str(s).map_err(|_| fmt::Error)
}
}
impl<const CAP: usize> Clone for ArrayString<CAP>
{
fn clone(&self) -> ArrayString<CAP> {
*self
}
fn clone_from(&mut self, rhs: &Self) {
// guaranteed to fit due to types matching.
self.clear();
self.try_push_str(rhs).ok();
}
}
impl<const CAP: usize> PartialOrd for ArrayString<CAP>
{
fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> {
(**self).partial_cmp(&**rhs)
}
fn lt(&self, rhs: &Self) -> bool { **self < **rhs }
fn le(&self, rhs: &Self) -> bool { **self <= **rhs }
fn gt(&self, rhs: &Self) -> bool { **self > **rhs }
fn ge(&self, rhs: &Self) -> bool { **self >= **rhs }
}
impl<const CAP: usize> PartialOrd<str> for ArrayString<CAP>
{
fn partial_cmp(&self, rhs: &str) -> Option<cmp::Ordering> {
(**self).partial_cmp(rhs)
}
fn lt(&self, rhs: &str) -> bool { &**self < rhs }
fn le(&self, rhs: &str) -> bool { &**self <= rhs }
fn gt(&self, rhs: &str) -> bool { &**self > rhs }
fn ge(&self, rhs: &str) -> bool { &**self >= rhs }
}
impl<const CAP: usize> PartialOrd<ArrayString<CAP>> for str
{
fn partial_cmp(&self, rhs: &ArrayString<CAP>) -> Option<cmp::Ordering> {
self.partial_cmp(&**rhs)
}
fn lt(&self, rhs: &ArrayString<CAP>) -> bool { self < &**rhs }
fn le(&self, rhs: &ArrayString<CAP>) -> bool { self <= &**rhs }
fn gt(&self, rhs: &ArrayString<CAP>) -> bool { self > &**rhs }
fn ge(&self, rhs: &ArrayString<CAP>) -> bool { self >= &**rhs }
}
impl<const CAP: usize> Ord for ArrayString<CAP>
{
fn cmp(&self, rhs: &Self) -> cmp::Ordering {
(**self).cmp(&**rhs)
}
}
impl<const CAP: usize> FromStr for ArrayString<CAP>
{
type Err = CapacityError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::from(s).map_err(CapacityError::simplify)
}
}
#[cfg(feature="serde")]
/// Requires crate feature `"serde"`
impl<const CAP: usize> Serialize for ArrayString<CAP>
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_str(&*self)
}
}
#[cfg(feature="serde")]
/// Requires crate feature `"serde"`
impl<'de, const CAP: usize> Deserialize<'de> for ArrayString<CAP>
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>
{
use serde::de::{self, Visitor};
use std::marker::PhantomData;
struct ArrayStringVisitor<const CAP: usize>(PhantomData<[u8; CAP]>);
impl<'de, const CAP: usize> Visitor<'de> for ArrayStringVisitor<CAP> {
type Value = ArrayString<CAP>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a string no more than {} bytes long", CAP)
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: de::Error,
{
ArrayString::from(v).map_err(|_| E::invalid_length(v.len(), &self))
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where E: de::Error,
{
let s = str::from_utf8(v).map_err(|_| E::invalid_value(de::Unexpected::Bytes(v), &self))?;
ArrayString::from(s).map_err(|_| E::invalid_length(s.len(), &self))
}
}
deserializer.deserialize_str(ArrayStringVisitor(PhantomData))
}
}
impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString<CAP>
{
type Error = CapacityError<&'a str>;
fn try_from(f: &'a str) -> Result<Self, Self::Error> {
let mut v = Self::new();
v.try_push_str(f)?;
Ok(v)
}
}
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;
let mut v = Self::new();
v.write_fmt(f).map_err(|e| CapacityError::new(e))?;
Ok(v)
}
}