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)))]