educe/common/
ident_bool.rs1use syn::{
2 parse::{Parse, ParseStream},
3 spanned::Spanned,
4 Expr, Ident, Lit, LitBool, LitStr, Meta, MetaNameValue,
5};
6
7use super::path::path_to_string;
8
9#[derive(Debug)]
10pub(crate) enum IdentOrBool {
11 Ident(Ident),
12 Bool(bool),
13}
14
15impl Parse for IdentOrBool {
16 #[inline]
17 fn parse(input: ParseStream) -> syn::Result<Self> {
18 if let Ok(lit) = input.parse::<Lit>() {
19 match lit {
20 Lit::Bool(lit) => return Ok(Self::Bool(lit.value)),
21 Lit::Str(lit) => {
22 return match lit.parse::<Ident>() {
23 Ok(ident) => Ok(Self::Ident(ident)),
24 Err(_) if lit.value().is_empty() => Ok(Self::Bool(false)),
25 Err(error) => Err(error),
26 }
27 },
28 _ => (),
29 }
30 }
31
32 Ok(Self::Ident(input.parse::<Ident>()?))
33 }
34}
35
36#[inline]
37pub(crate) fn meta_name_value_2_ident(name_value: &MetaNameValue) -> syn::Result<Ident> {
38 match &name_value.value {
39 Expr::Lit(lit) => {
40 if let Lit::Str(lit) = &lit.lit {
41 return lit.parse();
42 }
43 },
44 Expr::Path(path) => {
45 if let Some(ident) = path.path.get_ident() {
46 return Ok(ident.clone());
47 }
48 },
49 _ => (),
50 }
51
52 Err(syn::Error::new(
53 name_value.value.span(),
54 format!("expected `{path} = Ident`", path = path_to_string(&name_value.path)),
55 ))
56}
57
58#[inline]
59pub(crate) fn meta_2_ident(meta: &Meta) -> syn::Result<Ident> {
60 match &meta {
61 Meta::NameValue(name_value) => meta_name_value_2_ident(name_value),
62 Meta::List(list) => {
63 if let Ok(lit) = list.parse_args::<LitStr>() {
64 lit.parse()
65 } else {
66 list.parse_args()
67 }
68 },
69 Meta::Path(path) => Err(syn::Error::new(
70 path.span(),
71 format!("expected `{path} = Ident` or `{path}(Ident)`", path = path_to_string(path)),
72 )),
73 }
74}
75
76#[inline]
77pub(crate) fn meta_name_value_2_bool(name_value: &MetaNameValue) -> syn::Result<bool> {
78 if let Expr::Lit(lit) = &name_value.value {
79 if let Lit::Bool(b) = &lit.lit {
80 return Ok(b.value);
81 }
82 }
83
84 Err(syn::Error::new(
85 name_value.value.span(),
86 format!("expected `{path} = false`", path = path_to_string(&name_value.path)),
87 ))
88}
89
90#[inline]
91pub(crate) fn meta_2_bool(meta: &Meta) -> syn::Result<bool> {
92 match &meta {
93 Meta::NameValue(name_value) => meta_name_value_2_bool(name_value),
94 Meta::List(list) => Ok(list.parse_args::<LitBool>()?.value),
95 Meta::Path(path) => Err(syn::Error::new(
96 path.span(),
97 format!("expected `{path} = false` or `{path}(false)`", path = path_to_string(path)),
98 )),
99 }
100}
101
102#[inline]
103pub(crate) fn meta_2_bool_allow_path(meta: &Meta) -> syn::Result<bool> {
104 match &meta {
105 Meta::Path(_) => Ok(true),
106 Meta::NameValue(name_value) => meta_name_value_2_bool(name_value),
107 Meta::List(list) => Ok(list.parse_args::<LitBool>()?.value),
108 }
109}
110
111#[inline]
112pub(crate) fn meta_name_value_2_ident_and_bool(
113 name_value: &MetaNameValue,
114) -> syn::Result<IdentOrBool> {
115 match &name_value.value {
116 Expr::Lit(lit) => match &lit.lit {
117 Lit::Str(lit) => match lit.parse::<Ident>() {
118 Ok(ident) => return Ok(IdentOrBool::Ident(ident)),
119 Err(_) if lit.value().is_empty() => {
120 return Ok(IdentOrBool::Bool(false));
121 },
122 Err(error) => {
123 return Err(error);
124 },
125 },
126 Lit::Bool(lit) => {
127 return Ok(IdentOrBool::Bool(lit.value));
128 },
129 _ => (),
130 },
131 Expr::Path(path) => {
132 if let Some(ident) = path.path.get_ident() {
133 return Ok(IdentOrBool::Ident(ident.clone()));
134 }
135 },
136 _ => (),
137 }
138
139 Err(syn::Error::new(
140 name_value.value.span(),
141 format!(
142 "expected `{path} = Ident` or `{path} = false`",
143 path = path_to_string(&name_value.path)
144 ),
145 ))
146}
147
148#[inline]
149pub(crate) fn meta_2_ident_and_bool(meta: &Meta) -> syn::Result<IdentOrBool> {
150 match &meta {
151 Meta::NameValue(name_value) => meta_name_value_2_ident_and_bool(name_value),
152 Meta::List(list) => list.parse_args::<IdentOrBool>(),
153 Meta::Path(path) => Err(syn::Error::new(
154 path.span(),
155 format!(
156 "expected `{path} = Ident`, `{path}(Ident)`, `{path} = false`, or `{path}(false)`",
157 path = path_to_string(path)
158 ),
159 )),
160 }
161}