From dac4c4f4f13b5876df40e66d61770afdac7fa807 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 26 Feb 2015 09:02:32 -0800 Subject: [PATCH] Port to new IO --- Cargo.toml | 10 +- src/error.rs | 35 +++++-- src/{io.rs => io_util.rs} | 67 +++++-------- src/lib.rs | 98 ++++++++++++------- src/message.rs | 124 +++++++++++------------- src/types/json.rs | 10 +- src/types/mod.rs | 193 +++++++++++++++++++++++--------------- src/types/slice.rs | 24 +++-- src/types/time.rs | 15 ++- src/types/uuid.rs | 16 +++- src/ugh_privacy.rs | 7 ++ src/url.rs | 8 ++ src/util.rs | 27 +++++- tests/test.rs | 5 +- tests/types/mod.rs | 2 +- 15 files changed, 391 insertions(+), 250 deletions(-) rename src/{io.rs => io_util.rs} (56%) diff --git a/Cargo.toml b/Cargo.toml index a394c368..00ad4bd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,15 +25,19 @@ phf_codegen = "0.6.11" [dependencies] phf = "0.6" -openssl = "0.4.0" +openssl = "0.5" time = "0.1.14" log = "0.2" -rustc-serialize = "0.2" -byteorder = "0.2" +rustc-serialize = "0.3" +byteorder = "0.2.11" [dependencies.uuid] optional = true version = "0.1" +[dependencies.unix_socket] +optional = true +version = "0.1" + [dev-dependencies] url = "0.2" diff --git a/src/error.rs b/src/error.rs index 93a9b77b..fc8daa8b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,11 +1,16 @@ pub use ugh_privacy::DbError; -use std::error; -use std::old_io::IoError; -use std::fmt; +use std::option::Option::{self, Some, None}; +use std::result::Result::Ok; +use std::clone::Clone; +use std::string::String; +use byteorder; use openssl::ssl::error::SslError; use phf; +use std::error; +use std::fmt; +use std::io; use Result; use types::Type; @@ -31,7 +36,7 @@ pub enum ConnectError { /// There was an error initializing the SSL session SslError(SslError), /// There was an error communicating with the server - IoError(IoError), + IoError(io::Error), /// The server sent an unexpected response BadResponse, } @@ -73,8 +78,8 @@ impl error::Error for ConnectError { } } -impl error::FromError for ConnectError { - fn from_error(err: IoError) -> ConnectError { +impl error::FromError for ConnectError { + fn from_error(err: io::Error) -> ConnectError { ConnectError::IoError(err) } } @@ -91,6 +96,12 @@ impl error::FromError for ConnectError { } } +impl error::FromError for ConnectError { + fn from_error(err: byteorder::Error) -> ConnectError { + ConnectError::IoError(error::FromError::from_error(err)) + } +} + /// Represents the position of an error in a query #[derive(Clone, PartialEq, Eq, Debug)] pub enum ErrorPosition { @@ -111,7 +122,7 @@ pub enum Error { /// An error reported by the Postgres server DbError(DbError), /// An error communicating with the Postgres server - IoError(IoError), + IoError(io::Error), /// The communication channel with the Postgres server has desynchronized /// due to an earlier communications error. StreamDesynchronized, @@ -166,8 +177,14 @@ impl error::FromError for Error { } } -impl error::FromError for Error { - fn from_error(err: IoError) -> Error { +impl error::FromError for Error { + fn from_error(err: io::Error) -> Error { Error::IoError(err) } } + +impl error::FromError for Error { + fn from_error(err: byteorder::Error) -> Error { + Error::IoError(error::FromError::from_error(err)) + } +} diff --git a/src/io.rs b/src/io_util.rs similarity index 56% rename from src/io.rs rename to src/io_util.rs index 023d788a..dbf9cd69 100644 --- a/src/io.rs +++ b/src/io_util.rs @@ -1,82 +1,67 @@ +use std::option::Option::None; +use std::result::Result::{self, Ok, Err}; +#[cfg(feature = "unix_socket")] +use std::clone::Clone; + use openssl::ssl::{SslStream, MaybeSslStream}; -use std::old_io::BufferedStream; -use std::old_io::net::ip::Port; -use std::old_io::net::tcp::TcpStream; -use std::old_io::net::pipe::UnixStream; -use std::old_io::{IoResult, Stream}; +use std::io; +use std::io::prelude::*; +use std::net::TcpStream; +#[cfg(feature = "unix_socket")] +use unix_socket::UnixStream; +use byteorder::ReadBytesExt; use {ConnectParams, SslMode, ConnectTarget, ConnectError}; use message; use message::WriteMessage; use message::FrontendMessage::SslRequest; -const DEFAULT_PORT: Port = 5432; - -#[doc(hidden)] -pub trait Timeout { - fn set_read_timeout(&mut self, timeout_ms: Option); -} - -impl Timeout for MaybeSslStream { - fn set_read_timeout(&mut self, timeout_ms: Option) { - self.get_mut().set_read_timeout(timeout_ms); - } -} - -impl Timeout for BufferedStream { - fn set_read_timeout(&mut self, timeout_ms: Option) { - self.get_mut().set_read_timeout(timeout_ms); - } -} +const DEFAULT_PORT: u16 = 5432; pub enum InternalStream { Tcp(TcpStream), + #[cfg(feature = "unix_socket")] Unix(UnixStream), } -impl Reader for InternalStream { - fn read(&mut self, buf: &mut [u8]) -> IoResult { +impl Read for InternalStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { match *self { InternalStream::Tcp(ref mut s) => s.read(buf), + #[cfg(feature = "unix_socket")] InternalStream::Unix(ref mut s) => s.read(buf), } } } -impl Writer for InternalStream { - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { +impl Write for InternalStream { + fn write(&mut self, buf: &[u8]) -> io::Result { match *self { - InternalStream::Tcp(ref mut s) => s.write_all(buf), - InternalStream::Unix(ref mut s) => s.write_all(buf), + InternalStream::Tcp(ref mut s) => s.write(buf), + #[cfg(feature = "unix_socket")] + InternalStream::Unix(ref mut s) => s.write(buf), } } - fn flush(&mut self) -> IoResult<()> { + fn flush(&mut self) -> io::Result<()> { match *self { InternalStream::Tcp(ref mut s) => s.flush(), + #[cfg(feature = "unix_socket")] InternalStream::Unix(ref mut s) => s.flush(), } } } -impl Timeout for InternalStream { - fn set_read_timeout(&mut self, timeout_ms: Option) { - match *self { - InternalStream::Tcp(ref mut s) => s.set_read_timeout(timeout_ms), - InternalStream::Unix(ref mut s) => s.set_read_timeout(timeout_ms), - } - } -} - fn open_socket(params: &ConnectParams) -> Result { let port = params.port.unwrap_or(DEFAULT_PORT); match params.target { ConnectTarget::Tcp(ref host) => { - Ok(try!(TcpStream::connect((&**host, port)).map(InternalStream::Tcp))) + Ok(try!(TcpStream::connect(&(&**host, port)).map(InternalStream::Tcp))) } + #[cfg(feature = "unix_socket")] ConnectTarget::Unix(ref path) => { let mut path = path.clone(); - path.push(format!(".s.PGSQL.{}", port)); + path.push(&format!(".s.PGSQL.{}", port)); Ok(try!(UnixStream::connect(&path).map(InternalStream::Unix))) } } diff --git a/src/lib.rs b/src/lib.rs index 4219529a..b75a4837 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,8 +43,10 @@ //! } //! ``` #![doc(html_root_url="https://sfackler.github.io/rust-postgres/doc")] -#![feature(unsafe_destructor, collections, old_io, io, core, old_path, std_misc)] +#![feature(unsafe_destructor, collections, io, core, net)] +#![cfg_attr(feature = "unix_socket", feature(path))] #![warn(missing_docs)] +#![no_implicit_prelude] extern crate byteorder; #[macro_use] @@ -53,43 +55,58 @@ extern crate openssl; extern crate phf; extern crate "rustc-serialize" as serialize; extern crate time; +#[cfg(feature = "unix_socket")] +extern crate unix_socket; + +use std::option::Option::{self, Some, None}; +use std::result::Result::{Ok, Err}; +use std::boxed::Box; +use std::vec::Vec; +use std::clone::Clone; +use std::string::{String, ToString}; +use std::ops::Drop; +use std::iter::{Iterator, DoubleEndedIterator, ExactSizeIterator, IteratorExt}; +use std::prelude::v1::drop; +use std::marker::Send; +use std::slice::SliceExt; +use std::str::StrExt; use openssl::crypto::hash::{self, Hasher}; use openssl::ssl::{SslContext, MaybeSslStream}; use serialize::hex::ToHex; use std::borrow::{ToOwned, Cow}; use std::cell::{Cell, RefCell}; -use std::cmp::max; use std::collections::{VecDeque, HashMap}; use std::fmt; use std::iter::{IntoIterator, RandomAccessIterator}; -use std::old_io::{BufferedStream, IoResult, IoError, IoErrorKind}; -use std::old_io::net::ip::Port; +use std::io::{self, BufStream}; +use std::io::prelude::*; use std::mem; use std::slice; use std::result; -use std::time::Duration; use std::vec; -use time::SteadyTime; +use byteorder::{WriteBytesExt, BigEndian}; +#[cfg(feature = "unix_socket")] +use std::path::PathBuf; -use url::Url; pub use error::{Error, ConnectError, SqlState, DbError, ErrorPosition}; #[doc(inline)] pub use types::{Oid, Type, Kind, ToSql, FromSql}; use types::IsNull; #[doc(inline)] pub use types::Slice; -use io::{InternalStream, Timeout}; +use io_util::InternalStream; use message::BackendMessage::*; use message::FrontendMessage::*; use message::{FrontendMessage, BackendMessage, RowDescriptionEntry}; use message::{WriteMessage, ReadMessage}; +use url::Url; #[macro_use] mod macros; mod error; -mod io; +mod io_util; mod message; mod ugh_privacy; mod url; @@ -107,7 +124,10 @@ pub enum ConnectTarget { /// Connect via TCP to the specified host. Tcp(String), /// Connect via a Unix domain socket in the specified directory. - Unix(Path) + /// + /// Only available on Unix platforms with the `unix_socket` feature. + #[cfg(feature = "unix_socket")] + Unix(PathBuf) } /// Authentication information @@ -127,7 +147,7 @@ pub struct ConnectParams { /// The target port. /// /// Defaults to 5432 if not specified. - pub port: Option, + pub port: Option, /// The user to login as. /// /// `Connection::connect` requires a user but `cancel_query` does not. @@ -169,9 +189,19 @@ impl IntoConnectParams for Url { .. } = self; + #[cfg(feature = "unix_socket")] + fn make_unix(maybe_path: String) -> result::Result { + Ok(ConnectTarget::Unix(PathBuf::new(&maybe_path))) + } + #[cfg(not(feature = "unix_socket"))] + fn make_unix(_: String) -> result::Result { + Err(ConnectError::InvalidUrl("unix socket support requires the `unix_socket` feature" + .to_string())) + } + let maybe_path = try!(url::decode_component(&host).map_err(ConnectError::InvalidUrl)); let target = if maybe_path.starts_with("/") { - ConnectTarget::Unix(Path::new(maybe_path)) + try!(make_unix(maybe_path)) } else { ConnectTarget::Tcp(host) }; @@ -270,6 +300,7 @@ impl<'conn> Notifications<'conn> { } } + /* /// Returns the oldest pending notification /// /// If no notifications are pending, blocks for up to `timeout` time, after @@ -323,6 +354,7 @@ impl<'conn> Notifications<'conn> { } } } + */ } /// Contains information necessary to cancel queries for a session @@ -364,7 +396,7 @@ pub struct CancelData { pub fn cancel_query(params: T, ssl: &SslMode, data: CancelData) -> result::Result<(), ConnectError> where T: IntoConnectParams { let params = try!(params.into_connect_params()); - let mut socket = try!(io::initialize_stream(¶ms, ssl)); + let mut socket = try!(io_util::initialize_stream(¶ms, ssl)); try!(socket.write_message(&CancelRequest { code: message::CANCEL_CODE, @@ -384,7 +416,7 @@ struct CachedStatement { } struct InnerConnection { - stream: BufferedStream>, + stream: BufStream>, notice_handler: Box, notifications: VecDeque, cancel_data: CancelData, @@ -409,14 +441,14 @@ impl InnerConnection { fn connect(params: T, ssl: &SslMode) -> result::Result where T: IntoConnectParams { let params = try!(params.into_connect_params()); - let stream = try!(io::initialize_stream(¶ms, ssl)); + let stream = try!(io_util::initialize_stream(¶ms, ssl)); let ConnectParams { user, database, mut options, .. } = params; let user = try!(user.ok_or(ConnectError::MissingUser)); let mut conn = InnerConnection { - stream: BufferedStream::new(stream), + stream: BufStream::new(stream), next_stmt_id: 0, notice_handler: Box::new(LoggingNoticeHandler), notifications: VecDeque::new(), @@ -488,7 +520,7 @@ impl InnerConnection { } } - fn write_messages(&mut self, messages: &[FrontendMessage]) -> IoResult<()> { + fn write_messages(&mut self, messages: &[FrontendMessage]) -> io::Result<()> { debug_assert!(!self.desynchronized); for message in messages { try_desync!(self, self.stream.write_message(message)); @@ -496,7 +528,7 @@ impl InnerConnection { Ok(try_desync!(self, self.stream.flush())) } - fn read_one_message(&mut self) -> IoResult> { + fn read_one_message(&mut self) -> io::Result> { debug_assert!(!self.desynchronized); match try_desync!(self, self.stream.read_message()) { NoticeResponse { fields } => { @@ -513,7 +545,7 @@ impl InnerConnection { } } - fn read_message_with_notification(&mut self) -> IoResult { + fn read_message_with_notification(&mut self) -> io::Result { loop { if let Some(msg) = try!(self.read_one_message()) { return Ok(msg); @@ -521,7 +553,7 @@ impl InnerConnection { } } - fn read_message(&mut self) -> IoResult { + fn read_message(&mut self) -> io::Result { loop { match try!(self.read_message_with_notification()) { NotificationResponse { pid, channel, payload } => { @@ -874,12 +906,13 @@ impl Connection { /// (5432) is used if none is specified. The database name defaults to the /// username if not specified. /// - /// To connect to the server via Unix sockets, `host` should be set to the - /// absolute path of the directory containing the socket file. Since `/` is - /// a reserved character in URLs, the path should be URL encoded. If the - /// path contains non-UTF 8 characters, a `ConnectParams` struct - /// should be created manually and passed in. Note that Postgres does not - /// support SSL over Unix sockets. + /// Connection via Unix sockets is supported with the `unix_sockets` + /// feature. To connect to the server via Unix sockets, `host` should be + /// set to the absolute path of the directory containing the socket file. + /// Since `/` is a reserved character in URLs, the path should be URL + /// encoded. If the path contains non-UTF 8 characters, a `ConnectParams` + /// struct should be created manually and passed in. Note that Postgres + /// does not support SSL over Unix sockets. /// /// ## Examples /// @@ -902,6 +935,7 @@ impl Connection { /// ```rust,no_run /// # #![allow(unstable)] /// # use postgres::{Connection, UserInfo, ConnectParams, SslMode, ConnectTarget, ConnectError}; + /// # #[cfg(feature = "unix_socket")] /// # fn f() -> Result<(), ConnectError> { /// # let some_crazy_path = Path::new(""); /// let params = ConnectParams { @@ -2054,11 +2088,11 @@ impl<'a> CopyInStatement<'a> { let mut buf = vec![]; let _ = buf.write_all(b"PGCOPY\n\xff\r\n\x00"); - let _ = buf.write_be_i32(0); - let _ = buf.write_be_i32(0); + let _ = buf.write_i32::(0); + let _ = buf.write_i32::(0); 'l: for mut row in rows { - let _ = buf.write_be_i16(self.column_types.len() as i16); + let _ = buf.write_i16::(self.column_types.len() as i16); let mut types = self.column_types.iter(); loop { @@ -2067,10 +2101,10 @@ impl<'a> CopyInStatement<'a> { let mut inner_buf = vec![]; match val.to_sql_checked(ty, &mut inner_buf) { Ok(IsNull::Yes) => { - let _ = buf.write_be_i32(-1); + let _ = buf.write_i32::(-1); } Ok(IsNull::No) => { - let _ = buf.write_be_i32(inner_buf.len() as i32); + let _ = buf.write_i32::(inner_buf.len() as i32); let _ = buf.write_all(&inner_buf); } Err(err) => { @@ -2101,7 +2135,7 @@ impl<'a> CopyInStatement<'a> { buf.clear(); } - let _ = buf.write_be_i16(-1); + let _ = buf.write_i16::(-1); try!(conn.write_messages(&[ CopyData { data: &buf, diff --git a/src/message.rs b/src/message.rs index 358e962b..46b782eb 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,5 +1,3 @@ -#![no_implicit_prelude] - use std::result::Result::{Ok, Err}; use std::option::Option::{self, None, Some}; use std::vec::Vec; @@ -7,13 +5,13 @@ use std::string::String; use std::str::StrExt; use std::slice::SliceExt; -use std::old_io::{self, IoResult, IoError, OtherIoError, ByRefReader, Buffer}; -use std::old_io::util::LimitReader; +use std::io; +use std::io::prelude::*; use std::mem; -use byteorder::{BigEndian, ReaderBytesExt, WriterBytesExt}; +use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; -use io::Timeout; use types::Oid; +use util; use self::BackendMessage::*; use self::FrontendMessage::*; @@ -144,23 +142,23 @@ pub enum FrontendMessage<'a> { #[doc(hidden)] trait WriteCStr { - fn write_cstr(&mut self, s: &str) -> IoResult<()>; + fn write_cstr(&mut self, s: &str) -> io::Result<()>; } -impl WriteCStr for W { - fn write_cstr(&mut self, s: &str) -> IoResult<()> { +impl WriteCStr for W { + fn write_cstr(&mut self, s: &str) -> io::Result<()> { try!(self.write_all(s.as_bytes())); - self.write_u8(0) + Ok(try!(self.write_u8(0))) } } #[doc(hidden)] pub trait WriteMessage { - fn write_message(&mut self, &FrontendMessage) -> IoResult<()> ; + fn write_message(&mut self, &FrontendMessage) -> io::Result<()> ; } -impl WriteMessage for W { - fn write_message(&mut self, message: &FrontendMessage) -> IoResult<()> { +impl WriteMessage for W { + fn write_message(&mut self, message: &FrontendMessage) -> io::Result<()> { let mut buf = vec![]; let mut ident = None; @@ -181,7 +179,7 @@ impl WriteMessage for W { None => try!(buf.write_i32::(-1)), Some(ref value) => { try!(buf.write_i32::(value.len() as i32)); - try!(old_io::Writer::write_all(&mut buf, &**value)); + try!(buf.write_all(&**value)); } } } @@ -203,7 +201,7 @@ impl WriteMessage for W { } CopyData { data } => { ident = Some(b'd'); - try!(old_io::Writer::write_all(&mut buf, data)); + try!(buf.write_all(data)); } CopyDone => ident = Some(b'c'), CopyFail { message } => { @@ -264,40 +262,32 @@ impl WriteMessage for W { #[doc(hidden)] trait ReadCStr { - fn read_cstr(&mut self) -> IoResult; + fn read_cstr(&mut self) -> io::Result; } -impl ReadCStr for R { - fn read_cstr(&mut self) -> IoResult { - let mut buf = try!(self.read_until(0)); +impl ReadCStr for R { + fn read_cstr(&mut self) -> io::Result { + let mut buf = vec![]; + try!(self.read_until(0, &mut buf)); buf.pop(); - String::from_utf8(buf).map_err(|_| IoError { - kind: OtherIoError, - desc: "Received a non-utf8 string from server", - detail: None - }) + String::from_utf8(buf).map_err(|_| io::Error::new(io::ErrorKind::Other, + "received a non-utf8 string from server", + None)) } } #[doc(hidden)] pub trait ReadMessage { - fn read_message(&mut self) -> IoResult; + fn read_message(&mut self) -> io::Result; } -impl ReadMessage for R { - fn read_message(&mut self) -> IoResult { - // The first byte read is a bit complex to make - // Notifications::next_block_for work. - let ident = self.read_u8(); - // At this point we've got to turn off any read timeout to prevent - // stream desynchronization. We're assuming that if we've got the first - // byte, there's more stuff to follow. - self.set_read_timeout(None); - let ident = try!(ident); +impl ReadMessage for R { + fn read_message(&mut self) -> io::Result { + let ident = try!(self.read_u8()); // subtract size of length value let len = try!(self.read_u32::()) as usize - mem::size_of::(); - let mut rdr = LimitReader::new(self.by_ref(), len); + let mut rdr = self.by_ref().take(len as u64); let ret = match ident { b'1' => ParseComplete, @@ -338,24 +328,20 @@ impl ReadMessage for R { b't' => try!(read_parameter_description(&mut rdr)), b'T' => try!(read_row_description(&mut rdr)), b'Z' => ReadyForQuery { _state: try!(rdr.read_u8()) }, - ident => return Err(IoError { - kind: OtherIoError, - desc: "Unexpected message tag", - detail: Some(format!("got {}", ident)), - }) + ident => { + return Err(io::Error::new(io::ErrorKind::Other, + "unexpected message tag", + Some(format!("got {}", ident)))) + } }; if rdr.limit() != 0 { - return Err(IoError { - kind: OtherIoError, - desc: "didn't read entire message", - detail: None, - }); + return Err(io::Error::new(io::ErrorKind::Other, "didn't read entire message", None)); } Ok(ret) } } -fn read_fields(buf: &mut R) -> IoResult> { +fn read_fields(buf: &mut R) -> io::Result> { let mut fields = vec![]; loop { let ty = try!(buf.read_u8()); @@ -369,14 +355,18 @@ fn read_fields(buf: &mut R) -> IoResult> { Ok(fields) } -fn read_data_row(buf: &mut R) -> IoResult { - let len = try!(buf.read_be_u16()) as usize; +fn read_data_row(buf: &mut R) -> io::Result { + let len = try!(buf.read_u16::()) as usize; let mut values = Vec::with_capacity(len); for _ in 0..len { - let val = match try!(buf.read_be_i32()) { + let val = match try!(buf.read_i32::()) { -1 => None, - len => Some(try!(buf.read_exact(len as usize))) + len => { + let mut data = vec![]; + try!(buf.take(len as u64).read_to_end(&mut data)); + Some(data) + } }; values.push(val); } @@ -384,29 +374,29 @@ fn read_data_row(buf: &mut R) -> IoResult { Ok(DataRow { row: values }) } -fn read_auth_message(buf: &mut R) -> IoResult { - Ok(match try!(buf.read_be_i32()) { +fn read_auth_message(buf: &mut R) -> io::Result { + Ok(match try!(buf.read_i32::()) { 0 => AuthenticationOk, 2 => AuthenticationKerberosV5, 3 => AuthenticationCleartextPassword, 5 => { let mut salt = [0; 4]; - try!(buf.read_at_least(salt.len(), &mut salt)); + try!(util::read_all(buf, &mut salt)); AuthenticationMD5Password { salt: salt } }, 6 => AuthenticationSCMCredential, 7 => AuthenticationGSS, 9 => AuthenticationSSPI, - val => return Err(IoError { - kind: OtherIoError, - desc: "Unexpected authentication tag", - detail: Some(format!("got {}", val)), - }) + val => { + return Err(io::Error::new(io::ErrorKind::Other, + "unexpected authentication tag", + Some(format!("got {}", val)))); + } }) } -fn read_parameter_description(buf: &mut R) -> IoResult { - let len = try!(buf.read_be_i16()) as usize; +fn read_parameter_description(buf: &mut R) -> io::Result { + let len = try!(buf.read_i16::()) as usize; let mut types = Vec::with_capacity(len); for _ in 0..len { @@ -416,19 +406,19 @@ fn read_parameter_description(buf: &mut R) -> IoResult(buf: &mut R) -> IoResult { - let len = try!(buf.read_be_i16()) as usize; +fn read_row_description(buf: &mut R) -> io::Result { + let len = try!(buf.read_i16::()) as usize; let mut types = Vec::with_capacity(len); for _ in 0..len { types.push(RowDescriptionEntry { name: try!(buf.read_cstr()), table_oid: try!(buf.read_u32::()), - column_id: try!(buf.read_be_i16()), + column_id: try!(buf.read_i16::()), type_oid: try!(buf.read_u32::()), - type_size: try!(buf.read_be_i16()), - type_modifier: try!(buf.read_be_i32()), - format: try!(buf.read_be_i16()) + type_size: try!(buf.read_i16::()), + type_modifier: try!(buf.read_i32::()), + format: try!(buf.read_i16::()) }) } diff --git a/src/types/json.rs b/src/types/json.rs index aa480d0e..8100b50e 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -1,10 +1,16 @@ +use std::marker::Sized; +use std::result::Result::{Ok, Err}; +use std::clone::Clone; + use serialize::json; +use std::io::prelude::*; +use byteorder::{ReadBytesExt, WriteBytesExt}; use {Result, Error}; use types::{FromSql, ToSql, IsNull, Type}; impl FromSql for json::Json { - fn from_sql(ty: &Type, raw: &mut R) -> Result { + fn from_sql(ty: &Type, raw: &mut R) -> Result { if let Type::Jsonb = *ty { // We only support version 1 of the jsonb binary format if try!(raw.read_u8()) != 1 { @@ -18,7 +24,7 @@ impl FromSql for json::Json { } impl ToSql for json::Json { - fn to_sql(&self, ty: &Type, out: &mut W) -> Result { + fn to_sql(&self, ty: &Type, mut out: &mut W) -> Result { if let Type::Jsonb = *ty { try!(out.write_u8(1)); } diff --git a/src/types/mod.rs b/src/types/mod.rs index f34591bf..cca95ecc 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,9 +1,21 @@ //! Traits dealing with Postgres data types pub use self::slice::Slice; +use std::option::Option::{self, Some, None}; +use std::result::Result::{Ok, Err}; +use std::boxed::Box; +use std::vec::Vec; +use std::clone::Clone; +use std::string::String; +use std::iter::ExactSizeIterator; +use std::marker::Sized; +use std::str::StrExt; + use std::collections::HashMap; -use std::old_io::net::ip::IpAddr; +use std::net::IpAddr; use std::fmt; +use std::io::prelude::*; +use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian}; use Result; use error::Error; @@ -25,7 +37,7 @@ macro_rules! accepts { #[macro_export] macro_rules! to_sql_checked { () => { - fn to_sql_checked(&self, ty: &Type, out: &mut Writer) -> Result { + fn to_sql_checked(&self, ty: &Type, out: &mut Write) -> Result { if !::accepts(ty) { return Err($crate::Error::WrongType(ty.clone())); } @@ -440,9 +452,9 @@ make_postgres_type! { /// A trait for types that can be created from a Postgres value. pub trait FromSql: Sized { - /// Creates a new value of this type from a `Reader` of Postgres data. + /// Creates a new value of this type from a `Read` of Postgres data. /// - /// If the value was `NULL`, the `Reader` will be `None`. + /// If the value was `NULL`, the `Read` will be `None`. /// /// The caller of this method is responsible for ensuring that this type /// is compatible with the Postgres `Type`. @@ -450,19 +462,19 @@ pub trait FromSql: Sized { /// The default implementation calls `FromSql::from_sql` when `raw` is /// `Some` and returns `Err(Error::WasNull)` when `raw` is `None`. It does /// not typically need to be overridden. - fn from_sql_nullable(ty: &Type, raw: Option<&mut R>) -> Result { + fn from_sql_nullable(ty: &Type, raw: Option<&mut R>) -> Result { match raw { Some(raw) => FromSql::from_sql(ty, raw), None => Err(Error::WasNull), } } - /// Creates a new value of this type from a `Reader` of the binary format + /// Creates a new value of this type from a `Read` of the binary format /// of the specified Postgres `Type`. /// /// The caller of this method is responsible for ensuring that this type /// is compatible with the Postgres `Type`. - fn from_sql(ty: &Type, raw: &mut R) -> Result; + fn from_sql(ty: &Type, raw: &mut R) -> Result; /// Determines if a value of this type can be created from the specified /// Postgres `Type`. @@ -470,14 +482,14 @@ pub trait FromSql: Sized { } impl FromSql for Option { - fn from_sql_nullable(ty: &Type, raw: Option<&mut R>) -> Result> { + fn from_sql_nullable(ty: &Type, raw: Option<&mut R>) -> Result> { match raw { Some(raw) => ::from_sql(ty, raw).map(|e| Some(e)), None => Ok(None), } } - fn from_sql(ty: &Type, raw: &mut R) -> Result> { + fn from_sql(ty: &Type, raw: &mut R) -> Result> { ::from_sql(ty, raw).map(|e| Some(e)) } @@ -487,7 +499,7 @@ impl FromSql for Option { } impl FromSql for bool { - fn from_sql(_: &Type, raw: &mut R) -> Result { + fn from_sql(_: &Type, raw: &mut R) -> Result { Ok(try!(raw.read_u8()) != 0) } @@ -495,16 +507,20 @@ impl FromSql for bool { } impl FromSql for Vec { - fn from_sql(_: &Type, raw: &mut R) -> Result> { - Ok(try!(raw.read_to_end())) + fn from_sql(_: &Type, raw: &mut R) -> Result> { + let mut buf = vec![]; + try!(raw.read_to_end(&mut buf)); + Ok(buf) } accepts!(Type::Bytea); } impl FromSql for String { - fn from_sql(_: &Type, raw: &mut R) -> Result { - String::from_utf8(try!(raw.read_to_end())).map_err(|_| Error::BadResponse) + fn from_sql(_: &Type, raw: &mut R) -> Result { + let mut buf = vec![]; + try!(raw.read_to_end(&mut buf)); + String::from_utf8(buf).map_err(|_| Error::BadResponse) } fn accepts(ty: &Type) -> bool { @@ -519,8 +535,8 @@ impl FromSql for String { macro_rules! primitive_from { ($t:ty, $f:ident, $($expected:pat),+) => { impl FromSql for $t { - fn from_sql(_: &Type, raw: &mut R) -> Result<$t> { - Ok(try!(raw.$f())) + fn from_sql(_: &Type, raw: &mut R) -> Result<$t> { + Ok(try!(raw.$f::())) } accepts!($($expected),+); @@ -528,16 +544,23 @@ macro_rules! primitive_from { } } -primitive_from!(i8, read_i8, Type::Char); -primitive_from!(i16, read_be_i16, Type::Int2); -primitive_from!(i32, read_be_i32, Type::Int4); -primitive_from!(u32, read_be_u32, Type::Oid); -primitive_from!(i64, read_be_i64, Type::Int8); -primitive_from!(f32, read_be_f32, Type::Float4); -primitive_from!(f64, read_be_f64, Type::Float8); +impl FromSql for i8 { + fn from_sql(_: &Type, raw: &mut R) -> Result { + Ok(try!(raw.read_i8())) + } + + accepts!(Type::Char); +} + +primitive_from!(i16, read_i16, Type::Int2); +primitive_from!(i32, read_i32, Type::Int4); +primitive_from!(u32, read_u32, Type::Oid); +primitive_from!(i64, read_i64, Type::Int8); +primitive_from!(f32, read_f32, Type::Float4); +primitive_from!(f64, read_f64, Type::Float8); impl FromSql for IpAddr { - fn from_sql(_: &Type, raw: &mut R) -> Result { + fn from_sql(_: &Type, raw: &mut R) -> Result { let family = try!(raw.read_u8()); let _bits = try!(raw.read_u8()); let _is_cidr = try!(raw.read_u8()); @@ -545,20 +568,24 @@ impl FromSql for IpAddr { if nb > 16 { return Err(Error::BadResponse); } - let mut buf = [0u8; 16]; - try!(raw.read_at_least(nb as usize, &mut buf)); - let mut buf: &[u8] = &buf; match family { - 2 if nb == 4 => Ok(IpAddr::Ipv4Addr(buf[0], buf[1], buf[2], buf[3])), - 3 if nb == 16 => Ok(IpAddr::Ipv6Addr(try!(buf.read_be_u16()), - try!(buf.read_be_u16()), - try!(buf.read_be_u16()), - try!(buf.read_be_u16()), - try!(buf.read_be_u16()), - try!(buf.read_be_u16()), - try!(buf.read_be_u16()), - try!(buf.read_be_u16()))), + 2 if nb == 4 => { + Ok(IpAddr::new_v4(try!(raw.read_u8()), + try!(raw.read_u8()), + try!(raw.read_u8()), + try!(raw.read_u8()))) + } + 3 if nb == 16 => { + Ok(IpAddr::new_v6(try!(raw.read_u16::()), + try!(raw.read_u16::()), + try!(raw.read_u16::()), + try!(raw.read_u16::()), + try!(raw.read_u16::()), + try!(raw.read_u16::()), + try!(raw.read_u16::()), + try!(raw.read_u16::()))) + } _ => Err(Error::BadResponse), } } @@ -567,25 +594,27 @@ impl FromSql for IpAddr { } impl FromSql for HashMap> { - fn from_sql(_: &Type, raw: &mut R) + fn from_sql(_: &Type, raw: &mut R) -> Result>> { let mut map = HashMap::new(); - let count = try!(raw.read_be_i32()); + let count = try!(raw.read_i32::()); - for _ in range(0, count) { - let key_len = try!(raw.read_be_i32()); - let key = try!(raw.read_exact(key_len as usize)); + for _ in 0..count { + let key_len = try!(raw.read_i32::()); + let mut key = vec![]; + try!(raw.take(key_len as u64).read_to_end(&mut key)); let key = match String::from_utf8(key) { Ok(key) => key, Err(_) => return Err(Error::BadResponse), }; - let val_len = try!(raw.read_be_i32()); + let val_len = try!(raw.read_i32::()); let val = if val_len < 0 { None } else { - let val = try!(raw.read_exact(val_len as usize)); + let mut val = vec![]; + try!(raw.take(val_len as u64).read_to_end(&mut val)); match String::from_utf8(val) { Ok(val) => Some(val), Err(_) => return Err(Error::BadResponse), @@ -626,7 +655,7 @@ pub trait ToSql { /// `NULL`. If this is the case, implementations **must not** write /// anything to `out`. fn to_sql(&self, ty: &Type, out: &mut W) -> Result - where Self: Sized, W: Writer; + where Self: Sized, W: Write; /// Determines if a value of this type can be converted to the specified /// Postgres `Type`. @@ -636,13 +665,13 @@ pub trait ToSql { /// /// *All* implementations of this method should be generated by the /// `to_sql_checked!()` macro. - fn to_sql_checked(&self, ty: &Type, out: &mut Writer) -> Result; + fn to_sql_checked(&self, ty: &Type, out: &mut Write) -> Result; } impl ToSql for Option { to_sql_checked!(); - fn to_sql(&self, ty: &Type, out: &mut W) -> Result { + fn to_sql(&self, ty: &Type, out: &mut W) -> Result { match *self { Some(ref val) => val.to_sql(ty, out), None => Ok(IsNull::Yes), @@ -657,7 +686,7 @@ impl ToSql for Option { impl ToSql for bool { to_sql_checked!(); - fn to_sql(&self, _: &Type, w: &mut W) -> Result { + fn to_sql(&self, _: &Type, mut w: &mut W) -> Result { try!(w.write_u8(*self as u8)); Ok(IsNull::No) } @@ -668,7 +697,7 @@ impl ToSql for bool { impl<'a> ToSql for &'a [u8] { to_sql_checked!(); - fn to_sql(&self, _: &Type, w: &mut W) -> Result { + fn to_sql(&self, _: &Type, w: &mut W) -> Result { try!(w.write_all(*self)); Ok(IsNull::No) } @@ -679,7 +708,7 @@ impl<'a> ToSql for &'a [u8] { impl ToSql for Vec { to_sql_checked!(); - fn to_sql(&self, ty: &Type, w: &mut W) -> Result { + fn to_sql(&self, ty: &Type, w: &mut W) -> Result { (&**self).to_sql(ty, w) } @@ -691,7 +720,7 @@ impl ToSql for Vec { impl<'a> ToSql for &'a str { to_sql_checked!(); - fn to_sql(&self, _: &Type, w: &mut W) -> Result { + fn to_sql(&self, _: &Type, w: &mut W) -> Result { try!(w.write_all(self.as_bytes())); Ok(IsNull::No) } @@ -708,7 +737,7 @@ impl<'a> ToSql for &'a str { impl ToSql for String { to_sql_checked!(); - fn to_sql(&self, ty: &Type, w: &mut W) -> Result { + fn to_sql(&self, ty: &Type, w: &mut W) -> Result { (&**self).to_sql(ty, w) } @@ -722,8 +751,8 @@ macro_rules! to_primitive { impl ToSql for $t { to_sql_checked!(); - fn to_sql(&self, _: &Type, w: &mut W) -> Result { - try!(w.$f(*self)); + fn to_sql(&self, _: &Type, mut w: &mut W) -> Result { + try!(w.$f::(*self)); Ok(IsNull::No) } @@ -732,20 +761,31 @@ macro_rules! to_primitive { } } -to_primitive!(i8, write_i8, Type::Char); -to_primitive!(i16, write_be_i16, Type::Int2); -to_primitive!(i32, write_be_i32, Type::Int4); -to_primitive!(u32, write_be_u32, Type::Oid); -to_primitive!(i64, write_be_i64, Type::Int8); -to_primitive!(f32, write_be_f32, Type::Float4); -to_primitive!(f64, write_be_f64, Type::Float8); +impl ToSql for i8 { + to_sql_checked!(); + + fn to_sql(&self, _: &Type, mut w: &mut W) -> Result { + try!(w.write_i8(*self)); + Ok(IsNull::No) + } + + accepts!(Type::Char); +} + +to_primitive!(i16, write_i16, Type::Int2); +to_primitive!(i32, write_i32, Type::Int4); +to_primitive!(u32, write_u32, Type::Oid); +to_primitive!(i64, write_i64, Type::Int8); +to_primitive!(f32, write_f32, Type::Float4); +to_primitive!(f64, write_f64, Type::Float8); impl ToSql for IpAddr { to_sql_checked!(); - fn to_sql(&self, _: &Type, w: &mut W) -> Result { + fn to_sql(&self, _: &Type, mut w: &mut W) -> Result { match *self { - IpAddr::Ipv4Addr(a, b, c, d) => { + IpAddr::V4(addr) => { + let [a, b, c, d] = addr.octets(); try!(w.write_all(&[2, // family 32, // bits 0, // is_cidr @@ -753,20 +793,21 @@ impl ToSql for IpAddr { a, b, c, d // addr ])); } - IpAddr::Ipv6Addr(a, b, c, d, e, f, g, h) => { + IpAddr::V6(addr) => { + let [a, b, c, d, e, f, g, h] = addr.segments(); try!(w.write_all(&[3, // family 128, // bits 0, // is_cidr 16, // nb ])); - try!(w.write_be_u16(a)); - try!(w.write_be_u16(b)); - try!(w.write_be_u16(c)); - try!(w.write_be_u16(d)); - try!(w.write_be_u16(e)); - try!(w.write_be_u16(f)); - try!(w.write_be_u16(g)); - try!(w.write_be_u16(h)); + try!(w.write_u16::(a)); + try!(w.write_u16::(b)); + try!(w.write_u16::(c)); + try!(w.write_u16::(d)); + try!(w.write_u16::(e)); + try!(w.write_u16::(f)); + try!(w.write_u16::(g)); + try!(w.write_u16::(h)); } } Ok(IsNull::No) @@ -778,19 +819,19 @@ impl ToSql for IpAddr { impl ToSql for HashMap> { to_sql_checked!(); - fn to_sql(&self, _: &Type, w: &mut W) -> Result { - try!(w.write_be_i32(self.len() as i32)); + fn to_sql(&self, _: &Type, mut w: &mut W) -> Result { + try!(w.write_i32::(self.len() as i32)); for (key, val) in self.iter() { - try!(w.write_be_i32(key.len() as i32)); + try!(w.write_i32::(key.len() as i32)); try!(w.write_all(key.as_bytes())); match *val { Some(ref val) => { - try!(w.write_be_i32(val.len() as i32)); + try!(w.write_i32::(val.len() as i32)); try!(w.write_all(val.as_bytes())); } - None => try!(w.write_be_i32(-1)) + None => try!(w.write_i32::(-1)) } } diff --git a/src/types/slice.rs b/src/types/slice.rs index 525dcec1..65a5eb0b 100644 --- a/src/types/slice.rs +++ b/src/types/slice.rs @@ -1,3 +1,11 @@ +use std::result::Result::{Ok, Err}; +use std::marker::Sized; +use std::slice::SliceExt; +use std::clone::Clone; + +use std::io::prelude::*; +use byteorder::{WriteBytesExt, BigEndian}; + use {Type, ToSql, Result, Error, Kind}; use types::IsNull; @@ -26,7 +34,7 @@ pub struct Slice<'a, T: 'a + ToSql>(pub &'a [T]); impl<'a, T: 'a + ToSql> ToSql for Slice<'a, T> { to_sql_checked!(); - fn to_sql(&self, ty: &Type, w: &mut W) -> Result { + fn to_sql(&self, ty: &Type, mut w: &mut W) -> Result { let member_type = match ty.kind() { &Kind::Array(ref member) => member, _ => panic!("expected array type"), @@ -35,21 +43,21 @@ impl<'a, T: 'a + ToSql> ToSql for Slice<'a, T> { return Err(Error::WrongType(ty.clone())); } - try!(w.write_be_i32(1)); // number of dimensions - try!(w.write_be_i32(1)); // has nulls - try!(w.write_be_u32(member_type.to_oid())); + try!(w.write_i32::(1)); // number of dimensions + try!(w.write_i32::(1)); // has nulls + try!(w.write_u32::(member_type.to_oid())); - try!(w.write_be_i32(self.0.len() as i32)); - try!(w.write_be_i32(0)); // index offset + try!(w.write_i32::(self.0.len() as i32)); + try!(w.write_i32::(0)); // index offset for e in self.0 { let mut inner_buf = vec![]; match try!(e.to_sql(&member_type, &mut inner_buf)) { IsNull::No => { - try!(w.write_be_i32(inner_buf.len() as i32)); + try!(w.write_i32::(inner_buf.len() as i32)); try!(w.write_all(&inner_buf)); } - IsNull::Yes => try!(w.write_be_i32(-1)), + IsNull::Yes => try!(w.write_i32::(-1)), } } diff --git a/src/types/time.rs b/src/types/time.rs index 7c54a0fe..8d89ed5e 100644 --- a/src/types/time.rs +++ b/src/types/time.rs @@ -1,4 +1,11 @@ +use std::result::Result::{Ok, Err}; +use std::marker::Sized; +use std::clone::Clone; + +use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian}; use time::Timespec; +use std::io::prelude::*; + use Result; use types::{Type, FromSql, ToSql, IsNull}; @@ -9,8 +16,8 @@ const NSEC_PER_USEC: i64 = 1_000; const TIME_SEC_CONVERSION: i64 = 946684800; impl FromSql for Timespec { - fn from_sql(_: &Type, raw: &mut R) -> Result { - let t = try!(raw.read_be_i64()); + fn from_sql(_: &Type, raw: &mut R) -> Result { + let t = try!(raw.read_i64::()); let mut sec = t / USEC_PER_SEC + TIME_SEC_CONVERSION; let mut usec = t % USEC_PER_SEC; @@ -26,9 +33,9 @@ impl FromSql for Timespec { } impl ToSql for Timespec { - fn to_sql(&self, _: &Type, w: &mut W) -> Result { + fn to_sql(&self, _: &Type, mut w: &mut W) -> Result { let t = (self.sec - TIME_SEC_CONVERSION) * USEC_PER_SEC + self.nsec as i64 / NSEC_PER_USEC; - try!(w.write_be_i64(t)); + try!(w.write_i64::(t)); Ok(IsNull::No) } diff --git a/src/types/uuid.rs b/src/types/uuid.rs index e9708e40..c97cafa7 100644 --- a/src/types/uuid.rs +++ b/src/types/uuid.rs @@ -1,13 +1,23 @@ extern crate uuid; +use std::result::Result::{Ok, Err}; +use std::marker::Sized; +use std::option::Option::{Some, None}; +use std::clone::Clone; + +use std::io::prelude::*; + use self::uuid::Uuid; use types::{FromSql, ToSql, Type, IsNull}; use Error; use Result; +use util; impl FromSql for Uuid { - fn from_sql(_: &Type, raw: &mut R) -> Result { - match Uuid::from_bytes(&*try!(raw.read_to_end())) { + fn from_sql(_: &Type, raw: &mut R) -> Result { + let mut bytes = [0; 16]; + try!(util::read_all(raw, &mut bytes)); + match Uuid::from_bytes(&bytes) { Some(u) => Ok(u), None => Err(Error::BadResponse), } @@ -17,7 +27,7 @@ impl FromSql for Uuid { } impl ToSql for Uuid { - fn to_sql(&self, _: &Type, w: &mut W) -> Result { + fn to_sql(&self, _: &Type, w: &mut W) -> Result { try!(w.write_all(self.as_bytes())); Ok(IsNull::No) } diff --git a/src/ugh_privacy.rs b/src/ugh_privacy.rs index a1bfbef0..0ea3765f 100644 --- a/src/ugh_privacy.rs +++ b/src/ugh_privacy.rs @@ -1,3 +1,10 @@ +use std::option::Option::{self, Some, None}; +use std::result::Result::{Ok, Err}; +use std::vec::Vec; +use std::string::String; +use std::iter::IteratorExt; +use std::str::StrExt; + use std::collections::HashMap; use std::error; use std::fmt; diff --git a/src/url.rs b/src/url.rs index ceb7a14b..5fa29c6a 100644 --- a/src/url.rs +++ b/src/url.rs @@ -7,7 +7,15 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::option::Option::{self, Some, None}; +use std::result::Result::{self, Ok, Err}; +use std::vec::Vec; +use std::string::{String, ToString}; +use std::iter::{Iterator, IteratorExt, ExactSizeIterator}; +use std::slice::SliceExt; +use std::str::{Str, StrExt}; +use std::io::prelude::*; use std::str::FromStr; use std::num; use std::str; diff --git a/src/util.rs b/src/util.rs index 3edb8608..92c1920a 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,16 @@ -use std::old_io::IoResult; +use std::result::Result::{Ok, Err}; +use std::iter::Iterator; +use std::string::String; +use std::str::StrExt; +use std::iter::IteratorExt; +use std::option::Option::None; +use std::slice::SliceExt; -pub fn comma_join<'a, W, I>(writer: &mut W, strs: I) -> IoResult<()> - where W: Writer, I: Iterator { +use std::io; +use std::io::prelude::*; + +pub fn comma_join<'a, W, I>(writer: &mut W, strs: I) -> io::Result<()> + where W: Write, I: Iterator { let mut first = true; for str_ in strs { if !first { @@ -16,3 +25,15 @@ pub fn comma_join<'a, W, I>(writer: &mut W, strs: I) -> IoResult<()> pub fn parse_update_count(tag: String) -> u64 { tag.split(' ').last().unwrap().parse().unwrap_or(0) } + +pub fn read_all(r: &mut R, mut buf: &mut [u8]) -> io::Result<()> { + let mut start = 0; + while start != buf.len() { + match r.read(&mut buf[start..]) { + Ok(0) => return Err(io::Error::new(io::ErrorKind::Other, "unexpected EOF", None)), + Ok(len) => start += len, + Err(e) => return Err(e), + } + } + Ok(()) +} diff --git a/tests/test.rs b/tests/test.rs index 995b0c5d..62a6bf86 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,4 +1,4 @@ -#![feature(core, std_misc, old_io)] +#![feature(core, std_misc, old_io, net)] extern crate postgres; extern crate "rustc-serialize" as serialize; @@ -79,6 +79,7 @@ fn test_connection_finish() { } #[test] +#[cfg_attr(not(feature = "unix_socket"), ignore)] fn test_unix_connection() { let conn = or_panic!(Connection::connect("postgres://postgres@localhost", &SslMode::None)); let stmt = or_panic!(conn.prepare("SHOW unix_socket_directories")); @@ -609,6 +610,7 @@ fn test_notifications_next_block() { }, or_panic!(notifications.next_block())); } +/* #[test] fn test_notifications_next_block_for() { let conn = or_panic!(Connection::connect("postgres://postgres@localhost", &SslMode::None)); @@ -648,6 +650,7 @@ fn test_notifications_next_block_for_timeout() { or_panic!(conn.execute("SELECT 1", &[])); } +*/ #[test] // This test is pretty sad, but I don't think there's a better way :( diff --git a/tests/types/mod.rs b/tests/types/mod.rs index 1f6ff8fb..e0715892 100644 --- a/tests/types/mod.rs +++ b/tests/types/mod.rs @@ -3,7 +3,7 @@ use std::f32; use std::f64; use std::fmt; use std::num::Float; -use std::old_io::net::ip::IpAddr; +use std::net::IpAddr; use postgres::{Connection, SslMode, Slice, Error}; use postgres::types::{ToSql, FromSql};