use std::{fmt::Debug, hash::Hash};
use crate::subscriptions::{PathKey, StoreSubscriptions, TinyVec};
use dioxus_core::Subscribers;
use dioxus_signals::{
BorrowError, BorrowMutError, MappedMutSignal, Readable, ReadableRef, Writable, WritableExt,
WritableRef,
};
#[derive(PartialEq)]
pub struct SelectorScope<Lens> {
path: TinyVec,
store: StoreSubscriptions,
write: Lens,
}
impl<Lens> Debug for SelectorScope<Lens> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("SelectorScope")
.field("path", &self.path)
.finish()
}
}
impl<Lens> Clone for SelectorScope<Lens>
where
Lens: Clone,
{
fn clone(&self) -> Self {
Self {
path: self.path,
store: self.store,
write: self.write.clone(),
}
}
}
impl<Lens> Copy for SelectorScope<Lens> where Lens: Copy {}
impl<Lens> SelectorScope<Lens> {
pub(crate) fn new(path: TinyVec, store: StoreSubscriptions, write: Lens) -> Self {
Self { path, store, write }
}
pub fn hash_child<U: ?Sized, T, F, FMut>(
self,
index: &impl Hash,
map: F,
map_mut: FMut,
) -> SelectorScope<MappedMutSignal<U, Lens, F, FMut>>
where
F: Fn(&T) -> &U,
FMut: Fn(&mut T) -> &mut U,
{
let hash = self.store.hash(index);
self.child(hash, map, map_mut)
}
pub fn child<U: ?Sized, T, F, FMut>(
self,
index: PathKey,
map: F,
map_mut: FMut,
) -> SelectorScope<MappedMutSignal<U, Lens, F, FMut>>
where
F: Fn(&T) -> &U,
FMut: Fn(&mut T) -> &mut U,
{
self.child_unmapped(index).map(map, map_mut)
}
pub fn hash_child_unmapped(self, index: &impl Hash) -> SelectorScope<Lens> {
let hash = self.store.hash(index);
self.child_unmapped(hash)
}
pub fn child_unmapped(mut self, index: PathKey) -> SelectorScope<Lens> {
self.path.push(index);
self
}
pub fn map<U: ?Sized, T, F, FMut>(
self,
map: F,
map_mut: FMut,
) -> SelectorScope<MappedMutSignal<U, Lens, F, FMut>>
where
F: Fn(&T) -> &U,
FMut: Fn(&mut T) -> &mut U,
{
self.map_writer(move |write| MappedMutSignal::new(write, map, map_mut))
}
pub fn track_shallow(&self) {
self.store.track(&self.path);
}
pub fn track(&self) {
self.store.track_recursive(&self.path);
}
pub fn mark_dirty(&self) {
self.store.mark_dirty(&self.path);
}
pub fn mark_dirty_shallow(&self) {
self.store.mark_dirty_shallow(&self.path);
}
pub fn mark_dirty_at_and_after_index(&self, index: usize) {
self.store.mark_dirty_at_and_after_index(&self.path, index);
}
pub fn map_writer<W2>(self, map: impl FnOnce(Lens) -> W2) -> SelectorScope<W2> {
SelectorScope {
path: self.path,
store: self.store,
write: map(self.write),
}
}
pub fn write_untracked(&self) -> WritableRef<'static, Lens>
where
Lens: Writable,
{
self.write.write_unchecked()
}
pub(crate) fn as_ref(&self) -> SelectorScope<&Lens> {
SelectorScope {
path: self.path,
store: self.store,
write: &self.write,
}
}
}
impl<Lens: Readable> Readable for SelectorScope<Lens> {
type Target = Lens::Target;
type Storage = Lens::Storage;
fn try_read_unchecked(&self) -> Result<ReadableRef<'static, Lens>, BorrowError> {
self.track();
self.write.try_read_unchecked()
}
fn try_peek_unchecked(&self) -> Result<ReadableRef<'static, Lens>, BorrowError> {
self.write.try_peek_unchecked()
}
fn subscribers(&self) -> Subscribers {
self.store.subscribers(&self.path)
}
}
impl<Lens: Writable> Writable for SelectorScope<Lens> {
type WriteMetadata = Lens::WriteMetadata;
fn try_write_unchecked(&self) -> Result<WritableRef<'static, Lens>, BorrowMutError> {
self.mark_dirty();
self.write.try_write_unchecked()
}
}