use super::*;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CapabilityClass {
Infrastructure,
#[default]
Functional,
}
impl CapabilityClass {
fn is_functional(&self) -> bool {
*self == Self::Functional
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CapabilityVisibility {
Local,
Cluster,
Tenant,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CapabilityDeclaration {
id: CapabilityId,
#[serde(default, skip_serializing_if = "CapabilityClass::is_functional")]
class: CapabilityClass,
version: String,
mode: CapabilityMode,
visibility: CapabilityVisibility,
requires_leader: bool,
idempotency_required: bool,
}
impl CapabilityDeclaration {
pub fn new(
id: CapabilityId,
version: impl Into<String>,
mode: CapabilityMode,
visibility: CapabilityVisibility,
) -> ContractResult<Self> {
let declaration = Self {
id,
class: CapabilityClass::Functional,
version: version.into(),
mode,
visibility,
requires_leader: false,
idempotency_required: false,
};
declaration.validate()?;
Ok(declaration)
}
pub fn with_class(mut self, class: CapabilityClass) -> Self {
self.class = class;
self
}
pub fn with_leadership(mut self, required: bool) -> Self {
self.requires_leader = required;
self
}
pub fn with_idempotency(mut self, required: bool) -> Self {
self.idempotency_required = required;
self
}
pub fn id(&self) -> &CapabilityId {
&self.id
}
pub fn class(&self) -> CapabilityClass {
self.class
}
pub fn version(&self) -> &str {
&self.version
}
pub fn mode(&self) -> CapabilityMode {
self.mode
}
pub fn visibility(&self) -> CapabilityVisibility {
self.visibility
}
pub fn requires_leader(&self) -> bool {
self.requires_leader
}
pub fn idempotency_required(&self) -> bool {
self.idempotency_required
}
pub(crate) fn validate(&self) -> ContractResult<()> {
validate_text("capability.version", &self.version, 64)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RuntimeRequirements {
minimum_runtime_version: String,
maximum_runtime_version: Option<String>,
protocol_version: String,
required_features: BTreeSet<FeatureId>,
}
impl RuntimeRequirements {
pub fn new(
minimum_runtime_version: impl Into<String>,
protocol_version: impl Into<String>,
) -> ContractResult<Self> {
let requirements = Self {
minimum_runtime_version: minimum_runtime_version.into(),
maximum_runtime_version: None,
protocol_version: protocol_version.into(),
required_features: BTreeSet::new(),
};
requirements.validate()?;
Ok(requirements)
}
pub fn with_maximum_runtime_version(
mut self,
version: impl Into<String>,
) -> ContractResult<Self> {
let version = version.into();
validate_text("runtime.maximum_version", &version, 64)?;
self.maximum_runtime_version = Some(version);
Ok(self)
}
pub fn with_required_feature(mut self, feature: FeatureId) -> Self {
self.required_features.insert(feature);
self
}
pub fn minimum_runtime_version(&self) -> &str {
&self.minimum_runtime_version
}
pub fn maximum_runtime_version(&self) -> Option<&str> {
self.maximum_runtime_version.as_deref()
}
pub fn protocol_version(&self) -> &str {
&self.protocol_version
}
pub fn required_features(&self) -> &BTreeSet<FeatureId> {
&self.required_features
}
pub(crate) fn validate(&self) -> ContractResult<()> {
validate_text("runtime.minimum_version", &self.minimum_runtime_version, 64)?;
validate_text("runtime.protocol_version", &self.protocol_version, 64)?;
if let Some(version) = &self.maximum_runtime_version {
validate_text("runtime.maximum_version", version, 64)?;
}
Ok(())
}
}