1 | use std::iter::Peekable; |
2 | |
3 | use proc_macro::{token_stream, Ident, Span, TokenTree}; |
4 | |
5 | use crate::date::Date; |
6 | use crate::error::Error; |
7 | use crate::offset::Offset; |
8 | use crate::time::Time; |
9 | use crate::to_tokens::ToTokenTree; |
10 | use crate::{date, offset, time}; |
11 | |
12 | pub(crate) struct DateTime { |
13 | date: Date, |
14 | time: Time, |
15 | offset: Option<Offset>, |
16 | } |
17 | |
18 | pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<DateTime, Error> { |
19 | let date: Date = date::parse(chars)?; |
20 | let time: Time = time::parse(chars)?; |
21 | let offset: Option = match offset::parse(chars) { |
22 | Ok(offset: Offset) => Some(offset), |
23 | Err(Error::UnexpectedEndOfInput | Error::MissingComponent { name: "sign" , .. }) => None, |
24 | Err(err: Error) => return Err(err), |
25 | }; |
26 | |
27 | if let Some(token: &TokenTree) = chars.peek() { |
28 | return Err(Error::UnexpectedToken { |
29 | tree: token.clone(), |
30 | }); |
31 | } |
32 | |
33 | Ok(DateTime { date, time, offset }) |
34 | } |
35 | |
36 | impl ToTokenTree for DateTime { |
37 | fn into_token_tree(self) -> TokenTree { |
38 | let (type_name: Ident, maybe_offset: TokenStream) = match self.offset { |
39 | Some(offset: Offset) => ( |
40 | Ident::new(string:"OffsetDateTime" , Span::mixed_site()), |
41 | quote!(.assume_offset(#(offset))), |
42 | ), |
43 | None => ( |
44 | Ident::new(string:"PrimitiveDateTime" , Span::mixed_site()), |
45 | quote!(), |
46 | ), |
47 | }; |
48 | |
49 | quote_group! {{ |
50 | const DATE_TIME: ::time::#(type_name) = ::time::PrimitiveDateTime::new( |
51 | #(self.date), |
52 | #(self.time), |
53 | ) #S(maybe_offset); |
54 | DATE_TIME |
55 | }} |
56 | } |
57 | } |
58 | |