1use std::iter::Peekable;
2
3use proc_macro::{token_stream, Ident, Span, TokenTree};
4
5use crate::date::Date;
6use crate::error::Error;
7use crate::offset::Offset;
8use crate::time::Time;
9use crate::to_tokens::ToTokenTree;
10use crate::{date, offset, time};
11
12pub(crate) struct DateTime {
13 date: Date,
14 time: Time,
15 offset: Option<Offset>,
16}
17
18pub(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
36impl 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