1use super::*;
2use crate::element::*;
3use crate::error::{Error, Result};
4use serde::{Deserialize, Serialize};
5use serde_bytes::ByteBuf;
6use std::default::Default;
7
8#[inline]
9fn is_false(v: &bool) -> bool {
10 !v
11}
12
13#[inline]
14fn bytes_empty(v: &ByteBuf) -> bool {
15 v.is_empty()
16}
17
18#[inline]
19fn u32_is_zero(v: &u32) -> bool {
20 *v == 0
21}
22
23#[inline]
24fn u32_is_max(v: &u32) -> bool {
25 *v == u32::MAX
26}
27
28#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
65#[serde(deny_unknown_fields, default)]
66pub struct BinValidator {
67 #[serde(skip_serializing_if = "String::is_empty")]
69 pub comment: String,
70 #[serde(skip_serializing_if = "bytes_empty")]
73 pub bits_clr: ByteBuf,
74 #[serde(skip_serializing_if = "bytes_empty")]
77 pub bits_set: ByteBuf,
78 #[serde(skip_serializing_if = "bytes_empty")]
81 pub max: ByteBuf,
82 #[serde(skip_serializing_if = "bytes_empty")]
84 pub min: ByteBuf,
85 #[serde(skip_serializing_if = "is_false")]
87 pub ex_max: bool,
88 #[serde(skip_serializing_if = "is_false")]
90 pub ex_min: bool,
91 #[serde(skip_serializing_if = "u32_is_max")]
93 pub max_len: u32,
94 #[serde(skip_serializing_if = "u32_is_zero")]
96 pub min_len: u32,
97 #[serde(rename = "in", skip_serializing_if = "Vec::is_empty")]
99 pub in_list: Vec<ByteBuf>,
100 #[serde(rename = "nin", skip_serializing_if = "Vec::is_empty")]
102 pub nin_list: Vec<ByteBuf>,
103 #[serde(skip_serializing_if = "is_false")]
105 pub query: bool,
106 #[serde(skip_serializing_if = "is_false")]
109 pub bit: bool,
110 #[serde(skip_serializing_if = "is_false")]
113 pub ord: bool,
114 #[serde(skip_serializing_if = "is_false")]
117 pub size: bool,
118}
119
120impl Default for BinValidator {
121 fn default() -> Self {
122 Self {
123 comment: String::new(),
124 bits_clr: ByteBuf::new(),
125 bits_set: ByteBuf::new(),
126 ex_max: false,
127 ex_min: false,
128 max: ByteBuf::new(),
129 min: ByteBuf::new(),
130 max_len: u32::MAX,
131 min_len: u32::MIN,
132 in_list: Vec::new(),
133 nin_list: Vec::new(),
134 query: false,
135 bit: false,
136 ord: false,
137 size: false,
138 }
139 }
140}
141
142impl BinValidator {
143 pub fn new() -> Self {
145 Self::default()
146 }
147
148 pub fn comment(mut self, comment: impl Into<String>) -> Self {
150 self.comment = comment.into();
151 self
152 }
153
154 pub fn bits_set(mut self, bits_set: impl Into<Vec<u8>>) -> Self {
156 self.bits_set = ByteBuf::from(bits_set);
157 self
158 }
159
160 pub fn bits_clr(mut self, bits_clr: impl Into<Vec<u8>>) -> Self {
162 self.bits_clr = ByteBuf::from(bits_clr);
163 self
164 }
165
166 pub fn max(mut self, max: impl Into<Vec<u8>>) -> Self {
168 self.max = ByteBuf::from(max);
169 self
170 }
171
172 pub fn min(mut self, min: impl Into<Vec<u8>>) -> Self {
174 self.min = ByteBuf::from(min);
175 self
176 }
177
178 pub fn ex_max(mut self, ex_max: bool) -> Self {
180 self.ex_max = ex_max;
181 self
182 }
183
184 pub fn ex_min(mut self, ex_min: bool) -> Self {
186 self.ex_min = ex_min;
187 self
188 }
189
190 pub fn max_len(mut self, max_len: u32) -> Self {
192 self.max_len = max_len;
193 self
194 }
195
196 pub fn min_len(mut self, min_len: u32) -> Self {
198 self.min_len = min_len;
199 self
200 }
201
202 pub fn in_add(mut self, add: impl Into<Vec<u8>>) -> Self {
204 self.in_list.push(ByteBuf::from(add));
205 self
206 }
207
208 pub fn nin_add(mut self, add: impl Into<Vec<u8>>) -> Self {
210 self.nin_list.push(ByteBuf::from(add));
211 self
212 }
213
214 pub fn query(mut self, query: bool) -> Self {
216 self.query = query;
217 self
218 }
219
220 pub fn bit(mut self, bit: bool) -> Self {
222 self.bit = bit;
223 self
224 }
225
226 pub fn ord(mut self, ord: bool) -> Self {
228 self.ord = ord;
229 self
230 }
231
232 pub fn size(mut self, size: bool) -> Self {
234 self.size = size;
235 self
236 }
237
238 pub fn build(self) -> Validator {
240 Validator::Bin(Box::new(self))
241 }
242
243 pub(crate) fn validate(&self, parser: &mut Parser) -> Result<()> {
244 use std::iter::repeat;
245
246 let elem = parser
248 .next()
249 .ok_or_else(|| Error::FailValidate("expected binary data".to_string()))??;
250 let val = if let Element::Bin(v) = elem {
251 v
252 } else {
253 return Err(Error::FailValidate(format!(
254 "expected Bin, got {}",
255 elem.name()
256 )));
257 };
258
259 if (val.len() as u32) > self.max_len {
261 return Err(Error::FailValidate(
262 "Bin is longer than max_len".to_string(),
263 ));
264 }
265 if (val.len() as u32) < self.min_len {
266 return Err(Error::FailValidate(
267 "Bin is shorter than min_len".to_string(),
268 ));
269 }
270
271 if self
273 .bits_set
274 .iter()
275 .zip(val.iter().chain(repeat(&0u8)))
276 .any(|(bit, val)| (bit & val) != *bit)
277 {
278 return Err(Error::FailValidate(
279 "Bin does not have all required bits set".to_string(),
280 ));
281 }
282 if self
283 .bits_clr
284 .iter()
285 .zip(val.iter().chain(repeat(&0u8)))
286 .any(|(bit, val)| (bit & val) != 0)
287 {
288 return Err(Error::FailValidate(
289 "Bin does not have all required bits cleared".to_string(),
290 ));
291 }
292
293 use std::cmp::Ordering;
295 fn compare(lhs: &[u8], rhs: &[u8]) -> Ordering {
296 match lhs.len().cmp(&rhs.len()) {
297 Ordering::Equal => Iterator::cmp(lhs.iter().rev(), rhs.iter().rev()),
298 other => other,
299 }
300 }
301 fn trim(val: &[u8]) -> &[u8] {
302 let trim_amount = val.iter().rev().take_while(|v| **v == 0).count();
303 &val[0..(val.len() - trim_amount)]
304 }
305
306 if !self.max.is_empty() || !self.min.is_empty() || self.ex_min {
308 let trimmed_val = trim(val);
309 let max_pass = match (self.max.is_empty(), self.ex_max) {
310 (true, _) => true,
311 (false, true) => compare(trimmed_val, trim(&self.max)) == Ordering::Less,
312 (false, false) => compare(trimmed_val, trim(&self.max)) != Ordering::Greater,
313 };
314
315 let min_pass = match (self.min.is_empty(), self.ex_min) {
316 (true, true) => !trimmed_val.is_empty(), (true, false) => true, (false, true) => compare(trimmed_val, trim(&self.min)) == Ordering::Greater,
319 (false, false) => compare(trimmed_val, trim(&self.min)) != Ordering::Less,
320 };
321
322 if !max_pass {
323 return Err(Error::FailValidate(
324 "Bin greater than maximum allowed".to_string(),
325 ));
326 }
327 if !min_pass {
328 return Err(Error::FailValidate(
329 "Bin less than minimum allowed".to_string(),
330 ));
331 }
332 }
333
334 if !self.in_list.is_empty() && !self.in_list.iter().any(|v| *v == val) {
336 return Err(Error::FailValidate("Bin is not on `in` list".to_string()));
337 }
338 if self.nin_list.iter().any(|v| *v == val) {
339 return Err(Error::FailValidate("Bin is on `nin` list".to_string()));
340 }
341
342 Ok(())
343 }
344
345 fn query_check_self(&self, other: &Self) -> bool {
346 (self.query || (other.in_list.is_empty() && other.nin_list.is_empty()))
347 && (self.bit || (other.bits_set.is_empty() && other.bits_clr.is_empty()))
348 && (self.ord
349 || (!other.ex_min && !other.ex_max && other.min.is_empty() && other.max.is_empty()))
350 && (self.size || (u32_is_max(&other.max_len) && u32_is_zero(&other.min_len)))
351 }
352
353 pub(crate) fn query_check(&self, other: &Validator) -> bool {
354 match other {
355 Validator::Bin(other) => self.query_check_self(other),
356 Validator::Multi(list) => list.iter().all(|other| match other {
357 Validator::Bin(other) => self.query_check_self(other),
358 _ => false,
359 }),
360 Validator::Any => true,
361 _ => false,
362 }
363 }
364}