1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use syn::{
parse::{Parse, ParseStream},
punctuated::Punctuated,
*,
};
#[derive(Debug, Clone, PartialEq)]
pub struct NameValueExpr {
pub path: Ident,
pub eq_token: Token![=],
pub expr: Expr,
}
impl Parse for NameValueExpr {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(NameValueExpr {
path: input.parse()?,
eq_token: input.parse()?,
expr: input.parse()?,
})
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct FieldThenParams {
pub field: Field,
pub comma: Option<Token![,]>,
pub params: Punctuated<NameValueExpr, Token![,]>,
}
impl Parse for FieldThenParams {
fn parse(input: ParseStream) -> syn::Result<Self> {
let field = Field::parse_unnamed(input)?;
let comma: Option<Token![,]> = input.parse()?;
let params = if comma.is_some() {
input.parse_terminated(NameValueExpr::parse)?
} else {
Punctuated::new()
};
Ok(FieldThenParams {
field,
comma,
params,
})
}
}
pub fn try_extract_inner_type(ty: &Type, inner_of: &str) -> (Type, bool) {
if let Type::Path(p) = &ty {
let type_segment = p.path.segments.first().unwrap();
if type_segment.ident == inner_of {
let leaf_type = if let PathArguments::AngleBracketed(p) = &type_segment.arguments {
if let GenericArgument::Type(t) = p.args.first().unwrap().clone() {
t
} else {
panic!("Argument in angle brackets must be a type")
}
} else {
panic!("Expected angle bracketed path");
};
(leaf_type, true)
} else {
(ty.clone(), false)
}
} else {
(ty.clone(), false)
}
}