1 | //! # Feature flags |
2 | //! |
3 | //! This crate exposes a number of features. These can be enabled or disabled as shown |
4 | //! [in Cargo's documentation](https://doc.rust-lang.org/cargo/reference/features.html). Features |
5 | //! are _disabled_ by default unless otherwise noted. |
6 | //! |
7 | //! Reliance on a given feature is always indicated alongside the item definition. |
8 | //! |
9 | //! - `std` (_enabled by default, implicitly enables `alloc`_) |
10 | //! |
11 | //! This enables a number of features that depend on the standard library. |
12 | //! |
13 | //! - `alloc` (_enabled by default via `std`_) |
14 | //! |
15 | //! Enables a number of features that require the ability to dynamically allocate memory. |
16 | //! |
17 | //! - `macros` |
18 | //! |
19 | //! Enables macros that provide compile-time verification of values and intuitive syntax. |
20 | //! |
21 | //! - `formatting` (_implicitly enables `std`_) |
22 | //! |
23 | //! Enables formatting of most structs. |
24 | //! |
25 | //! - `parsing` |
26 | //! |
27 | //! Enables parsing of most structs. |
28 | //! |
29 | //! - `local-offset` (_implicitly enables `std`_) |
30 | //! |
31 | //! This feature enables a number of methods that allow obtaining the system's UTC offset. |
32 | //! |
33 | //! - `large-dates` |
34 | //! |
35 | //! By default, only years within the ±9999 range (inclusive) are supported. If you need support |
36 | //! for years outside this range, consider enabling this feature; the supported range will be |
37 | //! increased to ±999,999. |
38 | //! |
39 | //! Note that enabling this feature has some costs, as it means forgoing some optimizations. |
40 | //! Ambiguities may be introduced when parsing that would not otherwise exist. |
41 | //! |
42 | //! - `serde` |
43 | //! |
44 | //! Enables [serde](https://docs.rs/serde) support for all types except [`Instant`]. |
45 | //! |
46 | //! - `serde-human-readable` (_implicitly enables `serde`, `formatting`, and `parsing`_) |
47 | //! |
48 | //! Allows serde representations to use a human-readable format. This is determined by the |
49 | //! serializer, not the user. If this feature is not enabled or if the serializer requests a |
50 | //! non-human-readable format, a format optimized for binary representation will be used. |
51 | //! |
52 | //! Libraries should never enable this feature, as the decision of what format to use should be up |
53 | //! to the user. |
54 | //! |
55 | //! - `serde-well-known` (_implicitly enables `serde-human-readable`_) |
56 | //! |
57 | //! _This feature flag is deprecated and will be removed in a future breaking release. Use the |
58 | //! `serde-human-readable` feature instead._ |
59 | //! |
60 | //! Enables support for serializing and deserializing well-known formats using serde's |
61 | //! [`#[with]` attribute](https://serde.rs/field-attrs.html#with). |
62 | //! |
63 | //! - `rand` |
64 | //! |
65 | //! Enables [rand](https://docs.rs/rand) support for all types. |
66 | //! |
67 | //! - `quickcheck` (_implicitly enables `alloc`_) |
68 | //! |
69 | //! Enables [quickcheck](https://docs.rs/quickcheck) support for all types except [`Instant`]. |
70 | //! |
71 | //! - `wasm-bindgen` |
72 | //! |
73 | //! Enables [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) support for converting |
74 | //! [JavaScript dates](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Date.html), as |
75 | //! well as obtaining the UTC offset from JavaScript. |
76 | |
77 | #![doc (html_playground_url = "https://play.rust-lang.org" )] |
78 | #![cfg_attr (__time_03_docs, feature(doc_auto_cfg, doc_notable_trait))] |
79 | #![cfg_attr (coverage_nightly, feature(no_coverage))] |
80 | #![cfg_attr (not(feature = "std" ), no_std)] |
81 | #![deny ( |
82 | anonymous_parameters, |
83 | clippy::all, |
84 | clippy::alloc_instead_of_core, |
85 | clippy::explicit_auto_deref, |
86 | clippy::obfuscated_if_else, |
87 | clippy::std_instead_of_core, |
88 | clippy::undocumented_unsafe_blocks, |
89 | illegal_floating_point_literal_pattern, |
90 | late_bound_lifetime_arguments, |
91 | path_statements, |
92 | patterns_in_fns_without_body, |
93 | rust_2018_idioms, |
94 | trivial_casts, |
95 | trivial_numeric_casts, |
96 | unreachable_pub, |
97 | unsafe_op_in_unsafe_fn, |
98 | unused_extern_crates, |
99 | rustdoc::broken_intra_doc_links, |
100 | rustdoc::private_intra_doc_links |
101 | )] |
102 | #![warn ( |
103 | clippy::dbg_macro, |
104 | clippy::decimal_literal_representation, |
105 | clippy::get_unwrap, |
106 | clippy::missing_docs_in_private_items, |
107 | clippy::nursery, |
108 | clippy::print_stdout, |
109 | clippy::todo, |
110 | clippy::unimplemented, |
111 | clippy::uninlined_format_args, |
112 | clippy::unnested_or_patterns, |
113 | clippy::unwrap_in_result, |
114 | clippy::unwrap_used, |
115 | clippy::use_debug, |
116 | deprecated_in_future, |
117 | missing_copy_implementations, |
118 | missing_debug_implementations, |
119 | unused_qualifications, |
120 | variant_size_differences |
121 | )] |
122 | #![allow ( |
123 | clippy::redundant_pub_crate, // suggests bad style |
124 | clippy::option_if_let_else, // suggests terrible code |
125 | clippy::unused_peekable, // temporary due to bug: remove when Rust 1.66 is released |
126 | clippy::std_instead_of_core, // temporary due to bug: remove when Rust 1.66 is released |
127 | )] |
128 | #![doc (html_favicon_url = "https://avatars0.githubusercontent.com/u/55999857" )] |
129 | #![doc (html_logo_url = "https://avatars0.githubusercontent.com/u/55999857" )] |
130 | #![doc (test(attr(deny(warnings))))] |
131 | |
132 | #[allow (unused_extern_crates)] |
133 | #[cfg (feature = "alloc" )] |
134 | extern crate alloc; |
135 | |
136 | // TODO(jhpratt) remove this after a while |
137 | #[cfg (unsound_local_offset)] |
138 | compile_error!( |
139 | "The `unsound_local_offset` flag was removed in time 0.3.18. If you need this functionality, \ |
140 | see the `time::util::local_offset::set_soundness` function." |
141 | ); |
142 | |
143 | // region: macros |
144 | /// Helper macro for easily implementing `OpAssign`. |
145 | macro_rules! __impl_assign { |
146 | ($sym:tt $op:ident $fn:ident $target:ty : $($(#[$attr:meta])* $t:ty),+) => {$( |
147 | #[allow(unused_qualifications)] |
148 | $(#[$attr])* |
149 | impl core::ops::$op<$t> for $target { |
150 | fn $fn(&mut self, rhs: $t) { |
151 | *self = *self $sym rhs; |
152 | } |
153 | } |
154 | )+}; |
155 | } |
156 | |
157 | /// Implement `AddAssign` for the provided types. |
158 | macro_rules! impl_add_assign { |
159 | ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => { |
160 | __impl_assign!(+ AddAssign add_assign $target : $($(#[$attr])* $t),+); |
161 | }; |
162 | } |
163 | |
164 | /// Implement `SubAssign` for the provided types. |
165 | macro_rules! impl_sub_assign { |
166 | ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => { |
167 | __impl_assign!(- SubAssign sub_assign $target : $($(#[$attr])* $t),+); |
168 | }; |
169 | } |
170 | |
171 | /// Implement `MulAssign` for the provided types. |
172 | macro_rules! impl_mul_assign { |
173 | ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => { |
174 | __impl_assign!(* MulAssign mul_assign $target : $($(#[$attr])* $t),+); |
175 | }; |
176 | } |
177 | |
178 | /// Implement `DivAssign` for the provided types. |
179 | macro_rules! impl_div_assign { |
180 | ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => { |
181 | __impl_assign!(/ DivAssign div_assign $target : $($(#[$attr])* $t),+); |
182 | }; |
183 | } |
184 | |
185 | /// Division of integers, rounding the resulting value towards negative infinity. |
186 | macro_rules! div_floor { |
187 | ($a:expr, $b:expr) => {{ |
188 | let _a = $a; |
189 | let _b = $b; |
190 | |
191 | let (_quotient, _remainder) = (_a / _b, _a % _b); |
192 | |
193 | if (_remainder > 0 && _b < 0) || (_remainder < 0 && _b > 0) { |
194 | _quotient - 1 |
195 | } else { |
196 | _quotient |
197 | } |
198 | }}; |
199 | } |
200 | |
201 | /// Cascade an out-of-bounds value. |
202 | macro_rules! cascade { |
203 | (@ordinal ordinal) => {}; |
204 | (@year year) => {}; |
205 | |
206 | // Cascade an out-of-bounds value from "from" to "to". |
207 | ($from:ident in $min:literal.. $max:expr => $to:tt) => { |
208 | #[allow(unused_comparisons, unused_assignments)] |
209 | let min = $min; |
210 | let max = $max; |
211 | if $from >= max { |
212 | $from -= max - min; |
213 | $to += 1; |
214 | } else if $from < min { |
215 | $from += max - min; |
216 | $to -= 1; |
217 | } |
218 | }; |
219 | |
220 | // Special case the ordinal-to-year cascade, as it has different behavior. |
221 | ($ordinal:ident => $year:ident) => { |
222 | // We need to actually capture the idents. Without this, macro hygiene causes errors. |
223 | cascade!(@ordinal $ordinal); |
224 | cascade!(@year $year); |
225 | #[allow(unused_assignments)] |
226 | if $ordinal > crate::util::days_in_year($year) as i16 { |
227 | $ordinal -= crate::util::days_in_year($year) as i16; |
228 | $year += 1; |
229 | } else if $ordinal < 1 { |
230 | $year -= 1; |
231 | $ordinal += crate::util::days_in_year($year) as i16; |
232 | } |
233 | }; |
234 | } |
235 | |
236 | /// Returns `Err(error::ComponentRange)` if the value is not in range. |
237 | macro_rules! ensure_value_in_range { |
238 | ($value:ident in $start:expr => $end:expr) => {{ |
239 | let _start = $start; |
240 | let _end = $end; |
241 | #[allow(trivial_numeric_casts, unused_comparisons)] |
242 | if $value < _start || $value > _end { |
243 | return Err(crate::error::ComponentRange { |
244 | name: stringify!($value), |
245 | minimum: _start as _, |
246 | maximum: _end as _, |
247 | value: $value as _, |
248 | conditional_range: false, |
249 | }); |
250 | } |
251 | }}; |
252 | |
253 | ($value:ident conditionally in $start:expr => $end:expr) => {{ |
254 | let _start = $start; |
255 | let _end = $end; |
256 | #[allow(trivial_numeric_casts, unused_comparisons)] |
257 | if $value < _start || $value > _end { |
258 | return Err(crate::error::ComponentRange { |
259 | name: stringify!($value), |
260 | minimum: _start as _, |
261 | maximum: _end as _, |
262 | value: $value as _, |
263 | conditional_range: true, |
264 | }); |
265 | } |
266 | }}; |
267 | } |
268 | |
269 | /// Try to unwrap an expression, returning if not possible. |
270 | /// |
271 | /// This is similar to the `?` operator, but does not perform `.into()`. Because of this, it is |
272 | /// usable in `const` contexts. |
273 | macro_rules! const_try { |
274 | ($e:expr) => { |
275 | match $e { |
276 | Ok(value) => value, |
277 | Err(error) => return Err(error), |
278 | } |
279 | }; |
280 | } |
281 | |
282 | /// Try to unwrap an expression, returning if not possible. |
283 | /// |
284 | /// This is similar to the `?` operator, but is usable in `const` contexts. |
285 | macro_rules! const_try_opt { |
286 | ($e:expr) => { |
287 | match $e { |
288 | Some(value) => value, |
289 | None => return None, |
290 | } |
291 | }; |
292 | } |
293 | |
294 | /// Try to unwrap an expression, panicking if not possible. |
295 | /// |
296 | /// This is similar to `$e.expect($message)`, but is usable in `const` contexts. |
297 | macro_rules! expect_opt { |
298 | ($e:expr, $message:literal) => { |
299 | match $e { |
300 | Some(value) => value, |
301 | None => crate::expect_failed($message), |
302 | } |
303 | }; |
304 | } |
305 | |
306 | /// `unreachable!()`, but better. |
307 | macro_rules! bug { |
308 | () => { compile_error!("provide an error message to help fix a possible bug" ) }; |
309 | ($descr:literal $($rest:tt)?) => { |
310 | panic!(concat!("internal error: " , $descr) $($rest)?) |
311 | } |
312 | } |
313 | // endregion macros |
314 | |
315 | mod date; |
316 | mod date_time; |
317 | mod duration; |
318 | pub mod error; |
319 | pub mod ext; |
320 | #[cfg (any(feature = "formatting" , feature = "parsing" ))] |
321 | pub mod format_description; |
322 | #[cfg (feature = "formatting" )] |
323 | pub mod formatting; |
324 | #[cfg (feature = "std" )] |
325 | mod instant; |
326 | #[cfg (feature = "macros" )] |
327 | pub mod macros; |
328 | mod month; |
329 | mod offset_date_time; |
330 | #[cfg (feature = "parsing" )] |
331 | pub mod parsing; |
332 | mod primitive_date_time; |
333 | #[cfg (feature = "quickcheck" )] |
334 | mod quickcheck; |
335 | #[cfg (feature = "rand" )] |
336 | mod rand; |
337 | #[cfg (feature = "serde" )] |
338 | #[allow (missing_copy_implementations, missing_debug_implementations)] |
339 | pub mod serde; |
340 | mod sys; |
341 | #[cfg (test)] |
342 | mod tests; |
343 | mod time; |
344 | mod utc_offset; |
345 | pub mod util; |
346 | mod weekday; |
347 | |
348 | // Not public yet. |
349 | use time_core::convert; |
350 | |
351 | pub use crate::date::Date; |
352 | use crate::date_time::DateTime; |
353 | pub use crate::duration::Duration; |
354 | pub use crate::error::Error; |
355 | #[cfg (feature = "std" )] |
356 | pub use crate::instant::Instant; |
357 | pub use crate::month::Month; |
358 | pub use crate::offset_date_time::OffsetDateTime; |
359 | pub use crate::primitive_date_time::PrimitiveDateTime; |
360 | pub use crate::time::Time; |
361 | pub use crate::utc_offset::UtcOffset; |
362 | pub use crate::weekday::Weekday; |
363 | |
364 | /// An alias for [`std::result::Result`] with a generic error from the time crate. |
365 | pub type Result<T> = core::result::Result<T, Error>; |
366 | |
367 | /// This is a separate function to reduce the code size of `expect_opt!`. |
368 | #[inline (never)] |
369 | #[cold ] |
370 | #[track_caller ] |
371 | const fn expect_failed(message: &str) -> ! { |
372 | panic!("{}" , message) |
373 | } |
374 | |