summaryrefslogtreecommitdiffstats
path: root/vendor/time-macros/src/time.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/time-macros/src/time.rs')
-rw-r--r--vendor/time-macros/src/time.rs118
1 files changed, 118 insertions, 0 deletions
diff --git a/vendor/time-macros/src/time.rs b/vendor/time-macros/src/time.rs
new file mode 100644
index 000000000..719e2051f
--- /dev/null
+++ b/vendor/time-macros/src/time.rs
@@ -0,0 +1,118 @@
+use std::iter::Peekable;
+
+use proc_macro::{token_stream, Span, TokenTree};
+
+use crate::helpers::{consume_any_ident, consume_number, consume_punct};
+use crate::to_tokens::ToTokenTree;
+use crate::Error;
+
+enum Period {
+ Am,
+ Pm,
+ _24,
+}
+
+pub(crate) struct Time {
+ pub(crate) hour: u8,
+ pub(crate) minute: u8,
+ pub(crate) second: u8,
+ pub(crate) nanosecond: u32,
+}
+
+pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<Time, Error> {
+ fn consume_period(chars: &mut Peekable<token_stream::IntoIter>) -> (Option<Span>, Period) {
+ if let Ok(span) = consume_any_ident(&["am", "AM"], chars) {
+ (Some(span), Period::Am)
+ } else if let Ok(span) = consume_any_ident(&["pm", "PM"], chars) {
+ (Some(span), Period::Pm)
+ } else {
+ (None, Period::_24)
+ }
+ }
+
+ let (hour_span, hour) = consume_number("hour", chars)?;
+
+ let ((minute_span, minute), (second_span, second), (period_span, period)) =
+ match consume_period(chars) {
+ // Nothing but the 12-hour clock hour and AM/PM
+ (period_span @ Some(_), period) => (
+ (Span::mixed_site(), 0),
+ (Span::mixed_site(), 0.),
+ (period_span, period),
+ ),
+ (None, _) => {
+ consume_punct(':', chars)?;
+ let (minute_span, minute) = consume_number::<u8>("minute", chars)?;
+ let (second_span, second): (_, f64) = if consume_punct(':', chars).is_ok() {
+ consume_number("second", chars)?
+ } else {
+ (Span::mixed_site(), 0.)
+ };
+ let (period_span, period) = consume_period(chars);
+ (
+ (minute_span, minute),
+ (second_span, second),
+ (period_span, period),
+ )
+ }
+ };
+
+ let hour = match (hour, period) {
+ (0, Period::Am | Period::Pm) => {
+ return Err(Error::InvalidComponent {
+ name: "hour",
+ value: hour.to_string(),
+ span_start: Some(hour_span),
+ span_end: Some(period_span.unwrap_or(hour_span)),
+ });
+ }
+ (12, Period::Am) => 0,
+ (12, Period::Pm) => 12,
+ (hour, Period::Am | Period::_24) => hour,
+ (hour, Period::Pm) => hour + 12,
+ };
+
+ if hour >= 24 {
+ Err(Error::InvalidComponent {
+ name: "hour",
+ value: hour.to_string(),
+ span_start: Some(hour_span),
+ span_end: Some(period_span.unwrap_or(hour_span)),
+ })
+ } else if minute >= 60 {
+ Err(Error::InvalidComponent {
+ name: "minute",
+ value: minute.to_string(),
+ span_start: Some(minute_span),
+ span_end: Some(minute_span),
+ })
+ } else if second >= 60. {
+ Err(Error::InvalidComponent {
+ name: "second",
+ value: second.to_string(),
+ span_start: Some(second_span),
+ span_end: Some(second_span),
+ })
+ } else {
+ Ok(Time {
+ hour,
+ minute,
+ second: second.trunc() as _,
+ nanosecond: (second.fract() * 1_000_000_000.).round() as _,
+ })
+ }
+}
+
+impl ToTokenTree for Time {
+ fn into_token_tree(self) -> TokenTree {
+ quote_group! {{
+ const TIME: ::time::Time = ::time::Time::__from_hms_nanos_unchecked(
+ #(self.hour),
+ #(self.minute),
+ #(self.second),
+ #(self.nanosecond),
+ );
+ TIME
+ }}
+ }
+}