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