#[cfg(feature = "alloc")]
use alloc::string::String;
#[derive(
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
)]
#[serde(untagged)]
pub enum Vocabulary<T> {
Known(T),
Unknown(String),
}
impl<T> Vocabulary<T> {
#[must_use]
pub const fn is_known(&self) -> bool {
matches!(self, Self::Known(_))
}
#[must_use]
pub const fn as_known(&self) -> Option<&T> {
match self {
Self::Known(value) => Some(value),
Self::Unknown(_) => None,
}
}
#[must_use]
pub fn unrecognized(&self) -> Option<&str> {
match self {
Self::Unknown(value) => Some(value),
Self::Known(_) => None,
}
}
}
impl<T: Copy> Vocabulary<T> {
#[must_use]
pub const fn known(&self) -> Option<T> {
match self {
Self::Known(value) => Some(*value),
Self::Unknown(_) => None,
}
}
}
impl<T: Copy + PartialEq> Vocabulary<T> {
#[must_use]
pub fn is(&self, value: T) -> bool {
self.known() == Some(value)
}
}
impl<T: AsRef<str>> Vocabulary<T> {
#[must_use]
pub fn as_str(&self) -> &str {
match self {
Self::Known(value) => value.as_ref(),
Self::Unknown(value) => value.as_str(),
}
}
}
impl<T: serde::de::DeserializeOwned> Vocabulary<T> {
pub fn parse(value: impl Into<String>) -> Self {
use serde::de::IntoDeserializer as _;
let value = value.into();
let deserializer: serde::de::value::StrDeserializer<'_, serde::de::value::Error> =
value.as_str().into_deserializer();
match T::deserialize(deserializer) {
Ok(known) => Self::Known(known),
Err(_) => Self::Unknown(value),
}
}
}
impl<T: Default> Default for Vocabulary<T> {
fn default() -> Self {
Self::Known(T::default())
}
}
impl<T> From<T> for Vocabulary<T> {
fn from(value: T) -> Self {
Self::Known(value)
}
}
impl<T: AsRef<str>> core::fmt::Display for Vocabulary<T> {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter.write_str(self.as_str())
}
}
#[derive(
Clone,
Copy,
Debug,
Default,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
serde::Deserialize,
serde::Serialize,
strum::AsRefStr,
strum::Display,
strum::EnumCount,
strum::EnumIs,
strum::EnumString,
strum::IntoStaticStr,
strum::VariantArray,
strum::VariantNames,
)]
#[serde(rename_all = "snake_case")]
#[strum(ascii_case_insensitive, serialize_all = "snake_case")]
pub enum RunStatus {
#[default]
Planted,
Planned,
Executing,
Closing,
Closed,
}
impl RunStatus {
#[must_use]
pub const fn is_guarded_transition(self) -> bool {
matches!(self, Self::Planned | Self::Executing)
}
#[must_use]
pub const fn is_open(self) -> bool {
!matches!(self, Self::Closed)
}
#[must_use]
pub const fn admits_dispatch(self) -> bool {
matches!(self, Self::Planted | Self::Executing | Self::Closing)
}
}
#[derive(
Clone,
Copy,
Debug,
Default,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
serde::Deserialize,
serde::Serialize,
strum::AsRefStr,
strum::Display,
strum::EnumCount,
strum::EnumIs,
strum::EnumString,
strum::IntoStaticStr,
strum::VariantArray,
strum::VariantNames,
)]
#[serde(rename_all = "kebab-case")]
#[strum(ascii_case_insensitive, serialize_all = "kebab-case")]
pub enum RunKind {
#[default]
Sprint,
PatchArc,
}
#[derive(
Clone,
Copy,
Debug,
Default,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
serde::Deserialize,
serde::Serialize,
strum::AsRefStr,
strum::Display,
strum::EnumCount,
strum::EnumIs,
strum::EnumString,
strum::IntoStaticStr,
strum::VariantArray,
strum::VariantNames,
)]
#[serde(rename_all = "kebab-case")]
#[strum(ascii_case_insensitive, serialize_all = "kebab-case")]
pub enum LaneStatus {
#[default]
Pending,
InProgress,
Complete,
Error,
}