1cfg_select! {
4 feature = "std" => {}
5 feature = "alloc" => {
6 use alloc::{boxed::Box, string::String};
7 }
8 _ => {
9 compile_error!("expected either `std` or `alloc` to be enabled");
10 }
11}
12
13use non_empty_iter::{FromNonEmptyIterator, IntoNonEmptyIterator};
14use non_empty_slice::{NonEmptyBoxedBytes, NonEmptyBytes};
15use thiserror::Error;
16
17use crate::{
18 cow::NonEmptyCowStr,
19 str::NonEmptyStr,
20 string::{EmptyString, NonEmptyString},
21};
22
23pub const EMPTY_BOXED_STR: &str = "the boxed string is empty";
25
26#[derive(Debug, Error)]
28#[error("{EMPTY_BOXED_STR}")]
29pub struct EmptyBoxedStr {
30 boxed: Box<str>,
31}
32
33impl EmptyBoxedStr {
34 pub(crate) const fn new(boxed: Box<str>) -> Self {
36 Self { boxed }
37 }
38
39 #[must_use]
41 pub fn get(self) -> Box<str> {
42 self.boxed
43 }
44
45 #[must_use]
47 pub fn from_empty_string(empty: EmptyString) -> Self {
48 Self::new(empty.get().into_boxed_str())
49 }
50
51 #[must_use]
53 pub fn into_empty_string(self) -> EmptyString {
54 EmptyString::from_empty_boxed_str(self)
55 }
56}
57
58pub type NonEmptyBoxedStr = Box<NonEmptyStr>;
60
61impl Clone for NonEmptyBoxedStr {
62 fn clone(&self) -> Self {
63 self.to_non_empty_string().into_non_empty_boxed_str()
64 }
65}
66
67impl From<NonEmptyBoxedStr> for Box<str> {
68 fn from(boxed: NonEmptyBoxedStr) -> Self {
69 boxed.into_boxed_str()
70 }
71}
72
73impl From<NonEmptyBoxedStr> for Box<[u8]> {
74 fn from(boxed: NonEmptyBoxedStr) -> Self {
75 boxed.into_boxed_bytes()
76 }
77}
78
79impl TryFrom<Box<str>> for NonEmptyBoxedStr {
80 type Error = EmptyBoxedStr;
81
82 fn try_from(boxed: Box<str>) -> Result<Self, Self::Error> {
83 NonEmptyStr::from_boxed_str(boxed)
84 }
85}
86
87impl TryFrom<String> for NonEmptyBoxedStr {
88 type Error = EmptyString;
89
90 fn try_from(string: String) -> Result<Self, Self::Error> {
91 let non_empty_string = NonEmptyString::new(string)?;
92
93 Ok(non_empty_string.into())
94 }
95}
96
97impl From<NonEmptyBoxedStr> for NonEmptyString {
98 fn from(non_empty: NonEmptyBoxedStr) -> Self {
99 non_empty.into_non_empty_string()
100 }
101}
102
103impl From<NonEmptyString> for NonEmptyBoxedStr {
104 fn from(non_empty: NonEmptyString) -> Self {
105 non_empty.into_non_empty_boxed_str()
106 }
107}
108
109impl From<NonEmptyBoxedStr> for String {
110 fn from(non_empty: NonEmptyBoxedStr) -> Self {
111 non_empty.into_boxed_str().into_string()
112 }
113}
114
115impl From<NonEmptyBoxedStr> for NonEmptyBoxedBytes {
116 fn from(non_empty: NonEmptyBoxedStr) -> Self {
117 non_empty.into_non_empty_boxed_bytes()
118 }
119}
120
121impl NonEmptyStr {
122 pub fn from_boxed_str(boxed: Box<str>) -> Result<Box<Self>, EmptyBoxedStr> {
128 if boxed.is_empty() {
129 return Err(EmptyBoxedStr::new(boxed));
130 }
131
132 Ok(unsafe { Self::from_boxed_str_unchecked(boxed) })
134 }
135
136 #[must_use]
142 pub unsafe fn from_boxed_str_unchecked(boxed: Box<str>) -> Box<Self> {
143 unsafe { Box::from_raw(Box::into_raw(boxed) as *mut Self) }
147 }
148
149 #[must_use]
151 pub fn into_boxed_str(self: Box<Self>) -> Box<str> {
152 unsafe { Box::from_raw(Box::into_raw(self) as *mut str) }
155 }
156
157 #[must_use]
159 pub fn from_non_empty_string(non_empty: NonEmptyString) -> Box<Self> {
160 unsafe { Self::from_boxed_str_unchecked(non_empty.into_string().into_boxed_str()) }
162 }
163
164 #[must_use]
166 pub fn into_non_empty_string(self: Box<Self>) -> NonEmptyString {
167 NonEmptyString::from_non_empty_boxed_str(self)
168 }
169
170 #[must_use]
172 pub fn into_boxed_bytes(self: Box<Self>) -> Box<[u8]> {
173 self.into_boxed_str().into_boxed_bytes()
174 }
175
176 #[must_use]
178 pub fn into_non_empty_boxed_bytes(self: Box<Self>) -> NonEmptyBoxedBytes {
179 unsafe { NonEmptyBytes::from_boxed_slice_unchecked(self.into_boxed_bytes()) }
181 }
182}
183
184impl NonEmptyString {
185 #[must_use]
187 pub fn from_non_empty_boxed_str(non_empty: NonEmptyBoxedStr) -> Self {
188 unsafe { Self::new_unchecked(non_empty.into_boxed_str().into_string()) }
190 }
191
192 #[must_use]
194 pub fn into_non_empty_boxed_str(self) -> NonEmptyBoxedStr {
195 NonEmptyStr::from_non_empty_string(self)
196 }
197
198 #[must_use]
200 pub fn into_boxed_str(self) -> Box<str> {
201 self.into_string().into_boxed_str()
202 }
203
204 #[must_use]
206 pub fn into_boxed_bytes(self) -> Box<[u8]> {
207 self.into_non_empty_boxed_str().into_boxed_bytes()
208 }
209
210 #[must_use]
212 pub fn into_non_empty_boxed_bytes(self) -> NonEmptyBoxedBytes {
213 self.into_non_empty_boxed_str().into_non_empty_boxed_bytes()
214 }
215}
216
217impl FromNonEmptyIterator<char> for NonEmptyBoxedStr {
218 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = char>>(iterable: I) -> Self {
219 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
220 }
221}
222
223impl<'c> FromNonEmptyIterator<&'c char> for NonEmptyBoxedStr {
224 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = &'c char>>(iterable: I) -> Self {
225 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
226 }
227}
228
229impl<'s> FromNonEmptyIterator<&'s NonEmptyStr> for NonEmptyBoxedStr {
230 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = &'s NonEmptyStr>>(iterable: I) -> Self {
231 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
232 }
233}
234
235impl FromNonEmptyIterator<NonEmptyString> for NonEmptyBoxedStr {
236 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = NonEmptyString>>(iterable: I) -> Self {
237 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
238 }
239}
240
241impl FromNonEmptyIterator<Self> for NonEmptyBoxedStr {
242 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = Self>>(iterable: I) -> Self {
243 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
244 }
245}
246
247impl<'s> FromNonEmptyIterator<NonEmptyCowStr<'s>> for NonEmptyBoxedStr {
248 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = NonEmptyCowStr<'s>>>(
249 iterable: I,
250 ) -> Self {
251 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
252 }
253}