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` default() -> ArrayString<CAP>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 /// ``` new() -> ArrayString<CAP>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 /// ``` new_const() -> ArrayString<CAP>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] len(&self) -> usize85 pub const fn len(&self) -> usize { self.len as usize } 86 87 /// Returns whether the string is empty. 88 #[inline] is_empty(&self) -> bool89 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 /// ``` from(s: &str) -> Result<Self, CapacityError<&str>>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 /// ``` from_byte_string(b: &[u8; CAP]) -> Result<Self, Utf8Error>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] zero_filled() -> Self142 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)] capacity(&self) -> usize163 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 /// ``` is_full(&self) -> bool175 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 /// ``` remaining_capacity(&self) -> usize186 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] push(&mut self, c: char)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 /// ``` try_push(&mut self, c: char) -> Result<(), CapacityError<char>>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] push_str(&mut self, s: &str)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 /// ``` try_push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>>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 /// ``` pop(&mut self) -> Option<char>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 /// ``` truncate(&mut self, new_len: usize)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 /// ``` remove(&mut self, idx: usize) -> char368 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. clear(&mut self)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. set_len(&mut self, length: usize)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`. as_str(&self) -> &str408 pub fn as_str(&self) -> &str { 409 self 410 } 411 412 /// Return a mutable string slice of the whole `ArrayString`. as_mut_str(&mut self) -> &mut str413 pub fn as_mut_str(&mut self) -> &mut str { 414 self 415 } 416 as_ptr(&self) -> *const u8417 fn as_ptr(&self) -> *const u8 { 418 self.xs.as_ptr() as *const u8 419 } 420 as_mut_ptr(&mut self) -> *mut u8421 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] deref(&self) -> &str430 fn deref(&self) -> &str { 431 unsafe { 432 let sl = 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] deref_mut(&mut self) -> &mut str441 fn deref_mut(&mut self) -> &mut str { 442 unsafe { 443 let len = self.len(); 444 let sl = 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 { eq(&self, rhs: &Self) -> bool452 fn eq(&self, rhs: &Self) -> bool { 453 **self == **rhs 454 } 455 } 456 457 impl<const CAP: usize> PartialEq<str> for ArrayString<CAP> 458 { eq(&self, rhs: &str) -> bool459 fn eq(&self, rhs: &str) -> bool { 460 &**self == rhs 461 } 462 } 463 464 impl<const CAP: usize> PartialEq<ArrayString<CAP>> for str 465 { eq(&self, rhs: &ArrayString<CAP>) -> bool466 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 { hash<H: Hasher>(&self, h: &mut H)476 fn hash<H: Hasher>(&self, h: &mut H) { 477 (**self).hash(h) 478 } 479 } 480 481 impl<const CAP: usize> Borrow<str> for ArrayString<CAP> 482 { borrow(&self) -> &str483 fn borrow(&self) -> &str { self } 484 } 485 486 impl<const CAP: usize> BorrowMut<str> for ArrayString<CAP> 487 { borrow_mut(&mut self) -> &mut str488 fn borrow_mut(&mut self) -> &mut str { self } 489 } 490 491 impl<const CAP: usize> AsRef<str> for ArrayString<CAP> 492 { as_ref(&self) -> &str493 fn as_ref(&self) -> &str { self } 494 } 495 496 impl<const CAP: usize> fmt::Debug for ArrayString<CAP> 497 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result498 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 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result503 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 { write_char(&mut self, c: char) -> fmt::Result509 fn write_char(&mut self, c: char) -> fmt::Result { 510 self.try_push(c).map_err(|_| fmt::Error) 511 } 512 write_str(&mut self, s: &str) -> fmt::Result513 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 { clone(&self) -> ArrayString<CAP>520 fn clone(&self) -> ArrayString<CAP> { 521 *self 522 } clone_from(&mut self, rhs: &Self)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 { partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering>532 fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> { 533 (**self).partial_cmp(&**rhs) 534 } lt(&self, rhs: &Self) -> bool535 fn lt(&self, rhs: &Self) -> bool { **self < **rhs } le(&self, rhs: &Self) -> bool536 fn le(&self, rhs: &Self) -> bool { **self <= **rhs } gt(&self, rhs: &Self) -> bool537 fn gt(&self, rhs: &Self) -> bool { **self > **rhs } ge(&self, rhs: &Self) -> bool538 fn ge(&self, rhs: &Self) -> bool { **self >= **rhs } 539 } 540 541 impl<const CAP: usize> PartialOrd<str> for ArrayString<CAP> 542 { partial_cmp(&self, rhs: &str) -> Option<cmp::Ordering>543 fn partial_cmp(&self, rhs: &str) -> Option<cmp::Ordering> { 544 (**self).partial_cmp(rhs) 545 } lt(&self, rhs: &str) -> bool546 fn lt(&self, rhs: &str) -> bool { &**self < rhs } le(&self, rhs: &str) -> bool547 fn le(&self, rhs: &str) -> bool { &**self <= rhs } gt(&self, rhs: &str) -> bool548 fn gt(&self, rhs: &str) -> bool { &**self > rhs } ge(&self, rhs: &str) -> bool549 fn ge(&self, rhs: &str) -> bool { &**self >= rhs } 550 } 551 552 impl<const CAP: usize> PartialOrd<ArrayString<CAP>> for str 553 { partial_cmp(&self, rhs: &ArrayString<CAP>) -> Option<cmp::Ordering>554 fn partial_cmp(&self, rhs: &ArrayString<CAP>) -> Option<cmp::Ordering> { 555 self.partial_cmp(&**rhs) 556 } lt(&self, rhs: &ArrayString<CAP>) -> bool557 fn lt(&self, rhs: &ArrayString<CAP>) -> bool { self < &**rhs } le(&self, rhs: &ArrayString<CAP>) -> bool558 fn le(&self, rhs: &ArrayString<CAP>) -> bool { self <= &**rhs } gt(&self, rhs: &ArrayString<CAP>) -> bool559 fn gt(&self, rhs: &ArrayString<CAP>) -> bool { self > &**rhs } ge(&self, rhs: &ArrayString<CAP>) -> bool560 fn ge(&self, rhs: &ArrayString<CAP>) -> bool { self >= &**rhs } 561 } 562 563 impl<const CAP: usize> Ord for ArrayString<CAP> 564 { cmp(&self, rhs: &Self) -> cmp::Ordering565 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 from_str(s: &str) -> Result<Self, Self::Err>574 fn from_str(s: &str) -> Result<Self, Self::Err> { 575 Self::from(s).map_err(CapacityError::simplify) 576 } 577 } 578 579 #[cfg(feature="serde")] 580 /// Requires crate feature `"serde"` 581 impl<const CAP: usize> Serialize for ArrayString<CAP> 582 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer583 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 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>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 try_from(f: &'a str) -> Result<Self, Self::Error>632 fn try_from(f: &'a str) -> Result<Self, Self::Error> { 633 let mut v = 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 try_from(f: fmt::Arguments<'a>) -> Result<Self, Self::Error>643 fn try_from(f: fmt::Arguments<'a>) -> Result<Self, Self::Error> { 644 use fmt::Write; 645 let mut v = Self::new(); 646 v.write_fmt(f).map_err(|e| CapacityError::new(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> { zeroize(&mut self)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