#![cfg_attr(
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(all(feature = "macros", feature = "std"), doc = "\n```\n")]
use alloc::{
boxed::Box,
collections::{
btree_map::{self, Entry},
BTreeMap,
},
vec::{self, Vec},
};
#[cfg(feature = "std")]
use core::marker::PhantomData;
use core::{
any::{Any, TypeId},
fmt,
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},
AsXml, Context, FromEventsBuilder, FromXml, Item,
};
#[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")]
#[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")]
#[macro_export]
macro_rules! derive_dyn_traits {
($trait:ident use $registry:ty = $reginit:expr) => {
impl $crate::dynxso::DynXso for dyn $trait {
type Registry = $registry;
fn registry() -> &'static Self::Registry {
static DATA: $registry = $reginit;
&DATA
}
fn try_downcast<T: 'static>(
self: $crate::exports::alloc::boxed::Box<Self>,
) -> Result<
$crate::exports::alloc::boxed::Box<T>,
$crate::exports::alloc::boxed::Box<Self>,
>
where
Self: $crate::dynxso::MayContain<T>,
{
if (&*self as &dyn core::any::Any).is::<T>() {
match (self as $crate::exports::alloc::boxed::Box<dyn core::any::Any>)
.downcast()
{
Ok(v) => Ok(v),
Err(_) => unreachable!("Any::is and Any::downcast disagree!"),
}
} else {
Err(self)
}
}
fn try_downcast_ref<T: 'static>(&self) -> Option<&T>
where
Self: $crate::dynxso::MayContain<T>,
{
(&*self as &dyn core::any::Any).downcast_ref()
}
fn try_downcast_mut<T: 'static>(&mut self) -> Option<&mut T>
where
Self: $crate::dynxso::MayContain<T>,
{
(&mut *self as &mut dyn core::any::Any).downcast_mut()
}
fn is<T: 'static>(&self) -> bool
where
Self: $crate::dynxso::MayContain<T>,
{
(&*self as &dyn core::any::Any).is::<T>()
}
fn type_id(&self) -> core::any::TypeId {
(&*self as &dyn core::any::Any).type_id()
}
}
impl<T: $trait> $crate::dynxso::MayContain<T> for dyn $trait {
fn upcast_into(other: T) -> Box<Self> {
Box::new(other)
}
}
};
($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,
rxml::AttrMap,
&Context<'_>,
) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError>
+ Send
+ Sync
+ '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")
.field("matcher", &self.matcher)
.field("ty", &self.ty)
.finish_non_exhaustive()
}
}
#[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"
)]
#[cfg_attr(feature = "macros", doc = "\n```\n")]
#[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"
)]
#[cfg_attr(feature = "macros", doc = "\n```\n")]
#[derive(Debug)]
#[cfg(feature = "std")]
pub struct BuilderRegistry<T: ?Sized> {
inner: Mutex<Vec<BuilderRegistryEntry<T>>>,
}
#[cfg(feature = "std")]
impl<T: ?Sized + 'static> Default for BuilderRegistry<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "std")]
impl<T: ?Sized + 'static> BuilderRegistry<T> {
pub const fn new() -> Self {
Self {
inner: Mutex::new(Vec::new()),
}
}
fn insert(
&self,
matcher: XmlNameMatcher<'static>,
type_id: TypeId,
builder: BuilderRegistryBuilder<T>,
) {
let mut registry = self.inner.lock().unwrap();
let start_scan_at = registry.partition_point(|entry| entry.matcher < matcher);
let insert_at = 'outer: {
let mut i = start_scan_at;
while i < registry.len() {
let entry = ®istry[i];
if entry.matcher == matcher {
if entry.ty == type_id {
return;
}
i += 1;
continue;
}
break 'outer i;
}
registry.len()
};
registry.insert(
insert_at,
BuilderRegistryEntry {
matcher,
ty: type_id,
builder,
},
);
}
pub fn reserve(&self, n: usize) {
self.inner.lock().unwrap().reserve(n);
}
fn try_build(
inner: &mut [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>,
{
struct Wrapper<B, X: ?Sized> {
inner: B,
output: PhantomData<X>,
}
impl<X: ?Sized, O, B: FromEventsBuilder<Output = O>> FromEventsBuilder for Wrapper<B, X>
where
X: MayContain<O>,
{
type Output = Box<X>;
fn feed(
&mut self,
ev: rxml::Event,
ctx: &Context<'_>,
) -> Result<Option<Self::Output>, Error> {
self.inner
.feed(ev, ctx)
.map(|x| x.map(|x| <X as MayContain<O>>::upcast_into(x)))
}
}
self.insert(
U::xml_name_matcher(),
TypeId::of::<U>(),
Box::new(|name, attrs, ctx| {
U::from_events(name, attrs, ctx).map(|builder| {
Box::new(Wrapper {
inner: builder,
output: PhantomData,
}) as Box<dyn FromEventsBuilder<Output = Box<T>>>
})
}),
)
}
}
#[cfg(feature = "std")]
impl<T: ?Sized + 'static> DynXsoRegistryLookup<T> for BuilderRegistry<T> {
fn make_builder(
&self,
name: rxml::QName,
attrs: rxml::AttrMap,
ctx: &Context<'_>,
) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError> {
let mut inner = self.inner.lock().unwrap();
let (name, attrs) = match Self::try_build(&mut inner, name, attrs, ctx, |qname| {
XmlNameMatcher::Specific(qname.0.as_str(), qname.1.as_str())
}) {
Ok(v) => return Ok(v),
Err(FromEventsError::Invalid(e)) => return Err(FromEventsError::Invalid(e)),
Err(FromEventsError::Mismatch { name, attrs }) => (name, attrs),
};
let (name, attrs) = match Self::try_build(&mut inner, name, attrs, ctx, |qname| {
XmlNameMatcher::InNamespace(qname.0.as_str())
}) {
Ok(v) => return Ok(v),
Err(FromEventsError::Invalid(e)) => return Err(FromEventsError::Invalid(e)),
Err(FromEventsError::Mismatch { name, attrs }) => (name, attrs),
};
Self::try_build(&mut inner, name, attrs, ctx, |_| XmlNameMatcher::Any)
}
}
pub mod registry {
use super::*;
pub trait DynXsoRegistryLookup<T: ?Sized> {
fn make_builder(
&self,
name: rxml::QName,
attrs: rxml::AttrMap,
ctx: &Context<'_>,
) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError>;
}
pub trait DynXsoRegistryAdd<T: ?Sized> {
fn add<U: Any + FromXml>(&self)
where
T: MayContain<U>;
}
}
use registry::*;
pub trait DynXso: 'static {
type Registry: 'static;
fn registry() -> &'static Self::Registry;
fn try_downcast<T: 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>>
where
Self: MayContain<T>;
fn try_downcast_ref<T: 'static>(&self) -> Option<&T>
where
Self: MayContain<T>;
fn try_downcast_mut<T: 'static>(&mut self) -> Option<&mut T>
where
Self: MayContain<T>;
fn is<T: 'static>(&self) -> bool
where
Self: MayContain<T>;
fn type_id(&self) -> TypeId;
}
pub trait MayContain<T> {
fn upcast_into(other: T) -> Box<Self>;
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
#[repr(transparent)]
pub struct Xso<T: ?Sized> {
inner: Box<T>,
}
impl<T: ?Sized> Deref for Xso<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.inner.deref()
}
}
impl<T: ?Sized> DerefMut for Xso<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.inner.deref_mut()
}
}
impl<T: DynXso + ?Sized> fmt::Debug for Xso<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Xso")
.field("inner", &self.inner_type_id())
.finish()
}
}
impl<T: ?Sized> Xso<T> {
#[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
#[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
pub fn wrap<U: 'static>(value: U) -> Self
where
T: MayContain<U>,
{
Self {
inner: T::upcast_into(value),
}
}
#[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
#[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
pub fn into_boxed(self) -> Box<T> {
self.inner
}
}
impl<T: DynXso + ?Sized + 'static> Xso<T> {
#[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
#[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
pub fn downcast<U: 'static>(self) -> Result<Box<U>, Self>
where
T: MayContain<U>,
{
match self.inner.try_downcast() {
Ok(v) => Ok(v),
Err(inner) => Err(Self { inner }),
}
}
fn force_downcast<U: 'static>(self) -> Box<U>
where
T: MayContain<U>,
{
match self.downcast::<U>() {
Ok(v) => v,
Err(v) => panic!(
"force_downcast called on mismatching types: requested {:?} ({}) != actual {:?}",
TypeId::of::<U>(),
core::any::type_name::<U>(),
v.inner_type_id()
),
}
}
#[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
#[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
pub fn downcast_ref<U: 'static>(&self) -> Option<&U>
where
T: MayContain<U>,
{
self.inner.try_downcast_ref()
}
#[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
#[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
pub fn downcast_mut<U: 'static>(&mut self) -> Option<&mut U>
where
T: MayContain<U>,
{
self.inner.try_downcast_mut()
}
fn inner_type_id(&self) -> TypeId {
DynXso::type_id(&*self.inner)
}
}
impl<R: DynXsoRegistryAdd<T> + 'static, T: DynXso<Registry = R> + ?Sized + 'static> Xso<T> {
#[cfg_attr(
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(all(feature = "macros", feature = "std"), doc = "\n```\n")]
pub fn register_type<U: FromXml + 'static>()
where
T: MayContain<U>,
{
T::registry().add::<U>()
}
}
pub struct DynBuilder<B> {
inner: B,
}
impl<T: DynXso + ?Sized + 'static, B: FromEventsBuilder<Output = Box<T>>> FromEventsBuilder
for DynBuilder<B>
{
type Output = Xso<T>;
fn feed(&mut self, ev: rxml::Event, ctx: &Context) -> Result<Option<Self::Output>, Error> {
self.inner
.feed(ev, ctx)
.map(|x| x.map(|inner| Xso { inner }))
}
}
pub struct UnboxBuilder<T> {
inner: T,
}
impl<O, T: FromEventsBuilder<Output = Box<O>>> UnboxBuilder<T> {
pub fn wrap(inner: T) -> Self {
Self { inner }
}
}
impl<O, T: FromEventsBuilder<Output = Box<O>>> FromEventsBuilder for UnboxBuilder<T> {
type Output = O;
fn feed(&mut self, ev: rxml::Event, ctx: &Context) -> Result<Option<Self::Output>, Error> {
self.inner.feed(ev, ctx).map(|x| x.map(|inner| *inner))
}
}
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(
name: rxml::QName,
attrs: rxml::AttrMap,
ctx: &Context<'_>,
) -> Result<Self::Builder, FromEventsError> {
T::registry()
.make_builder(name, attrs, ctx)
.map(|inner| DynBuilder { inner })
}
}
impl<T: DynXso + AsXmlDyn + ?Sized + 'static> AsXml for Xso<T> {
type ItemIter<'x> = Box<dyn Iterator<Item = Result<Item<'x>, Error>> + 'x>;
fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
self.inner.as_xml_dyn_iter()
}
fn as_xml_dyn_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
self.inner.as_xml_dyn_iter()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum TakeOneError {
MultipleEntries,
}
impl fmt::Display for TakeOneError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::MultipleEntries => f.write_str("multiple entries found"),
}
}
}
pub struct XsoVec<T: ?Sized> {
inner: BTreeMap<TypeId, Vec<Xso<T>>>,
}
impl<T: ?Sized> fmt::Debug for XsoVec<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"XsoVec[{} types, {} items]",
self.inner.len(),
self.len()
)
}
}
impl<T: ?Sized> Default for XsoVec<T> {
fn default() -> Self {
Self {
inner: BTreeMap::default(),
}
}
}
impl<T: DynXso + ?Sized + 'static> XsoVec<T> {
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub const fn new() -> Self {
Self {
inner: BTreeMap::new(),
}
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn get_first<U: 'static>(&self) -> Option<&U>
where
T: MayContain<U>,
{
self.iter_typed::<U>().next()
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn get_first_mut<U: 'static>(&mut self) -> Option<&mut U>
where
T: MayContain<U>,
{
self.iter_typed_mut::<U>().next()
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn take_one<U: 'static>(&mut self) -> Result<Option<Box<U>>, TakeOneError>
where
T: MayContain<U>,
{
let source = match self.inner.get_mut(&TypeId::of::<U>()) {
Some(v) => v,
None => return Ok(None),
};
if source.len() > 1 {
return Err(TakeOneError::MultipleEntries);
}
Ok(source.pop().map(Xso::force_downcast))
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn take_first<U: 'static>(&mut self) -> Option<Box<U>>
where
T: MayContain<U>,
{
let source = self.inner.get_mut(&TypeId::of::<U>())?;
if source.len() == 0 {
return None;
}
Some(source.remove(0).force_downcast())
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn take_last<U: 'static>(&mut self) -> Option<Box<U>>
where
T: MayContain<U>,
{
let source = self.inner.get_mut(&TypeId::of::<U>())?;
source.pop().map(Xso::force_downcast)
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn iter_typed<U: 'static>(&self) -> impl Iterator<Item = &U>
where
T: MayContain<U>,
{
let iter = match self.inner.get(&TypeId::of::<U>()) {
Some(v) => v.deref().iter(),
None => [].iter(),
};
iter.map(|x| x.downcast_ref::<U>().unwrap())
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn iter_typed_mut<U: 'static>(&mut self) -> impl Iterator<Item = &mut U>
where
T: MayContain<U>,
{
let iter = match self.inner.get_mut(&TypeId::of::<U>()) {
Some(v) => v.deref_mut().iter_mut(),
None => [].iter_mut(),
};
iter.map(|x| x.downcast_mut::<U>().unwrap())
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn drain_typed<U: 'static>(&mut self) -> impl Iterator<Item = Box<U>>
where
T: MayContain<U>,
{
let iter = match self.inner.remove(&TypeId::of::<U>()) {
Some(v) => v.into_iter(),
None => Vec::new().into_iter(),
};
iter.map(|x| match x.downcast::<U>() {
Ok(v) => v,
Err(_) => {
unreachable!("TypeId disagrees with Xso<_>::downcast, or internal state corruption")
}
})
}
fn ensure_vec_mut_for(&mut self, type_id: TypeId) -> &mut Vec<Xso<T>> {
match self.inner.entry(type_id) {
Entry::Vacant(v) => v.insert(Vec::new()),
Entry::Occupied(o) => o.into_mut(),
}
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn push<U: 'static>(&mut self, value: U)
where
T: MayContain<U>,
{
self.ensure_vec_mut_for(TypeId::of::<U>())
.push(Xso::wrap(value));
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn push_dyn(&mut self, value: Xso<T>) {
self.ensure_vec_mut_for(value.inner_type_id()).push(value);
}
}
impl<T: ?Sized> XsoVec<T> {
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn clear(&mut self) {
self.inner.values_mut().for_each(|x| x.clear());
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn is_empty(&self) -> bool {
self.inner.values().all(|x| x.is_empty())
}
pub fn shrink_to_fit(&mut self) {
self.inner.retain(|_, x| {
if x.is_empty() {
return false;
}
x.shrink_to_fit();
true
});
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn len(&self) -> usize {
self.inner.values().map(|x| x.len()).sum()
}
#[doc = include_str!("xso_vec_test_prelude.rs")]
pub fn iter(&self) -> XsoVecIter<'_, T> {
XsoVecIter {
remaining: self.len(),
outer: self.inner.values(),
inner: None,
}
}
pub fn iter_mut(&mut self) -> XsoVecIterMut<'_, T> {
XsoVecIterMut {
remaining: self.len(),
outer: self.inner.values_mut(),
inner: None,
}
}
}
impl<T: ?Sized> IntoIterator for XsoVec<T> {
type Item = Xso<T>;
type IntoIter = XsoVecIntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
XsoVecIntoIter {
remaining: self.len(),
outer: self.inner.into_values(),
inner: None,
}
}
}
impl<'x, T: ?Sized> IntoIterator for &'x XsoVec<T> {
type Item = &'x Xso<T>;
type IntoIter = XsoVecIter<'x, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'x, T: ?Sized> IntoIterator for &'x mut XsoVec<T> {
type Item = &'x mut Xso<T>;
type IntoIter = XsoVecIterMut<'x, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T: DynXso + ?Sized + 'static> Extend<Xso<T>> for XsoVec<T> {
fn extend<I: IntoIterator<Item = Xso<T>>>(&mut self, iter: I) {
for item in iter {
self.ensure_vec_mut_for(item.inner_type_id()).push(item);
}
}
}
pub mod xso_vec {
use super::*;
pub struct XsoVecIter<'x, T: ?Sized> {
pub(super) outer: btree_map::Values<'x, TypeId, Vec<Xso<T>>>,
pub(super) inner: Option<slice::Iter<'x, Xso<T>>>,
pub(super) remaining: usize,
}
impl<'x, T: ?Sized> Iterator for XsoVecIter<'x, T> {
type Item = &'x Xso<T>;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(inner) = self.inner.as_mut() {
if let Some(item) = inner.next() {
self.remaining = self.remaining.saturating_sub(1);
return Some(item);
}
}
self.inner = Some(self.outer.next()?.deref().iter())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
pub struct XsoVecIterMut<'x, T: ?Sized> {
pub(super) outer: btree_map::ValuesMut<'x, TypeId, Vec<Xso<T>>>,
pub(super) inner: Option<slice::IterMut<'x, Xso<T>>>,
pub(super) remaining: usize,
}
impl<'x, T: ?Sized> Iterator for XsoVecIterMut<'x, T> {
type Item = &'x mut Xso<T>;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(inner) = self.inner.as_mut() {
if let Some(item) = inner.next() {
self.remaining = self.remaining.saturating_sub(1);
return Some(item);
}
}
self.inner = Some(self.outer.next()?.deref_mut().iter_mut())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
pub struct XsoVecIntoIter<T: ?Sized> {
pub(super) outer: btree_map::IntoValues<TypeId, Vec<Xso<T>>>,
pub(super) inner: Option<vec::IntoIter<Xso<T>>>,
pub(super) remaining: usize,
}
impl<T: ?Sized> Iterator for XsoVecIntoIter<T> {
type Item = Xso<T>;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(inner) = self.inner.as_mut() {
if let Some(item) = inner.next() {
self.remaining = self.remaining.saturating_sub(1);
return Some(item);
}
}
self.inner = Some(self.outer.next()?.into_iter())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
}
use xso_vec::*;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn xso_inner_type_id_is_correct() {
trait Trait: Any {}
crate::derive_dyn_traits!(Trait use () = ());
struct Foo;
impl Trait for Foo {}
let ty_id = TypeId::of::<Foo>();
let x: Xso<dyn Trait> = Xso::wrap(Foo);
assert_eq!(x.inner_type_id(), ty_id);
}
}