mod packets;
mod rails;
mod routing;
use super::RailTransmission;
use crate::{Error, Result};
pub use packets::{FabricConstraints, PacketRequest, PacketScheduler, RoutePolicy};
pub use rails::{RailPacketScheduler, RailRoute, WavelengthConstraints};
pub(crate) use routing::Reservation;
pub use routing::{Route, RouteHop};
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct NodeId(pub usize);
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum NodeKind {
Source,
Switch,
Fusion,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct FabricNode {
pub kind: NodeKind,
pub storage: RailTransmission,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct FabricLink {
pub from: NodeId,
pub to: NodeId,
pub ticks: u64,
pub transmission: RailTransmission,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct FabricData {
version: u32,
nodes: Vec<FabricNode>,
links: Vec<FabricLink>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(try_from = "FabricData", into = "FabricData")]
pub struct Fabric(FabricData);
impl Fabric {
pub fn new(nodes: Vec<FabricNode>, links: Vec<FabricLink>) -> Result<Self> {
if nodes.is_empty() || nodes.len() > 4096 || links.len() > 16384 {
return Err(Error::InvalidValue(
"fabric exceeds node/link limits or is empty".into(),
));
}
for link in &links {
if link.from.0 >= nodes.len()
|| link.to.0 >= nodes.len()
|| link.from == link.to
|| link.ticks == 0
{
return Err(Error::InvalidValue(
"invalid fabric link endpoints or duration".into(),
));
}
}
Ok(Self(FabricData {
version: 1,
nodes,
links,
}))
}
pub fn nodes(&self) -> &[FabricNode] {
&self.0.nodes
}
pub fn links(&self) -> &[FabricLink] {
&self.0.links
}
pub fn node(&self, node: NodeId) -> Result<&FabricNode> {
self.0
.nodes
.get(node.0)
.ok_or_else(|| Error::InvalidValue("fabric node out of range".into()))
}
}
impl TryFrom<FabricData> for Fabric {
type Error = Error;
fn try_from(v: FabricData) -> Result<Self> {
if v.version != 1 {
return Err(Error::Unsupported("unknown fabric schema version".into()));
}
Self::new(v.nodes, v.links)
}
}
impl From<Fabric> for FabricData {
fn from(v: Fabric) -> Self {
v.0
}
}