Skip to main content

idkollen_client/models/
ip_address.rs

1use fmt::Display;
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::fmt;
4use std::net::IpAddr;
5use thiserror::Error;
6
7/// A validated IPv4 or IPv6 address.
8///
9/// Constructed via [`IpAddress::parse`]; serializes/deserializes as a plain JSON string.
10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct IpAddress(IpAddr);
12
13#[derive(Debug, Error)]
14#[error("invalid IP address: {0}")]
15pub struct IpAddressError(#[from] std::net::AddrParseError);
16
17impl IpAddress {
18    #[inline]
19    pub fn parse(s: &str) -> Result<Self, IpAddressError> {
20        Ok(Self(s.parse::<IpAddr>()?))
21    }
22
23    #[inline]
24    #[must_use]
25    pub fn inner(&self) -> IpAddr {
26        self.0
27    }
28}
29
30impl From<IpAddr> for IpAddress {
31    #[inline]
32    fn from(addr: IpAddr) -> Self {
33        Self(addr)
34    }
35}
36
37impl From<IpAddress> for IpAddr {
38    #[inline]
39    fn from(a: IpAddress) -> IpAddr {
40        a.0
41    }
42}
43
44impl Display for IpAddress {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        Display::fmt(&self.0, f)
47    }
48}
49
50impl Serialize for IpAddress {
51    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
52        // IpAddr serializes as a string in JSON
53        self.0.serialize(s)
54    }
55}
56
57impl<'de> Deserialize<'de> for IpAddress {
58    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
59        IpAddr::deserialize(d).map(Self)
60    }
61}