icydb_core/traits/
sanitize.rs1use std::collections::{HashMap, HashSet};
2
3pub trait Sanitize: SanitizeAuto + SanitizeCustom {}
8
9impl<T> Sanitize for T where T: SanitizeAuto + SanitizeCustom {}
10
11#[derive(Clone, Debug, Default)]
24pub struct SanitizeContext {
25 pub now: Option<u64>,
26 pub is_new: Option<bool>,
27}
28
29impl SanitizeContext {
30 #[must_use]
31 pub const fn new(now: Option<u64>, is_new: Option<bool>) -> Self {
32 Self { now, is_new }
33 }
34}
35
36pub trait SanitizeAuto {
46 fn sanitize_self(&mut self) {}
47 fn sanitize_children(&mut self) {}
48
49 fn sanitize_self_with(&mut self, _ctx: &SanitizeContext) {
50 self.sanitize_self();
51 }
52
53 fn sanitize_children_with(&mut self, _ctx: &SanitizeContext) {
54 self.sanitize_children();
55 }
56}
57
58impl<T: SanitizeAuto> SanitizeAuto for Box<T> {
59 fn sanitize_self(&mut self) {
60 (**self).sanitize_self();
61 }
62
63 fn sanitize_children(&mut self) {
64 (**self).sanitize_children();
65 }
66}
67
68impl<T: SanitizeAuto> SanitizeAuto for Option<T> {
69 fn sanitize_self(&mut self) {
70 if let Some(inner) = self.as_mut() {
71 inner.sanitize_self();
72 }
73 }
74
75 fn sanitize_children(&mut self) {
76 if let Some(inner) = self.as_mut() {
77 inner.sanitize_children();
78 }
79 }
80}
81
82impl<T: SanitizeAuto> SanitizeAuto for Vec<T> {
83 fn sanitize_self(&mut self) {
84 for v in self {
85 v.sanitize_self();
86 }
87 }
88
89 fn sanitize_children(&mut self) {
90 for v in self {
91 v.sanitize_children();
92 }
93 }
94}
95
96impl<T: SanitizeAuto, S> SanitizeAuto for HashSet<T, S> {
97 fn sanitize_self(&mut self) {
98 }
100
101 fn sanitize_children(&mut self) {
102 }
104}
105
106impl<K: SanitizeAuto, V: SanitizeAuto, S> SanitizeAuto for HashMap<K, V, S> {
107 fn sanitize_self(&mut self) {
108 for v in self.values_mut() {
109 v.sanitize_self();
110 }
111 }
112
113 fn sanitize_children(&mut self) {
114 for v in self.values_mut() {
116 v.sanitize_children();
117 }
118 }
119}
120
121impl_primitive!(SanitizeAuto);
122
123pub trait SanitizeCustom {
130 fn sanitize_custom(&mut self) {}
131
132 fn sanitize_custom_with(&mut self, _ctx: &SanitizeContext) {
133 self.sanitize_custom();
134 }
135}
136
137impl<T: SanitizeCustom> SanitizeCustom for Box<T> {
138 fn sanitize_custom(&mut self) {
139 (**self).sanitize_custom();
140 }
141}
142
143impl<T: SanitizeCustom> SanitizeCustom for Option<T> {
144 fn sanitize_custom(&mut self) {
145 if let Some(inner) = self.as_mut() {
146 inner.sanitize_custom();
147 }
148 }
149}
150
151impl<T: SanitizeCustom> SanitizeCustom for Vec<T> {
152 fn sanitize_custom(&mut self) {
153 for v in self {
154 v.sanitize_custom();
155 }
156 }
157}
158
159impl<T: SanitizeCustom, S> SanitizeCustom for HashSet<T, S> {
160 }
162
163impl<K: SanitizeCustom, V: SanitizeCustom, S> SanitizeCustom for HashMap<K, V, S> {
164 fn sanitize_custom(&mut self) {
165 for v in self.values_mut() {
167 v.sanitize_custom();
168 }
169 }
170}
171
172impl_primitive!(SanitizeCustom);
173
174#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[derive(Debug, Eq, Hash, PartialEq)]
184 struct NeedsSanitizing(i32);
185
186 impl SanitizeAuto for NeedsSanitizing {
187 fn sanitize_self(&mut self) {
188 if self.0 < 0 {
189 self.0 = 0;
190 }
191 }
192 }
193
194 impl SanitizeCustom for NeedsSanitizing {
195 fn sanitize_custom(&mut self) {
196 if self.0 > 100 {
197 self.0 = 100;
198 }
199 }
200 }
201
202 #[test]
203 fn test_sanitize_auto_and_custom() {
204 let mut x = NeedsSanitizing(-5);
205 x.sanitize_self();
206 assert_eq!(x.0, 0);
207
208 let mut y = NeedsSanitizing(200);
209 y.sanitize_custom();
210 assert_eq!(y.0, 100);
211 }
212
213 #[test]
214 fn test_vec_sanitization() {
215 let mut v = vec![NeedsSanitizing(-1), NeedsSanitizing(150)];
216 v.sanitize_self();
217 v.sanitize_custom();
218 assert_eq!(v[0].0, 0);
219 assert_eq!(v[1].0, 100);
220 }
221}