tamasfe_macro_utils/
path.rs1use syn::{Path, PathArguments, Type};
2
3#[macro_export]
4macro_rules! path_segments {
5 ($($ty:tt)::*) => {
6 $crate::path::PathSegments::new(&[$(stringify!($ty)),*])
7 };
8 (::$($ty:tt)::*) => {
9 $crate::path::PathSegments::new(&[$(stringify!($ty)),*])
10 };
11}
12
13#[derive(Debug, Clone)]
14pub struct PathSegments<'s>(&'s [&'s str]);
15
16impl<'s> PathSegments<'s> {
17 pub fn new(segments: &'s [&'s str]) -> Self {
18 Self(segments)
19 }
20}
21
22pub fn is_type(ty: &Type, segments: &PathSegments) -> bool {
23 match ty {
24 Type::Path(p) => is_path(&p.path, segments),
25 Type::Reference(ty_ref) => {
26 match &*ty_ref.elem {
27 Type::Path(p) => is_path(&p.path, segments),
28 _ => false, }
30 }
31 _ => false,
32 }
33}
34
35pub fn is_path(p: &Path, segments: &PathSegments) -> bool {
36 if segments.0.len() < p.segments.len() {
37 return false;
38 }
39
40 let mut ty_segs = p.segments.iter().rev();
41
42 for seg in segments.0.iter().rev() {
43 match ty_segs.next() {
44 Some(ty_seg) => {
45 if ty_seg.ident != seg {
46 return false;
47 }
48 }
49 None => return true,
50 }
51 }
52
53 true
54}
55
56pub fn type_args(ty: &Type) -> Option<&PathArguments> {
57 match ty {
58 Type::Path(p) => p.path.segments.last().map(|s| &s.arguments),
59 Type::Reference(ty_ref) => match &*ty_ref.elem {
60 Type::Path(p) => p.path.segments.last().map(|s| &s.arguments),
61 _ => None,
62 },
63 _ => None,
64 }
65}
66
67pub fn is_option(ty: &Type) -> bool {
68 is_type(ty, &path_segments!(::core::option::Option))
69 || is_type(ty, &path_segments!(::std::option::Option))
70}