xso: relax the feature = "std" requirement for xso::dynxso
This commit is contained in:
parent
345209bce9
commit
bdae845b14
3 changed files with 208 additions and 85 deletions
|
|
@ -32,10 +32,10 @@
|
|||
//! ## Example
|
||||
//!
|
||||
#![cfg_attr(
|
||||
not(feature = "macros"),
|
||||
not(all(feature = "macros", feature = "std")),
|
||||
doc = "Because the macros feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
|
||||
)]
|
||||
#![cfg_attr(feature = "macros", doc = "\n```\n")]
|
||||
#![cfg_attr(all(feature = "macros", feature = "std"), doc = "\n```\n")]
|
||||
//! # use core::any::Any;
|
||||
//! # use xso::{dynxso::{Xso, BuilderRegistry}, FromXml, from_bytes, derive_dyn_traits};
|
||||
//! trait MyPayload: Any {}
|
||||
|
|
@ -69,19 +69,22 @@ use alloc::{
|
|||
},
|
||||
vec::{self, Vec},
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use core::marker::PhantomData;
|
||||
use core::{
|
||||
any::{Any, TypeId},
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
slice,
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::fromxml::XmlNameMatcher;
|
||||
use crate::{
|
||||
asxml::AsXmlDyn,
|
||||
error::{Error, FromEventsError},
|
||||
fromxml::XmlNameMatcher,
|
||||
AsXml, Context, FromEventsBuilder, FromXml, Item,
|
||||
};
|
||||
|
||||
|
|
@ -92,9 +95,25 @@ use crate::{
|
|||
/// that is a useful thing to have, see the [`dynxso`][`crate::dynxso`]
|
||||
/// module.
|
||||
///
|
||||
/// ## Syntax
|
||||
///
|
||||
/// This macro can be called in two forms:
|
||||
///
|
||||
/// - `derive_dyn_traits!(Trait)` uses the default [`BuilderRegistry`]
|
||||
/// as [`DynXso::Registry`] type and is only available if `xso` is built
|
||||
/// with the `"std"` feature.
|
||||
/// - `derive_dyn_traits!(Trait use Type = expr)` where `Type` is used as
|
||||
/// [`DynXso::Registry`], initialized with `expr`. This form is available
|
||||
/// for any set of crate features.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```
|
||||
/// When `std` is enabled, the simple syntax can be used.
|
||||
#[cfg_attr(
|
||||
not(feature = "std"),
|
||||
doc = "Because the std feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
|
||||
)]
|
||||
#[cfg_attr(feature = "std", doc = "\n```\n")]
|
||||
/// # use core::any::Any;
|
||||
/// use xso::derive_dyn_traits;
|
||||
/// trait Foo: Any {}
|
||||
|
|
@ -104,19 +123,38 @@ use crate::{
|
|||
/// Note that the trait this macro is called on **must** have a bound on
|
||||
/// `Any`, otherwise the generated code will not compile:
|
||||
///
|
||||
/// ```compile_fail
|
||||
#[cfg_attr(
|
||||
not(feature = "std"),
|
||||
doc = "Because the std feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
|
||||
)]
|
||||
#[cfg_attr(feature = "std", doc = "\n```compile_fail\n")]
|
||||
/// use xso::derive_dyn_traits;
|
||||
/// trait Foo {}
|
||||
/// derive_dyn_traits!(Foo);
|
||||
/// // ↑ will generate a bunch of errors about incompatible types
|
||||
/// ```
|
||||
///
|
||||
/// If the `std` feature is not enabled or if you want to use another
|
||||
/// `Registry` for whichever reason, the explicit form can be used:
|
||||
///
|
||||
/// ```
|
||||
/// # use core::any::Any;
|
||||
/// use xso::derive_dyn_traits;
|
||||
/// trait Foo: Any {}
|
||||
/// struct Registry { /* .. */ }
|
||||
/// derive_dyn_traits!(Foo use Registry = Registry { /* .. */ });
|
||||
/// ```
|
||||
///
|
||||
/// In that case, you should review the trait requirements of the
|
||||
/// [`DynXso::Registry`] associated type.
|
||||
#[macro_export]
|
||||
macro_rules! derive_dyn_traits {
|
||||
($trait:ident) => {
|
||||
($trait:ident use $registry:ty = $reginit:expr) => {
|
||||
impl $crate::dynxso::DynXso for dyn $trait {
|
||||
fn registry() -> &'static $crate::dynxso::BuilderRegistry<Self> {
|
||||
static DATA: $crate::dynxso::BuilderRegistry<dyn $trait> =
|
||||
$crate::dynxso::BuilderRegistry::new();
|
||||
type Registry = $registry;
|
||||
|
||||
fn registry() -> &'static Self::Registry {
|
||||
static DATA: $registry = $reginit;
|
||||
&DATA
|
||||
}
|
||||
|
||||
|
|
@ -173,8 +211,30 @@ macro_rules! derive_dyn_traits {
|
|||
}
|
||||
}
|
||||
};
|
||||
($trait:ident) => {
|
||||
$crate::_internal_derive_dyn_traits_std_only!($trait);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "std")]
|
||||
macro_rules! _internal_derive_dyn_traits_std_only {
|
||||
($trait:ident) => {
|
||||
$crate::derive_dyn_traits!($trait use $crate::dynxso::BuilderRegistry<dyn $trait> = $crate::dynxso::BuilderRegistry::new());
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
#[cfg(not(feature = "std"))]
|
||||
macro_rules! _internal_derive_dyn_traits_std_only {
|
||||
($trait:ident) => {
|
||||
compile_error!(concat!("derive_dyn_traits!(", stringify!($trait), ") can only be used if the xso crate has been built with the \"std\" feature enabled. Without \"std\", the explicit form of derive_dyn_traits!(", stringify!($trait), " use .. = ..) must be used (see docs)."));
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
type BuilderRegistryBuilder<T> = Box<
|
||||
dyn Fn(
|
||||
rxml::QName,
|
||||
|
|
@ -186,12 +246,14 @@ type BuilderRegistryBuilder<T> = Box<
|
|||
+ 'static,
|
||||
>;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
struct BuilderRegistryEntry<T: ?Sized> {
|
||||
matcher: XmlNameMatcher<'static>,
|
||||
ty: TypeId,
|
||||
builder: BuilderRegistryBuilder<T>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: ?Sized> fmt::Debug for BuilderRegistryEntry<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("BuilderRegistryEntry")
|
||||
|
|
@ -203,16 +265,7 @@ impl<T: ?Sized> fmt::Debug for BuilderRegistryEntry<T> {
|
|||
|
||||
/// # Registry for type-erased [`FromXml`] builders which construct `T`
|
||||
///
|
||||
/// This registry holds type-erased [`FromXml::from_events`] implementations.
|
||||
/// It can be used to dynamically dispatch to a set of `FromXml`
|
||||
/// implementations which is not known at compile time.
|
||||
///
|
||||
/// Under the hood, this is used by the `FromXml` implementation on
|
||||
/// [`Xso<T>`][`Xso`], via the [`DynXso`] trait.
|
||||
///
|
||||
/// Note that this registry does not allow to add arbitrary builders. All
|
||||
/// builders must originate in a [`FromXml`] implementation and their output
|
||||
/// must be convertible to `T`.
|
||||
/// For general information on builder registries, see [`registry`].
|
||||
///
|
||||
/// ## Performance trade-offs
|
||||
///
|
||||
|
|
@ -238,7 +291,7 @@ impl<T: ?Sized> fmt::Debug for BuilderRegistryEntry<T> {
|
|||
doc = "Because the macros feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
|
||||
)]
|
||||
#[cfg_attr(feature = "macros", doc = "\n```\n")]
|
||||
/// # use xso::{dynxso::{BuilderRegistry, MayContain}, FromXml, from_bytes, exports::rxml::{Namespace, AttrMap, QName, Event, parser::EventMetrics, xml_ncname}, Context, FromEventsBuilder, error::FromEventsError};
|
||||
/// # use xso::{dynxso::{BuilderRegistry, MayContain, registry::{DynXsoRegistryAdd, DynXsoRegistryLookup}}, FromXml, from_bytes, exports::rxml::{Namespace, AttrMap, QName, Event, parser::EventMetrics, xml_ncname}, Context, FromEventsBuilder, error::FromEventsError};
|
||||
/// #[derive(FromXml, Debug, PartialEq)]
|
||||
/// #[xml(namespace = "urn:example", name = "foo")]
|
||||
/// struct Foo;
|
||||
|
|
@ -299,7 +352,7 @@ impl<T: ?Sized> fmt::Debug for BuilderRegistryEntry<T> {
|
|||
doc = "Because the macros feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
|
||||
)]
|
||||
#[cfg_attr(feature = "macros", doc = "\n```\n")]
|
||||
/// # use xso::{dynxso::{BuilderRegistry, MayContain}, FromXml, from_bytes, exports::rxml::{Namespace, AttrMap, QName, Event, parser::EventMetrics}, Context, FromEventsBuilder, error::FromEventsError};
|
||||
/// # use xso::{dynxso::{BuilderRegistry, MayContain, registry::{DynXsoRegistryAdd, DynXsoRegistryLookup}}, FromXml, from_bytes, exports::rxml::{Namespace, AttrMap, QName, Event, parser::EventMetrics}, Context, FromEventsBuilder, error::FromEventsError};
|
||||
/// # #[derive(FromXml, Debug, PartialEq)]
|
||||
/// # #[xml(namespace = "urn:example", name = "foo")]
|
||||
/// # struct Foo;
|
||||
|
|
@ -350,10 +403,12 @@ impl<T: ?Sized> fmt::Debug for BuilderRegistryEntry<T> {
|
|||
/// );
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
#[cfg(feature = "std")]
|
||||
pub struct BuilderRegistry<T: ?Sized> {
|
||||
inner: Mutex<Vec<BuilderRegistryEntry<T>>>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: ?Sized + 'static> BuilderRegistry<T> {
|
||||
/// Create an empty registry.
|
||||
pub const fn new() -> Self {
|
||||
|
|
@ -409,11 +464,41 @@ impl<T: ?Sized + 'static> BuilderRegistry<T> {
|
|||
self.inner.lock().unwrap().reserve(n);
|
||||
}
|
||||
|
||||
/// Add a new builder to the registry.
|
||||
///
|
||||
/// This allows to add any `FromXml` implementation whose output can be
|
||||
/// converted to `T`.
|
||||
pub fn add<U: Any + FromXml>(&self)
|
||||
fn try_build(
|
||||
inner: &mut Vec<BuilderRegistryEntry<T>>,
|
||||
mut name: rxml::QName,
|
||||
mut attrs: rxml::AttrMap,
|
||||
ctx: &Context<'_>,
|
||||
matcher_builder: impl for<'x> FnOnce(&'x rxml::QName) -> XmlNameMatcher<'x>,
|
||||
) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError> {
|
||||
let matcher = matcher_builder(&name);
|
||||
let start_scan_at = inner.partition_point(|entry| entry.matcher < matcher);
|
||||
|
||||
for entry in &inner[start_scan_at..] {
|
||||
if !entry.matcher.matches(&name) {
|
||||
return Err(FromEventsError::Mismatch { name, attrs });
|
||||
}
|
||||
|
||||
match (entry.builder)(name, attrs, ctx) {
|
||||
Ok(v) => return Ok(v),
|
||||
Err(FromEventsError::Invalid(e)) => return Err(FromEventsError::Invalid(e)),
|
||||
Err(FromEventsError::Mismatch {
|
||||
name: new_name,
|
||||
attrs: new_attrs,
|
||||
}) => {
|
||||
name = new_name;
|
||||
attrs = new_attrs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(FromEventsError::Mismatch { name, attrs })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: ?Sized + 'static> DynXsoRegistryAdd<T> for BuilderRegistry<T> {
|
||||
fn add<U: Any + FromXml>(&self)
|
||||
where
|
||||
T: MayContain<U>,
|
||||
{
|
||||
|
|
@ -452,50 +537,11 @@ impl<T: ?Sized + 'static> BuilderRegistry<T> {
|
|||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn try_build(
|
||||
inner: &mut Vec<BuilderRegistryEntry<T>>,
|
||||
mut name: rxml::QName,
|
||||
mut attrs: rxml::AttrMap,
|
||||
ctx: &Context<'_>,
|
||||
matcher_builder: impl for<'x> FnOnce(&'x rxml::QName) -> XmlNameMatcher<'x>,
|
||||
) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError> {
|
||||
let matcher = matcher_builder(&name);
|
||||
let start_scan_at = inner.partition_point(|entry| entry.matcher < matcher);
|
||||
|
||||
for entry in &inner[start_scan_at..] {
|
||||
if !entry.matcher.matches(&name) {
|
||||
return Err(FromEventsError::Mismatch { name, attrs });
|
||||
}
|
||||
|
||||
match (entry.builder)(name, attrs, ctx) {
|
||||
Ok(v) => return Ok(v),
|
||||
Err(FromEventsError::Invalid(e)) => return Err(FromEventsError::Invalid(e)),
|
||||
Err(FromEventsError::Mismatch {
|
||||
name: new_name,
|
||||
attrs: new_attrs,
|
||||
}) => {
|
||||
name = new_name;
|
||||
attrs = new_attrs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(FromEventsError::Mismatch { name, attrs })
|
||||
}
|
||||
|
||||
/// Make a builder for the given element header.
|
||||
///
|
||||
/// This tries all applicable `FromXml` implementations which have
|
||||
/// previously been added via [`add`][`Self::add`] in unspecified order.
|
||||
/// The first implementation to either fail or succeed at constructing a
|
||||
/// builder determines the result. Implementations which return a
|
||||
/// [`FromEventsError::Mismatch`][`crate::error::FromEventsError::Mismatch`]
|
||||
/// are ignored.
|
||||
///
|
||||
/// If all applicable implementations return `Mismatch`, this function
|
||||
/// returns `Mismatch`, too.
|
||||
pub fn make_builder(
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: ?Sized + 'static> DynXsoRegistryLookup<T> for BuilderRegistry<T> {
|
||||
fn make_builder(
|
||||
&self,
|
||||
name: rxml::QName,
|
||||
attrs: rxml::AttrMap,
|
||||
|
|
@ -522,6 +568,62 @@ impl<T: ?Sized + 'static> BuilderRegistry<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// # Helper traits for dynamic XSO builder registries.
|
||||
///
|
||||
/// Builder registries hold type-erased [`FromXml::from_events`]
|
||||
/// implementations. Registries can be used to dynamically dispatch to a set
|
||||
/// of `FromXml` implementations which is not known at compile time.
|
||||
///
|
||||
/// Under the hood, they are used by the `FromXml` implementation on
|
||||
/// [`Xso<T>`][`Xso`], via the [`DynXso::Registry`] type.
|
||||
///
|
||||
/// Note that registries generally do not allow to add arbitrary builders. All
|
||||
/// builders must originate in a [`FromXml`] implementation and their output
|
||||
/// must be convertible to the specific type the registry is defined for.
|
||||
///
|
||||
/// The default implementation is [`BuilderRegistry`], which is only available
|
||||
/// if `xso` is built with the `"std"` feature due to the inherent need for a
|
||||
/// `Mutex`.
|
||||
pub mod registry {
|
||||
use super::*;
|
||||
|
||||
/// Trait for a builder registry supports constructing elements.
|
||||
pub trait DynXsoRegistryLookup<T: ?Sized> {
|
||||
/// Make a builder for the given element header.
|
||||
///
|
||||
/// This tries all applicable `FromXml` implementations which have
|
||||
/// previously been added via [`add`][`DynXsoRegistryAdd::add`] in
|
||||
/// unspecified order. The first implementation to either fail or
|
||||
/// succeed at constructing a builder determines the result.
|
||||
/// Implementations which return a
|
||||
/// [`FromEventsError::Mismatch`][`crate::error::FromEventsError::Mismatch`]
|
||||
/// are ignored.
|
||||
///
|
||||
/// If all applicable implementations return `Mismatch`, this function
|
||||
/// returns `Mismatch`, too.
|
||||
fn make_builder(
|
||||
&self,
|
||||
name: rxml::QName,
|
||||
attrs: rxml::AttrMap,
|
||||
ctx: &Context<'_>,
|
||||
) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError>;
|
||||
}
|
||||
|
||||
/// Trait for a builder registry supports registering new builders at
|
||||
/// runtime.
|
||||
pub trait DynXsoRegistryAdd<T: ?Sized> {
|
||||
/// Add a new builder to the registry.
|
||||
///
|
||||
/// This allows to add any `FromXml` implementation whose output can be
|
||||
/// converted to `T`.
|
||||
fn add<U: Any + FromXml>(&self)
|
||||
where
|
||||
T: MayContain<U>;
|
||||
}
|
||||
}
|
||||
|
||||
use registry::*;
|
||||
|
||||
/// # Dynamic XSO type
|
||||
///
|
||||
/// This trait provides the infrastructure for dynamic XSO types. In
|
||||
|
|
@ -544,11 +646,24 @@ impl<T: ?Sized + 'static> BuilderRegistry<T> {
|
|||
/// *Hint*: It should not be necessary for user code to directly interact
|
||||
/// with this trait.
|
||||
pub trait DynXso: 'static {
|
||||
/// Builder registry type for this dynamic type.
|
||||
///
|
||||
/// The `Registry` type *should* implement the following traits:
|
||||
///
|
||||
/// - [`DynXsoRegistryAdd`] is required to make
|
||||
/// [`Xso::<Self>::register_type()`][`Xso::register_type`] available.
|
||||
/// - [`DynXsoRegistryLookup`] is required to make [`FromXml`] available
|
||||
/// on [`Xso<Self>`][`Xso`] (and, by extension, on
|
||||
/// [`XsoVec<Self>`][`XsoVec`]).
|
||||
///
|
||||
/// However, any type with static lifetime can be used, even without the
|
||||
/// trait implementations above, if the limitations are acceptable.
|
||||
type Registry: 'static;
|
||||
|
||||
/// Return the builder registry for this dynamic type.
|
||||
///
|
||||
/// The builder registry is used by [`Xso::register_type`] and the
|
||||
/// `FromXml` implementation.
|
||||
fn registry() -> &'static BuilderRegistry<Self>;
|
||||
/// See [`Registry`][`Self::Registry`] for details.
|
||||
fn registry() -> &'static Self::Registry;
|
||||
|
||||
/// Try to downcast a boxed dynamic XSO to a specific type.
|
||||
///
|
||||
|
|
@ -661,7 +776,8 @@ impl<T: ?Sized> Xso<T> {
|
|||
/// # use core::any::Any;
|
||||
/// # use xso::{dynxso::Xso, derive_dyn_traits};
|
||||
/// trait Trait: Any {}
|
||||
/// derive_dyn_traits!(Trait);
|
||||
#[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
|
||||
#[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
|
||||
///
|
||||
/// struct Foo;
|
||||
/// impl Trait for Foo {}
|
||||
|
|
@ -683,7 +799,8 @@ impl<T: ?Sized> Xso<T> {
|
|||
/// # use core::any::Any;
|
||||
/// # use xso::{dynxso::Xso, derive_dyn_traits};
|
||||
/// trait Trait: Any {}
|
||||
/// derive_dyn_traits!(Trait);
|
||||
#[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
|
||||
#[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
|
||||
///
|
||||
/// struct Foo;
|
||||
/// impl Trait for Foo {}
|
||||
|
|
@ -705,7 +822,8 @@ impl<T: DynXso + ?Sized + 'static> Xso<T> {
|
|||
/// # use core::any::Any;
|
||||
/// # use xso::{dynxso::Xso, derive_dyn_traits};
|
||||
/// trait Trait: Any {}
|
||||
/// derive_dyn_traits!(Trait);
|
||||
#[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
|
||||
#[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
|
||||
///
|
||||
/// struct Foo;
|
||||
/// impl Trait for Foo {}
|
||||
|
|
@ -750,7 +868,8 @@ impl<T: DynXso + ?Sized + 'static> Xso<T> {
|
|||
/// # use core::any::Any;
|
||||
/// # use xso::{dynxso::Xso, derive_dyn_traits};
|
||||
/// trait Trait: Any {}
|
||||
/// derive_dyn_traits!(Trait);
|
||||
#[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
|
||||
#[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
|
||||
///
|
||||
/// struct Foo;
|
||||
/// impl Trait for Foo {}
|
||||
|
|
@ -777,7 +896,8 @@ impl<T: DynXso + ?Sized + 'static> Xso<T> {
|
|||
/// # use core::any::Any;
|
||||
/// # use xso::{dynxso::Xso, derive_dyn_traits};
|
||||
/// trait Trait: Any {}
|
||||
/// derive_dyn_traits!(Trait);
|
||||
#[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
|
||||
#[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
|
||||
///
|
||||
/// struct Foo;
|
||||
/// impl Trait for Foo {}
|
||||
|
|
@ -801,7 +921,9 @@ impl<T: DynXso + ?Sized + 'static> Xso<T> {
|
|||
fn inner_type_id(&self) -> TypeId {
|
||||
DynXso::type_id(&*self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: DynXsoRegistryAdd<T> + 'static, T: DynXso<Registry = R> + ?Sized + 'static> Xso<T> {
|
||||
/// Register a new type to be constructible.
|
||||
///
|
||||
/// Only types registered through this function can be parsed from XML via
|
||||
|
|
@ -809,10 +931,10 @@ impl<T: DynXso + ?Sized + 'static> Xso<T> {
|
|||
/// [`dynxso`][`crate::dynxso`] for details.
|
||||
///
|
||||
#[cfg_attr(
|
||||
not(feature = "macros"),
|
||||
doc = "Because the macros feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
|
||||
not(all(feature = "macros", feature = "std")),
|
||||
doc = "Because the macros and std features were not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
|
||||
)]
|
||||
#[cfg_attr(feature = "macros", doc = "\n```\n")]
|
||||
#[cfg_attr(all(feature = "macros", feature = "std"), doc = "\n```\n")]
|
||||
/// # use core::any::Any;
|
||||
/// # use xso::{dynxso::Xso, derive_dyn_traits, from_bytes, FromXml};
|
||||
/// trait Trait: Any {}
|
||||
|
|
@ -882,7 +1004,9 @@ impl<O, T: FromEventsBuilder<Output = Box<O>>> FromEventsBuilder for UnboxBuilde
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: DynXso + ?Sized + 'static> FromXml for Xso<T> {
|
||||
impl<R: DynXsoRegistryLookup<T> + 'static, T: DynXso<Registry = R> + ?Sized + 'static> FromXml
|
||||
for Xso<T>
|
||||
{
|
||||
type Builder = DynBuilder<Box<dyn FromEventsBuilder<Output = Box<T>>>>;
|
||||
|
||||
fn from_events(
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ extern crate std;
|
|||
use std::io;
|
||||
|
||||
pub mod asxml;
|
||||
#[cfg(feature = "std")]
|
||||
pub mod dynxso;
|
||||
pub mod error;
|
||||
pub mod fromxml;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# use core::any::Any;
|
||||
# use core::fmt::Debug;
|
||||
# use xso::{derive_dyn_traits, dynxso::{XsoVec, TakeOneError}};
|
||||
# use xso::{dynxso::{XsoVec, TakeOneError, DynXso, MayContain}, derive_dyn_traits};
|
||||
#
|
||||
# trait Trait: Any + Debug {}
|
||||
#
|
||||
# derive_dyn_traits!(Trait);
|
||||
# derive_dyn_traits!(Trait use () = ());
|
||||
|
|
|
|||
Loading…
Reference in a new issue