icydb_core/traits/
view.rs1use crate::{
2 patch::{list::ListPatch, map::MapPatch, set::SetPatch},
3 traits::Atomic,
4};
5use candid::CandidType;
6use std::{
7 collections::{BTreeMap, BTreeSet, HashMap, HashSet},
8 hash::{BuildHasher, Hash},
9};
10
11pub trait AsView: Sized {
19 type ViewType: Default;
20
21 fn as_view(&self) -> Self::ViewType;
22 fn from_view(view: Self::ViewType) -> Self;
23}
24
25impl AsView for () {
26 type ViewType = Self;
27
28 fn as_view(&self) -> Self::ViewType {}
29 fn from_view((): Self::ViewType) -> Self {}
30}
31
32impl AsView for String {
33 type ViewType = Self;
34
35 fn as_view(&self) -> Self::ViewType {
36 self.clone()
37 }
38
39 fn from_view(view: Self::ViewType) -> Self {
40 view
41 }
42}
43
44impl<T: AsView> AsView for Box<T> {
46 type ViewType = T::ViewType;
47
48 fn as_view(&self) -> Self::ViewType {
49 T::as_view(self.as_ref())
51 }
52
53 fn from_view(view: Self::ViewType) -> Self {
54 Self::new(T::from_view(view))
56 }
57}
58
59impl<T: AsView> AsView for Option<T> {
60 type ViewType = Option<T::ViewType>;
61
62 fn as_view(&self) -> Self::ViewType {
63 self.as_ref().map(AsView::as_view)
64 }
65
66 fn from_view(view: Self::ViewType) -> Self {
67 view.map(T::from_view)
68 }
69}
70
71impl<T: AsView> AsView for Vec<T> {
72 type ViewType = Vec<T::ViewType>;
73
74 fn as_view(&self) -> Self::ViewType {
75 self.iter().map(AsView::as_view).collect()
76 }
77
78 fn from_view(view: Self::ViewType) -> Self {
79 view.into_iter().map(T::from_view).collect()
80 }
81}
82
83impl<T, S> AsView for HashSet<T, S>
84where
85 T: AsView + Eq + Hash + Clone,
86 S: BuildHasher + Default,
87{
88 type ViewType = Vec<T::ViewType>;
89
90 fn as_view(&self) -> Self::ViewType {
91 self.iter().map(AsView::as_view).collect()
92 }
93
94 fn from_view(view: Self::ViewType) -> Self {
95 view.into_iter().map(T::from_view).collect()
96 }
97}
98
99impl<K, V, S> AsView for HashMap<K, V, S>
100where
101 K: AsView + Eq + Hash + Clone,
102 V: AsView,
103 S: BuildHasher + Default,
104{
105 type ViewType = Vec<(K::ViewType, V::ViewType)>;
106
107 fn as_view(&self) -> Self::ViewType {
108 self.iter()
109 .map(|(k, v)| (k.as_view(), v.as_view()))
110 .collect()
111 }
112
113 fn from_view(view: Self::ViewType) -> Self {
114 view.into_iter()
115 .map(|(k, v)| (K::from_view(k), V::from_view(v)))
116 .collect()
117 }
118}
119
120impl<T> AsView for BTreeSet<T>
121where
122 T: AsView + Ord + Clone,
123{
124 type ViewType = Vec<T::ViewType>;
125
126 fn as_view(&self) -> Self::ViewType {
127 self.iter().map(AsView::as_view).collect()
128 }
129
130 fn from_view(view: Self::ViewType) -> Self {
131 view.into_iter().map(T::from_view).collect()
132 }
133}
134
135impl<K, V> AsView for BTreeMap<K, V>
136where
137 K: AsView + Ord + Clone,
138 V: AsView,
139{
140 type ViewType = Vec<(K::ViewType, V::ViewType)>;
141
142 fn as_view(&self) -> Self::ViewType {
143 self.iter()
144 .map(|(k, v)| (k.as_view(), v.as_view()))
145 .collect()
146 }
147
148 fn from_view(view: Self::ViewType) -> Self {
149 view.into_iter()
150 .map(|(k, v)| (K::from_view(k), V::from_view(v)))
151 .collect()
152 }
153}
154
155#[macro_export]
156macro_rules! impl_view {
157 ($($type:ty),*) => {
158 $(
159 impl AsView for $type {
160 type ViewType = Self;
161
162 fn as_view(&self) -> Self::ViewType {
163 *self
164 }
165
166 fn from_view(view: Self::ViewType) -> Self {
167 view
168 }
169 }
170 )*
171 };
172}
173
174impl_view!(bool, i8, i16, i32, i64, u8, u16, u32, u64);
175
176impl AsView for f32 {
177 type ViewType = Self;
178
179 fn as_view(&self) -> Self::ViewType {
180 *self
181 }
182
183 fn from_view(view: Self::ViewType) -> Self {
184 if view.is_finite() {
185 if view == 0.0 { 0.0 } else { view }
186 } else {
187 0.0
188 }
189 }
190}
191
192impl AsView for f64 {
193 type ViewType = Self;
194
195 fn as_view(&self) -> Self::ViewType {
196 *self
197 }
198
199 fn from_view(view: Self::ViewType) -> Self {
200 if view.is_finite() {
201 if view == 0.0 { 0.0 } else { view }
202 } else {
203 0.0
204 }
205 }
206}
207
208pub trait CreateView: AsView {
213 type CreateViewType: CandidType + Default;
218
219 fn from_create_view(view: Self::CreateViewType) -> Self;
220}
221
222pub trait UpdateView: AsView {
227 type UpdateViewType: CandidType + Default;
229}
230
231impl<T> UpdateView for T
232where
233 T: Atomic + AsView + CandidType + Default,
234{
235 type UpdateViewType = Self;
236}
237
238impl<T> UpdateView for Option<T>
239where
240 T: UpdateView,
241{
242 type UpdateViewType = Option<T::UpdateViewType>;
243}
244
245impl<T> UpdateView for Vec<T>
246where
247 T: UpdateView,
248{
249 type UpdateViewType = Vec<ListPatch<T::UpdateViewType>>;
250}
251
252impl<T, S> UpdateView for HashSet<T, S>
253where
254 T: UpdateView + Clone + Eq + Hash,
255 S: BuildHasher + Default,
256{
257 type UpdateViewType = Vec<SetPatch<T::UpdateViewType>>;
258}
259
260impl<K, V, S> UpdateView for HashMap<K, V, S>
261where
262 K: UpdateView + Clone + Eq + Hash,
263 V: UpdateView,
264 S: BuildHasher + Default,
265{
266 type UpdateViewType = Vec<MapPatch<K::UpdateViewType, V::UpdateViewType>>;
267}
268
269impl<T> UpdateView for BTreeSet<T>
270where
271 T: UpdateView + Clone + Ord,
272{
273 type UpdateViewType = Vec<SetPatch<T::UpdateViewType>>;
274}
275
276impl<K, V> UpdateView for BTreeMap<K, V>
277where
278 K: UpdateView + Clone + Ord,
279 V: UpdateView,
280{
281 type UpdateViewType = Vec<MapPatch<K::UpdateViewType, V::UpdateViewType>>;
282}