iddqd/tri_hash_map/
ref_mut.rs1use crate::{DefaultHashBuilder, TriHashItem, support::map_hash::MapHash};
2use core::{
3 fmt,
4 hash::BuildHasher,
5 ops::{Deref, DerefMut},
6};
7
8pub struct RefMut<
47 'a,
48 T: TriHashItem,
49 S: Clone + BuildHasher = DefaultHashBuilder,
50> {
51 inner: Option<RefMutInner<'a, T, S>>,
52}
53
54impl<'a, T: TriHashItem, S: Clone + BuildHasher> RefMut<'a, T, S> {
55 pub(super) fn new(
56 state: S,
57 hashes: [MapHash; 3],
58 borrowed: &'a mut T,
59 ) -> Self {
60 Self { inner: Some(RefMutInner { state, hashes, borrowed }) }
61 }
62
63 pub fn reborrow(&mut self) -> RefMut<'_, T, S> {
67 let inner = self.inner.as_mut().unwrap();
68 let borrowed = &mut *inner.borrowed;
69 RefMut::new(inner.state.clone(), inner.hashes.clone(), borrowed)
70 }
71
72 pub fn into_ref(mut self) -> &'a T {
74 let inner = self.inner.take().unwrap();
75 inner.into_ref()
76 }
77}
78
79impl<T: TriHashItem, S: Clone + BuildHasher> Drop for RefMut<'_, T, S> {
80 fn drop(&mut self) {
81 if let Some(inner) = self.inner.take() {
82 inner.into_ref();
83 }
84 }
85}
86
87impl<T: TriHashItem, S: Clone + BuildHasher> Deref for RefMut<'_, T, S> {
88 type Target = T;
89
90 fn deref(&self) -> &Self::Target {
91 self.inner.as_ref().unwrap().borrowed
92 }
93}
94
95impl<T: TriHashItem, S: Clone + BuildHasher> DerefMut for RefMut<'_, T, S> {
96 fn deref_mut(&mut self) -> &mut Self::Target {
97 self.inner.as_mut().unwrap().borrowed
98 }
99}
100
101impl<T: TriHashItem + fmt::Debug, S: Clone + BuildHasher> fmt::Debug
102 for RefMut<'_, T, S>
103{
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 match self.inner {
106 Some(ref inner) => inner.fmt(f),
107 None => {
108 f.debug_struct("RefMut").field("borrowed", &"missing").finish()
109 }
110 }
111 }
112}
113
114struct RefMutInner<'a, T: TriHashItem, S> {
115 state: S,
116 hashes: [MapHash; 3],
117 borrowed: &'a mut T,
118}
119
120impl<'a, T: TriHashItem, S: BuildHasher> RefMutInner<'a, T, S> {
121 fn into_ref(self) -> &'a T {
122 if !self.hashes[0].is_same_hash(&self.state, self.borrowed.key1()) {
123 panic!("key1 changed during RefMut borrow");
124 }
125 if !self.hashes[1].is_same_hash(&self.state, self.borrowed.key2()) {
126 panic!("key2 changed during RefMut borrow");
127 }
128 if !self.hashes[2].is_same_hash(&self.state, self.borrowed.key3()) {
129 panic!("key3 changed during RefMut borrow");
130 }
131
132 self.borrowed
133 }
134}
135
136impl<T: TriHashItem + fmt::Debug, S> fmt::Debug for RefMutInner<'_, T, S> {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 self.borrowed.fmt(f)
139 }
140}