use core::fmt::{Debug, Display};
pub trait Routine {
type Strategy;
type Blueprint;
}
pub enum BlueprintStrategy<R: Routine> {
Forced(R::Blueprint),
Inferred(R::Strategy),
}
impl<R: Routine<Strategy: Clone + Default, Blueprint: Clone>> BlueprintStrategy<R> {
pub fn maybe_forced_default(blueprint: &Option<R::Blueprint>) -> Self {
blueprint
.as_ref()
.map(|blueprint| Self::Forced(blueprint.clone()))
.unwrap_or_default()
}
pub fn maybe_forced_or(blueprint: &Option<R::Blueprint>, strategy: &R::Strategy) -> Self {
blueprint
.as_ref()
.map(|blueprint| Self::Forced(blueprint.clone()))
.unwrap_or_else(|| Self::Inferred(strategy.clone()))
}
}
impl<R: Routine<Strategy: Default>> Default for BlueprintStrategy<R> {
fn default() -> Self {
Self::Inferred(R::Strategy::default())
}
}
impl<R: Routine<Strategy: Clone, Blueprint: Clone>> Clone for BlueprintStrategy<R> {
fn clone(&self) -> Self {
match self {
Self::Forced(blueprint) => Self::Forced(blueprint.clone()),
Self::Inferred(strategy) => Self::Inferred(strategy.clone()),
}
}
}
impl<R: Routine<Strategy: Debug, Blueprint: Debug>> Debug for BlueprintStrategy<R> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Forced(blueprint) => f.debug_tuple("Forced").field(blueprint).finish(),
Self::Inferred(strategy) => f.debug_tuple("Inferred").field(strategy).finish(),
}
}
}
impl<R: Routine<Strategy: Display>> Display for BlueprintStrategy<R> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Forced(_) => f.write_str("_forced"),
Self::Inferred(strategy) => write!(f, "{strategy}"),
}
}
}