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