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.
This commit is contained in:
Brandon W Maister 2019-09-15 20:45:49 -04:00
parent 5b72ef3ed6
commit e5bbc94c3b
7 changed files with 68 additions and 22 deletions

View File

@ -27,6 +27,8 @@ name = "chrono"
default = ["clock", "std"] default = ["clock", "std"]
alloc = [] alloc = []
std = [] std = []
serde_alloc = ["serde/alloc"]
serde_std = ["serde/std"]
clock = ["time", "std"] clock = ["time", "std"]
wasmbind = ["wasm-bindgen", "js-sys"] 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-integer = { version = "0.1.36", default-features = false }
num-traits = { version = "0.2", default-features = false } num-traits = { version = "0.2", default-features = false }
rustc-serialize = { version = "0.3.20", optional = true } 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] [target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies]
wasm-bindgen = { version = "0.2", optional = true } wasm-bindgen = { version = "0.2", optional = true }

View File

@ -10,8 +10,10 @@ use core::ops::{Add, Sub};
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use oldtime::Duration as OldDuration; use oldtime::Duration as OldDuration;
#[cfg(any(feature = "alloc", feature = "std", test))] #[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::string::{String, ToString}; use alloc::string::{String, ToString};
#[cfg(feature = "std")]
use std::string::ToString;
use {Weekday, Timelike, Datelike}; use {Weekday, Timelike, Datelike};
#[cfg(feature="clock")] #[cfg(feature="clock")]
@ -921,26 +923,50 @@ pub mod rustc_serialize {
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
pub mod serde { pub mod serde {
use core::fmt; use core::fmt;
#[cfg(not(any(feature = "std", test)))] // #[cfg(any(test, feature = "alloc"))]
use alloc::format; // use alloc::format;
use super::DateTime; use super::DateTime;
#[cfg(feature="clock")] #[cfg(feature="clock")]
use offset::Local; use offset::Local;
use offset::{LocalResult, TimeZone, Utc, FixedOffset}; use offset::{LocalResult, TimeZone, Utc, FixedOffset};
use serdelib::{ser, de}; use serdelib::{ser, de};
enum SerdeError<V: fmt::Display, D: fmt::Display> {
NonExistent { timestamp: V },
Ambiguous { timestamp: V, min: D, max: D }
}
impl<V: fmt::Display, D: fmt::Display> fmt::Debug for SerdeError<V, D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ChronoSerdeError({})", self)
}
}
// impl<V: fmt::Display, D: fmt::Debug> core::error::Error for SerdeError<V, D> {}
impl<V: fmt::Display, D: fmt::Display> fmt::Display for SerdeError<V, D> {
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 // try!-like function to convert a LocalResult into a serde-ish Result
fn serde_from<T, E, V>(me: LocalResult<T>, ts: &V) -> Result<T, E> fn serde_from<T, E, V>(me: LocalResult<T>, ts: &V) -> Result<T, E>
where E: de::Error, where
E: de::Error,
V: fmt::Display, V: fmt::Display,
T: fmt::Display, T: fmt::Display,
{ {
match me { match me {
LocalResult::None => Err(E::custom( 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( LocalResult::Ambiguous(min, max) => Err(E::custom(
format!("value is an ambiguous timestamp: {}, could be either of {}, {}", SerdeError::Ambiguous { timestamp: ts, min: min, max: max })),
ts, min, max))),
LocalResult::Single(val) => Ok(val) LocalResult::Single(val) => Ok(val)
} }
} }
@ -1418,7 +1444,7 @@ pub mod serde {
fn visit_str<E>(self, value: &str) -> Result<DateTime<FixedOffset>, E> fn visit_str<E>(self, value: &str) -> Result<DateTime<FixedOffset>, E>
where E: de::Error where E: de::Error
{ {
value.parse().map_err(|err| E::custom(format!("{}", err))) value.parse().map_err(|err: ::format::ParseError| E::custom(err))
} }
} }

View File

@ -21,9 +21,9 @@ use core::fmt;
use core::str::FromStr; use core::str::FromStr;
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
use std::error::Error; use std::error::Error;
#[cfg(any(feature = "alloc", feature = "std", test))] #[cfg(feature = "alloc")]
use alloc::boxed::Box; use alloc::boxed::Box;
#[cfg(any(feature = "alloc", feature = "std", test))] #[cfg(feature = "alloc")]
use alloc::string::{String, ToString}; use alloc::string::{String, ToString};
#[cfg(not(any(feature = "alloc", feature = "std", test)))] #[cfg(not(any(feature = "alloc", feature = "std", test)))]

View File

@ -405,11 +405,11 @@
trivially_copy_pass_by_ref, trivially_copy_pass_by_ref,
))] ))]
#[cfg(not(any(feature = "std", test)))] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
extern crate std as core; extern crate std as core;
#[cfg(any(feature = "std", test))] #[cfg(all(feature = "std", not(feature="alloc")))]
extern crate std as alloc; extern crate std as alloc;
#[cfg(feature="clock")] #[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 /// 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. /// [`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. /// Do not heavily depend on this though; use explicit methods whenever possible.
@ -707,15 +721,13 @@ impl fmt::Debug for ParseWeekdayError {
mod weekday_serde { mod weekday_serde {
use super::Weekday; use super::Weekday;
use core::fmt; use core::fmt;
#[cfg(not(any(feature = "std", test)))]
use alloc::format;
use serdelib::{ser, de}; use serdelib::{ser, de};
impl ser::Serialize for Weekday { impl ser::Serialize for Weekday {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer where S: ser::Serializer
{ {
serializer.serialize_str(&format!("{:?}", self)) serializer.collect_str(&self)
} }
} }

View File

@ -1605,8 +1605,6 @@ mod rustc_serialize {
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
mod serde { mod serde {
use core::fmt; use core::fmt;
#[cfg(not(any(feature = "std", test)))]
use alloc::format;
use super::NaiveDate; use super::NaiveDate;
use serdelib::{ser, de}; use serdelib::{ser, de};
@ -1640,11 +1638,19 @@ mod serde {
write!(formatter, "a formatted date string") write!(formatter, "a formatted date string")
} }
#[cfg(any(feature = "std", test))]
fn visit_str<E>(self, value: &str) -> Result<NaiveDate, E> fn visit_str<E>(self, value: &str) -> Result<NaiveDate, E>
where E: de::Error where E: de::Error
{ {
value.parse().map_err(|err| E::custom(format!("{}", err))) value.parse().map_err(|err| E::custom(format!("{}", err)))
} }
#[cfg(not(any(feature = "std", test)))]
fn visit_str<E>(self, value: &str) -> Result<NaiveDate, E>
where E: de::Error
{
value.parse().map_err(|err| E::custom(err))
}
} }
impl<'de> de::Deserialize<'de> for NaiveDate { impl<'de> de::Deserialize<'de> for NaiveDate {

View File

@ -1668,7 +1668,7 @@ pub mod rustc_serialize {
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
pub mod serde { pub mod serde {
use core::fmt; use core::fmt;
#[cfg(not(any(feature = "std", test)))] #[cfg(feature = "alloc")]
use alloc::format; use alloc::format;
use super::{NaiveDateTime}; use super::{NaiveDateTime};
use serdelib::{ser, de}; use serdelib::{ser, de};

View File

@ -1416,7 +1416,7 @@ mod rustc_serialize {
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
mod serde { mod serde {
use core::fmt; use core::fmt;
#[cfg(not(any(feature = "std", test)))] #[cfg(feature = "alloc")]
use alloc::format; use alloc::format;
use super::NaiveTime; use super::NaiveTime;
use serdelib::{ser, de}; use serdelib::{ser, de};