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