Skip to content
Snippets Groups Projects
Commit 687e5c36 authored by Ian Jackson's avatar Ian Jackson
Browse files

tor-config: Introduce Builder trait and ConfigReolveError

We are going to need this for some generic code which is going to
appear shortly.  Having it produced by impl_standard_builder seems
best.  But that does mean being able to disable it, so extra stuff in
the macro.  Nothing uses this trait yet.

ConfigResolveError is not used now either, but will be in a moment.
parent d15cc758
No related branches found
No related tags found
No related merge requests found
......@@ -116,7 +116,7 @@ impl Reconfigure {
///
/// #[derive(Debug, Builder, Clone, Eq, PartialEq)]
/// struct UnusualStruct { }
/// impl_standard_builder! { UnusualStruct: !Deserialize }
/// impl_standard_builder! { UnusualStruct: !Deserialize + !Builder }
/// ```
///
/// # Requirements
......@@ -133,9 +133,13 @@ impl Reconfigure {
/// This should not be done for structs which are part of Arti's configuration,
/// but can be appropriate for other types that use [`derive_builder`].
///
/// * `!Builder` suppresses the impl of the [`tor_config::load::Builder`](load::Builder) trait
/// This will be necessary if the error from the builder is not [`ConfigBuildError`].
///
/// # Generates
///
/// * `impl Default for $Config`
/// * `impl Builder for $ConfigBuilder`
/// * a self-test that the `Default` impl actually works
/// * a test that the `Builder` can be deserialized from an empty [`config::Config`],
/// and then built, and that the result is the same as the ordinary default.
......@@ -149,19 +153,32 @@ macro_rules! impl_standard_builder {
$Config:ty $(: $($options:tt)* )?
} => { $crate::impl_standard_builder!{
// ^Being processed format:
@ ( try_deserialize ) $Config : $( $( $options )* )?
@ ( Builder )
( try_deserialize ) $Config : $( $( $options )* )?
// ~~~~~~~~~~~~~~~ ^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// present iff not !Builder
// present iff not !Deserialize type always present options yet to be parsed
} };
// If !Deserialize is the next option, implement it by making $try_deserialize absent
{
@ ( $($try_deserialize:ident)? ) $Config:ty : $(+)? !Deserialize $( $options:tt )*
@ ( $($Builder :ident)? )
( $($try_deserialize:ident)? ) $Config:ty : $(+)? !Deserialize $( $options:tt )*
} => { $crate::impl_standard_builder!{
@ ( $($Builder )? )
( ) $Config : $( $options )*
} };
// If !Builder is the next option, implement it by making $Builder absent
{
@ ( $($Builder :ident)? )
( $($try_deserialize:ident)? ) $Config:ty : $(+)? !Builder $( $options:tt )*
} => { $crate::impl_standard_builder!{
@ ( ) $Config : $( $options )*
@ ( )
( $($try_deserialize )? ) $Config : $( $options )*
} };
// Having parsed all options, produce output:
{
@ ( $($try_deserialize:ident)? ) $Config:ty : $(+)?
@ ( $($Builder :ident)? )
( $($try_deserialize:ident)? ) $Config:ty : $(+)?
} => { $crate::paste!{
impl $Config {
/// Returns a fresh, default, builder
......@@ -177,6 +194,15 @@ macro_rules! impl_standard_builder {
}
}
$( // expands iff there was $Builder, which is always Builder
impl $crate::load::$Builder for [< $Config Builder >] {
type Built = $Config;
fn build(&self) -> Result<$Config, $crate::ConfigBuildError> {
[< $Config Builder >]::build(self)
}
}
)?
#[test]
#[allow(non_snake_case)]
fn [< test_impl_Default_for_ $Config >] () {
......
//! Processing a config::Config into a validated configuration
use serde::de::DeserializeOwned;
use thiserror::Error;
use crate::ConfigBuildError;
/// Error resolveing a configuration (during deserialize, or build)
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum ConfigResolveError {
/// Deserialize failed
#[error("config contents not as expected: {0}")]
Deserialize(#[from] config::ConfigError),
/// Build failed
#[error("config semantically incorrect: {0}")]
Build(#[from] ConfigBuildError),
}
/// A type that can be built from a builder via a build method
pub trait Builder {
///
type Built;
/// Build into a `Built`
///
/// Often shadows an inherent `build` method
fn build(&self) -> Result<Self::Built, ConfigBuildError>;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment