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(hashes: [MapHash<S>; 3], borrowed: &'a mut T) -> Self {
56 Self { inner: Some(RefMutInner { hashes, borrowed }) }
57 }
58
59 pub fn reborrow(&mut self) -> RefMut<'_, T, S> {
63 let inner = self.inner.as_mut().unwrap();
64 let borrowed = &mut *inner.borrowed;
65 RefMut::new(inner.hashes.clone(), borrowed)
66 }
67
68 pub fn into_ref(mut self) -> &'a T {
70 let inner = self.inner.take().unwrap();
71 inner.into_ref()
72 }
73}
74
75impl<T: TriHashItem, S: Clone + BuildHasher> Drop for RefMut<'_, T, S> {
76 fn drop(&mut self) {
77 if let Some(inner) = self.inner.take() {
78 inner.into_ref();
79 }
80 }
81}
82
83impl<T: TriHashItem, S: Clone + BuildHasher> Deref for RefMut<'_, T, S> {
84 type Target = T;
85
86 fn deref(&self) -> &Self::Target {
87 self.inner.as_ref().unwrap().borrowed
88 }
89}
90
91impl<T: TriHashItem, S: Clone + BuildHasher> DerefMut for RefMut<'_, T, S> {
92 fn deref_mut(&mut self) -> &mut Self::Target {
93 self.inner.as_mut().unwrap().borrowed
94 }
95}
96
97impl<T: TriHashItem + fmt::Debug, S: Clone + BuildHasher> fmt::Debug
98 for RefMut<'_, T, S>
99{
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 match self.inner {
102 Some(ref inner) => inner.fmt(f),
103 None => {
104 f.debug_struct("RefMut").field("borrowed", &"missing").finish()
105 }
106 }
107 }
108}
109
110struct RefMutInner<'a, T: TriHashItem, S> {
111 hashes: [MapHash<S>; 3],
112 borrowed: &'a mut T,
113}
114
115impl<'a, T: TriHashItem, S: BuildHasher> RefMutInner<'a, T, S> {
116 fn into_ref(self) -> &'a T {
117 if !self.hashes[0].is_same_hash(self.borrowed.key1()) {
118 panic!("key1 changed during RefMut borrow");
119 }
120 if !self.hashes[1].is_same_hash(self.borrowed.key2()) {
121 panic!("key2 changed during RefMut borrow");
122 }
123 if !self.hashes[2].is_same_hash(self.borrowed.key3()) {
124 panic!("key3 changed during RefMut borrow");
125 }
126
127 self.borrowed
128 }
129}
130
131impl<T: TriHashItem + fmt::Debug, S> fmt::Debug for RefMutInner<'_, T, S> {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 self.borrowed.fmt(f)
134 }
135}