non_empty_str/
owned.rs

1//! Non-empty [`String`].
2
3#[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/// Represents non-empty owned strings.
22#[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    /// Constructs [`Self`], provided that the value is non-empty.
85    ///
86    /// # Errors
87    ///
88    /// Returns [`Empty`] if the string is empty.
89    pub fn new(value: String) -> Result<Self, Empty> {
90        const_early!(value.is_empty() => Empty);
91
92        // SAFETY: the value is non-empty at this point
93        Ok(unsafe { Self::new_unchecked(value) })
94    }
95
96    /// Similar to [`new`], but the error is discarded.
97    ///
98    /// [`new`]: Self::new
99    pub fn new_ok(value: String) -> Option<Self> {
100        const_ok!(Self::new(value))
101    }
102
103    /// Constructs [`Self`] without checking if the value is non-empty.
104    ///
105    /// # Safety
106    ///
107    /// The caller must ensure that the value is non-empty.
108    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    /// Constructs [`Self`] from [`Str`] via cloning.
120    pub fn from_str(value: Str<'_>) -> Self {
121        // SAFETY: the contained string is non-empty
122        unsafe { Self::new_unchecked(value.take().to_owned()) }
123    }
124
125    /// Constructs [`Self`] from [`CowStr`] via (optionally) cloning.
126    pub fn from_cow_str(value: CowStr<'_>) -> Self {
127        // SAFETY: the contained string is non-empty
128        unsafe { Self::new_unchecked(value.take().into_owned()) }
129    }
130
131    /// Consumes [`Self`] and returns the contained [`String`].
132    pub fn take(self) -> String {
133        #[cfg(feature = "unsafe-assert")]
134        self.assert_non_empty();
135
136        self.value
137    }
138
139    /// Returns the contained string reference.
140    pub fn get(&self) -> &str {
141        #[cfg(feature = "unsafe-assert")]
142        self.assert_non_empty();
143
144        self.value.as_str()
145    }
146}