use std::borrow::Cow;
use std::marker::PhantomData;
pub struct Publish<B>(PhantomData<fn() -> B>);
pub struct Subscribe<B>(PhantomData<fn() -> B>);
pub struct AskQuery<Req, Resp>(PhantomData<fn() -> (Req, Resp)>);
pub struct ServeQuery<Req, Resp>(PhantomData<fn() -> (Req, Resp)>);
mod sealed {
pub trait Sealed {}
}
pub trait TopicKind: sealed::Sealed {}
impl<B> sealed::Sealed for Publish<B> {}
impl<B> TopicKind for Publish<B> {}
impl<B> sealed::Sealed for Subscribe<B> {}
impl<B> TopicKind for Subscribe<B> {}
impl<Req, Resp> sealed::Sealed for AskQuery<Req, Resp> {}
impl<Req, Resp> TopicKind for AskQuery<Req, Resp> {}
impl<Req, Resp> sealed::Sealed for ServeQuery<Req, Resp> {}
impl<Req, Resp> TopicKind for ServeQuery<Req, Resp> {}
pub struct Topic<Kind> {
key: Cow<'static, str>,
_kind: PhantomData<Kind>,
}
impl<Kind> Topic<Kind> {
#[doc(hidden)]
pub fn new_static(key: &'static str) -> Self {
Topic {
key: Cow::Borrowed(key),
_kind: PhantomData,
}
}
#[doc(hidden)]
pub fn new_owned(key: String) -> Self {
Topic {
key: Cow::Owned(key),
_kind: PhantomData,
}
}
pub fn key(&self) -> &str {
&self.key
}
pub fn publish_key(&self) -> Result<&str, WildcardPublish> {
if self.key.split('/').any(|seg| seg == "*" || seg == "**") {
Err(WildcardPublish {
key: self.key.to_string(),
})
} else {
Ok(&self.key)
}
}
}
impl<Kind> Clone for Topic<Kind> {
fn clone(&self) -> Self {
Topic {
key: self.key.clone(),
_kind: PhantomData,
}
}
}
#[derive(Debug, thiserror::Error)]
#[error("cannot publish on wildcard topic '{key}' (wildcards are subscribe-only)")]
pub struct WildcardPublish {
pub key: String,
}