I am trying to implement the builder pattern for a struct with generic parameters. The builder struct implements the default trait returning itself with the properties set to specific implementations of the generic parameters.
The problem is that once the builder is generated with the default properties, the user should still be able to change it to other types/implementations of the generic types.
#[derive(Educe)]
#[educe(Debug)]
pub struct ArtiConnector<R: Runtime, TC: TlsConn> {
/// Arti client to connect to Tor.
#[educe(Debug(ignore))]
client: Arc<TorClient<R>>,
/// The runtime to use for blocking operations.
rt: R,
/// Has type `TlsConn` corresponding to any implementation of the trait [`ureq::unversioned::transport::Connector`].
#[educe(Debug(ignore))]
tls_conn: TC,
}
impl<R: Runtime, TC: TlsConn> std::default::Default for ArtiConnectorBuilder<R, TC> {
fn default() -> Self {
// Default TorClientConfig
let config = arti_client::TorClientConfig::default();
// Default Runtime
let rt = tor_rtcompat::PreferredRuntime::create().expect("Failed to create runtime.");
// Default TorClient
let client = TorClient::with_runtime(rt.clone())
.create_unbootstrapped()
.expect("Error creating Tor Client.");
client
.reconfigure(&config, Reconfigure::AllOrNothing)
.expect("Error applying config to Tor Client.");
// Default TlsConn
let tls_conn = ureq::unversioned::transport::DefaultConnector::default();
Self {
client: Arc::new(client),
rt,
tls_conn,
tor_config: config,
}
}
}
impl ArtiConnector<tor_rtcompat::PreferredRuntime, ureq::unversioned::transport::DefaultConnector> {
pub fn builder() -> ArtiConnectorBuilder<tor_rtcompat::PreferredRuntime, ureq::unversioned::transport::DefaultConnector> {
ArtiConnectorBuilder::default()
}
}
pub struct ArtiConnectorBuilder<R: Runtime = tor_rtcompat::PreferredRuntime, TC: TlsConn = ureq::unversioned::transport::DefaultConnector> {
client: Arc<TorClient<R>>,
rt: R,
tls_conn: TC,
tor_config: TorClientConfig,
}
impl <R: Runtime, TC: TlsConn> ArtiConnectorBuilder<R, TC> {
pub fn build(self) -> ArtiConnector<R, TC> {
self.client.reconfigure(&self.tor_config, Reconfigure::AllOrNothing)
.expect("Error applying config to Tor Client.");
ArtiConnector {
client: self.client,
rt: self.rt,
tls_conn: self.tls_conn,
}
}
pub fn with_tor_client(mut self, client: TorClient<R>) -> Self {
self.client = client.into();
self
}
pub fn with_tor_config(mut self, config: TorClientConfig) -> Self {
self.tor_config = config;
self
}
pub fn with_runtime(mut self, rt: R) -> Self {
self.rt = rt;
self
}
pub fn with_tls_conn(mut self, tls_conn: TC) -> Self {
self.tls_conn = tls_conn;
self
}
}
Error:
error[E0308]: mismatched types
--> crates/arti-ureq/src/lib.rs:104:30
|
84 | impl<R: Runtime, TC: TlsConn> std::default::Default for ArtiConnectorBuilder<R,...
| - expected this type parameter
...
104 | client: Arc::new(client),
| -------- ^^^^^^ expected `TorClient<R>`, found `TorClient<PreferredRuntime>`
| |
| arguments to this function are incorrect
|
= note: expected struct `TorClient<R>`
found struct `TorClient<tor_rtcompat::PreferredRuntime>`
note: associated function defined here
--> /Users/name/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:385:12
|
385 | pub fn new(data: T) -> Arc<T> {
| ^^^
error[E0308]: mismatched types
--> crates/arti-ureq/src/lib.rs:105:13
|
84 | impl<R: Runtime, TC: TlsConn> std::default::Default for ArtiConnectorBuilder<R,...
| - expected this type parameter
...
105 | rt,
| ^^ expected type parameter `R`, found `PreferredRuntime`
|
= note: expected type parameter `R`
found struct `tor_rtcompat::PreferredRuntime`
error[E0308]: mismatched types
--> crates/arti-ureq/src/lib.rs:106:13
|
84 | impl<R: Runtime, TC: TlsConn> std::default::Default for ArtiConnectorBuilder<R,...
| -- expected this type parameter
...
106 | tls_conn,
| ^^^^^^^^ expected type parameter `TC`, found `DefaultConnector`
|
= note: expected type parameter `TC`
found struct `DefaultConnector`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `arti-ureq` (lib) due to 3 previous errors
How would I fix this? I want the default
method in the builder to return specific implementations of the generic parameters, but the user should be able to edit those properties to other types implementing the trait of the generic parameters.