arrayvec/
array_string.rs

1use std::borrow::Borrow;
2use std::cmp;
3use std::fmt;
4use std::hash::{Hash, Hasher};
5use std::ptr;
6use std::ops::{Deref, DerefMut};
7use std::str;
8use std::str::FromStr;
9use std::str::Utf8Error;
10use std::slice;
11
12use crate::array::Array;
13use crate::array::Index;
14use crate::CapacityError;
15use crate::char::encode_utf8;
16
17#[cfg(feature="serde")]
18use serde::{Serialize, Deserialize, Serializer, Deserializer};
19
20use super::MaybeUninit as MaybeUninitCopy;
21
22/// A string with a fixed capacity.
23///
24/// The `ArrayString` is a string backed by a fixed size array. It keeps track
25/// of its length.
26///
27/// The string is a contiguous value that you can store directly on the stack
28/// if needed.
29#[derive(Copy)]
30pub struct ArrayString<A>
31    where A: Array<Item=u8> + Copy
32{
33    xs: MaybeUninitCopy<A>,
34    len: A::Index,
35}
36
37impl<A> Default for ArrayString<A>
38    where A: Array<Item=u8> + Copy
39{
40    /// Return an empty `ArrayString`
41    fn default() -> ArrayString<A> {
42        ArrayString::new()
43    }
44}
45
46impl<A> ArrayString<A>
47    where A: Array<Item=u8> + Copy
48{
49    /// Create a new empty `ArrayString`.
50    ///
51    /// Capacity is inferred from the type parameter.
52    ///
53    /// ```
54    /// use arrayvec::ArrayString;
55    ///
56    /// let mut string = ArrayString::<[_; 16]>::new();
57    /// string.push_str("foo");
58    /// assert_eq!(&string[..], "foo");
59    /// assert_eq!(string.capacity(), 16);
60    /// ```
61    #[cfg(not(feature="unstable-const-fn"))]
62    pub fn new() -> ArrayString<A> {
63        unsafe {
64            ArrayString {
65                xs: MaybeUninitCopy::uninitialized(),
66                len: Index::ZERO,
67            }
68        }
69    }
70
71    #[cfg(feature="unstable-const-fn")]
72    pub const fn new() -> ArrayString<A> {
73        unsafe {
74            ArrayString {
75                xs: MaybeUninitCopy::uninitialized(),
76                len: Index::ZERO,
77            }
78        }
79    }
80
81    /// Return the length of the string.
82    #[inline]
83    pub fn len(&self) -> usize { self.len.to_usize() }
84
85    /// Returns whether the string is empty.
86    #[inline]
87    pub fn is_empty(&self) -> bool { self.len() == 0 }
88
89    /// Create a new `ArrayString` from a `str`.
90    ///
91    /// Capacity is inferred from the type parameter.
92    ///
93    /// **Errors** if the backing array is not large enough to fit the string.
94    ///
95    /// ```
96    /// use arrayvec::ArrayString;
97    ///
98    /// let mut string = ArrayString::<[_; 3]>::from("foo").unwrap();
99    /// assert_eq!(&string[..], "foo");
100    /// assert_eq!(string.len(), 3);
101    /// assert_eq!(string.capacity(), 3);
102    /// ```
103    pub fn from(s: &str) -> Result<Self, CapacityError<&str>> {
104        let mut arraystr = Self::new();
105        arraystr.try_push_str(s)?;
106        Ok(arraystr)
107    }
108
109    /// Create a new `ArrayString` from a byte string literal.
110    ///
111    /// **Errors** if the byte string literal is not valid UTF-8.
112    ///
113    /// ```
114    /// use arrayvec::ArrayString;
115    ///
116    /// let string = ArrayString::from_byte_string(b"hello world").unwrap();
117    /// ```
118    pub fn from_byte_string(b: &A) -> Result<Self, Utf8Error> {
119        let len = str::from_utf8(b.as_slice())?.len();
120        debug_assert_eq!(len, A::CAPACITY);
121        Ok(ArrayString {
122            xs: MaybeUninitCopy::from(*b),
123            len: Index::from(A::CAPACITY),
124        })
125    }
126
127    /// Return the capacity of the `ArrayString`.
128    ///
129    /// ```
130    /// use arrayvec::ArrayString;
131    ///
132    /// let string = ArrayString::<[_; 3]>::new();
133    /// assert_eq!(string.capacity(), 3);
134    /// ```
135    #[inline(always)]
136    pub fn capacity(&self) -> usize { A::CAPACITY }
137
138    /// Return if the `ArrayString` is completely filled.
139    ///
140    /// ```
141    /// use arrayvec::ArrayString;
142    ///
143    /// let mut string = ArrayString::<[_; 1]>::new();
144    /// assert!(!string.is_full());
145    /// string.push_str("A");
146    /// assert!(string.is_full());
147    /// ```
148    pub fn is_full(&self) -> bool { self.len() == self.capacity() }
149
150    /// Adds the given char to the end of the string.
151    ///
152    /// ***Panics*** if the backing array is not large enough to fit the additional char.
153    ///
154    /// ```
155    /// use arrayvec::ArrayString;
156    ///
157    /// let mut string = ArrayString::<[_; 2]>::new();
158    ///
159    /// string.push('a');
160    /// string.push('b');
161    ///
162    /// assert_eq!(&string[..], "ab");
163    /// ```
164    pub fn push(&mut self, c: char) {
165        self.try_push(c).unwrap();
166    }
167
168    /// Adds the given char to the end of the string.
169    ///
170    /// Returns `Ok` if the push succeeds.
171    ///
172    /// **Errors** if the backing array is not large enough to fit the additional char.
173    ///
174    /// ```
175    /// use arrayvec::ArrayString;
176    ///
177    /// let mut string = ArrayString::<[_; 2]>::new();
178    ///
179    /// string.try_push('a').unwrap();
180    /// string.try_push('b').unwrap();
181    /// let overflow = string.try_push('c');
182    ///
183    /// assert_eq!(&string[..], "ab");
184    /// assert_eq!(overflow.unwrap_err().element(), 'c');
185    /// ```
186    pub fn try_push(&mut self, c: char) -> Result<(), CapacityError<char>> {
187        let len = self.len();
188        unsafe {
189            let ptr = self.xs.ptr_mut().add(len);
190            let remaining_cap = self.capacity() - len;
191            match encode_utf8(c, ptr, remaining_cap) {
192                Ok(n) => {
193                    self.set_len(len + n);
194                    Ok(())
195                }
196                Err(_) => Err(CapacityError::new(c)),
197            }
198        }
199    }
200
201    /// Adds the given string slice to the end of the string.
202    ///
203    /// ***Panics*** if the backing array is not large enough to fit the string.
204    ///
205    /// ```
206    /// use arrayvec::ArrayString;
207    ///
208    /// let mut string = ArrayString::<[_; 2]>::new();
209    ///
210    /// string.push_str("a");
211    /// string.push_str("d");
212    ///
213    /// assert_eq!(&string[..], "ad");
214    /// ```
215    pub fn push_str(&mut self, s: &str) {
216        self.try_push_str(s).unwrap()
217    }
218
219    /// Adds the given string slice to the end of the string.
220    ///
221    /// Returns `Ok` if the push succeeds.
222    ///
223    /// **Errors** if the backing array is not large enough to fit the string.
224    ///
225    /// ```
226    /// use arrayvec::ArrayString;
227    ///
228    /// let mut string = ArrayString::<[_; 2]>::new();
229    ///
230    /// string.try_push_str("a").unwrap();
231    /// let overflow1 = string.try_push_str("bc");
232    /// string.try_push_str("d").unwrap();
233    /// let overflow2 = string.try_push_str("ef");
234    ///
235    /// assert_eq!(&string[..], "ad");
236    /// assert_eq!(overflow1.unwrap_err().element(), "bc");
237    /// assert_eq!(overflow2.unwrap_err().element(), "ef");
238    /// ```
239    pub fn try_push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> {
240        if s.len() > self.capacity() - self.len() {
241            return Err(CapacityError::new(s));
242        }
243        unsafe {
244            let dst = self.xs.ptr_mut().add(self.len());
245            let src = s.as_ptr();
246            ptr::copy_nonoverlapping(src, dst, s.len());
247            let newl = self.len() + s.len();
248            self.set_len(newl);
249        }
250        Ok(())
251    }
252
253    /// Removes the last character from the string and returns it.
254    ///
255    /// Returns `None` if this `ArrayString` is empty.
256    ///
257    /// ```
258    /// use arrayvec::ArrayString;
259    /// 
260    /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap();
261    ///
262    /// assert_eq!(s.pop(), Some('o'));
263    /// assert_eq!(s.pop(), Some('o'));
264    /// assert_eq!(s.pop(), Some('f'));
265    ///
266    /// assert_eq!(s.pop(), None);
267    /// ```
268    pub fn pop(&mut self) -> Option<char> {
269        let ch = match self.chars().rev().next() {
270            Some(ch) => ch,
271            None => return None,
272        };
273        let new_len = self.len() - ch.len_utf8();
274        unsafe {
275            self.set_len(new_len);
276        }
277        Some(ch)
278    }
279
280    /// Shortens this `ArrayString` to the specified length.
281    ///
282    /// If `new_len` is greater than the string’s current length, this has no
283    /// effect.
284    ///
285    /// ***Panics*** if `new_len` does not lie on a `char` boundary.
286    ///
287    /// ```
288    /// use arrayvec::ArrayString;
289    ///
290    /// let mut string = ArrayString::<[_; 6]>::from("foobar").unwrap();
291    /// string.truncate(3);
292    /// assert_eq!(&string[..], "foo");
293    /// string.truncate(4);
294    /// assert_eq!(&string[..], "foo");
295    /// ```
296    pub fn truncate(&mut self, new_len: usize) {
297        if new_len <= self.len() {
298            assert!(self.is_char_boundary(new_len));
299            unsafe { 
300                // In libstd truncate is called on the underlying vector,
301                // which in turns drops each element.
302                // As we know we don't have to worry about Drop,
303                // we can just set the length (a la clear.)
304                self.set_len(new_len);
305            }
306        }
307    }
308
309    /// Removes a `char` from this `ArrayString` at a byte position and returns it.
310    ///
311    /// This is an `O(n)` operation, as it requires copying every element in the
312    /// array.
313    ///
314    /// ***Panics*** if `idx` is larger than or equal to the `ArrayString`’s length,
315    /// or if it does not lie on a `char` boundary.
316    ///
317    /// ```
318    /// use arrayvec::ArrayString;
319    /// 
320    /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap();
321    ///
322    /// assert_eq!(s.remove(0), 'f');
323    /// assert_eq!(s.remove(1), 'o');
324    /// assert_eq!(s.remove(0), 'o');
325    /// ```
326    pub fn remove(&mut self, idx: usize) -> char {
327        let ch = match self[idx..].chars().next() {
328            Some(ch) => ch,
329            None => panic!("cannot remove a char from the end of a string"),
330        };
331
332        let next = idx + ch.len_utf8();
333        let len = self.len();
334        unsafe {
335            ptr::copy(self.xs.ptr().add(next),
336                      self.xs.ptr_mut().add(idx),
337                      len - next);
338            self.set_len(len - (next - idx));
339        }
340        ch
341    }
342
343    /// Make the string empty.
344    pub fn clear(&mut self) {
345        unsafe {
346            self.set_len(0);
347        }
348    }
349
350    /// Set the strings’s length.
351    ///
352    /// This function is `unsafe` because it changes the notion of the
353    /// number of “valid” bytes in the string. Use with care.
354    ///
355    /// This method uses *debug assertions* to check the validity of `length`
356    /// and may use other debug assertions.
357    pub unsafe fn set_len(&mut self, length: usize) {
358        debug_assert!(length <= self.capacity());
359        self.len = Index::from(length);
360    }
361
362    /// Return a string slice of the whole `ArrayString`.
363    pub fn as_str(&self) -> &str {
364        self
365    }
366}
367
368impl<A> Deref for ArrayString<A>
369    where A: Array<Item=u8> + Copy
370{
371    type Target = str;
372    #[inline]
373    fn deref(&self) -> &str {
374        unsafe {
375            let sl = slice::from_raw_parts(self.xs.ptr(), self.len.to_usize());
376            str::from_utf8_unchecked(sl)
377        }
378    }
379}
380
381impl<A> DerefMut for ArrayString<A>
382    where A: Array<Item=u8> + Copy
383{
384    #[inline]
385    fn deref_mut(&mut self) -> &mut str {
386        unsafe {
387            let sl = slice::from_raw_parts_mut(self.xs.ptr_mut(), self.len.to_usize());
388            str::from_utf8_unchecked_mut(sl)
389        }
390    }
391}
392
393impl<A> PartialEq for ArrayString<A>
394    where A: Array<Item=u8> + Copy
395{
396    fn eq(&self, rhs: &Self) -> bool {
397        **self == **rhs
398    }
399}
400
401impl<A> PartialEq<str> for ArrayString<A>
402    where A: Array<Item=u8> + Copy
403{
404    fn eq(&self, rhs: &str) -> bool {
405        &**self == rhs
406    }
407}
408
409impl<A> PartialEq<ArrayString<A>> for str
410    where A: Array<Item=u8> + Copy
411{
412    fn eq(&self, rhs: &ArrayString<A>) -> bool {
413        self == &**rhs
414    }
415}
416
417impl<A> Eq for ArrayString<A> 
418    where A: Array<Item=u8> + Copy
419{ }
420
421impl<A> Hash for ArrayString<A>
422    where A: Array<Item=u8> + Copy
423{
424    fn hash<H: Hasher>(&self, h: &mut H) {
425        (**self).hash(h)
426    }
427}
428
429impl<A> Borrow<str> for ArrayString<A>
430    where A: Array<Item=u8> + Copy
431{
432    fn borrow(&self) -> &str { self }
433}
434
435impl<A> AsRef<str> for ArrayString<A>
436    where A: Array<Item=u8> + Copy
437{
438    fn as_ref(&self) -> &str { self }
439}
440
441impl<A> fmt::Debug for ArrayString<A>
442    where A: Array<Item=u8> + Copy
443{
444    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
445}
446
447impl<A> fmt::Display for ArrayString<A>
448    where A: Array<Item=u8> + Copy
449{
450    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
451}
452
453/// `Write` appends written data to the end of the string.
454impl<A> fmt::Write for ArrayString<A>
455    where A: Array<Item=u8> + Copy
456{
457    fn write_char(&mut self, c: char) -> fmt::Result {
458        self.try_push(c).map_err(|_| fmt::Error)
459    }
460
461    fn write_str(&mut self, s: &str) -> fmt::Result {
462        self.try_push_str(s).map_err(|_| fmt::Error)
463    }
464}
465
466impl<A> Clone for ArrayString<A>
467    where A: Array<Item=u8> + Copy
468{
469    fn clone(&self) -> ArrayString<A> {
470        *self
471    }
472    fn clone_from(&mut self, rhs: &Self) {
473        // guaranteed to fit due to types matching.
474        self.clear();
475        self.try_push_str(rhs).ok();
476    }
477}
478
479impl<A> PartialOrd for ArrayString<A>
480    where A: Array<Item=u8> + Copy
481{
482    fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> {
483        (**self).partial_cmp(&**rhs)
484    }
485    fn lt(&self, rhs: &Self) -> bool { **self < **rhs }
486    fn le(&self, rhs: &Self) -> bool { **self <= **rhs }
487    fn gt(&self, rhs: &Self) -> bool { **self > **rhs }
488    fn ge(&self, rhs: &Self) -> bool { **self >= **rhs }
489}
490
491impl<A> PartialOrd<str> for ArrayString<A>
492    where A: Array<Item=u8> + Copy
493{
494    fn partial_cmp(&self, rhs: &str) -> Option<cmp::Ordering> {
495        (**self).partial_cmp(rhs)
496    }
497    fn lt(&self, rhs: &str) -> bool { &**self < rhs }
498    fn le(&self, rhs: &str) -> bool { &**self <= rhs }
499    fn gt(&self, rhs: &str) -> bool { &**self > rhs }
500    fn ge(&self, rhs: &str) -> bool { &**self >= rhs }
501}
502
503impl<A> PartialOrd<ArrayString<A>> for str
504    where A: Array<Item=u8> + Copy
505{
506    fn partial_cmp(&self, rhs: &ArrayString<A>) -> Option<cmp::Ordering> {
507        self.partial_cmp(&**rhs)
508    }
509    fn lt(&self, rhs: &ArrayString<A>) -> bool { self < &**rhs }
510    fn le(&self, rhs: &ArrayString<A>) -> bool { self <= &**rhs }
511    fn gt(&self, rhs: &ArrayString<A>) -> bool { self > &**rhs }
512    fn ge(&self, rhs: &ArrayString<A>) -> bool { self >= &**rhs }
513}
514
515impl<A> Ord for ArrayString<A>
516    where A: Array<Item=u8> + Copy
517{
518    fn cmp(&self, rhs: &Self) -> cmp::Ordering {
519        (**self).cmp(&**rhs)
520    }
521}
522
523impl<A> FromStr for ArrayString<A>
524    where A: Array<Item=u8> + Copy
525{
526    type Err = CapacityError;
527
528    fn from_str(s: &str) -> Result<Self, Self::Err> {
529        Self::from(s).map_err(CapacityError::simplify)
530    }
531}
532
533#[cfg(feature="serde")]
534/// Requires crate feature `"serde"`
535impl<A> Serialize for ArrayString<A>
536    where A: Array<Item=u8> + Copy
537{
538    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
539        where S: Serializer
540    {
541        serializer.serialize_str(&*self)
542    }
543}
544
545#[cfg(feature="serde")]
546/// Requires crate feature `"serde"`
547impl<'de, A> Deserialize<'de> for ArrayString<A> 
548    where A: Array<Item=u8> + Copy
549{
550    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
551        where D: Deserializer<'de>
552    {
553        use serde::de::{self, Visitor};
554        use std::marker::PhantomData;
555
556        struct ArrayStringVisitor<A: Array<Item=u8>>(PhantomData<A>);
557
558        impl<'de, A: Copy + Array<Item=u8>> Visitor<'de> for ArrayStringVisitor<A> {
559            type Value = ArrayString<A>;
560
561            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
562                write!(formatter, "a string no more than {} bytes long", A::CAPACITY)
563            }
564
565            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
566                where E: de::Error,
567            {
568                ArrayString::from(v).map_err(|_| E::invalid_length(v.len(), &self))
569            }
570
571            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
572                where E: de::Error,
573            {
574                let s = str::from_utf8(v).map_err(|_| E::invalid_value(de::Unexpected::Bytes(v), &self))?;
575
576                ArrayString::from(s).map_err(|_| E::invalid_length(s.len(), &self))
577            }
578        }
579
580        deserializer.deserialize_str(ArrayStringVisitor::<A>(PhantomData))
581    }
582}