1#[cfg(feature = "unsafe-assert")]
4use core::hint::assert_unchecked;
5
6use core::{fmt, ops::Deref};
7
8#[cfg(feature = "std")]
9use std::borrow::Cow;
10
11#[cfg(all(not(feature = "std"), feature = "alloc"))]
12use alloc::{borrow::Cow, string::String};
13
14#[cfg(all(not(feature = "std"), feature = "alloc", feature = "serde"))]
15use alloc::borrow::ToOwned;
16
17use const_macros::{const_none, const_ok, const_try};
18
19#[cfg(feature = "serde")]
20use serde::{
21 Deserialize, Deserializer, Serialize, Serializer,
22 de::{Error, Visitor},
23};
24
25use crate::{
26 empty::{Empty, check_str},
27 str::Str,
28};
29
30#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
32pub struct CowStr<'s> {
33 value: Cow<'s, str>,
34}
35
36impl fmt::Display for CowStr<'_> {
37 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
38 self.get().fmt(formatter)
39 }
40}
41
42#[cfg(feature = "serde")]
43struct CowStrVisitor;
44
45#[cfg(feature = "serde")]
46impl<'de> Visitor<'de> for CowStrVisitor {
47 type Value = CowStr<'de>;
48
49 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
50 formatter.write_str("non-empty string")
51 }
52
53 fn visit_borrowed_str<E: Error>(self, string: &'de str) -> Result<Self::Value, E> {
54 Self::Value::borrowed(string).map_err(E::custom)
55 }
56
57 fn visit_str<E: Error>(self, string: &str) -> Result<Self::Value, E> {
58 self.visit_string(string.to_owned())
59 }
60
61 fn visit_string<E: Error>(self, string: String) -> Result<Self::Value, E> {
62 Self::Value::owned(string).map_err(E::custom)
63 }
64}
65
66#[cfg(feature = "serde")]
67impl Serialize for CowStr<'_> {
68 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
69 self.get().serialize(serializer)
70 }
71}
72
73#[cfg(feature = "serde")]
74impl<'de> Deserialize<'de> for CowStr<'de> {
75 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
76 deserializer.deserialize_string(CowStrVisitor)
77 }
78}
79
80impl AsRef<str> for CowStr<'_> {
81 fn as_ref(&self) -> &str {
82 self.get()
83 }
84}
85
86impl Deref for CowStr<'_> {
87 type Target = str;
88
89 fn deref(&self) -> &Self::Target {
90 self.get()
91 }
92}
93
94impl<'s> TryFrom<Cow<'s, str>> for CowStr<'s> {
95 type Error = Empty;
96
97 fn try_from(value: Cow<'s, str>) -> Result<Self, Self::Error> {
98 Self::new(value)
99 }
100}
101
102impl<'s> TryFrom<&'s str> for CowStr<'s> {
103 type Error = Empty;
104
105 fn try_from(value: &'s str) -> Result<Self, Self::Error> {
106 Self::borrowed(value)
107 }
108}
109
110impl TryFrom<String> for CowStr<'_> {
111 type Error = Empty;
112
113 fn try_from(value: String) -> Result<Self, Self::Error> {
114 Self::owned(value)
115 }
116}
117
118impl<'s> From<Str<'s>> for CowStr<'s> {
119 fn from(string: Str<'s>) -> Self {
120 Self::from_str(string)
121 }
122}
123
124impl<'s> From<CowStr<'s>> for Cow<'s, str> {
125 fn from(value: CowStr<'s>) -> Self {
126 value.take()
127 }
128}
129
130impl<'s> CowStr<'s> {
131 pub fn new(value: Cow<'s, str>) -> Result<Self, Empty> {
137 const_try!(check_str(value.as_ref()));
138
139 Ok(unsafe { Self::new_unchecked(value) })
140 }
141
142 pub fn new_ok(value: Cow<'s, str>) -> Option<Self> {
146 const_ok!(Self::new(value))
147 }
148
149 pub const unsafe fn new_unchecked(value: Cow<'s, str>) -> Self {
155 Self { value }
156 }
157
158 pub const fn borrowed(value: &'s str) -> Result<Self, Empty> {
166 const_try!(check_str(value));
167
168 Ok(unsafe { Self::borrowed_unchecked(value) })
170 }
171
172 pub const fn borrowed_ok(value: &'s str) -> Option<Self> {
176 const_none!(const_ok!(check_str(value)));
179
180 Some(unsafe { Self::borrowed_unchecked(value) })
181 }
182
183 pub const unsafe fn borrowed_unchecked(value: &'s str) -> Self {
191 unsafe { Self::new_unchecked(Cow::Borrowed(value)) }
193 }
194
195 pub fn owned(value: String) -> Result<Self, Empty> {
203 const_try!(check_str(value.as_str()));
204
205 Ok(unsafe { Self::owned_unchecked(value) })
207 }
208
209 pub fn owned_ok(value: String) -> Option<Self> {
213 const_ok!(Self::owned(value))
214 }
215
216 pub const unsafe fn owned_unchecked(value: String) -> Self {
224 unsafe { Self::new_unchecked(Cow::Owned(value)) }
225 }
226
227 #[cfg(feature = "unsafe-assert")]
228 fn assert_non_empty(&self) {
229 unsafe { assert_unchecked(!self.value.is_empty()) }
230 }
231
232 pub fn take(self) -> Cow<'s, str> {
234 #[cfg(feature = "unsafe-assert")]
235 self.assert_non_empty();
236
237 self.value
238 }
239
240 pub const fn from_str(string: Str<'s>) -> Self {
242 unsafe { Self::borrowed_unchecked(string.take()) }
244 }
245}
246
247impl CowStr<'_> {
248 pub fn get(&self) -> &str {
250 #[cfg(feature = "unsafe-assert")]
251 self.assert_non_empty();
252
253 self.value.as_ref()
254 }
255}