use std::net::IpAddr; use serde_derive::{Deserialize, Serialize}; type Version = u8; const CONF_VERSION: Version = 0; #[derive(Default, Debug, Serialize, Deserialize)] pub struct Configuration { /// The version of the configuration. This is a MAJOR configuration only; /// it should be incremented whenever breaking changes to the configuration /// are made. pub version: Version, /// The IP to listen on for incoming user datagrams (excluding port). pub ip: String, /// The port to listen on for incoming user datagrams. pub port: u16, } #[derive(Debug)] pub enum ConfigurationError { InvalidIp, IncompatibleVersion(Version), } impl std::fmt::Display for ConfigurationError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ConfigurationError::IncompatibleVersion(v) => write!(f, "Expected configuration version {} but got version {}.", CONF_VERSION, v), ConfigurationError::InvalidIp => write!(f, "Invalid IP."), } } } impl std::error::Error for ConfigurationError {} impl Configuration { pub fn check(&self) -> Result<(), ConfigurationError> { self.check_version()?; self.check_ip()?; // No need to check the port; any u16 is a valid port. Ok(()) } fn check_version(&self) -> Result<(), ConfigurationError> { if self.version != CONF_VERSION { Err(ConfigurationError::IncompatibleVersion(self.version)) } else { Ok(()) } } fn check_ip(&self) -> Result<(), ConfigurationError> { if self.ip.parse::().is_err() { Err(ConfigurationError::InvalidIp) } else { Ok(()) } } }