// Copyright (C) 2021-2022 Soni L. // SPDX-License-Identifier: MIT OR Apache-2.0 //! Datafu Patterns. use std::borrow::Borrow; use std::collections::BTreeMap; use serde::de::Deserialize; use serde::de::DeserializeSeed; use serde::de::Deserializer; use serde::ser::Serialize; use crate::Predicate; use crate::errors::PatternError; use crate::parser::parse; use crate::vm; use crate::vm::PatternConstants; use crate::vm::MAX_CALLS; /// A compiled Datafu pattern. /// /// # Examples /// /// ``` /// use datafu::Pattern; /// /// let pattern = Pattern::<()>::compile::<&str, &str>( /// "->'hello'", /// None, None /// ).expect("failed to compile pattern"); /// ``` pub struct Pattern { consts: PatternConstants, } impl Pattern { /// Compiles the input into a pattern. /// /// # Examples /// /// ``` /// use datafu::Pattern; /// use serde::Deserialize; /// use charx; /// /// let preds = vec![ /// ("dict", datafu::pred(|v| { todo!() })), /// ("str", datafu::pred(|v| { String::deserialize(v).is_ok() })), /// ("commit", datafu::pred(|v| { /// if let Ok(v) = String::deserialize(v) { /// v.len() == 40 && v.trim_start_matches( /// charx::is_ascii_hexdigit /// ).is_empty() /// } else { /// false /// } /// })), /// ("uri", datafu::pred(|v| { todo!() })), /// ("bool", datafu::pred(|v| { todo!() })), /// ].into_iter().collect(); /// let pattern = Pattern::<()>::compile::<&str, &str>(" /// ->'projects':$dict /// ->commit[:?$str:?$commit]:?$dict /// ->url[:?$str:?$uri]:?$dict /// ->branch:?$dict /// (->active'active'?:?$bool) /// (->federate'federate'?:?$bool)?", /// Some(preds), None /// ).expect("failed to compile pattern"); /// ``` pub fn compile<'s, PKey, OKey>( input: &'s str, preds: Option>>, objs: Option> ) -> Result> where PKey: Borrow + Ord, OKey: Borrow + Ord, { Ok(Self { consts: parse(input, preds, objs)? }) } /// Matches the pattern against an input. pub fn deserialize<'de, Der, De>(&self, der: Der) -> Result where Der: Deserializer<'de>, De: Deserialize<'de>, { let pack = vm::Packer::new(&self.consts, MAX_CALLS).deserialize(der)?; let de = De::deserialize(vm::Unpacker::new(pack, MAX_CALLS)); todo!() } }