vimwiki_core/lang/elements/utils/
mod.rs1use crate::StrictEq;
2use derive_more::{Constructor, Deref, DerefMut, Display};
3use serde::{Deserialize, Serialize};
4use std::hash::{Hash, Hasher};
5
6mod region;
7pub use region::Region;
8
9pub trait AsChildrenSlice {
12 type Child;
14
15 fn as_children_slice(&self) -> &[Self::Child];
17}
18
19pub trait AsChildrenMutSlice {
22 type Child;
24
25 fn as_children_mut_slice(&mut self) -> &mut [Self::Child];
27}
28
29pub trait IntoChildren {
32 type Child;
34
35 fn into_children(self) -> Vec<Self::Child>;
37}
38
39#[derive(
42 Constructor,
43 Copy,
44 Clone,
45 Debug,
46 Display,
47 Deref,
48 DerefMut,
49 Eq,
50 Serialize,
51 Deserialize,
52)]
53#[display(fmt = "{}", inner)]
54pub struct Located<T> {
55 #[deref]
56 #[deref_mut]
57 inner: T,
58 region: Region,
59}
60
61impl<T> Located<T> {
62 #[inline]
67 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Located<U> {
68 Located::new(f(self.inner), self.region)
69 }
70
71 pub fn take_with_region(mut self, region: Region) -> Self {
74 self.region = region;
75 self
76 }
77
78 pub fn as_ref(&self) -> Located<&T> {
80 Located {
81 inner: &self.inner,
82 region: self.region,
83 }
84 }
85
86 pub fn as_mut(&mut self) -> Located<&mut T> {
88 Located {
89 inner: &mut self.inner,
90 region: self.region,
91 }
92 }
93
94 pub fn as_inner(&self) -> &T {
96 &self.inner
97 }
98
99 pub fn as_mut_inner(&mut self) -> &mut T {
101 &mut self.inner
102 }
103
104 pub fn into_inner(self) -> T {
106 self.inner
107 }
108
109 pub fn depth(&self) -> u16 {
111 self.region.depth()
112 }
113
114 pub fn region(&self) -> Region {
116 self.region
117 }
118}
119
120impl<T> Located<Option<T>> {
121 pub fn transpose(self) -> Option<Located<T>> {
132 let region = self.region();
133 self.into_inner().map(|inner| Located::new(inner, region))
134 }
135}
136
137impl<T: PartialEq> PartialEq for Located<T> {
138 fn eq(&self, other: &Self) -> bool {
139 self.inner == other.inner
140 }
141}
142
143impl<T: PartialEq> PartialEq<T> for Located<T> {
144 fn eq(&self, other: &T) -> bool {
145 &self.inner == other
146 }
147}
148
149impl<T: StrictEq> StrictEq for Located<T> {
150 fn strict_eq(&self, other: &Self) -> bool {
153 self.inner.strict_eq(&other.inner) && self.region == other.region
154 }
155}
156
157impl<T: StrictEq> StrictEq<T> for Located<T> {
158 fn strict_eq(&self, other: &T) -> bool {
161 self.inner.strict_eq(&other)
162 }
163}
164
165impl<T: Hash> Hash for Located<T> {
166 fn hash<H: Hasher>(&self, state: &mut H) {
167 self.inner.hash(state);
168 }
169}
170
171impl<T> From<T> for Located<T> {
172 fn from(t: T) -> Self {
174 Self::new(t, Default::default())
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181 use std::collections::HashSet;
182
183 #[test]
184 fn map_should_transform_inner_value_and_keep_region() {
185 let le = Located::new(3, Region::new(1, 4));
186 let mapped_le = le.map(|c| c + 1);
187 assert_eq!(*mapped_le.as_inner(), 4);
188 assert_eq!(mapped_le.region(), Region::new(1, 4));
189 }
190
191 #[test]
192 fn equality_with_other_should_only_use_inner_value() {
193 let le1 = Located::new(3, Region::new(1, 4));
194 let le2 = Located::new(3, Region::default());
195 assert_eq!(le1, le2);
196 }
197
198 #[test]
199 fn equality_with_inner_type_should_only_use_inner_value() {
200 let le = Located::new(3, Region::new(1, 4));
201 let inner = 3;
202 assert_eq!(le, inner);
203 assert!(le != inner + 1);
204 }
205
206 #[test]
207 fn hashing_should_only_use_inner_value() {
208 let le1 = Located::new(3, Region::new(1, 4));
209 let le2 = Located::new(3, Region::default());
210 let le3 = Located::new(4, Region::new(1, 4));
211 let le4 = Located::new(3, Region::new(1, 4));
212
213 let mut m = HashSet::new();
214 m.insert(le1);
215
216 let le = m
217 .get(&le2)
218 .expect("Failed to retrieve Located with another Located");
219 assert_eq!(*le.as_inner(), 3);
220 assert_eq!(le.region(), Region::new(1, 4));
221
222 assert_eq!(m.get(&le3), None);
223
224 let le = m
225 .get(&le4)
226 .expect("Failed to retrieve Located with another Located");
227 assert_eq!(*le.as_inner(), 3);
228 assert_eq!(le.region(), Region::new(1, 4));
229 }
230
231 #[test]
232 fn as_ref_should_return_new_element_with_ref_and_same_region() {
233 #[derive(Debug, PartialEq, Eq)]
234 struct Test(usize);
235
236 let le = Located::new(Test(5), Region::new(1, 4));
237 let le_ref = le.as_ref();
238
239 assert_eq!(le_ref.inner, &Test(5));
240 assert_eq!(le_ref.region(), Region::new(1, 4));
241 }
242
243 #[test]
244 fn as_mut_should_return_new_element_with_mut_and_same_region() {
245 #[derive(Debug, PartialEq, Eq)]
246 struct Test(usize);
247
248 let mut le = Located::new(Test(5), Region::new(1, 4));
249 let le_mut = le.as_mut();
250
251 assert_eq!(le_mut.inner, &mut Test(5));
252 assert_eq!(le_mut.region(), Region::new(1, 4));
253 }
254
255 #[test]
256 fn as_inner_should_return_new_element_with_ref_to_inner_and_same_region() {
257 #[derive(Debug, PartialEq, Eq)]
258 struct Test(usize);
259
260 let le = Located::new(Test(5), Region::new(1, 4));
261 let inner = le.as_inner();
262
263 assert_eq!(inner, &Test(5));
264 }
265
266 #[test]
267 fn as_mut_inner_should_return_new_element_with_mut_ref_to_inner_and_same_region(
268 ) {
269 #[derive(Debug, PartialEq, Eq)]
270 struct Test(usize);
271
272 let mut le = Located::new(Test(5), Region::new(1, 4));
273 let inner = le.as_mut_inner();
274
275 assert_eq!(inner, &mut Test(5));
276 }
277
278 #[test]
279 fn into_inner_should_return_inner_value_as_owned() {
280 #[derive(Debug, PartialEq, Eq)]
281 struct Test(usize);
282
283 let le = Located::new(Test(5), Region::new(1, 4));
284 let inner = le.into_inner();
285
286 assert_eq!(inner, Test(5));
287 }
288}