diff --git a/Cargo.toml b/Cargo.toml index f9870652f..072e66128 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,14 +28,14 @@ rustdoc-args = ["--cfg", "__time_03_docs"] [features] default = ["std"] alloc = ["serde?/alloc"] -formatting = ["dep:itoa", "std"] +formatting = ["dep:itoa", "std", "time-macros?/formatting"] large-dates = ["time-macros?/large-dates"] local-offset = ["std"] macros = ["dep:time-macros"] -parsing = [] +parsing = ["time-macros?/parsing"] quickcheck = ["dep:quickcheck", "alloc"] rand = ["dep:rand"] -serde = ["dep:serde"] +serde = ["dep:serde", "time-macros?/serde"] serde-human-readable = ["serde", "formatting", "parsing"] # Deprecated in favor of `serde-human-readable`. serde-well-known = ["serde-human-readable"] diff --git a/time-macros/Cargo.toml b/time-macros/Cargo.toml index 74ed48733..a30911e78 100644 --- a/time-macros/Cargo.toml +++ b/time-macros/Cargo.toml @@ -12,7 +12,10 @@ license = "MIT OR Apache-2.0" description = "Procedural macros for the time crate." [features] +formatting = [] large-dates = [] +parsing = [] +serde = [] [lib] proc-macro = true diff --git a/time-macros/src/error.rs b/time-macros/src/error.rs index d5cf315e3..4de369daf 100644 --- a/time-macros/src/error.rs +++ b/time-macros/src/error.rs @@ -1,9 +1,9 @@ use std::borrow::Cow; use std::fmt; -use std::iter::once; use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +#[cfg(any(feature = "formatting", feature = "parsing"))] use crate::format_description::error::InvalidFormatDescription; trait WithSpan { @@ -29,6 +29,7 @@ pub(crate) enum Error { span_start: Option, span_end: Option, }, + #[cfg(any(feature = "formatting", feature = "parsing"))] ExpectedString { span_start: Option, span_end: Option, @@ -37,6 +38,7 @@ pub(crate) enum Error { tree: TokenTree, }, UnexpectedEndOfInput, + #[cfg(any(feature = "formatting", feature = "parsing"))] InvalidFormatDescription { error: InvalidFormatDescription, span_start: Option, @@ -56,9 +58,11 @@ impl fmt::Display for Error { Self::InvalidComponent { name, value, .. } => { write!(f, "invalid component: {name} was {value}") } + #[cfg(any(feature = "formatting", feature = "parsing"))] Self::ExpectedString { .. } => f.write_str("expected string"), Self::UnexpectedToken { tree } => write!(f, "unexpected token: {tree}"), Self::UnexpectedEndOfInput => f.write_str("unexpected end of input"), + #[cfg(any(feature = "formatting", feature = "parsing"))] Self::InvalidFormatDescription { error, .. } => error.fmt(f), Self::Custom { message, .. } => f.write_str(message), } @@ -70,9 +74,10 @@ impl Error { match self { Self::MissingComponent { span_start, .. } | Self::InvalidComponent { span_start, .. } - | Self::ExpectedString { span_start, .. } - | Self::InvalidFormatDescription { span_start, .. } | Self::Custom { span_start, .. } => *span_start, + #[cfg(any(feature = "formatting", feature = "parsing"))] + Self::ExpectedString { span_start, .. } + | Self::InvalidFormatDescription { span_start, .. } => *span_start, Self::UnexpectedToken { tree } => Some(tree.span()), Self::UnexpectedEndOfInput => Some(Span::mixed_site()), } @@ -83,9 +88,10 @@ impl Error { match self { Self::MissingComponent { span_end, .. } | Self::InvalidComponent { span_end, .. } - | Self::ExpectedString { span_end, .. } - | Self::InvalidFormatDescription { span_end, .. } | Self::Custom { span_end, .. } => *span_end, + #[cfg(any(feature = "formatting", feature = "parsing"))] + Self::ExpectedString { span_end, .. } + | Self::InvalidFormatDescription { span_end, .. } => *span_end, Self::UnexpectedToken { tree, .. } => Some(tree.span()), Self::UnexpectedEndOfInput => Some(Span::mixed_site()), } @@ -117,11 +123,12 @@ impl Error { } /// Like `to_compile_error`, but for use in macros that produce items. + #[cfg(all(feature = "serde", any(feature = "formatting", feature = "parsing")))] pub(crate) fn to_compile_error_standalone(&self) -> TokenStream { let end = self.span_end(); self.to_compile_error() .into_iter() - .chain(once( + .chain(std::iter::once( TokenTree::from(Punct::new(';', Spacing::Alone)).with_span(end), )) .collect() diff --git a/time-macros/src/helpers/mod.rs b/time-macros/src/helpers/mod.rs index db618ab32..1a40dbb41 100644 --- a/time-macros/src/helpers/mod.rs +++ b/time-macros/src/helpers/mod.rs @@ -1,12 +1,16 @@ +#[cfg(any(feature = "formatting", feature = "parsing"))] mod string; use std::iter::Peekable; use std::str::FromStr; -use proc_macro::{token_stream, Span, TokenStream, TokenTree}; +#[cfg(any(feature = "formatting", feature = "parsing"))] +use proc_macro::TokenStream; +use proc_macro::{token_stream, Span, TokenTree}; use crate::Error; +#[cfg(any(feature = "formatting", feature = "parsing"))] pub(crate) fn get_string_literal(tokens: TokenStream) -> Result<(Span, Vec), Error> { let mut tokens = tokens.into_iter(); diff --git a/time-macros/src/lib.rs b/time-macros/src/lib.rs index f8c296d54..eecb0bace 100644 --- a/time-macros/src/lib.rs +++ b/time-macros/src/lib.rs @@ -36,14 +36,18 @@ mod quote; mod date; mod datetime; mod error; +#[cfg(any(feature = "formatting", feature = "parsing"))] mod format_description; mod helpers; mod offset; +#[cfg(all(feature = "serde", any(feature = "formatting", feature = "parsing")))] mod serde_format_description; mod time; mod to_tokens; -use proc_macro::{TokenStream, TokenTree}; +use proc_macro::TokenStream; +#[cfg(all(feature = "serde", any(feature = "formatting", feature = "parsing")))] +use proc_macro::TokenTree; use self::error::Error; @@ -67,8 +71,7 @@ macro_rules! impl_macros { impl_macros![date datetime offset time]; -// TODO Gate this behind the the `formatting` or `parsing` feature flag when weak dependency -// features land. +#[cfg(any(feature = "formatting", feature = "parsing"))] #[proc_macro] pub fn format_description(input: TokenStream) -> TokenStream { (|| { @@ -88,6 +91,7 @@ pub fn format_description(input: TokenStream) -> TokenStream { .unwrap_or_else(|err: Error| err.to_compile_error()) } +#[cfg(all(feature = "serde", any(feature = "formatting", feature = "parsing")))] #[proc_macro] pub fn serde_format_description(input: TokenStream) -> TokenStream { (|| { diff --git a/time-macros/src/quote.rs b/time-macros/src/quote.rs index d2b8ebfe3..61b9e3977 100644 --- a/time-macros/src/quote.rs +++ b/time-macros/src/quote.rs @@ -8,6 +8,7 @@ macro_rules! quote { }}; } +#[cfg(any(feature = "formatting", feature = "parsing"))] macro_rules! quote_append { ($ts:ident $($x:tt)*) => {{ quote_inner!($ts $($x)*);