Skip to main content

icydb_core/traits/
view.rs

1use std::{
2    collections::{BTreeMap, BTreeSet, HashMap, HashSet},
3    hash::{BuildHasher, Hash},
4};
5
6///
7/// AsView
8///
9/// Recursive for all field/value nodes
10/// `from_view` is infallible; view values are treated as canonical.
11///
12
13pub trait AsView: Sized {
14    type ViewType: Default;
15
16    fn as_view(&self) -> Self::ViewType;
17    fn from_view(view: Self::ViewType) -> Self;
18}
19
20impl AsView for () {
21    type ViewType = Self;
22
23    fn as_view(&self) -> Self::ViewType {}
24    fn from_view((): Self::ViewType) -> Self {}
25}
26
27impl AsView for String {
28    type ViewType = Self;
29
30    fn as_view(&self) -> Self::ViewType {
31        self.clone()
32    }
33
34    fn from_view(view: Self::ViewType) -> Self {
35        view
36    }
37}
38
39// Make Box<T> *not* appear in the view type
40impl<T: AsView> AsView for Box<T> {
41    type ViewType = T::ViewType;
42
43    fn as_view(&self) -> Self::ViewType {
44        // Delegate to inner value
45        T::as_view(self.as_ref())
46    }
47
48    fn from_view(view: Self::ViewType) -> Self {
49        // Re-box after reconstructing inner
50        Self::new(T::from_view(view))
51    }
52}
53
54impl<T: AsView> AsView for Option<T> {
55    type ViewType = Option<T::ViewType>;
56
57    fn as_view(&self) -> Self::ViewType {
58        self.as_ref().map(AsView::as_view)
59    }
60
61    fn from_view(view: Self::ViewType) -> Self {
62        view.map(T::from_view)
63    }
64}
65
66impl<T: AsView> AsView for Vec<T> {
67    type ViewType = Vec<T::ViewType>;
68
69    fn as_view(&self) -> Self::ViewType {
70        self.iter().map(AsView::as_view).collect()
71    }
72
73    fn from_view(view: Self::ViewType) -> Self {
74        view.into_iter().map(T::from_view).collect()
75    }
76}
77
78impl<T, S> AsView for HashSet<T, S>
79where
80    T: AsView + Eq + Hash + Clone,
81    S: BuildHasher + Default,
82{
83    type ViewType = Vec<T::ViewType>;
84
85    fn as_view(&self) -> Self::ViewType {
86        self.iter().map(AsView::as_view).collect()
87    }
88
89    fn from_view(view: Self::ViewType) -> Self {
90        view.into_iter().map(T::from_view).collect()
91    }
92}
93
94impl<K, V, S> AsView for HashMap<K, V, S>
95where
96    K: AsView + Eq + Hash + Clone,
97    V: AsView,
98    S: BuildHasher + Default,
99{
100    type ViewType = Vec<(K::ViewType, V::ViewType)>;
101
102    fn as_view(&self) -> Self::ViewType {
103        self.iter()
104            .map(|(k, v)| (k.as_view(), v.as_view()))
105            .collect()
106    }
107
108    fn from_view(view: Self::ViewType) -> Self {
109        view.into_iter()
110            .map(|(k, v)| (K::from_view(k), V::from_view(v)))
111            .collect()
112    }
113}
114
115impl<T> AsView for BTreeSet<T>
116where
117    T: AsView + Ord + Clone,
118{
119    type ViewType = Vec<T::ViewType>;
120
121    fn as_view(&self) -> Self::ViewType {
122        self.iter().map(AsView::as_view).collect()
123    }
124
125    fn from_view(view: Self::ViewType) -> Self {
126        view.into_iter().map(T::from_view).collect()
127    }
128}
129
130impl<K, V> AsView for BTreeMap<K, V>
131where
132    K: AsView + Ord + Clone,
133    V: AsView,
134{
135    type ViewType = Vec<(K::ViewType, V::ViewType)>;
136
137    fn as_view(&self) -> Self::ViewType {
138        self.iter()
139            .map(|(k, v)| (k.as_view(), v.as_view()))
140            .collect()
141    }
142
143    fn from_view(view: Self::ViewType) -> Self {
144        view.into_iter()
145            .map(|(k, v)| (K::from_view(k), V::from_view(v)))
146            .collect()
147    }
148}
149
150#[macro_export]
151macro_rules! impl_view {
152    ($($type:ty),*) => {
153        $(
154            impl AsView for $type {
155                type ViewType = Self;
156
157                fn as_view(&self) -> Self::ViewType {
158                    *self
159                }
160
161                fn from_view(view: Self::ViewType) -> Self {
162                    view
163                }
164            }
165        )*
166    };
167}
168
169impl_view!(bool, i8, i16, i32, i64, u8, u16, u32, u64);
170
171impl AsView for f32 {
172    type ViewType = Self;
173
174    fn as_view(&self) -> Self::ViewType {
175        *self
176    }
177
178    fn from_view(view: Self::ViewType) -> Self {
179        if view.is_finite() {
180            if view == 0.0 { 0.0 } else { view }
181        } else {
182            0.0
183        }
184    }
185}
186
187impl AsView for f64 {
188    type ViewType = Self;
189
190    fn as_view(&self) -> Self::ViewType {
191        *self
192    }
193
194    fn from_view(view: Self::ViewType) -> Self {
195        if view.is_finite() {
196            if view == 0.0 { 0.0 } else { view }
197        } else {
198            0.0
199        }
200    }
201}