#![cfg_attr(feature = "i128", feature(i128_type))]
#![cfg_attr(feature = "proc-macro", feature(proc_macro))]
#[cfg(feature = "proc-macro")]
extern crate proc_macro;
#[cfg(feature = "proc-macro2")]
extern crate proc_macro2;
#[cfg(feature = "dummy")]
use std::fmt;
mod internal;
mod test;
#[cfg(feature = "dummy")]
pub struct DummyLiteral<T: fmt::Display>(pub T);
#[cfg(feature = "dummy")]
impl<T: fmt::Display> fmt::Display for DummyLiteral<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
#[cfg(not(feature = "i128"))]
type RawInt = u64;
#[cfg(feature = "i128")]
type RawInt = u128;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct IntLit {
val: Option<RawInt>, suffix: &'static str,
}
macro_rules! as_int_type {
($name:ident, $t:ident) => {
pub fn $name(&self) -> Option<$t> {
if self.suffix != "" &&
self.suffix != stringify!($t) {
return None;
}
self.val.and_then(|v| {
if v > ($t::max_value() as RawInt) {
None
} else {
Some(v as $t)
}
})
}
}
}
impl IntLit {
pub fn suffix(&self) -> &str {
&self.suffix
}
as_int_type!(as_u8, u8);
as_int_type!(as_i8, i8);
as_int_type!(as_u16, u16);
as_int_type!(as_i16, i16);
as_int_type!(as_u32, u32);
as_int_type!(as_i32, i32);
as_int_type!(as_u64, u64);
as_int_type!(as_i64, i64);
#[cfg(feature = "i128")]
as_int_type!(as_u128, u128);
#[cfg(feature = "i128")]
as_int_type!(as_i128, i128);
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct FloatLit {
val: f64,
suffix: &'static str,
}
macro_rules! as_float_type {
($name:ident, $t:ident) => {
pub fn $name(&self) -> Option<$t> {
if self.suffix != "" && self.suffix != stringify!($t) {
return None
} else {
Some(self.val as $t)
}
}
}
}
impl FloatLit {
pub fn suffix(&self) -> &str {
&self.suffix
}
as_float_type!(as_f32, f32);
as_float_type!(as_f64, f64);
}
pub trait LiteralExt {
fn parse_int(&self) -> Option<IntLit>;
fn parse_float(&self) -> Option<FloatLit>;
fn parse_string(&self) -> Option<String>;
fn parse_char(&self) -> Option<char>;
fn parse_bytes(&self) -> Option<Vec<u8>>;
fn parse_byte(&self) -> Option<u8>;
fn parse_inner_doc(&self) -> Option<String>;
fn parse_outer_doc(&self) -> Option<String>;
}
macro_rules! impl_literal {
() => {
fn parse_int(&self) -> Option<IntLit> {
$crate::internal::int_lit(&self.to_string())
}
fn parse_float(&self) -> Option<FloatLit> {
$crate::internal::float_lit(self.to_string())
}
fn parse_string(&self) -> Option<String> {
$crate::internal::str_lit(&self.to_string())
}
fn parse_char(&self) -> Option<char> {
$crate::internal::char_lit(&self.to_string())
}
fn parse_bytes(&self) -> Option<Vec<u8>> {
$crate::internal::byte_str_lit(&self.to_string())
}
fn parse_byte(&self) -> Option<u8> {
$crate::internal::byte_lit(&self.to_string())
}
fn parse_inner_doc(&self) -> Option<String> {
$crate::internal::inner_doc(self.to_string())
}
fn parse_outer_doc(&self) -> Option<String> {
$crate::internal::outer_doc(self.to_string())
}
}
}
#[cfg(feature = "dummy")]
impl<T: fmt::Display> LiteralExt for DummyLiteral<T> {
impl_literal!();
}
#[cfg(feature = "proc-macro")]
impl LiteralExt for proc_macro::Literal {
impl_literal!();
}
#[cfg(feature = "proc-macro2")]
impl LiteralExt for proc_macro2::Literal {
impl_literal!();
}