a3s_runtime/contract/
network.rs1use serde::{Deserialize, Serialize};
2use std::collections::BTreeSet;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
5#[serde(rename_all = "snake_case")]
6pub enum NetworkMode {
7 None,
8 Outbound,
9 Service,
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
13#[serde(rename_all = "snake_case")]
14pub enum TransportProtocol {
15 Tcp,
16 Udp,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(deny_unknown_fields)]
21pub struct RuntimePort {
22 pub name: String,
23 pub container_port: u16,
24 pub protocol: TransportProtocol,
25}
26
27impl RuntimePort {
28 pub(crate) fn validate(&self) -> Result<(), String> {
29 super::validate_name("port name", &self.name)?;
30 if self.container_port == 0 {
31 return Err("container_port must be positive".into());
32 }
33 Ok(())
34 }
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
38#[serde(deny_unknown_fields)]
39pub struct RuntimeNetworkSpec {
40 pub mode: NetworkMode,
41 pub ports: Vec<RuntimePort>,
42}
43
44impl RuntimeNetworkSpec {
45 pub(crate) fn validate(&self) -> Result<(), String> {
46 if self.ports.len() > 64 {
47 return Err("Runtime unit declares more than 64 ports".into());
48 }
49 if self.mode != NetworkMode::Service && !self.ports.is_empty() {
50 return Err("declared ports require service network mode".into());
51 }
52 let mut names = BTreeSet::new();
53 let mut sockets = BTreeSet::new();
54 for port in &self.ports {
55 port.validate()?;
56 if !names.insert(&port.name) {
57 return Err(format!("duplicate Runtime port name {:?}", port.name));
58 }
59 if !sockets.insert((port.container_port, port.protocol)) {
60 return Err(format!(
61 "duplicate Runtime port socket {}/{}",
62 port.container_port,
63 match port.protocol {
64 TransportProtocol::Tcp => "tcp",
65 TransportProtocol::Udp => "udp",
66 }
67 ));
68 }
69 }
70 Ok(())
71 }
72
73 pub(crate) fn has_port(&self, name: &str) -> bool {
74 self.ports.iter().any(|port| port.name == name)
75 }
76}