#![allow(unused)]
use syn::{LitStr, Type};
pub(crate) fn has_attribute_value(field: &syn::Field, name: &str, value: &str) -> bool {
field.attrs.iter().any(|attr| {
attr.path().is_ident(name)
&& attr
.parse_nested_meta(|meta| {
if meta.path.is_ident(value) {
Ok(())
} else {
Err(meta.error("attribute value not found"))
}
})
.is_ok()
})
}
pub(crate) fn has_attribute(field: &syn::Field, name: &str) -> bool {
field.attrs.iter().any(|attr| attr.path().is_ident(name))
}
pub(crate) fn get_attribute_by_key(
attrs: &[syn::Attribute], name: &str, key: &str,
) -> Option<String> {
let mut val: Option<String> = None;
for attr in attrs.iter() {
if !attr.path().is_ident(name) {
continue;
}
attr.parse_nested_meta(|meta| {
if meta.path.is_ident(key) {
let value = meta.value()?; let v: LitStr = value.parse()?; val = Some(v.value());
return Ok(());
}
Err(meta.error("attribute value not found"))
})
.ok();
}
val
}
pub(crate) fn get_attribute_value(attrs: &[syn::Attribute], key: &str) -> Option<String> {
for attr in attrs {
if attr.path().is_ident(key) {
let r = attr.meta.require_name_value();
if let Ok(v) = r {
if let syn::Expr::Lit(v) = &v.value {
match &v.lit {
syn::Lit::Str(s) => {
return Some(s.value());
},
syn::Lit::Int(i) => {
return Some(i.to_string());
},
syn::Lit::Float(f) => {
return Some(f.to_string());
},
syn::Lit::Bool(b) => {
return Some(b.value().to_string());
},
_ => {},
}
}
}
}
}
None
}
pub(crate) fn get_attribute_arg(attrs: &[syn::Attribute], key: &str) -> Option<String> {
for attr in attrs {
if attr.path().is_ident(key) {
let r = attr.parse_args::<syn::Lit>();
if let Ok(v) = r {
println!("v: {:?}", v);
match &v {
syn::Lit::Str(s) => {
return Some(s.value());
},
syn::Lit::Int(i) => {
return Some(i.to_string());
},
syn::Lit::Float(f) => {
return Some(f.to_string());
},
syn::Lit::Bool(b) => {
return Some(b.value().to_string());
},
_ => {},
}
}
}
}
None
}
pub(crate) fn get_option_type(ty: &Type) -> (bool, &Type) {
get_inner_type(ty, "Option")
}
#[allow(dead_code)]
pub(crate) fn get_vec_type(ty: &Type) -> (bool, &Type) {
get_inner_type(ty, "Vec")
}
pub(crate) fn get_inner_type<'a>(ty: &'a Type, name: &str) -> (bool, &'a Type) {
if let syn::Type::Path(ref path) = ty {
if let Some(segment) = path.path.segments.first() {
if segment.ident == name {
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
args,
..
}) = &segment.arguments
{
if let Some(syn::GenericArgument::Type(ty)) = args.first() {
return (true, ty);
}
}
}
}
}
(false, ty)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_name() {
let attr: syn::Attribute = syn::parse_quote!(#[name = "0b{:08b}"]);
let v = get_attribute_value(&[attr], "name");
println!("v: {:?}", v);
let attr: syn::Attribute = syn::parse_quote!(#[name("yes")]);
let v = get_attribute_arg(&[attr], "name");
println!("v: {:?}", v);
}
}