use syn::{spanned::Spanned, Error, Expr, Lit, LitBool, LitFloat, LitInt, LitStr};
pub trait FromMetaExpr: Sized {
fn try_from_expr(expr: Expr) -> syn::Result<Self>;
}
impl FromMetaExpr for Lit {
fn try_from_expr(expr: Expr) -> syn::Result<Self> {
if let Expr::Lit(lit) = expr {
return Ok(lit.lit);
}
Err(Error::new(expr.span(), "expected literal"))
}
}
impl FromMetaExpr for LitStr {
fn try_from_expr(expr: Expr) -> syn::Result<Self> {
if let Expr::Lit(lit) = &expr {
let lit = lit.lit.clone();
if let Lit::Str(lit) = lit {
return Ok(lit);
}
}
Err(Error::new(expr.span(), "expected litteral str"))
}
}
impl FromMetaExpr for LitInt {
fn try_from_expr(expr: Expr) -> syn::Result<Self> {
if let Expr::Lit(lit) = &expr {
let lit = lit.lit.clone();
if let Lit::Int(lit) = lit {
return Ok(lit);
}
}
Err(Error::new(expr.span(), "expected litteral int"))
}
}
impl FromMetaExpr for LitBool {
fn try_from_expr(expr: Expr) -> syn::Result<Self> {
if let Expr::Lit(lit) = &expr {
let lit = lit.lit.clone();
if let Lit::Bool(lit) = lit {
return Ok(lit);
}
}
Err(Error::new(expr.span(), "expected litteral bool"))
}
}
impl FromMetaExpr for LitFloat {
fn try_from_expr(expr: Expr) -> syn::Result<Self> {
if let Expr::Lit(lit) = &expr {
let lit = lit.lit.clone();
if let Lit::Float(lit) = lit {
return Ok(lit);
}
}
Err(Error::new(expr.span(), "expected litteral float"))
}
}
impl FromMetaExpr for bool {
fn try_from_expr(expr: Expr) -> syn::Result<Self> {
let lit = LitBool::try_from_expr(expr)?;
Ok(lit.value)
}
}
impl FromMetaExpr for f64 {
fn try_from_expr(expr: Expr) -> syn::Result<Self> {
let lit = LitFloat::try_from_expr(expr)?;
lit.base10_parse::<f64>()
}
}
impl FromMetaExpr for i64 {
fn try_from_expr(expr: Expr) -> syn::Result<Self> {
let lit = LitInt::try_from_expr(expr)?;
lit.base10_parse::<i64>()
}
}
impl FromMetaExpr for String {
fn try_from_expr(expr: Expr) -> syn::Result<Self> {
let lit = LitStr::try_from_expr(expr)?;
Ok(lit.value())
}
}
impl<T: FromMetaExpr> FromMetaExpr for Option<T> {
fn try_from_expr(expr: Expr) -> syn::Result<Self> {
let result = T::try_from_expr(expr)?;
Ok(Some(result))
}
}