1use std::fmt::Debug;
2use std::ops::{Index, IndexMut};
3use std::slice::SliceIndex;
4
5use crate::Observe;
6use crate::general::UnsizeObserver;
7use crate::helper::macros::{delegate_methods, shallow_observer};
8use crate::helper::{AsDeref, AsDerefMut, QuasiObserver, Unsigned};
9use crate::impls::slices::shallow::ShallowMut;
10use crate::observe::{DefaultSpec, RefObserve};
11
12shallow_observer! {
13 impl StrObserver for str;
14}
15
16impl RefObserve for str {
17 type Observer<'ob, S, D>
18 = UnsizeObserver<'ob, S, D>
19 where
20 Self: 'ob,
21 D: Unsigned,
22 S: AsDeref<D, Target = Self> + ?Sized + 'ob;
23
24 type Spec = DefaultSpec;
25}
26
27impl<'ob, S: ?Sized, D> StrObserver<'ob, S, D>
28where
29 D: Unsigned,
30 S: AsDerefMut<D, Target = str>,
31{
32 fn nonempty_mut(&mut self) -> &mut str {
33 if (*self).untracked_ref().is_empty() {
34 self.untracked_mut()
35 } else {
36 self.tracked_mut()
37 }
38 }
39
40 delegate_methods! { nonempty_mut() as str =>
41 pub fn as_mut_ptr(&mut self) -> *mut u8;
42 pub fn make_ascii_uppercase(&mut self);
43 pub fn make_ascii_lowercase(&mut self);
44 }
45
46 pub unsafe fn as_bytes_mut(&mut self) -> ShallowMut<'_, [u8]> {
48 let inner = unsafe { (*self.ptr).as_deref_mut().as_bytes_mut() };
49 ShallowMut::new(inner, &raw mut self.mutated)
50 }
51
52 pub fn get_mut<I: SliceIndex<str, Output = str>>(&mut self, i: I) -> Option<ShallowMut<'_, str>> {
54 let output = (*self.ptr).as_deref_mut().get_mut(i)?;
55 Some(ShallowMut::new(output, &raw mut self.mutated))
56 }
57
58 pub unsafe fn get_unchecked_mut<I: SliceIndex<str, Output = str>>(&mut self, i: I) -> ShallowMut<'_, str> {
60 let output = unsafe { (*self.ptr).as_deref_mut().get_unchecked_mut(i) };
61 ShallowMut::new(output, &raw mut self.mutated)
62 }
63
64 pub fn split_at_mut(&mut self, mid: usize) -> (ShallowMut<'_, str>, ShallowMut<'_, str>) {
66 let (left, right) = (*self.ptr).as_deref_mut().split_at_mut(mid);
67 (
68 ShallowMut::new(left, &raw mut self.mutated),
69 ShallowMut::new(right, &raw mut self.mutated),
70 )
71 }
72
73 pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(ShallowMut<'_, str>, ShallowMut<'_, str>)> {
75 let (left, right) = (*self.ptr).as_deref_mut().split_at_mut_checked(mid)?;
76 Some((
77 ShallowMut::new(left, &raw mut self.mutated),
78 ShallowMut::new(right, &raw mut self.mutated),
79 ))
80 }
81}
82
83impl<'ob, S: ?Sized, D> AsMut<str> for StrObserver<'ob, S, D>
84where
85 D: Unsigned,
86 S: AsDerefMut<D, Target = str>,
87{
88 fn as_mut(&mut self) -> &mut str {
89 self.tracked_mut()
90 }
91}
92
93impl<'ob, S: ?Sized, D> Debug for StrObserver<'ob, S, D>
94where
95 D: Unsigned,
96 S: AsDerefMut<D, Target = str>,
97{
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 f.debug_tuple("StrObserver").field(&self.untracked_ref()).finish()
100 }
101}
102
103impl<'ob, S1: ?Sized, S2: ?Sized, D1, D2> PartialEq<StrObserver<'ob, S2, D2>> for StrObserver<'ob, S1, D1>
104where
105 D1: Unsigned,
106 D2: Unsigned,
107 S1: AsDeref<D1>,
108 S2: AsDeref<D2>,
109 S1::Target: PartialEq<S2::Target>,
110{
111 fn eq(&self, other: &StrObserver<'ob, S2, D2>) -> bool {
112 self.untracked_ref().eq(other.untracked_ref())
113 }
114}
115
116impl<'ob, S: ?Sized, D> Eq for StrObserver<'ob, S, D>
117where
118 D: Unsigned,
119 S: AsDerefMut<D, Target = str>,
120{
121}
122
123impl<'ob, S1: ?Sized, S2: ?Sized, D1, D2> PartialOrd<StrObserver<'ob, S2, D2>> for StrObserver<'ob, S1, D1>
124where
125 D1: Unsigned,
126 D2: Unsigned,
127 S1: AsDeref<D1>,
128 S2: AsDeref<D2>,
129 S1::Target: PartialOrd<S2::Target>,
130{
131 fn partial_cmp(&self, other: &StrObserver<'ob, S2, D2>) -> Option<std::cmp::Ordering> {
132 self.untracked_ref().partial_cmp(other.untracked_ref())
133 }
134}
135
136impl<'ob, S: ?Sized, D> Ord for StrObserver<'ob, S, D>
137where
138 D: Unsigned,
139 S: AsDerefMut<D, Target = str>,
140{
141 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
142 self.untracked_ref().cmp(other.untracked_ref())
143 }
144}
145
146impl<'ob, S: ?Sized, D, I> Index<I> for StrObserver<'ob, S, D>
147where
148 D: Unsigned,
149 S: AsDerefMut<D, Target = str>,
150 I: SliceIndex<str>,
151{
152 type Output = I::Output;
153
154 fn index(&self, index: I) -> &Self::Output {
155 self.untracked_ref().index(index)
156 }
157}
158
159impl<'ob, S: ?Sized, D, I> IndexMut<I> for StrObserver<'ob, S, D>
160where
161 D: Unsigned,
162 S: AsDerefMut<D, Target = str>,
163 I: SliceIndex<str>,
164{
165 fn index_mut(&mut self, index: I) -> &mut Self::Output {
166 self.tracked_mut().index_mut(index)
167 }
168}
169
170macro_rules! generic_impl_cmp {
171 ($(impl $([$($gen:tt)*])? _ for $ty:ty);* $(;)?) => {
172 $(
173 impl<'ob, $($($gen)*,)? S: ?Sized, D> PartialEq<$ty> for StrObserver<'ob, S, D>
174 where
175 D: Unsigned,
176 S: AsDeref<D>,
177 S::Target: PartialEq<$ty>,
178 {
179 fn eq(&self, other: &$ty) -> bool {
180 (***self).as_deref().eq(other)
181 }
182 }
183
184 impl<'ob, $($($gen)*,)? S: ?Sized, D> PartialOrd<$ty> for StrObserver<'ob, S, D>
185 where
186 D: Unsigned,
187 S: AsDeref<D>,
188 S::Target: PartialOrd<$ty>,
189 {
190 fn partial_cmp(&self, other: &$ty) -> Option<std::cmp::Ordering> {
191 (***self).as_deref().partial_cmp(other)
192 }
193 }
194 )*
195 };
196}
197
198generic_impl_cmp! {
199 impl _ for str;
200 impl _ for String;
201 impl _ for std::ffi::OsStr;
202 impl _ for std::ffi::OsString;
203 impl _ for std::path::Path;
204 impl _ for std::path::PathBuf;
205 impl ['a] _ for std::borrow::Cow<'a, str>;
206}
207
208impl<'ob> ShallowMut<'ob, str> {
209 fn nonempty_mut(&mut self) -> &mut str {
210 if !self.inner.is_empty() {
211 unsafe { *self.mutated = true }
212 }
213 self.inner
214 }
215
216 delegate_methods! { nonempty_mut() as str =>
217 pub fn as_mut_ptr(&mut self) -> *mut u8;
218 pub fn make_ascii_uppercase(&mut self);
219 pub fn make_ascii_lowercase(&mut self);
220 }
221
222 pub unsafe fn as_bytes_mut(&mut self) -> ShallowMut<'_, [u8]> {
224 let inner = unsafe { self.inner.as_bytes_mut() };
225 ShallowMut::new(inner, self.mutated)
226 }
227
228 pub fn get_mut<I: SliceIndex<str, Output = str>>(&mut self, i: I) -> Option<ShallowMut<'_, str>> {
230 let output = self.inner.get_mut(i)?;
231 Some(ShallowMut::new(output, self.mutated))
232 }
233
234 pub unsafe fn get_unchecked_mut<I: SliceIndex<str, Output = str>>(&mut self, i: I) -> ShallowMut<'_, str> {
236 let output = unsafe { self.inner.get_unchecked_mut(i) };
237 ShallowMut::new(output, self.mutated)
238 }
239
240 pub fn split_at_mut(&mut self, mid: usize) -> (ShallowMut<'_, str>, ShallowMut<'_, str>) {
242 let (left, right) = self.inner.split_at_mut(mid);
243 (
244 ShallowMut::new(left, self.mutated),
245 ShallowMut::new(right, self.mutated),
246 )
247 }
248
249 pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(ShallowMut<'_, str>, ShallowMut<'_, str>)> {
251 let (left, right) = self.inner.split_at_mut_checked(mid)?;
252 Some((
253 ShallowMut::new(left, self.mutated),
254 ShallowMut::new(right, self.mutated),
255 ))
256 }
257}