fog_pack/validator/mod.rs
1//! The fog-pack Validators, for building Schemas and Queries.
2//!
3//! This submodule contains various validators, which can be transformed into the [`Validator`]
4//! enum type for use in a Schema or a Query. Each struct acts as a constructor that can be
5//! built into a `Validator`.
6//!
7//! Validators are not used directly; instead, they should be used to build a Schema or Query,
8//! which will run them against fog-pack data.
9//!
10//! There are validators for each fog-pack core type:
11//! - [`Validator::Null`][Validator::new_null] - for the null type.
12//! - [`BoolValidator`] - for booleans.
13//! - [`IntValidator`] - for [`Integer`][crate::integer::Integer] and other integer values.
14//! - [`F32Validator`] - for `f32` values.
15//! - [`F64Validator`] - for `f64` values.
16//! - [`BinValidator`] - for byte sequences.
17//! - [`StrValidator`] - for UTF-8 strings.
18//! - [`ArrayValidator`] - for sequences, like [`Vec`], arrays, or tuples.
19//! - [`MapValidator`] - for maps, like `struct`, [`BTreeMap`], and `HashMap`
20//! - [`TimeValidator`] - for [`Timestamp`][crate::timestamp::Timestamp]
21//! - [`HashValidator`] - for [`Hash`]
22//! - [`IdentityValidator`] - for [`Identity`][crate::types::Identity]
23//! - [`StreamIdValidator`] - for [`StreamId`][crate::types::StreamId]
24//! - [`LockIdValidator`] - for [`LockId`][crate::types::LockId]
25//! - [`BareIdKey`][Validator::new_bare_id_key] - for [`BareIdKey`][crate::types::BareIdKey]
26//! - [`DataLockboxValidator`] - for [`DataLockbox`][crate::types::DataLockbox]
27//! - [`IdentityLockboxValidator`] - for [`IdentityLockbox`][crate::types::IdentityLockbox]
28//! - [`StreamLockboxValidator`] - for [`StreamLockbox`][crate::types::StreamLockbox]
29//! - [`LockLockboxValidator`] - for [`LockLockbox`][crate::types::LockLockbox]
30//!
31//! In addition to the core types, there are 4 special validators:
32//! - [`Validator::Ref`][Validator::new_ref] - a reference to a validator stored in a
33//! schema's map of types. Uses a name to look up the validator.
34//! - [`MultiValidator`] - Will attempt a sequence of validators, passing if any one of them pass.
35//! - [`EnumValidator`] - Acts as a validator for serialized Rust enums.
36//! This can also be implemented through [`MapValidator`], but this
37//! validator is generally easier to use correctly in such cases.
38//! - [`Validator::Any`][Validator::new_any] - accepts any fog-pack value without examining it.
39//!
40//!
41//! # Examples
42//!
43//! Say we want to build a Document that acts like a file directory. We want to store the creation
44//! time of the directory, and a list of file names with associated Hashes, each of which will be
45//! the Hash of a file or directory. Let's also assume we want a valid Unix file name, meaning "/"
46//! and NUL cannot be in the name, it cannot be longer than 255 bytes, and shouldn't be "." or
47//! "..". A validator for this Document might look like:
48//!
49//! ```
50//! # use fog_pack::validator::*;
51//! # use regex::Regex;
52//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
53//! let dir = MapValidator::new()
54//! .req_add("created", TimeValidator::new().build())
55//! .req_add("contents", MapValidator::new()
56//! .keys(StrValidator::new()
57//! .nin_add(".")
58//! .nin_add("..")
59//! .ban_char("/\0")
60//! .max_len(255)
61//! .min_len(1)
62//! )
63//! .values(HashValidator::new().build())
64//! .build()
65//! )
66//! .build();
67//! # Ok(())
68//! # }
69//! ```
70
71mod array;
72mod bin;
73mod bool;
74mod checklist;
75mod enum_set;
76mod float32;
77mod float64;
78mod hash;
79mod identity;
80mod integer;
81mod lock_id;
82mod lockbox;
83mod map;
84mod multi;
85mod serde_regex;
86mod str;
87mod stream_id;
88mod time;
89
90pub use self::array::*;
91pub use self::bin::*;
92pub use self::bool::*;
93pub use self::checklist::*;
94pub use self::enum_set::*;
95pub use self::float32::*;
96pub use self::float64::*;
97pub use self::hash::*;
98pub use self::identity::*;
99pub use self::integer::*;
100pub use self::lock_id::*;
101pub use self::lockbox::*;
102pub use self::map::*;
103pub use self::multi::*;
104pub use self::str::*;
105pub use self::stream_id::*;
106pub use self::time::*;
107use crate::element::*;
108use crate::error::{Error, Result};
109
110use serde::{Deserialize, Serialize};
111use std::collections::BTreeMap;
112
113/// [Unicode Normalization](http://www.unicode.org/reports/tr15/) settings.
114#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
115pub enum Normalize {
116 /// No normalization applied.
117 None,
118 /// NFC normalization applied.
119 NFC,
120 /// NFKC normalization applied.
121 NFKC,
122}
123
124/// A fog-pack Validator, for verifying the form of a fog-pack Document or Entry.
125///
126/// Validators can be used to verify a fog-pack Document or Entry. Schemas use them for
127/// verification, and they are also used by Queries to find matching Entries.
128///
129/// This enum contains all possible validators. See the
130/// [module-level documentation][crate::validator] for details.
131///
132#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
133pub enum Validator {
134 /// [`Validator::Null`][Validator::new_null] - for the null type.
135 Null,
136 /// [`BoolValidator`] - for booleans.
137 Bool(Box<BoolValidator>),
138 /// [`IntValidator`] - for [`Integer`][crate::integer::Integer] and other integer values.
139 Int(Box<IntValidator>),
140 /// [`F32Validator`] - for `f32` values.
141 F32(Box<F32Validator>),
142 /// [`F64Validator`] - for `f64` values.
143 F64(Box<F64Validator>),
144 /// [`BinValidator`] - for byte sequences.
145 Bin(Box<BinValidator>),
146 /// [`StrValidator`] - for UTF-8 strings.
147 Str(Box<StrValidator>),
148 /// [`ArrayValidator`] - for sequences, like [`Vec`], arrays, or tuples.
149 Array(Box<ArrayValidator>),
150 /// [`MapValidator`] - for maps, like `struct`, [`BTreeMap`], and `HashMap`
151 Map(Box<MapValidator>),
152 /// [`TimeValidator`] - for [`Timestamp`][crate::timestamp::Timestamp]
153 Time(Box<TimeValidator>),
154 /// [`HashValidator`] - for [`Hash`]
155 Hash(Box<HashValidator>),
156 /// [`IdentityValidator`] - for [`Identity`][crate::types::Identity]
157 Identity(Box<IdentityValidator>),
158 /// [`StreamIdValidator`] - for [`StreamId`][crate::types::StreamId]
159 StreamId(Box<StreamIdValidator>),
160 /// [`LockIdValidator`] - for [`LockId`][crate::types::LockId]
161 LockId(Box<LockIdValidator>),
162 /// [`BareIdKey`][Validator::new_bare_id_key] - for [`BareIdKey`][crate::types::BareIdKey]
163 BareIdKey,
164 /// [`DataLockboxValidator`] - for [`DataLockbox`][crate::types::DataLockbox]
165 DataLockbox(Box<DataLockboxValidator>),
166 /// [`IdentityLockboxValidator`] - for [`IdentityLockbox`][crate::types::IdentityLockbox]
167 IdentityLockbox(Box<IdentityLockboxValidator>),
168 /// [`StreamLockboxValidator`] - for [`StreamLockbox`][crate::types::StreamLockbox]
169 StreamLockbox(Box<StreamLockboxValidator>),
170 /// [`LockLockboxValidator`] - for [`LockLockbox`][crate::types::LockLockbox]
171 LockLockbox(Box<LockLockboxValidator>),
172 /// [`Validator::Ref`][Validator::new_ref] - a reference to a validator stored in a
173 /// schema's map of types. Uses a name to look up the validator.
174 Ref(String),
175 /// [`MultiValidator`] - Will attempt a sequence of validators, passing if any one of them pass.
176 Multi(MultiValidator),
177 /// [`EnumValidator`] - Acts as a validator for serialized Rust enums.
178 /// This can also be implemented through [`MapValidator`], but this
179 /// validator is generally easier to use correctly in such cases.
180 Enum(EnumValidator),
181 /// [`Validator::Any`][Validator::new_any] - accepts any fog-pack value without examining it.
182 Any,
183}
184
185impl Validator {
186 /// Create a new reference validator from the given string.
187 pub fn new_ref(name: impl Into<String>) -> Self {
188 Self::Ref(name.into())
189 }
190
191 /// Create a new validator for the Null value.
192 pub fn new_null() -> Self {
193 Self::Null
194 }
195
196 /// Create a new validator for a [`BareIdKey`][crate::types::BareIdKey].
197 pub fn new_bare_id_key() -> Self {
198 Self::BareIdKey
199 }
200
201 /// Create a new validator that passes any value.
202 pub fn new_any() -> Self {
203 Self::Any
204 }
205
206 pub(crate) fn validate<'de, 'c>(
207 &'c self,
208 types: &'c BTreeMap<String, Validator>,
209 mut parser: Parser<'de>,
210 mut checklist: Option<Checklist<'c>>,
211 ) -> Result<(Parser<'de>, Option<Checklist<'c>>)> {
212 match self {
213 Validator::Null => {
214 let elem = parser
215 .next()
216 .ok_or_else(|| Error::FailValidate("expected null".to_string()))??;
217 if let Element::Null = elem {
218 Ok((parser, checklist))
219 } else {
220 Err(Error::FailValidate("expected null".to_string()))
221 }
222 }
223 Validator::Bool(validator) => {
224 validator.validate(&mut parser)?;
225 Ok((parser, checklist))
226 }
227 Validator::Int(validator) => {
228 validator.validate(&mut parser)?;
229 Ok((parser, checklist))
230 }
231 Validator::F32(validator) => {
232 validator.validate(&mut parser)?;
233 Ok((parser, checklist))
234 }
235 Validator::F64(validator) => {
236 validator.validate(&mut parser)?;
237 Ok((parser, checklist))
238 }
239 Validator::Bin(validator) => {
240 validator.validate(&mut parser)?;
241 Ok((parser, checklist))
242 }
243 Validator::Str(validator) => {
244 validator.validate(&mut parser)?;
245 Ok((parser, checklist))
246 }
247 Validator::Array(validator) => validator.validate(types, parser, checklist),
248 Validator::Map(validator) => validator.validate(types, parser, checklist),
249 Validator::Time(validator) => {
250 validator.validate(&mut parser)?;
251 Ok((parser, checklist))
252 }
253 Validator::Hash(validator) => {
254 validator.validate(&mut parser, &mut checklist)?;
255 Ok((parser, checklist))
256 }
257 Validator::Identity(validator) => {
258 validator.validate(&mut parser)?;
259 Ok((parser, checklist))
260 }
261 Validator::StreamId(validator) => {
262 validator.validate(&mut parser)?;
263 Ok((parser, checklist))
264 }
265 Validator::LockId(validator) => {
266 validator.validate(&mut parser)?;
267 Ok((parser, checklist))
268 }
269 Validator::BareIdKey => {
270 let elem = parser
271 .next()
272 .ok_or_else(|| Error::FailValidate("expected BareIdKey".to_string()))??;
273 if let Element::BareIdKey(_) = elem {
274 Ok((parser, checklist))
275 } else {
276 Err(Error::FailValidate("expected BareIdKey".to_string()))
277 }
278 }
279 Validator::DataLockbox(validator) => {
280 validator.validate(&mut parser)?;
281 Ok((parser, checklist))
282 }
283 Validator::IdentityLockbox(validator) => {
284 validator.validate(&mut parser)?;
285 Ok((parser, checklist))
286 }
287 Validator::StreamLockbox(validator) => {
288 validator.validate(&mut parser)?;
289 Ok((parser, checklist))
290 }
291 Validator::LockLockbox(validator) => {
292 validator.validate(&mut parser)?;
293 Ok((parser, checklist))
294 }
295 Validator::Ref(ref_name) => {
296 // Fail if cyclic validation is possible, by banning Ref->Ref.
297 // Ref->Multi->... checks are in the Multi validator code further down.
298 // All other validators pull at least one element, ensuring infinite
299 // recursion/cycling is impossible.
300 let validator = types.get(ref_name).ok_or_else(|| {
301 Error::FailValidate(format!("validator Ref({}) not in list of types", ref_name))
302 })?;
303 match validator {
304 Validator::Ref(_) => Err(Error::FailValidate(format!(
305 "validator Ref({}) is itself a Ref",
306 ref_name
307 ))),
308 _ => validator.validate(types, parser, checklist),
309 }
310 }
311 Validator::Multi(validator) => validator.validate(types, parser, checklist),
312 Validator::Enum(validator) => validator.validate(types, parser, checklist),
313 Validator::Any => {
314 read_any(&mut parser)?;
315 Ok((parser, checklist))
316 }
317 }
318 }
319
320 pub(crate) fn query_check(
321 &self,
322 types: &BTreeMap<String, Validator>,
323 other: &Validator,
324 ) -> bool {
325 match self {
326 Validator::Null => matches!(other, Validator::Null | Validator::Any),
327 Validator::Bool(validator) => validator.query_check(other),
328 Validator::Int(validator) => validator.query_check(other),
329 Validator::F32(validator) => validator.query_check(other),
330 Validator::F64(validator) => validator.query_check(other),
331 Validator::Bin(validator) => validator.query_check(other),
332 Validator::Str(validator) => validator.query_check(other),
333 Validator::Time(validator) => validator.query_check(other),
334 Validator::Array(validator) => validator.query_check(types, other),
335 Validator::Map(validator) => validator.query_check(types, other),
336 Validator::Hash(validator) => validator.query_check(types, other),
337 Validator::Identity(validator) => validator.query_check(other),
338 Validator::StreamId(validator) => validator.query_check(other),
339 Validator::LockId(validator) => validator.query_check(other),
340 Validator::BareIdKey => matches!(other, Validator::BareIdKey | Validator::Any),
341 Validator::DataLockbox(validator) => validator.query_check(other),
342 Validator::IdentityLockbox(validator) => validator.query_check(other),
343 Validator::StreamLockbox(validator) => validator.query_check(other),
344 Validator::LockLockbox(validator) => validator.query_check(other),
345 Validator::Ref(ref_name) => match types.get(ref_name) {
346 None => false,
347 Some(validator) => {
348 if let Validator::Ref(_) = validator {
349 false
350 } else {
351 validator.query_check(types, other)
352 }
353 }
354 },
355 Validator::Multi(validator) => validator.query_check(types, other),
356 Validator::Enum(validator) => validator.query_check(types, other),
357 Validator::Any => false,
358 }
359 }
360}
361
362fn read_any(parser: &mut Parser) -> Result<()> {
363 fn get_elem<'a>(parser: &mut Parser<'a>) -> Result<Element<'a>> {
364 parser
365 .next()
366 .ok_or_else(|| Error::FailValidate("expected another value".to_string()))?
367 }
368 let elem = get_elem(parser)?;
369 match elem {
370 Element::Map(len) => {
371 let mut last_key = None;
372 for _ in 0..len {
373 if let Element::Str(key) = get_elem(parser)? {
374 if let Some(last_key) = last_key {
375 if key <= last_key {
376 return Err(Error::FailValidate(format!(
377 "map keys are unordered: {} follows {}",
378 key, last_key
379 )));
380 }
381 }
382 last_key = Some(key);
383 } else {
384 return Err(Error::FailValidate(
385 "expected string for map key".to_string(),
386 ));
387 }
388 read_any(parser)?;
389 }
390 Ok(())
391 }
392 Element::Array(len) => {
393 for _ in 0..len {
394 read_any(parser)?;
395 }
396 Ok(())
397 }
398 _ => Ok(()),
399 }
400}