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
use super::{Receiver, Handle}; /// Trait for type-level identifiers for config entries. /// /// All implementors should be uninhabited types, as the creation of a type implementing `Entry` doesn't make sense: it's just a type-level marker identifying a configuration field. There are two ways to create such a type: /// ```rust /// enum MyUninhabited {} /// # /* /// // Works only on the nightly version of the compiler as of Rust 1.46 // FIXME remove this notice when the never type gets stabilized /// struct MyUninhabited (!); /// # */ /// ``` /// The first one is recommended, as it works on the stable version of the compiler. When the [`!` type gets stabilized], the second could be used as well, depending on your preference. /// /// [`!` type gets stabilized]: https://github.com/rust-lang/rust/issues/35121 " " pub trait Entry: Sized { /// The data value that the entry expects. type Data; /// The textual representation of the name of the entry. Should follow the same naming convention as struct fields and variables, i.e. `snake_case`. const NAME: &'static str; } /// Trait for getting handles to fields in config tables. /// /// This trait is implemented by config tables for every `E` which is a field inside the table. pub trait Get<E: Entry> { /// The [receiver] which will be notified when modifications are performed via the handle. /// /// [receiver]: trait.Receiver.html " " type Receiver: Receiver<E>; /// Returns an unguarded immutable reference to the field. fn get_ref(&self) -> &E::Data; /// Returns a [`Handle`] to the field. /// /// [`Handle`]: struct.Handle.html " " fn get_handle(&mut self) -> Handle<'_, E, Self::Receiver>; } /// A convenience trait for using turbofish syntax to get handles to fields in config tables. /// /// Using only [`Get`], getting handles to fields is inconvenient when there is no inference to help you, forcing you to use fully qualified trait call syntax. With `GetExt`, this becomes much easier: /// ``` /// # use snec::{ConfigTable, Entry, Handle, EmptyReceiver}; /// # #[derive(ConfigTable, Default)] /// # struct MyConfigTable { /// # #[snec] /// # my_entry: i32, /// # } /// use snec::GetExt as _; /// let mut table = MyConfigTable::default(); /// // Using the Get trait directly: /// let handle = <MyConfigTable as snec::Get<entries::MyEntry>>::get_handle(&mut table); /// // Using the GetExt trait: /// let handle = table.get_handle_to::<entries::MyEntry>(); /// ``` /// [`Get`]: trait.Get.html " " pub trait GetExt { /// Returns an unguarded immutable reference to the field. #[inline(always)] fn get_ref_to<E: Entry>(&self) -> &E::Data where Self: Get<E> { <Self as Get<E>>::get_ref(self) } /// Returns a [`Handle`] to the field. /// /// [`Handle`]: struct.Handle.html " " #[inline(always)] fn get_handle_to<E: Entry>(&mut self) -> Handle<'_, E, <Self as Get<E>>::Receiver> where Self: Get<E> { <Self as Get<E>>::get_handle(self) } } impl<T: ?Sized> GetExt for T {}