Struct BuilderRegistry

Source
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§

Source§

impl<T: ?Sized + 'static> BuilderRegistry<T>

Source

pub const fn new() -> Self

Create an empty registry.

Source

pub fn reserve(&self, n: usize)

Reserve space for at least n additional types.

Trait Implementations§

Source§

impl<T: Debug + ?Sized> Debug for BuilderRegistry<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: ?Sized + 'static> DynXsoRegistryAdd<T> for BuilderRegistry<T>

Source§

fn add<U: Any + FromXml>(&self)
where T: MayContain<U>,

Add a new builder to the registry. Read more
Source§

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>

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> ErasedDestructor for T
where T: 'static,