kcl_derive_docs/
unbox.rs

1// Unbox a Vec<Box<T>> to Vec<T>.
2// Unbox a Box<T> to T.
3pub(crate) fn unbox(t: syn::Type) -> syn::Type {
4    unbox_inner(unbox_vec(t))
5}
6
7// Unbox a syn::Type that is boxed to the inner object.
8fn unbox_inner(t: syn::Type) -> syn::Type {
9    match t {
10        syn::Type::Path(syn::TypePath { ref path, .. }) => {
11            let path = &path.segments;
12            if path.len() == 1 {
13                let seg = &path[0];
14                if seg.ident == "Box" {
15                    if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
16                        &seg.arguments
17                    {
18                        if args.len() == 1 {
19                            let mut args = args.iter();
20                            let ok = args.next().unwrap();
21                            if let syn::GenericArgument::Type(ty) = ok {
22                                return ty.clone();
23                            }
24                        }
25                    }
26                }
27            }
28        }
29        _ => {
30            return t;
31        }
32    }
33    t
34}
35
36// For a Vec<Box<T>> return Vec<T>.
37// For a Vec<T> return Vec<T>.
38fn unbox_vec(t: syn::Type) -> syn::Type {
39    match t {
40        syn::Type::Path(syn::TypePath { ref path, .. }) => {
41            let path = &path.segments;
42            if path.len() == 1 {
43                let seg = &path[0];
44                if seg.ident == "Vec" {
45                    if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
46                        &seg.arguments
47                    {
48                        if args.len() == 1 {
49                            let mut args = args.iter();
50                            let ok = args.next().unwrap();
51                            if let syn::GenericArgument::Type(ty) = ok {
52                                let unboxed = unbox(ty.clone());
53                                // Wrap it back in a vec.
54                                let wrapped = syn::Type::Path(syn::TypePath {
55                                    qself: None,
56                                    path: syn::Path {
57                                        leading_colon: None,
58                                        segments: {
59                                            let mut segments = syn::punctuated::Punctuated::new();
60                                            segments.push_value(syn::PathSegment {
61                                                ident: syn::Ident::new("Vec", proc_macro2::Span::call_site()),
62                                                arguments: syn::PathArguments::AngleBracketed(
63                                                    syn::AngleBracketedGenericArguments {
64                                                        colon2_token: None,
65                                                        lt_token: syn::token::Lt::default(),
66                                                        args: {
67                                                            let mut args = syn::punctuated::Punctuated::new();
68                                                            args.push_value(syn::GenericArgument::Type(unboxed));
69                                                            args
70                                                        },
71                                                        gt_token: syn::token::Gt::default(),
72                                                    },
73                                                ),
74                                            });
75                                            segments
76                                        },
77                                    },
78                                });
79                                return wrapped;
80                            }
81                        }
82                    }
83                }
84            }
85        }
86        _ => {
87            return t;
88        }
89    }
90    t
91}