diff --git a/.travis.yml b/.travis.yml index b634ecd..68eeb24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,9 @@ language: rust rust: - nightly - beta -- 1.26.0 +- 1.40.0 addons: postgresql: 9.4 script: - cargo test -- cargo test --features "with-time with-chrono" +- cargo test --features "with-chrono-0_4" diff --git a/Cargo.toml b/Cargo.toml index 2166895..9bda1bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,20 +2,19 @@ name = "postgres_range" version = "0.9.1" authors = ["Steven Fackler "] +edition = "2018" license = "MIT" description = "Range support for rust-postgres" repository = "https://github.com/sfackler/rust-postgres-range" documentation = "https://sfackler.github.io/rust-postgres-range/doc/v0.9.0/postgres_range" [features] -with-time = ["time", "postgres-shared/with-time"] -with-chrono = ["chrono", "postgres-shared/with-chrono"] +with-chrono-0_4 = ["chrono-04", "postgres-types/with-chrono-0_4"] [dependencies] -time = { version = "0.1", optional = true } -postgres-protocol = "0.3" -chrono = { version = "0.4.0", optional = true } -postgres-shared = "0.4.0" +postgres-protocol = "0.5" +postgres-types = "0.1" +chrono-04 = { version = "0.4", package = "chrono", optional = true } [dev-dependencies] -postgres = { version = "0.15", features = ["with-time"] } +postgres = { version = "0.17" } diff --git a/src/chrono_04.rs b/src/chrono_04.rs new file mode 100644 index 0000000..be9a741 --- /dev/null +++ b/src/chrono_04.rs @@ -0,0 +1,23 @@ +use chrono_04::{DateTime, NaiveDateTime, TimeZone}; + +use crate::{Normalizable, RangeBound, BoundSided}; + +impl Normalizable for DateTime + where T: TimeZone { + fn normalize(bound: RangeBound>) -> RangeBound> + where + S: BoundSided, + { + bound + } +} + +impl Normalizable for NaiveDateTime +{ + fn normalize(bound: RangeBound) -> RangeBound + where + S: BoundSided, + { + bound + } +} \ No newline at end of file diff --git a/src/impls.rs b/src/impls.rs index 567500f..19615e1 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -1,16 +1,17 @@ use std::error::Error; -use postgres_shared::types::{FromSql, IsNull, Kind, ToSql, Type}; +use postgres_types::{FromSql, IsNull, Kind, ToSql, Type}; +use postgres_types::private::BytesMut; use postgres_protocol::{self as protocol, types}; -use {BoundSided, BoundType, Normalizable, Range, RangeBound}; +use crate::{BoundSided, BoundType, Normalizable, Range, RangeBound}; -impl FromSql for Range +impl<'a, T> FromSql<'a> for Range where - T: PartialOrd + Normalizable + FromSql, + T: PartialOrd + Normalizable + FromSql<'a>, { - fn from_sql(ty: &Type, raw: &[u8]) -> Result, Box> { - let element_type = match ty.kind() { - &Kind::Range(ref ty) => ty, + fn from_sql(ty: &Type, raw: &'a [u8]) -> Result, Box> { + let element_type = match *ty.kind() { + Kind::Range(ref ty) => ty, _ => panic!("unexpected type {:?}", ty), }; @@ -25,16 +26,16 @@ where } fn accepts(ty: &Type) -> bool { - match ty.kind() { - &Kind::Range(ref inner) => ::accepts(inner), + match *ty.kind() { + Kind::Range(ref inner) => ::accepts(inner), _ => false, } } } -fn bound_from_sql(bound: types::RangeBound>, ty: &Type) -> Result>, Box> +fn bound_from_sql<'a, T, S>(bound: types::RangeBound>, ty: &Type) -> Result>, Box> where - T: PartialOrd + Normalizable + FromSql, + T: PartialOrd + Normalizable + FromSql<'a>, S: BoundSided, { match bound { @@ -60,9 +61,9 @@ impl ToSql for Range where T: PartialOrd + Normalizable + ToSql, { - fn to_sql(&self, ty: &Type, buf: &mut Vec) -> Result> { - let element_type = match ty.kind() { - &Kind::Range(ref ty) => ty, + fn to_sql(&self, ty: &Type, buf: &mut BytesMut) -> Result> { + let element_type = match *ty.kind() { + Kind::Range(ref ty) => ty, _ => panic!("unexpected type {:?}", ty), }; @@ -80,8 +81,8 @@ where } fn accepts(ty: &Type) -> bool { - match ty.kind() { - &Kind::Range(ref inner) => ::accepts(inner), + match *ty.kind() { + Kind::Range(ref inner) => ::accepts(inner), _ => false, } } @@ -89,7 +90,7 @@ where to_sql_checked!(); } -fn bound_to_sql(bound: Option<&RangeBound>, ty: &Type, buf: &mut Vec) -> Result, Box> +fn bound_to_sql(bound: Option<&RangeBound>, ty: &Type, buf: &mut BytesMut) -> Result, Box> where S: BoundSided, T: ToSql, @@ -114,10 +115,10 @@ where mod test { use std::fmt; - use postgres::{Connection, TlsMode}; + use postgres::{Client, NoTls}; use postgres::types::{FromSql, ToSql}; - #[cfg(feature = "with-time")] - use time::{self, Timespec}; + #[cfg(feature = "with-chrono-0_4")] + use chrono_04::{TimeZone, Utc, Duration}; macro_rules! test_range { ($name:expr, $t:ty, $low:expr, $low_str:expr, $high:expr, $high_str:expr) => ({ @@ -140,16 +141,21 @@ mod test { }) } - fn test_type(sql_type: &str, checks: &[(T, S)]) { - let conn = Connection::connect("postgres://postgres@localhost", TlsMode::None).unwrap(); + + fn test_type(sql_type: &str, checks: &[(T, S)]) + where for<'a> + T: Sync + PartialEq + FromSql<'a> + ToSql, + S: fmt::Display + { + let mut conn = Client::connect("postgres://postgres@localhost", NoTls).unwrap(); for &(ref val, ref repr) in checks { let stmt = conn.prepare(&*format!("SELECT {}::{}", *repr, sql_type)) .unwrap(); - let result = stmt.query(&[]).unwrap().iter().next().unwrap().get(0); + let result = conn.query(&stmt, &[]).unwrap().iter().next().unwrap().get(0); assert!(val == &result); let stmt = conn.prepare(&*format!("SELECT $1::{}", sql_type)).unwrap(); - let result = stmt.query(&[val]).unwrap().iter().next().unwrap().get(0); + let result = conn.query(&stmt, &[val]).unwrap().iter().next().unwrap().get(0); assert!(val == &result); } } @@ -164,25 +170,19 @@ mod test { test_range!("INT8RANGE", i64, 100i64, "100", 200i64, "200") } - #[cfg(feature = "with-time")] - fn test_timespec_range_params(sql_type: &str) { - fn t(time: &str) -> Timespec { - time::strptime(time, "%Y-%m-%d").unwrap().to_timespec() - } - let low = "1970-01-01"; - let high = "1980-01-01"; - test_range!(sql_type, Timespec, t(low), low, t(high), high); - } - #[test] - #[cfg(feature = "with-time")] + #[cfg(feature = "with-chrono-0_4")] fn test_tsrange_params() { - test_timespec_range_params("TSRANGE"); + let low = Utc.timestamp(0, 0); + let high = low + Duration::days(10); + test_range!("TSRANGE", NaiveDateTime, low.naive_utc(), "1970-01-01", high.naive_utc(), "1970-01-11"); } #[test] - #[cfg(feature = "with-time")] + #[cfg(feature = "with-chrono-0_4")] fn test_tstzrange_params() { - test_timespec_range_params("TSTZRANGE"); + let low = Utc.timestamp(0, 0); + let high = low + Duration::days(10); + test_range!("TSTZRANGE", DateTime, low, "1970-01-01", high, "1970-01-11"); } } diff --git a/src/lib.rs b/src/lib.rs index 300f543..f4d0c53 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,27 +1,18 @@ //! Types dealing with ranges of values #![doc(html_root_url = "https://sfackler.github.io/rust-postgres-range/doc/v0.9")] +#![warn(clippy::all, rust_2018_idioms, missing_docs)] -extern crate postgres_protocol; #[macro_use(to_sql_checked)] -extern crate postgres_shared; +extern crate postgres_types; -#[cfg(feature = "with-time")] -extern crate time; -#[cfg(feature = "with-chrono")] -extern crate chrono; +#[cfg(feature = "with-chrono-0_4")] +mod chrono_04; -#[cfg(test)] -extern crate postgres; - -#[cfg(feature = "with-chrono")] -use chrono::{DateTime, NaiveDateTime, TimeZone}; use std::cmp::Ordering; use std::fmt; use std::i32; use std::i64; use std::marker::PhantomData; -#[cfg(feature = "with-time")] -use time::Timespec; use BoundSide::{Lower, Upper}; use BoundType::{Exclusive, Inclusive}; @@ -155,38 +146,6 @@ macro_rules! bounded_normalizable { bounded_normalizable!(i32); bounded_normalizable!(i64); -#[cfg(feature = "with-time")] -impl Normalizable for Timespec { - fn normalize(bound: RangeBound) -> RangeBound - where - S: BoundSided, - { - bound - } -} - -#[cfg(feature = "with-chrono")] -impl Normalizable for DateTime - where T: TimeZone { - fn normalize(bound: RangeBound>) -> RangeBound> - where - S: BoundSided, - { - bound - } -} - -#[cfg(feature = "with-chrono")] -impl Normalizable for NaiveDateTime -{ - fn normalize(bound: RangeBound) -> RangeBound - where - S: BoundSided, - { - bound - } -} - /// The possible sides of a bound. #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum BoundSide { @@ -260,7 +219,7 @@ where fn clone(&self) -> RangeBound { RangeBound { value: self.value.clone(), - type_: self.type_.clone(), + type_: self.type_, _m: PhantomData, } } @@ -271,7 +230,7 @@ where S: BoundSided, T: fmt::Debug, { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("RangeBound") .field("value", &self.value) .field("type_", &self.type_) @@ -284,7 +243,7 @@ where S: BoundSided, T: fmt::Display, { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let (lower, upper) = match self.type_ { Inclusive => ('[', ']'), Exclusive => ('(', ')'), @@ -306,9 +265,9 @@ where self.value == other.value && self.type_ == other.type_ } - fn ne(&self, other: &RangeBound) -> bool { + /*fn ne(&self, other: &RangeBound) -> bool { self.value != other.value || self.type_ != other.type_ - } + }*/ } impl Eq for RangeBound @@ -364,8 +323,8 @@ where /// Constructs a new range bound pub fn new(value: T, type_: BoundType) -> RangeBound { RangeBound { - value: value, - type_: type_, + value, + type_, _m: PhantomData, } } @@ -381,7 +340,7 @@ where } } -struct OptBound<'a, S: 'a + BoundSided, T: 'a>(Option<&'a RangeBound>); +struct OptBound<'a, S: BoundSided, T>(Option<&'a RangeBound>); impl<'a, S, T> PartialEq for OptBound<'a, S, T> where @@ -393,10 +352,10 @@ where self_ == other } - fn ne(&self, &OptBound(ref other): &OptBound<'a, S, T>) -> bool { + /*fn ne(&self, &OptBound(ref other): &OptBound<'a, S, T>) -> bool { let &OptBound(ref self_) = self; self_ != other - } + }*/ } impl<'a, S, T> PartialOrd for OptBound<'a, S, T> @@ -433,7 +392,7 @@ impl fmt::Display for Range where T: fmt::Display, { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self.inner { Empty => write!(fmt, "empty"), Normal(ref lower, ref upper) => { @@ -558,7 +517,7 @@ where let (_, OptBound(lower)) = order(OptBound(self.lower()), OptBound(other.lower())); let (OptBound(upper), _) = order(OptBound(self.upper()), OptBound(other.upper())); - Range::new(lower.map(|v| v.clone()), upper.map(|v| v.clone())) + Range::new(lower.cloned(), upper.cloned()) } /// Returns the union of this range with another if it is contiguous. @@ -595,8 +554,8 @@ where None } else { Some(Range::new( - l_lower.map(|v| v.clone()), - u_upper.map(|v| v.clone()), + l_lower.cloned(), + u_upper.cloned(), )) } } @@ -758,7 +717,7 @@ mod test { assert_eq!(r1, (range!('(',; ')')).intersect(&r1)); let r2 = range!('(' 10i32,; ')'); - let exp = Range::new(r2.lower().map(|v| v.clone()), r1.upper().map(|v| v.clone())); + let exp = Range::new(r2.lower().copied(), r1.upper().copied()); assert_eq!(exp, r1.intersect(&r2)); assert_eq!(exp, r2.intersect(&r1));