mod array;
mod bin;
mod bool;
mod checklist;
mod enum_set;
mod float32;
mod float64;
mod hash;
mod identity;
mod integer;
mod lock_id;
mod lockbox;
mod map;
mod multi;
mod serde_regex;
mod str;
mod stream_id;
mod time;
pub use self::array::*;
pub use self::bin::*;
pub use self::bool::*;
pub use self::checklist::*;
pub use self::enum_set::*;
pub use self::float32::*;
pub use self::float64::*;
pub use self::hash::*;
pub use self::identity::*;
pub use self::integer::*;
pub use self::lock_id::*;
pub use self::lockbox::*;
pub use self::map::*;
pub use self::multi::*;
pub use self::str::*;
pub use self::stream_id::*;
pub use self::time::*;
use crate::element::*;
use crate::error::{Error, Result};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Normalize {
None,
NFC,
NFKC,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Validator {
Null,
Bool(BoolValidator),
Int(IntValidator),
F32(F32Validator),
F64(F64Validator),
Bin(BinValidator),
Str(StrValidator),
Array(ArrayValidator),
Map(MapValidator),
Time(TimeValidator),
Hash(HashValidator),
Identity(IdentityValidator),
StreamId(StreamIdValidator),
LockId(LockIdValidator),
DataLockbox(DataLockboxValidator),
IdentityLockbox(IdentityLockboxValidator),
StreamLockbox(StreamLockboxValidator),
LockLockbox(LockLockboxValidator),
Ref(String),
Multi(MultiValidator),
Enum(EnumValidator),
Any,
}
impl Validator {
pub fn new_ref(name: impl Into<String>) -> Self {
Self::Ref(name.into())
}
pub fn new_null() -> Self {
Self::Null
}
pub fn new_any() -> Self {
Self::Any
}
pub(crate) fn validate<'de, 'c>(
&'c self,
types: &'c BTreeMap<String, Validator>,
mut parser: Parser<'de>,
mut checklist: Option<Checklist<'c>>,
) -> Result<(Parser<'de>, Option<Checklist<'c>>)> {
match self {
Validator::Null => {
let elem = parser
.next()
.ok_or_else(|| Error::FailValidate("expected null".to_string()))??;
if let Element::Null = elem {
Ok((parser, checklist))
} else {
Err(Error::FailValidate("expected null".to_string()))
}
}
Validator::Bool(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::Int(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::F32(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::F64(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::Bin(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::Str(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::Array(validator) => validator.validate(types, parser, checklist),
Validator::Map(validator) => validator.validate(types, parser, checklist),
Validator::Time(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::Hash(validator) => {
validator.validate(&mut parser, &mut checklist)?;
Ok((parser, checklist))
}
Validator::Identity(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::StreamId(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::LockId(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::DataLockbox(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::IdentityLockbox(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::StreamLockbox(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::LockLockbox(validator) => {
validator.validate(&mut parser)?;
Ok((parser, checklist))
}
Validator::Ref(ref_name) => {
let validator = types.get(ref_name).ok_or_else(|| {
Error::FailValidate(format!("validator Ref({}) not in list of types", ref_name))
})?;
match validator {
Validator::Ref(_) => Err(Error::FailValidate(format!(
"validator Ref({}) is itself a Ref",
ref_name
))),
_ => validator.validate(types, parser, checklist),
}
}
Validator::Multi(validator) => validator.validate(types, parser, checklist),
Validator::Enum(validator) => validator.validate(types, parser, checklist),
Validator::Any => {
read_any(&mut parser)?;
Ok((parser, checklist))
}
}
}
pub(crate) fn query_check(
&self,
types: &BTreeMap<String, Validator>,
other: &Validator,
) -> bool {
match self {
Validator::Null => matches!(other, Validator::Null | Validator::Any),
Validator::Bool(validator) => validator.query_check(other),
Validator::Int(validator) => validator.query_check(other),
Validator::F32(validator) => validator.query_check(other),
Validator::F64(validator) => validator.query_check(other),
Validator::Bin(validator) => validator.query_check(other),
Validator::Str(validator) => validator.query_check(other),
Validator::Time(validator) => validator.query_check(other),
Validator::Array(validator) => validator.query_check(types, other),
Validator::Map(validator) => validator.query_check(types, other),
Validator::Hash(validator) => validator.query_check(types, other),
Validator::Identity(validator) => validator.query_check(other),
Validator::StreamId(validator) => validator.query_check(other),
Validator::LockId(validator) => validator.query_check(other),
Validator::DataLockbox(validator) => validator.query_check(other),
Validator::IdentityLockbox(validator) => validator.query_check(other),
Validator::StreamLockbox(validator) => validator.query_check(other),
Validator::LockLockbox(validator) => validator.query_check(other),
Validator::Ref(ref_name) => match types.get(ref_name) {
None => false,
Some(validator) => {
if let Validator::Ref(_) = validator {
false
} else {
validator.query_check(types, other)
}
}
},
Validator::Multi(validator) => validator.query_check(types, other),
Validator::Enum(validator) => validator.query_check(types, other),
Validator::Any => false,
}
}
}
fn read_any(parser: &mut Parser) -> Result<()> {
fn get_elem<'a>(parser: &mut Parser<'a>) -> Result<Element<'a>> {
parser
.next()
.ok_or_else(|| Error::FailValidate("expected another value".to_string()))?
}
let elem = get_elem(parser)?;
match elem {
Element::Map(len) => {
let mut last_key = None;
for _ in 0..len {
if let Element::Str(key) = get_elem(parser)? {
if let Some(last_key) = last_key {
if key <= last_key {
return Err(Error::FailValidate(format!(
"map keys are unordered: {} follows {}",
key, last_key
)));
}
}
last_key = Some(key);
} else {
return Err(Error::FailValidate(
"expected string for map key".to_string(),
));
}
read_any(parser)?;
}
Ok(())
}
Element::Array(len) => {
for _ in 0..len {
read_any(parser)?;
}
Ok(())
}
_ => Ok(()),
}
}