summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml1
-rw-r--r--src/lib.rs29
-rw-r--r--src/pattern.rs47
-rw-r--r--src/vm.rs9
-rw-r--r--src/vm/de.rs6
-rw-r--r--tests/basic_match.rs4
6 files changed, 89 insertions, 7 deletions
diff --git a/Cargo.toml b/Cargo.toml
index a0532df..1a85a35 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,6 +21,7 @@ erased-serde = "0.3.21"
 proptest = "1.0.0"
 serde_json = "1.0.82"
 serde = {version = "1.0.140", features = ["derive"]}
+charx = "1"
 
 [features]
 default = ['stable']
diff --git a/src/lib.rs b/src/lib.rs
index 8fa727f..a3a6e1e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -106,15 +106,34 @@ mod vm;
 pub use pattern::Pattern;
 
 /// A predicate.
-pub type Predicate = dyn (for<'x, 'de, 'a> Fn(
-    &'x (dyn 'a + erased_serde::Deserializer<'de>)
+pub type Predicate = dyn (Fn(
+    &mut dyn erased_serde::Deserializer<>
 ) -> bool) + Send + Sync;
 
-/// Helper to build predicates because HRTB inference is the worst.
+/// Helper to build predicates because closure inference is the worst.
+///
+/// # Examples
+///
+/// This doesn't work:
+///
+/// ```rust compile_fail
+/// use serde::Deserialize;
+/// use datafu::Predicate;
+///
+/// let x = Box::new(|v| String::deserialize(v).is_ok()) as Box<Predicate>;
+/// ```
+///
+/// But this does:
+///
+/// ```rust
+/// use serde::Deserialize;
+///
+/// let x = datafu::pred(|v| String::deserialize(v).is_ok());
+/// ```
 pub fn pred<F>(f: F) -> Box<Predicate>
 where
-    F: (for<'x, 'de, 'a> Fn(
-        &'x (dyn 'a + erased_serde::Deserializer<'de>)
+    F: (Fn(
+        &mut dyn erased_serde::Deserializer<>
     ) -> bool) +  Send + Sync + 'static,
 {
     Box::new(f)
diff --git a/src/pattern.rs b/src/pattern.rs
index 3a8c91f..2e69714 100644
--- a/src/pattern.rs
+++ b/src/pattern.rs
@@ -1,6 +1,8 @@
 // Copyright (C) 2021-2022 Soni L.
 // SPDX-License-Identifier: MIT OR Apache-2.0
 
+//! Datafu Patterns.
+
 use std::borrow::Borrow;
 use std::collections::BTreeMap;
 
@@ -15,12 +17,57 @@ use crate::parser::parse;
 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<O: Serialize> {
     consts: PatternConstants<O>,
 }
 
 impl<O: Serialize> Pattern<O> {
     /// 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<BTreeMap<PKey, Box<Predicate>>>,
diff --git a/src/vm.rs b/src/vm.rs
index 6bcbf70..ac5c95d 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -1,17 +1,24 @@
 // Copyright (C) 2021-2022 Soni L.
 // SPDX-License-Identifier: MIT OR Apache-2.0
 
+//! The Datafu Virtual Machine.
+//!
+//! This is the stuff that actually matches the pattern.
+
 use regex::Regex;
 use serde::Serialize;
 
 use crate::Predicate;
 //use crate::errors::MatchError;
 
+mod de;
+
+/// Max depth for VM/serde recursion.
 pub(crate) const MAX_CALLS: usize = 250;
 
 //type Matches<'a, 'b, T> = BTreeMap<&'a str, KVPair<'b, T>>;
 
-// TODO: use a builder for this?
+// maybe we should use a builder for this?
 /// The constant pool for a pattern.
 pub(crate) struct PatternConstants<O: Serialize> {
     // last proto is implicitly the whole pattern.
diff --git a/src/vm/de.rs b/src/vm/de.rs
new file mode 100644
index 0000000..7039ea9
--- /dev/null
+++ b/src/vm/de.rs
@@ -0,0 +1,6 @@
+// Copyright (C) 2022 Soni L.
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+use crate::vm;
+
+
diff --git a/tests/basic_match.rs b/tests/basic_match.rs
index 1500356..5c03a48 100644
--- a/tests/basic_match.rs
+++ b/tests/basic_match.rs
@@ -4,10 +4,12 @@
 use serde_json::Deserializer as JsonDer;
 use serde::Deserialize;
 
+use datafu::Predicate;
+
 #[test]
 fn test_basic() {
     let mut der = JsonDer::from_str(r#"{"foo": 1, "bar": {"baz": 2}}"#);
-    let preds = vec![("dict", datafu::pred(|v| { todo!() }))].into_iter().collect();
+    let preds = vec![("dict", datafu::pred(|v| { todo!(); false }))].into_iter().collect();
     let pat = datafu::Pattern::<()>::compile::<&str, &str>("->[x]:?$dict->y[yk]", Some(preds), None).unwrap();
     #[derive(Deserialize)]
     struct Values {