use crate::*;
use std::convert::{TryFrom, TryInto};
use syn::{Expr, Ident, Type, TypeArray, TypePath};
impl TryFrom<&Type> for Ty {
type Error = syn::Error;
fn try_from(ty: &Type) -> Result<Self, Self::Error> {
match ty {
Type::Path(ty) => ty.try_into(),
Type::Array(ty) => ty.try_into(),
Type::Reference(ty) => Err(syn::Error::new_spanned(ty, E::ReferenceUnsupported)),
_ => Err(syn::Error::new_spanned(ty, E::UnsupportedType)),
}
}
}
impl TryFrom<&TypePath> for Ty {
type Error = syn::Error;
fn try_from(ty: &TypePath) -> Result<Self, Self::Error> {
if let Some(ident) = ty.path.get_ident() {
ident.try_into()
} else {
Err(syn::Error::new_spanned(ty, E::UnsupportedType))
}
}
}
impl TryFrom<&Ident> for Ty {
type Error = syn::Error;
fn try_from(ident: &Ident) -> Result<Self, Self::Error> {
Ok(match ident.to_string().as_str() {
"u8" => Ty::U8,
"u16" => Ty::U16,
"u32" => Ty::U32,
"u64" => Ty::U64,
"u128" => Ty::U128,
"i8" => Ty::I8,
"i16" => Ty::I16,
"i32" => Ty::I32,
"i64" => Ty::I64,
"i128" => Ty::I128,
"f32" => Ty::F32,
"f64" => Ty::F64,
"bool" => Ty::Bool,
_linked => Ty::LinkedToU8(ident.to_string()),
})
}
}
impl TryFrom<&TypeArray> for Ty {
type Error = syn::Error;
fn try_from(ty: &TypeArray) -> Result<Self, Self::Error> {
fn extract_array_len(len: &Expr) -> Result<usize, syn::Error> {
if let Expr::Lit(expr_lit) = len
&& let syn::Lit::Int(lit_int) = &expr_lit.lit
{
return lit_int.base10_parse::<usize>();
}
Err(syn::Error::new_spanned(len, E::MissedArraySize))
}
if !matches!(Ty::try_from(&*ty.elem)?, Ty::U8) {
Err(syn::Error::new_spanned(&*ty.elem, E::UnsupportedType))
} else {
Ok(Ty::Blob(extract_array_len(&ty.len)?))
}
}
}