Introduce an `alloc` feature

This commit is contained in:
Christopher Serr 2019-09-09 13:41:44 +02:00
parent 5ccec02e54
commit e62a054cd9
11 changed files with 90 additions and 31 deletions

View File

@ -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 }

View File

@ -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:

View File

@ -9,3 +9,6 @@ edition = "2018"
[dependencies]
chrono = { path = "../..", default-features = false, features = ["serde"] }
[features]
alloc = ["chrono/alloc"]

View File

@ -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

View File

@ -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<Tz: TimeZone, F>(d: &Date<Tz>, mut f: F) -> Option<Date<Tz>>
impl<Tz: TimeZone> Date<Tz> 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<I>
where I: Iterator<Item=Item<'a>> + Clone {
@ -264,6 +266,7 @@ impl<Tz: TimeZone> Date<Tz> 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<StrftimeItems<'a>> {
self.format_with_items(StrftimeItems::new(fmt))

View File

@ -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<FixedOffset> {
impl<Tz: TimeZone> DateTime<Tz> 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<Tz: TimeZone> DateTime<Tz> 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<Tz: TimeZone> DateTime<Tz> 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<I>
where I: Iterator<Item=Item<'a>> + Clone {
@ -463,6 +469,7 @@ impl<Tz: TimeZone> DateTime<Tz> 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<StrftimeItems<'a>> {
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)))]

View File

@ -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<T: ?Sized>(core::marker::PhantomData<T>);
impl Box<str> {
/// Core only
pub fn len(&self) -> usize { 0 }
}
impl Clone for Box<str> { fn clone(&self) -> Self { Box(core::marker::PhantomData) } }
impl core::ops::Index<core::ops::RangeFull> for Box<str> {
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<I> {
/// The date view, if any.
@ -621,6 +653,7 @@ pub struct DelayedFormat<I> {
items: I,
}
#[cfg(any(feature = "alloc", feature = "std", test))]
impl<'a, I: Iterator<Item=Item<'a>> + Clone> DelayedFormat<I> {
/// Makes a new `DelayedFormat` value out of local date and time.
pub fn new(date: Option<NaiveDate>, time: Option<NaiveTime>, items: I) -> DelayedFormat<I> {
@ -636,6 +669,7 @@ impl<'a, I: Iterator<Item=Item<'a>> + Clone> DelayedFormat<I> {
}
}
#[cfg(any(feature = "alloc", feature = "std", test))]
impl<'a, I: Iterator<Item=Item<'a>> + Clone> fmt::Display for DelayedFormat<I> {
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())

View File

@ -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;

View File

@ -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<I>
where I: Iterator<Item=Item<'a>> + 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<StrftimeItems<'a>> {
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)))]

View File

@ -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<I>
where I: Iterator<Item=Item<'a>> + 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<StrftimeItems<'a>> {
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)))]

View File

@ -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<I>
where I: Iterator<Item=Item<'a>> + 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<StrftimeItems<'a>> {
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)))]