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