use components::EphemeralRegistry; use crossbeam_channel::Receiver; use libchat::{ChatError, ChatStorage, IdentityProvider, RegistrationService, StorageConfig}; use storage::ChatStore; use crate::Transport; use crate::client::ChatClient; use crate::delegate::DelegateSigner; use crate::errors::ClientError; use crate::event::Event; /// Marker for a builder field that has not been configured; the corresponding /// component will be filled in with a sensible default when `build()` is called. pub struct Unset; pub struct ChatClientBuilder { ident: I, transport: T, registration: R, storage: S, } impl Default for ChatClientBuilder { fn default() -> Self { Self { ident: Unset, transport: Unset, registration: Unset, storage: Unset, } } } impl ChatClientBuilder { pub fn new() -> Self { Self::default() } } impl ChatClientBuilder { pub fn ident(self, ident: NI) -> ChatClientBuilder { ChatClientBuilder { ident, transport: self.transport, registration: self.registration, storage: self.storage, } } pub fn transport(self, transport: NT) -> ChatClientBuilder { ChatClientBuilder { ident: self.ident, transport, registration: self.registration, storage: self.storage, } } pub fn registration(self, registration: NR) -> ChatClientBuilder { ChatClientBuilder { ident: self.ident, transport: self.transport, registration, storage: self.storage, } } pub fn storage(self, storage: NS) -> ChatClientBuilder { ChatClientBuilder { ident: self.ident, transport: self.transport, registration: self.registration, storage, } } pub fn storage_config(self, config: StorageConfig) -> ChatClientBuilder { let storage = ChatStorage::new(config) .map_err(ChatError::from) .expect("Storage config file should be valid"); ChatClientBuilder { ident: self.ident, transport: self.transport, registration: self.registration, storage, } } } type Built = Result<(ChatClient, Receiver), ClientError>; // All four explicitly provided. impl ChatClientBuilder where I: IdentityProvider + Send + 'static, T: Transport + Send + 'static, R: RegistrationService + Send + 'static, S: ChatStore + Send + 'static, { pub fn build(self) -> Built { ChatClient::new(self.ident, self.transport, self.registration, self.storage) } } // Transport only; I, R, S all default. impl ChatClientBuilder { pub fn build(self) -> Built { ChatClient::new( DelegateSigner::random(), self.transport, EphemeralRegistry::new(), ChatStorage::in_memory(), ) } } // I and T; R and S default. impl ChatClientBuilder where I: IdentityProvider + Send + 'static, T: Transport + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( self.ident, self.transport, EphemeralRegistry::new(), ChatStorage::in_memory(), ) } } // T and R; I and S default. impl ChatClientBuilder where T: Transport + Send + 'static, R: RegistrationService + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( DelegateSigner::random(), self.transport, self.registration, ChatStorage::in_memory(), ) } } // T and S; I and R default. impl ChatClientBuilder where T: Transport + Send + 'static, S: ChatStore + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( DelegateSigner::random(), self.transport, EphemeralRegistry::new(), self.storage, ) } } // I, T, and R; S defaults. impl ChatClientBuilder where I: IdentityProvider + Send + 'static, T: Transport + Send + 'static, R: RegistrationService + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( self.ident, self.transport, self.registration, ChatStorage::in_memory(), ) } } // T, R, and S; I defaults. impl ChatClientBuilder where T: Transport + Send + 'static, R: RegistrationService + Send + 'static, S: ChatStore + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( DelegateSigner::random(), self.transport, self.registration, self.storage, ) } } // I, T, and S; R defaults. impl ChatClientBuilder where I: IdentityProvider + Send + 'static, T: Transport + Send + 'static, S: ChatStore + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( self.ident, self.transport, EphemeralRegistry::new(), self.storage, ) } }