Skip to content

Commit 3ac26d4

Browse files
committed
Add inet support
It's lossy ATM, since IpAddr doesn't store the netmask. Closes rust-postgres#88
1 parent db198a5 commit 3ac26d4

4 files changed

Lines changed: 77 additions & 1 deletion

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ types. The driver currently supports the following conversions:
204204
<td>serialize::json::Json</td>
205205
<td>JSON</td>
206206
</tr>
207+
<tr>
208+
<td>IpAddr</td>
209+
<td>INET</td>
210+
</tr>
207211
<tr>
208212
<td>time::Timespec</td>
209213
<td>TIMESTAMP, TIMESTAMP WITH TIME ZONE</td>

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ pub mod types;
9898

9999
const CANARY: u32 = 0xdeadbeef;
100100

101-
/// A typedef of the result returned by many methods.
101+
/// A type alias of the result returned by many methods.
102102
pub type Result<T> = result::Result<T, Error>;
103103

104104
/// Specifies the target server to connect to.

src/types/mod.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use serialize::json;
33
use std::collections::HashMap;
44
use std::io::{ByRefReader, BufReader};
5+
use std::io::net::ip::IpAddr;
56

67
use self::Type::*;
78
use Result;
@@ -325,6 +326,7 @@ const JSONOID: Oid = 114;
325326
const JSONARRAYOID: Oid = 199;
326327
const FLOAT4OID: Oid = 700;
327328
const FLOAT8OID: Oid = 701;
329+
const INETOID: Oid = 869;
328330
const BOOLARRAYOID: Oid = 1000;
329331
const BYTEAARRAYOID: Oid = 1001;
330332
const CHARARRAYOID: Oid = 1002;
@@ -433,6 +435,8 @@ make_postgres_type!(
433435
FLOAT4OID => Float4,
434436
#[doc="FLOAT8/DOUBLE PRECISION"]
435437
FLOAT8OID => Float8,
438+
#[doc="INET"]
439+
INETOID => Inet,
436440
#[doc="BOOL[]"]
437441
BOOLARRAYOID => BoolArray member Bool,
438442
#[doc="BYTEA[]"]
@@ -538,6 +542,29 @@ impl RawFromSql for json::Json {
538542
}
539543
}
540544

545+
impl RawFromSql for IpAddr {
546+
fn raw_from_sql<R: Reader>(raw: &mut R) -> Result<IpAddr> {
547+
let family = try!(raw.read_u8());
548+
let _bits = try!(raw.read_u8());
549+
let _is_cidr = try!(raw.read_u8());
550+
let nb = try!(raw.read_u8());
551+
let mut buf = &*try!(raw.read_exact(nb as uint));
552+
553+
match family {
554+
2 if nb == 4 => Ok(IpAddr::Ipv4Addr(buf[0], buf[1], buf[2], buf[3])),
555+
3 if nb == 16 => Ok(IpAddr::Ipv6Addr(try!(buf.read_be_u16()),
556+
try!(buf.read_be_u16()),
557+
try!(buf.read_be_u16()),
558+
try!(buf.read_be_u16()),
559+
try!(buf.read_be_u16()),
560+
try!(buf.read_be_u16()),
561+
try!(buf.read_be_u16()),
562+
try!(buf.read_be_u16()))),
563+
_ => Err(Error::BadData),
564+
}
565+
}
566+
}
567+
541568
from_raw_from_impl!(Bool, bool)
542569
from_raw_from_impl!(ByteA, Vec<u8>)
543570
from_raw_from_impl!(Varchar | Text | CharN | Name, String)
@@ -548,6 +575,7 @@ from_raw_from_impl!(Int8, i64)
548575
from_raw_from_impl!(Float4, f32)
549576
from_raw_from_impl!(Float8, f64)
550577
from_raw_from_impl!(Json, json::Json)
578+
from_raw_from_impl!(Inet, IpAddr)
551579

552580
from_raw_from_impl!(Int4Range, Range<i32>)
553581
from_raw_from_impl!(Int8Range, Range<i64>)
@@ -668,10 +696,44 @@ impl RawToSql for json::Json {
668696
}
669697
}
670698

699+
impl RawToSql for IpAddr {
700+
fn raw_to_sql<W: Writer>(&self, raw: &mut W) -> Result<()> {
701+
match *self {
702+
IpAddr::Ipv4Addr(a, b, c, d) => {
703+
let buf = [2, // family
704+
32, // bits
705+
0, // is_cidr
706+
4, // nb
707+
a, b, c, d // addr
708+
];
709+
try!(raw.write(&buf));
710+
}
711+
IpAddr::Ipv6Addr(a, b, c, d, e, f, g, h) => {
712+
let buf = [3, // family
713+
128, // bits
714+
0, // is_cidr
715+
16, // nb
716+
];
717+
try!(raw.write(&buf));
718+
try!(raw.write_be_u16(a));
719+
try!(raw.write_be_u16(b));
720+
try!(raw.write_be_u16(c));
721+
try!(raw.write_be_u16(d));
722+
try!(raw.write_be_u16(e));
723+
try!(raw.write_be_u16(f));
724+
try!(raw.write_be_u16(g));
725+
try!(raw.write_be_u16(h));
726+
}
727+
}
728+
Ok(())
729+
}
730+
}
731+
671732
to_raw_to_impl!(Bool, bool)
672733
to_raw_to_impl!(ByteA, Vec<u8>)
673734
to_raw_to_impl!(Varchar | Text | CharN | Name, String)
674735
to_raw_to_impl!(Json, json::Json)
736+
to_raw_to_impl!(Inet, IpAddr)
675737
to_raw_to_impl!(Char, i8)
676738
to_raw_to_impl!(Int2, i16)
677739
to_raw_to_impl!(Int4, i32)

tests/types/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::f32;
44
use std::f64;
55
use std::fmt;
66
use std::num::Float;
7+
use std::io::net::ip::IpAddr;
78

89
use postgres::{Connection, SslMode};
910
use postgres::types::{ToSql, FromSql};
@@ -164,6 +165,15 @@ fn test_json_params() {
164165
(None, "NULL")])
165166
}
166167

168+
#[test]
169+
fn test_inet_params() {
170+
test_type("INET", &[(Some(from_str::<IpAddr>("127.0.0.1").unwrap()),
171+
"'127.0.0.1'"),
172+
(Some(from_str("2001:0db8:85a3:0000:0000:8a2e:0370:7334").unwrap()),
173+
"'2001:0db8:85a3:0000:0000:8a2e:0370:7334'"),
174+
(None, "NULL")])
175+
}
176+
167177
#[test]
168178
fn test_int4range_params() {
169179
test_range!("INT4RANGE", i32, 100i32, "100", 200i32, "200")

0 commit comments

Comments
 (0)