use serde::{Deserialize, Serialize};
use crate::Principal;
#[derive(Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
enum ScopePrincipal {
Reserved { module_id: String },
Direct {},
Unverified {},
}
impl From<ScopePrincipal> for Principal {
fn from(value: ScopePrincipal) -> Self {
match value {
ScopePrincipal::Reserved { module_id } => Self::Reserved { module_id },
ScopePrincipal::Direct {} => Self::Direct,
ScopePrincipal::Unverified {} => Self::Unverified,
}
}
}
fn deserialize_scope_principal<'de, D: serde::Deserializer<'de>>(
deserializer: D,
) -> Result<Principal, D::Error> {
ScopePrincipal::deserialize(deserializer).map(Into::into)
}
fn deserialize_scope_principals<'de, D: serde::Deserializer<'de>>(
deserializer: D,
) -> Result<Vec<Principal>, D::Error> {
Vec::<ScopePrincipal>::deserialize(deserializer)
.map(|principals| principals.into_iter().map(Into::into).collect())
}
pub const CAP_SCOPES_V1: &str = "scopes/v1";
pub const CAP_ROUTE_ROLE_VERSIONS_V1: &str = "route-role-versions/v1";
pub const SCOPE_SYNC_OP: &str = "scope.sync";
pub const SCOPE_DESCRIBE_OP: &str = "scope.describe";
pub const MAX_LIVE_SCOPES_PER_OWNER: usize = 10_000;
pub const MAX_SCOPE_ATTRIBUTE_BYTES: usize = 4 * 1024;
pub const MAX_SCOPE_TOMBSTONES_PER_OWNER: usize = 1_000;
pub const MAX_CARRIER_TARGETS: usize = 16;
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum ScopeKind {
Head,
Worker,
Ephemeral,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct ScopeParent {
#[serde(deserialize_with = "deserialize_scope_principal")]
pub owner: Principal,
#[serde(rename = "ref")]
pub scope_ref: String,
pub scope_epoch: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct ScopeCarrier {
#[serde(deserialize_with = "deserialize_scope_principal")]
pub principal: Principal,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub targets: Option<Vec<String>>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct ScopeAttributes {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent_id: Option<String>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub delegates: bool,
}
impl ScopeAttributes {
pub fn is_empty(&self) -> bool {
self.agent_id.is_none() && !self.delegates
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct ScopeRecord {
#[serde(rename = "ref")]
pub scope_ref: String,
pub scope_epoch: u64,
pub kind: ScopeKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent: Option<ScopeParent>,
#[serde(
default,
skip_serializing_if = "Vec::is_empty",
deserialize_with = "deserialize_scope_principals"
)]
pub child_owners: Vec<Principal>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub carriers: Vec<ScopeCarrier>,
#[serde(default, skip_serializing_if = "ScopeAttributes::is_empty")]
pub attributes: ScopeAttributes,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct ScopeSelector {
#[serde(deserialize_with = "deserialize_scope_principal")]
pub owner: Principal,
#[serde(rename = "ref")]
pub scope_ref: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub scope_epoch: Option<u64>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum ParentState {
Linked,
Pending,
Ended,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ScopeRecordOutcome {
Created,
Replaced,
Updated,
Unchanged,
Refused,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ScopeRecordResult {
#[serde(rename = "ref")]
pub scope_ref: String,
pub scope_epoch: u64,
pub outcome: ScopeRecordOutcome,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub version: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent_state: Option<ParentState>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ScopeEnded {
#[serde(rename = "ref")]
pub scope_ref: String,
pub scope_epoch: u64,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ScopeStatus {
Live,
Ended,
NotLive,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ScopeStamp {
pub owner: Principal,
#[serde(rename = "ref")]
pub scope_ref: String,
pub scope_epoch: u64,
pub kind: ScopeKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent: Option<ScopeParent>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent_state: Option<ParentState>,
#[serde(default, skip_serializing_if = "ScopeAttributes::is_empty")]
pub attributes: ScopeAttributes,
pub owner_authorized: bool,
}