From 9dc91f78ed9ebad77381a47d52daa72c34dfb0b3 Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Sat, 7 Sep 2019 12:12:49 +0200 Subject: [PATCH 01/15] Implement Support for no_std This adds a new `std` feature to chrono that is enabled by default. By deactivating this feature via `default-features = false` you can now use chrono in applications that don't use the standard library. The `serde` feature is supported as well. Resolves #336 --- Cargo.toml | 8 ++++---- ci/core-test/Cargo.toml | 11 +++++++++++ ci/core-test/src/lib.rs | 1 + ci/travis.sh | 10 ++++++++++ src/date.rs | 6 +++--- src/datetime.rs | 32 ++++++++++++++++++++------------ src/format/mod.rs | 39 +++++++++++++++++++++++++-------------- src/format/parse.rs | 2 +- src/lib.rs | 15 +++++++++++++-- src/naive/date.rs | 12 +++++++----- src/naive/datetime.rs | 20 ++++++++++++++------ src/naive/internals.rs | 2 +- src/naive/isoweek.rs | 2 +- src/naive/time.rs | 12 +++++++----- src/offset/fixed.rs | 4 ++-- src/offset/mod.rs | 2 +- src/offset/utc.rs | 2 +- src/oldtime.rs | 16 ++++++++++++---- src/round.rs | 2 +- 19 files changed, 135 insertions(+), 63 deletions(-) create mode 100644 ci/core-test/Cargo.toml create mode 100644 ci/core-test/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 5185872..7893ecb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,17 +24,17 @@ appveyor = { repository = "chronotope/chrono" } name = "chrono" [features] -default = ["clock"] -clock = ["time"] +default = ["clock", "std"] +std = [] +clock = ["time", "std"] wasmbind = ["wasm-bindgen", "js-sys"] [dependencies] -libc = { version = "0.2", default-features = false } time = { version = "0.1.39", optional = true } num-integer = { version = "0.1.36", default-features = false } num-traits = { version = "0.2", default-features = false } rustc-serialize = { version = "0.3.20", optional = true } -serde = { version = "1", optional = true } +serde = { version = "1.0.99", default-features = false, optional = true } [target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] wasm-bindgen = { version = "0.2", optional = true } diff --git a/ci/core-test/Cargo.toml b/ci/core-test/Cargo.toml new file mode 100644 index 0000000..ad75e16 --- /dev/null +++ b/ci/core-test/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "core-test" +version = "0.1.0" +authors = [ + "Kang Seonghoon ", + "Brandon W Maister ", +] +edition = "2018" + +[dependencies] +chrono = { path = "../..", default-features = false, features = ["serde"] } diff --git a/ci/core-test/src/lib.rs b/ci/core-test/src/lib.rs new file mode 100644 index 0000000..0c9ac1a --- /dev/null +++ b/ci/core-test/src/lib.rs @@ -0,0 +1 @@ +#![no_std] diff --git a/ci/travis.sh b/ci/travis.sh index 98e25ce..809f234 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -85,6 +85,13 @@ build_only() { channel build -v --no-default-features } +build_core_test() { + rustup target add thumbv6m-none-eabi --toolchain $CHANNEL + cd ci/core-test + channel build -v --target thumbv6m-none-eabi + cd ../.. +} + run_clippy() { # cached installation will not work on a later nightly if [ -n "${TRAVIS}" ] && ! cargo install clippy --debug --force; then @@ -119,3 +126,6 @@ build_and_test CHANNEL=1.13.0 build_only + +CHANNEL=stable +build_core_test diff --git a/src/date.rs b/src/date.rs index f8b59ce..a6e5ab8 100644 --- a/src/date.rs +++ b/src/date.rs @@ -3,9 +3,9 @@ //! ISO 8601 calendar date with time zone. -use std::{fmt, hash}; -use std::cmp::Ordering; -use std::ops::{Add, Sub}; +use core::{fmt, hash}; +use core::cmp::Ordering; +use core::ops::{Add, Sub}; use oldtime::Duration as OldDuration; use {Weekday, Datelike}; diff --git a/src/datetime.rs b/src/datetime.rs index b4881bf..75a6922 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -3,12 +3,16 @@ //! ISO 8601 date and time with time zone. -use std::{str, fmt, hash}; -use std::cmp::Ordering; -use std::ops::{Add, Sub}; +use core::{str, fmt, hash}; +use core::cmp::Ordering; +use core::ops::{Add, Sub}; +#[cfg(any(feature = "std", test))] use std::time::{SystemTime, UNIX_EPOCH}; use oldtime::Duration as OldDuration; +#[cfg(not(any(feature = "std", test)))] +use alloc::string::{String, ToString}; + use {Weekday, Timelike, Datelike}; #[cfg(feature="clock")] use offset::Local; @@ -647,6 +651,7 @@ impl str::FromStr for DateTime { } } +#[cfg(any(feature = "std", test))] impl From for DateTime { fn from(t: SystemTime) -> DateTime { let (sec, nsec) = match t.duration_since(UNIX_EPOCH) { @@ -672,6 +677,7 @@ impl From for DateTime { } } +#[cfg(any(feature = "std", test))] impl From> for SystemTime { fn from(dt: DateTime) -> SystemTime { use std::time::Duration; @@ -699,7 +705,7 @@ fn test_auto_conversion() { fn test_encodable_json(to_string_utc: FUtc, to_string_fixed: FFixed) where FUtc: Fn(&DateTime) -> Result, FFixed: Fn(&DateTime) -> Result, - E: ::std::fmt::Debug + E: ::core::fmt::Debug { assert_eq!(to_string_utc(&Utc.ymd(2014, 7, 24).and_hms(12, 34, 6)).ok(), Some(r#""2014-07-24T12:34:06Z""#.into())); @@ -717,7 +723,7 @@ fn test_decodable_json(utc_from_str: FUtc, where FUtc: Fn(&str) -> Result, E>, FFixed: Fn(&str) -> Result, E>, FLocal: Fn(&str) -> Result, E>, - E: ::std::fmt::Debug + E: ::core::fmt::Debug { // should check against the offset as well (the normal DateTime comparison will ignore them) fn norm(dt: &Option>) -> Option<(&DateTime, &Tz::Offset)> { @@ -754,7 +760,7 @@ fn test_decodable_json_timestamps(utc_from_str: FUtc, where FUtc: Fn(&str) -> Result, E>, FFixed: Fn(&str) -> Result, E>, FLocal: Fn(&str) -> Result, E>, - E: ::std::fmt::Debug + E: ::core::fmt::Debug { fn norm(dt: &Option>) -> Option<(&DateTime, &Tz::Offset)> { dt.as_ref().map(|dt| (dt, dt.offset())) @@ -778,8 +784,8 @@ fn test_decodable_json_timestamps(utc_from_str: FUtc, #[cfg(feature = "rustc-serialize")] pub mod rustc_serialize { - use std::fmt; - use std::ops::Deref; + use core::fmt; + use core::ops::Deref; use super::DateTime; #[cfg(feature="clock")] use offset::Local; @@ -907,7 +913,9 @@ pub mod rustc_serialize { /// documented at re-export site #[cfg(feature = "serde")] pub mod serde { - use std::fmt; + use core::fmt; + #[cfg(not(any(feature = "std", test)))] + use alloc::format; use super::DateTime; #[cfg(feature="clock")] use offset::Local; @@ -967,7 +975,7 @@ pub mod serde { /// # fn main() { example().unwrap(); } /// ``` pub mod ts_nanoseconds { - use std::fmt; + use core::fmt; use serdelib::{ser, de}; use {DateTime, Utc}; @@ -1114,7 +1122,7 @@ pub mod serde { /// # fn main() { example().unwrap(); } /// ``` pub mod ts_milliseconds { - use std::fmt; + use core::fmt; use serdelib::{ser, de}; use {DateTime, Utc}; @@ -1261,7 +1269,7 @@ pub mod serde { /// # fn main() { example().unwrap(); } /// ``` pub mod ts_seconds { - use std::fmt; + use core::fmt; use serdelib::{ser, de}; use {DateTime, Utc}; diff --git a/src/format/mod.rs b/src/format/mod.rs index 24647b4..e4e6776 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -17,9 +17,13 @@ #![allow(ellipsis_inclusive_range_patterns)] -use std::fmt; -use std::str::FromStr; +use core::fmt; +use core::str::FromStr; +#[cfg(any(feature = "std", test))] use std::error::Error; +use alloc::boxed::Box; +#[cfg(not(any(feature = "std", test)))] +use alloc::string::{String, ToString}; use {Datelike, Timelike, Weekday, ParseWeekdayError}; use div::{div_floor, mod_floor}; @@ -30,7 +34,7 @@ pub use self::strftime::StrftimeItems; pub use self::parsed::Parsed; pub use self::parse::parse; -/// An unhabitated type used for `InternalNumeric` and `InternalFixed` below. +/// An uninhabited type used for `InternalNumeric` and `InternalFixed` below. #[derive(Clone, PartialEq, Eq)] enum Void {} @@ -55,7 +59,7 @@ pub enum Pad { /// /// The **parsing width** is the maximal width to be scanned. /// The parser only tries to consume from one to given number of digits (greedily). -/// It also trims the preceding whitespaces if any. +/// It also trims the preceding whitespace if any. /// It cannot parse the negative number, so some date and time cannot be formatted then /// parsed with the same formatting items. #[derive(Clone, PartialEq, Eq, Debug)] @@ -185,13 +189,13 @@ pub enum Fixed { TimezoneName, /// Offset from the local time to UTC (`+09:00` or `-04:00` or `+00:00`). /// - /// In the parser, the colon can be omitted and/or surrounded with any amount of whitespaces. + /// In the parser, the colon can be omitted and/or surrounded with any amount of whitespace. /// The offset is limited from `-24:00` to `+24:00`, /// which is same to [`FixedOffset`](../offset/struct.FixedOffset.html)'s range. TimezoneOffsetColon, /// Offset from the local time to UTC (`+09:00` or `-04:00` or `Z`). /// - /// In the parser, the colon can be omitted and/or surrounded with any amount of whitespaces, + /// In the parser, the colon can be omitted and/or surrounded with any amount of whitespace, /// and `Z` can be either in upper case or in lower case. /// The offset is limited from `-24:00` to `+24:00`, /// which is same to [`FixedOffset`](../offset/struct.FixedOffset.html)'s range. @@ -305,13 +309,7 @@ enum ParseErrorKind { /// Same to `Result`. pub type ParseResult = Result; -impl fmt::Display for ParseError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -impl Error for ParseError { +impl ParseError { fn description(&self) -> &str { match self.0 { ParseErrorKind::OutOfRange => "input is out of range", @@ -325,6 +323,19 @@ impl Error for ParseError { } } +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} + +#[cfg(any(feature = "std", test))] +impl Error for ParseError { + fn description(&self) -> &str { + self.description() + } +} + // to be used in this module and submodules const OUT_OF_RANGE: ParseError = ParseError(ParseErrorKind::OutOfRange); const IMPOSSIBLE: ParseError = ParseError(ParseErrorKind::Impossible); @@ -356,7 +367,7 @@ pub fn format<'a, I>( static LONG_WEEKDAYS: [&'static str; 7] = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]; - use std::fmt::Write; + use core::fmt::Write; let mut result = String::new(); for item in items { diff --git a/src/format/parse.rs b/src/format/parse.rs index 01e326e..c10a802 100644 --- a/src/format/parse.rs +++ b/src/format/parse.rs @@ -6,7 +6,7 @@ #![allow(deprecated)] -use std::usize; +use core::usize; use Weekday; diff --git a/src/lib.rs b/src/lib.rs index b43fa0d..704f3b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -387,6 +387,8 @@ #![deny(missing_docs)] #![deny(missing_debug_implementations)] +#![cfg_attr(not(any(feature = "std", test)), no_std)] + // The explicit 'static lifetimes are still needed for rustc 1.13-16 // backward compatibility, and this appeases clippy. If minimum rustc // becomes 1.17, should be able to remove this, those 'static lifetimes, @@ -403,6 +405,13 @@ trivially_copy_pass_by_ref, ))] +#[cfg(not(any(feature = "std", test)))] +extern crate alloc; +#[cfg(any(feature = "std", test))] +extern crate std as core; +#[cfg(any(feature = "std", test))] +extern crate std as alloc; + #[cfg(feature="clock")] extern crate time as oldtime; extern crate num_integer; @@ -678,7 +687,7 @@ impl num_traits::FromPrimitive for Weekday { } } -use std::fmt; +use core::fmt; /// An error resulting from reading `Weekday` value with `FromStr`. #[derive(Clone, PartialEq)] @@ -697,7 +706,9 @@ impl fmt::Debug for ParseWeekdayError { #[cfg(feature = "serde")] mod weekday_serde { use super::Weekday; - use std::fmt; + use core::fmt; + #[cfg(not(any(feature = "std", test)))] + use alloc::format; use serdelib::{ser, de}; impl ser::Serialize for Weekday { diff --git a/src/naive/date.rs b/src/naive/date.rs index aad98bc..f429597 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -3,8 +3,8 @@ //! ISO 8601 calendar date without timezone. -use std::{str, fmt}; -use std::ops::{Add, Sub, AddAssign, SubAssign}; +use core::{str, fmt}; +use core::ops::{Add, Sub, AddAssign, SubAssign}; use num_traits::ToPrimitive; use oldtime::Duration as OldDuration; @@ -1387,7 +1387,7 @@ impl SubAssign for NaiveDate { /// Subtracts another `NaiveDate` from the current date. /// Returns a `Duration` of integral numbers. -/// +/// /// This does not overflow or underflow at all, /// as all possible output fits in the range of `Duration`. /// @@ -1600,7 +1600,9 @@ mod rustc_serialize { #[cfg(feature = "serde")] mod serde { - use std::fmt; + use core::fmt; + #[cfg(not(any(feature = "std", test)))] + use alloc::format; use super::NaiveDate; use serdelib::{ser, de}; @@ -1629,7 +1631,7 @@ mod serde { impl<'de> de::Visitor<'de> for NaiveDateVisitor { type Value = NaiveDate; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a formatted date string") } diff --git a/src/naive/datetime.rs b/src/naive/datetime.rs index bb9ff8d..6f4fbe7 100644 --- a/src/naive/datetime.rs +++ b/src/naive/datetime.rs @@ -3,8 +3,8 @@ //! ISO 8601 date and time without timezone. -use std::{str, fmt, hash}; -use std::ops::{Add, Sub, AddAssign, SubAssign}; +use core::{str, fmt, hash}; +use core::ops::{Add, Sub, AddAssign, SubAssign}; use num_traits::ToPrimitive; use oldtime::Duration as OldDuration; @@ -1663,7 +1663,9 @@ pub mod rustc_serialize { /// Tools to help serializing/deserializing `NaiveDateTime`s #[cfg(feature = "serde")] pub mod serde { - use std::fmt; + use core::fmt; + #[cfg(not(any(feature = "std", test)))] + use alloc::format; use super::{NaiveDateTime}; use serdelib::{ser, de}; @@ -1750,7 +1752,9 @@ pub mod serde { /// # fn main() { example().unwrap(); } /// ``` pub mod ts_nanoseconds { - use std::fmt; + use core::fmt; + #[cfg(not(any(feature = "std", test)))] + use alloc::format; use serdelib::{ser, de}; use NaiveDateTime; @@ -1895,7 +1899,9 @@ pub mod serde { /// # fn main() { example().unwrap(); } /// ``` pub mod ts_milliseconds { - use std::fmt; + use core::fmt; + #[cfg(not(any(feature = "std", test)))] + use alloc::format; use serdelib::{ser, de}; use NaiveDateTime; @@ -2040,7 +2046,9 @@ pub mod serde { /// # fn main() { example().unwrap(); } /// ``` pub mod ts_seconds { - use std::fmt; + use core::fmt; + #[cfg(not(any(feature = "std", test)))] + use alloc::format; use serdelib::{ser, de}; use NaiveDateTime; diff --git a/src/naive/internals.rs b/src/naive/internals.rs index dd9d535..a1cd1f6 100644 --- a/src/naive/internals.rs +++ b/src/naive/internals.rs @@ -15,7 +15,7 @@ #![allow(dead_code)] // some internal methods have been left for consistency -use std::{i32, fmt}; +use core::{i32, fmt}; use num_traits::FromPrimitive; use Weekday; use div::{div_rem, mod_floor}; diff --git a/src/naive/isoweek.rs b/src/naive/isoweek.rs index 667cf2f..0aeedb0 100644 --- a/src/naive/isoweek.rs +++ b/src/naive/isoweek.rs @@ -3,7 +3,7 @@ //! ISO 8601 week. -use std::fmt; +use core::fmt; use super::internals::{DateImpl, Of, YearFlags}; diff --git a/src/naive/time.rs b/src/naive/time.rs index 440c8a7..c1cf297 100644 --- a/src/naive/time.rs +++ b/src/naive/time.rs @@ -3,8 +3,8 @@ //! ISO 8601 time without timezone. -use std::{str, fmt, hash}; -use std::ops::{Add, Sub, AddAssign, SubAssign}; +use core::{str, fmt, hash}; +use core::ops::{Add, Sub, AddAssign, SubAssign}; use oldtime::Duration as OldDuration; use Timelike; @@ -681,7 +681,7 @@ impl NaiveTime { // `rhs.frac`|========================================>| // | | | `self - rhs` | | - use std::cmp::Ordering; + use core::cmp::Ordering; let secs = i64::from(self.secs) - i64::from(rhs.secs); let frac = i64::from(self.frac) - i64::from(rhs.frac); @@ -1411,7 +1411,9 @@ mod rustc_serialize { #[cfg(feature = "serde")] mod serde { - use std::fmt; + use core::fmt; + #[cfg(not(any(feature = "std", test)))] + use alloc::format; use super::NaiveTime; use serdelib::{ser, de}; @@ -1431,7 +1433,7 @@ mod serde { impl<'de> de::Visitor<'de> for NaiveTimeVisitor { type Value = NaiveTime; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a formatted time string") } diff --git a/src/offset/fixed.rs b/src/offset/fixed.rs index 5b69ef0..01512c0 100644 --- a/src/offset/fixed.rs +++ b/src/offset/fixed.rs @@ -3,8 +3,8 @@ //! The time zone which has a fixed offset from UTC. -use std::ops::{Add, Sub}; -use std::fmt; +use core::ops::{Add, Sub}; +use core::fmt; use oldtime::Duration as OldDuration; use Timelike; diff --git a/src/offset/mod.rs b/src/offset/mod.rs index 566e427..a255292 100644 --- a/src/offset/mod.rs +++ b/src/offset/mod.rs @@ -18,7 +18,7 @@ //! and provides implementations for 1 and 3. //! An `TimeZone` instance can be reconstructed from the corresponding `Offset` instance. -use std::fmt; +use core::fmt; use format::{parse, ParseResult, Parsed, StrftimeItems}; use naive::{NaiveDate, NaiveDateTime, NaiveTime}; diff --git a/src/offset/utc.rs b/src/offset/utc.rs index 87a4fba..da8de11 100644 --- a/src/offset/utc.rs +++ b/src/offset/utc.rs @@ -3,7 +3,7 @@ //! The UTC (Coordinated Universal Time) time zone. -use std::fmt; +use core::fmt; #[cfg(all(feature="clock", not(all(target_arch = "wasm32", feature = "wasmbind"))))] use oldtime; diff --git a/src/oldtime.rs b/src/oldtime.rs index 2bdc2f6..d523b54 100644 --- a/src/oldtime.rs +++ b/src/oldtime.rs @@ -10,10 +10,11 @@ //! Temporal quantification -use std::{fmt, i64}; +use core::{fmt, i64}; +#[cfg(any(feature = "std", test))] use std::error::Error; -use std::ops::{Add, Sub, Mul, Div, Neg}; -use std::time::Duration as StdDuration; +use core::ops::{Add, Sub, Mul, Div, Neg}; +use core::time::Duration as StdDuration; /// The number of nanoseconds in a microsecond. const NANOS_PER_MICRO: i32 = 1000; @@ -392,15 +393,22 @@ impl fmt::Display for Duration { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct OutOfRangeError(()); +impl OutOfRangeError { + fn description(&self) -> &str { + "Source duration value is out of range for the target type" + } +} + impl fmt::Display for OutOfRangeError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.description()) } } +#[cfg(any(feature = "std", test))] impl Error for OutOfRangeError { fn description(&self) -> &str { - "Source duration value is out of range for the target type" + self.description() } } diff --git a/src/round.rs b/src/round.rs index bf62762..ac5b984 100644 --- a/src/round.rs +++ b/src/round.rs @@ -2,7 +2,7 @@ // See README.md and LICENSE.txt for details. use Timelike; -use std::ops::{Add, Sub}; +use core::ops::{Add, Sub}; use oldtime::Duration; /// Extension trait for subsecond rounding or truncation to a maximum number From 5ccec02e54c3455dd297742b9dcc641ff869446f Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Sat, 7 Sep 2019 12:20:52 +0200 Subject: [PATCH 02/15] Use std in all other tests on CI --- ci/travis.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ci/travis.sh b/ci/travis.sh index 809f234..0f31fb2 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -54,14 +54,14 @@ build_and_test_nonwasm() { TZ=Asia/Katmandu channel test -v --features serde,rustc-serialize # without default "clock" feature - channel build -v --no-default-features + channel build -v --no-default-features --features std TZ=ACST-9:30 channel test -v --no-default-features --lib - channel build -v --no-default-features --features rustc-serialize + channel build -v --no-default-features --features std,rustc-serialize TZ=EST4 channel test -v --no-default-features --features rustc-serialize --lib - channel build -v --no-default-features --features serde + channel build -v --no-default-features --features std,serde TZ=UTC0 channel test -v --no-default-features --features serde --lib - channel build -v --no-default-features --features serde,rustc-serialize - TZ=Asia/Katmandu channel test -v --no-default-features --features serde,rustc-serialize --lib + channel build -v --no-default-features --features std,serde,rustc-serialize + TZ=Asia/Katmandu channel test -v --no-default-features --features std,serde,rustc-serialize --lib } build_and_test_wasm() { @@ -82,7 +82,7 @@ build_only() { channel build -v channel build -v --features rustc-serialize channel build -v --features 'serde bincode' - channel build -v --no-default-features + channel build -v --no-default-features --features std } build_core_test() { From e62a054cd9797d7a5c6b14144b7b7790060f2cc1 Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Mon, 9 Sep 2019 13:41:44 +0200 Subject: [PATCH 03/15] Introduce an `alloc` feature --- Cargo.toml | 4 +++- README.md | 2 +- ci/core-test/Cargo.toml | 3 +++ ci/travis.sh | 24 +++++++++++------------- src/date.rs | 5 ++++- src/datetime.rs | 13 ++++++++++--- src/format/mod.rs | 38 ++++++++++++++++++++++++++++++++++++-- src/lib.rs | 8 ++++---- src/naive/date.rs | 8 ++++++-- src/naive/datetime.rs | 8 ++++++-- src/naive/time.rs | 8 ++++++-- 11 files changed, 90 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7893ecb..d252cbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,9 @@ name = "chrono" [features] default = ["clock", "std"] +alloc = [] std = [] +serde-1 = ["serde", "alloc"] clock = ["time", "std"] wasmbind = ["wasm-bindgen", "js-sys"] @@ -34,7 +36,7 @@ time = { version = "0.1.39", optional = true } num-integer = { version = "0.1.36", default-features = false } num-traits = { version = "0.2", default-features = false } rustc-serialize = { version = "0.3.20", optional = true } -serde = { version = "1.0.99", default-features = false, optional = true } +serde = { version = "1.0.99", default-features = false, features = ["alloc"], optional = true } [target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] wasm-bindgen = { version = "0.2", optional = true } diff --git a/README.md b/README.md index 6401210..26b1a48 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ feature like this: ```toml [dependencies] -chrono = { version = "0.4", features = ["serde"] } +chrono = { version = "0.4", features = ["serde-1"] } ``` Then put this in your crate root: diff --git a/ci/core-test/Cargo.toml b/ci/core-test/Cargo.toml index ad75e16..b35ff9a 100644 --- a/ci/core-test/Cargo.toml +++ b/ci/core-test/Cargo.toml @@ -9,3 +9,6 @@ edition = "2018" [dependencies] chrono = { path = "../..", default-features = false, features = ["serde"] } + +[features] +alloc = ["chrono/alloc"] \ No newline at end of file diff --git a/ci/travis.sh b/ci/travis.sh index 0f31fb2..0145357 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -48,20 +48,20 @@ build_and_test_nonwasm() { TZ=ACST-9:30 channel test -v --lib channel build -v --features rustc-serialize TZ=EST4 channel test -v --features rustc-serialize --lib - channel build -v --features serde - TZ=UTC0 channel test -v --features serde --lib - channel build -v --features serde,rustc-serialize - TZ=Asia/Katmandu channel test -v --features serde,rustc-serialize + channel build -v --features serde-1 + TZ=UTC0 channel test -v --features serde-1 --lib + channel build -v --features serde-1,rustc-serialize + TZ=Asia/Katmandu channel test -v --features serde-1,rustc-serialize # without default "clock" feature channel build -v --no-default-features --features std TZ=ACST-9:30 channel test -v --no-default-features --lib channel build -v --no-default-features --features std,rustc-serialize TZ=EST4 channel test -v --no-default-features --features rustc-serialize --lib - channel build -v --no-default-features --features std,serde - TZ=UTC0 channel test -v --no-default-features --features serde --lib - channel build -v --no-default-features --features std,serde,rustc-serialize - TZ=Asia/Katmandu channel test -v --no-default-features --features std,serde,rustc-serialize --lib + channel build -v --no-default-features --features std,serde-1 + TZ=UTC0 channel test -v --no-default-features --features serde-1 --lib + channel build -v --no-default-features --features std,serde-1,rustc-serialize + TZ=Asia/Katmandu channel test -v --no-default-features --features std,serde-1,rustc-serialize --lib } build_and_test_wasm() { @@ -81,7 +81,7 @@ build_only() { cargo clean channel build -v channel build -v --features rustc-serialize - channel build -v --features 'serde bincode' + channel build -v --features 'serde-1 bincode' channel build -v --no-default-features --features std } @@ -99,7 +99,7 @@ run_clippy() { exit fi - cargo clippy --features 'serde bincode rustc-serialize' -- -Dclippy + cargo clippy --features 'serde-1 bincode rustc-serialize' -- -Dclippy } check_readme() { @@ -123,9 +123,7 @@ build_and_test CHANNEL=stable build_and_test +build_core_test CHANNEL=1.13.0 build_only - -CHANNEL=stable -build_core_test diff --git a/src/date.rs b/src/date.rs index a6e5ab8..d449009 100644 --- a/src/date.rs +++ b/src/date.rs @@ -12,7 +12,8 @@ use {Weekday, Datelike}; use offset::{TimeZone, Utc}; use naive::{self, NaiveDate, NaiveTime, IsoWeek}; use DateTime; -use format::{Item, DelayedFormat, StrftimeItems}; +#[cfg(any(feature = "alloc", feature = "std", test))] +use format::{DelayedFormat, Item, StrftimeItems}; /// ISO 8601 calendar date with time zone. /// @@ -255,6 +256,7 @@ fn map_local(d: &Date, mut f: F) -> Option> impl Date where Tz::Offset: fmt::Display { /// Formats the date with the specified formatting items. + #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat where I: Iterator> + Clone { @@ -264,6 +266,7 @@ impl Date where Tz::Offset: fmt::Display { /// Formats the date with the specified format string. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. + #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { self.format_with_items(StrftimeItems::new(fmt)) diff --git a/src/datetime.rs b/src/datetime.rs index 75a6922..6adec62 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -10,7 +10,7 @@ use core::ops::{Add, Sub}; use std::time::{SystemTime, UNIX_EPOCH}; use oldtime::Duration as OldDuration; -#[cfg(not(any(feature = "std", test)))] +#[cfg(any(feature = "alloc", feature = "std", test))] use alloc::string::{String, ToString}; use {Weekday, Timelike, Datelike}; @@ -20,7 +20,9 @@ use offset::{TimeZone, Offset, Utc, FixedOffset}; use naive::{NaiveTime, NaiveDateTime, IsoWeek}; use Date; use format::{Item, Numeric, Pad, Fixed}; -use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems}; +use format::{parse, Parsed, ParseError, ParseResult, StrftimeItems}; +#[cfg(any(feature = "alloc", feature = "std", test))] +use format::DelayedFormat; /// Specific formatting options for seconds. This may be extended in the /// future, so exhaustive matching in external code is not recommended. @@ -367,12 +369,14 @@ impl DateTime { impl DateTime where Tz::Offset: fmt::Display { /// Returns an RFC 2822 date and time string such as `Tue, 1 Jul 2003 10:52:37 +0200`. + #[cfg(any(feature = "alloc", feature = "std", test))] pub fn to_rfc2822(&self) -> String { const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC2822)]; self.format_with_items(ITEMS.iter().cloned()).to_string() } /// Returns an RFC 3339 and ISO 8601 date and time string such as `1996-12-19T16:39:57-08:00`. + #[cfg(any(feature = "alloc", feature = "std", test))] pub fn to_rfc3339(&self) -> String { const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC3339)]; self.format_with_items(ITEMS.iter().cloned()).to_string() @@ -402,6 +406,7 @@ impl DateTime where Tz::Offset: fmt::Display { /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true), /// "2018-01-26T10:30:09+08:00"); /// ``` + #[cfg(any(feature = "alloc", feature = "std", test))] pub fn to_rfc3339_opts(&self, secform: SecondsFormat, use_z: bool) -> String { use format::Numeric::*; use format::Pad::Zero; @@ -453,6 +458,7 @@ impl DateTime where Tz::Offset: fmt::Display { } /// Formats the combined date and time with the specified formatting items. + #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat where I: Iterator> + Clone { @@ -463,6 +469,7 @@ impl DateTime where Tz::Offset: fmt::Display { /// Formats the combined date and time with the specified format string. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. + #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { self.format_with_items(StrftimeItems::new(fmt)) @@ -911,7 +918,7 @@ pub mod rustc_serialize { } /// documented at re-export site -#[cfg(feature = "serde")] +#[cfg(feature = "serde-1")] pub mod serde { use core::fmt; #[cfg(not(any(feature = "std", test)))] diff --git a/src/format/mod.rs b/src/format/mod.rs index e4e6776..fb05c93 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -21,13 +21,43 @@ use core::fmt; use core::str::FromStr; #[cfg(any(feature = "std", test))] use std::error::Error; +#[cfg(any(feature = "alloc", feature = "std", test))] use alloc::boxed::Box; -#[cfg(not(any(feature = "std", test)))] +#[cfg(any(feature = "alloc", feature = "std", test))] use alloc::string::{String, ToString}; -use {Datelike, Timelike, Weekday, ParseWeekdayError}; +#[cfg(not(any(feature = "alloc", feature = "std", test)))] +mod core_only { + /// Core only + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] + pub struct Box(core::marker::PhantomData); + + impl Box { + /// Core only + pub fn len(&self) -> usize { 0 } + } + + impl Clone for Box { fn clone(&self) -> Self { Box(core::marker::PhantomData) } } + + impl core::ops::Index for Box { + type Output = str; + fn index(&self, _: core::ops::RangeFull) -> &Self::Output { + "" + } + } +} + +#[cfg(not(any(feature = "alloc", feature = "std", test)))] +use self::core_only::Box; + +#[cfg(any(feature = "alloc", feature = "std", test))] +use {Datelike, Timelike}; +use {Weekday, ParseWeekdayError}; +#[cfg(any(feature = "alloc", feature = "std", test))] use div::{div_floor, mod_floor}; +#[cfg(any(feature = "alloc", feature = "std", test))] use offset::{Offset, FixedOffset}; +#[cfg(any(feature = "alloc", feature = "std", test))] use naive::{NaiveDate, NaiveTime}; pub use self::strftime::StrftimeItems; @@ -347,6 +377,7 @@ const BAD_FORMAT: ParseError = ParseError(ParseErrorKind::BadFormat); /// Tries to format given arguments with given formatting items. /// Internally used by `DelayedFormat`. +#[cfg(any(feature = "alloc", feature = "std", test))] pub fn format<'a, I>( w: &mut fmt::Formatter, date: Option<&NaiveDate>, @@ -609,6 +640,7 @@ pub mod strftime; /// A *temporary* object which can be used as an argument to `format!` or others. /// This is normally constructed via `format` methods of each date and time type. +#[cfg(any(feature = "alloc", feature = "std", test))] #[derive(Debug)] pub struct DelayedFormat { /// The date view, if any. @@ -621,6 +653,7 @@ pub struct DelayedFormat { items: I, } +#[cfg(any(feature = "alloc", feature = "std", test))] impl<'a, I: Iterator> + Clone> DelayedFormat { /// Makes a new `DelayedFormat` value out of local date and time. pub fn new(date: Option, time: Option, items: I) -> DelayedFormat { @@ -636,6 +669,7 @@ impl<'a, I: Iterator> + Clone> DelayedFormat { } } +#[cfg(any(feature = "alloc", feature = "std", test))] impl<'a, I: Iterator> + Clone> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) diff --git a/src/lib.rs b/src/lib.rs index 704f3b0..b7f60b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -418,7 +418,7 @@ extern crate num_integer; extern crate num_traits; #[cfg(feature = "rustc-serialize")] extern crate rustc_serialize; -#[cfg(feature = "serde")] +#[cfg(feature = "serde-1")] extern crate serde as serdelib; #[cfg(test)] #[macro_use] @@ -497,7 +497,7 @@ pub mod naive { /// /// [1]: https://serde.rs/attributes.html#field-attributes /// [2]: https://tools.ietf.org/html/rfc3339 - #[cfg(feature = "serde")] + #[cfg(feature = "serde-1")] pub mod serde { pub use super::datetime::serde::*; } @@ -515,7 +515,7 @@ mod round; /// /// [1]: https://serde.rs/attributes.html#field-attributes /// [2]: https://tools.ietf.org/html/rfc3339 -#[cfg(feature = "serde")] +#[cfg(feature = "serde-1")] pub mod serde { pub use super::datetime::serde::*; } @@ -703,7 +703,7 @@ impl fmt::Debug for ParseWeekdayError { // the actual `FromStr` implementation is in the `format` module to leverage the existing code -#[cfg(feature = "serde")] +#[cfg(feature = "serde-1")] mod weekday_serde { use super::Weekday; use core::fmt; diff --git a/src/naive/date.rs b/src/naive/date.rs index f429597..23c6f57 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -12,7 +12,9 @@ use {Weekday, Datelike}; use div::div_mod_floor; use naive::{NaiveTime, NaiveDateTime, IsoWeek}; use format::{Item, Numeric, Pad}; -use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems}; +use format::{parse, Parsed, ParseError, ParseResult, StrftimeItems}; +#[cfg(any(feature = "alloc", feature = "std", test))] +use format::DelayedFormat; use super::isoweek; use super::internals::{self, DateImpl, Of, Mdf, YearFlags}; @@ -916,6 +918,7 @@ impl NaiveDate { /// # let d = NaiveDate::from_ymd(2015, 9, 5); /// assert_eq!(format!("{}", d.format_with_items(fmt)), "2015-09-05"); /// ~~~~ + #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat where I: Iterator> + Clone { @@ -954,6 +957,7 @@ impl NaiveDate { /// assert_eq!(format!("{}", d.format("%Y-%m-%d")), "2015-09-05"); /// assert_eq!(format!("{}", d.format("%A, %-d %B, %C%y")), "Saturday, 5 September, 2015"); /// ~~~~ + #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { self.format_with_items(StrftimeItems::new(fmt)) @@ -1598,7 +1602,7 @@ mod rustc_serialize { } } -#[cfg(feature = "serde")] +#[cfg(feature = "serde-1")] mod serde { use core::fmt; #[cfg(not(any(feature = "std", test)))] diff --git a/src/naive/datetime.rs b/src/naive/datetime.rs index 6f4fbe7..25eefe3 100644 --- a/src/naive/datetime.rs +++ b/src/naive/datetime.rs @@ -12,7 +12,9 @@ use {Weekday, Timelike, Datelike}; use div::div_mod_floor; use naive::{NaiveTime, NaiveDate, IsoWeek}; use format::{Item, Numeric, Pad, Fixed}; -use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems}; +use format::{parse, Parsed, ParseError, ParseResult, StrftimeItems}; +#[cfg(any(feature = "alloc", feature = "std", test))] +use format::DelayedFormat; /// The tight upper bound guarantees that a duration with `|Duration| >= 2^MAX_SECS_BITS` /// will always overflow the addition with any date and time type. @@ -645,6 +647,7 @@ impl NaiveDateTime { /// # let dt = NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4); /// assert_eq!(format!("{}", dt.format_with_items(fmt)), "2015-09-05 23:56:04"); /// ~~~~ + #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat where I: Iterator> + Clone { @@ -683,6 +686,7 @@ impl NaiveDateTime { /// assert_eq!(format!("{}", dt.format("%Y-%m-%d %H:%M:%S")), "2015-09-05 23:56:04"); /// assert_eq!(format!("{}", dt.format("around %l %p on %b %-d")), "around 11 PM on Sep 5"); /// ~~~~ + #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { self.format_with_items(StrftimeItems::new(fmt)) @@ -1661,7 +1665,7 @@ pub mod rustc_serialize { } /// Tools to help serializing/deserializing `NaiveDateTime`s -#[cfg(feature = "serde")] +#[cfg(feature = "serde-1")] pub mod serde { use core::fmt; #[cfg(not(any(feature = "std", test)))] diff --git a/src/naive/time.rs b/src/naive/time.rs index c1cf297..54bed5e 100644 --- a/src/naive/time.rs +++ b/src/naive/time.rs @@ -10,7 +10,9 @@ use oldtime::Duration as OldDuration; use Timelike; use div::div_mod_floor; use format::{Item, Numeric, Pad, Fixed}; -use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems}; +use format::{parse, Parsed, ParseError, ParseResult, StrftimeItems}; +#[cfg(any(feature = "alloc", feature = "std", test))] +use format::DelayedFormat; /// ISO 8601 time without timezone. /// Allows for the nanosecond precision and optional leap second representation. @@ -723,6 +725,7 @@ impl NaiveTime { /// # let t = NaiveTime::from_hms(23, 56, 4); /// assert_eq!(format!("{}", t.format_with_items(fmt)), "23:56:04"); /// ~~~~ + #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat where I: Iterator> + Clone { @@ -763,6 +766,7 @@ impl NaiveTime { /// assert_eq!(format!("{}", t.format("%H:%M:%S%.6f")), "23:56:04.012345"); /// assert_eq!(format!("{}", t.format("%-I:%M %p")), "11:56 PM"); /// ~~~~ + #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { self.format_with_items(StrftimeItems::new(fmt)) @@ -1409,7 +1413,7 @@ mod rustc_serialize { } } -#[cfg(feature = "serde")] +#[cfg(feature = "serde-1")] mod serde { use core::fmt; #[cfg(not(any(feature = "std", test)))] From 4027bbb66d6cfaca492a577c14607764cb9e556b Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 13 Sep 2019 14:49:41 -0400 Subject: [PATCH 04/15] Rename serde-1 back to serde --- Cargo.toml | 1 - README.md | 2 +- ci/travis.sh | 27 ++++++++++++++------------- src/datetime.rs | 2 +- src/lib.rs | 8 ++++---- src/naive/date.rs | 2 +- src/naive/datetime.rs | 2 +- src/naive/time.rs | 2 +- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d252cbc..58392f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ name = "chrono" default = ["clock", "std"] alloc = [] std = [] -serde-1 = ["serde", "alloc"] clock = ["time", "std"] wasmbind = ["wasm-bindgen", "js-sys"] diff --git a/README.md b/README.md index 26b1a48..6401210 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ feature like this: ```toml [dependencies] -chrono = { version = "0.4", features = ["serde-1"] } +chrono = { version = "0.4", features = ["serde"] } ``` Then put this in your crate root: diff --git a/ci/travis.sh b/ci/travis.sh index 0145357..9665573 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -48,20 +48,20 @@ build_and_test_nonwasm() { TZ=ACST-9:30 channel test -v --lib channel build -v --features rustc-serialize TZ=EST4 channel test -v --features rustc-serialize --lib - channel build -v --features serde-1 - TZ=UTC0 channel test -v --features serde-1 --lib - channel build -v --features serde-1,rustc-serialize - TZ=Asia/Katmandu channel test -v --features serde-1,rustc-serialize + channel build -v --features serde + TZ=UTC0 channel test -v --features serde --lib + channel build -v --features serde,rustc-serialize + TZ=Asia/Katmandu channel test -v --features serde,rustc-serialize # without default "clock" feature channel build -v --no-default-features --features std TZ=ACST-9:30 channel test -v --no-default-features --lib channel build -v --no-default-features --features std,rustc-serialize TZ=EST4 channel test -v --no-default-features --features rustc-serialize --lib - channel build -v --no-default-features --features std,serde-1 - TZ=UTC0 channel test -v --no-default-features --features serde-1 --lib - channel build -v --no-default-features --features std,serde-1,rustc-serialize - TZ=Asia/Katmandu channel test -v --no-default-features --features std,serde-1,rustc-serialize --lib + channel build -v --no-default-features --features std,serde + TZ=UTC0 channel test -v --no-default-features --features serde --lib + channel build -v --no-default-features --features std,serde,rustc-serialize + TZ=Asia/Katmandu channel test -v --no-default-features --features std,serde,rustc-serialize --lib } build_and_test_wasm() { @@ -81,15 +81,16 @@ build_only() { cargo clean channel build -v channel build -v --features rustc-serialize - channel build -v --features 'serde-1 bincode' + channel build -v --features 'serde bincode' channel build -v --no-default-features --features std } build_core_test() { rustup target add thumbv6m-none-eabi --toolchain $CHANNEL - cd ci/core-test - channel build -v --target thumbv6m-none-eabi - cd ../.. + ( + cd ci/core-test + channel build -v --target thumbv6m-none-eabi + ) } run_clippy() { @@ -99,7 +100,7 @@ run_clippy() { exit fi - cargo clippy --features 'serde-1 bincode rustc-serialize' -- -Dclippy + cargo clippy --features 'serde bincode rustc-serialize' -- -Dclippy } check_readme() { diff --git a/src/datetime.rs b/src/datetime.rs index 6adec62..99bd316 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -918,7 +918,7 @@ pub mod rustc_serialize { } /// documented at re-export site -#[cfg(feature = "serde-1")] +#[cfg(feature = "serde")] pub mod serde { use core::fmt; #[cfg(not(any(feature = "std", test)))] diff --git a/src/lib.rs b/src/lib.rs index b7f60b0..704f3b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -418,7 +418,7 @@ extern crate num_integer; extern crate num_traits; #[cfg(feature = "rustc-serialize")] extern crate rustc_serialize; -#[cfg(feature = "serde-1")] +#[cfg(feature = "serde")] extern crate serde as serdelib; #[cfg(test)] #[macro_use] @@ -497,7 +497,7 @@ pub mod naive { /// /// [1]: https://serde.rs/attributes.html#field-attributes /// [2]: https://tools.ietf.org/html/rfc3339 - #[cfg(feature = "serde-1")] + #[cfg(feature = "serde")] pub mod serde { pub use super::datetime::serde::*; } @@ -515,7 +515,7 @@ mod round; /// /// [1]: https://serde.rs/attributes.html#field-attributes /// [2]: https://tools.ietf.org/html/rfc3339 -#[cfg(feature = "serde-1")] +#[cfg(feature = "serde")] pub mod serde { pub use super::datetime::serde::*; } @@ -703,7 +703,7 @@ impl fmt::Debug for ParseWeekdayError { // the actual `FromStr` implementation is in the `format` module to leverage the existing code -#[cfg(feature = "serde-1")] +#[cfg(feature = "serde")] mod weekday_serde { use super::Weekday; use core::fmt; diff --git a/src/naive/date.rs b/src/naive/date.rs index 23c6f57..eecf84b 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -1602,7 +1602,7 @@ mod rustc_serialize { } } -#[cfg(feature = "serde-1")] +#[cfg(feature = "serde")] mod serde { use core::fmt; #[cfg(not(any(feature = "std", test)))] diff --git a/src/naive/datetime.rs b/src/naive/datetime.rs index 25eefe3..9d93b2f 100644 --- a/src/naive/datetime.rs +++ b/src/naive/datetime.rs @@ -1665,7 +1665,7 @@ pub mod rustc_serialize { } /// Tools to help serializing/deserializing `NaiveDateTime`s -#[cfg(feature = "serde-1")] +#[cfg(feature = "serde")] pub mod serde { use core::fmt; #[cfg(not(any(feature = "std", test)))] diff --git a/src/naive/time.rs b/src/naive/time.rs index 54bed5e..71379e7 100644 --- a/src/naive/time.rs +++ b/src/naive/time.rs @@ -1413,7 +1413,7 @@ mod rustc_serialize { } } -#[cfg(feature = "serde-1")] +#[cfg(feature = "serde")] mod serde { use core::fmt; #[cfg(not(any(feature = "std", test)))] From 5e1e2d5633da23fb379e0b5b2b06542632eeadec Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 13 Sep 2019 14:50:14 -0400 Subject: [PATCH 05/15] Add a trivial function in core test To ensure that we don't accidentaly not verify that chrono compiles for core. --- ci/core-test/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ci/core-test/src/lib.rs b/ci/core-test/src/lib.rs index 0c9ac1a..e311edb 100644 --- a/ci/core-test/src/lib.rs +++ b/ci/core-test/src/lib.rs @@ -1 +1,7 @@ #![no_std] + +use chrono::{TimeZone, Utc}; + +pub fn create_time() { + let _ = Utc.ymd(2019, 1, 1).and_hms(0, 0, 0); +} From e8c708d81b91a90d4ca581b5ea372f2a4f177bc3 Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 13 Sep 2019 15:24:28 -0400 Subject: [PATCH 06/15] Make CI able to run non-cargo commands in `channel` --- ci/travis.sh | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/ci/travis.sh b/ci/travis.sh index 9665573..18b7c27 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -8,19 +8,33 @@ set -e DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" channel() { + channel_run cargo "$@" +} + +channel_run() { if [ -n "${TRAVIS}" ]; then if [ "${TRAVIS_RUST_VERSION}" = "${CHANNEL}" ]; then pwd - (set -x; cargo "$@") + echo "$ $*" + "$@" fi elif [ -n "${APPVEYOR}" ]; then if [ "${APPVEYOR_RUST_CHANNEL}" = "${CHANNEL}" ]; then pwd - (set -x; cargo "$@") + echo "$ $*" + "$@" fi else pwd - (set -x; cargo "+${CHANNEL}" "$@") + local cmd="$1" + shift + if [[ $cmd = cargo ]] ; then + echo "$ $cmd +${CHANNEL} $*" + "$cmd" "+${CHANNEL}" "$@" + else + echo "$ $cmd $*" + "$cmd" "$@" + fi fi } @@ -86,7 +100,7 @@ build_only() { } build_core_test() { - rustup target add thumbv6m-none-eabi --toolchain $CHANNEL + channel_run rustup target add thumbv6m-none-eabi --toolchain "$CHANNEL" ( cd ci/core-test channel build -v --target thumbv6m-none-eabi From 5b72ef3ed63d1d582e00b6c92058a2fc50268e1a Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Sun, 15 Sep 2019 20:44:37 -0400 Subject: [PATCH 07/15] Make travis.sh and Makefile "nicer" Slightly easier to reason about the code via some code movement, printing some banners to make it more obvious when cargo is being run since it is run so many times. --- Makefile | 7 ++- ci/travis.sh | 122 ++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 89 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index bb938cc..46b39dd 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ # this Makefile is mostly for the packaging convenience. # casual users should use `cargo` to retrieve the appropriate version of Chrono. +CHANNEL=stable + .PHONY: all all: @echo 'Try `cargo build` instead.' @@ -20,11 +22,8 @@ README.md: src/lib.rs .PHONY: test test: - TZ=UTC0 cargo test --features 'serde rustc-serialize bincode' --lib - TZ=ACST-9:30 cargo test --features 'serde rustc-serialize bincode' --lib - TZ=EST4 cargo test --features 'serde rustc-serialize bincode' + CHANNEL=$(CHANNEL) ./ci/travis.sh .PHONY: doc doc: authors readme cargo doc --features 'serde rustc-serialize bincode' - diff --git a/ci/travis.sh b/ci/travis.sh index 18b7c27..8b5e067 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -7,37 +7,81 @@ set -e DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +main() { + if [[ -n $CHANNEL ]] ; then + if [[ $CHANNEL == 1.13.0 ]]; then + banner "Building $CHANNEL" + build_only + else + banner "Building/testing $CHANNEL" + #build_and_test + banner "Testing Core $CHANNEL" + build_core_test + fi + else + CHANNEL=nightly + matching_banner "Test $CHANNEL" + if [ "x${CLIPPY}" = xy ] ; then + run_clippy + else + build_and_test + fi + + CHANNEL=beta + matching_banner "Test $CHANNEL" + build_and_test + + CHANNEL=stable + matching_banner "Test $CHANNEL" + build_and_test + build_core_test + + CHANNEL=1.13.0 + matching_banner "Test $CHANNEL" + build_only + fi +} + channel() { channel_run cargo "$@" } channel_run() { - if [ -n "${TRAVIS}" ]; then - if [ "${TRAVIS_RUST_VERSION}" = "${CHANNEL}" ]; then - pwd - echo "$ $*" - "$@" - fi - elif [ -n "${APPVEYOR}" ]; then - if [ "${APPVEYOR_RUST_CHANNEL}" = "${CHANNEL}" ]; then - pwd - echo "$ $*" - "$@" - fi + if channel_matches ; then + pwd + local the_cmd="$ $*" + echo "$the_cmd" + "$@" else pwd local cmd="$1" shift - if [[ $cmd = cargo ]] ; then - echo "$ $cmd +${CHANNEL} $*" + if [[ $cmd == cargo || $cmd == rustc ]] ; then + underline "$ $cmd +${CHANNEL} $*" "$cmd" "+${CHANNEL}" "$@" + else - echo "$ $cmd $*" + underline "$ $cmd $*" "$cmd" "$@" fi fi } +channel_matches() { + if [ -n "${TRAVIS}" ]; then + if [ "${TRAVIS_RUST_VERSION}" = "${CHANNEL}" ]; then + return 0 + fi + elif [ -n "${APPVEYOR}" ]; then + if [ "${APPVEYOR_RUST_CHANNEL}" = "${CHANNEL}" ]; then + return 0 + fi + else + return 1 + fi +} + build_and_test() { # interleave building and testing in hope that it saves time # also vary the local time zone to (hopefully) catch tz-dependent bugs @@ -76,6 +120,9 @@ build_and_test_nonwasm() { TZ=UTC0 channel test -v --no-default-features --features serde --lib channel build -v --no-default-features --features std,serde,rustc-serialize TZ=Asia/Katmandu channel test -v --no-default-features --features std,serde,rustc-serialize --lib + + channel build -v --no-default-features --features 'alloc serde' + TZ=UTC0 channel test -v --no-default-features --features 'alloc serde' --lib } build_and_test_wasm() { @@ -95,15 +142,16 @@ build_only() { cargo clean channel build -v channel build -v --features rustc-serialize - channel build -v --features 'serde bincode' + channel build -v --features serde channel build -v --no-default-features --features std + channel build -v --no-default-features --features 'std serde_std' } build_core_test() { channel_run rustup target add thumbv6m-none-eabi --toolchain "$CHANNEL" ( cd ci/core-test - channel build -v --target thumbv6m-none-eabi + channel build -v --features alloc --target thumbv6m-none-eabi ) } @@ -114,7 +162,7 @@ run_clippy() { exit fi - cargo clippy --features 'serde bincode rustc-serialize' -- -Dclippy + cargo clippy --features 'serde rustc-serialize' -- -Dclippy } check_readme() { @@ -122,23 +170,25 @@ check_readme() { (set -x; git diff --exit-code -- README.md) ; echo $? } -rustc --version -cargo --version +banner() { + echo "======================================================================" + echo "$*" + echo "======================================================================" +} + +underline() { + echo "$*" + echo "${*//?/^}" +} + +matching_banner() { + if channel_matches || [[ -z $TRAVIS && -z $APPVEYOR ]] ; then + banner "$*" + fi +} + +channel_run rustc --version +channel_run cargo --version node --version -CHANNEL=nightly -if [ "x${CLIPPY}" = xy ] ; then - run_clippy -else - build_and_test -fi - -CHANNEL=beta -build_and_test - -CHANNEL=stable -build_and_test -build_core_test - -CHANNEL=1.13.0 -build_only +main From e5bbc94c3bcd7406cca33502bb73a7a50ab127a6 Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Sun, 15 Sep 2019 20:45:49 -0400 Subject: [PATCH 08/15] First pass at making "alloc" its own feature Part of this means that we don't actually need to allocate to write to Serde any more, which is a win in its own right. --- Cargo.toml | 4 +++- src/datetime.rs | 46 +++++++++++++++++++++++++++++++++---------- src/format/mod.rs | 4 ++-- src/lib.rs | 22 ++++++++++++++++----- src/naive/date.rs | 10 ++++++++-- src/naive/datetime.rs | 2 +- src/naive/time.rs | 2 +- 7 files changed, 68 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 58392f7..5135032 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,8 @@ name = "chrono" default = ["clock", "std"] alloc = [] std = [] +serde_alloc = ["serde/alloc"] +serde_std = ["serde/std"] clock = ["time", "std"] wasmbind = ["wasm-bindgen", "js-sys"] @@ -35,7 +37,7 @@ time = { version = "0.1.39", optional = true } num-integer = { version = "0.1.36", default-features = false } num-traits = { version = "0.2", default-features = false } rustc-serialize = { version = "0.3.20", optional = true } -serde = { version = "1.0.99", default-features = false, features = ["alloc"], optional = true } +serde = { version = "1.0.99", default-features = false, optional = true } [target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] wasm-bindgen = { version = "0.2", optional = true } diff --git a/src/datetime.rs b/src/datetime.rs index 99bd316..092da60 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -10,8 +10,10 @@ use core::ops::{Add, Sub}; use std::time::{SystemTime, UNIX_EPOCH}; use oldtime::Duration as OldDuration; -#[cfg(any(feature = "alloc", feature = "std", test))] +#[cfg(all(not(feature = "std"), feature = "alloc"))] use alloc::string::{String, ToString}; +#[cfg(feature = "std")] +use std::string::ToString; use {Weekday, Timelike, Datelike}; #[cfg(feature="clock")] @@ -921,26 +923,50 @@ pub mod rustc_serialize { #[cfg(feature = "serde")] pub mod serde { use core::fmt; - #[cfg(not(any(feature = "std", test)))] - use alloc::format; + // #[cfg(any(test, feature = "alloc"))] + // use alloc::format; use super::DateTime; #[cfg(feature="clock")] use offset::Local; use offset::{LocalResult, TimeZone, Utc, FixedOffset}; use serdelib::{ser, de}; + enum SerdeError { + NonExistent { timestamp: V }, + Ambiguous { timestamp: V, min: D, max: D } + } + + impl fmt::Debug for SerdeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "ChronoSerdeError({})", self) + } + } + + // impl core::error::Error for SerdeError {} + impl fmt::Display for SerdeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &SerdeError::NonExistent { ref timestamp } => write!( + f, "value is not a legal timestamp: {}", timestamp), + &SerdeError::Ambiguous { ref timestamp, ref min, ref max } => write!( + f, "value is an ambiguous timestamp: {}, could be either of {}, {}", + timestamp, min, max), + } + } + } + // try!-like function to convert a LocalResult into a serde-ish Result fn serde_from(me: LocalResult, ts: &V) -> Result - where E: de::Error, - V: fmt::Display, - T: fmt::Display, + where + E: de::Error, + V: fmt::Display, + T: fmt::Display, { match me { LocalResult::None => Err(E::custom( - format!("value is not a legal timestamp: {}", ts))), + SerdeError::NonExistent::<_, u8> { timestamp: ts })), LocalResult::Ambiguous(min, max) => Err(E::custom( - format!("value is an ambiguous timestamp: {}, could be either of {}, {}", - ts, min, max))), + SerdeError::Ambiguous { timestamp: ts, min: min, max: max })), LocalResult::Single(val) => Ok(val) } } @@ -1418,7 +1444,7 @@ pub mod serde { fn visit_str(self, value: &str) -> Result, E> where E: de::Error { - value.parse().map_err(|err| E::custom(format!("{}", err))) + value.parse().map_err(|err: ::format::ParseError| E::custom(err)) } } diff --git a/src/format/mod.rs b/src/format/mod.rs index fb05c93..e003c30 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -21,9 +21,9 @@ use core::fmt; use core::str::FromStr; #[cfg(any(feature = "std", test))] use std::error::Error; -#[cfg(any(feature = "alloc", feature = "std", test))] +#[cfg(feature = "alloc")] use alloc::boxed::Box; -#[cfg(any(feature = "alloc", feature = "std", test))] +#[cfg(feature = "alloc")] use alloc::string::{String, ToString}; #[cfg(not(any(feature = "alloc", feature = "std", test)))] diff --git a/src/lib.rs b/src/lib.rs index 704f3b0..ad6710c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -405,11 +405,11 @@ trivially_copy_pass_by_ref, ))] -#[cfg(not(any(feature = "std", test)))] +#[cfg(feature = "alloc")] extern crate alloc; #[cfg(any(feature = "std", test))] extern crate std as core; -#[cfg(any(feature = "std", test))] +#[cfg(all(feature = "std", not(feature="alloc")))] extern crate std as alloc; #[cfg(feature="clock")] @@ -654,6 +654,20 @@ impl Weekday { } } +impl fmt::Display for Weekday { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(match *self { + Weekday::Mon => "Mon", + Weekday::Tue => "Tue", + Weekday::Wed => "Wed", + Weekday::Thu => "Thu", + Weekday::Fri => "Fri", + Weekday::Sat => "Sat", + Weekday::Sun => "Sun", + }) + } +} + /// Any weekday can be represented as an integer from 0 to 6, which equals to /// [`Weekday::num_days_from_monday`](#method.num_days_from_monday) in this implementation. /// Do not heavily depend on this though; use explicit methods whenever possible. @@ -707,15 +721,13 @@ impl fmt::Debug for ParseWeekdayError { mod weekday_serde { use super::Weekday; use core::fmt; - #[cfg(not(any(feature = "std", test)))] - use alloc::format; use serdelib::{ser, de}; impl ser::Serialize for Weekday { fn serialize(&self, serializer: S) -> Result where S: ser::Serializer { - serializer.serialize_str(&format!("{:?}", self)) + serializer.collect_str(&self) } } diff --git a/src/naive/date.rs b/src/naive/date.rs index eecf84b..cbd1350 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -1605,8 +1605,6 @@ mod rustc_serialize { #[cfg(feature = "serde")] mod serde { use core::fmt; - #[cfg(not(any(feature = "std", test)))] - use alloc::format; use super::NaiveDate; use serdelib::{ser, de}; @@ -1640,11 +1638,19 @@ mod serde { write!(formatter, "a formatted date string") } + #[cfg(any(feature = "std", test))] fn visit_str(self, value: &str) -> Result where E: de::Error { value.parse().map_err(|err| E::custom(format!("{}", err))) } + + #[cfg(not(any(feature = "std", test)))] + fn visit_str(self, value: &str) -> Result + where E: de::Error + { + value.parse().map_err(|err| E::custom(err)) + } } impl<'de> de::Deserialize<'de> for NaiveDate { diff --git a/src/naive/datetime.rs b/src/naive/datetime.rs index 9d93b2f..60e2a77 100644 --- a/src/naive/datetime.rs +++ b/src/naive/datetime.rs @@ -1668,7 +1668,7 @@ pub mod rustc_serialize { #[cfg(feature = "serde")] pub mod serde { use core::fmt; - #[cfg(not(any(feature = "std", test)))] + #[cfg(feature = "alloc")] use alloc::format; use super::{NaiveDateTime}; use serdelib::{ser, de}; diff --git a/src/naive/time.rs b/src/naive/time.rs index 71379e7..45b2643 100644 --- a/src/naive/time.rs +++ b/src/naive/time.rs @@ -1416,7 +1416,7 @@ mod rustc_serialize { #[cfg(feature = "serde")] mod serde { use core::fmt; - #[cfg(not(any(feature = "std", test)))] + #[cfg(feature = "alloc")] use alloc::format; use super::NaiveTime; use serdelib::{ser, de}; From a09f9ba2a8a3219cddd02ca20f4698e3c3d37d3d Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 20 Sep 2019 10:50:28 -0400 Subject: [PATCH 09/15] Test against serde with no features in both std and no-std --- Cargo.toml | 8 +++----- ci/travis.sh | 5 ++++- src/datetime.rs | 29 ++--------------------------- src/lib.rs | 35 +++++++++++++++++++++++++++++++++++ src/naive/date.rs | 4 ++-- src/naive/datetime.rs | 28 ++++++++++------------------ src/naive/time.rs | 4 +--- 7 files changed, 57 insertions(+), 56 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5135032..3e2e229 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,8 +27,6 @@ name = "chrono" default = ["clock", "std"] alloc = [] std = [] -serde_alloc = ["serde/alloc"] -serde_std = ["serde/std"] clock = ["time", "std"] wasmbind = ["wasm-bindgen", "js-sys"] @@ -44,9 +42,9 @@ wasm-bindgen = { version = "0.2", optional = true } js-sys = { version = "0.3", optional = true } # contains FFI bindings for the JS Date API [dev-dependencies] -serde_json = { version = "1" } -serde_derive = { version = "1" } -bincode = { version = "0.8.0" } +serde_json = { version = "1", default-features = false } +serde_derive = { version = "1", default-features = false } +bincode = { version = "1.1.0" } num-iter = { version = "0.1.35", default-features = false } doc-comment = "0.3" diff --git a/ci/travis.sh b/ci/travis.sh index 8b5e067..c757b71 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -121,6 +121,9 @@ build_and_test_nonwasm() { channel build -v --no-default-features --features std,serde,rustc-serialize TZ=Asia/Katmandu channel test -v --no-default-features --features std,serde,rustc-serialize --lib + channel build -v --no-default-features --features 'serde' + TZ=UTC0 channel test -v --no-default-features --features 'serde' --lib + channel build -v --no-default-features --features 'alloc serde' TZ=UTC0 channel test -v --no-default-features --features 'alloc serde' --lib } @@ -151,7 +154,7 @@ build_core_test() { channel_run rustup target add thumbv6m-none-eabi --toolchain "$CHANNEL" ( cd ci/core-test - channel build -v --features alloc --target thumbv6m-none-eabi + channel build -v --target thumbv6m-none-eabi ) } diff --git a/src/datetime.rs b/src/datetime.rs index 092da60..aa61fe4 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -923,37 +923,12 @@ pub mod rustc_serialize { #[cfg(feature = "serde")] pub mod serde { use core::fmt; - // #[cfg(any(test, feature = "alloc"))] - // use alloc::format; use super::DateTime; #[cfg(feature="clock")] use offset::Local; use offset::{LocalResult, TimeZone, Utc, FixedOffset}; use serdelib::{ser, de}; - - enum SerdeError { - NonExistent { timestamp: V }, - Ambiguous { timestamp: V, min: D, max: D } - } - - impl fmt::Debug for SerdeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "ChronoSerdeError({})", self) - } - } - - // impl core::error::Error for SerdeError {} - impl fmt::Display for SerdeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &SerdeError::NonExistent { ref timestamp } => write!( - f, "value is not a legal timestamp: {}", timestamp), - &SerdeError::Ambiguous { ref timestamp, ref min, ref max } => write!( - f, "value is an ambiguous timestamp: {}, could be either of {}, {}", - timestamp, min, max), - } - } - } + use {SerdeError, ne_timestamp}; // try!-like function to convert a LocalResult into a serde-ish Result fn serde_from(me: LocalResult, ts: &V) -> Result @@ -964,7 +939,7 @@ pub mod serde { { match me { LocalResult::None => Err(E::custom( - SerdeError::NonExistent::<_, u8> { timestamp: ts })), + ne_timestamp(ts))), LocalResult::Ambiguous(min, max) => Err(E::custom( SerdeError::Ambiguous { timestamp: ts, min: min, max: max })), LocalResult::Single(val) => Ok(val) diff --git a/src/lib.rs b/src/lib.rs index ad6710c..9b684dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -520,6 +520,41 @@ pub mod serde { pub use super::datetime::serde::*; } +// Until rust 1.18 there is no "pub(crate)" so to share this we need it in the root + +#[cfg(feature = "serde")] +enum SerdeError { + NonExistent { timestamp: V }, + Ambiguous { timestamp: V, min: D, max: D }, +} + +/// Construct a [`SerdeError::NonExistent`] +#[cfg(feature = "serde")] +fn ne_timestamp(timestamp: T) -> SerdeError { + SerdeError::NonExistent:: { timestamp } +} + +#[cfg(feature = "serde")] +impl fmt::Debug for SerdeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "ChronoSerdeError({})", self) + } +} + +// impl core::error::Error for SerdeError {} +#[cfg(feature = "serde")] +impl fmt::Display for SerdeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &SerdeError::NonExistent { ref timestamp } => write!( + f, "value is not a legal timestamp: {}", timestamp), + &SerdeError::Ambiguous { ref timestamp, ref min, ref max } => write!( + f, "value is an ambiguous timestamp: {}, could be either of {}, {}", + timestamp, min, max), + } + } +} + /// The day of week. /// /// The order of the days of week depends on the context. diff --git a/src/naive/date.rs b/src/naive/date.rs index cbd1350..981e9f4 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -1642,14 +1642,14 @@ mod serde { fn visit_str(self, value: &str) -> Result where E: de::Error { - value.parse().map_err(|err| E::custom(format!("{}", err))) + value.parse().map_err(E::custom) } #[cfg(not(any(feature = "std", test)))] fn visit_str(self, value: &str) -> Result where E: de::Error { - value.parse().map_err(|err| E::custom(err)) + value.parse().map_err(E::custom) } } diff --git a/src/naive/datetime.rs b/src/naive/datetime.rs index 60e2a77..2049782 100644 --- a/src/naive/datetime.rs +++ b/src/naive/datetime.rs @@ -1668,8 +1668,6 @@ pub mod rustc_serialize { #[cfg(feature = "serde")] pub mod serde { use core::fmt; - #[cfg(feature = "alloc")] - use alloc::format; use super::{NaiveDateTime}; use serdelib::{ser, de}; @@ -1708,7 +1706,7 @@ pub mod serde { fn visit_str(self, value: &str) -> Result where E: de::Error { - value.parse().map_err(|err| E::custom(format!("{}", err))) + value.parse().map_err(E::custom) } } @@ -1757,11 +1755,9 @@ pub mod serde { /// ``` pub mod ts_nanoseconds { use core::fmt; - #[cfg(not(any(feature = "std", test)))] - use alloc::format; use serdelib::{ser, de}; - use NaiveDateTime; + use {NaiveDateTime, ne_timestamp}; /// Serialize a UTC datetime into an integer number of nanoseconds since the epoch /// @@ -1854,7 +1850,7 @@ pub mod serde { { NaiveDateTime::from_timestamp_opt(value / 1_000_000_000, (value % 1_000_000_000) as u32) - .ok_or_else(|| E::custom(format!("value is not a legal timestamp: {}", value))) + .ok_or_else(|| E::custom(ne_timestamp(value))) } fn visit_u64(self, value: u64) -> Result @@ -1862,7 +1858,7 @@ pub mod serde { { NaiveDateTime::from_timestamp_opt(value as i64 / 1_000_000_000, (value as i64 % 1_000_000_000) as u32) - .ok_or_else(|| E::custom(format!("value is not a legal timestamp: {}", value))) + .ok_or_else(|| E::custom(ne_timestamp(value))) } } } @@ -1904,11 +1900,9 @@ pub mod serde { /// ``` pub mod ts_milliseconds { use core::fmt; - #[cfg(not(any(feature = "std", test)))] - use alloc::format; use serdelib::{ser, de}; - use NaiveDateTime; + use {NaiveDateTime, ne_timestamp}; /// Serialize a UTC datetime into an integer number of milliseconds since the epoch /// @@ -2001,7 +1995,7 @@ pub mod serde { { NaiveDateTime::from_timestamp_opt(value / 1000, ((value % 1000) * 1_000_000) as u32) - .ok_or_else(|| E::custom(format!("value is not a legal timestamp: {}", value))) + .ok_or_else(|| E::custom(ne_timestamp(value))) } fn visit_u64(self, value: u64) -> Result @@ -2009,7 +2003,7 @@ pub mod serde { { NaiveDateTime::from_timestamp_opt((value / 1000) as i64, ((value % 1000) * 1_000_000) as u32) - .ok_or_else(|| E::custom(format!("value is not a legal timestamp: {}", value))) + .ok_or_else(|| E::custom(ne_timestamp(value))) } } } @@ -2051,11 +2045,9 @@ pub mod serde { /// ``` pub mod ts_seconds { use core::fmt; - #[cfg(not(any(feature = "std", test)))] - use alloc::format; use serdelib::{ser, de}; - use NaiveDateTime; + use {NaiveDateTime, ne_timestamp}; /// Serialize a UTC datetime into an integer number of seconds since the epoch /// @@ -2147,14 +2139,14 @@ pub mod serde { where E: de::Error { NaiveDateTime::from_timestamp_opt(value, 0) - .ok_or_else(|| E::custom(format!("value is not a legal timestamp: {}", value))) + .ok_or_else(|| E::custom(ne_timestamp(value))) } fn visit_u64(self, value: u64) -> Result where E: de::Error { NaiveDateTime::from_timestamp_opt(value as i64, 0) - .ok_or_else(|| E::custom(format!("value is not a legal timestamp: {}", value))) + .ok_or_else(|| E::custom(ne_timestamp(value))) } } } diff --git a/src/naive/time.rs b/src/naive/time.rs index 45b2643..c0272c8 100644 --- a/src/naive/time.rs +++ b/src/naive/time.rs @@ -1416,8 +1416,6 @@ mod rustc_serialize { #[cfg(feature = "serde")] mod serde { use core::fmt; - #[cfg(feature = "alloc")] - use alloc::format; use super::NaiveTime; use serdelib::{ser, de}; @@ -1445,7 +1443,7 @@ mod serde { fn visit_str(self, value: &str) -> Result where E: de::Error { - value.parse().map_err(|err| E::custom(format!("{}", err))) + value.parse().map_err(E::custom) } } From ffcd0f9c198267f4db73cc20b60da67eb819c289 Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 20 Sep 2019 11:01:11 -0400 Subject: [PATCH 10/15] put bincode back to the version used for testing --- Cargo.toml | 2 +- ci/travis.sh | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3e2e229..6fbb591 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ js-sys = { version = "0.3", optional = true } # contains FFI bindings for the JS [dev-dependencies] serde_json = { version = "1", default-features = false } serde_derive = { version = "1", default-features = false } -bincode = { version = "1.1.0" } +bincode = { version = "0.8.0" } num-iter = { version = "0.1.35", default-features = false } doc-comment = "0.3" diff --git a/ci/travis.sh b/ci/travis.sh index c757b71..5971c41 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -15,7 +15,7 @@ main() { build_only else banner "Building/testing $CHANNEL" - #build_and_test + build_and_test banner "Testing Core $CHANNEL" build_core_test fi @@ -51,7 +51,7 @@ channel_run() { if channel_matches ; then pwd local the_cmd="$ $*" - echo "$the_cmd" + underline "$the_cmd" "$@" else pwd @@ -60,7 +60,6 @@ channel_run() { if [[ $cmd == cargo || $cmd == rustc ]] ; then underline "$ $cmd +${CHANNEL} $*" "$cmd" "+${CHANNEL}" "$@" - else underline "$ $cmd $*" "$cmd" "$@" From 9a3e48931b2e49cd30e60ea69ce22e53911fd1e0 Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 20 Sep 2019 11:15:57 -0400 Subject: [PATCH 11/15] Make ci script more understandable and robust, hopefully --- ci/travis.sh | 105 +++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/ci/travis.sh b/ci/travis.sh index 5971c41..97f52f9 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -2,6 +2,12 @@ # This is the script that's executed by travis, you can run it yourself to run # the exact same suite +# +# When running it locally the most important thing to set is the CHANNEL env +# var, otherwise it will run tests against every version of rust that it knows +# about (nightly, beta, stable, 1.13.0): +# +# $ CHANNEL=stable ./ci/travis.sh set -e @@ -9,8 +15,8 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" main() { - if [[ -n $CHANNEL ]] ; then - if [[ $CHANNEL == 1.13.0 ]]; then + if [[ -n "$CHANNEL" ]] ; then + if [[ "$CHANNEL" == 1.13.0 ]]; then banner "Building $CHANNEL" build_only else @@ -22,7 +28,7 @@ main() { else CHANNEL=nightly matching_banner "Test $CHANNEL" - if [ "x${CLIPPY}" = xy ] ; then + if [[ "${CLIPPY}" = y ]] ; then run_clippy else build_and_test @@ -43,44 +49,6 @@ main() { fi } -channel() { - channel_run cargo "$@" -} - -channel_run() { - if channel_matches ; then - pwd - local the_cmd="$ $*" - underline "$the_cmd" - "$@" - else - pwd - local cmd="$1" - shift - if [[ $cmd == cargo || $cmd == rustc ]] ; then - underline "$ $cmd +${CHANNEL} $*" - "$cmd" "+${CHANNEL}" "$@" - else - underline "$ $cmd $*" - "$cmd" "$@" - fi - fi -} - -channel_matches() { - if [ -n "${TRAVIS}" ]; then - if [ "${TRAVIS_RUST_VERSION}" = "${CHANNEL}" ]; then - return 0 - fi - elif [ -n "${APPVEYOR}" ]; then - if [ "${APPVEYOR_RUST_CHANNEL}" = "${CHANNEL}" ]; then - return 0 - fi - else - return 1 - fi -} - build_and_test() { # interleave building and testing in hope that it saves time # also vary the local time zone to (hopefully) catch tz-dependent bugs @@ -172,6 +140,8 @@ check_readme() { (set -x; git diff --exit-code -- README.md) ; echo $? } +# script helpers + banner() { echo "======================================================================" echo "$*" @@ -184,13 +154,58 @@ underline() { } matching_banner() { - if channel_matches || [[ -z $TRAVIS && -z $APPVEYOR ]] ; then + if channel_matches || ! is_ci ; then banner "$*" + echo_versions fi } -channel_run rustc --version -channel_run cargo --version -node --version +echo_versions() { + channel_run rustc --version + channel_run cargo --version + node --version +} + +channel() { + channel_run cargo "$@" +} + +channel_run() { + if channel_matches ; then + pwd + local the_cmd="$ $*" + underline "$the_cmd" + "$@" + elif ! is_ci ; then + pwd + local cmd="$1" + shift + if [[ $cmd == cargo || $cmd == rustc ]] ; then + underline "$ $cmd +${CHANNEL} $*" + "$cmd" "+${CHANNEL}" "$@" + else + underline "$ $cmd $*" + "$cmd" "$@" + fi + fi +} + +channel_matches() { + if is_ci ; then + if [[ "${TRAVIS_RUST_VERSION}" = "${CHANNEL}" + || "${APPVEYOR_RUST_CHANNEL}" = "${CHANNEL}" ]] ; then + return 0 + fi + fi + return 1 +} + +is_ci() { + if [[ -n "$TRAVIS" || -n "$APPVEYOR" ]] ; then + return 0 + else + return 1 + fi +} main From 911dc57402e480622ac52c39904ab4998bae2b90 Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 20 Sep 2019 11:41:23 -0400 Subject: [PATCH 12/15] support rust v1.13.0 struct initialization syntax --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9b684dd..f9db6f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -530,8 +530,8 @@ enum SerdeError { /// Construct a [`SerdeError::NonExistent`] #[cfg(feature = "serde")] -fn ne_timestamp(timestamp: T) -> SerdeError { - SerdeError::NonExistent:: { timestamp } +fn ne_timestamp(ts: T) -> SerdeError { + SerdeError::NonExistent:: { timestamp: ts } } #[cfg(feature = "serde")] From 6499c5b1c994635496ee9148a523e587a576a7a8 Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 20 Sep 2019 13:49:01 -0400 Subject: [PATCH 13/15] Using core-only on 1.13 doesn't seem to work the same as stable --- ci/travis.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/ci/travis.sh b/ci/travis.sh index 97f52f9..008c1ec 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -114,7 +114,6 @@ build_only() { channel build -v --features rustc-serialize channel build -v --features serde channel build -v --no-default-features --features std - channel build -v --no-default-features --features 'std serde_std' } build_core_test() { From 918cff1f724305d3d1b126abf49425c653a4a201 Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 20 Sep 2019 13:49:30 -0400 Subject: [PATCH 14/15] Remove some pwds from the CI script They just add noise, now. --- ci/travis.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/ci/travis.sh b/ci/travis.sh index 008c1ec..18f639b 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -171,12 +171,10 @@ channel() { channel_run() { if channel_matches ; then - pwd local the_cmd="$ $*" underline "$the_cmd" "$@" elif ! is_ci ; then - pwd local cmd="$1" shift if [[ $cmd == cargo || $cmd == rustc ]] ; then From 64a28d6812ca221261be7ae6e341340b91b2d76c Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 22 Nov 2019 15:27:10 -0500 Subject: [PATCH 15/15] Remove core_only, cfg-out the `format::Item::Owned*` variants This means that a few more features of formatting items don't compile in non-alloc environments, but they wouldn't have worked correctly anyway. --- src/format/mod.rs | 27 +++------------------------ src/format/parse.rs | 8 +++++++- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index e003c30..b8e6458 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -26,30 +26,6 @@ use alloc::boxed::Box; #[cfg(feature = "alloc")] use alloc::string::{String, ToString}; -#[cfg(not(any(feature = "alloc", feature = "std", test)))] -mod core_only { - /// Core only - #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] - pub struct Box(core::marker::PhantomData); - - impl Box { - /// Core only - pub fn len(&self) -> usize { 0 } - } - - impl Clone for Box { fn clone(&self) -> Self { Box(core::marker::PhantomData) } } - - impl core::ops::Index for Box { - type Output = str; - fn index(&self, _: core::ops::RangeFull) -> &Self::Output { - "" - } - } -} - -#[cfg(not(any(feature = "alloc", feature = "std", test)))] -use self::core_only::Box; - #[cfg(any(feature = "alloc", feature = "std", test))] use {Datelike, Timelike}; use {Weekday, ParseWeekdayError}; @@ -279,10 +255,12 @@ pub enum Item<'a> { /// A literally printed and parsed text. Literal(&'a str), /// Same to `Literal` but with the string owned by the item. + #[cfg(any(feature = "alloc", feature = "std", test))] OwnedLiteral(Box), /// Whitespace. Prints literally but reads zero or more whitespace. Space(&'a str), /// Same to `Space` but with the string owned by the item. + #[cfg(any(feature = "alloc", feature = "std", test))] OwnedSpace(Box), /// Numeric item. Can be optionally padded to the maximal length (if any) when formatting; /// the parser simply ignores any padded whitespace and zeroes. @@ -404,6 +382,7 @@ pub fn format<'a, I>( for item in items { match item { Item::Literal(s) | Item::Space(s) => result.push_str(s), + #[cfg(any(feature = "alloc", feature = "std", test))] Item::OwnedLiteral(ref s) | Item::OwnedSpace(ref s) => result.push_str(s), Item::Numeric(spec, pad) => { diff --git a/src/format/parse.rs b/src/format/parse.rs index c10a802..e8e0d25 100644 --- a/src/format/parse.rs +++ b/src/format/parse.rs @@ -218,13 +218,19 @@ pub fn parse<'a, I>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<( s = &s[prefix.len()..]; } + #[cfg(any(feature = "alloc", feature = "std", test))] Item::OwnedLiteral(ref prefix) => { if s.len() < prefix.len() { return Err(TOO_SHORT); } if !s.starts_with(&prefix[..]) { return Err(INVALID); } s = &s[prefix.len()..]; } - Item::Space(_) | Item::OwnedSpace(_) => { + Item::Space(_) => { + s = s.trim_left(); + } + + #[cfg(any(feature = "alloc", feature = "std", test))] + Item::OwnedSpace(_) => { s = s.trim_left(); }