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
use crate::value::{Object, Value}; /// A `Document` that can be evaluated by the solver. /// /// Rules are solved against Documents, and thus to solve against a data type it must implement /// `Document`. Implementing `Object` gives this trait for free. Most of the time this trait will /// not need to be implmented, it is there to enable complex use cases. /// /// # Implementations /// /// The implementation for `Object` will just pass the `find` call along to the `Object` /// implementation of find. If for some reason this was undesired or just not needed below is an /// example of how to implement `Document`. /// /// ``` /// use std::borrow::Cow; /// /// use tau_engine::{Document, Value}; /// /// struct Foo { /// bar: String, /// baz: String, /// } /// /// impl Document for Foo { /// fn find(&self, key: &str) -> Option<Value<'_>> { /// match key { /// "bar" => Some(Value::String(Cow::Borrowed(&self.bar))), /// "baz" => Some(Value::String(Cow::Borrowed(&self.baz))), /// _ => None, /// } /// } /// } /// ``` pub trait Document { /// Looks for a `Value` by key and returns it if found. fn find(&self, key: &str) -> Option<Value<'_>>; } impl Document for &dyn Object { #[inline] fn find(&self, key: &str) -> Option<Value<'_>> { Object::find(*self, key) } } impl<O: Object> Document for O { #[inline] fn find(&self, key: &str) -> Option<Value<'_>> { Object::find(self, key) } } #[cfg(test)] mod tests { use super::*; use std::borrow::Cow; struct Foo { bar: String, } impl Document for Foo { fn find(&self, key: &str) -> Option<Value<'_>> { match key { "bar" => Some(Value::String(Cow::Borrowed(&self.bar))), _ => None, } } } #[test] fn find() { let foo = Foo { bar: "baz".to_owned(), }; assert_eq!(foo.find("bar").unwrap().as_str().unwrap(), "baz"); } }