use crate::peer::PeerIdentity;
use std::collections::BTreeSet;
pub type Scope = String;
pub const ROLE_SCOPE_PREFIX: &str = "role:";
pub fn role_scope(role: &str) -> Scope {
format!("{ROLE_SCOPE_PREFIX}{role}")
}
pub fn role_of<'a>(scopes: impl IntoIterator<Item = &'a str>) -> Option<&'a str> {
let mut found = None;
for scope in scopes {
if let Some(name) = scope.strip_prefix(ROLE_SCOPE_PREFIX) {
if name.is_empty() || found.is_some() {
return None;
}
found = Some(name);
}
}
found
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Caller {
LocalApp { app: String, peer: PeerIdentity },
Device { id: String, scopes: BTreeSet<Scope> },
}
impl Caller {
pub fn local_app(app: impl Into<String>, peer: PeerIdentity) -> Self {
Caller::LocalApp {
app: app.into(),
peer,
}
}
pub fn device<I, S>(id: impl Into<String>, scopes: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<Scope>,
{
Caller::Device {
id: id.into(),
scopes: scopes.into_iter().map(Into::into).collect(),
}
}
pub fn peer(&self) -> Option<&PeerIdentity> {
match self {
Caller::LocalApp { peer, .. } => Some(peer),
Caller::Device { .. } => None,
}
}
pub fn role(&self) -> Option<&str> {
match self {
Caller::LocalApp { .. } => None,
Caller::Device { scopes, .. } => role_of(scopes.iter().map(String::as_str)),
}
}
pub fn label(&self) -> &str {
match self {
Caller::LocalApp { app, .. } => app,
Caller::Device { id, .. } => id,
}
}
}