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}