1use crate as stabby;
18
19use core::ops::{Deref, DerefMut};
20
21#[stabby::stabby]
23#[derive(Clone, Copy, PartialEq, Eq, Hash)]
24pub struct Str<'a> {
25 pub(crate) inner: crate::slice::Slice<'a, u8>,
26}
27impl<'a> Str<'a> {
28 pub const fn new(s: &'a str) -> Self {
30 Self {
31 inner: crate::slice::Slice::new(s.as_bytes()),
32 }
33 }
34 pub const fn as_str(self) -> &'a str {
36 unsafe { core::str::from_utf8_unchecked(self.inner.as_slice()) }
38 }
39}
40impl<'a> From<&'a str> for Str<'a> {
41 fn from(value: &'a str) -> Self {
42 Self::new(value)
43 }
44}
45impl<'a> From<&'a mut str> for Str<'a> {
46 fn from(value: &'a mut str) -> Self {
47 Self::from(&*value)
48 }
49}
50impl<'a> From<Str<'a>> for &'a str {
51 fn from(value: Str<'a>) -> Self {
52 value.as_str()
53 }
54}
55impl AsRef<str> for Str<'_> {
56 fn as_ref(&self) -> &str {
57 self
58 }
59}
60impl Deref for Str<'_> {
61 type Target = str;
62 fn deref(&self) -> &Self::Target {
63 self.as_str()
64 }
65}
66impl core::fmt::Debug for Str<'_> {
67 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
68 self.deref().fmt(f)
69 }
70}
71impl core::fmt::Display for Str<'_> {
72 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73 self.deref().fmt(f)
74 }
75}
76impl core::cmp::PartialOrd for Str<'_> {
77 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
78 self.deref().partial_cmp(other.deref())
79 }
80}
81
82#[stabby::stabby]
84pub struct StrMut<'a> {
85 pub(crate) inner: crate::slice::SliceMut<'a, u8>,
86}
87impl AsRef<str> for StrMut<'_> {
88 fn as_ref(&self) -> &str {
89 self
90 }
91}
92impl Deref for StrMut<'_> {
93 type Target = str;
94 fn deref(&self) -> &Self::Target {
95 unsafe { core::str::from_utf8_unchecked(&self.inner) }
97 }
98}
99impl DerefMut for StrMut<'_> {
100 fn deref_mut(&mut self) -> &mut Self::Target {
101 unsafe { core::str::from_utf8_unchecked_mut(&mut self.inner) }
103 }
104}
105impl<'a> From<&'a mut str> for StrMut<'a> {
106 fn from(value: &'a mut str) -> Self {
107 Self {
108 inner: unsafe { value.as_bytes_mut().into() },
109 }
110 }
111}
112impl<'a> From<StrMut<'a>> for Str<'a> {
113 fn from(value: StrMut<'a>) -> Self {
114 Self {
115 inner: value.inner.into(),
116 }
117 }
118}
119impl<'a> From<StrMut<'a>> for &'a mut str {
120 fn from(value: StrMut<'a>) -> Self {
121 unsafe { core::str::from_utf8_unchecked_mut(value.inner.into()) }
123 }
124}
125
126impl<'a> From<StrMut<'a>> for &'a str {
127 fn from(value: StrMut<'a>) -> Self {
128 unsafe { core::str::from_utf8_unchecked(value.inner.into()) }
130 }
131}
132
133#[cfg(feature = "serde")]
134mod serde_impl {
135 use super::*;
136 use serde::{de::Visitor, Deserialize, Serialize};
137 impl<'a> Serialize for Str<'a> {
138 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139 where
140 S: serde::Serializer,
141 {
142 serializer.serialize_str(self)
143 }
144 }
145 impl<'a> Serialize for StrMut<'a> {
146 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
147 where
148 S: serde::Serializer,
149 {
150 serializer.serialize_str(self)
151 }
152 }
153 impl<'a> Deserialize<'a> for Str<'a> {
154 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
155 where
156 D: serde::Deserializer<'a>,
157 {
158 deserializer.deserialize_str(StrVisitor(core::marker::PhantomData))
159 }
160 }
161 struct StrVisitor<'a>(core::marker::PhantomData<Str<'a>>);
162 impl<'a> Visitor<'a> for StrVisitor<'a> {
163 type Value = Str<'a>;
164 fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
165 where
166 E: serde::de::Error,
167 {
168 Ok(v.into())
169 }
170 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
171 write!(formatter, "A borrowed_str")
172 }
173 }
174}