use std::fmt;
use std::str::FromStr;
pub trait Addressable: Authenticable {
fn as_agent_id(&self) -> &AgentId;
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct AgentId {
account_id: AccountId,
label: String,
}
#[cfg(feature = "sqlx")]
impl sqlx::encode::Encode<'_, sqlx::Postgres> for AgentId
where
AccountId: for<'q> sqlx::encode::Encode<'q, sqlx::Postgres>,
AccountId: sqlx::types::Type<sqlx::Postgres>,
String: for<'q> sqlx::encode::Encode<'q, sqlx::Postgres>,
String: sqlx::types::Type<sqlx::Postgres>,
{
fn encode_by_ref(&self, buf: &mut sqlx::postgres::PgArgumentBuffer) -> sqlx::encode::IsNull {
let mut encoder = sqlx::postgres::types::PgRecordEncoder::new(buf);
encoder.encode(&self.account_id);
encoder.encode(&self.label);
encoder.finish();
sqlx::encode::IsNull::No
}
fn size_hint(&self) -> usize {
2usize * (4 + 4)
+ <AccountId as sqlx::encode::Encode<sqlx::Postgres>>::size_hint(&self.account_id)
+ <String as sqlx::encode::Encode<sqlx::Postgres>>::size_hint(&self.label)
}
}
#[cfg(feature = "sqlx")]
impl<'r> sqlx::decode::Decode<'r, sqlx::Postgres> for AgentId
where
AccountId: for<'q> sqlx::decode::Decode<'q, sqlx::Postgres>,
AccountId: sqlx::types::Type<sqlx::Postgres>,
String: sqlx::decode::Decode<'r, sqlx::Postgres>,
String: sqlx::types::Type<sqlx::Postgres>,
{
fn decode(
value: sqlx::postgres::PgValueRef<'r>,
) -> std::result::Result<Self, Box<dyn std::error::Error + 'static + Send + Sync>> {
let mut decoder = sqlx::postgres::types::PgRecordDecoder::new(value)?;
let account_id = decoder.try_decode::<AccountId>()?;
let label = decoder.try_decode::<String>()?;
Ok(AgentId { account_id, label })
}
}
#[cfg(feature = "sqlx")]
impl sqlx::Type<sqlx::Postgres> for AgentId {
fn type_info() -> sqlx::postgres::PgTypeInfo {
sqlx::postgres::PgTypeInfo::with_name("agent_id")
}
}
#[cfg(feature = "sqlx")]
impl sqlx::postgres::PgHasArrayType for AgentId {
fn array_type_info() -> sqlx::postgres::PgTypeInfo {
sqlx::postgres::PgTypeInfo::with_name("_agent_id")
}
}
#[cfg(feature = "sqlx")]
impl sqlx::postgres::PgHasArrayType for &AgentId {
fn array_type_info() -> sqlx::postgres::PgTypeInfo {
sqlx::postgres::PgTypeInfo::with_name("_agent_id")
}
}
impl AgentId {
pub fn new<S: Into<String>>(label: S, account_id: AccountId) -> Self {
Self {
label: label.into(),
account_id,
}
}
pub fn label(&self) -> &str {
&self.label
}
}
impl fmt::Display for AgentId {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}.{}", self.label(), self.account_id)
}
}
impl FromStr for AgentId {
type Err = Error;
fn from_str(val: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = val.splitn(2, '.').collect();
match parts[..] {
[label, rest] => {
let account_id = rest.parse::<AccountId>().map_err(|e| {
Error::new(&format!(
"error deserializing shared group from a string, {}",
&e
))
})?;
Ok(Self::new(label, account_id))
}
_ => Err(Error::new(&format!(
"invalid value for the agent id: {}",
val
))),
}
}
}
impl Authenticable for AgentId {
fn as_account_id(&self) -> &AccountId {
&self.account_id
}
}
impl Addressable for AgentId {
fn as_agent_id(&self) -> &Self {
self
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SharedGroup {
label: String,
account_id: AccountId,
}
impl SharedGroup {
pub fn new(label: &str, account_id: AccountId) -> Self {
Self {
label: label.to_owned(),
account_id,
}
}
}
impl fmt::Display for SharedGroup {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{}", self.label, self.account_id)
}
}
impl FromStr for SharedGroup {
type Err = Error;
fn from_str(val: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = val.splitn(2, '.').collect();
match parts[..] {
[label, rest] => {
let account_id = rest.parse::<AccountId>().map_err(|e| {
Error::new(&format!(
"error deserializing shared group from a string, {}",
&e
))
})?;
Ok(Self::new(label, account_id))
}
_ => Err(Error::new(&format!(
"invalid value for the application group: {}",
val
))),
}
}
}
#[derive(Debug)]
pub enum Destination {
Broadcast(String),
Multicast(AccountId, String),
Unicast(AgentId, String),
}
#[derive(Debug)]
pub enum Source<'a> {
Broadcast(&'a AccountId, &'a str, &'a str),
Multicast(Option<&'a AgentId>, Option<&'a str>),
Unicast(Option<&'a AccountId>),
}
pub struct Subscription {}
impl Subscription {
pub fn broadcast_events<'a, A>(
from: &'a A,
version: &'a str,
uri: &'a str,
) -> EventSubscription<'a>
where
A: Authenticable,
{
EventSubscription::new(Source::Broadcast(from.as_account_id(), version, uri))
}
pub fn multicast_requests(version: Option<&str>) -> RequestSubscription {
RequestSubscription::new(Source::Multicast(None, version))
}
pub fn multicast_requests_from<'a, A>(
from: &'a A,
version: Option<&'a str>,
) -> RequestSubscription<'a>
where
A: Addressable,
{
RequestSubscription::new(Source::Multicast(Some(from.as_agent_id()), version))
}
pub fn unicast_requests<'a>() -> RequestSubscription<'a> {
RequestSubscription::new(Source::Unicast(None))
}
pub fn unicast_requests_from<A>(from: &A) -> RequestSubscription
where
A: Authenticable,
{
RequestSubscription::new(Source::Unicast(Some(from.as_account_id())))
}
pub fn unicast_responses<'a>() -> ResponseSubscription<'a> {
ResponseSubscription::new(Source::Unicast(None))
}
pub fn unicast_responses_from<A>(from: &A) -> ResponseSubscription
where
A: Authenticable,
{
ResponseSubscription::new(Source::Unicast(Some(from.as_account_id())))
}
}
pub struct EventSubscription<'a> {
source: Source<'a>,
}
impl<'a> EventSubscription<'a> {
pub fn new(source: Source<'a>) -> Self {
Self { source }
}
}
pub struct RequestSubscription<'a> {
source: Source<'a>,
}
impl<'a> RequestSubscription<'a> {
pub fn new(source: Source<'a>) -> Self {
Self { source }
}
}
pub struct ResponseSubscription<'a> {
source: Source<'a>,
}
impl<'a> ResponseSubscription<'a> {
pub fn new(source: Source<'a>) -> Self {
Self { source }
}
}
pub use svc_authn::{AccountId, Authenticable};
pub use self::error::Error;
pub mod error;
pub mod mqtt;
#[cfg(feature = "queue-counter")]
pub mod queue_counter;
pub mod request;
pub(crate) mod serde;