use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use serde_json::Value;
use tokio::sync::oneshot;
use trust_tasks_rs::TrustTask;
#[derive(Clone, Default)]
pub struct PendingReplies {
inner: Arc<Mutex<HashMap<String, Waiter>>>,
}
struct Waiter {
peer: String,
tx: oneshot::Sender<TrustTask<Value>>,
}
fn base_did(did: &str) -> &str {
did.split('#').next().unwrap_or(did)
}
impl PendingReplies {
pub fn new() -> Self {
Self::default()
}
pub fn register(&self, request_id: &str, peer: &str) -> oneshot::Receiver<TrustTask<Value>> {
let (tx, rx) = oneshot::channel();
self.lock().insert(
request_id.to_string(),
Waiter {
peer: base_did(peer).to_string(),
tx,
},
);
rx
}
pub fn abandon(&self, request_id: &str) {
self.lock().remove(request_id);
}
pub fn complete(&self, document: TrustTask<Value>, verified_signer: Option<&str>) -> bool {
let Some(thread_id) = document.thread_id.clone() else {
return false;
};
let Some(signer) = verified_signer.map(base_did) else {
return false;
};
let waiter = {
let mut map = self.lock();
match map.get(&thread_id) {
Some(w) if w.peer == signer => map.remove(&thread_id),
_ => None,
}
};
match waiter {
Some(w) => w.tx.send(document).is_ok(),
None => false,
}
}
pub async fn complete_verified(
&self,
document: TrustTask<Value>,
received: &Value,
resolver: &vti_common::auth::TrustTaskVmResolver,
) -> bool {
let signer = match document.proof.as_ref() {
Some(_) => vti_common::auth::verify_trust_task_proof_value(received, resolver)
.await
.ok()
.map(|s| base_did(&s).to_string())
.filter(|s| document.issuer.as_deref() == Some(s.as_str())),
None => None,
};
self.complete(document, signer.as_deref())
}
fn lock(&self) -> std::sync::MutexGuard<'_, HashMap<String, Waiter>> {
self.inner.lock().unwrap_or_else(|p| p.into_inner())
}
}