2026-06-23 12:02:01 -07:00
|
|
|
use components::EphemeralRegistry;
|
|
|
|
|
use crossbeam_channel::Receiver;
|
2026-07-03 23:18:10 +02:00
|
|
|
use libchat::{ChatError, ChatStorage, RegistrationService, StorageConfig};
|
|
|
|
|
use logos_account::AccountDirectory;
|
2026-06-23 12:02:01 -07:00
|
|
|
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<I = Unset, T = Unset, R = Unset, S = Unset> {
|
|
|
|
|
ident: I,
|
2026-07-03 23:18:10 +02:00
|
|
|
account: String,
|
2026-06-23 12:02:01 -07:00
|
|
|
transport: T,
|
|
|
|
|
registration: R,
|
|
|
|
|
storage: S,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-03 23:18:10 +02:00
|
|
|
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<String>) -> Self {
|
2026-06-23 12:02:01 -07:00
|
|
|
Self {
|
|
|
|
|
ident: Unset,
|
2026-07-03 23:18:10 +02:00
|
|
|
account: account.into(),
|
2026-06-23 12:02:01 -07:00
|
|
|
transport: Unset,
|
|
|
|
|
registration: Unset,
|
|
|
|
|
storage: Unset,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<I, T, R, S> ChatClientBuilder<I, T, R, S> {
|
2026-07-03 23:18:10 +02:00
|
|
|
pub fn ident(self, ident: DelegateSigner) -> ChatClientBuilder<DelegateSigner, T, R, S> {
|
2026-06-23 12:02:01 -07:00
|
|
|
ChatClientBuilder {
|
|
|
|
|
ident,
|
2026-07-03 23:18:10 +02:00
|
|
|
account: self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
transport: self.transport,
|
|
|
|
|
registration: self.registration,
|
|
|
|
|
storage: self.storage,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn transport<NT>(self, transport: NT) -> ChatClientBuilder<I, NT, R, S> {
|
|
|
|
|
ChatClientBuilder {
|
|
|
|
|
ident: self.ident,
|
2026-07-03 23:18:10 +02:00
|
|
|
account: self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
transport,
|
|
|
|
|
registration: self.registration,
|
|
|
|
|
storage: self.storage,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn registration<NR>(self, registration: NR) -> ChatClientBuilder<I, T, NR, S> {
|
|
|
|
|
ChatClientBuilder {
|
|
|
|
|
ident: self.ident,
|
2026-07-03 23:18:10 +02:00
|
|
|
account: self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
transport: self.transport,
|
|
|
|
|
registration,
|
|
|
|
|
storage: self.storage,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn storage<NS>(self, storage: NS) -> ChatClientBuilder<I, T, R, NS> {
|
|
|
|
|
ChatClientBuilder {
|
|
|
|
|
ident: self.ident,
|
2026-07-03 23:18:10 +02:00
|
|
|
account: self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
transport: self.transport,
|
|
|
|
|
registration: self.registration,
|
|
|
|
|
storage,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn storage_config(self, config: StorageConfig) -> ChatClientBuilder<I, T, R, ChatStorage> {
|
|
|
|
|
let storage = ChatStorage::new(config)
|
|
|
|
|
.map_err(ChatError::from)
|
|
|
|
|
.expect("Storage config file should be valid");
|
|
|
|
|
|
|
|
|
|
ChatClientBuilder {
|
|
|
|
|
ident: self.ident,
|
2026-07-03 23:18:10 +02:00
|
|
|
account: self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
transport: self.transport,
|
|
|
|
|
registration: self.registration,
|
|
|
|
|
storage,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-03 23:18:10 +02:00
|
|
|
type Built<T, R, S> = Result<(ChatClient<T, R, S>, Receiver<Event>), ClientError>;
|
2026-06-23 12:02:01 -07:00
|
|
|
|
|
|
|
|
// All four explicitly provided.
|
2026-07-03 23:18:10 +02:00
|
|
|
impl<T, R, S> ChatClientBuilder<DelegateSigner, T, R, S>
|
2026-06-23 12:02:01 -07:00
|
|
|
where
|
|
|
|
|
T: Transport + Send + 'static,
|
2026-07-03 23:18:10 +02:00
|
|
|
R: RegistrationService + AccountDirectory + Clone + Send + 'static,
|
2026-06-23 12:02:01 -07:00
|
|
|
S: ChatStore + Send + 'static,
|
|
|
|
|
{
|
2026-07-03 23:18:10 +02:00
|
|
|
pub fn build(self) -> Built<T, R, S> {
|
|
|
|
|
ChatClient::new(
|
|
|
|
|
self.ident,
|
|
|
|
|
self.account,
|
|
|
|
|
self.transport,
|
|
|
|
|
self.registration,
|
|
|
|
|
self.storage,
|
|
|
|
|
)
|
2026-06-23 12:02:01 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Transport only; I, R, S all default.
|
|
|
|
|
impl<T: Transport + Send + 'static> ChatClientBuilder<Unset, T, Unset, Unset> {
|
2026-07-03 23:18:10 +02:00
|
|
|
pub fn build(self) -> Built<T, EphemeralRegistry, ChatStorage> {
|
2026-06-23 12:02:01 -07:00
|
|
|
ChatClient::new(
|
|
|
|
|
DelegateSigner::random(),
|
2026-07-03 23:18:10 +02:00
|
|
|
self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
self.transport,
|
|
|
|
|
EphemeralRegistry::new(),
|
|
|
|
|
ChatStorage::in_memory(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// I and T; R and S default.
|
2026-07-03 23:18:10 +02:00
|
|
|
impl<T> ChatClientBuilder<DelegateSigner, T, Unset, Unset>
|
2026-06-23 12:02:01 -07:00
|
|
|
where
|
|
|
|
|
T: Transport + Send + 'static,
|
|
|
|
|
{
|
2026-07-03 23:18:10 +02:00
|
|
|
pub fn build(self) -> Built<T, EphemeralRegistry, ChatStorage> {
|
2026-06-23 12:02:01 -07:00
|
|
|
ChatClient::new(
|
|
|
|
|
self.ident,
|
2026-07-03 23:18:10 +02:00
|
|
|
self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
self.transport,
|
|
|
|
|
EphemeralRegistry::new(),
|
|
|
|
|
ChatStorage::in_memory(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// T and R; I and S default.
|
|
|
|
|
impl<T, R> ChatClientBuilder<Unset, T, R, Unset>
|
|
|
|
|
where
|
|
|
|
|
T: Transport + Send + 'static,
|
2026-07-03 23:18:10 +02:00
|
|
|
R: RegistrationService + AccountDirectory + Clone + Send + 'static,
|
2026-06-23 12:02:01 -07:00
|
|
|
{
|
2026-07-03 23:18:10 +02:00
|
|
|
pub fn build(self) -> Built<T, R, ChatStorage> {
|
2026-06-23 12:02:01 -07:00
|
|
|
ChatClient::new(
|
|
|
|
|
DelegateSigner::random(),
|
2026-07-03 23:18:10 +02:00
|
|
|
self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
self.transport,
|
|
|
|
|
self.registration,
|
|
|
|
|
ChatStorage::in_memory(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// T and S; I and R default.
|
|
|
|
|
impl<T, S> ChatClientBuilder<Unset, T, Unset, S>
|
|
|
|
|
where
|
|
|
|
|
T: Transport + Send + 'static,
|
|
|
|
|
S: ChatStore + Send + 'static,
|
|
|
|
|
{
|
2026-07-03 23:18:10 +02:00
|
|
|
pub fn build(self) -> Built<T, EphemeralRegistry, S> {
|
2026-06-23 12:02:01 -07:00
|
|
|
ChatClient::new(
|
|
|
|
|
DelegateSigner::random(),
|
2026-07-03 23:18:10 +02:00
|
|
|
self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
self.transport,
|
|
|
|
|
EphemeralRegistry::new(),
|
|
|
|
|
self.storage,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// I, T, and R; S defaults.
|
2026-07-03 23:18:10 +02:00
|
|
|
impl<T, R> ChatClientBuilder<DelegateSigner, T, R, Unset>
|
2026-06-23 12:02:01 -07:00
|
|
|
where
|
|
|
|
|
T: Transport + Send + 'static,
|
2026-07-03 23:18:10 +02:00
|
|
|
R: RegistrationService + AccountDirectory + Clone + Send + 'static,
|
2026-06-23 12:02:01 -07:00
|
|
|
{
|
2026-07-03 23:18:10 +02:00
|
|
|
pub fn build(self) -> Built<T, R, ChatStorage> {
|
2026-06-23 12:02:01 -07:00
|
|
|
ChatClient::new(
|
|
|
|
|
self.ident,
|
2026-07-03 23:18:10 +02:00
|
|
|
self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
self.transport,
|
|
|
|
|
self.registration,
|
|
|
|
|
ChatStorage::in_memory(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// T, R, and S; I defaults.
|
|
|
|
|
impl<T, R, S> ChatClientBuilder<Unset, T, R, S>
|
|
|
|
|
where
|
|
|
|
|
T: Transport + Send + 'static,
|
2026-07-03 23:18:10 +02:00
|
|
|
R: RegistrationService + AccountDirectory + Clone + Send + 'static,
|
2026-06-23 12:02:01 -07:00
|
|
|
S: ChatStore + Send + 'static,
|
|
|
|
|
{
|
2026-07-03 23:18:10 +02:00
|
|
|
pub fn build(self) -> Built<T, R, S> {
|
2026-06-23 12:02:01 -07:00
|
|
|
ChatClient::new(
|
|
|
|
|
DelegateSigner::random(),
|
2026-07-03 23:18:10 +02:00
|
|
|
self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
self.transport,
|
|
|
|
|
self.registration,
|
|
|
|
|
self.storage,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// I, T, and S; R defaults.
|
2026-07-03 23:18:10 +02:00
|
|
|
impl<T, S> ChatClientBuilder<DelegateSigner, T, Unset, S>
|
2026-06-23 12:02:01 -07:00
|
|
|
where
|
|
|
|
|
T: Transport + Send + 'static,
|
|
|
|
|
S: ChatStore + Send + 'static,
|
|
|
|
|
{
|
2026-07-03 23:18:10 +02:00
|
|
|
pub fn build(self) -> Built<T, EphemeralRegistry, S> {
|
2026-06-23 12:02:01 -07:00
|
|
|
ChatClient::new(
|
|
|
|
|
self.ident,
|
2026-07-03 23:18:10 +02:00
|
|
|
self.account,
|
2026-06-23 12:02:01 -07:00
|
|
|
self.transport,
|
|
|
|
|
EphemeralRegistry::new(),
|
|
|
|
|
self.storage,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|