1#[cfg(not(any(feature = "std", feature = "alloc")))]
4compile_error!("expected either `std` or `alloc` to be enabled");
5
6#[cfg(feature = "unsafe-assert")]
7use core::hint::assert_unchecked;
8
9use core::{fmt, ops::Deref};
10
11#[cfg(all(not(feature = "std"), feature = "alloc"))]
12use alloc::{borrow::ToOwned, string::String};
13
14use const_macros::{const_early, const_ok};
15
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
18
19use crate::{cow::CowStr, empty::Empty, str::Str};
20
21#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub struct OwnedStr {
24 value: String,
25}
26
27#[cfg(feature = "serde")]
28impl Serialize for OwnedStr {
29 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
30 self.get().serialize(serializer)
31 }
32}
33
34#[cfg(feature = "serde")]
35impl<'de> Deserialize<'de> for OwnedStr {
36 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
37 let string = String::deserialize(deserializer)?;
38
39 Self::new(string).map_err(Error::custom)
40 }
41}
42
43impl fmt::Display for OwnedStr {
44 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
45 self.get().fmt(formatter)
46 }
47}
48
49impl TryFrom<String> for OwnedStr {
50 type Error = Empty;
51
52 fn try_from(value: String) -> Result<Self, Self::Error> {
53 Self::new(value)
54 }
55}
56
57impl From<OwnedStr> for String {
58 fn from(owned: OwnedStr) -> Self {
59 owned.take()
60 }
61}
62
63impl From<Str<'_>> for OwnedStr {
64 fn from(string: Str<'_>) -> Self {
65 Self::from_str(string)
66 }
67}
68
69impl From<CowStr<'_>> for OwnedStr {
70 fn from(cow: CowStr<'_>) -> Self {
71 Self::from_cow_str(cow)
72 }
73}
74
75impl Deref for OwnedStr {
76 type Target = str;
77
78 fn deref(&self) -> &Self::Target {
79 self.get()
80 }
81}
82
83impl OwnedStr {
84 pub fn new(value: String) -> Result<Self, Empty> {
90 const_early!(value.is_empty() => Empty);
91
92 Ok(unsafe { Self::new_unchecked(value) })
94 }
95
96 pub fn new_ok(value: String) -> Option<Self> {
100 const_ok!(Self::new(value))
101 }
102
103 pub const unsafe fn new_unchecked(value: String) -> Self {
109 Self { value }
110 }
111
112 #[cfg(feature = "unsafe-assert")]
113 fn assert_non_empty(&self) {
114 unsafe {
115 assert_unchecked(!self.value.is_empty());
116 }
117 }
118
119 pub fn from_str(value: Str<'_>) -> Self {
121 unsafe { Self::new_unchecked(value.take().to_owned()) }
123 }
124
125 pub fn from_cow_str(value: CowStr<'_>) -> Self {
127 unsafe { Self::new_unchecked(value.take().into_owned()) }
129 }
130
131 pub fn take(self) -> String {
133 #[cfg(feature = "unsafe-assert")]
134 self.assert_non_empty();
135
136 self.value
137 }
138
139 pub fn get(&self) -> &str {
141 #[cfg(feature = "unsafe-assert")]
142 self.assert_non_empty();
143
144 self.value.as_str()
145 }
146}