GMZ22FTMR2IJWPF7DXHIXRIQPWBOS4CT7BIABTKYBM4CUXKCNWZAC //! Lets say we have a struct like//! ```//! struct Hobbit {//! name: String,//! age: u32,//! friends: Vec<Hobbit>,//! nick: Option<String>,//! }//! ```//! and we want to record in a file how to create an instance of this struct. So we create a string//! like
//! Now we need to tell the struct how to select the the relevant part of this string, so for//! instance we need to tell the struct that we get the name by following the path//! `hobbit::name`. This selection mechanism has to be somewhat more sophisticated because we want//! to be able to select a `Vec` by, for instance, using the `hobbit::friends::hobbit` path to//! select both of Frodo's friends. Once we have selected the set of lines in the string we need a//! way to tell the data-structure how to convert that line into the correct type for the//! data-structure. To do this we need to implement the `FromStr` trait (if the field type does not//! already implement one) for the, so that the data-structure can take the selected key-values, and//! convert them to the field type. If the field type is a type `T` that we have built, we can//! implement `TryInto<T>` on it. The ! `TryInto` implementation for `Hobbit` looks like//! ```//! impl<'a> TryInto<Hobbit> for KeyTreeRef<'a> {//! type Error = Error;
//! so data can be recursive. Also, it is easy to refer to a set of data using a path such as//! `hobbit::friends::hobbit` refers to a collection of two hobbits.
//! fn try_into(self) -> Result<Hobbit, Error> {//! Ok(//! Hobbit {//! name: self.value("hobbit::name")?,//! age: self.value("hobbit::age")?,//! friends: self.opt_vec_at("hobbit::friends::hobbit")?,//! nick: self.opt_value("hobbit::nick")?,//! }//! )//! }//! }//! ```//! The important functions are//! ```//! name: self.value("hobbit::name")?//! ```//! and which converts from a string and//! ```//! hobbit: self.at("hobbit")?//! ```//! which converts to a type `T` implementing the `TryInto<T>` trait. Then there are variations of//! `value()` and `at()` for handling conversions into `Options`://!//! ```//! self.opt_value()//! ```//! and//! ```//! self.opt_at()//! ```//! In these cases, if the selected key-value does not exist, we get a `None` value. To convert into//! a `Vec` we can use//! ```//! self.vec_value()//! ```//! and//! ```//! self.vec_at()//! ```//! which require at least one key-value and//! ```//! self.opt_vec_at()//! ```//! and//! ```//! self.opt_vec_value()//! ```//! which will return an empty `Vec` if the key-value does not exist.
//! ```//!//! In the `TryInto` implementation that deserializes the keytree string into a data-structure, the//! line//! ```//! name: self.value("hobbit::name")?,//! ```//! takes the value on the line specified by `hobbit:name` (`Frodo Baggins`) and then uses the//! `FromStr` implement to convert it into the receiver type of the `name` field which is type//! `String`.//!//! The line//! ```//! friends: self.vec_at("hobbit::friends::hobbit")?,//! ```//! takes the collection of lines//! ```text//! hobbit://! name: Bilbo Baggins//! age: 111//! hobbit://! name: Samwise Gamgee//! age: 38//! nick: Sam
//! ## Efficiency//!//! There are no copies of the original string. The parsing process builds of immutable tree-structure which//! points into the original string. Selection operations involve the manipulation of a single `usize`//! cursor, so once A `KeyTree` is built, many lightweight `KeyTree` refs can be efficiently built//! and used for searching. So the only string copy that occurs is the final conversion into the//! receiving data-structure. Following a path into a keytree involves a scan of differently names//! siblings held in a Vec. The assumption is that the number of different sibling names is//! generally small because the number of fields in data-structures is also generally small. From//! the point of view of compile time, there are no dependencies and no macros.