use components::EphemeralRegistry; use crossbeam_channel::Receiver; use libchat::{ChatError, ChatStorage, RegistrationService, StorageConfig}; use logos_account::AccountDirectory; 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, account: String, transport: T, registration: R, storage: S, } impl ChatClientBuilder { /// Every client acts for an account, so the builder starts from its /// address. It becomes the client's shareable address /// ([`ChatClient::addr`]) and the account claim in the wire credential; /// the account must endorse the signer in the directory for peers to /// verify that claim. pub fn new(account: impl Into) -> Self { Self { ident: Unset, account: account.into(), transport: Unset, registration: Unset, storage: Unset, } } } impl ChatClientBuilder { pub fn ident(self, ident: DelegateSigner) -> ChatClientBuilder { ChatClientBuilder { ident, account: self.account, transport: self.transport, registration: self.registration, storage: self.storage, } } pub fn transport(self, transport: NT) -> ChatClientBuilder { ChatClientBuilder { ident: self.ident, account: self.account, transport, registration: self.registration, storage: self.storage, } } pub fn registration(self, registration: NR) -> ChatClientBuilder { ChatClientBuilder { ident: self.ident, account: self.account, transport: self.transport, registration, storage: self.storage, } } pub fn storage(self, storage: NS) -> ChatClientBuilder { ChatClientBuilder { ident: self.ident, account: self.account, 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, account: self.account, transport: self.transport, registration: self.registration, storage, } } } type Built = Result<(ChatClient, Receiver), ClientError>; // All four explicitly provided. impl ChatClientBuilder where T: Transport + Send + 'static, R: RegistrationService + AccountDirectory + Clone + Send + 'static, S: ChatStore + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( self.ident, self.account, 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.account, self.transport, EphemeralRegistry::new(), ChatStorage::in_memory(), ) } } // I and T; R and S default. impl ChatClientBuilder where T: Transport + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( self.ident, self.account, self.transport, EphemeralRegistry::new(), ChatStorage::in_memory(), ) } } // T and R; I and S default. impl ChatClientBuilder where T: Transport + Send + 'static, R: RegistrationService + AccountDirectory + Clone + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( DelegateSigner::random(), self.account, 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.account, self.transport, EphemeralRegistry::new(), self.storage, ) } } // I, T, and R; S defaults. impl ChatClientBuilder where T: Transport + Send + 'static, R: RegistrationService + AccountDirectory + Clone + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( self.ident, self.account, self.transport, self.registration, ChatStorage::in_memory(), ) } } // T, R, and S; I defaults. impl ChatClientBuilder where T: Transport + Send + 'static, R: RegistrationService + AccountDirectory + Clone + Send + 'static, S: ChatStore + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( DelegateSigner::random(), self.account, self.transport, self.registration, self.storage, ) } } // I, T, and S; R defaults. impl ChatClientBuilder where T: Transport + Send + 'static, S: ChatStore + Send + 'static, { pub fn build(self) -> Built { ChatClient::new( self.ident, self.account, self.transport, EphemeralRegistry::new(), self.storage, ) } }