xso-proc: refactor enum handling
This will allow other kinds of enumerations in the future more easily.
This commit is contained in:
parent
8e16ae1cbb
commit
b36d1d0d4c
1 changed files with 122 additions and 69 deletions
|
@ -140,8 +140,7 @@ impl NameVariant {
|
|||
}
|
||||
}
|
||||
|
||||
/// Definition of an enum and how to parse it.
|
||||
pub(crate) struct EnumDef {
|
||||
struct NameSwitchedEnum {
|
||||
/// The XML namespace of the element to map the enum to.
|
||||
namespace: NamespaceRef,
|
||||
|
||||
|
@ -150,24 +149,10 @@ pub(crate) struct EnumDef {
|
|||
|
||||
/// Flag indicating whether the enum is exhaustive.
|
||||
exhaustive: bool,
|
||||
|
||||
/// Name of the target type.
|
||||
target_ty_ident: Ident,
|
||||
|
||||
/// Name of the builder type.
|
||||
builder_ty_ident: Ident,
|
||||
|
||||
/// Name of the iterator type.
|
||||
item_iter_ty_ident: Ident,
|
||||
|
||||
/// Flag whether debug mode is enabled.
|
||||
debug: bool,
|
||||
}
|
||||
|
||||
impl EnumDef {
|
||||
/// Create a new enum from its name, meta, and variants.
|
||||
pub(crate) fn new<'x, I: IntoIterator<Item = &'x Variant>>(
|
||||
ident: &Ident,
|
||||
impl NameSwitchedEnum {
|
||||
fn new<'x, I: IntoIterator<Item = &'x Variant>>(
|
||||
meta: XmlCompoundMeta,
|
||||
variant_iter: I,
|
||||
) -> Result<Self> {
|
||||
|
@ -184,6 +169,13 @@ impl EnumDef {
|
|||
transparent,
|
||||
} = meta;
|
||||
|
||||
// These must've been cleared by the caller. Because these being set
|
||||
// is a programming error (in xso-proc) and not a usage error, we
|
||||
// assert here instead of using reject_key!.
|
||||
assert!(builder.is_none());
|
||||
assert!(iterator.is_none());
|
||||
assert!(!debug.is_set());
|
||||
|
||||
reject_key!(name not on "enums" only on "their variants");
|
||||
reject_key!(transparent flag not on "enums" only on "structs");
|
||||
|
||||
|
@ -208,44 +200,24 @@ impl EnumDef {
|
|||
variants.push(variant);
|
||||
}
|
||||
|
||||
let builder_ty_ident = match builder {
|
||||
Some(v) => v,
|
||||
None => quote::format_ident!("{}FromXmlBuilder", ident.to_string()),
|
||||
};
|
||||
|
||||
let item_iter_ty_ident = match iterator {
|
||||
Some(v) => v,
|
||||
None => quote::format_ident!("{}AsXmlIterator", ident.to_string()),
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
namespace,
|
||||
variants,
|
||||
exhaustive: exhaustive.is_set(),
|
||||
target_ty_ident: ident.clone(),
|
||||
builder_ty_ident,
|
||||
item_iter_ty_ident,
|
||||
debug: debug.is_set(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemDef for EnumDef {
|
||||
fn make_from_events_builder(
|
||||
fn make_from_events_statemachine(
|
||||
&self,
|
||||
vis: &Visibility,
|
||||
name_ident: &Ident,
|
||||
attrs_ident: &Ident,
|
||||
) -> Result<FromXmlParts> {
|
||||
target_ty_ident: &Ident,
|
||||
state_ty_ident: &Ident,
|
||||
) -> Result<FromEventsStateMachine> {
|
||||
let xml_namespace = &self.namespace;
|
||||
let target_ty_ident = &self.target_ty_ident;
|
||||
let builder_ty_ident = &self.builder_ty_ident;
|
||||
let state_ty_ident = quote::format_ident!("{}State", builder_ty_ident);
|
||||
|
||||
let mut statemachine = FromEventsStateMachine::new();
|
||||
for variant in self.variants.iter() {
|
||||
statemachine
|
||||
.merge(variant.make_from_events_statemachine(target_ty_ident, &state_ty_ident)?);
|
||||
.merge(variant.make_from_events_statemachine(target_ty_ident, state_ty_ident)?);
|
||||
}
|
||||
|
||||
statemachine.set_pre_init(quote! {
|
||||
|
@ -266,16 +238,100 @@ impl ItemDef for EnumDef {
|
|||
})
|
||||
}
|
||||
|
||||
let defs = statemachine.render(
|
||||
vis,
|
||||
Ok(statemachine)
|
||||
}
|
||||
|
||||
fn make_as_item_iter_statemachine(
|
||||
&self,
|
||||
target_ty_ident: &Ident,
|
||||
state_ty_ident: &Ident,
|
||||
item_iter_ty_lifetime: &Lifetime,
|
||||
) -> Result<AsItemsStateMachine> {
|
||||
let mut statemachine = AsItemsStateMachine::new();
|
||||
for variant in self.variants.iter() {
|
||||
statemachine.merge(variant.make_as_item_iter_statemachine(
|
||||
&self.namespace,
|
||||
target_ty_ident,
|
||||
state_ty_ident,
|
||||
item_iter_ty_lifetime,
|
||||
)?);
|
||||
}
|
||||
|
||||
Ok(statemachine)
|
||||
}
|
||||
}
|
||||
|
||||
/// Definition of an enum and how to parse it.
|
||||
pub(crate) struct EnumDef {
|
||||
/// Implementation of the enum itself
|
||||
inner: NameSwitchedEnum,
|
||||
|
||||
/// Name of the target type.
|
||||
target_ty_ident: Ident,
|
||||
|
||||
/// Name of the builder type.
|
||||
builder_ty_ident: Ident,
|
||||
|
||||
/// Name of the iterator type.
|
||||
item_iter_ty_ident: Ident,
|
||||
|
||||
/// Flag whether debug mode is enabled.
|
||||
debug: bool,
|
||||
}
|
||||
|
||||
impl EnumDef {
|
||||
/// Create a new enum from its name, meta, and variants.
|
||||
pub(crate) fn new<'x, I: IntoIterator<Item = &'x Variant>>(
|
||||
ident: &Ident,
|
||||
mut meta: XmlCompoundMeta,
|
||||
variant_iter: I,
|
||||
) -> Result<Self> {
|
||||
let builder_ty_ident = match meta.builder.take() {
|
||||
Some(v) => v,
|
||||
None => quote::format_ident!("{}FromXmlBuilder", ident.to_string()),
|
||||
};
|
||||
|
||||
let item_iter_ty_ident = match meta.iterator.take() {
|
||||
Some(v) => v,
|
||||
None => quote::format_ident!("{}AsXmlIterator", ident.to_string()),
|
||||
};
|
||||
|
||||
let debug = meta.debug.take().is_set();
|
||||
|
||||
Ok(Self {
|
||||
inner: NameSwitchedEnum::new(meta, variant_iter)?,
|
||||
target_ty_ident: ident.clone(),
|
||||
builder_ty_ident,
|
||||
&state_ty_ident,
|
||||
&TypePath {
|
||||
qself: None,
|
||||
path: target_ty_ident.clone().into(),
|
||||
}
|
||||
.into(),
|
||||
)?;
|
||||
item_iter_ty_ident,
|
||||
debug,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemDef for EnumDef {
|
||||
fn make_from_events_builder(
|
||||
&self,
|
||||
vis: &Visibility,
|
||||
name_ident: &Ident,
|
||||
attrs_ident: &Ident,
|
||||
) -> Result<FromXmlParts> {
|
||||
let target_ty_ident = &self.target_ty_ident;
|
||||
let builder_ty_ident = &self.builder_ty_ident;
|
||||
let state_ty_ident = quote::format_ident!("{}State", builder_ty_ident);
|
||||
|
||||
let defs = self
|
||||
.inner
|
||||
.make_from_events_statemachine(target_ty_ident, &state_ty_ident)?
|
||||
.render(
|
||||
vis,
|
||||
builder_ty_ident,
|
||||
&state_ty_ident,
|
||||
&TypePath {
|
||||
qself: None,
|
||||
path: target_ty_ident.clone().into(),
|
||||
}
|
||||
.into(),
|
||||
)?;
|
||||
|
||||
Ok(FromXmlParts {
|
||||
defs,
|
||||
|
@ -318,26 +374,23 @@ impl ItemDef for EnumDef {
|
|||
});
|
||||
let state_ty_ident = quote::format_ident!("{}State", item_iter_ty_ident);
|
||||
|
||||
let mut statemachine = AsItemsStateMachine::new();
|
||||
for variant in self.variants.iter() {
|
||||
statemachine.merge(variant.make_as_item_iter_statemachine(
|
||||
&self.namespace,
|
||||
let defs = self
|
||||
.inner
|
||||
.make_as_item_iter_statemachine(
|
||||
target_ty_ident,
|
||||
&state_ty_ident,
|
||||
&item_iter_ty_lifetime,
|
||||
)?);
|
||||
}
|
||||
|
||||
let defs = statemachine.render(
|
||||
vis,
|
||||
&ref_ty(
|
||||
ty_from_ident(target_ty_ident.clone()).into(),
|
||||
item_iter_ty_lifetime.clone(),
|
||||
),
|
||||
&state_ty_ident,
|
||||
&item_iter_ty_lifetime,
|
||||
&item_iter_ty,
|
||||
)?;
|
||||
)?
|
||||
.render(
|
||||
vis,
|
||||
&ref_ty(
|
||||
ty_from_ident(target_ty_ident.clone()).into(),
|
||||
item_iter_ty_lifetime.clone(),
|
||||
),
|
||||
&state_ty_ident,
|
||||
&item_iter_ty_lifetime,
|
||||
&item_iter_ty,
|
||||
)?;
|
||||
|
||||
Ok(AsXmlParts {
|
||||
defs,
|
||||
|
|
Loading…
Reference in a new issue