1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
use std::iter::Peekable;
use proc_macro::{token_stream, Span, TokenTree};
use time_core::convert::*;
use crate::helpers::{consume_any_ident, consume_number, consume_punct};
use crate::to_tokens::ToTokenTree;
use crate::Error;
pub(crate) struct Offset {
pub(crate) hours: i8,
pub(crate) minutes: i8,
pub(crate) seconds: i8,
}
pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<Offset, Error> {
if consume_any_ident(&["utc", "UTC"], chars).is_ok() {
return Ok(Offset {
hours: 0,
minutes: 0,
seconds: 0,
});
}
let sign = if consume_punct('+', chars).is_ok() {
1
} else if consume_punct('-', chars).is_ok() {
-1
} else if let Some(tree) = chars.next() {
return Err(Error::UnexpectedToken { tree });
} else {
return Err(Error::MissingComponent {
name: "sign",
span_start: None,
span_end: None,
});
};
let (hours_span, hours) = consume_number::<i8>("hour", chars)?;
let (mut minutes_span, mut minutes) = (Span::mixed_site(), 0);
let (mut seconds_span, mut seconds) = (Span::mixed_site(), 0);
if consume_punct(':', chars).is_ok() {
let min = consume_number::<i8>("minute", chars)?;
minutes_span = min.0;
minutes = min.1;
if consume_punct(':', chars).is_ok() {
let sec = consume_number::<i8>("second", chars)?;
seconds_span = sec.0;
seconds = sec.1;
}
}
if hours >= 24 {
Err(Error::InvalidComponent {
name: "hour",
value: hours.to_string(),
span_start: Some(hours_span),
span_end: Some(hours_span),
})
} else if minutes >= Minute::per(Hour) as _ {
Err(Error::InvalidComponent {
name: "minute",
value: minutes.to_string(),
span_start: Some(minutes_span),
span_end: Some(minutes_span),
})
} else if seconds >= Second::per(Minute) as _ {
Err(Error::InvalidComponent {
name: "second",
value: seconds.to_string(),
span_start: Some(seconds_span),
span_end: Some(seconds_span),
})
} else {
Ok(Offset {
hours: sign * hours,
minutes: sign * minutes,
seconds: sign * seconds,
})
}
}
impl ToTokenTree for Offset {
fn into_token_tree(self) -> TokenTree {
quote_group! {{
const OFFSET: ::time::UtcOffset = unsafe {
::time::UtcOffset::__from_hms_unchecked(
#(self.hours),
#(self.minutes),
#(self.seconds),
)
};
OFFSET
}}
}
}
|