diff options
Diffstat (limited to 'crates/common/tedge_config/src/models/ipaddress.rs')
-rw-r--r-- | crates/common/tedge_config/src/models/ipaddress.rs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/crates/common/tedge_config/src/models/ipaddress.rs b/crates/common/tedge_config/src/models/ipaddress.rs new file mode 100644 index 00000000..3c0edc4a --- /dev/null +++ b/crates/common/tedge_config/src/models/ipaddress.rs @@ -0,0 +1,80 @@ +use serde::{Deserialize, Serialize}; +use std::convert::{TryFrom, TryInto}; +use std::fmt; +use std::net::IpAddr; + +#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub struct IpAddress(pub IpAddr); + +#[derive(thiserror::Error, Debug)] +#[error("Invalid ip address: '{input}'.")] +pub struct InvalidIpAddress { + input: String, +} + +impl fmt::Display for IpAddress { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + +impl Default for IpAddress { + fn default() -> Self { + IpAddress(IpAddr::V4(Ipv4Addr::LOCALHOST)) + } +} + +impl TryFrom<String> for IpAddress { + type Error = InvalidIpAddress; + + fn try_from(input: String) -> Result<Self, Self::Error> { + input + .parse::<IpAddr>() + .map_err(|_| InvalidIpAddress { input }) + .map(IpAddress) + } +} + +impl TryInto<String> for IpAddress { + type Error = std::convert::Infallible; + + fn try_into(self) -> Result<String, Self::Error> { + Ok(self.to_string()) + } +} + +impl From<IpAddress> for IpAddr { + fn from(val: IpAddress) -> Self { + val.0 + } +} + +#[cfg(test)] +use assert_matches::*; +use std::net::Ipv4Addr; +use std::net::Ipv6Addr; + +#[test] +fn conversion_from_valid_ipv4_succeeds() { + let _loh: IpAddress = IpAddress::try_from("127.0.0.1".to_string()).unwrap(); + assert_matches!(Ipv4Addr::LOCALHOST, _loh); +} + +#[test] +fn conversion_from_valid_ipv6_succeeds() { + let _loh: IpAddress = IpAddress::try_from("::1".to_string()).unwrap(); + assert_matches!(Ipv6Addr::LOCALHOST, _loh); +} + +#[test] +fn conversion_from_longer_integer_fails() { + assert_matches!( + IpAddress::try_from("66000".to_string()), + Err(InvalidIpAddress { .. }) + ); +} + +#[test] +fn conversion_from_ip_to_string() { + assert_matches!(TryInto::<String>::try_into(IpAddress(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)))), Ok(ip_str) if ip_str == "::1"); +} |