use crate::registry::mailbox::{Call, Completion, Verb};
use crate::registry::{Client, tools};
use super::dispatch::Deps;
use super::reply::Reply;
pub(super) fn route(deps: &Deps, ts: &str, verb: &Verb) -> Result<Reply, String> {
match verb {
Verb::Invoke(call) => invoke(deps, ts, call),
Verb::Complete(done) => complete(deps, done),
}
}
fn invoke(deps: &Deps, ts: &str, call: &Call) -> Result<Reply, String> {
let client = Client::parse(&call.client)?;
if !tools::read(&deps.state_root, &client)
.iter()
.any(|tool| tool.name == call.tool)
{
return Err(format!(
"client {:?} advertises no tool {:?} right now",
call.client, call.tool
));
}
let invocation =
deps.caller
.mailbox
.post(ts.parse().unwrap_or(0), &deps.caller.client.name(), call);
Ok(Reply::Routed {
invocation,
capture: None,
})
}
fn complete(deps: &Deps, done: &Completion) -> Result<Reply, String> {
let client = connected(deps, "complete")?;
let capture = deps
.caller
.mailbox
.complete(&client, &done.invocation, &done.capture)?;
Ok(Reply::Routed {
invocation: done.invocation.clone(),
capture: Some(capture),
})
}
pub(super) fn invocations(deps: &Deps) -> Result<Reply, String> {
let client = connected(deps, "invocations")?;
Ok(Reply::Invocations(deps.caller.mailbox.take(&client)))
}
pub(super) fn capture(deps: &Deps, invocation: &str) -> Result<Reply, String> {
let capture = deps
.caller
.mailbox
.collect(&deps.caller.client.name(), invocation)?;
Ok(Reply::Routed {
invocation: invocation.to_owned(),
capture,
})
}
fn connected(deps: &Deps, verb: &str) -> Result<String, String> {
let client = &deps.caller.client;
if client.is_local() {
return Err(format!(
"{verb}: this intake carries no client identity — a tool host's work \
is addressed to the certificate a connection presented, and an \
in-world caller has none"
));
}
Ok(client.name())
}
#[cfg(test)]
mod tests;