57 lines
1.6 KiB
Rust
57 lines
1.6 KiB
Rust
use std::iter::Peekable;
|
|
|
|
use proc_macro::{token_stream, Ident, Span, TokenTree};
|
|
|
|
use crate::date::Date;
|
|
use crate::error::Error;
|
|
use crate::offset::Offset;
|
|
use crate::time::Time;
|
|
use crate::to_tokens::ToTokenTree;
|
|
use crate::{date, offset, time};
|
|
|
|
pub(crate) struct DateTime {
|
|
date: Date,
|
|
time: Time,
|
|
offset: Option<Offset>,
|
|
}
|
|
|
|
pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<DateTime, Error> {
|
|
let date = date::parse(chars)?;
|
|
let time = time::parse(chars)?;
|
|
let offset = match offset::parse(chars) {
|
|
Ok(offset) => Some(offset),
|
|
Err(Error::UnexpectedEndOfInput | Error::MissingComponent { name: "sign", .. }) => None,
|
|
Err(err) => return Err(err),
|
|
};
|
|
|
|
if let Some(token) = chars.peek() {
|
|
return Err(Error::UnexpectedToken {
|
|
tree: token.clone(),
|
|
});
|
|
}
|
|
|
|
Ok(DateTime { date, time, offset })
|
|
}
|
|
|
|
impl ToTokenTree for DateTime {
|
|
fn into_token_tree(self) -> TokenTree {
|
|
let (type_name, maybe_offset) = match self.offset {
|
|
Some(offset) => (
|
|
Ident::new("OffsetDateTime", Span::mixed_site()),
|
|
quote!(.assume_offset(#(offset))),
|
|
),
|
|
None => (
|
|
Ident::new("PrimitiveDateTime", Span::mixed_site()),
|
|
quote!(),
|
|
),
|
|
};
|
|
|
|
quote_group! {{
|
|
const DATE_TIME: ::time::#(type_name) = ::time::PrimitiveDateTime::new(
|
|
#(self.date),
|
|
#(self.time),
|
|
) #S(maybe_offset);
|
|
DATE_TIME
|
|
}}
|
|
}
|
|
}
|