diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/time-macros/src/time.rs | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | third_party/rust/time-macros/src/time.rs | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/third_party/rust/time-macros/src/time.rs b/third_party/rust/time-macros/src/time.rs new file mode 100644 index 0000000000..719e2051f1 --- /dev/null +++ b/third_party/rust/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 + }} + } +} |