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}