From 82aa4b902a77ce703cbb94a36c6265143741285b Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 16 Mar 2022 19:30:10 +0000 Subject: [PATCH] Provide define_accessor_trait and use it to generate CircMgrConfig --- Cargo.lock | 1 + crates/tor-basic-utils/Cargo.toml | 1 + crates/tor-basic-utils/src/lib.rs | 68 +++++++++++++++++++++++++++++++ crates/tor-circmgr/src/config.rs | 32 ++++++--------- 4 files changed, 82 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e1b047c1..cdcae9108 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3129,6 +3129,7 @@ dependencies = [ name = "tor-basic-utils" version = "0.1.0" dependencies = [ + "derive_more", "educe", "rand 0.8.5", ] diff --git a/crates/tor-basic-utils/Cargo.toml b/crates/tor-basic-utils/Cargo.toml index 9ae19c4c5..3ceea934c 100644 --- a/crates/tor-basic-utils/Cargo.toml +++ b/crates/tor-basic-utils/Cargo.toml @@ -15,4 +15,5 @@ repository = "https://gitlab.torproject.org/tpo/core/arti.git/" rand = "0.8" [dev-dependencies] +derive_more = "0.99" educe = "0.4.6" diff --git a/crates/tor-basic-utils/src/lib.rs b/crates/tor-basic-utils/src/lib.rs index 2c5ec8cd7..fb7f423fa 100644 --- a/crates/tor-basic-utils/src/lib.rs +++ b/crates/tor-basic-utils/src/lib.rs @@ -72,3 +72,71 @@ pub fn skip_fmt(_: &T, f: &mut fmt::Formatter) -> fmt::Result { } // ---------------------------------------------------------------------- + +/// Define an "accessor trait", which describes structs that have fields of certain types +/// +/// This can be useful if a large struct, living high up in the dependency graph, +/// contains fields that lower-lever crates want to be able to use without having +/// to copy the data about etc. +/// +/// ``` +/// // imagine this in the lower-level module +/// use tor_basic_utils::define_accessor_trait; +/// define_accessor_trait! { +/// pub trait View { +/// lorem: String, +/// ipsum: usize, +/// } +/// } +/// +/// fn test_view(v: &V) { +/// assert_eq!(v.lorem(), "sit"); +/// assert_eq!(v.ipsum(), &42); +/// } +/// +/// // imagine this in the higher-level module +/// use derive_more::AsRef; +/// #[derive(AsRef)] +/// struct Everything { +/// #[as_ref] lorem: String, +/// #[as_ref] ipsum: usize, +/// dolor: Vec<()>, +/// } +/// impl View for Everything { } +/// +/// let everything = Everything { +/// lorem: "sit".into(), +/// ipsum: 42, +/// dolor: vec![()], +/// }; +/// +/// test_view(&everything); +/// ``` +/// +/// ### Generated code +/// +/// ``` +/// pub trait View: AsRef + AsRef { +/// fn lorem(&self) -> &String { self.as_ref() } +/// fn ipsum(&self) -> &usize { self.as_ref() } +/// } +/// ``` +#[macro_export] +macro_rules! define_accessor_trait { + { + $( #[ $attr:meta ])* + $vis:vis trait $Trait:ident { + $( $accessor:ident: $type:ty, )* + } + } => { + $( #[ $attr ])* + $vis trait $Trait: $( core::convert::AsRef<$type> + )* { + $( + /// Access the field + fn $accessor(&self) -> &$type { core::convert::AsRef::as_ref(self) } + )* + } + } +} + +// ---------------------------------------------------------------------- diff --git a/crates/tor-circmgr/src/config.rs b/crates/tor-circmgr/src/config.rs index 6e0adecc8..dbce3df8a 100644 --- a/crates/tor-circmgr/src/config.rs +++ b/crates/tor-circmgr/src/config.rs @@ -4,6 +4,7 @@ //! //! Most types in this module are re-exported by `arti-client`. +use tor_basic_utils::define_accessor_trait; use tor_config::ConfigBuildError; use derive_builder::Builder; @@ -248,26 +249,17 @@ impl PreemptiveCircuitConfig { } } -/// Configuration for a circuit manager -/// -/// If the circuit manager gains new configurabilities, this trait will gain additional -/// supertraits, as an API break. -/// -/// Prefer to use `TorClientConfig`, which will always implement this trait. -pub trait CircMgrConfig: - AsRef + AsRef + AsRef -{ - /// Get the PathConfig - fn path_rules(&self) -> &PathConfig { - self.as_ref() - } - /// Get the CircuitTiming - fn circuit_timing(&self) -> &CircuitTiming { - self.as_ref() - } - /// Get the PreemptiveCircuitConfig - fn preemptive_circuits(&self) -> &PreemptiveCircuitConfig { - self.as_ref() +define_accessor_trait! { + /// Configuration for a circuit manager + /// + /// If the circuit manager gains new configurabilities, this trait will gain additional + /// supertraits, as an API break. + /// + /// Prefer to use [`TorClientConfig`], which will always implement this trait. + pub trait CircMgrConfig { + path_rules: PathConfig, + circuit_timing: CircuitTiming, + preemptive_circuits: PreemptiveCircuitConfig, } }