struct RegistrationQuery {
name: Arc<str>,
registration: Option<ActorRegistration<'static>>,
put_query_id: Option<kad::QueryId>,
provider_result: Option<kad::AddProviderResult>,
reply: Option<RegisterReply>,
}
struct LookupQuery {
name: Arc<str>,
providers_finished: bool,
metadata_queries: HashSet<kad::QueryId>,
queried_providers: HashSet<PeerId>,
reported_providers: HashSet<PeerId>,
reply: Option<LookupReply>,
}
impl LookupQuery {
fn get_metadata_record(
&mut self,
kademlia: &mut kad::Behaviour<kad::store::MemoryStore>,
provider: &PeerId,
) -> bool {
if self.queried_providers.contains(provider) {
return false;
}
self.queried_providers.insert(*provider);
let key = format!("{}:meta:{provider}", self.name);
let query_id = kademlia.get_record(key.into_bytes().into());
self.metadata_queries.insert(query_id);
true
}
fn has_metadata_query(&self, query_id: &kad::QueryId) -> bool {
self.metadata_queries.contains(query_id)
}
fn metadata_query_finished(&mut self, query_id: &kad::QueryId) {
self.metadata_queries.remove(query_id);
}
fn is_finished(&self) -> bool {
self.providers_finished && self.metadata_queries.is_empty()
}
}
#[derive(Debug)]
pub struct ActorRegistration<'a> {
pub actor_id: ActorId,
pub remote_id: Cow<'a, str>,
}
impl<'a> ActorRegistration<'a> {
pub fn new(actor_id: ActorId, remote_id: Cow<'a, str>) -> Self {
ActorRegistration {
actor_id,
remote_id,
}
}
pub fn into_bytes(self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(1 + 8 + 42 + self.remote_id.len());
let actor_id_bytes = self.actor_id.to_bytes();
let peer_id_len = (actor_id_bytes.len() - 8) as u8;
bytes.extend_from_slice(&peer_id_len.to_le_bytes());
bytes.extend_from_slice(&actor_id_bytes);
bytes.extend_from_slice(self.remote_id.as_bytes());
bytes
}
pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, InvalidActorRegistration> {
if bytes.is_empty() {
return Err(InvalidActorRegistration::EmptyActorRegistration);
}
let peer_id_bytes_len = u8::from_le_bytes(bytes[..1].try_into().unwrap()) as usize;
let actor_id = ActorId::from_bytes(&bytes[1..1 + 8 + peer_id_bytes_len])?;
let remote_id = std::str::from_utf8(&bytes[1 + 8 + peer_id_bytes_len..])
.map_err(InvalidActorRegistration::InvalidRemoteIDUtf8)?;
Ok(ActorRegistration::new(actor_id, Cow::Borrowed(remote_id)))
}
pub fn into_owned(self) -> ActorRegistration<'static> {
ActorRegistration::new(self.actor_id, Cow::Owned(self.remote_id.into_owned()))
}
}
#[derive(Debug)]
pub enum InvalidActorRegistration {
EmptyActorRegistration,
ActorId(ActorIdFromBytesError),
InvalidRemoteIDUtf8(str::Utf8Error),
}
impl From<ActorIdFromBytesError> for InvalidActorRegistration {
fn from(err: ActorIdFromBytesError) -> Self {
InvalidActorRegistration::ActorId(err)
}
}
impl fmt::Display for InvalidActorRegistration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InvalidActorRegistration::EmptyActorRegistration => {
write!(f, "empty actor registration")
}
InvalidActorRegistration::ActorId(err) => err.fmt(f),
InvalidActorRegistration::InvalidRemoteIDUtf8(err) => err.fmt(f),
}
}
}