mod matcher;
mod meta;
mod structure;
mod value;
mod vm;
use dcbor::prelude::*;
pub use matcher::*;
pub use meta::*;
pub use structure::*;
pub use value::*;
pub use vm::*;
use crate::{Error, Result};
pub type Path = Vec<CBOR>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Pattern {
Value(ValuePattern),
Structure(StructurePattern),
Meta(MetaPattern),
}
impl Pattern {
pub fn any_bool() -> Self {
Pattern::Value(ValuePattern::Bool(
crate::pattern::value::BoolPattern::any(),
))
}
pub fn bool(value: bool) -> Self {
Pattern::Value(ValuePattern::Bool(
crate::pattern::value::BoolPattern::value(value),
))
}
pub fn any_number() -> Self {
Pattern::Value(ValuePattern::Number(
crate::pattern::value::NumberPattern::any(),
))
}
pub fn number<T>(value: T) -> Self
where
T: Into<f64>,
{
Pattern::Value(ValuePattern::Number(
crate::pattern::value::NumberPattern::value(value),
))
}
pub fn number_range<A>(range: std::ops::RangeInclusive<A>) -> Self
where
A: Into<f64> + Copy,
{
Pattern::Value(ValuePattern::Number(
crate::pattern::value::NumberPattern::range(range),
))
}
pub fn number_greater_than<T>(value: T) -> Self
where
T: Into<f64>,
{
Pattern::Value(ValuePattern::Number(
crate::pattern::value::NumberPattern::greater_than(value),
))
}
pub fn number_greater_than_or_equal<T>(value: T) -> Self
where
T: Into<f64>,
{
Pattern::Value(ValuePattern::Number(
crate::pattern::value::NumberPattern::greater_than_or_equal(value),
))
}
pub fn number_less_than<T>(value: T) -> Self
where
T: Into<f64>,
{
Pattern::Value(ValuePattern::Number(
crate::pattern::value::NumberPattern::less_than(value),
))
}
pub fn number_less_than_or_equal<T>(value: T) -> Self
where
T: Into<f64>,
{
Pattern::Value(ValuePattern::Number(
crate::pattern::value::NumberPattern::less_than_or_equal(value),
))
}
pub fn number_nan() -> Self {
Pattern::Value(ValuePattern::Number(
crate::pattern::value::NumberPattern::nan(),
))
}
pub fn number_infinity() -> Self {
Pattern::Value(ValuePattern::Number(
crate::pattern::value::NumberPattern::infinity(),
))
}
pub fn number_neg_infinity() -> Self {
Pattern::Value(ValuePattern::Number(
crate::pattern::value::NumberPattern::neg_infinity(),
))
}
pub fn any_text() -> Self {
Pattern::Value(ValuePattern::Text(
crate::pattern::value::TextPattern::any(),
))
}
pub fn text<T: Into<String>>(value: T) -> Self {
Pattern::Value(ValuePattern::Text(
crate::pattern::value::TextPattern::value(value),
))
}
pub fn text_regex(regex: regex::Regex) -> Self {
Pattern::Value(ValuePattern::Text(
crate::pattern::value::TextPattern::regex(regex),
))
}
pub fn any_byte_string() -> Self {
Pattern::Value(ValuePattern::ByteString(
crate::pattern::value::ByteStringPattern::any(),
))
}
pub fn byte_string(value: impl AsRef<[u8]>) -> Self {
Pattern::Value(ValuePattern::ByteString(
crate::pattern::value::ByteStringPattern::value(value),
))
}
pub fn byte_string_regex(regex: regex::bytes::Regex) -> Self {
Pattern::Value(ValuePattern::ByteString(
crate::pattern::value::ByteStringPattern::regex(regex),
))
}
pub fn any_date() -> Self {
Pattern::Value(ValuePattern::Date(
crate::pattern::value::DatePattern::any(),
))
}
pub fn date(date: Date) -> Self {
Pattern::Value(ValuePattern::Date(
crate::pattern::value::DatePattern::value(date),
))
}
pub fn date_range(range: std::ops::RangeInclusive<Date>) -> Self {
Pattern::Value(ValuePattern::Date(
crate::pattern::value::DatePattern::range(range),
))
}
pub fn date_earliest(date: Date) -> Self {
Pattern::Value(ValuePattern::Date(
crate::pattern::value::DatePattern::earliest(date),
))
}
pub fn date_latest(date: Date) -> Self {
Pattern::Value(ValuePattern::Date(
crate::pattern::value::DatePattern::latest(date),
))
}
pub fn date_iso8601(iso_string: impl Into<String>) -> Self {
Pattern::Value(ValuePattern::Date(
crate::pattern::value::DatePattern::string(iso_string),
))
}
pub fn date_regex(regex: regex::Regex) -> Self {
Pattern::Value(ValuePattern::Date(
crate::pattern::value::DatePattern::regex(regex),
))
}
pub fn null() -> Self {
Pattern::Value(ValuePattern::Null(crate::pattern::value::NullPattern))
}
pub fn any_known_value() -> Self {
Pattern::Value(ValuePattern::KnownValue(
crate::pattern::value::KnownValuePattern::any(),
))
}
pub fn known_value(value: known_values::KnownValue) -> Self {
Pattern::Value(ValuePattern::KnownValue(
crate::pattern::value::KnownValuePattern::value(value),
))
}
pub fn known_value_named(name: impl Into<String>) -> Self {
Pattern::Value(ValuePattern::KnownValue(
crate::pattern::value::KnownValuePattern::named(name),
))
}
pub fn known_value_regex(regex: regex::Regex) -> Self {
Pattern::Value(ValuePattern::KnownValue(
crate::pattern::value::KnownValuePattern::regex(regex),
))
}
pub fn any_digest() -> Self {
Pattern::Value(ValuePattern::Digest(
crate::pattern::value::DigestPattern::any(),
))
}
pub fn digest(digest: bc_components::Digest) -> Self {
Pattern::Value(ValuePattern::Digest(
crate::pattern::value::DigestPattern::digest(digest),
))
}
pub fn digest_prefix(prefix: impl AsRef<[u8]>) -> Self {
Pattern::Value(ValuePattern::Digest(
crate::pattern::value::DigestPattern::prefix(prefix),
))
}
pub fn digest_binary_regex(regex: regex::bytes::Regex) -> Self {
Pattern::Value(ValuePattern::Digest(
crate::pattern::value::DigestPattern::binary_regex(regex),
))
}
pub fn any() -> Self {
Pattern::Meta(MetaPattern::Any(crate::pattern::meta::AnyPattern::new()))
}
pub fn and(patterns: Vec<Pattern>) -> Self {
Pattern::Meta(MetaPattern::And(crate::pattern::meta::AndPattern::new(
patterns,
)))
}
pub fn or(patterns: Vec<Pattern>) -> Self {
Pattern::Meta(MetaPattern::Or(crate::pattern::meta::OrPattern::new(
patterns,
)))
}
pub fn not_matching(pattern: Pattern) -> Self {
Pattern::Meta(MetaPattern::Not(crate::pattern::meta::NotPattern::new(
pattern,
)))
}
pub fn capture(name: impl AsRef<str>, pattern: Pattern) -> Self {
Pattern::Meta(MetaPattern::Capture(
crate::pattern::meta::CapturePattern::new(name, pattern),
))
}
pub fn search(pattern: Pattern) -> Self {
Pattern::Meta(MetaPattern::Search(
crate::pattern::meta::SearchPattern::new(pattern),
))
}
pub fn repeat(pattern: Pattern, quantifier: crate::Quantifier) -> Self {
Pattern::Meta(MetaPattern::Repeat(
crate::pattern::meta::RepeatPattern::repeat(pattern, quantifier),
))
}
pub fn group(pattern: Pattern) -> Self {
Pattern::Meta(MetaPattern::Repeat(
crate::pattern::meta::RepeatPattern::new(pattern),
))
}
pub fn sequence(patterns: Vec<Pattern>) -> Self {
Pattern::Meta(MetaPattern::Sequence(
crate::pattern::meta::SequencePattern::new(patterns),
))
}
pub fn any_array() -> Self {
Pattern::Structure(crate::pattern::structure::StructurePattern::Array(
crate::pattern::structure::ArrayPattern::any(),
))
}
pub fn any_map() -> Self {
Pattern::Structure(crate::pattern::structure::StructurePattern::Map(
crate::pattern::structure::MapPattern::any(),
))
}
}
impl Pattern {
pub fn any_tagged() -> Self {
Pattern::Structure(crate::pattern::structure::StructurePattern::Tagged(
crate::pattern::structure::TaggedPattern::any(),
))
}
pub fn tagged(tag: impl Into<Tag>, pattern: Pattern) -> Self {
Pattern::Structure(crate::pattern::structure::StructurePattern::Tagged(
crate::pattern::structure::TaggedPattern::with_tag(tag, pattern),
))
}
pub fn tagged_name(name: impl Into<String>, pattern: Pattern) -> Self {
Pattern::Structure(crate::pattern::structure::StructurePattern::Tagged(
crate::pattern::structure::TaggedPattern::with_name(name, pattern),
))
}
pub fn tagged_regex(regex: regex::Regex, pattern: Pattern) -> Self {
Pattern::Structure(crate::pattern::structure::StructurePattern::Tagged(
crate::pattern::structure::TaggedPattern::with_regex(
regex, pattern,
),
))
}
}
impl TryFrom<&str> for Pattern {
type Error = Error;
fn try_from(value: &str) -> Result<Self> { Self::parse(value) }
}
impl Matcher for Pattern {
fn paths_with_captures(
&self,
haystack: &CBOR,
) -> (Vec<Path>, std::collections::HashMap<String, Vec<Path>>) {
let mut capture_names = Vec::new();
self.collect_capture_names(&mut capture_names);
if capture_names.is_empty() {
return (self.paths(haystack), std::collections::HashMap::new());
}
match self {
Pattern::Meta(pattern) => {
return pattern.paths_with_captures(haystack);
}
Pattern::Structure(pattern) => {
return pattern.paths_with_captures(haystack);
}
_ => {
}
}
let mut code = Vec::new();
let mut literals = Vec::new();
let mut captures = Vec::new();
self.compile(&mut code, &mut literals, &mut captures);
code.push(crate::pattern::vm::Instr::Accept);
let program = crate::pattern::vm::Program {
code,
literals,
capture_names: captures,
};
crate::pattern::vm::run(&program, haystack)
}
fn paths(&self, haystack: &CBOR) -> Vec<Path> {
match self {
Pattern::Value(pattern) => pattern.paths(haystack),
Pattern::Structure(pattern) => pattern.paths(haystack),
Pattern::Meta(pattern) => pattern.paths(haystack),
}
}
fn compile(
&self,
code: &mut Vec<Instr>,
literals: &mut Vec<Pattern>,
captures: &mut Vec<String>,
) {
match self {
Pattern::Value(pattern) => {
pattern.compile(code, literals, captures);
}
Pattern::Structure(pattern) => {
pattern.compile(code, literals, captures);
}
Pattern::Meta(pattern) => {
pattern.compile(code, literals, captures);
}
}
}
fn collect_capture_names(&self, names: &mut Vec<String>) {
match self {
Pattern::Value(_) => {
}
Pattern::Structure(pattern) => {
pattern.collect_capture_names(names);
}
Pattern::Meta(pattern) => {
pattern.collect_capture_names(names);
}
}
}
fn is_complex(&self) -> bool {
match self {
Pattern::Value(pattern) => pattern.is_complex(),
Pattern::Structure(_pattern) => false,
Pattern::Meta(pattern) => pattern.is_complex(),
}
}
}
impl std::fmt::Display for Pattern {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Pattern::Value(pattern) => write!(f, "{}", pattern),
Pattern::Structure(pattern) => write!(f, "{}", pattern),
Pattern::Meta(pattern) => write!(f, "{}", pattern),
}
}
}