use std::fmt::{Debug, Display};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::slice::SliceIndex;
use crate::general::{Unsize, UnsizeObserver};
use crate::helper::macros::delegate_methods;
use crate::helper::shallow::{ShallowDelegate, ShallowMut};
use crate::helper::{AsDeref, AsDerefMut, Invalidate, Pointer, QuasiObserver, Succ, Unsigned, Zero};
use crate::impls::strings::string::StringObserverState;
use crate::mutation::Mutations;
use crate::observe::{DefaultSpec, Observe, Observer, RefObserve, SerializeObserver};
pub trait StrObserverState: Invalidate<str> + Sized {
fn observe(value: &str) -> Self;
}
pub trait StrSerializeObserverState<S: ?Sized, D>: Invalidate<str> {
fn flush(&mut self, ptr: &mut Pointer<S>) -> Mutations;
}
pub struct StrObserver<'ob, V, S: ?Sized, D = Zero> {
pub(super) ptr: Pointer<S>,
pub(super) state: V,
phantom: PhantomData<&'ob mut D>,
}
impl<'ob, V, S: ?Sized, D> Deref for StrObserver<'ob, V, S, D> {
type Target = Pointer<S>;
fn deref(&self) -> &Self::Target {
&self.ptr
}
}
impl<'ob, V, S: ?Sized, D> DerefMut for StrObserver<'ob, V, S, D> {
fn deref_mut(&mut self) -> &mut Self::Target {
std::ptr::from_mut(self).expose_provenance();
Pointer::invalidate(&mut self.ptr);
&mut self.ptr
}
}
impl<'ob, V, S: ?Sized, D> QuasiObserver for StrObserver<'ob, V, S, D>
where
V: Invalidate<str>,
D: Unsigned,
S: AsDeref<D, Target = str>,
{
type Head = S;
type OuterDepth = Succ<Zero>;
type InnerDepth = D;
fn invalidate(this: &mut Self) {
Invalidate::invalidate(&mut this.state, (*this.ptr).as_deref());
}
}
impl<'ob, V, S: ?Sized, D> Observer for StrObserver<'ob, V, S, D>
where
V: StrObserverState,
D: Unsigned,
S: AsDerefMut<D, Target = str>,
{
fn observe(head: &mut Self::Head) -> Self {
let this = Self {
state: V::observe(head.as_deref_mut()),
ptr: Pointer::new(head),
phantom: PhantomData,
};
Pointer::register_state::<_, D>(&this.ptr, &this.state);
this
}
unsafe fn relocate(this: &mut Self, head: &mut Self::Head) {
Pointer::set(this, head);
}
}
impl<'ob, V, S: ?Sized, D> SerializeObserver for StrObserver<'ob, V, S, D>
where
V: StrSerializeObserverState<S, D>,
D: Unsigned,
S: AsDeref<D, Target = str>,
{
unsafe fn flush(this: &mut Self) -> Mutations {
this.state.flush(&mut this.ptr)
}
}
impl<'ob, V, S: ?Sized, D> StrObserver<'ob, V, S, D>
where
V: Invalidate<()> + Invalidate<str>,
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], V> {
let inner = unsafe { (*self.ptr).as_deref_mut().as_bytes_mut() };
ShallowMut::new(inner, &raw mut self.state)
}
pub fn get_mut<I: SliceIndex<str, Output = str>>(
&mut self,
i: I,
) -> Option<StrObserver<'_, ShallowDelegate<V>, str>> {
let output = (*self.ptr).as_deref_mut().get_mut(i)?;
let state = ShallowDelegate::new(&raw mut self.state);
let ob = StrObserver {
ptr: Pointer::new(output),
state,
phantom: PhantomData,
};
Pointer::register_state::<_, Zero>(&ob.ptr, &ob.state);
Some(ob)
}
pub unsafe fn get_unchecked_mut<I: SliceIndex<str, Output = str>>(
&mut self,
i: I,
) -> StrObserver<'_, ShallowDelegate<V>, str> {
let output = unsafe { (*self.ptr).as_deref_mut().get_unchecked_mut(i) };
let state = ShallowDelegate::new(&raw mut self.state);
let ob = StrObserver {
ptr: Pointer::new(output),
state,
phantom: PhantomData,
};
Pointer::register_state::<_, Zero>(&ob.ptr, &ob.state);
ob
}
pub fn split_at_mut(
&mut self,
mid: usize,
) -> (
StrObserver<'_, ShallowDelegate<V>, str>,
StrObserver<'_, ShallowDelegate<V>, str>,
) {
let state = &raw mut self.state;
let (left, right) = (*self.ptr).as_deref_mut().split_at_mut(mid);
let left_ob = StrObserver {
ptr: Pointer::new(left),
state: ShallowDelegate::new(state),
phantom: PhantomData,
};
Pointer::register_state::<_, Zero>(&left_ob.ptr, &left_ob.state);
let right_ob = StrObserver {
ptr: Pointer::new(right),
state: ShallowDelegate::new(state),
phantom: PhantomData,
};
Pointer::register_state::<_, Zero>(&right_ob.ptr, &right_ob.state);
(left_ob, right_ob)
}
#[allow(clippy::type_complexity)]
pub fn split_at_mut_checked(
&mut self,
mid: usize,
) -> Option<(
StrObserver<'_, ShallowDelegate<V>, str>,
StrObserver<'_, ShallowDelegate<V>, str>,
)> {
let state = &raw mut self.state;
let (left, right) = (*self.ptr).as_deref_mut().split_at_mut_checked(mid)?;
let left_ob = StrObserver {
ptr: Pointer::new(left),
state: ShallowDelegate::new(state),
phantom: PhantomData,
};
Pointer::register_state::<_, Zero>(&left_ob.ptr, &left_ob.state);
let right_ob = StrObserver {
ptr: Pointer::new(right),
state: ShallowDelegate::new(state),
phantom: PhantomData,
};
Pointer::register_state::<_, Zero>(&right_ob.ptr, &right_ob.state);
Some((left_ob, right_ob))
}
}
impl<'ob, V, S: ?Sized, D, I> Index<I> for StrObserver<'ob, V, S, D>
where
V: Invalidate<str>,
D: Unsigned,
S: AsDeref<D, Target = str>,
I: SliceIndex<str>,
{
type Output = I::Output;
fn index(&self, index: I) -> &Self::Output {
self.untracked_ref().index(index)
}
}
impl<'ob, V, S: ?Sized, D, I> IndexMut<I> for StrObserver<'ob, V, S, D>
where
V: Invalidate<str>,
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)
}
}
impl<'ob, V, S: ?Sized, D> Debug for StrObserver<'ob, V, S, D>
where
V: Invalidate<str>,
D: Unsigned,
S: AsDeref<D, Target = str>,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("StrObserver").field(&self.untracked_ref()).finish()
}
}
impl<'ob, V, S: ?Sized, D> Display for StrObserver<'ob, V, S, D>
where
V: Invalidate<str>,
D: Unsigned,
S: AsDeref<D, Target = str>,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(self.untracked_ref(), f)
}
}
macro_rules! generic_impl_cmp {
($(impl $([$($gen:tt)*])? _ for $ty:ty);* $(;)?) => {
$(
impl<'ob, $($($gen)*,)? V, S: ?Sized, D> PartialEq<$ty> for StrObserver<'ob, V, 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)*,)? V, S: ?Sized, D> PartialOrd<$ty> for StrObserver<'ob, V, 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 Unsize for str {
type Slice = Self;
fn len(&self) -> usize {
self.chars().count()
}
fn range_from(&self, from: usize) -> &Self::Slice {
&self[from..]
}
}
impl Observe for str {
type Observer<'ob, S, D>
= StrObserver<'ob, StringObserverState, S, D>
where
Self: 'ob,
D: Unsigned,
S: AsDerefMut<D, Target = Self> + ?Sized + 'ob;
type Spec = DefaultSpec;
}
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;
}
#[cfg(test)]
mod tests {
use morphix_test_utils::*;
use serde_json::json;
use super::*;
use crate::adapter::Json;
use crate::observe::SerializeObserverExt;
#[test]
fn split_at_mut() {
let mut s = String::from("hello world");
let mut ob: StrObserver<'_, StringObserverState, str> = Observer::observe(&mut s[..]);
let (mut left, mut right) = ob.split_at_mut(5);
unsafe {
left.as_bytes_mut()[0] = b'H';
right.as_bytes_mut()[0] = b'_';
left.as_bytes_mut()[4] = b'O';
right.as_bytes_mut()[5] = b'D';
}
let Json(mutation) = ob.flush().unwrap();
assert_eq!(mutation, Some(replace!(_, json!("HellO_worlD"))));
}
}