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_try;
18
19#[cfg(feature = "serde")]
20use serde::{
21 Deserialize, Deserializer, Serialize, Serializer,
22 de::{Error, Visitor},
23};
24
25use crate::empty::{Empty, check_str};
26
27#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct CowStr<'s> {
30 value: Cow<'s, str>,
31}
32
33impl fmt::Display for CowStr<'_> {
34 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
35 self.get().fmt(formatter)
36 }
37}
38
39#[cfg(feature = "serde")]
40struct CowStrVisitor;
41
42#[cfg(feature = "serde")]
43impl<'de> Visitor<'de> for CowStrVisitor {
44 type Value = CowStr<'de>;
45
46 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
47 formatter.write_str("non-empty string")
48 }
49
50 fn visit_borrowed_str<E: Error>(self, string: &'de str) -> Result<Self::Value, E> {
51 Self::Value::borrowed(string).map_err(E::custom)
52 }
53
54 fn visit_str<E: Error>(self, string: &str) -> Result<Self::Value, E> {
55 self.visit_string(string.to_owned())
56 }
57
58 fn visit_string<E: Error>(self, string: String) -> Result<Self::Value, E> {
59 Self::Value::owned(string).map_err(E::custom)
60 }
61}
62
63#[cfg(feature = "serde")]
64impl Serialize for CowStr<'_> {
65 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
66 self.get().serialize(serializer)
67 }
68}
69
70#[cfg(feature = "serde")]
71impl<'de> Deserialize<'de> for CowStr<'de> {
72 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
73 deserializer.deserialize_string(CowStrVisitor)
74 }
75}
76
77impl AsRef<str> for CowStr<'_> {
78 fn as_ref(&self) -> &str {
79 self.get()
80 }
81}
82
83impl Deref for CowStr<'_> {
84 type Target = str;
85
86 fn deref(&self) -> &Self::Target {
87 self.get()
88 }
89}
90
91impl<'s> CowStr<'s> {
92 pub fn new(value: Cow<'s, str>) -> Result<Self, Empty> {
98 const_try!(check_str(value.as_ref()));
99
100 Ok(unsafe { Self::new_unchecked(value) })
101 }
102
103 pub const unsafe fn new_unchecked(value: Cow<'s, str>) -> Self {
109 Self { value }
110 }
111
112 pub fn borrowed(value: &'s str) -> Result<Self, Empty> {
120 Self::new(Cow::Borrowed(value))
121 }
122
123 pub const unsafe fn borrowed_unchecked(value: &'s str) -> Self {
131 unsafe { Self::new_unchecked(Cow::Borrowed(value)) }
133 }
134
135 pub fn owned(value: String) -> Result<Self, Empty> {
143 Self::new(Cow::Owned(value))
144 }
145
146 pub const unsafe fn owned_unchecked(value: String) -> Self {
154 unsafe { Self::new_unchecked(Cow::Owned(value)) }
155 }
156
157 #[cfg(feature = "unsafe-assert")]
158 fn assert_non_empty(&self) {
159 unsafe { assert_unchecked(!self.value.is_empty()) }
160 }
161
162 pub fn take(self) -> Cow<'s, str> {
164 #[cfg(feature = "unsafe-assert")]
165 self.assert_non_empty();
166
167 self.value
168 }
169}
170
171impl CowStr<'_> {
172 pub fn get(&self) -> &str {
174 #[cfg(feature = "unsafe-assert")]
175 self.assert_non_empty();
176
177 self.value.as_ref()
178 }
179}