use std::ops::{Index, IndexMut};
use std::slice::SliceIndex;
use crate::general::{Unsize, UnsizeObserver};
use crate::helper::macros::{delegate_methods, shallow_observer};
use crate::helper::{AsDeref, AsDerefMut, QuasiObserver, Unsigned};
use crate::impls::strings::shallow::ShallowMut;
use crate::observe::{DefaultSpec, RefObserve};
shallow_observer! {
struct StrObserver(str);
}
impl Unsize for str {
type Slice = Self;
fn len(&self) -> usize {
self.chars().count()
}
fn range_from(&self, from: usize) -> &Self::Slice {
&self[from..]
}
}
impl RefObserve for str {
type Observer<'ob, S, D>
= UnsizeObserver<'ob, S, D>
where
Self: 'ob,
D: Unsigned,
S: AsDeref<D, Target = Self> + ?Sized + 'ob;
type Spec = DefaultSpec;
}
impl<'ob, S: ?Sized, D> StrObserver<'ob, S, D>
where
D: Unsigned,
S: AsDerefMut<D, Target = str>,
{
fn nonempty_mut(&mut self) -> &mut str {
if (*self).untracked_ref().is_empty() {
self.untracked_mut()
} else {
self.tracked_mut()
}
}
delegate_methods! { nonempty_mut() as str =>
pub fn as_mut_ptr(&mut self) -> *mut u8;
pub fn make_ascii_uppercase(&mut self);
pub fn make_ascii_lowercase(&mut self);
}
pub unsafe fn as_bytes_mut(&mut self) -> ShallowMut<'_, [u8]> {
let inner = unsafe { (*self.ptr).as_deref_mut().as_bytes_mut() };
ShallowMut::new(inner, &raw mut self.mutated)
}
pub fn get_mut<I: SliceIndex<str, Output = str>>(&mut self, i: I) -> Option<ShallowMut<'_, str>> {
let output = (*self.ptr).as_deref_mut().get_mut(i)?;
Some(ShallowMut::new(output, &raw mut self.mutated))
}
pub unsafe fn get_unchecked_mut<I: SliceIndex<str, Output = str>>(&mut self, i: I) -> ShallowMut<'_, str> {
let output = unsafe { (*self.ptr).as_deref_mut().get_unchecked_mut(i) };
ShallowMut::new(output, &raw mut self.mutated)
}
pub fn split_at_mut(&mut self, mid: usize) -> (ShallowMut<'_, str>, ShallowMut<'_, str>) {
let (left, right) = (*self.ptr).as_deref_mut().split_at_mut(mid);
(
ShallowMut::new(left, &raw mut self.mutated),
ShallowMut::new(right, &raw mut self.mutated),
)
}
pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(ShallowMut<'_, str>, ShallowMut<'_, str>)> {
let (left, right) = (*self.ptr).as_deref_mut().split_at_mut_checked(mid)?;
Some((
ShallowMut::new(left, &raw mut self.mutated),
ShallowMut::new(right, &raw mut self.mutated),
))
}
}
impl<'ob, S: ?Sized, D, I> Index<I> for StrObserver<'ob, S, D>
where
D: Unsigned,
S: AsDerefMut<D, Target = str>,
I: SliceIndex<str>,
{
type Output = I::Output;
fn index(&self, index: I) -> &Self::Output {
self.untracked_ref().index(index)
}
}
impl<'ob, S: ?Sized, D, I> IndexMut<I> for StrObserver<'ob, S, D>
where
D: Unsigned,
S: AsDerefMut<D, Target = str>,
I: SliceIndex<str>,
{
fn index_mut(&mut self, index: I) -> &mut Self::Output {
self.tracked_mut().index_mut(index)
}
}
macro_rules! generic_impl_cmp {
($(impl $([$($gen:tt)*])? _ for $ty:ty);* $(;)?) => {
$(
impl<'ob, $($($gen)*,)? S: ?Sized, D> PartialEq<$ty> for StrObserver<'ob, S, D>
where
D: Unsigned,
S: AsDeref<D>,
S::Target: PartialEq<$ty>,
{
fn eq(&self, other: &$ty) -> bool {
(***self).as_deref().eq(other)
}
}
impl<'ob, $($($gen)*,)? S: ?Sized, D> PartialOrd<$ty> for StrObserver<'ob, S, D>
where
D: Unsigned,
S: AsDeref<D>,
S::Target: PartialOrd<$ty>,
{
fn partial_cmp(&self, other: &$ty) -> Option<std::cmp::Ordering> {
(***self).as_deref().partial_cmp(other)
}
}
)*
};
}
generic_impl_cmp! {
impl _ for str;
impl _ for String;
impl _ for std::ffi::OsStr;
impl _ for std::ffi::OsString;
impl _ for std::path::Path;
impl _ for std::path::PathBuf;
impl ['a] _ for std::borrow::Cow<'a, str>;
}
impl ShallowMut<'_, str> {
fn nonempty_mut(&mut self) -> &mut str {
if (*self).untracked_ref().is_empty() {
self.untracked_mut()
} else {
self.tracked_mut()
}
}
delegate_methods! { nonempty_mut() as str =>
pub fn as_mut_ptr(&mut self) -> *mut u8;
pub fn make_ascii_uppercase(&mut self);
pub fn make_ascii_lowercase(&mut self);
}
pub unsafe fn as_bytes_mut(&mut self) -> ShallowMut<'_, [u8]> {
let inner = unsafe { self.inner.as_bytes_mut() };
ShallowMut::new(inner, self.mutated)
}
pub fn get_mut<I: SliceIndex<str, Output = str>>(&mut self, i: I) -> Option<ShallowMut<'_, str>> {
let output = self.inner.get_mut(i)?;
Some(ShallowMut::new(output, self.mutated))
}
pub unsafe fn get_unchecked_mut<I: SliceIndex<str, Output = str>>(&mut self, i: I) -> ShallowMut<'_, str> {
let output = unsafe { self.inner.get_unchecked_mut(i) };
ShallowMut::new(output, self.mutated)
}
pub fn split_at_mut(&mut self, mid: usize) -> (ShallowMut<'_, str>, ShallowMut<'_, str>) {
let (left, right) = self.inner.split_at_mut(mid);
(
ShallowMut::new(left, self.mutated),
ShallowMut::new(right, self.mutated),
)
}
pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(ShallowMut<'_, str>, ShallowMut<'_, str>)> {
let (left, right) = self.inner.split_at_mut_checked(mid)?;
Some((
ShallowMut::new(left, self.mutated),
ShallowMut::new(right, self.mutated),
))
}
}