Skip to content

Commit 77eae15

Browse files
committed
Use TryFrom
1 parent f21d855 commit 77eae15

File tree

1 file changed

+46
-43
lines changed

1 file changed

+46
-43
lines changed

crates/macros/src/newtype_oparg.rs

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -93,29 +93,10 @@ struct VariantInfo {
9393
catch_all: bool,
9494
}
9595

96-
pub(super) fn handle_enum(item: ItemEnum) -> syn::Result<proc_macro2::TokenStream> {
97-
if !item.generics.params.is_empty() {
98-
return Err(Error::new(
99-
item.span(),
100-
"A new type oparg cannot be generic.",
101-
));
102-
}
103-
104-
let ItemEnum {
105-
attrs,
106-
vis,
107-
enum_token,
108-
ident,
109-
generics: _,
110-
brace_token: _,
111-
variants,
112-
} = item.clone();
113-
114-
let mut variants_info = vec![];
115-
for variant in &variants {
116-
let ident = variant.ident.clone();
117-
let discriminant = variant.discriminant.as_ref().map(|(_, expr)| expr.clone());
96+
impl TryFrom<syn::Variant> for VariantInfo {
97+
type Error = syn::Error;
11898

99+
fn try_from(variant: syn::Variant) -> Result<Self, Self::Error> {
119100
let mut display = None;
120101
let mut catch_all = false;
121102
for attr in &variant.attrs {
@@ -137,13 +118,55 @@ pub(super) fn handle_enum(item: ItemEnum) -> syn::Result<proc_macro2::TokenStrea
137118
})?
138119
}
139120

140-
variants_info.push(VariantInfo {
121+
let ident = variant.ident.clone();
122+
let discriminant = variant.discriminant.as_ref().map(|(_, expr)| expr.clone());
123+
124+
if catch_all && display.is_some() {
125+
return Err(Error::new(
126+
ident.span(),
127+
r#"Cannot define both `#[oparg(catch_all)`] and `#[oparg(display = "...")]` on the same variant"#,
128+
));
129+
}
130+
131+
if discriminant.is_none() && !catch_all {
132+
return Err(Error::new(
133+
ident.span(),
134+
"Is a variant without an assigned value",
135+
));
136+
}
137+
138+
Ok(Self {
141139
ident,
142140
discriminant,
143141
display,
144142
catch_all,
145143
})
146144
}
145+
}
146+
147+
pub(super) fn handle_enum(item: ItemEnum) -> syn::Result<proc_macro2::TokenStream> {
148+
if !item.generics.params.is_empty() {
149+
return Err(Error::new(
150+
item.span(),
151+
"A new type oparg cannot be generic.",
152+
));
153+
}
154+
155+
let ItemEnum {
156+
attrs,
157+
vis,
158+
enum_token,
159+
ident,
160+
generics: _,
161+
brace_token: _,
162+
variants,
163+
} = item.clone();
164+
165+
let mut variants_info = variants
166+
.iter()
167+
.cloned()
168+
.map(VariantInfo::try_from)
169+
.collect::<syn::Result<Vec<_>>>()?;
147170

148171
let catch_all = variants_info.pop_if(|info| info.catch_all);
149172

@@ -155,26 +178,6 @@ pub(super) fn handle_enum(item: ItemEnum) -> syn::Result<proc_macro2::TokenStrea
155178
));
156179
};
157180

158-
match catch_all {
159-
Some(vinfo) if vinfo.display.is_some() => {
160-
return Err(Error::new(
161-
vinfo.ident.span(),
162-
r#"Cannot define both `#[oparg(catch_all)`] and `#[oparg(display = "...")]` on the same variant"#,
163-
));
164-
}
165-
_ => {}
166-
};
167-
168-
// Ensure all variants has a discriminant.
169-
for vinfo in &variants_info {
170-
if vinfo.discriminant.is_none() {
171-
return Err(Error::new(
172-
vinfo.ident.span(),
173-
"Is a variant without an assigned value",
174-
));
175-
}
176-
}
177-
178181
let variants_def = variants.iter().cloned().map(|mut variant| {
179182
// Don't assign value. Enables more optimizations by the compiler.
180183
variant.discriminant = None;

0 commit comments

Comments
 (0)