1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
// 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<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>>>,
objs: Option<BTreeMap<OKey, O>>
) -> Result<Self, PatternError<'s>>
where
PKey: Borrow<str> + Ord,
OKey: Borrow<str> + Ord,
{
Ok(Self {
consts: parse(input, preds, objs)?
})
}
/// Matches the pattern against an input.
pub fn deserialize<'de, Der, De>(&self, der: Der) -> Result<De, Der::Error>
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!()
}
}
|