1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
use quote::{quote, ToTokens};
use syn::{spanned::Spanned, Expr, Lit, Meta, Type};
use super::path::path_to_string;
const INT_TYPES: [&str; 12] =
["u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"];
const FLOAT_TYPES: [&str; 2] = ["f32", "f64"];
#[inline]
pub(crate) fn meta_2_expr(meta: &Meta) -> syn::Result<Expr> {
match &meta {
Meta::NameValue(name_value) => Ok(name_value.value.clone()),
Meta::List(list) => list.parse_args::<Expr>(),
Meta::Path(path) => Err(syn::Error::new(
path.span(),
format!("expected `{path} = Expr` or `{path}(Expr)`", path = path_to_string(path)),
)),
}
}
#[inline]
pub(crate) fn auto_adjust_expr(expr: Expr, ty: Option<&Type>) -> Expr {
match &expr {
Expr::Lit(lit) => {
match &lit.lit {
Lit::Int(lit) => {
if let Some(Type::Path(ty)) = ty {
let ty_string = ty.into_token_stream().to_string();
if lit.suffix() == ty_string || INT_TYPES.contains(&ty_string.as_str()) {
// don't call into
return expr;
}
}
},
Lit::Float(lit) => {
if let Some(Type::Path(ty)) = ty {
let ty_string = ty.into_token_stream().to_string();
if lit.suffix() == ty_string || FLOAT_TYPES.contains(&ty_string.as_str()) {
// don't call into
return expr;
}
}
},
Lit::Str(_) => {
if let Some(Type::Reference(ty)) = ty {
let ty_string = ty.elem.clone().into_token_stream().to_string();
if ty_string == "str" {
// don't call into
return expr;
}
}
},
Lit::Bool(_) => {
if let Some(Type::Path(ty)) = ty {
let ty_string = ty.into_token_stream().to_string();
if ty_string == "bool" {
// don't call into
return expr;
}
}
},
Lit::Char(_) => {
if let Some(Type::Path(ty)) = ty {
let ty_string = ty.into_token_stream().to_string();
if ty_string == "char" {
// don't call into
return expr;
}
}
},
Lit::Byte(_) => {
if let Some(Type::Path(ty)) = ty {
let ty_string = ty.into_token_stream().to_string();
if ty_string == "u8" {
// don't call into
return expr;
}
}
},
Lit::ByteStr(_) => {
if let Some(Type::Reference(ty)) = ty {
if let Type::Array(ty) = ty.elem.as_ref() {
if let Type::Path(ty) = ty.elem.as_ref() {
let ty_string = ty.into_token_stream().to_string();
if ty_string == "u8" {
// don't call into
return expr;
}
}
}
}
},
_ => (),
}
syn::parse2(quote!(::core::convert::Into::into(#expr))).unwrap()
},
_ => expr,
}
}