use std::fmt;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Id(u64);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Status {
pub phase: Phase,
pub outcome: Option<Outcome>,
pub cancellation_requested: bool,
pub attempt: u32,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Phase {
Queued,
Initializing,
Running,
RetryWaiting,
Restarting,
Stopping,
CleaningUp,
Stopped,
Settled,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Outcome {
Succeeded,
Failed,
Cancelled,
TimedOut,
Unavailable,
}
#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
#[error("unknown operation instance {kind} `{value}`")]
pub struct ParseError {
kind: &'static str,
value: String,
}
impl Id {
pub const fn new(value: u64) -> Self {
Self(value)
}
pub const fn value(self) -> u64 {
self.0
}
}
impl fmt::Display for Id {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(formatter)
}
}
impl Status {
pub fn is_settled(&self) -> bool {
matches!(self.phase, Phase::Settled | Phase::Stopped)
}
}
impl Phase {
pub const fn as_str(self) -> &'static str {
match self {
Self::Queued => "queued",
Self::Initializing => "initializing",
Self::Running => "running",
Self::RetryWaiting => "retry_waiting",
Self::Restarting => "restarting",
Self::Stopping => "stopping",
Self::CleaningUp => "cleaning_up",
Self::Stopped => "stopped",
Self::Settled => "settled",
}
}
}
impl FromStr for Phase {
type Err = ParseError;
fn from_str(value: &str) -> Result<Self, ParseError> {
let phase = match value {
"queued" => Self::Queued,
"initializing" => Self::Initializing,
"running" => Self::Running,
"retry_waiting" => Self::RetryWaiting,
"restarting" => Self::Restarting,
"stopping" => Self::Stopping,
"cleaning_up" => Self::CleaningUp,
"stopped" => Self::Stopped,
"settled" => Self::Settled,
_ => {
return Err(ParseError { kind: "phase", value: value.to_owned() });
}
};
Ok(phase)
}
}
impl Outcome {
pub const fn as_str(self) -> &'static str {
match self {
Self::Succeeded => "succeeded",
Self::Failed => "failed",
Self::Cancelled => "cancelled",
Self::TimedOut => "timed_out",
Self::Unavailable => "unavailable",
}
}
}
impl FromStr for Outcome {
type Err = ParseError;
fn from_str(value: &str) -> Result<Self, ParseError> {
let outcome = match value {
"succeeded" => Self::Succeeded,
"failed" => Self::Failed,
"cancelled" => Self::Cancelled,
"timed_out" => Self::TimedOut,
"unavailable" => Self::Unavailable,
_ => {
return Err(ParseError { kind: "outcome", value: value.to_owned() });
}
};
Ok(outcome)
}
}