1#[cfg(not(any(feature = "std", feature = "alloc")))]
6compile_error!("expected either `std` or `alloc` to be enabled");
7
8#[cfg(feature = "unsafe-assert")]
9use core::hint::assert_unchecked;
10
11use core::{fmt, ops::Deref};
12
13#[cfg(feature = "std")]
14use std::borrow::Cow;
15
16#[cfg(all(not(feature = "std"), feature = "alloc"))]
17use alloc::{borrow::Cow, string::String};
18
19#[cfg(all(
20 not(feature = "std"),
21 feature = "alloc",
22 feature = "serde",
23 feature = "borrow"
24))]
25use alloc::borrow::ToOwned;
26
27use const_macros::{const_early, const_ok, const_quick};
28
29#[cfg(feature = "into-static")]
30use into_static::IntoStatic;
31
32#[cfg(feature = "serde")]
33use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
34
35#[cfg(all(feature = "serde", feature = "borrow"))]
36use serde::de::Visitor;
37
38use crate::{empty::Empty, owned::OwnedStr, str::Str};
39
40#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub struct CowStr<'s> {
43 value: Cow<'s, str>,
44}
45
46#[cfg(feature = "serde")]
47impl Serialize for CowStr<'_> {
48 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
49 self.get().serialize(serializer)
50 }
51}
52
53#[cfg(all(feature = "serde", feature = "borrow"))]
54struct CowStrVisitor;
55
56#[cfg(all(feature = "serde", feature = "borrow"))]
57impl<'de> Visitor<'de> for CowStrVisitor {
58 type Value = CowStr<'de>;
59
60 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
61 formatter.write_str("non-empty string")
62 }
63
64 fn visit_borrowed_str<E: Error>(self, value: &'de str) -> Result<Self::Value, E> {
65 CowStr::borrowed(value).map_err(Error::custom)
66 }
67
68 fn visit_str<E: Error>(self, value: &str) -> Result<Self::Value, E> {
69 self.visit_string(value.to_owned())
70 }
71
72 fn visit_string<E: Error>(self, value: String) -> Result<Self::Value, E> {
73 CowStr::owned(value).map_err(Error::custom)
74 }
75}
76
77#[cfg(all(feature = "serde", feature = "borrow"))]
78impl<'de: 'c, 'c> Deserialize<'de> for CowStr<'c> {
79 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
80 deserializer.deserialize_str(CowStrVisitor)
81 }
82}
83
84#[cfg(all(feature = "serde", not(feature = "borrow")))]
85impl<'de> Deserialize<'de> for CowStr<'_> {
86 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
87 let value = Cow::deserialize(deserializer)?;
88
89 Self::new(value).map_err(Error::custom)
90 }
91}
92
93impl fmt::Display for CowStr<'_> {
94 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
95 self.get().fmt(formatter)
96 }
97}
98
99impl AsRef<str> for CowStr<'_> {
100 fn as_ref(&self) -> &str {
101 self.get()
102 }
103}
104
105impl Deref for CowStr<'_> {
106 type Target = str;
107
108 fn deref(&self) -> &Self::Target {
109 self.get()
110 }
111}
112
113impl<'s> TryFrom<Cow<'s, str>> for CowStr<'s> {
114 type Error = Empty;
115
116 fn try_from(value: Cow<'s, str>) -> Result<Self, Self::Error> {
117 Self::new(value)
118 }
119}
120
121impl<'s> TryFrom<&'s str> for CowStr<'s> {
122 type Error = Empty;
123
124 fn try_from(value: &'s str) -> Result<Self, Self::Error> {
125 Self::borrowed(value)
126 }
127}
128
129impl TryFrom<String> for CowStr<'_> {
130 type Error = Empty;
131
132 fn try_from(value: String) -> Result<Self, Self::Error> {
133 Self::owned(value)
134 }
135}
136
137impl<'s> From<Str<'s>> for CowStr<'s> {
138 fn from(string: Str<'s>) -> Self {
139 Self::from_str(string)
140 }
141}
142
143impl From<OwnedStr> for CowStr<'_> {
144 fn from(string: OwnedStr) -> Self {
145 Self::from_owned_str(string)
146 }
147}
148
149impl<'s> From<CowStr<'s>> for Cow<'s, str> {
150 fn from(value: CowStr<'s>) -> Self {
151 value.take()
152 }
153}
154
155impl<'s> CowStr<'s> {
156 pub fn new(value: Cow<'s, str>) -> Result<Self, Empty> {
162 const_early!(value.is_empty() => Empty);
163
164 Ok(unsafe { Self::new_unchecked(value) })
166 }
167
168 pub fn new_ok(value: Cow<'s, str>) -> Option<Self> {
172 const_ok!(Self::new(value))
173 }
174
175 pub const unsafe fn new_unchecked(value: Cow<'s, str>) -> Self {
181 Self { value }
182 }
183
184 pub const fn borrowed(value: &'s str) -> Result<Self, Empty> {
192 const_early!(value.is_empty() => Empty);
193
194 Ok(unsafe { Self::borrowed_unchecked(value) })
196 }
197
198 pub const fn borrowed_ok(value: &'s str) -> Option<Self> {
202 const_quick!(value.is_empty());
203
204 Some(unsafe { Self::borrowed_unchecked(value) })
206 }
207
208 pub const unsafe fn borrowed_unchecked(value: &'s str) -> Self {
216 unsafe { Self::new_unchecked(Cow::Borrowed(value)) }
218 }
219
220 pub fn owned(value: String) -> Result<Self, Empty> {
228 const_early!(value.is_empty() => Empty);
229
230 Ok(unsafe { Self::owned_unchecked(value) })
232 }
233
234 pub fn owned_ok(value: String) -> Option<Self> {
238 const_ok!(Self::owned(value))
239 }
240
241 pub const unsafe fn owned_unchecked(value: String) -> Self {
249 unsafe { Self::new_unchecked(Cow::Owned(value)) }
251 }
252
253 #[cfg(feature = "unsafe-assert")]
254 fn assert_non_empty(&self) {
255 unsafe {
257 assert_unchecked(!self.value.is_empty());
258 }
259 }
260
261 pub fn take(self) -> Cow<'s, str> {
263 #[cfg(feature = "unsafe-assert")]
264 self.assert_non_empty();
265
266 self.value
267 }
268
269 pub const fn from_str(string: Str<'s>) -> Self {
271 unsafe { Self::borrowed_unchecked(string.take()) }
273 }
274
275 pub fn from_owned_str(string: OwnedStr) -> Self {
277 unsafe { Self::owned_unchecked(string.take()) }
279 }
280}
281
282impl CowStr<'_> {
283 pub fn get(&self) -> &str {
285 #[cfg(feature = "unsafe-assert")]
286 self.assert_non_empty();
287
288 self.value.as_ref()
289 }
290}
291
292#[cfg(feature = "into-static")]
293impl IntoStatic for CowStr<'_> {
294 type Static = CowStr<'static>;
295
296 fn into_static(self) -> Self::Static {
297 unsafe { Self::Static::new_unchecked(self.take().into_static()) }
299 }
300}