1#[cfg(doc)]
4use core::cell::RefCell;
5use core::{
6 cell::{Ref, RefMut},
7 ops::{Deref, DerefMut},
8};
9
10use generic_array::{arr, typenum::U0, ArrayLength, GenericArray};
11
12use crate::clone_arr::clone_arr;
13
14pub struct NestedRefMut<'a, T, N>
35where
36 T: ?Sized,
37 N: ArrayLength<Ref<'a, ()>>,
38{
39 pub(crate) inner: RefMut<'a, T>,
41 pub(crate) outer: GenericArray<Ref<'a, ()>, N>,
45}
46
47impl<'a, T> NestedRefMut<'a, T, U0>
48where
49 T: ?Sized,
50{
51 #[must_use]
53 #[inline]
54 pub fn new(inner: RefMut<'a, T>) -> Self {
55 let outer = arr![Ref<'a, ()>;];
57 Self { inner, outer }
58 }
59}
60
61impl<'a, T, N> NestedRefMut<'a, T, N>
62where
63 T: ?Sized,
64 N: ArrayLength<Ref<'a, ()>>,
65{
66 #[inline]
71 pub fn map<U, F>(orig: Self, f: F) -> NestedRefMut<'a, U, N>
72 where
73 U: ?Sized,
74 F: FnOnce(&mut T) -> &mut U,
75 {
76 NestedRefMut {
78 inner: RefMut::map(orig.inner, f),
79 outer: orig.outer,
80 }
81 }
82
83 #[inline]
90 #[allow(clippy::missing_errors_doc)]
91 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<NestedRefMut<'a, U, N>, Self>
92 where
93 U: ?Sized,
94 F: FnOnce(&mut T) -> Option<&mut U>,
95 {
96 let outer = orig.outer;
98 match RefMut::filter_map(orig.inner, f) {
100 Ok(inner) => Ok(NestedRefMut { inner, outer }),
101 Err(inner) => Err(NestedRefMut { inner, outer }),
102 }
103 }
104
105 #[inline]
111 pub fn map_split<U, V, F>(orig: Self, f: F) -> (NestedRefMut<'a, U, N>, NestedRefMut<'a, V, N>)
112 where
113 U: ?Sized,
114 V: ?Sized,
115 F: FnOnce(&mut T) -> (&mut U, &mut V),
116 {
117 let outer_a = clone_arr(&orig.outer);
119 let outer_b = orig.outer;
120 let (inner_a, inner_b) = RefMut::map_split(orig.inner, f);
122 (
123 NestedRefMut {
124 inner: inner_a,
125 outer: outer_a,
126 },
127 NestedRefMut {
128 inner: inner_b,
129 outer: outer_b,
130 },
131 )
132 }
133}
134
135impl<'a, T, N> Deref for NestedRefMut<'a, T, N>
136where
137 T: ?Sized,
138 N: ArrayLength<Ref<'a, ()>>,
139{
140 type Target = T;
141
142 #[inline]
143 fn deref(&self) -> &Self::Target {
144 &self.inner
145 }
146}
147
148impl<'a, T, N> DerefMut for NestedRefMut<'a, T, N>
149where
150 T: ?Sized,
151 N: ArrayLength<Ref<'a, ()>>,
152{
153 #[inline]
154 fn deref_mut(&mut self) -> &mut Self::Target {
155 &mut self.inner
156 }
157}
158
159#[cfg(test)]
160mod tests {
161 use core::cell::RefCell;
162
163 use crate::{NestedRef, NestedRefMut};
164
165 #[test]
167 fn simple() {
168 let rc = RefCell::new(0);
170 let mut nr = NestedRefMut::new(rc.borrow_mut());
171
172 assert_eq!(*nr, 0);
173 *nr = 1;
174 assert_eq!(*nr, 1);
175 }
176
177 #[test]
179 fn deep() {
180 let rc = RefCell::new(RefCell::new(RefCell::new(0)));
182 let nr = NestedRef::new(rc.borrow());
183 let nr = NestedRef::map_ref(nr, RefCell::borrow);
184 let mut nr = NestedRef::map_ref_mut(nr, RefCell::borrow_mut);
185
186 assert_eq!(*nr, 0);
187 *nr = 1;
188 assert_eq!(*nr, 1);
189 }
190
191 #[test]
193 fn map() {
194 let rc = RefCell::new((0, 0));
196 let nr = NestedRefMut::new(rc.borrow_mut());
197 let mut nr = NestedRefMut::map(nr, |x| &mut x.0);
198
199 assert_eq!(*nr, 0);
200 *nr = 1;
201 assert_eq!(*nr, 1);
202 }
203
204 #[test]
206 fn filter_map() {
207 let rc = RefCell::new(0);
209 let nr = NestedRefMut::new(rc.borrow_mut());
210 let nr = NestedRefMut::filter_map::<(), _>(nr, |_| None)
211 .map(|_| ())
212 .expect_err("This filter_map should fail");
213 let mut nr = NestedRefMut::filter_map(nr, |x| Some(x))
214 .map_err(|_| ())
215 .expect("This filter_map should succeed");
216
217 assert_eq!(*nr, 0);
218 *nr = 1;
219 assert_eq!(*nr, 1);
220 }
221
222 #[test]
224 fn map_split() {
225 let rc = RefCell::new((0, 0));
227 let nr = NestedRefMut::new(rc.borrow_mut());
228 let (mut nr, _nr2) = NestedRefMut::map_split(nr, |x| (&mut x.0, &mut x.1));
229
230 assert_eq!(*nr, 0);
231 *nr = 1;
232 assert_eq!(*nr, 1);
233 }
234}