use super::types::{DefExpr, CONSTDEF};
use ::quote::{quote, ToTokens};
use ::syn::{Type, TypeArray, TypePath, TypeTuple};
pub(crate) fn analyze_type_path(t: &TypePath) -> Option<DefExpr> {
if t.path.segments.len() == 1 {
let fpath = t.path.segments[0].clone().into_token_stream().to_string();
CONSTDEF.get(fpath.as_str()).cloned()
} else {
let r = t
.path
.segments
.iter()
.map(|seg| seg.ident.clone().into_token_stream().to_string())
.collect();
try_minimize_typepath(r)
.ok()
.and_then(|minimized| CONSTDEF.get(minimized.as_str()))
.cloned()
}
}
fn try_minimize_typepath(tpath: Vec<String>) -> Result<String, Vec<String>> {
let mut path = tpath.iter();
let mut ret = None;
match path.next().map(|v| v.as_ref()) {
Some(p) => match p {
"core" | "std" => match path.next() {
Some(s) => match s.as_str() {
"primitive" => match path.next() {
Some(ty) => {
ret = Some(ty.to_owned());
}
None => {}
},
_ => {}
},
None => {}
},
_ => {}
},
None => {}
}
ret.ok_or(tpath)
}
pub(super) fn recursive_process_tuple(tuple: &TypeTuple) -> Option<DefExpr> {
let mut inner_decl = quote! {};
for elem in tuple.elems.iter() {
match elem {
Type::Path(ref tpath) => {
let ret = self::analyze_type_path(tpath)?.into_base_token();
inner_decl = quote! {
#inner_decl
#ret,
};
}
Type::Tuple(ref tuple) => {
let ret = self::recursive_process_tuple(tuple)?.into_base_token();
inner_decl = quote! {
#inner_decl
#ret,
};
}
Type::Array(ref arr) => {
let ret = self::process_array(arr)?.into_base_token();
inner_decl = quote! {
#inner_decl
#ret,
};
}
_ => return None,
}
}
Some(DefExpr::CustomTuple(inner_decl.to_string()))
}
pub(super) fn process_array(array: &TypeArray) -> Option<DefExpr> {
let mut inner_decl = quote! {};
let len = &array.len;
match &*array.elem {
Type::Path(tpath) => {
let ret = self::analyze_type_path(tpath)?.into_base_token();
inner_decl = quote! {
#inner_decl
#ret; #len
};
}
Type::Array(arr) => {
let ret = self::process_array(arr)?.into_base_token();
inner_decl = quote! {
#inner_decl
#ret; #len
};
}
Type::Tuple(ref tuple) => {
let ret = self::recursive_process_tuple(tuple)?.into_base_token();
inner_decl = quote! {
#inner_decl
#ret; #len
};
}
_ => return None,
}
Some(DefExpr::CustomArray(inner_decl.to_string()))
}