pub struct BuilderRegistry<T: ?Sized> { /* private fields */ }
Available on crate feature
std
only.Expand description
§Registry for type-erased FromXml
builders which construct T
For general information on builder registries, see registry
.
§Performance trade-offs
The implementation of the BuilderRegistry
is optimized toward specific
usages. Other usages may see negative performance impacts. The following
assumptions are made:
- Types are added only once at startup and a matching
reserve
call is made beforehands. - There are many different types.
FromXml::xml_name_matcher
returns a different value for most of the types which are added.
The lookup algorithms in particular are geared toward the implications of the last two assumptions and may be rather inefficient otherwise.
§Example
This example illustrates the manual usage of the BuilderRegistry
.
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "foo")]
struct Foo;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "bar")]
struct Bar;
#[derive(Debug, PartialEq)]
enum Either {
A(Foo),
B(Bar),
}
// BuilderRegistry::add::<U> requires that Either: MayContain<U>, in order
// to be able to wrap the U::Builder such that it outputs a Xso<Either>
// instead.
impl MayContain<Foo> for Either {
fn upcast_into(other: Foo) -> Box<Self> { Box::new(Self::A(other)) }
}
impl MayContain<Bar> for Either {
fn upcast_into(other: Bar) -> Box<Self> { Box::new(Self::B(other)) }
}
let registry = BuilderRegistry::<Either>::new();
registry.add::<Foo>();
registry.add::<Bar>();
let mut builder = registry.make_builder(
(
Namespace::from_str("urn:example"),
xml_ncname!("foo").to_owned(), // <- Selects the Foo variant
),
AttrMap::new(),
&Context::empty(),
).unwrap();
let x = builder.feed(Event::EndElement(EventMetrics::zero()), &Context::empty()).unwrap().unwrap();
assert_eq!(Either::A(Foo), *x);
let mut builder = registry.make_builder(
(
Namespace::from_str("urn:example"),
xml_ncname!("bar").to_owned(), // <- Selects the Bar variant
),
AttrMap::new(),
&Context::empty(),
).unwrap();
let x = builder.feed(Event::EndElement(EventMetrics::zero()), &Context::empty()).unwrap().unwrap();
assert_eq!(Either::B(Bar), *x);
Implementing FromXml
on the Either
type in the above example would
be trivial and look like this:
// ... code from the previous example ...
use xso::dynxso::UnboxBuilder;
// In order to be able to use the registry from the FromXml implementation,
// it must be a static (as opposed to a local variable as in the previous
// example).
static REGISTRY: BuilderRegistry<Either> = BuilderRegistry::new();
REGISTRY.add::<Foo>();
REGISTRY.add::<Bar>();
impl FromXml for Either {
type Builder = UnboxBuilder<Box<dyn FromEventsBuilder<Output = Box<Either>>>>;
fn from_events(name: QName, attrs: AttrMap, ctx: &Context<'_>) -> Result<Self::Builder, FromEventsError> {
REGISTRY.make_builder(name, attrs, ctx).map(UnboxBuilder::wrap)
}
}
assert_eq!(
Either::A(Foo),
from_bytes("<foo xmlns='urn:example'/>".as_bytes()).unwrap(),
);
assert_eq!(
Either::B(Bar),
from_bytes("<bar xmlns='urn:example'/>".as_bytes()).unwrap(),
);
Implementations§
Trait Implementations§
Source§impl<T: ?Sized + 'static> DynXsoRegistryAdd<T> for BuilderRegistry<T>
impl<T: ?Sized + 'static> DynXsoRegistryAdd<T> for BuilderRegistry<T>
Source§impl<T: ?Sized + 'static> DynXsoRegistryLookup<T> for BuilderRegistry<T>
impl<T: ?Sized + 'static> DynXsoRegistryLookup<T> for BuilderRegistry<T>
Source§fn make_builder(
&self,
name: QName,
attrs: AttrMap,
ctx: &Context<'_>,
) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError>
fn make_builder( &self, name: QName, attrs: AttrMap, ctx: &Context<'_>, ) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError>
Make a builder for the given element header. Read more
Auto Trait Implementations§
impl<T> !Freeze for BuilderRegistry<T>
impl<T> RefUnwindSafe for BuilderRegistry<T>where
T: ?Sized,
impl<T> Send for BuilderRegistry<T>where
T: ?Sized,
impl<T> Sync for BuilderRegistry<T>where
T: ?Sized,
impl<T> Unpin for BuilderRegistry<T>where
T: ?Sized,
impl<T> UnwindSafe for BuilderRegistry<T>where
T: ?Sized,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more