Skip to main content

xso/
dynxso.rs

1// Copyright (c) 2025 Jonas Schäfer <jonas@zombofant.net>
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7//! # Dynamically-typed XSOs
8//!
9//! This module provides the utilities to make dynamically-typed XSOs work.
10//! Dynamically typed XSOs are contained in [`Xso<dyn Trait>`][`Xso`], where
11//! `Trait` is a trait provided and defined by the user.
12//!
13//! The given `Trait` constrains the specific types which can be used in the
14//! `Xso<dyn Trait>` box. This allows users to provide additional methods on
15//! the trait which are available on all `Xso<dyn Trait>` objects via the
16//! [`Deref`][`core::ops::Deref`] and [`DerefMut`][`core::ops::DerefMut`]
17//! implementations.
18//!
19//! ## Creating a new `Trait`
20//!
21//! In order to be usable within `Xso<dyn Trait>`, a trait must satisfy the
22//! following constraints:
23//!
24//! - `dyn Trait` must implement [`DynXso`].
25//! - `dyn Trait` must implement [`MayContain<T>`] for all `T` which implement
26//!   `Trait`.
27//!
28//! The easiest and most forward-compatible way of providing these
29//! implementations is the [`derive_dyn_traits`][`crate::derive_dyn_traits`]
30//! macro.
31//!
32//! ## Example
33//!
34#![cfg_attr(
35    not(all(feature = "macros", feature = "std")),
36    doc = "Because the macros feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
37)]
38#![cfg_attr(all(feature = "macros", feature = "std"), doc = "\n```\n")]
39//! # use core::any::Any;
40//! # use xso::{dynxso::{Xso, BuilderRegistry}, FromXml, from_bytes, derive_dyn_traits};
41//! trait MyPayload: Any {}
42//!
43//! derive_dyn_traits!(MyPayload);
44//!
45//! #[derive(FromXml, Debug, PartialEq)]
46//! #[xml(namespace = "urn:example", name = "foo")]
47//! struct Foo;
48//! impl MyPayload for Foo {}
49//! Xso::<dyn MyPayload>::register_type::<Foo>();
50//!
51//! #[derive(FromXml, Debug, PartialEq)]
52//! #[xml(namespace = "urn:example", name = "bar")]
53//! struct Bar;
54//! impl MyPayload for Bar {}
55//! Xso::<dyn MyPayload>::register_type::<Bar>();
56//!
57//! let x: Xso<dyn MyPayload> = from_bytes("<foo xmlns='urn:example'/>".as_bytes()).unwrap();
58//! assert_eq!(Foo, *x.downcast::<Foo>().unwrap());
59//!
60//! let x: Xso<dyn MyPayload> = from_bytes("<bar xmlns='urn:example'/>".as_bytes()).unwrap();
61//! assert_eq!(Bar, *x.downcast::<Bar>().unwrap());
62//! ```
63
64use alloc::{
65    boxed::Box,
66    collections::{
67        btree_map::{self, Entry},
68        BTreeMap,
69    },
70    vec::{self, Vec},
71};
72use core::{
73    any::{Any, TypeId},
74    fmt,
75    ops::{Deref, DerefMut},
76    slice,
77};
78
79use crate::{
80    asxml::AsXmlDyn,
81    error::{Error, FromEventsError},
82    AsXml, Context, FromEventsBuilder, FromXml, Item,
83};
84
85/// **NOT** part of the public API -- only exposed for use by macros.
86#[doc(hidden)]
87#[cfg(feature = "linktime")]
88pub mod linktime;
89
90#[cfg(feature = "std")]
91mod stdreg;
92
93#[cfg(feature = "std")]
94pub use stdreg::*;
95
96#[doc(inline)]
97#[cfg(feature = "linktime")]
98pub use crate::__linktime as linktime;
99
100/// # Generate `DynXso` and `MayContain` trait implementations
101///
102/// This macro generates trait [`DynXso`] and [`MayContain`] trait
103/// implementations for a given trait. For more background information on when
104/// that is a useful thing to have, see the [`dynxso`][`crate::dynxso`]
105/// module.
106///
107/// ## Syntax
108///
109/// This macro can be called in two forms:
110///
111/// - `derive_dyn_traits!(Trait)` uses the default [`BuilderRegistry`]
112///    as [`DynXso::Registry`] type and is only available if `xso` is built
113///    with the `"std"` feature.
114/// - `derive_dyn_traits!(Trait use Type = expr)` where `Type` is used as
115///   [`DynXso::Registry`], initialized with `expr`. This form is available
116///   for any set of crate features.
117///
118/// ## Example
119///
120/// When `std` is enabled, the simple syntax can be used.
121#[cfg_attr(
122    not(feature = "std"),
123    doc = "Because the std feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
124)]
125#[cfg_attr(feature = "std", doc = "\n```\n")]
126/// # use core::any::Any;
127/// use xso::derive_dyn_traits;
128/// trait Foo: Any {}
129/// derive_dyn_traits!(Foo);
130/// ```
131///
132/// Note that the trait this macro is called on **must** have a bound on
133/// `Any`, otherwise the generated code will not compile:
134///
135#[cfg_attr(
136    not(feature = "std"),
137    doc = "Because the std feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
138)]
139#[cfg_attr(feature = "std", doc = "\n```compile_fail\n")]
140/// use xso::derive_dyn_traits;
141/// trait Foo {}
142/// derive_dyn_traits!(Foo);
143/// // ↑ will generate a bunch of errors about incompatible types
144/// ```
145///
146/// If the `std` feature is not enabled or if you want to use another
147/// `Registry` for whichever reason, the explicit form can be used:
148///
149/// ```
150/// # use core::any::Any;
151/// use xso::derive_dyn_traits;
152/// trait Foo: Any {}
153/// struct Registry { /* .. */ }
154/// derive_dyn_traits!(Foo use Registry = Registry { /* .. */ });
155/// ```
156///
157/// In that case, you should review the trait requirements of the
158/// [`DynXso::Registry`] associated type.
159#[macro_export]
160macro_rules! derive_dyn_traits {
161    ($trait:ident use $registry:ty = $reginit:expr) => {
162        impl $crate::dynxso::DynXso for dyn $trait {
163            type Registry = $registry;
164
165            fn registry() -> &'static Self::Registry {
166                static DATA: $registry = $reginit;
167                &DATA
168            }
169
170            fn try_downcast<T: 'static>(
171                self: $crate::exports::alloc::boxed::Box<Self>,
172            ) -> Result<
173                $crate::exports::alloc::boxed::Box<T>,
174                $crate::exports::alloc::boxed::Box<Self>,
175            >
176            where
177                Self: $crate::dynxso::MayContain<T>,
178            {
179                if (&*self as &dyn core::any::Any).is::<T>() {
180                    match (self as $crate::exports::alloc::boxed::Box<dyn core::any::Any>)
181                        .downcast()
182                    {
183                        Ok(v) => Ok(v),
184                        Err(_) => unreachable!("Any::is and Any::downcast disagree!"),
185                    }
186                } else {
187                    Err(self)
188                }
189            }
190
191            fn try_downcast_ref<T: 'static>(&self) -> Option<&T>
192            where
193                Self: $crate::dynxso::MayContain<T>,
194            {
195                (&*self as &dyn core::any::Any).downcast_ref()
196            }
197
198            fn try_downcast_mut<T: 'static>(&mut self) -> Option<&mut T>
199            where
200                Self: $crate::dynxso::MayContain<T>,
201            {
202                (&mut *self as &mut dyn core::any::Any).downcast_mut()
203            }
204
205            fn is<T: 'static>(&self) -> bool
206            where
207                Self: $crate::dynxso::MayContain<T>,
208            {
209                (&*self as &dyn core::any::Any).is::<T>()
210            }
211
212            fn type_id(&self) -> core::any::TypeId {
213                (&*self as &dyn core::any::Any).type_id()
214            }
215        }
216
217        impl<T: $trait> $crate::dynxso::MayContain<T> for dyn $trait {
218            fn upcast_into(other: T) -> Box<Self> {
219                Box::new(other)
220            }
221        }
222    };
223    ($trait:ident) => {
224        $crate::_internal_derive_dyn_traits_std_only!($trait);
225    };
226}
227
228#[macro_export]
229#[doc(hidden)]
230#[cfg(feature = "std")]
231macro_rules! _internal_derive_dyn_traits_std_only {
232    ($trait:ident) => {
233        $crate::derive_dyn_traits!($trait use $crate::dynxso::BuilderRegistry<dyn $trait> = $crate::dynxso::BuilderRegistry::new());
234    };
235}
236
237#[macro_export]
238#[doc(hidden)]
239#[cfg(not(feature = "std"))]
240macro_rules! _internal_derive_dyn_traits_std_only {
241    ($trait:ident) => {
242        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)."));
243    };
244}
245
246/// # Helper traits for dynamic XSO builder registries.
247///
248/// Builder registries hold type-erased [`FromXml::from_events`]
249/// implementations. Registries can be used to dynamically dispatch to a set
250/// of `FromXml` implementations which is not known at compile time.
251///
252/// Under the hood, they are used by the `FromXml` implementation on
253/// [`Xso<T>`][`Xso`], via the [`DynXso::Registry`] type.
254///
255/// Note that registries generally do not allow to add arbitrary builders. All
256/// builders must originate in a [`FromXml`] implementation and their output
257/// must be convertible to the specific type the registry is defined for.
258///
259/// The default implementation is [`BuilderRegistry`], which is only available
260/// if `xso` is built with the `"std"` feature due to the inherent need for a
261/// `Mutex`.
262pub mod registry {
263    use super::*;
264
265    /// Trait for a builder registry supports constructing elements.
266    pub trait DynXsoRegistryLookup<T: ?Sized> {
267        /// Make a builder for the given element header.
268        ///
269        /// This tries all applicable `FromXml` implementations which have
270        /// previously been added via [`add`][`DynXsoRegistryAdd::add`] in
271        /// unspecified order. The first implementation to either fail or
272        /// succeed at constructing a builder determines the result.
273        /// Implementations which return a
274        /// [`FromEventsError::Mismatch`][`crate::error::FromEventsError::Mismatch`]
275        /// are ignored.
276        ///
277        /// If all applicable implementations return `Mismatch`, this function
278        /// returns `Mismatch`, too.
279        fn make_builder(
280            &self,
281            name: rxml::QName,
282            attrs: rxml::AttrMap,
283            ctx: &Context<'_>,
284        ) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError>;
285    }
286
287    /// Trait for a builder registry supports registering new builders at
288    /// runtime.
289    pub trait DynXsoRegistryAdd<T: ?Sized> {
290        /// Add a new builder to the registry.
291        ///
292        /// This allows to add any `FromXml` implementation whose output can be
293        /// converted to `T`.
294        fn add<U: Any + FromXml>(&self)
295        where
296            T: MayContain<U>;
297    }
298}
299
300use registry::*;
301
302/// # Dynamic XSO type
303///
304/// This trait provides the infrastructure for dynamic XSO types. In
305/// particular, it provides:
306///
307/// - Access to a [`BuilderRegistry`] which allows constructing an instance of
308///   the dynamic XSO type from XML.
309/// - Downcasts to specific types.
310///
311/// Like [`MayContain`], it is typically implemented on `dyn Trait` for some
312/// `Trait` and it is best generated using
313/// [`derive_dyn_traits`][`crate::derive_dyn_traits`].
314///
315/// This trait explicitly provides the methods provided by [`Any`]. The reason
316/// for this duplication is that with `DynXso` being intended to be
317/// implemented on `dyn Trait`, code using this trait cannot cast the value
318/// to `dyn Any` to access the `downcast`-related methods (`type_id` would,
319/// in fact, work if `DynXso` had a bound on `Any`, but not the downcasts).
320///
321/// *Hint*: It should not be necessary for user code to directly interact
322/// with this trait.
323pub trait DynXso: 'static {
324    /// Builder registry type for this dynamic type.
325    ///
326    /// The `Registry` type *should* implement the following traits:
327    ///
328    /// - [`DynXsoRegistryAdd`] is required to make
329    ///   [`Xso::<Self>::register_type()`][`Xso::register_type`] available.
330    /// - [`DynXsoRegistryLookup`] is required to make [`FromXml`] available
331    ///   on [`Xso<Self>`][`Xso`] (and, by extension, on
332    ///   [`XsoVec<Self>`][`XsoVec`]).
333    ///
334    /// However, any type with static lifetime can be used, even without the
335    /// trait implementations above, if the limitations are acceptable.
336    type Registry: 'static;
337
338    /// Return the builder registry for this dynamic type.
339    ///
340    /// See [`Registry`][`Self::Registry`] for details.
341    fn registry() -> &'static Self::Registry;
342
343    /// Try to downcast a boxed dynamic XSO to a specific type.
344    ///
345    /// If `self` contains a `T` (and thus, the downcast succeeds), `Ok(_)`
346    /// is returned. Otherwise, `Err(self)` is returned, allowing to chain
347    /// this function with other downcast attempts.
348    ///
349    /// This is similar to `downcast` on [`dyn Any`][`core::any::Any`].
350    fn try_downcast<T: 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>>
351    where
352        Self: MayContain<T>;
353
354    /// Try to downcast a dynamic XSO to a reference to a specific type.
355    ///
356    /// If `self` contains a `T` (and thus, the downcast succeeds), `Some(_)`
357    /// is returned. Otherwise, `None`.
358    ///
359    /// This is similar to `downcast_ref` on [`dyn Any`][`core::any::Any`].
360    fn try_downcast_ref<T: 'static>(&self) -> Option<&T>
361    where
362        Self: MayContain<T>;
363
364    /// Try to downcast a dynamic XSO to a mutable reference to a specific
365    /// type.
366    ///
367    /// If `self` contains a `T` (and thus, the downcast succeeds), `Some(_)`
368    /// is returned. Otherwise, `None`.
369    ///
370    /// This is similar to `downcast_mut` on [`dyn Any`][`core::any::Any`].
371    fn try_downcast_mut<T: 'static>(&mut self) -> Option<&mut T>
372    where
373        Self: MayContain<T>;
374
375    /// Return true if `self` contains a `T`.
376    ///
377    /// This is similar to `is` on [`dyn Any`][`core::any::Any`].
378    fn is<T: 'static>(&self) -> bool
379    where
380        Self: MayContain<T>;
381
382    /// Return the [`TypeId`] of `self`.
383    ///
384    /// This is similar to `type_id` on [`dyn Any`][`core::any::Any`].
385    fn type_id(&self) -> TypeId;
386}
387
388/// # Declare that `T` may be held by `Box<Self>`
389///
390/// This trait is used to constrain which types can be put in
391/// [`Xso<Self>`][`Xso`]. It is typically implemented on `dyn Trait` for all
392/// `T: Trait`.
393///
394/// To automatically generate suitable implementations of this trait, see
395/// [`derive_dyn_traits`][`crate::derive_dyn_traits`].
396///
397/// Implementation-wise, this trait is very similar to `Box<Self>: From<T>`.
398/// However, `From` is also used in many different circumstances and it cannot
399/// be suitably overloaded on `Box<_>`, so a new trait was introduced for this
400/// particular purpose.
401pub trait MayContain<T> {
402    /// Convert a value of `T` into `Box<Self>`.
403    fn upcast_into(other: T) -> Box<Self>;
404}
405
406/// # Dynamic XSO container
407///
408/// This container is very similar to `Box<_>`, but geared specifically toward
409/// the use with `T` being a `dyn Trait`. It also implements [`FromXml`]
410/// (unconditionally) and [`AsXml`] if `T` implements [`AsXmlDyn`].
411///
412/// In order to provide these features, `T` must implement [`DynXso`] and
413/// [`MayContain`]. Implementations for these traits can be generated using
414/// [`derive_dyn_traits`][`crate::derive_dyn_traits`].
415///
416/// Most methods on `Xso<dyn Trait>` which take type parameters are only
417/// available for types `U` implementing `Trait` (or, more precisely, where
418/// `dyn Trait` implements `MayContain<U>`).
419#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
420#[repr(transparent)]
421pub struct Xso<T: ?Sized> {
422    inner: Box<T>,
423}
424
425impl<T: ?Sized> Deref for Xso<T> {
426    type Target = T;
427
428    fn deref(&self) -> &Self::Target {
429        self.inner.deref()
430    }
431}
432
433impl<T: ?Sized> DerefMut for Xso<T> {
434    fn deref_mut(&mut self) -> &mut Self::Target {
435        self.inner.deref_mut()
436    }
437}
438
439impl<T: DynXso + ?Sized> fmt::Debug for Xso<T> {
440    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
441        f.debug_struct("Xso")
442            .field("inner", &self.inner_type_id())
443            .finish()
444    }
445}
446
447impl<T: ?Sized> Xso<T> {
448    /// Wrap a value into a `Xso<dyn Trait>`.
449    ///
450    /// ```
451    /// # use core::any::Any;
452    /// # use xso::{dynxso::Xso, derive_dyn_traits};
453    /// trait Trait: Any {}
454    #[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
455    #[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
456    ///
457    /// struct Foo;
458    /// impl Trait for Foo {}
459    ///
460    /// let x: Xso<dyn Trait> = Xso::wrap(Foo);
461    /// ```
462    pub fn wrap<U: 'static>(value: U) -> Self
463    where
464        T: MayContain<U>,
465    {
466        Self {
467            inner: T::upcast_into(value),
468        }
469    }
470
471    /// Convert `Xso<T>` into `Box<T>`.
472    ///
473    /// ```
474    /// # use core::any::Any;
475    /// # use xso::{dynxso::Xso, derive_dyn_traits};
476    /// trait Trait: Any {}
477    #[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
478    #[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
479    ///
480    /// struct Foo;
481    /// impl Trait for Foo {}
482    ///
483    /// let x: Xso<dyn Trait> = Xso::wrap(Foo);
484    /// let x: Box<dyn Trait> = x.into_boxed();
485    /// ```
486    pub fn into_boxed(self) -> Box<T> {
487        self.inner
488    }
489}
490
491impl<T: DynXso + ?Sized + 'static> Xso<T> {
492    /// Downcast `self` to `Box<U>`.
493    ///
494    /// If the downcast fails, `self` is returned without change.
495    ///
496    /// ```
497    /// # use core::any::Any;
498    /// # use xso::{dynxso::Xso, derive_dyn_traits};
499    /// trait Trait: Any {}
500    #[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
501    #[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
502    ///
503    /// struct Foo;
504    /// impl Trait for Foo {}
505    ///
506    /// struct Bar;
507    /// impl Trait for Bar {}
508    ///
509    /// let x: Xso<dyn Trait> = Xso::wrap(Foo);
510    /// // Does not contain a Bar, so downcast fails.
511    /// let x: Xso<dyn Trait> = x.downcast::<Bar>().err().unwrap();
512    /// // *Does* contain a Foo, so downcast succeeds.
513    /// let f: Foo = *x.downcast().unwrap();
514    /// ```
515    pub fn downcast<U: 'static>(self) -> Result<Box<U>, Self>
516    where
517        T: MayContain<U>,
518    {
519        match self.inner.try_downcast() {
520            Ok(v) => Ok(v),
521            Err(inner) => Err(Self { inner }),
522        }
523    }
524
525    fn force_downcast<U: 'static>(self) -> Box<U>
526    where
527        T: MayContain<U>,
528    {
529        match self.downcast::<U>() {
530            Ok(v) => v,
531            Err(v) => panic!(
532                "force_downcast called on mismatching types: requested {:?} ({}) != actual {:?}",
533                TypeId::of::<U>(),
534                core::any::type_name::<U>(),
535                v.inner_type_id()
536            ),
537        }
538    }
539
540    /// Downcast `&self` to `&U`.
541    ///
542    /// ```
543    /// # use core::any::Any;
544    /// # use xso::{dynxso::Xso, derive_dyn_traits};
545    /// trait Trait: Any {}
546    #[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
547    #[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
548    ///
549    /// struct Foo;
550    /// impl Trait for Foo {}
551    ///
552    /// struct Bar;
553    /// impl Trait for Bar {}
554    ///
555    /// let x: Xso<dyn Trait> = Xso::wrap(Foo);
556    /// // Does not contain a Bar, so downcast fails.
557    /// assert!(x.downcast_ref::<Bar>().is_none());
558    /// // *Does* contain a Foo, so downcast succeeds.
559    /// let f: &Foo = x.downcast_ref().unwrap();
560    /// ```
561    pub fn downcast_ref<U: 'static>(&self) -> Option<&U>
562    where
563        T: MayContain<U>,
564    {
565        self.inner.try_downcast_ref()
566    }
567
568    /// Downcast `&mut self` to `&mut U`.
569    ///
570    /// ```
571    /// # use core::any::Any;
572    /// # use xso::{dynxso::Xso, derive_dyn_traits};
573    /// trait Trait: Any {}
574    #[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
575    #[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
576    ///
577    /// struct Foo;
578    /// impl Trait for Foo {}
579    ///
580    /// struct Bar;
581    /// impl Trait for Bar {}
582    ///
583    /// let mut x: Xso<dyn Trait> = Xso::wrap(Foo);
584    /// // Does not contain a Bar, so downcast fails.
585    /// assert!(x.downcast_mut::<Bar>().is_none());
586    /// // *Does* contain a Foo, so downcast succeeds.
587    /// let f: &mut Foo = x.downcast_mut().unwrap();
588    /// ```
589    pub fn downcast_mut<U: 'static>(&mut self) -> Option<&mut U>
590    where
591        T: MayContain<U>,
592    {
593        self.inner.try_downcast_mut()
594    }
595
596    fn inner_type_id(&self) -> TypeId {
597        DynXso::type_id(&*self.inner)
598    }
599}
600
601impl<R: DynXsoRegistryAdd<T> + 'static, T: DynXso<Registry = R> + ?Sized + 'static> Xso<T> {
602    /// Register a new type to be constructible.
603    ///
604    /// Only types registered through this function or through
605    /// [`linktime`] can be parsed from XML via the [`FromXml`]
606    /// implementation on `Xso<T>`. See [`dynxso`][`crate::dynxso`] for
607    /// details.
608    ///
609    #[cfg_attr(
610        not(all(feature = "macros", feature = "std")),
611        doc = "Because the macros and std features were not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
612    )]
613    #[cfg_attr(all(feature = "macros", feature = "std"), doc = "\n```\n")]
614    /// # use core::any::Any;
615    /// # use xso::{dynxso::Xso, derive_dyn_traits, from_bytes, FromXml};
616    /// trait Trait: Any {}
617    /// derive_dyn_traits!(Trait);
618    ///
619    /// #[derive(FromXml, PartialEq, Debug)]
620    /// #[xml(namespace = "urn:example", name = "foo")]
621    /// struct Foo;
622    /// impl Trait for Foo {}
623    ///
624    /// // Parsing fails, because register_type() has not been called for
625    /// // Foo:
626    /// assert!(from_bytes::<Xso<dyn Trait>>("<foo xmlns='urn:example'/>".as_bytes()).is_err());
627    ///
628    /// Xso::<dyn Trait>::register_type::<Foo>();
629    /// // After registering Foo with Xso<dyn Trait>, parsing succeeds and
630    /// // we can downcast to Foo:
631    /// let x: Xso<dyn Trait> = from_bytes("<foo xmlns='urn:example'/>".as_bytes()).unwrap();
632    /// assert_eq!(Foo, *x.downcast().unwrap());
633    /// ```
634    pub fn register_type<U: FromXml + 'static>()
635    where
636        T: MayContain<U>,
637    {
638        T::registry().add::<U>()
639    }
640}
641
642/// Wrapper around a `FromEventsBuilder` to convert a `Box<T>` output to a
643/// `Xso<T>` output.
644///
645/// Not constructible by users, only for internal use.
646pub struct DynBuilder<B> {
647    inner: B,
648}
649
650impl<T: DynXso + ?Sized + 'static, B: FromEventsBuilder<Output = Box<T>>> FromEventsBuilder
651    for DynBuilder<B>
652{
653    type Output = Xso<T>;
654
655    fn feed(&mut self, ev: rxml::Event, ctx: &Context) -> Result<Option<Self::Output>, Error> {
656        self.inner
657            .feed(ev, ctx)
658            .map(|x| x.map(|inner| Xso { inner }))
659    }
660}
661
662/// Wrapper around a `FromEventsBuilder` to convert a `Box<T>` output to a
663/// `T` output.
664pub struct UnboxBuilder<T> {
665    inner: T,
666}
667
668impl<O, T: FromEventsBuilder<Output = Box<O>>> UnboxBuilder<T> {
669    /// Wrap a `FromEventsBuilder` which generates `Box<O>`.
670    pub fn wrap(inner: T) -> Self {
671        Self { inner }
672    }
673}
674
675impl<O, T: FromEventsBuilder<Output = Box<O>>> FromEventsBuilder for UnboxBuilder<T> {
676    type Output = O;
677
678    fn feed(&mut self, ev: rxml::Event, ctx: &Context) -> Result<Option<Self::Output>, Error> {
679        self.inner.feed(ev, ctx).map(|x| x.map(|inner| *inner))
680    }
681}
682
683impl<R: DynXsoRegistryLookup<T> + 'static, T: DynXso<Registry = R> + ?Sized + 'static> FromXml
684    for Xso<T>
685{
686    type Builder = DynBuilder<Box<dyn FromEventsBuilder<Output = Box<T>>>>;
687
688    fn from_events(
689        name: rxml::QName,
690        attrs: rxml::AttrMap,
691        ctx: &Context<'_>,
692    ) -> Result<Self::Builder, FromEventsError> {
693        T::registry()
694            .make_builder(name, attrs, ctx)
695            .map(|inner| DynBuilder { inner })
696    }
697}
698
699impl<T: DynXso + AsXmlDyn + ?Sized + 'static> AsXml for Xso<T> {
700    type ItemIter<'x> = Box<dyn Iterator<Item = Result<Item<'x>, Error>> + 'x>;
701
702    fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
703        self.inner.as_xml_dyn_iter()
704    }
705
706    fn as_xml_dyn_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
707        self.inner.as_xml_dyn_iter()
708    }
709}
710
711/// Error type for retrieving a single item from `XsoVec`.
712#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
713pub enum TakeOneError {
714    /// More than one item was found.
715    MultipleEntries,
716}
717
718impl fmt::Display for TakeOneError {
719    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
720        match self {
721            Self::MultipleEntries => f.write_str("multiple entries found"),
722        }
723    }
724}
725
726/// # Container for dynamically-typed XSOs optimized for type-keyed access
727///
728/// This container holds dynamically typed XSOs (see
729/// [`Xso<dyn Trait>`][`Xso`]). It allows efficient access to its contents
730/// based on the actual type.
731///
732/// Like `Xso<dyn Trait>` itself, `XsoVec<dyn Trait>` requires that
733/// `MayContain` is implemented by `dyn Trait` for all items which are added
734/// to the container. This is automatically the case for all `T: Trait`
735/// if [`derive_dyn_traits`][`crate::derive_dyn_traits`] has been used on
736/// `Trait`.
737///
738/// Note that `XsoVec` has a non-obvious iteration order, which is described
739/// in [`XsoVec::iter()`][`Self::iter`].
740pub struct XsoVec<T: ?Sized> {
741    inner: BTreeMap<TypeId, Vec<Xso<T>>>,
742}
743
744impl<T: ?Sized> fmt::Debug for XsoVec<T> {
745    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
746        write!(
747            f,
748            "XsoVec[{} types, {} items]",
749            self.inner.len(),
750            self.len()
751        )
752    }
753}
754
755impl<T: ?Sized> Default for XsoVec<T> {
756    fn default() -> Self {
757        Self {
758            inner: BTreeMap::default(),
759        }
760    }
761}
762
763impl<T: DynXso + ?Sized + 'static> XsoVec<T> {
764    /// Construct a new, empty `XsoVec`.
765    ///
766    /// ```
767    #[doc = include_str!("xso_vec_test_prelude.rs")]
768    /// let mut vec = XsoVec::<dyn Trait>::new();
769    /// ```
770    pub const fn new() -> Self {
771        Self {
772            inner: BTreeMap::new(),
773        }
774    }
775
776    /// Return a reference to the first item of type `U`.
777    ///
778    /// If the container does not hold any item of type `U`, return `None`.
779    ///
780    /// ```
781    #[doc = include_str!("xso_vec_test_prelude.rs")]
782    /// #[derive(PartialEq, Debug)]
783    /// struct Foo(u8);
784    /// impl Trait for Foo {}
785    ///
786    /// #[derive(PartialEq, Debug)]
787    /// struct Bar(u16);
788    /// impl Trait for Bar {}
789    ///
790    /// #[derive(PartialEq, Debug)]
791    /// struct Baz(u32);
792    /// impl Trait for Baz {}
793    ///
794    /// let mut vec = XsoVec::<dyn Trait>::new();
795    /// vec.push(Bar(1));
796    /// vec.push(Foo(2));
797    /// vec.push(Foo(1));
798    /// assert_eq!(vec.get_first::<Foo>(), Some(&Foo(2)));
799    /// assert_eq!(vec.get_first::<Bar>(), Some(&Bar(1)));
800    /// assert_eq!(vec.get_first::<Baz>(), None);
801    ///
802    /// ```
803    pub fn get_first<U: 'static>(&self) -> Option<&U>
804    where
805        T: MayContain<U>,
806    {
807        self.iter_typed::<U>().next()
808    }
809
810    /// Return a mutable reference to the first item of type `U`.
811    ///
812    /// If the container does not hold any item of type `U`, return `None`.
813    ///
814    /// ```
815    #[doc = include_str!("xso_vec_test_prelude.rs")]
816    /// #[derive(PartialEq, Debug)]
817    /// struct Foo(u8);
818    /// impl Trait for Foo {}
819    ///
820    /// let mut vec = XsoVec::<dyn Trait>::new();
821    /// vec.push(Foo(1));
822    /// vec.get_first_mut::<Foo>().unwrap().0 = 2;
823    /// assert_eq!(vec.get_first::<Foo>(), Some(&Foo(2)));
824    /// ```
825    pub fn get_first_mut<U: 'static>(&mut self) -> Option<&mut U>
826    where
827        T: MayContain<U>,
828    {
829        self.iter_typed_mut::<U>().next()
830    }
831
832    /// Take and return exactly one item of type `U`.
833    ///
834    /// If no item of type `U` is present in the container, return Ok(None).
835    /// If more than one item of type `U` is present in the container,
836    /// return an error.
837    /// ```
838    #[doc = include_str!("xso_vec_test_prelude.rs")]
839    /// #[derive(PartialEq, Debug)]
840    /// struct Foo(u8);
841    /// impl Trait for Foo {}
842    ///
843    /// #[derive(PartialEq, Debug)]
844    /// struct Bar(u16);
845    /// impl Trait for Bar {}
846    ///
847    /// #[derive(PartialEq, Debug)]
848    /// struct Baz(u32);
849    /// impl Trait for Baz {}
850    ///
851    /// let mut vec = XsoVec::<dyn Trait>::new();
852    /// vec.push(Bar(1));
853    /// vec.push(Foo(2));
854    /// vec.push(Foo(1));
855    /// assert_eq!(vec.take_one::<Foo>(), Err(TakeOneError::MultipleEntries));
856    /// assert_eq!(*vec.take_one::<Bar>().unwrap().unwrap(), Bar(1));
857    /// assert_eq!(vec.take_one::<Bar>(), Ok(None));
858    /// assert_eq!(vec.take_one::<Baz>(), Ok(None));
859    /// ```
860    pub fn take_one<U: 'static>(&mut self) -> Result<Option<Box<U>>, TakeOneError>
861    where
862        T: MayContain<U>,
863    {
864        let source = match self.inner.get_mut(&TypeId::of::<U>()) {
865            Some(v) => v,
866            None => return Ok(None),
867        };
868        if source.len() > 1 {
869            return Err(TakeOneError::MultipleEntries);
870        }
871        Ok(source.pop().map(Xso::force_downcast))
872    }
873
874    /// Take and return the first item of type `U`.
875    ///
876    /// If no item of type `U` is present in the container, return None.
877    /// ```
878    #[doc = include_str!("xso_vec_test_prelude.rs")]
879    /// #[derive(PartialEq, Debug)]
880    /// struct Foo(u8);
881    /// impl Trait for Foo {}
882    ///
883    /// #[derive(PartialEq, Debug)]
884    /// struct Bar(u16);
885    /// impl Trait for Bar {}
886    ///
887    /// #[derive(PartialEq, Debug)]
888    /// struct Baz(u32);
889    /// impl Trait for Baz {}
890    ///
891    /// let mut vec = XsoVec::<dyn Trait>::new();
892    /// vec.push(Bar(1));
893    /// vec.push(Foo(2));
894    /// vec.push(Foo(1));
895    /// assert_eq!(*vec.take_first::<Foo>().unwrap(), Foo(2));
896    /// assert_eq!(*vec.take_first::<Foo>().unwrap(), Foo(1));
897    /// assert_eq!(*vec.take_first::<Bar>().unwrap(), Bar(1));
898    /// assert_eq!(vec.take_first::<Bar>(), None);
899    /// assert_eq!(vec.take_first::<Baz>(), None);
900    /// ```
901    pub fn take_first<U: 'static>(&mut self) -> Option<Box<U>>
902    where
903        T: MayContain<U>,
904    {
905        let source = self.inner.get_mut(&TypeId::of::<U>())?;
906        if source.len() == 0 {
907            return None;
908        }
909        Some(source.remove(0).force_downcast())
910    }
911
912    /// Take and return the last item of type `U`.
913    ///
914    /// If no item of type `U` is present in the container, return None.
915    /// ```
916    #[doc = include_str!("xso_vec_test_prelude.rs")]
917    /// #[derive(PartialEq, Debug)]
918    /// struct Foo(u8);
919    /// impl Trait for Foo {}
920    ///
921    /// #[derive(PartialEq, Debug)]
922    /// struct Bar(u16);
923    /// impl Trait for Bar {}
924    ///
925    /// #[derive(PartialEq, Debug)]
926    /// struct Baz(u32);
927    /// impl Trait for Baz {}
928    ///
929    /// let mut vec = XsoVec::<dyn Trait>::new();
930    /// vec.push(Bar(1));
931    /// vec.push(Foo(2));
932    /// vec.push(Foo(1));
933    /// assert_eq!(*vec.take_last::<Foo>().unwrap(), Foo(1));
934    /// assert_eq!(*vec.take_last::<Foo>().unwrap(), Foo(2));
935    /// assert_eq!(*vec.take_last::<Bar>().unwrap(), Bar(1));
936    /// assert_eq!(vec.take_last::<Bar>(), None);
937    /// assert_eq!(vec.take_last::<Baz>(), None);
938    /// ```
939    pub fn take_last<U: 'static>(&mut self) -> Option<Box<U>>
940    where
941        T: MayContain<U>,
942    {
943        let source = self.inner.get_mut(&TypeId::of::<U>())?;
944        source.pop().map(Xso::force_downcast)
945    }
946
947    /// Iterate all items of type `U` as references.
948    ///
949    /// ```
950    #[doc = include_str!("xso_vec_test_prelude.rs")]
951    /// #[derive(PartialEq, Debug)]
952    /// struct Foo(u8);
953    /// impl Trait for Foo {}
954    ///
955    /// #[derive(PartialEq, Debug)]
956    /// struct Bar(u16);
957    /// impl Trait for Bar {}
958    ///
959    /// #[derive(PartialEq, Debug)]
960    /// struct Baz(u32);
961    /// impl Trait for Baz {}
962    ///
963    /// let mut vec = XsoVec::<dyn Trait>::new();
964    /// vec.push(Bar(1));
965    /// vec.push(Foo(2));
966    /// vec.push(Foo(1));
967    ///
968    /// let foos: Vec<_> = vec.iter_typed::<Foo>().collect();
969    /// assert_eq!(&foos[..], &[&Foo(2), &Foo(1)]);
970    /// ```
971    pub fn iter_typed<U: 'static>(&self) -> impl Iterator<Item = &U>
972    where
973        T: MayContain<U>,
974    {
975        let iter = match self.inner.get(&TypeId::of::<U>()) {
976            Some(v) => v.deref().iter(),
977            None => [].iter(),
978        };
979        // UNWRAP: We group the values by TypeId, so the downcast should never
980        // fail, but I am too chicken to use the unchecked variants :).
981        iter.map(|x| x.downcast_ref::<U>().unwrap())
982    }
983
984    /// Iterate all items of type `U` as mutable references.
985    ///
986    /// ```
987    #[doc = include_str!("xso_vec_test_prelude.rs")]
988    /// #[derive(PartialEq, Debug)]
989    /// struct Foo(u8);
990    /// impl Trait for Foo {}
991    ///
992    /// #[derive(PartialEq, Debug)]
993    /// struct Bar(u16);
994    /// impl Trait for Bar {}
995    ///
996    /// #[derive(PartialEq, Debug)]
997    /// struct Baz(u32);
998    /// impl Trait for Baz {}
999    ///
1000    /// let mut vec = XsoVec::<dyn Trait>::new();
1001    /// vec.push(Bar(1));
1002    /// vec.push(Foo(2));
1003    /// vec.push(Foo(1));
1004    ///
1005    /// let foos: Vec<_> = vec.iter_typed_mut::<Foo>().collect();
1006    /// assert_eq!(&foos[..], &[&mut Foo(2), &mut Foo(1)]);
1007    /// ```
1008    pub fn iter_typed_mut<U: 'static>(&mut self) -> impl Iterator<Item = &mut U>
1009    where
1010        T: MayContain<U>,
1011    {
1012        let iter = match self.inner.get_mut(&TypeId::of::<U>()) {
1013            Some(v) => v.deref_mut().iter_mut(),
1014            None => [].iter_mut(),
1015        };
1016        // UNWRAP: We group the values by TypeId, so the downcast should never
1017        // fail, but I am too chicken to use the unchecked variants :).
1018        iter.map(|x| x.downcast_mut::<U>().unwrap())
1019    }
1020
1021    /// Drain all items of type `U` out of the container.
1022    ///
1023    /// If the result is dropped before the end of the iterator has been
1024    /// reached, the remaining items are still dropped out of the container.
1025    ///
1026    /// ```
1027    #[doc = include_str!("xso_vec_test_prelude.rs")]
1028    /// #[derive(PartialEq, Debug)]
1029    /// struct Foo(u8);
1030    /// impl Trait for Foo {}
1031    ///
1032    /// #[derive(PartialEq, Debug)]
1033    /// struct Bar(u16);
1034    /// impl Trait for Bar {}
1035    ///
1036    /// #[derive(PartialEq, Debug)]
1037    /// struct Baz(u32);
1038    /// impl Trait for Baz {}
1039    ///
1040    /// let mut vec = XsoVec::<dyn Trait>::new();
1041    /// vec.push(Bar(1));
1042    /// vec.push(Foo(2));
1043    /// vec.push(Foo(1));
1044    ///
1045    /// let foos: Vec<_> = vec.drain_typed::<Foo>().map(|x| *x).collect();
1046    /// //                             converts Box<T> to T ↑
1047    /// assert_eq!(&foos[..], &[Foo(2), Foo(1)]);
1048    /// ```
1049    pub fn drain_typed<U: 'static>(&mut self) -> impl Iterator<Item = Box<U>>
1050    where
1051        T: MayContain<U>,
1052    {
1053        let iter = match self.inner.remove(&TypeId::of::<U>()) {
1054            Some(v) => v.into_iter(),
1055            None => Vec::new().into_iter(),
1056        };
1057        // UNWRAP: We group the values by TypeId, so the downcast should never
1058        // fail, but I am too chicken to use the unchecked variants :).
1059        iter.map(|x| match x.downcast::<U>() {
1060            Ok(v) => v,
1061            Err(_) => {
1062                unreachable!("TypeId disagrees with Xso<_>::downcast, or internal state corruption")
1063            }
1064        })
1065    }
1066
1067    fn ensure_vec_mut_for(&mut self, type_id: TypeId) -> &mut Vec<Xso<T>> {
1068        match self.inner.entry(type_id) {
1069            Entry::Vacant(v) => v.insert(Vec::new()),
1070            Entry::Occupied(o) => o.into_mut(),
1071        }
1072    }
1073
1074    /// Push a new item of type `U` to the end of the section of `U` inside
1075    /// the container.
1076    ///
1077    /// Please note the information about iteration order of the `XsoVec`
1078    /// at [`XsoVec::iter`][`Self::iter`].
1079    ///
1080    /// ```
1081    #[doc = include_str!("xso_vec_test_prelude.rs")]
1082    /// #[derive(PartialEq, Debug)]
1083    /// struct Foo(u8);
1084    /// impl Trait for Foo {}
1085    ///
1086    /// let mut vec = XsoVec::<dyn Trait>::new();
1087    /// vec.push(Foo(1));
1088    /// ```
1089    pub fn push<U: 'static>(&mut self, value: U)
1090    where
1091        T: MayContain<U>,
1092    {
1093        self.ensure_vec_mut_for(TypeId::of::<U>())
1094            .push(Xso::wrap(value));
1095    }
1096
1097    /// Push a new dynamically typed item to the end of the section of values
1098    /// with the same type inside the container.
1099    ///
1100    /// Please note the information about iteration order of the `XsoVec`
1101    /// at [`XsoVec::iter`][`Self::iter`].
1102    ///
1103    /// ```
1104    /// # use xso::dynxso::Xso;
1105    #[doc = include_str!("xso_vec_test_prelude.rs")]
1106    /// #[derive(PartialEq, Debug)]
1107    /// struct Foo(u8);
1108    /// impl Trait for Foo {}
1109    ///
1110    /// #[derive(PartialEq, Debug)]
1111    /// struct Bar(u8);
1112    /// impl Trait for Bar {}
1113    ///
1114    /// let mut vec = XsoVec::<dyn Trait>::new();
1115    /// vec.push(Foo(1));
1116    /// vec.push_dyn(Xso::wrap(Foo(2)));
1117    /// vec.push_dyn(Xso::wrap(Bar(1)));
1118    /// vec.push(Bar(2));
1119    ///
1120    /// let foos: Vec<_> = vec.iter_typed::<Foo>().collect();
1121    /// assert_eq!(&foos[..], &[&Foo(1), &Foo(2)]);
1122    ///
1123    /// let bars: Vec<_> = vec.iter_typed::<Bar>().collect();
1124    /// assert_eq!(&bars[..], &[&Bar(1), &Bar(2)]);
1125    /// ```
1126    pub fn push_dyn(&mut self, value: Xso<T>) {
1127        self.ensure_vec_mut_for(value.inner_type_id()).push(value);
1128    }
1129}
1130
1131impl<T: ?Sized> XsoVec<T> {
1132    /// Clear all contents, without deallocating memory.
1133    ///
1134    /// ```
1135    #[doc = include_str!("xso_vec_test_prelude.rs")]
1136    /// #[derive(PartialEq, Debug)]
1137    /// struct Foo(u8);
1138    /// impl Trait for Foo {}
1139    ///
1140    /// let mut vec = XsoVec::<dyn Trait>::new();
1141    /// vec.push(Foo(1));
1142    /// vec.push(Foo(2));
1143    /// vec.clear();
1144    /// assert_eq!(vec.len(), 0);
1145    /// ```
1146    pub fn clear(&mut self) {
1147        self.inner.values_mut().for_each(|x| x.clear());
1148    }
1149
1150    /// Return true if there are no items in the container.
1151    ///
1152    /// ```
1153    #[doc = include_str!("xso_vec_test_prelude.rs")]
1154    /// #[derive(PartialEq, Debug)]
1155    /// struct Foo(u8);
1156    /// impl Trait for Foo {}
1157    ///
1158    /// let mut vec = XsoVec::<dyn Trait>::new();
1159    /// assert!(vec.is_empty());
1160    /// vec.push(Foo(1));
1161    /// assert!(!vec.is_empty());
1162    /// ```
1163    pub fn is_empty(&self) -> bool {
1164        self.inner.values().all(|x| x.is_empty())
1165    }
1166
1167    /// Reduce memory use of the container to the minimum required to hold
1168    /// the current data.
1169    ///
1170    /// This may be expensive if lots of data needs to be shuffled.
1171    pub fn shrink_to_fit(&mut self) {
1172        self.inner.retain(|_, x| {
1173            if x.is_empty() {
1174                return false;
1175            }
1176            x.shrink_to_fit();
1177            true
1178        });
1179    }
1180
1181    /// Return the total amount of items in the container.
1182    ///
1183    /// ```
1184    #[doc = include_str!("xso_vec_test_prelude.rs")]
1185    /// #[derive(PartialEq, Debug)]
1186    /// struct Foo(u8);
1187    /// impl Trait for Foo {}
1188    ///
1189    /// let mut vec = XsoVec::<dyn Trait>::new();
1190    /// assert_eq!(vec.len(), 0);
1191    /// vec.push(Foo(1));
1192    /// assert_eq!(vec.len(), 1);
1193    /// ```
1194    pub fn len(&self) -> usize {
1195        self.inner.values().map(|x| x.len()).sum()
1196    }
1197
1198    /// Iterate the items inside the container.
1199    ///
1200    /// This iterator (unlike the iterator returned by
1201    /// [`iter_typed()`][`Self::iter_typed`]) yields references to **untyped**
1202    /// [`Xso<dyn Trait>`][`Xso`].
1203    ///
1204    /// # Iteration order
1205    ///
1206    /// Items which have the same concrete type are grouped and their ordering
1207    /// with respect to one another is preserved. However, the ordering of
1208    /// items with *different* concrete types is unspecified.
1209    ///
1210    /// # Example
1211    ///
1212    /// ```
1213    #[doc = include_str!("xso_vec_test_prelude.rs")]
1214    /// #[derive(PartialEq, Debug)]
1215    /// struct Foo(u8);
1216    /// impl Trait for Foo {}
1217    ///
1218    /// #[derive(PartialEq, Debug)]
1219    /// struct Bar(u16);
1220    /// impl Trait for Bar {}
1221    ///
1222    /// let mut vec = XsoVec::<dyn Trait>::new();
1223    /// vec.push(Foo(1));
1224    /// vec.push(Bar(1));
1225    /// vec.push(Foo(2));
1226    ///
1227    /// for item in vec.iter() {
1228    ///     println!("{:?}", item);
1229    /// }
1230    /// ```
1231    pub fn iter(&self) -> XsoVecIter<'_, T> {
1232        XsoVecIter {
1233            remaining: self.len(),
1234            outer: self.inner.values(),
1235            inner: None,
1236        }
1237    }
1238
1239    /// Iterate the items inside the container, mutably.
1240    ///
1241    /// This iterator (unlike the iterator returned by
1242    /// [`iter_typed_mut()`][`Self::iter_typed_mut`]) yields mutable
1243    /// references to **untyped** [`Xso<dyn Trait>`][`Xso`].
1244    ///
1245    /// Please note the information about iteration order of the `XsoVec`
1246    /// at [`XsoVec::iter`][`Self::iter`].
1247    pub fn iter_mut(&mut self) -> XsoVecIterMut<'_, T> {
1248        XsoVecIterMut {
1249            remaining: self.len(),
1250            outer: self.inner.values_mut(),
1251            inner: None,
1252        }
1253    }
1254}
1255
1256impl<T: ?Sized> IntoIterator for XsoVec<T> {
1257    type Item = Xso<T>;
1258    type IntoIter = XsoVecIntoIter<T>;
1259
1260    fn into_iter(self) -> Self::IntoIter {
1261        XsoVecIntoIter {
1262            remaining: self.len(),
1263            outer: self.inner.into_values(),
1264            inner: None,
1265        }
1266    }
1267}
1268
1269impl<'x, T: ?Sized> IntoIterator for &'x XsoVec<T> {
1270    type Item = &'x Xso<T>;
1271    type IntoIter = XsoVecIter<'x, T>;
1272
1273    fn into_iter(self) -> Self::IntoIter {
1274        self.iter()
1275    }
1276}
1277
1278impl<'x, T: ?Sized> IntoIterator for &'x mut XsoVec<T> {
1279    type Item = &'x mut Xso<T>;
1280    type IntoIter = XsoVecIterMut<'x, T>;
1281
1282    fn into_iter(self) -> Self::IntoIter {
1283        self.iter_mut()
1284    }
1285}
1286
1287impl<T: DynXso + ?Sized + 'static> Extend<Xso<T>> for XsoVec<T> {
1288    fn extend<I: IntoIterator<Item = Xso<T>>>(&mut self, iter: I) {
1289        for item in iter {
1290            self.ensure_vec_mut_for(item.inner_type_id()).push(item);
1291        }
1292    }
1293}
1294
1295/// Helper types for [`XsoVec`].
1296pub mod xso_vec {
1297    use super::*;
1298
1299    /// Iterator over the contents of an [`XsoVec`].
1300    pub struct XsoVecIter<'x, T: ?Sized> {
1301        pub(super) outer: btree_map::Values<'x, TypeId, Vec<Xso<T>>>,
1302        pub(super) inner: Option<slice::Iter<'x, Xso<T>>>,
1303        pub(super) remaining: usize,
1304    }
1305
1306    impl<'x, T: ?Sized> Iterator for XsoVecIter<'x, T> {
1307        type Item = &'x Xso<T>;
1308
1309        fn next(&mut self) -> Option<Self::Item> {
1310            loop {
1311                if let Some(inner) = self.inner.as_mut() {
1312                    if let Some(item) = inner.next() {
1313                        self.remaining = self.remaining.saturating_sub(1);
1314                        return Some(item);
1315                    }
1316                    // Inner is exhausted, so equivalent to None, fall through.
1317                }
1318                // The `?` in there is our exit condition.
1319                self.inner = Some(self.outer.next()?.deref().iter())
1320            }
1321        }
1322
1323        fn size_hint(&self) -> (usize, Option<usize>) {
1324            (self.remaining, Some(self.remaining))
1325        }
1326    }
1327
1328    /// Mutable iterator over the contents of an [`XsoVec`].
1329    pub struct XsoVecIterMut<'x, T: ?Sized> {
1330        pub(super) outer: btree_map::ValuesMut<'x, TypeId, Vec<Xso<T>>>,
1331        pub(super) inner: Option<slice::IterMut<'x, Xso<T>>>,
1332        pub(super) remaining: usize,
1333    }
1334
1335    impl<'x, T: ?Sized> Iterator for XsoVecIterMut<'x, T> {
1336        type Item = &'x mut Xso<T>;
1337
1338        fn next(&mut self) -> Option<Self::Item> {
1339            loop {
1340                if let Some(inner) = self.inner.as_mut() {
1341                    if let Some(item) = inner.next() {
1342                        self.remaining = self.remaining.saturating_sub(1);
1343                        return Some(item);
1344                    }
1345                    // Inner is exhausted, so equivalent to None, fall through.
1346                }
1347                // The `?` in there is our exit condition.
1348                self.inner = Some(self.outer.next()?.deref_mut().iter_mut())
1349            }
1350        }
1351
1352        fn size_hint(&self) -> (usize, Option<usize>) {
1353            (self.remaining, Some(self.remaining))
1354        }
1355    }
1356
1357    /// Iterator over the owned contents of an [`XsoVec`].
1358    pub struct XsoVecIntoIter<T: ?Sized> {
1359        pub(super) outer: btree_map::IntoValues<TypeId, Vec<Xso<T>>>,
1360        pub(super) inner: Option<vec::IntoIter<Xso<T>>>,
1361        pub(super) remaining: usize,
1362    }
1363
1364    impl<T: ?Sized> Iterator for XsoVecIntoIter<T> {
1365        type Item = Xso<T>;
1366
1367        fn next(&mut self) -> Option<Self::Item> {
1368            loop {
1369                if let Some(inner) = self.inner.as_mut() {
1370                    if let Some(item) = inner.next() {
1371                        self.remaining = self.remaining.saturating_sub(1);
1372                        return Some(item);
1373                    }
1374                    // Inner is exhausted, so equivalent to None, fall through.
1375                }
1376                // The `?` in there is our exit condition.
1377                self.inner = Some(self.outer.next()?.into_iter())
1378            }
1379        }
1380
1381        fn size_hint(&self) -> (usize, Option<usize>) {
1382            (self.remaining, Some(self.remaining))
1383        }
1384    }
1385}
1386
1387use xso_vec::*;
1388
1389#[cfg(test)]
1390mod tests {
1391    use super::*;
1392
1393    #[test]
1394    fn xso_inner_type_id_is_correct() {
1395        trait Trait: Any {}
1396        crate::derive_dyn_traits!(Trait use () = ());
1397        struct Foo;
1398        impl Trait for Foo {}
1399
1400        let ty_id = TypeId::of::<Foo>();
1401        let x: Xso<dyn Trait> = Xso::wrap(Foo);
1402        assert_eq!(x.inner_type_id(), ty_id);
1403    }
1404}