1use crate::{
7 patch::{
8 ListPatch, MapPatch, MergePatchError, SetPatch,
9 merge::{
10 merge_atomic, merge_btree_map, merge_btree_set, merge_hash_map, merge_hash_set,
11 merge_option, merge_vec,
12 },
13 },
14 traits::Atomic,
15};
16use candid::CandidType;
17use std::{
18 collections::{BTreeMap, BTreeSet, HashMap, HashSet},
19 hash::{BuildHasher, Hash},
20};
21
22pub trait AsView: Sized {
30 type ViewType: Default;
31
32 fn as_view(&self) -> Self::ViewType;
33 fn from_view(view: Self::ViewType) -> Self;
34}
35
36impl AsView for () {
37 type ViewType = Self;
38
39 fn as_view(&self) -> Self::ViewType {}
40 fn from_view((): Self::ViewType) -> Self {}
41}
42
43impl AsView for String {
44 type ViewType = Self;
45
46 fn as_view(&self) -> Self::ViewType {
47 self.clone()
48 }
49
50 fn from_view(view: Self::ViewType) -> Self {
51 view
52 }
53}
54
55impl<T: AsView> AsView for Box<T> {
57 type ViewType = T::ViewType;
58
59 fn as_view(&self) -> Self::ViewType {
60 T::as_view(self.as_ref())
62 }
63
64 fn from_view(view: Self::ViewType) -> Self {
65 Self::new(T::from_view(view))
67 }
68}
69
70impl<T: AsView> AsView for Option<T> {
71 type ViewType = Option<T::ViewType>;
72
73 fn as_view(&self) -> Self::ViewType {
74 self.as_ref().map(AsView::as_view)
75 }
76
77 fn from_view(view: Self::ViewType) -> Self {
78 view.map(T::from_view)
79 }
80}
81
82impl<T: AsView> AsView for Vec<T> {
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<T, S> AsView for HashSet<T, S>
95where
96 T: AsView + Eq + Hash + Clone,
97 S: BuildHasher + Default,
98{
99 type ViewType = Vec<T::ViewType>;
100
101 fn as_view(&self) -> Self::ViewType {
102 self.iter().map(AsView::as_view).collect()
103 }
104
105 fn from_view(view: Self::ViewType) -> Self {
106 view.into_iter().map(T::from_view).collect()
107 }
108}
109
110impl<K, V, S> AsView for HashMap<K, V, S>
111where
112 K: AsView + Eq + Hash + Clone,
113 V: AsView,
114 S: BuildHasher + Default,
115{
116 type ViewType = Vec<(K::ViewType, V::ViewType)>;
117
118 fn as_view(&self) -> Self::ViewType {
119 self.iter()
120 .map(|(k, v)| (k.as_view(), v.as_view()))
121 .collect()
122 }
123
124 fn from_view(view: Self::ViewType) -> Self {
125 view.into_iter()
126 .map(|(k, v)| (K::from_view(k), V::from_view(v)))
127 .collect()
128 }
129}
130
131impl<T> AsView for BTreeSet<T>
132where
133 T: AsView + Ord + Clone,
134{
135 type ViewType = Vec<T::ViewType>;
136
137 fn as_view(&self) -> Self::ViewType {
138 self.iter().map(AsView::as_view).collect()
139 }
140
141 fn from_view(view: Self::ViewType) -> Self {
142 view.into_iter().map(T::from_view).collect()
143 }
144}
145
146impl<K, V> AsView for BTreeMap<K, V>
147where
148 K: AsView + Ord + Clone,
149 V: AsView,
150{
151 type ViewType = Vec<(K::ViewType, V::ViewType)>;
152
153 fn as_view(&self) -> Self::ViewType {
154 self.iter()
155 .map(|(k, v)| (k.as_view(), v.as_view()))
156 .collect()
157 }
158
159 fn from_view(view: Self::ViewType) -> Self {
160 view.into_iter()
161 .map(|(k, v)| (K::from_view(k), V::from_view(v)))
162 .collect()
163 }
164}
165
166#[macro_export]
167macro_rules! impl_view {
168 ($($type:ty),*) => {
169 $(
170 impl AsView for $type {
171 type ViewType = Self;
172
173 fn as_view(&self) -> Self::ViewType {
174 *self
175 }
176
177 fn from_view(view: Self::ViewType) -> Self {
178 view
179 }
180 }
181 )*
182 };
183}
184
185impl_view!(bool, i8, i16, i32, i64, u8, u16, u32, u64);
186
187impl AsView for f32 {
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}
202
203impl AsView for f64 {
204 type ViewType = Self;
205
206 fn as_view(&self) -> Self::ViewType {
207 *self
208 }
209
210 fn from_view(view: Self::ViewType) -> Self {
211 if view.is_finite() {
212 if view == 0.0 { 0.0 } else { view }
213 } else {
214 0.0
215 }
216 }
217}
218
219pub trait CreateView: AsView {
224 type CreateViewType: CandidType + Default;
229
230 fn from_create_view(view: Self::CreateViewType) -> Self;
231}
232
233pub trait UpdateView: AsView {
238 type UpdateViewType: CandidType + Default;
240 fn merge(&mut self, patch: Self::UpdateViewType) -> Result<(), MergePatchError>;
241}
242
243impl<T> UpdateView for T
244where
245 T: Atomic + AsView + CandidType + Default,
246{
247 type UpdateViewType = Self;
248
249 fn merge(&mut self, patch: Self::UpdateViewType) -> Result<(), MergePatchError> {
250 merge_atomic(self, patch);
251
252 Ok(())
253 }
254}
255
256impl<T> UpdateView for Option<T>
257where
258 T: UpdateView + Default,
259{
260 type UpdateViewType = Option<T::UpdateViewType>;
261
262 fn merge(&mut self, patch: Self::UpdateViewType) -> Result<(), MergePatchError> {
263 merge_option(self, patch)
264 }
265}
266
267impl<T> UpdateView for Vec<T>
268where
269 T: UpdateView + Default,
270{
271 type UpdateViewType = Vec<ListPatch<T::UpdateViewType>>;
272
273 fn merge(&mut self, patch: Self::UpdateViewType) -> Result<(), MergePatchError> {
274 merge_vec(self, patch)
275 }
276}
277
278impl<T, S> UpdateView for HashSet<T, S>
279where
280 T: UpdateView + Clone + Default + Eq + Hash,
281 S: BuildHasher + Default,
282{
283 type UpdateViewType = Vec<SetPatch<T::UpdateViewType>>;
284
285 fn merge(&mut self, patch: Self::UpdateViewType) -> Result<(), MergePatchError> {
286 merge_hash_set(self, patch)
287 }
288}
289
290impl<K, V, S> UpdateView for HashMap<K, V, S>
291where
292 K: UpdateView + Clone + Default + Eq + Hash,
293 V: UpdateView + Default,
294 S: BuildHasher + Default,
295{
296 type UpdateViewType = Vec<MapPatch<K::UpdateViewType, V::UpdateViewType>>;
297
298 fn merge(&mut self, patch: Self::UpdateViewType) -> Result<(), MergePatchError> {
299 merge_hash_map(self, patch)
300 }
301}
302
303impl<T> UpdateView for BTreeSet<T>
304where
305 T: UpdateView + Clone + Default + Ord,
306{
307 type UpdateViewType = Vec<SetPatch<T::UpdateViewType>>;
308
309 fn merge(&mut self, patch: Self::UpdateViewType) -> Result<(), MergePatchError> {
310 merge_btree_set(self, patch)
311 }
312}
313
314impl<K, V> UpdateView for BTreeMap<K, V>
315where
316 K: UpdateView + Clone + Default + Ord,
317 V: UpdateView + Default,
318{
319 type UpdateViewType = Vec<MapPatch<K::UpdateViewType, V::UpdateViewType>>;
320
321 fn merge(&mut self, patch: Self::UpdateViewType) -> Result<(), MergePatchError> {
322 merge_btree_map(self, patch)
323 }
324}