diff --git a/src/div.rs b/src/div.rs index 693460b..718c3a1 100644 --- a/src/div.rs +++ b/src/div.rs @@ -8,44 +8,7 @@ // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) -use std::ops::{Add, Sub, Div, Rem}; -use std::num::{Zero, One}; - -/// Same as `(a / b, a % b)`. -#[inline] -pub fn div_rem(a: T, b: T) -> (T, T) - where T: Copy + Div + Rem { - (a / b, a % b) -} - -/// Calculates a floored integer quotient. -#[inline] -pub fn div_floor(a: T, b: T) -> T - where T: Copy + Ord + Zero + One + - Add + Sub + Div + Rem { - div_mod_floor(a, b).0 -} - -/// Calculates a floored modulo. -#[inline] -pub fn mod_floor(a: T, b: T) -> T - where T: Copy + Ord + Zero + One + - Add + Sub + Div + Rem { - div_mod_floor(a, b).1 -} - -/// Calculates a floored integer quotient and modulo. -#[inline] -pub fn div_mod_floor(a: T, b: T) -> (T, T) - where T: Copy + Ord + Zero + One + - Add + Sub + Div + Rem { - let zero = Zero::zero(); - let one = One::one(); - match (a / b, a % b) { - (d, r) if (r > zero && b < zero) || (r < zero && b > zero) => (d - one, r + b), - (d, r) => (d, r), - } -} +pub use num::integer::{div_rem, div_floor, mod_floor, div_mod_floor}; #[cfg(test)] mod tests { diff --git a/src/format/parse.rs b/src/format/parse.rs index cfe75ce..dbd0f91 100644 --- a/src/format/parse.rs +++ b/src/format/parse.rs @@ -291,9 +291,9 @@ pub fn parse<'a, I>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<( LowerAmPm | UpperAmPm => { if s.len() < 2 { return Err(TOO_SHORT); } - let ampm = match [s.as_bytes()[0] | 32, s.as_bytes()[1] | 32] { - [b'a',b'm'] => false, - [b'p',b'm'] => true, + let ampm = match (s.as_bytes()[0] | 32, s.as_bytes()[1] | 32) { + (b'a',b'm') => false, + (b'p',b'm') => true, _ => return Err(INVALID) }; try!(parsed.set_ampm(ampm)); diff --git a/src/format/scan.rs b/src/format/scan.rs index c62efdc..0676fc1 100644 --- a/src/format/scan.rs +++ b/src/format/scan.rs @@ -6,16 +6,22 @@ * Various scanning routines for the parser. */ -use std::iter; - use Weekday; use super::{ParseResult, TOO_SHORT, INVALID, OUT_OF_RANGE}; /// Returns true when two slices are equal case-insensitively (in ASCII). /// Assumes that the `pattern` is already converted to lower case. fn equals(s: &str, pattern: &str) -> bool { - iter::order::equals(s.as_bytes().iter().map(|&c| match c { b'A'...b'Z' => c + 32, _ => c }), - pattern.as_bytes().iter().cloned()) + let mut xs = s.as_bytes().iter().map(|&c| match c { b'A'...b'Z' => c + 32, _ => c }); + let mut ys = pattern.as_bytes().iter().cloned(); + loop { + match (xs.next(), ys.next()) { + (None, None) => return true, + (None, _) | (_, None) => return false, + (Some(x), Some(y)) if x != y => return false, + _ => (), + } + } } /// Tries to parse the non-negative number from `min` to `max` digits. @@ -64,19 +70,19 @@ pub fn nanosecond(s: &str) -> ParseResult<(&str, i64)> { pub fn short_month0(s: &str) -> ParseResult<(&str, u8)> { if s.len() < 3 { return Err(TOO_SHORT); } let buf = s.as_bytes(); - let month0 = match [buf[0] | 32, buf[1] | 32, buf[2] | 32] { - [b'j',b'a',b'n'] => 0, - [b'f',b'e',b'b'] => 1, - [b'm',b'a',b'r'] => 2, - [b'a',b'p',b'r'] => 3, - [b'm',b'a',b'y'] => 4, - [b'j',b'u',b'n'] => 5, - [b'j',b'u',b'l'] => 6, - [b'a',b'u',b'g'] => 7, - [b's',b'e',b'p'] => 8, - [b'o',b'c',b't'] => 9, - [b'n',b'o',b'v'] => 10, - [b'd',b'e',b'c'] => 11, + let month0 = match (buf[0] | 32, buf[1] | 32, buf[2] | 32) { + (b'j',b'a',b'n') => 0, + (b'f',b'e',b'b') => 1, + (b'm',b'a',b'r') => 2, + (b'a',b'p',b'r') => 3, + (b'm',b'a',b'y') => 4, + (b'j',b'u',b'n') => 5, + (b'j',b'u',b'l') => 6, + (b'a',b'u',b'g') => 7, + (b's',b'e',b'p') => 8, + (b'o',b'c',b't') => 9, + (b'n',b'o',b'v') => 10, + (b'd',b'e',b'c') => 11, _ => return Err(INVALID) }; Ok((&s[3..], month0)) @@ -86,14 +92,14 @@ pub fn short_month0(s: &str) -> ParseResult<(&str, u8)> { pub fn short_weekday(s: &str) -> ParseResult<(&str, Weekday)> { if s.len() < 3 { return Err(TOO_SHORT); } let buf = s.as_bytes(); - let weekday = match [buf[0] | 32, buf[1] | 32, buf[2] | 32] { - [b'm',b'o',b'n'] => Weekday::Mon, - [b't',b'u',b'e'] => Weekday::Tue, - [b'w',b'e',b'd'] => Weekday::Wed, - [b't',b'h',b'u'] => Weekday::Thu, - [b'f',b'r',b'i'] => Weekday::Fri, - [b's',b'a',b't'] => Weekday::Sat, - [b's',b'u',b'n'] => Weekday::Sun, + let weekday = match (buf[0] | 32, buf[1] | 32, buf[2] | 32) { + (b'm',b'o',b'n') => Weekday::Mon, + (b't',b'u',b'e') => Weekday::Tue, + (b'w',b'e',b'd') => Weekday::Wed, + (b't',b'h',b'u') => Weekday::Thu, + (b'f',b'r',b'i') => Weekday::Fri, + (b's',b'a',b't') => Weekday::Sat, + (b's',b'u',b'n') => Weekday::Sun, _ => return Err(INVALID) }; Ok((&s[3..], weekday)) @@ -167,6 +173,14 @@ pub fn colon_or_space(s: &str) -> ParseResult<&str> { /// between hours and minutes, and should return either a new suffix or `Err` when parsing fails. pub fn timezone_offset(mut s: &str, mut colon: F) -> ParseResult<(&str, i32)> where F: FnMut(&str) -> ParseResult<&str> { + fn digits(s: &str) -> ParseResult<(u8, u8)> { + let b = s.as_bytes(); + if b.len() < 2 { + Err(TOO_SHORT) + } else { + Ok((b[0], b[1])) + } + } let negative = match s.as_bytes().first() { Some(&b'+') => false, Some(&b'-') => true, @@ -176,9 +190,8 @@ pub fn timezone_offset(mut s: &str, mut colon: F) -> ParseResult<(&str, i32)> s = &s[1..]; // hours (00--99) - let hours = match s.as_bytes() { - [h1 @ b'0'...b'9', h2 @ b'0'...b'9', ..] => ((h1 - b'0') * 10 + (h2 - b'0')) as i32, - [] | [_] => return Err(TOO_SHORT), + let hours = match try!(digits(s)) { + (h1 @ b'0'...b'9', h2 @ b'0'...b'9') => ((h1 - b'0') * 10 + (h2 - b'0')) as i32, _ => return Err(INVALID), }; s = &s[2..]; @@ -187,10 +200,9 @@ pub fn timezone_offset(mut s: &str, mut colon: F) -> ParseResult<(&str, i32)> s = try!(colon(s)); // minutes (00--59) - let minutes = match s.as_bytes() { - [m1 @ b'0'...b'5', m2 @ b'0'...b'9', ..] => ((m1 - b'0') * 10 + (m2 - b'0')) as i32, - [b'6'...b'9', b'0'...b'9', ..] => return Err(OUT_OF_RANGE), - [] | [_] => return Err(TOO_SHORT), + let minutes = match try!(digits(s)) { + (m1 @ b'0'...b'5', m2 @ b'0'...b'9') => ((m1 - b'0') * 10 + (m2 - b'0')) as i32, + (b'6'...b'9', b'0'...b'9') => return Err(OUT_OF_RANGE), _ => return Err(INVALID), }; s = &s[2..]; diff --git a/src/lib.rs b/src/lib.rs index d22db86..09b2dbe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,7 +100,6 @@ Addition and subtraction is also supported. The following illustrates most supported operations to the date and time: ~~~~ {.rust} -# #![feature(std_misc)] use chrono::*; # /* we intentionally fake the datetime... @@ -267,9 +266,7 @@ Advanced time zone handling is not yet supported (but is planned in 0.3). #![doc(html_root_url = "https://lifthrasiir.github.io/rust-chrono/")] -#![feature(slice_patterns)] -#![feature(core, std_misc, zero_one)] // lib stability features as per RFC #507 -#![cfg_attr(test, feature(test))] // ditto +#![cfg_attr(bench, feature(test))] // lib stability features as per RFC #507 #![deny(missing_docs)] extern crate time as stdtime; @@ -298,7 +295,7 @@ pub mod duration { //! //! This used to be a part of rust-chrono, //! but has been subsequently merged into Rust's standard library. - pub use std::time::duration::{MIN, MAX, Duration}; + pub use stdtime::Duration; } pub mod offset; pub mod naive { @@ -601,7 +598,7 @@ pub trait Timelike { #[test] fn test_readme_doomsday() { - use std::iter::range_inclusive; + use num::iter::range_inclusive; for y in range_inclusive(naive::date::MIN.year(), naive::date::MAX.year()) { // even months diff --git a/src/naive/date.rs b/src/naive/date.rs index 6531fd9..46e1cf1 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -1490,12 +1490,12 @@ mod internals { #[cfg(test)] mod tests { - extern crate test; + #[cfg(bench)] extern crate test; use Weekday; use super::{Of, Mdf}; use super::{YearFlags, A, B, C, D, E, F, G, AG, BA, CB, DC, ED, FE, GF}; - use std::iter::range_inclusive; + use num::iter::range_inclusive; use std::u32; const NONLEAP_FLAGS: [YearFlags; 7] = [A, B, C, D, E, F, G]; @@ -1537,6 +1537,7 @@ mod internals { assert_eq!(GF.nisoweeks(), 52); } + #[cfg(bench)] #[bench] fn bench_year_flags_from_year(bh: &mut test::Bencher) { bh.iter(|| {