Provide define_accessor_trait and use it to generate CircMgrConfig

This commit is contained in:
Ian Jackson 2022-03-16 19:30:10 +00:00
parent 8bde40fdd3
commit 82aa4b902a
4 changed files with 82 additions and 20 deletions

1
Cargo.lock generated
View File

@ -3129,6 +3129,7 @@ dependencies = [
name = "tor-basic-utils"
version = "0.1.0"
dependencies = [
"derive_more",
"educe",
"rand 0.8.5",
]

View File

@ -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"

View File

@ -72,3 +72,71 @@ pub fn skip_fmt<T>(_: &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: 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<String> + AsRef<usize> {
/// 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) }
)*
}
}
}
// ----------------------------------------------------------------------

View File

@ -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 {
}
}
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:
AsRef<PathConfig> + AsRef<CircuitTiming> + AsRef<PreemptiveCircuitConfig>
{
/// 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()
/// Prefer to use [`TorClientConfig`], which will always implement this trait.
pub trait CircMgrConfig {
path_rules: PathConfig,
circuit_timing: CircuitTiming,
preemptive_circuits: PreemptiveCircuitConfig,
}
}