bon_macros/util/ty/
mod.rsmod match_types;
use crate::util::prelude::*;
use syn::punctuated::Punctuated;
pub(crate) trait TypeExt {
fn as_path(&self) -> Option<&syn::TypePath>;
fn as_path_no_qself(&self) -> Option<&syn::Path>;
fn option_type_param(&self) -> Option<&syn::Type>;
fn as_generic_angle_bracketed_path(
&self,
is_desired_last_segment: impl FnOnce(&syn::Ident) -> bool,
) -> Option<GenericAngleBracketedPath<'_>>;
fn is_option(&self) -> bool;
fn peel(&self) -> &Self;
fn matches(&self, pattern: &syn::Type) -> Result<bool>;
}
impl TypeExt for syn::Type {
fn as_path(&self) -> Option<&syn::TypePath> {
match self.peel() {
Self::Path(path) => Some(path),
_ => None,
}
}
fn as_path_no_qself(&self) -> Option<&syn::Path> {
let path = self.as_path()?;
if path.qself.is_some() {
return None;
}
Some(&path.path)
}
fn option_type_param(&self) -> Option<&syn::Type> {
let ty = self.as_generic_angle_bracketed_path(|last_segment| last_segment == "Option")?;
if ty.args.len() != 1 {
return None;
}
let arg = ty.args.first()?;
let arg = match arg {
syn::GenericArgument::Type(arg) => arg,
_ => return None,
};
Some(arg)
}
fn as_generic_angle_bracketed_path(
&self,
is_desired_last_segment: impl FnOnce(&syn::Ident) -> bool,
) -> Option<GenericAngleBracketedPath<'_>> {
let path = self.as_path_no_qself()?;
let last_segment = path.segments.last()?;
if !is_desired_last_segment(&last_segment.ident) {
return None;
}
let args = match &last_segment.arguments {
syn::PathArguments::AngleBracketed(args) => &args.args,
_ => return None,
};
Some(GenericAngleBracketedPath { path, args })
}
fn is_option(&self) -> bool {
self.option_type_param().is_some()
}
fn peel(&self) -> &Self {
match self {
Self::Group(group) => group.elem.peel(),
Self::Paren(paren) => paren.elem.peel(),
_ => self,
}
}
fn matches(&self, pattern: &syn::Type) -> Result<bool> {
match_types::match_types(self, pattern)
}
}
pub(crate) struct GenericAngleBracketedPath<'a> {
pub(crate) path: &'a syn::Path,
pub(crate) args: &'a Punctuated<syn::GenericArgument, syn::Token![,]>,
}