ip_network/
postgres_support.rs1use std::error::Error;
2use postgres::types::{FromSql, IsNull, ToSql, Type, accepts, to_sql_checked};
3use crate::{IpNetwork, Ipv4Network, Ipv6Network};
4use crate::postgres_common;
5use postgres::types::private::BytesMut;
6
7type PostgresResult<T> = Result<T, Box<dyn Error + Sync + Send>>;
8
9impl<'a> FromSql<'a> for Ipv4Network {
10 fn from_sql(_: &Type, raw: &'a [u8]) -> PostgresResult<Ipv4Network> {
11 postgres_common::from_sql_ipv4_network(raw)
12 }
13
14 accepts!(CIDR);
15}
16
17impl<'a> FromSql<'a> for Ipv6Network {
18 fn from_sql(_: &Type, raw: &'a [u8]) -> PostgresResult<Ipv6Network> {
19 postgres_common::from_sql_ipv6_network(raw)
20 }
21
22 accepts!(CIDR);
23}
24
25impl<'a> FromSql<'a> for IpNetwork {
26 fn from_sql(t: &Type, raw: &'a [u8]) -> PostgresResult<IpNetwork> {
27 match raw[0] {
28 postgres_common::IPV4_TYPE => Ok(IpNetwork::V4(Ipv4Network::from_sql(t, raw)?)),
29 postgres_common::IPV6_TYPE => Ok(IpNetwork::V6(Ipv6Network::from_sql(t, raw)?)),
30 _ => Err("CIDR is not IP version 4 or 6".into()),
31 }
32 }
33
34 accepts!(CIDR);
35}
36
37impl ToSql for Ipv4Network {
38 fn to_sql(&self, _ty: &Type, w: &mut BytesMut) -> PostgresResult<IsNull> {
39 let bytes = postgres_common::to_sql_ipv4_network(self);
40 w.extend_from_slice(&bytes);
41
42 Ok(IsNull::No)
43 }
44
45 accepts!(CIDR);
46 to_sql_checked!();
47}
48
49impl ToSql for Ipv6Network {
50 fn to_sql(&self, _ty: &Type, w: &mut BytesMut) -> PostgresResult<IsNull> {
51 let bytes = postgres_common::to_sql_ipv6_network(self);
52 w.extend_from_slice(&bytes);
53
54 Ok(IsNull::No)
55 }
56
57 accepts!(CIDR);
58 to_sql_checked!();
59}
60
61impl ToSql for IpNetwork {
62 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> PostgresResult<IsNull> {
63 match *self {
64 IpNetwork::V4(ref network) => network.to_sql(ty, w),
65 IpNetwork::V6(ref network) => network.to_sql(ty, w),
66 }
67 }
68
69 accepts!(CIDR);
70 to_sql_checked!();
71}
72
73#[cfg(test)]
74mod tests {
75 use std::net::{Ipv4Addr, Ipv6Addr};
76 use postgres::types::{FromSql, ToSql};
77 use postgres::types::Type;
78 use crate::{IpNetwork, Ipv4Network, Ipv6Network};
79 use postgres::types::private::BytesMut;
80
81 fn return_test_ipv4_network() -> Ipv4Network {
82 Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 0), 16).unwrap()
83 }
84
85 fn return_test_ipv6_network() -> Ipv6Network {
86 Ipv6Network::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0), 32).unwrap()
87 }
88
89 #[test]
90 fn ivp4_to_sql() {
91 let ip_network = return_test_ipv4_network();
92 let mut output = BytesMut::new();
93 assert!(ip_network.to_sql(&Type::CIDR, &mut output).is_ok());
94 assert_eq!(2, output[0]);
95 assert_eq!(16, output[1]);
96 assert_eq!(1, output[2]);
97 assert_eq!(4, output[3]);
98 assert_eq!(192, output[4]);
99 assert_eq!(168, output[5]);
100 assert_eq!(0, output[6]);
101 assert_eq!(0, output[7]);
102 }
103
104 #[test]
105 fn ivp4_both_direction() {
106 let ip_network = return_test_ipv4_network();
107 let mut output = BytesMut::new();
108
109 assert!(ip_network.to_sql(&Type::CIDR, &mut output).is_ok());
110
111 let result = Ipv4Network::from_sql(&Type::CIDR, &output);
112 assert!(result.is_ok());
113
114 let ip_network_converted = result.unwrap();
115 assert_eq!(ip_network, ip_network_converted);
116 }
117
118 #[test]
119 fn ivp6_to_sql() {
120 let ip_network = return_test_ipv6_network();
121 let mut output = BytesMut::new();
122 assert!(ip_network.to_sql(&Type::CIDR, &mut output).is_ok());
123 assert_eq!(3, output[0]);
124 assert_eq!(32, output[1]);
125 assert_eq!(1, output[2]);
126 assert_eq!(16, output[3]);
127 assert_eq!(0x20, output[4]);
128 assert_eq!(0x01, output[5]);
129 assert_eq!(0x0d, output[6]);
130 assert_eq!(0xb8, output[7]);
131 for i in 8..20 {
132 assert_eq!(0, output[i]);
133 }
134 }
135
136 #[test]
137 fn ivp6_both_direction() {
138 let ip_network = return_test_ipv6_network();
139 let mut output = BytesMut::new();
140
141 assert!(ip_network.to_sql(&Type::CIDR, &mut output).is_ok());
142
143 let result = Ipv6Network::from_sql(&Type::CIDR, &output);
144 assert!(result.is_ok());
145
146 let ip_network_converted = result.unwrap();
147 assert_eq!(ip_network, ip_network_converted);
148 }
149
150 #[test]
151 fn ipnetwork_to_sql_v4() {
152 let ip_network = IpNetwork::V4(return_test_ipv4_network());
153 let mut output = BytesMut::new();
154 assert!(ip_network.to_sql(&Type::CIDR, &mut output).is_ok());
155 }
156
157 #[test]
158 fn ipnetwork_to_sql_v6() {
159 let ip_network = IpNetwork::V6(return_test_ipv6_network());
160 let mut output = BytesMut::new();
161 assert!(ip_network.to_sql(&Type::CIDR, &mut output).is_ok());
162 }
163}