postgres_types_extra/
pg_cidr.rs

1use bytes::BytesMut;
2use cidr::{IpCidr, IpInet};
3use postgres_protocol::types;
4use postgres_types::{FromSql, IsNull, ToSql, Type, accepts, to_sql_checked};
5use std::{error::Error, fmt};
6
7#[derive(Debug, Clone)]
8pub struct PgCidr(IpCidr);
9
10#[derive(Debug, Clone)]
11
12pub struct PgInet(IpInet);
13
14impl fmt::Display for PgCidr {
15    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16        let w = format!("{}", self.0).to_ascii_lowercase();
17        write!(f, "{w}")
18    }
19}
20
21impl FromSql<'_> for PgCidr {
22    fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
23        let inet = types::inet_from_sql(raw)?;
24        Ok(PgCidr(IpCidr::new(inet.addr(), inet.netmask())?))
25    }
26
27    accepts!(CIDR);
28}
29
30impl ToSql for PgCidr {
31    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
32        types::inet_to_sql(self.0.first_address(), self.0.network_length(), w);
33        Ok(IsNull::No)
34    }
35
36    accepts!(CIDR);
37    to_sql_checked!();
38}
39
40impl fmt::Display for PgInet {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        let w = format!("{}", self.0).to_ascii_lowercase();
43        write!(f, "{w}")
44    }
45}
46impl FromSql<'_> for PgInet {
47    fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
48        let inet = types::inet_from_sql(raw)?;
49        Ok(PgInet(IpInet::new(inet.addr(), inet.netmask())?))
50    }
51
52    accepts!(INET);
53}
54
55impl ToSql for PgInet {
56    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
57        types::inet_to_sql(self.0.address(), self.0.network_length(), w);
58        Ok(IsNull::No)
59    }
60
61    accepts!(INET);
62    to_sql_checked!();
63
64    fn encode_format(&self, _ty: &Type) -> postgres_types::Format {
65        postgres_types::Format::Binary
66    }
67}