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 internals::Bytes,
20 str::NonEmptyStr,
21 string::{EmptyString, NonEmptyString},
22};
23
24pub const EMPTY_BOXED_STR: &str = "the boxed string is empty";
26
27#[derive(Debug, Error)]
29#[error("{EMPTY_BOXED_STR}")]
30pub struct EmptyBoxedStr {
31 boxed: Box<str>,
32}
33
34impl EmptyBoxedStr {
35 pub(crate) const fn new(boxed: Box<str>) -> Self {
37 Self { boxed }
38 }
39
40 #[must_use]
42 pub fn get(self) -> Box<str> {
43 self.boxed
44 }
45
46 #[must_use]
48 pub fn from_empty_string(empty: EmptyString) -> Self {
49 Self::new(empty.get().into_boxed_str())
50 }
51
52 #[must_use]
54 pub fn into_empty_string(self) -> EmptyString {
55 EmptyString::from_empty_boxed_str(self)
56 }
57}
58
59pub type NonEmptyBoxedStr = Box<NonEmptyStr>;
61
62impl Clone for NonEmptyBoxedStr {
63 fn clone(&self) -> Self {
64 self.to_non_empty_string().into_non_empty_boxed_str()
65 }
66}
67
68impl From<NonEmptyBoxedStr> for Box<str> {
69 fn from(boxed: NonEmptyBoxedStr) -> Self {
70 boxed.into_boxed_str()
71 }
72}
73
74impl From<NonEmptyBoxedStr> for Box<Bytes> {
75 fn from(boxed: NonEmptyBoxedStr) -> Self {
76 boxed.into_boxed_bytes()
77 }
78}
79
80impl TryFrom<Box<str>> for NonEmptyBoxedStr {
81 type Error = EmptyBoxedStr;
82
83 fn try_from(boxed: Box<str>) -> Result<Self, Self::Error> {
84 NonEmptyStr::from_boxed_str(boxed)
85 }
86}
87
88impl TryFrom<String> for NonEmptyBoxedStr {
89 type Error = EmptyString;
90
91 fn try_from(string: String) -> Result<Self, Self::Error> {
92 let non_empty_string = NonEmptyString::new(string)?;
93
94 Ok(non_empty_string.into())
95 }
96}
97
98impl From<NonEmptyBoxedStr> for NonEmptyString {
99 fn from(non_empty: NonEmptyBoxedStr) -> Self {
100 non_empty.into_non_empty_string()
101 }
102}
103
104impl From<NonEmptyString> for NonEmptyBoxedStr {
105 fn from(non_empty: NonEmptyString) -> Self {
106 non_empty.into_non_empty_boxed_str()
107 }
108}
109
110impl From<NonEmptyBoxedStr> for String {
111 fn from(non_empty: NonEmptyBoxedStr) -> Self {
112 non_empty.into_boxed_str().into_string()
113 }
114}
115
116impl From<NonEmptyBoxedStr> for NonEmptyBoxedBytes {
117 fn from(non_empty: NonEmptyBoxedStr) -> Self {
118 non_empty.into_non_empty_boxed_bytes()
119 }
120}
121
122impl NonEmptyStr {
123 pub fn from_boxed_str(boxed: Box<str>) -> Result<Box<Self>, EmptyBoxedStr> {
129 if boxed.is_empty() {
130 return Err(EmptyBoxedStr::new(boxed));
131 }
132
133 Ok(unsafe { Self::from_boxed_str_unchecked(boxed) })
135 }
136
137 #[must_use]
143 pub unsafe fn from_boxed_str_unchecked(boxed: Box<str>) -> Box<Self> {
144 unsafe { Box::from_raw(Box::into_raw(boxed) as *mut Self) }
148 }
149
150 #[must_use]
152 pub fn into_boxed_str(self: Box<Self>) -> Box<str> {
153 unsafe { Box::from_raw(Box::into_raw(self) as *mut str) }
156 }
157
158 #[must_use]
160 pub fn from_non_empty_string(non_empty: NonEmptyString) -> Box<Self> {
161 unsafe { Self::from_boxed_str_unchecked(non_empty.into_string().into_boxed_str()) }
163 }
164
165 #[must_use]
167 pub fn into_non_empty_string(self: Box<Self>) -> NonEmptyString {
168 NonEmptyString::from_non_empty_boxed_str(self)
169 }
170
171 #[must_use]
173 pub fn into_boxed_bytes(self: Box<Self>) -> Box<Bytes> {
174 self.into_boxed_str().into_boxed_bytes()
175 }
176
177 #[must_use]
179 pub fn into_non_empty_boxed_bytes(self: Box<Self>) -> NonEmptyBoxedBytes {
180 unsafe { NonEmptyBytes::from_boxed_slice_unchecked(self.into_boxed_bytes()) }
182 }
183}
184
185impl NonEmptyString {
186 #[must_use]
188 pub fn from_non_empty_boxed_str(non_empty: NonEmptyBoxedStr) -> Self {
189 unsafe { Self::new_unchecked(non_empty.into_boxed_str().into_string()) }
191 }
192
193 #[must_use]
195 pub fn into_non_empty_boxed_str(self) -> NonEmptyBoxedStr {
196 NonEmptyStr::from_non_empty_string(self)
197 }
198
199 #[must_use]
201 pub fn into_boxed_str(self) -> Box<str> {
202 self.into_string().into_boxed_str()
203 }
204
205 #[must_use]
207 pub fn into_boxed_bytes(self) -> Box<Bytes> {
208 self.into_non_empty_boxed_str().into_boxed_bytes()
209 }
210
211 #[must_use]
213 pub fn into_non_empty_boxed_bytes(self) -> NonEmptyBoxedBytes {
214 self.into_non_empty_boxed_str().into_non_empty_boxed_bytes()
215 }
216}
217
218impl FromNonEmptyIterator<char> for NonEmptyBoxedStr {
219 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = char>>(iterable: I) -> Self {
220 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
221 }
222}
223
224impl<'c> FromNonEmptyIterator<&'c char> for NonEmptyBoxedStr {
225 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = &'c char>>(iterable: I) -> Self {
226 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
227 }
228}
229
230impl<'s> FromNonEmptyIterator<&'s NonEmptyStr> for NonEmptyBoxedStr {
231 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = &'s NonEmptyStr>>(iterable: I) -> Self {
232 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
233 }
234}
235
236impl FromNonEmptyIterator<NonEmptyString> for NonEmptyBoxedStr {
237 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = NonEmptyString>>(iterable: I) -> Self {
238 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
239 }
240}
241
242impl FromNonEmptyIterator<Self> for NonEmptyBoxedStr {
243 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = Self>>(iterable: I) -> Self {
244 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
245 }
246}
247
248impl<'s> FromNonEmptyIterator<NonEmptyCowStr<'s>> for NonEmptyBoxedStr {
249 fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = NonEmptyCowStr<'s>>>(
250 iterable: I,
251 ) -> Self {
252 NonEmptyString::from_non_empty_iter(iterable).into_non_empty_boxed_str()
253 }
254}