1 use super::TryClone; 2 use crate::error::OutOfMemory; 3 use core::{fmt, ops}; 4 use std_alloc::string as inner; 5 6 /// A newtype wrapper around [`std::string::String`] that only exposes 7 /// fallible-allocation methods. 8 pub struct String { 9 inner: inner::String, 10 } 11 12 impl TryClone for String { 13 fn try_clone(&self) -> Result<Self, OutOfMemory> { 14 let mut s = Self::new(); 15 s.push_str(self)?; 16 Ok(s) 17 } 18 } 19 20 impl fmt::Debug for String { 21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 22 fmt::Debug::fmt(&self.inner, f) 23 } 24 } 25 26 impl fmt::Display for String { 27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 28 fmt::Display::fmt(&self.inner, f) 29 } 30 } 31 32 impl ops::Deref for String { 33 type Target = str; 34 35 #[inline] 36 fn deref(&self) -> &Self::Target { 37 &self.inner 38 } 39 } 40 41 impl ops::DerefMut for String { 42 #[inline] 43 fn deref_mut(&mut self) -> &mut Self::Target { 44 &mut self.inner 45 } 46 } 47 48 impl From<inner::String> for String { 49 #[inline] 50 fn from(inner: inner::String) -> Self { 51 Self { inner } 52 } 53 } 54 55 impl String { 56 /// Same as [`std::string::String::new`]. 57 #[inline] 58 pub fn new() -> Self { 59 Self { 60 inner: inner::String::new(), 61 } 62 } 63 64 /// Same as [`std::string::String::with_capacity`] but returns an error on 65 /// allocation failure. 66 #[inline] 67 pub fn with_capacity(capacity: usize) -> Result<Self, OutOfMemory> { 68 let mut s = Self::new(); 69 s.reserve(capacity)?; 70 Ok(s) 71 } 72 73 /// Same as [`std::string::String::reserve`] but returns an error on 74 /// allocation failure. 75 #[inline] 76 pub fn reserve(&mut self, additional: usize) -> Result<(), OutOfMemory> { 77 self.inner 78 .try_reserve(additional) 79 .map_err(|_| OutOfMemory::new(self.len().saturating_add(additional))) 80 } 81 82 /// Same as [`std::string::String::reserve_exact`] but returns an error on 83 /// allocation failure. 84 #[inline] 85 pub fn reserve_exact(&mut self, additional: usize) -> Result<(), OutOfMemory> { 86 self.inner 87 .try_reserve_exact(additional) 88 .map_err(|_| OutOfMemory::new(self.len().saturating_add(additional))) 89 } 90 91 /// Same as [`std::string::String::push`] but returns an error on allocation 92 /// failure. 93 #[inline] 94 pub fn push(&mut self, c: char) -> Result<(), OutOfMemory> { 95 self.reserve(c.len_utf8())?; 96 self.inner.push(c); 97 Ok(()) 98 } 99 100 /// Same as [`std::string::String::push_str`] but returns an error on 101 /// allocation failure. 102 #[inline] 103 pub fn push_str(&mut self, s: &str) -> Result<(), OutOfMemory> { 104 self.reserve(s.len())?; 105 self.inner.push_str(s); 106 Ok(()) 107 } 108 } 109