| 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 | |