#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum OperationImpact {
ReadOnly,
Mutation,
Destructive,
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum RequestSemantics {
Safe,
Idempotent,
NonIdempotent,
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum RetryEligibility {
Never,
ExplicitPolicy,
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum CostIntent {
NoKnownCost,
MayIncurCost,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum OperationMetadataError {
ReadOnlyMustBeSafe,
StateChangeCannotBeSafe,
NonIdempotentRetry,
}
impl_static_error!(OperationMetadataError,
Self::ReadOnlyMustBeSafe => "read-only operation must use safe semantics",
Self::StateChangeCannotBeSafe => "state-changing operation cannot use safe semantics",
Self::NonIdempotentRetry => "non-idempotent operation cannot be retry eligible",
);
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct OperationMetadata {
impact: OperationImpact,
semantics: RequestSemantics,
retry: RetryEligibility,
cost: CostIntent,
}
impl OperationMetadata {
pub const fn new(
impact: OperationImpact,
semantics: RequestSemantics,
retry: RetryEligibility,
cost: CostIntent,
) -> Result<Self, OperationMetadataError> {
match (impact, semantics, retry) {
(OperationImpact::ReadOnly, semantics, _)
if !matches!(semantics, RequestSemantics::Safe) =>
{
return Err(OperationMetadataError::ReadOnlyMustBeSafe);
}
(
OperationImpact::Mutation | OperationImpact::Destructive,
RequestSemantics::Safe,
_,
) => {
return Err(OperationMetadataError::StateChangeCannotBeSafe);
}
(_, RequestSemantics::NonIdempotent, RetryEligibility::ExplicitPolicy) => {
return Err(OperationMetadataError::NonIdempotentRetry);
}
_ => {}
}
Ok(Self {
impact,
semantics,
retry,
cost,
})
}
#[must_use]
pub const fn impact(self) -> OperationImpact {
self.impact
}
#[must_use]
pub const fn semantics(self) -> RequestSemantics {
self.semantics
}
#[must_use]
pub const fn retry_eligibility(self) -> RetryEligibility {
self.retry
}
#[must_use]
pub const fn cost_intent(self) -> CostIntent {
self.cost
}
}