tau_engine/
document.rs

1use crate::value::{Object, Value};
2
3/// A `Document` that can be evaluated by the solver.
4///
5/// Rules are solved against Documents, and thus to solve against a data type it must implement
6/// `Document`. Implementing `Object` gives this trait for free. Most of the time this trait will
7/// not need to be implmented, it is there to enable complex use cases.
8///
9/// # Implementations
10///
11/// The implementation for `Object` will just pass the `find` call along to the `Object`
12/// implementation of find. If for some reason this was undesired or just not needed below is an
13/// example of how to implement `Document`.
14///
15/// ```
16/// use std::borrow::Cow;
17///
18/// use tau_engine::{Document, Value};
19///
20/// struct Foo {
21///     bar: String,
22///     baz: String,
23/// }
24///
25/// impl Document for Foo {
26///     fn find(&self, key: &str) -> Option<Value<'_>> {
27///         match key {
28///             "bar" => Some(Value::String(Cow::Borrowed(&self.bar))),
29///             "baz" => Some(Value::String(Cow::Borrowed(&self.baz))),
30///             _ => None,
31///         }
32///     }
33/// }
34/// ```
35#[cfg(not(feature = "sync"))]
36pub trait Document {
37    /// Looks for a `Value` by key and returns it if found.
38    fn find(&self, key: &str) -> Option<Value<'_>>;
39}
40#[cfg(feature = "sync")]
41pub trait Document: Send + Sync {
42    fn find(&self, key: &str) -> Option<Value<'_>>;
43}
44
45impl Document for &dyn Object {
46    #[inline]
47    fn find(&self, key: &str) -> Option<Value<'_>> {
48        Object::find(*self, key)
49    }
50}
51
52impl<O: Object> Document for O {
53    #[inline]
54    fn find(&self, key: &str) -> Option<Value<'_>> {
55        Object::find(self, key)
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    use std::borrow::Cow;
64
65    struct Foo {
66        bar: String,
67    }
68    impl Document for Foo {
69        fn find(&self, key: &str) -> Option<Value<'_>> {
70            match key {
71                "bar" => Some(Value::String(Cow::Borrowed(&self.bar))),
72                _ => None,
73            }
74        }
75    }
76
77    #[test]
78    fn find() {
79        let foo = Foo {
80            bar: "baz".to_owned(),
81        };
82        assert_eq!(foo.find("bar").unwrap().as_str().unwrap(), "baz");
83    }
84}