Skip to main content

powerio_pkg/
model.rs

1//! The model kind and the single typed IR payload.
2//!
3//! The two IR families never merge. [`ModelKind`] is stored explicitly on the
4//! package; [`ModelPayload`] is the tagged wrapper around exactly one payload.
5//! The payload's `kind()` must agree with the package's `model_kind` (the
6//! package asserts this), but the authoritative kind is the standalone field, so
7//! a reader never infers the kind from which payload field is present.
8
9use serde::{Deserialize, Serialize};
10
11use powerio::BalancedNetwork;
12use powerio_dist::MulticonductorNetwork;
13
14/// Which concrete static-grid IR family the payload is.
15#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
16#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
17#[serde(rename_all = "snake_case")]
18#[non_exhaustive]
19pub enum ModelKind {
20    /// Scalar positive-sequence transmission model ([`powerio::BalancedNetwork`]).
21    Balanced,
22    /// Wire-coordinate distribution model ([`powerio_dist::MulticonductorNetwork`]).
23    Multiconductor,
24}
25
26/// The one IR payload a package carries, tagged by `kind` in JSON so the payload
27/// is self-describing in addition to the top-level `model_kind`.
28///
29/// The payload is the serde snapshot of the PowerIO Rust IR
30/// ([`powerio::Network`] / [`powerio_dist::DistNetwork`]); changes to it are
31/// document changes under the package `schema_version`. See
32/// `docs/src/pio-json-schema.md`.
33#[derive(Clone, Debug, Serialize, Deserialize)]
34#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
35#[serde(tag = "kind", rename_all = "snake_case")]
36pub enum ModelPayload {
37    Balanced {
38        balanced_network: Box<BalancedNetwork>,
39    },
40    Multiconductor {
41        multiconductor_network: Box<MulticonductorNetwork>,
42    },
43}
44
45impl ModelPayload {
46    pub fn balanced(net: BalancedNetwork) -> Self {
47        Self::Balanced {
48            balanced_network: Box::new(net),
49        }
50    }
51
52    pub fn multiconductor(net: MulticonductorNetwork) -> Self {
53        Self::Multiconductor {
54            multiconductor_network: Box::new(net),
55        }
56    }
57
58    pub fn kind(&self) -> ModelKind {
59        match self {
60            ModelPayload::Balanced { .. } => ModelKind::Balanced,
61            ModelPayload::Multiconductor { .. } => ModelKind::Multiconductor,
62        }
63    }
64
65    /// The balanced payload, if this is one.
66    pub fn as_balanced(&self) -> Option<&BalancedNetwork> {
67        match self {
68            ModelPayload::Balanced { balanced_network } => Some(balanced_network),
69            ModelPayload::Multiconductor { .. } => None,
70        }
71    }
72
73    /// The multiconductor payload, if this is one.
74    pub fn as_multiconductor(&self) -> Option<&MulticonductorNetwork> {
75        match self {
76            ModelPayload::Multiconductor {
77                multiconductor_network,
78            } => Some(multiconductor_network),
79            ModelPayload::Balanced { .. } => None,
80        }
81    }
82}