use anyhow::{Result, anyhow};
use zenoh::Session;
use zenoh::handlers::FifoChannelHandler;
#[derive(Debug, Clone)]
pub struct ServedQuery {
pub selector: String,
pub parameters: String,
pub payload: Option<zenoh::bytes::ZBytes>,
pub encoding: Option<String>,
pub attachment: Option<zenoh::bytes::ZBytes>,
}
pub struct MockResponder {
queryable: zenoh::query::Queryable<FifoChannelHandler<zenoh::query::Query>>,
reply: Vec<u8>,
encoding: Option<String>,
}
impl std::fmt::Debug for MockResponder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MockResponder").finish_non_exhaustive()
}
}
pub async fn declare_responder(
session: &Session,
keyexpr: &str,
reply: Vec<u8>,
encoding: Option<&str>,
complete: bool,
) -> Result<MockResponder> {
let queryable = session
.declare_queryable(keyexpr.to_string())
.complete(complete)
.await
.map_err(|e| anyhow!("declare queryable {keyexpr}: {e}"))?;
Ok(MockResponder {
queryable,
reply,
encoding: encoding.map(str::to_string),
})
}
impl MockResponder {
pub async fn next(&self) -> Option<ServedQuery> {
let query = self.queryable.recv_async().await.ok()?;
let view = ServedQuery {
selector: query.selector().to_string(),
parameters: query.parameters().to_string(),
payload: query.payload().cloned(),
encoding: query.encoding().map(|e| e.to_string()),
attachment: query.attachment().cloned(),
};
let key = query.key_expr().clone();
let reply = query.reply(key, self.reply.clone());
let reply = match &self.encoding {
Some(e) => reply.encoding(e.as_str()),
None => reply,
};
let _ = reply.await;
Some(view)
}
pub async fn undeclare(self) -> Result<()> {
self.queryable
.undeclare()
.await
.map_err(|e| anyhow!("undeclare queryable: {e}"))
}
}