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