use std::fmt;
use lgwks_std::json::Serialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(crate = "lgwks_std::json::serde")]
pub struct Architecture {
flows: &'static [FlowShape],
}
impl Architecture {
#[doc(hidden)]
#[must_use]
pub const fn new(flows: &'static [FlowShape]) -> Self {
Self { flows }
}
#[must_use]
pub const fn flows(&self) -> &'static [FlowShape] {
self.flows
}
#[must_use]
pub fn flow(&self, name: &str) -> Option<&'static FlowShape> {
self.flows.iter().find(|flow| flow.name == name)
}
pub fn to_json(&self) -> Result<String, lgwks_std::json::Error> {
lgwks_std::json::to_string(self)
}
}
impl fmt::Display for Architecture {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
for flow in self.flows {
writeln!(formatter, "flow {} @{}", flow.signature, flow.line)?;
render_steps(formatter, flow.steps, 1)?;
}
Ok(())
}
}
fn render_steps(
formatter: &mut fmt::Formatter<'_>,
steps: &[StepShape],
depth: usize,
) -> fmt::Result {
for step in steps {
for _ in 0..depth {
formatter.write_str(" ")?;
}
writeln!(formatter, "{} @{}", step.detail, step.line)?;
render_steps(formatter, step.steps, depth.saturating_add(1))?;
}
Ok(())
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(crate = "lgwks_std::json::serde")]
pub struct FlowShape {
name: &'static str,
signature: &'static str,
line: u32,
steps: &'static [StepShape],
}
impl FlowShape {
#[doc(hidden)]
#[must_use]
pub const fn new(
name: &'static str,
signature: &'static str,
line: u32,
steps: &'static [StepShape],
) -> Self {
Self {
name,
signature,
line,
steps,
}
}
#[must_use]
pub const fn name(&self) -> &'static str {
self.name
}
#[must_use]
pub const fn signature(&self) -> &'static str {
self.signature
}
#[must_use]
pub const fn steps(&self) -> &'static [StepShape] {
self.steps
}
#[must_use]
pub fn runs(&self) -> Vec<&'static str> {
runs_in(self.steps)
}
}
fn runs_in(steps: &'static [StepShape]) -> Vec<&'static str> {
steps
.iter()
.flat_map(|step| {
let own = (step.kind == StepKind::Run).then_some(step.subject);
own.into_iter().chain(runs_in(step.steps))
})
.collect()
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(crate = "lgwks_std::json::serde")]
pub struct StepShape {
kind: StepKind,
subject: &'static str,
detail: &'static str,
line: u32,
steps: &'static [StepShape],
}
impl StepShape {
#[doc(hidden)]
#[must_use]
pub const fn new(
kind: StepKind,
subject: &'static str,
detail: &'static str,
line: u32,
steps: &'static [StepShape],
) -> Self {
Self {
kind,
subject,
detail,
line,
steps,
}
}
#[must_use]
pub const fn kind(&self) -> StepKind {
self.kind
}
#[must_use]
pub const fn subject(&self) -> &'static str {
self.subject
}
#[must_use]
pub const fn detail(&self) -> &'static str {
self.detail
}
#[must_use]
pub const fn line(&self) -> u32 {
self.line
}
#[must_use]
pub const fn steps(&self) -> &'static [StepShape] {
self.steps
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(crate = "lgwks_std::json::serde")]
#[non_exhaustive]
pub enum StepKind {
Each,
Within,
Retry,
Together,
Step,
For,
Run,
If,
Else,
Fail,
GiveBack,
}