summaryrefslogtreecommitdiff
path: root/vendor/educe/src/common/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/educe/src/common/expr.rs')
-rw-r--r--vendor/educe/src/common/expr.rs109
1 files changed, 109 insertions, 0 deletions
diff --git a/vendor/educe/src/common/expr.rs b/vendor/educe/src/common/expr.rs
new file mode 100644
index 00000000..ab49d3a0
--- /dev/null
+++ b/vendor/educe/src/common/expr.rs
@@ -0,0 +1,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,
+ }
+}