spreadsheet_ods/ds/
detach.rs1use get_size2::GetSize;
2use std::ops::{Deref, DerefMut};
4
5#[derive(Debug, GetSize)]
6pub(crate) struct Detach<T> {
7 val: Option<Box<T>>,
8}
9
10impl<T> Default for Detach<T> {
11 fn default() -> Self {
12 Self { val: None }
13 }
14}
15
16impl<T> Clone for Detach<T>
17where
18 T: Clone,
19{
20 fn clone(&self) -> Self {
21 if let Some(t) = &self.val {
22 Detach {
23 val: Some(t.clone()),
24 }
25 } else {
26 Detach { val: None }
27 }
28 }
29}
30
31impl<T> Deref for Detach<T> {
32 type Target = T;
33
34 fn deref(&self) -> &Self::Target {
35 self.val.as_ref().expect("already detached")
36 }
37}
38
39impl<T> DerefMut for Detach<T> {
40 fn deref_mut(&mut self) -> &mut Self::Target {
41 self.val.as_mut().expect("already detached")
42 }
43}
44
45impl<T> Detach<T> {
46 #[allow(dead_code)]
47 pub(crate) fn new(val: T) -> Self {
48 Self {
49 val: Some(Box::new(val)),
50 }
51 }
52
53 #[allow(dead_code)]
55 pub(crate) fn is_detached(&self) -> bool {
56 self.val.is_none()
57 }
58
59 pub(crate) fn detach<K: Copy>(&mut self, key: K) -> Detached<K, T> {
67 let val = self.val.take().expect("already detached");
68 Detached::new(key, val)
69 }
70
71 pub(crate) fn attach<K: Copy>(&mut self, detached: Detached<K, T>) {
73 let Detached { key: _, val } = detached;
74 self.val.replace(val);
75 }
76
77 pub(crate) fn as_ref(&self) -> &T {
83 self.val.as_ref().expect("already detached")
84 }
85
86 pub(crate) fn as_mut(&mut self) -> &mut T {
92 self.val.as_mut().expect("already detached")
93 }
94
95 pub(crate) fn take(mut self) -> T {
101 *self.val.take().expect("already detached")
102 }
103}
104
105impl<T> From<T> for Detach<T> {
106 fn from(val: T) -> Self {
107 Self {
108 val: Some(Box::new(val)),
109 }
110 }
111}
112
113#[derive(Debug)]
116pub struct Detached<K, T> {
117 key: K,
118 val: Box<T>,
119}
120
121impl<K, T> Detached<K, T>
122where
123 K: Copy,
124{
125 fn new(key: K, val: Box<T>) -> Self {
126 Self { key, val }
127 }
128
129 pub fn key(det: &Detached<K, T>) -> K {
131 det.key
132 }
133}
134
135impl<K, T> Deref for Detached<K, T> {
136 type Target = T;
137
138 fn deref(&self) -> &Self::Target {
139 self.val.as_ref()
140 }
141}
142
143impl<K, T> DerefMut for Detached<K, T> {
144 fn deref_mut(&mut self) -> &mut Self::Target {
145 self.val.as_mut()
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use crate::ds::detach::Detach;
152
153 #[test]
154 fn test_detach() {
155 let mut dd = Detach::new("fop");
156
157 assert!(!dd.is_detached());
158
159 assert_eq!(*dd.as_ref(), "fop");
160 assert_eq!(*dd.as_mut(), "fop");
161
162 let d = dd.detach(0u32);
163
164 assert_eq!(*d, "fop");
165 assert_eq!(d.trim(), "fop");
166
167 assert!(dd.is_detached());
168
169 dd.attach(d);
170
171 assert!(!dd.is_detached());
172
173 let tt = dd.take();
174
175 assert_eq!(tt, "fop");
176 }
177}