use std::collections::HashMap;
pub use samod_core::PeerRequestState;
use samod_core::{ConnectionId, DocSearch, DocSearchPhase, DocumentActorId};
use crate::{DocHandle, actor_handle::ActorHandle};
#[derive(Debug, Clone)]
pub enum SearchState {
Loading,
Requesting(Request),
Found(DocHandle),
}
impl SearchState {
pub(crate) fn from_doc_search(
search: DocSearch,
actor_id: DocumentActorId,
actors: &HashMap<DocumentActorId, ActorHandle>,
) -> Self {
match search.phase() {
DocSearchPhase::Loading => Self::Loading,
DocSearchPhase::Searching(peers) => Self::Requesting(Request::new(
peers.clone(),
search.pending_connections().to_vec(),
)),
DocSearchPhase::Ready => {
if let Some(actor) = actors.get(&actor_id) {
Self::Found(actor.doc.clone())
} else {
tracing::warn!(
?actor_id,
"search reports Ready but no DocHandle is registered"
);
SearchState::Requesting(Request::empty())
}
}
}
}
}
#[derive(Debug, Clone)]
pub struct Request {
peers: HashMap<ConnectionId, PeerRequestState>,
pending_dialers: Vec<url::Url>,
}
impl Request {
pub(crate) fn empty() -> Self {
Self {
peers: HashMap::new(),
pending_dialers: Vec::new(),
}
}
pub(crate) fn new(
peers: HashMap<ConnectionId, PeerRequestState>,
pending_dialers: Vec<url::Url>,
) -> Self {
Self {
peers,
pending_dialers,
}
}
pub fn is_currently_unavailable(&self) -> bool {
self.pending_dialers.is_empty()
&& self
.peers
.values()
.all(|state| matches!(state, PeerRequestState::Unavailable))
}
pub fn peers(&self) -> &HashMap<ConnectionId, PeerRequestState> {
&self.peers
}
pub fn pending_dialers(&self) -> &[url::Url] {
&self.pending_dialers
}
}