use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Role {
Client,
Server,
}
impl fmt::Display for Role {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Role::Client => write!(f, "client"),
Role::Server => write!(f, "server"),
}
}
}
impl std::str::FromStr for Role {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"client" => Ok(Role::Client),
"server" => Ok(Role::Server),
_ => Err(anyhow::anyhow!("Invalid role: '{}'. Use 'client' or 'server'", s)),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Protocol {
Tcp,
Udp,
}
impl fmt::Display for Protocol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Protocol::Tcp => write!(f, "tcp"),
Protocol::Udp => write!(f, "udp"),
}
}
}
impl std::str::FromStr for Protocol {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"tcp" => Ok(Protocol::Tcp),
"udp" => Ok(Protocol::Udp),
_ => Err(anyhow::anyhow!("Invalid protocol: '{}'. Use 'tcp' or 'udp'", s)),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PortMapping {
pub id: String,
pub local_port: u16,
pub remote_port: u16,
pub protocol: Protocol,
#[serde(default)]
pub description: String,
#[serde(default = "default_true")]
pub enabled: bool,
}
fn default_true() -> bool {
true
}