1use std::{
2 cell::{Ref, RefMut},
3 collections::HashMap,
4 fmt::Debug,
5 hash::Hash,
6 ops::Deref,
7};
8
9use crate::{impls::leaf::LeafPathBuilder, path::Path, trackable::Trackable};
10
11#[derive(x_bow_macros::IntoPath)]
12#[into_path(prefix = crate::trackable)]
13pub struct HashMapPathBuilder<K: Eq + Clone + Hash, V, P: Path<Out = HashMap<K, V>>> {
14 inner_path: P,
15}
16
17impl<K: Eq + Clone + Hash, V, P: Path<Out = HashMap<K, V>>> Deref for HashMapPathBuilder<K, V, P> {
18 type Target = P;
19
20 fn deref(&self) -> &Self::Target {
21 &self.inner_path
22 }
23}
24
25impl<K: Eq + Clone + Hash, V> Trackable for HashMap<K, V> {
26 type PathBuilder<P: Path<Out = Self>> = HashMapPathBuilder<K, V, P>;
27
28 fn new_path_builder<P: Path<Out = Self>>(parent: P) -> Self::PathBuilder<P> {
29 HashMapPathBuilder { inner_path: parent }
30 }
31}
32
33impl<K: Eq + Clone + Hash, V, P: Path<Out = HashMap<K, V>> + Clone> Clone
34 for HashMapPathBuilder<K, V, P>
35{
36 fn clone(&self) -> Self {
37 Self {
38 inner_path: self.inner_path.clone(),
39 }
40 }
41}
42
43impl<K: Eq + Clone + Hash, V, P: Path<Out = HashMap<K, V>> + Copy> Copy
44 for HashMapPathBuilder<K, V, P>
45{
46}
47
48impl<K: Eq + Clone + Hash, V: Trackable, P: Path<Out = HashMap<K, V>>> HashMapPathBuilder<K, V, P> {
49 pub fn key(self, key: K) -> V::PathBuilder<HashMapKeyMapper<K, V, P>> {
50 V::new_path_builder(HashMapKeyMapper {
51 parent: self.inner_path,
52 key,
53 })
54 }
55}
56
57impl<K: Eq + Clone + Hash, V, P: Path<Out = HashMap<K, V>>> HashMapPathBuilder<K, V, P> {
58 pub fn key_shallow(self, key: K) -> LeafPathBuilder<HashMapKeyMapper<K, V, P>> {
59 LeafPathBuilder::new(HashMapKeyMapper {
60 parent: self.inner_path,
61 key,
62 })
63 }
64}
65
66pub struct HashMapKeyMapper<K: Eq + Clone + Hash, V, P: Path<Out = HashMap<K, V>>> {
67 parent: P,
68 key: K,
69}
70
71impl<K: Eq + Clone + Hash, V, P: Path<Out = HashMap<K, V>> + Clone> Clone
72 for HashMapKeyMapper<K, V, P>
73{
74 fn clone(&self) -> Self {
75 Self {
76 parent: self.parent.clone(),
77 key: self.key.clone(),
78 }
79 }
80}
81impl<K: Eq + Clone + Hash + Copy, V, P: Path<Out = HashMap<K, V>> + Copy> Copy
82 for HashMapKeyMapper<K, V, P>
83{
84}
85
86impl<K: Eq + Clone + Hash + Debug, V, P: Path<Out = HashMap<K, V>> + Debug> Debug
87 for HashMapKeyMapper<K, V, P>
88{
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 self.parent.fmt(f)?;
91 f.write_fmt(format_args!("→(key {:?})", self.key))
92 }
93}
94
95impl<K: Eq + Clone + Hash, V, P: Path<Out = HashMap<K, V>>> Path for HashMapKeyMapper<K, V, P> {
96 type Out = V;
97
98 fn path_borrow(&self) -> Option<Ref<'_, Self::Out>> {
99 self.parent
100 .path_borrow()
101 .and_then(|r| Ref::filter_map(r, |hm| hm.get(&self.key)).ok())
102 }
103
104 fn path_borrow_mut(&self) -> Option<RefMut<'_, Self::Out>> {
105 self.parent
106 .path_borrow_mut()
107 .and_then(|r| RefMut::filter_map(r, |hm| hm.get_mut(&self.key)).ok())
108 }
109
110 fn visit_hashes(&self, visitor: &mut crate::hash_visitor::HashVisitor) {
111 self.parent.visit_hashes(visitor);
112 self.key.hash(&mut **visitor);
113 visitor.finish_one();
114 }
115
116 fn store_wakers(&self) -> &std::cell::RefCell<crate::wakers::StoreWakers> {
117 self.parent.store_wakers()
118 }
119}