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