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 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};
  72#[cfg(feature = "std")]
  73use core::marker::PhantomData;
  74use core::{
  75    any::{Any, TypeId},
  76    fmt,
  77    ops::{Deref, DerefMut},
  78    slice,
  79};
  80#[cfg(feature = "std")]
  81use std::sync::Mutex;
  82
  83#[cfg(feature = "std")]
  84use crate::fromxml::XmlNameMatcher;
  85use crate::{
  86    asxml::AsXmlDyn,
  87    error::{Error, FromEventsError},
  88    AsXml, Context, FromEventsBuilder, FromXml, Item,
  89};
  90
  91/// # Generate `DynXso` and `MayContain` trait implementations
  92///
  93/// This macro generates trait [`DynXso`] and [`MayContain`] trait
  94/// implementations for a given trait. For more background information on when
  95/// that is a useful thing to have, see the [`dynxso`][`crate::dynxso`]
  96/// module.
  97///
  98/// ## Syntax
  99///
 100/// This macro can be called in two forms:
 101///
 102/// - `derive_dyn_traits!(Trait)` uses the default [`BuilderRegistry`]
 103///    as [`DynXso::Registry`] type and is only available if `xso` is built
 104///    with the `"std"` feature.
 105/// - `derive_dyn_traits!(Trait use Type = expr)` where `Type` is used as
 106///   [`DynXso::Registry`], initialized with `expr`. This form is available
 107///   for any set of crate features.
 108///
 109/// ## Example
 110///
 111/// When `std` is enabled, the simple syntax can be used.
 112#[cfg_attr(
 113    not(feature = "std"),
 114    doc = "Because the std feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
 115)]
 116#[cfg_attr(feature = "std", doc = "\n```\n")]
 117/// # use core::any::Any;
 118/// use xso::derive_dyn_traits;
 119/// trait Foo: Any {}
 120/// derive_dyn_traits!(Foo);
 121/// ```
 122///
 123/// Note that the trait this macro is called on **must** have a bound on
 124/// `Any`, otherwise the generated code will not compile:
 125///
 126#[cfg_attr(
 127    not(feature = "std"),
 128    doc = "Because the std feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
 129)]
 130#[cfg_attr(feature = "std", doc = "\n```compile_fail\n")]
 131/// use xso::derive_dyn_traits;
 132/// trait Foo {}
 133/// derive_dyn_traits!(Foo);
 134/// // ↑ will generate a bunch of errors about incompatible types
 135/// ```
 136///
 137/// If the `std` feature is not enabled or if you want to use another
 138/// `Registry` for whichever reason, the explicit form can be used:
 139///
 140/// ```
 141/// # use core::any::Any;
 142/// use xso::derive_dyn_traits;
 143/// trait Foo: Any {}
 144/// struct Registry { /* .. */ }
 145/// derive_dyn_traits!(Foo use Registry = Registry { /* .. */ });
 146/// ```
 147///
 148/// In that case, you should review the trait requirements of the
 149/// [`DynXso::Registry`] associated type.
 150#[macro_export]
 151macro_rules! derive_dyn_traits {
 152    ($trait:ident use $registry:ty = $reginit:expr) => {
 153        impl $crate::dynxso::DynXso for dyn $trait {
 154            type Registry = $registry;
 155
 156            fn registry() -> &'static Self::Registry {
 157                static DATA: $registry = $reginit;
 158                &DATA
 159            }
 160
 161            fn try_downcast<T: 'static>(
 162                self: $crate::exports::alloc::boxed::Box<Self>,
 163            ) -> Result<
 164                $crate::exports::alloc::boxed::Box<T>,
 165                $crate::exports::alloc::boxed::Box<Self>,
 166            >
 167            where
 168                Self: $crate::dynxso::MayContain<T>,
 169            {
 170                if (&*self as &dyn core::any::Any).is::<T>() {
 171                    match (self as $crate::exports::alloc::boxed::Box<dyn core::any::Any>)
 172                        .downcast()
 173                    {
 174                        Ok(v) => Ok(v),
 175                        Err(_) => unreachable!("Any::is and Any::downcast disagree!"),
 176                    }
 177                } else {
 178                    Err(self)
 179                }
 180            }
 181
 182            fn try_downcast_ref<T: 'static>(&self) -> Option<&T>
 183            where
 184                Self: $crate::dynxso::MayContain<T>,
 185            {
 186                (&*self as &dyn core::any::Any).downcast_ref()
 187            }
 188
 189            fn try_downcast_mut<T: 'static>(&mut self) -> Option<&mut T>
 190            where
 191                Self: $crate::dynxso::MayContain<T>,
 192            {
 193                (&mut *self as &mut dyn core::any::Any).downcast_mut()
 194            }
 195
 196            fn is<T: 'static>(&self) -> bool
 197            where
 198                Self: $crate::dynxso::MayContain<T>,
 199            {
 200                (&*self as &dyn core::any::Any).is::<T>()
 201            }
 202
 203            fn type_id(&self) -> core::any::TypeId {
 204                (&*self as &dyn core::any::Any).type_id()
 205            }
 206        }
 207
 208        impl<T: $trait> $crate::dynxso::MayContain<T> for dyn $trait {
 209            fn upcast_into(other: T) -> Box<Self> {
 210                Box::new(other)
 211            }
 212        }
 213    };
 214    ($trait:ident) => {
 215        $crate::_internal_derive_dyn_traits_std_only!($trait);
 216    };
 217}
 218
 219#[macro_export]
 220#[doc(hidden)]
 221#[cfg(feature = "std")]
 222macro_rules! _internal_derive_dyn_traits_std_only {
 223    ($trait:ident) => {
 224        $crate::derive_dyn_traits!($trait use $crate::dynxso::BuilderRegistry<dyn $trait> = $crate::dynxso::BuilderRegistry::new());
 225    };
 226}
 227
 228#[macro_export]
 229#[doc(hidden)]
 230#[cfg(not(feature = "std"))]
 231macro_rules! _internal_derive_dyn_traits_std_only {
 232    ($trait:ident) => {
 233        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)."));
 234    };
 235}
 236
 237#[cfg(feature = "std")]
 238type BuilderRegistryBuilder<T> = Box<
 239    dyn Fn(
 240            rxml::QName,
 241            rxml::AttrMap,
 242            &Context<'_>,
 243        ) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError>
 244        + Send
 245        + Sync
 246        + 'static,
 247>;
 248
 249#[cfg(feature = "std")]
 250struct BuilderRegistryEntry<T: ?Sized> {
 251    matcher: XmlNameMatcher<'static>,
 252    ty: TypeId,
 253    builder: BuilderRegistryBuilder<T>,
 254}
 255
 256#[cfg(feature = "std")]
 257impl<T: ?Sized> fmt::Debug for BuilderRegistryEntry<T> {
 258    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 259        f.debug_struct("BuilderRegistryEntry")
 260            .field("matcher", &self.matcher)
 261            .field("ty", &self.ty)
 262            .finish_non_exhaustive()
 263    }
 264}
 265
 266/// # Registry for type-erased [`FromXml`] builders which construct `T`
 267///
 268/// For general information on builder registries, see [`registry`].
 269///
 270/// ## Performance trade-offs
 271///
 272/// The implementation of the `BuilderRegistry` is optimized toward specific
 273/// usages. Other usages may see negative performance impacts. The following
 274/// assumptions are made:
 275///
 276/// - Types are added only once at startup and a matching
 277///   [`reserve`][`Self::reserve`] call is made beforehands.
 278/// - There are many different types.
 279/// - [`FromXml::xml_name_matcher`] returns a different value for most of the
 280///   types which are added.
 281///
 282/// The lookup algorithms in particular are geared toward the implications of
 283/// the last two assumptions and may be rather inefficient otherwise.
 284///
 285/// ## Example
 286///
 287/// This example illustrates the manual usage of the `BuilderRegistry`.
 288///
 289#[cfg_attr(
 290    not(feature = "macros"),
 291    doc = "Because the macros feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
 292)]
 293#[cfg_attr(feature = "macros", doc = "\n```\n")]
 294/// # 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};
 295/// #[derive(FromXml, Debug, PartialEq)]
 296/// #[xml(namespace = "urn:example", name = "foo")]
 297/// struct Foo;
 298///
 299/// #[derive(FromXml, Debug, PartialEq)]
 300/// #[xml(namespace = "urn:example", name = "bar")]
 301/// struct Bar;
 302///
 303/// #[derive(Debug, PartialEq)]
 304/// enum Either {
 305///    A(Foo),
 306///    B(Bar),
 307/// }
 308///
 309/// // BuilderRegistry::add::<U> requires that Either: MayContain<U>, in order
 310/// // to be able to wrap the U::Builder such that it outputs a Xso<Either>
 311/// // instead.
 312/// impl MayContain<Foo> for Either {
 313///     fn upcast_into(other: Foo) -> Box<Self> { Box::new(Self::A(other)) }
 314/// }
 315///
 316/// impl MayContain<Bar> for Either {
 317///     fn upcast_into(other: Bar) -> Box<Self> { Box::new(Self::B(other)) }
 318/// }
 319///
 320/// let registry = BuilderRegistry::<Either>::new();
 321/// registry.add::<Foo>();
 322/// registry.add::<Bar>();
 323///
 324/// let mut builder = registry.make_builder(
 325///     (
 326///         Namespace::from_str("urn:example"),
 327///         xml_ncname!("foo").to_owned(),   // <- Selects the Foo variant
 328///     ),
 329///     AttrMap::new(),
 330///     &Context::empty(),
 331/// ).unwrap();
 332/// let x = builder.feed(Event::EndElement(EventMetrics::zero()), &Context::empty()).unwrap().unwrap();
 333/// assert_eq!(Either::A(Foo), *x);
 334///
 335/// let mut builder = registry.make_builder(
 336///     (
 337///         Namespace::from_str("urn:example"),
 338///         xml_ncname!("bar").to_owned(),   // <- Selects the Bar variant
 339///     ),
 340///     AttrMap::new(),
 341///     &Context::empty(),
 342/// ).unwrap();
 343/// let x = builder.feed(Event::EndElement(EventMetrics::zero()), &Context::empty()).unwrap().unwrap();
 344/// assert_eq!(Either::B(Bar), *x);
 345/// ```
 346///
 347/// Implementing `FromXml` on the `Either` type in the above example would
 348/// be trivial and look like this:
 349///
 350#[cfg_attr(
 351    not(feature = "macros"),
 352    doc = "Because the macros feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
 353)]
 354#[cfg_attr(feature = "macros", doc = "\n```\n")]
 355/// # use xso::{dynxso::{BuilderRegistry, MayContain, registry::{DynXsoRegistryAdd, DynXsoRegistryLookup}}, FromXml, from_bytes, exports::rxml::{Namespace, AttrMap, QName, Event, parser::EventMetrics}, Context, FromEventsBuilder, error::FromEventsError};
 356/// # #[derive(FromXml, Debug, PartialEq)]
 357/// # #[xml(namespace = "urn:example", name = "foo")]
 358/// # struct Foo;
 359/// #
 360/// # #[derive(FromXml, Debug, PartialEq)]
 361/// # #[xml(namespace = "urn:example", name = "bar")]
 362/// # struct Bar;
 363/// #
 364/// # #[derive(Debug, PartialEq)]
 365/// # enum Either {
 366/// #    A(Foo),
 367/// #    B(Bar),
 368/// # }
 369/// #
 370/// # impl MayContain<Foo> for Either {
 371/// #     fn upcast_into(other: Foo) -> Box<Self> { Box::new(Self::A(other)) }
 372/// # }
 373/// #
 374/// # impl MayContain<Bar> for Either {
 375/// #     fn upcast_into(other: Bar) -> Box<Self> { Box::new(Self::B(other)) }
 376/// # }
 377/// #
 378/// // ... code from the previous example ...
 379/// use xso::dynxso::UnboxBuilder;
 380/// // In order to be able to use the registry from the FromXml implementation,
 381/// // it must be a static (as opposed to a local variable as in the previous
 382/// // example).
 383/// static REGISTRY: BuilderRegistry<Either> = BuilderRegistry::new();
 384/// REGISTRY.add::<Foo>();
 385/// REGISTRY.add::<Bar>();
 386///
 387/// impl FromXml for Either {
 388///     type Builder = UnboxBuilder<Box<dyn FromEventsBuilder<Output = Box<Either>>>>;
 389///
 390///     fn from_events(name: QName, attrs: AttrMap, ctx: &Context<'_>) -> Result<Self::Builder, FromEventsError> {
 391///         REGISTRY.make_builder(name, attrs, ctx).map(UnboxBuilder::wrap)
 392///     }
 393/// }
 394///
 395/// assert_eq!(
 396///     Either::A(Foo),
 397///     from_bytes("<foo xmlns='urn:example'/>".as_bytes()).unwrap(),
 398/// );
 399///
 400/// assert_eq!(
 401///     Either::B(Bar),
 402///     from_bytes("<bar xmlns='urn:example'/>".as_bytes()).unwrap(),
 403/// );
 404/// ```
 405#[derive(Debug)]
 406#[cfg(feature = "std")]
 407pub struct BuilderRegistry<T: ?Sized> {
 408    inner: Mutex<Vec<BuilderRegistryEntry<T>>>,
 409}
 410
 411#[cfg(feature = "std")]
 412impl<T: ?Sized + 'static> BuilderRegistry<T> {
 413    /// Create an empty registry.
 414    pub const fn new() -> Self {
 415        Self {
 416            inner: Mutex::new(Vec::new()),
 417        }
 418    }
 419
 420    fn insert(
 421        &self,
 422        matcher: XmlNameMatcher<'static>,
 423        type_id: TypeId,
 424        builder: BuilderRegistryBuilder<T>,
 425    ) {
 426        let mut registry = self.inner.lock().unwrap();
 427        let start_scan_at = registry.partition_point(|entry| entry.matcher < matcher);
 428        let insert_at = 'outer: {
 429            let mut i = start_scan_at;
 430            while i < registry.len() {
 431                let entry = &registry[i];
 432                if entry.matcher == matcher {
 433                    if entry.ty == type_id {
 434                        // Already inserted.
 435                        return;
 436                    }
 437                    // Still entries with the same matcher -> continue.
 438                    i += 1;
 439                    continue;
 440                }
 441
 442                // Found insertion point;
 443                break 'outer i;
 444            }
 445
 446            // The entire (rest of the) registry contains items matching
 447            // `matcher`, but none matching the given `type_id` -> insert at
 448            // the end.
 449            registry.len()
 450        };
 451
 452        registry.insert(
 453            insert_at,
 454            BuilderRegistryEntry {
 455                matcher,
 456                ty: type_id,
 457                builder,
 458            },
 459        );
 460    }
 461
 462    /// Reserve space for at least `n` additional types.
 463    pub fn reserve(&self, n: usize) {
 464        self.inner.lock().unwrap().reserve(n);
 465    }
 466
 467    fn try_build(
 468        inner: &mut Vec<BuilderRegistryEntry<T>>,
 469        mut name: rxml::QName,
 470        mut attrs: rxml::AttrMap,
 471        ctx: &Context<'_>,
 472        matcher_builder: impl for<'x> FnOnce(&'x rxml::QName) -> XmlNameMatcher<'x>,
 473    ) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError> {
 474        let matcher = matcher_builder(&name);
 475        let start_scan_at = inner.partition_point(|entry| entry.matcher < matcher);
 476
 477        for entry in &inner[start_scan_at..] {
 478            if !entry.matcher.matches(&name) {
 479                return Err(FromEventsError::Mismatch { name, attrs });
 480            }
 481
 482            match (entry.builder)(name, attrs, ctx) {
 483                Ok(v) => return Ok(v),
 484                Err(FromEventsError::Invalid(e)) => return Err(FromEventsError::Invalid(e)),
 485                Err(FromEventsError::Mismatch {
 486                    name: new_name,
 487                    attrs: new_attrs,
 488                }) => {
 489                    name = new_name;
 490                    attrs = new_attrs;
 491                }
 492            }
 493        }
 494
 495        Err(FromEventsError::Mismatch { name, attrs })
 496    }
 497}
 498
 499#[cfg(feature = "std")]
 500impl<T: ?Sized + 'static> DynXsoRegistryAdd<T> for BuilderRegistry<T> {
 501    fn add<U: Any + FromXml>(&self)
 502    where
 503        T: MayContain<U>,
 504    {
 505        struct Wrapper<B, X: ?Sized> {
 506            inner: B,
 507            output: PhantomData<X>,
 508        }
 509
 510        impl<X: ?Sized, O, B: FromEventsBuilder<Output = O>> FromEventsBuilder for Wrapper<B, X>
 511        where
 512            X: MayContain<O>,
 513        {
 514            type Output = Box<X>;
 515
 516            fn feed(
 517                &mut self,
 518                ev: rxml::Event,
 519                ctx: &Context<'_>,
 520            ) -> Result<Option<Self::Output>, Error> {
 521                self.inner
 522                    .feed(ev, ctx)
 523                    .map(|x| x.map(|x| <X as MayContain<O>>::upcast_into(x)))
 524            }
 525        }
 526
 527        self.insert(
 528            U::xml_name_matcher(),
 529            TypeId::of::<U>(),
 530            Box::new(|name, attrs, ctx| {
 531                U::from_events(name, attrs, ctx).map(|builder| {
 532                    Box::new(Wrapper {
 533                        inner: builder,
 534                        output: PhantomData,
 535                    }) as Box<dyn FromEventsBuilder<Output = Box<T>>>
 536                })
 537            }),
 538        )
 539    }
 540}
 541
 542#[cfg(feature = "std")]
 543impl<T: ?Sized + 'static> DynXsoRegistryLookup<T> for BuilderRegistry<T> {
 544    fn make_builder(
 545        &self,
 546        name: rxml::QName,
 547        attrs: rxml::AttrMap,
 548        ctx: &Context<'_>,
 549    ) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError> {
 550        let mut inner = self.inner.lock().unwrap();
 551        let (name, attrs) = match Self::try_build(&mut *inner, name, attrs, ctx, |qname| {
 552            XmlNameMatcher::Specific(qname.0.as_str(), qname.1.as_str())
 553        }) {
 554            Ok(v) => return Ok(v),
 555            Err(FromEventsError::Invalid(e)) => return Err(FromEventsError::Invalid(e)),
 556            Err(FromEventsError::Mismatch { name, attrs }) => (name, attrs),
 557        };
 558
 559        let (name, attrs) = match Self::try_build(&mut *inner, name, attrs, ctx, |qname| {
 560            XmlNameMatcher::InNamespace(qname.0.as_str())
 561        }) {
 562            Ok(v) => return Ok(v),
 563            Err(FromEventsError::Invalid(e)) => return Err(FromEventsError::Invalid(e)),
 564            Err(FromEventsError::Mismatch { name, attrs }) => (name, attrs),
 565        };
 566
 567        Self::try_build(&mut *inner, name, attrs, ctx, |_| XmlNameMatcher::Any)
 568    }
 569}
 570
 571/// # Helper traits for dynamic XSO builder registries.
 572///
 573/// Builder registries hold type-erased [`FromXml::from_events`]
 574/// implementations. Registries can be used to dynamically dispatch to a set
 575/// of `FromXml` implementations which is not known at compile time.
 576///
 577/// Under the hood, they are used by the `FromXml` implementation on
 578/// [`Xso<T>`][`Xso`], via the [`DynXso::Registry`] type.
 579///
 580/// Note that registries generally do not allow to add arbitrary builders. All
 581/// builders must originate in a [`FromXml`] implementation and their output
 582/// must be convertible to the specific type the registry is defined for.
 583///
 584/// The default implementation is [`BuilderRegistry`], which is only available
 585/// if `xso` is built with the `"std"` feature due to the inherent need for a
 586/// `Mutex`.
 587pub mod registry {
 588    use super::*;
 589
 590    /// Trait for a builder registry supports constructing elements.
 591    pub trait DynXsoRegistryLookup<T: ?Sized> {
 592        /// Make a builder for the given element header.
 593        ///
 594        /// This tries all applicable `FromXml` implementations which have
 595        /// previously been added via [`add`][`DynXsoRegistryAdd::add`] in
 596        /// unspecified order. The first implementation to either fail or
 597        /// succeed at constructing a builder determines the result.
 598        /// Implementations which return a
 599        /// [`FromEventsError::Mismatch`][`crate::error::FromEventsError::Mismatch`]
 600        /// are ignored.
 601        ///
 602        /// If all applicable implementations return `Mismatch`, this function
 603        /// returns `Mismatch`, too.
 604        fn make_builder(
 605            &self,
 606            name: rxml::QName,
 607            attrs: rxml::AttrMap,
 608            ctx: &Context<'_>,
 609        ) -> Result<Box<dyn FromEventsBuilder<Output = Box<T>>>, FromEventsError>;
 610    }
 611
 612    /// Trait for a builder registry supports registering new builders at
 613    /// runtime.
 614    pub trait DynXsoRegistryAdd<T: ?Sized> {
 615        /// Add a new builder to the registry.
 616        ///
 617        /// This allows to add any `FromXml` implementation whose output can be
 618        /// converted to `T`.
 619        fn add<U: Any + FromXml>(&self)
 620        where
 621            T: MayContain<U>;
 622    }
 623}
 624
 625use registry::*;
 626
 627/// # Dynamic XSO type
 628///
 629/// This trait provides the infrastructure for dynamic XSO types. In
 630/// particular, it provides:
 631///
 632/// - Access to a [`BuilderRegistry`] which allows constructing an instance of
 633///   the dynamic XSO type from XML.
 634/// - Downcasts to specific types.
 635///
 636/// Like [`MayContain`], it is typically implemented on `dyn Trait` for some
 637/// `Trait` and it is best generated using
 638/// [`derive_dyn_traits`][`crate::derive_dyn_traits`].
 639///
 640/// This trait explicitly provides the methods provided by [`Any`]. The reason
 641/// for this duplication is that with `DynXso` being intended to be
 642/// implemented on `dyn Trait`, code using this trait cannot cast the value
 643/// to `dyn Any` to access the `downcast`-related methods (`type_id` would,
 644/// in fact, work if `DynXso` had a bound on `Any`, but not the downcasts).
 645///
 646/// *Hint*: It should not be necessary for user code to directly interact
 647/// with this trait.
 648pub trait DynXso: 'static {
 649    /// Builder registry type for this dynamic type.
 650    ///
 651    /// The `Registry` type *should* implement the following traits:
 652    ///
 653    /// - [`DynXsoRegistryAdd`] is required to make
 654    ///   [`Xso::<Self>::register_type()`][`Xso::register_type`] available.
 655    /// - [`DynXsoRegistryLookup`] is required to make [`FromXml`] available
 656    ///   on [`Xso<Self>`][`Xso`] (and, by extension, on
 657    ///   [`XsoVec<Self>`][`XsoVec`]).
 658    ///
 659    /// However, any type with static lifetime can be used, even without the
 660    /// trait implementations above, if the limitations are acceptable.
 661    type Registry: 'static;
 662
 663    /// Return the builder registry for this dynamic type.
 664    ///
 665    /// See [`Registry`][`Self::Registry`] for details.
 666    fn registry() -> &'static Self::Registry;
 667
 668    /// Try to downcast a boxed dynamic XSO to a specific type.
 669    ///
 670    /// If `self` contains a `T` (and thus, the downcast succeeds), `Ok(_)`
 671    /// is returned. Otherwise, `Err(self)` is returned, allowing to chain
 672    /// this function with other downcast attempts.
 673    ///
 674    /// This is similar to `downcast` on [`dyn Any`][`core::any::Any`].
 675    fn try_downcast<T: 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>>
 676    where
 677        Self: MayContain<T>;
 678
 679    /// Try to downcast a dynamic XSO to a reference to a specific type.
 680    ///
 681    /// If `self` contains a `T` (and thus, the downcast succeeds), `Some(_)`
 682    /// is returned. Otherwise, `None`.
 683    ///
 684    /// This is similar to `downcast_ref` on [`dyn Any`][`core::any::Any`].
 685    fn try_downcast_ref<T: 'static>(&self) -> Option<&T>
 686    where
 687        Self: MayContain<T>;
 688
 689    /// Try to downcast a dynamic XSO to a mutable reference to a specific
 690    /// type.
 691    ///
 692    /// If `self` contains a `T` (and thus, the downcast succeeds), `Some(_)`
 693    /// is returned. Otherwise, `None`.
 694    ///
 695    /// This is similar to `downcast_mut` on [`dyn Any`][`core::any::Any`].
 696    fn try_downcast_mut<T: 'static>(&mut self) -> Option<&mut T>
 697    where
 698        Self: MayContain<T>;
 699
 700    /// Return true if `self` contains a `T`.
 701    ///
 702    /// This is similar to `is` on [`dyn Any`][`core::any::Any`].
 703    fn is<T: 'static>(&self) -> bool
 704    where
 705        Self: MayContain<T>;
 706
 707    /// Return the [`TypeId`] of `self`.
 708    ///
 709    /// This is similar to `type_id` on [`dyn Any`][`core::any::Any`].
 710    fn type_id(&self) -> TypeId;
 711}
 712
 713/// # Declare that `T` may be held by `Box<Self>`
 714///
 715/// This trait is used to constrain which types can be put in
 716/// [`Xso<Self>`][`Xso`]. It is typically implemented on `dyn Trait` for all
 717/// `T: Trait`.
 718///
 719/// To automatically generate suitable implementations of this trait, see
 720/// [`derive_dyn_traits`][`crate::derive_dyn_traits`].
 721///
 722/// Implementation-wise, this trait is very similar to `Box<Self>: From<T>`.
 723/// However, `From` is also used in many different circumstances and it cannot
 724/// be suitably overloaded on `Box<_>`, so a new trait was introduced for this
 725/// particular purpose.
 726pub trait MayContain<T> {
 727    /// Convert a value of `T` into `Box<Self>`.
 728    fn upcast_into(other: T) -> Box<Self>;
 729}
 730
 731/// # Dynamic XSO container
 732///
 733/// This container is very similar to `Box<_>`, but geared specifically toward
 734/// the use with `T` being a `dyn Trait`. It also implements [`FromXml`]
 735/// (unconditionally) and [`AsXml`] if `T` implements [`AsXmlDyn`].
 736///
 737/// In order to provide these features, `T` must implement [`DynXso`] and
 738/// [`MayContain`]. Implementations for these traits can be generated using
 739/// [`derive_dyn_traits`][`crate::derive_dyn_traits`].
 740///
 741/// Most methods on `Xso<dyn Trait>` which take type parameters are only
 742/// available for types `U` implementing `Trait` (or, more precisely, where
 743/// `dyn Trait` implements `MayContain<U>`).
 744#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
 745#[repr(transparent)]
 746pub struct Xso<T: ?Sized> {
 747    inner: Box<T>,
 748}
 749
 750impl<T: ?Sized> Deref for Xso<T> {
 751    type Target = T;
 752
 753    fn deref(&self) -> &Self::Target {
 754        self.inner.deref()
 755    }
 756}
 757
 758impl<T: ?Sized> DerefMut for Xso<T> {
 759    fn deref_mut(&mut self) -> &mut Self::Target {
 760        self.inner.deref_mut()
 761    }
 762}
 763
 764impl<T: DynXso + ?Sized> fmt::Debug for Xso<T> {
 765    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 766        f.debug_struct("Xso")
 767            .field("inner", &self.inner_type_id())
 768            .finish()
 769    }
 770}
 771
 772impl<T: ?Sized> Xso<T> {
 773    /// Wrap a value into a `Xso<dyn Trait>`.
 774    ///
 775    /// ```
 776    /// # use core::any::Any;
 777    /// # use xso::{dynxso::Xso, derive_dyn_traits};
 778    /// trait Trait: Any {}
 779    #[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
 780    #[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
 781    ///
 782    /// struct Foo;
 783    /// impl Trait for Foo {}
 784    ///
 785    /// let x: Xso<dyn Trait> = Xso::wrap(Foo);
 786    /// ```
 787    pub fn wrap<U: 'static>(value: U) -> Self
 788    where
 789        T: MayContain<U>,
 790    {
 791        Self {
 792            inner: T::upcast_into(value),
 793        }
 794    }
 795
 796    /// Convert `Xso<T>` into `Box<T>`.
 797    ///
 798    /// ```
 799    /// # use core::any::Any;
 800    /// # use xso::{dynxso::Xso, derive_dyn_traits};
 801    /// trait Trait: Any {}
 802    #[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
 803    #[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
 804    ///
 805    /// struct Foo;
 806    /// impl Trait for Foo {}
 807    ///
 808    /// let x: Xso<dyn Trait> = Xso::wrap(Foo);
 809    /// let x: Box<dyn Trait> = x.into_boxed();
 810    /// ```
 811    pub fn into_boxed(self) -> Box<T> {
 812        self.inner
 813    }
 814}
 815
 816impl<T: DynXso + ?Sized + 'static> Xso<T> {
 817    /// Downcast `self` to `Box<U>`.
 818    ///
 819    /// If the downcast fails, `self` is returned without change.
 820    ///
 821    /// ```
 822    /// # use core::any::Any;
 823    /// # use xso::{dynxso::Xso, derive_dyn_traits};
 824    /// trait Trait: Any {}
 825    #[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
 826    #[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
 827    ///
 828    /// struct Foo;
 829    /// impl Trait for Foo {}
 830    ///
 831    /// struct Bar;
 832    /// impl Trait for Bar {}
 833    ///
 834    /// let x: Xso<dyn Trait> = Xso::wrap(Foo);
 835    /// // Does not contain a Bar, so downcast fails.
 836    /// let x: Xso<dyn Trait> = x.downcast::<Bar>().err().unwrap();
 837    /// // *Does* contain a Foo, so downcast succeeds.
 838    /// let f: Foo = *x.downcast().unwrap();
 839    /// ```
 840    pub fn downcast<U: 'static>(self) -> Result<Box<U>, Self>
 841    where
 842        T: MayContain<U>,
 843    {
 844        match self.inner.try_downcast() {
 845            Ok(v) => Ok(v),
 846            Err(inner) => Err(Self { inner }),
 847        }
 848    }
 849
 850    fn force_downcast<U: 'static>(self) -> Box<U>
 851    where
 852        T: MayContain<U>,
 853    {
 854        match self.downcast::<U>() {
 855            Ok(v) => v,
 856            Err(v) => panic!(
 857                "force_downcast called on mismatching types: requested {:?} ({}) != actual {:?}",
 858                TypeId::of::<U>(),
 859                core::any::type_name::<U>(),
 860                v.inner_type_id()
 861            ),
 862        }
 863    }
 864
 865    /// Downcast `&self` to `&U`.
 866    ///
 867    /// ```
 868    /// # use core::any::Any;
 869    /// # use xso::{dynxso::Xso, derive_dyn_traits};
 870    /// trait Trait: Any {}
 871    #[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
 872    #[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
 873    ///
 874    /// struct Foo;
 875    /// impl Trait for Foo {}
 876    ///
 877    /// struct Bar;
 878    /// impl Trait for Bar {}
 879    ///
 880    /// let x: Xso<dyn Trait> = Xso::wrap(Foo);
 881    /// // Does not contain a Bar, so downcast fails.
 882    /// assert!(x.downcast_ref::<Bar>().is_none());
 883    /// // *Does* contain a Foo, so downcast succeeds.
 884    /// let f: &Foo = x.downcast_ref().unwrap();
 885    /// ```
 886    pub fn downcast_ref<U: 'static>(&self) -> Option<&U>
 887    where
 888        T: MayContain<U>,
 889    {
 890        self.inner.try_downcast_ref()
 891    }
 892
 893    /// Downcast `&mut self` to `&mut U`.
 894    ///
 895    /// ```
 896    /// # use core::any::Any;
 897    /// # use xso::{dynxso::Xso, derive_dyn_traits};
 898    /// trait Trait: Any {}
 899    #[cfg_attr(feature = "std", doc = "derive_dyn_traits!(Trait);")]
 900    #[cfg_attr(not(feature = "std"), doc = "derive_dyn_traits!(Trait use () = ());")]
 901    ///
 902    /// struct Foo;
 903    /// impl Trait for Foo {}
 904    ///
 905    /// struct Bar;
 906    /// impl Trait for Bar {}
 907    ///
 908    /// let mut x: Xso<dyn Trait> = Xso::wrap(Foo);
 909    /// // Does not contain a Bar, so downcast fails.
 910    /// assert!(x.downcast_mut::<Bar>().is_none());
 911    /// // *Does* contain a Foo, so downcast succeeds.
 912    /// let f: &mut Foo = x.downcast_mut().unwrap();
 913    /// ```
 914    pub fn downcast_mut<U: 'static>(&mut self) -> Option<&mut U>
 915    where
 916        T: MayContain<U>,
 917    {
 918        self.inner.try_downcast_mut()
 919    }
 920
 921    fn inner_type_id(&self) -> TypeId {
 922        DynXso::type_id(&*self.inner)
 923    }
 924}
 925
 926impl<R: DynXsoRegistryAdd<T> + 'static, T: DynXso<Registry = R> + ?Sized + 'static> Xso<T> {
 927    /// Register a new type to be constructible.
 928    ///
 929    /// Only types registered through this function can be parsed from XML via
 930    /// the [`FromXml`] implementation on `Xso<T>`. See
 931    /// [`dynxso`][`crate::dynxso`] for details.
 932    ///
 933    #[cfg_attr(
 934        not(all(feature = "macros", feature = "std")),
 935        doc = "Because the macros and std features were not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
 936    )]
 937    #[cfg_attr(all(feature = "macros", feature = "std"), doc = "\n```\n")]
 938    /// # use core::any::Any;
 939    /// # use xso::{dynxso::Xso, derive_dyn_traits, from_bytes, FromXml};
 940    /// trait Trait: Any {}
 941    /// derive_dyn_traits!(Trait);
 942    ///
 943    /// #[derive(FromXml, PartialEq, Debug)]
 944    /// #[xml(namespace = "urn:example", name = "foo")]
 945    /// struct Foo;
 946    /// impl Trait for Foo {}
 947    ///
 948    /// // Parsing fails, because register_type() has not been called for
 949    /// // Foo:
 950    /// assert!(from_bytes::<Xso<dyn Trait>>("<foo xmlns='urn:example'/>".as_bytes()).is_err());
 951    ///
 952    /// Xso::<dyn Trait>::register_type::<Foo>();
 953    /// // After registering Foo with Xso<dyn Trait>, parsing succeeds and
 954    /// // we can downcast to Foo:
 955    /// let x: Xso<dyn Trait> = from_bytes("<foo xmlns='urn:example'/>".as_bytes()).unwrap();
 956    /// assert_eq!(Foo, *x.downcast().unwrap());
 957    /// ```
 958    pub fn register_type<U: FromXml + 'static>()
 959    where
 960        T: MayContain<U>,
 961    {
 962        T::registry().add::<U>()
 963    }
 964}
 965
 966/// Wrapper around a `FromEventsBuilder` to convert a `Box<T>` output to a
 967/// `Xso<T>` output.
 968///
 969/// Not constructible by users, only for internal use.
 970pub struct DynBuilder<B> {
 971    inner: B,
 972}
 973
 974impl<T: DynXso + ?Sized + 'static, B: FromEventsBuilder<Output = Box<T>>> FromEventsBuilder
 975    for DynBuilder<B>
 976{
 977    type Output = Xso<T>;
 978
 979    fn feed(&mut self, ev: rxml::Event, ctx: &Context) -> Result<Option<Self::Output>, Error> {
 980        self.inner
 981            .feed(ev, ctx)
 982            .map(|x| x.map(|inner| Xso { inner }))
 983    }
 984}
 985
 986/// Wrapper around a `FromEventsBuilder` to convert a `Box<T>` output to a
 987/// `T` output.
 988pub struct UnboxBuilder<T> {
 989    inner: T,
 990}
 991
 992impl<O, T: FromEventsBuilder<Output = Box<O>>> UnboxBuilder<T> {
 993    /// Wrap a `FromEventsBuilder` which generates `Box<O>`.
 994    pub fn wrap(inner: T) -> Self {
 995        Self { inner }
 996    }
 997}
 998
 999impl<O, T: FromEventsBuilder<Output = Box<O>>> FromEventsBuilder for UnboxBuilder<T> {
1000    type Output = O;
1001
1002    fn feed(&mut self, ev: rxml::Event, ctx: &Context) -> Result<Option<Self::Output>, Error> {
1003        self.inner.feed(ev, ctx).map(|x| x.map(|inner| *inner))
1004    }
1005}
1006
1007impl<R: DynXsoRegistryLookup<T> + 'static, T: DynXso<Registry = R> + ?Sized + 'static> FromXml
1008    for Xso<T>
1009{
1010    type Builder = DynBuilder<Box<dyn FromEventsBuilder<Output = Box<T>>>>;
1011
1012    fn from_events(
1013        name: rxml::QName,
1014        attrs: rxml::AttrMap,
1015        ctx: &Context<'_>,
1016    ) -> Result<Self::Builder, FromEventsError> {
1017        T::registry()
1018            .make_builder(name, attrs, ctx)
1019            .map(|inner| DynBuilder { inner })
1020    }
1021}
1022
1023impl<T: DynXso + AsXmlDyn + ?Sized + 'static> AsXml for Xso<T> {
1024    type ItemIter<'x> = Box<dyn Iterator<Item = Result<Item<'x>, Error>> + 'x>;
1025
1026    fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
1027        self.inner.as_xml_dyn_iter()
1028    }
1029
1030    fn as_xml_dyn_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
1031        self.inner.as_xml_dyn_iter()
1032    }
1033}
1034
1035/// Error type for retrieving a single item from `XsoVec`.
1036#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1037pub enum TakeOneError {
1038    /// More than one item was found.
1039    MultipleEntries,
1040}
1041
1042impl fmt::Display for TakeOneError {
1043    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1044        match self {
1045            Self::MultipleEntries => f.write_str("multiple entries found"),
1046        }
1047    }
1048}
1049
1050/// # Container for dynamically-typed XSOs optimized for type-keyed access
1051///
1052/// This container holds dynamically typed XSOs (see
1053/// [`Xso<dyn Trait>`][`Xso`]). It allows efficient access to its contents
1054/// based on the actual type.
1055///
1056/// Like `Xso<dyn Trait>` itself, `XsoVec<dyn Trait>` requires that
1057/// `MayContain` is implemented by `dyn Trait` for all items which are added
1058/// to the container. This is automatically the case for all `T: Trait`
1059/// if [`derive_dyn_traits`][`crate::derive_dyn_traits`] has been used on
1060/// `Trait`.
1061///
1062/// Note that `XsoVec` has a non-obvious iteration order, which is described
1063/// in [`XsoVec::iter()`][`Self::iter`].
1064pub struct XsoVec<T: ?Sized> {
1065    inner: BTreeMap<TypeId, Vec<Xso<T>>>,
1066}
1067
1068impl<T: ?Sized> fmt::Debug for XsoVec<T> {
1069    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1070        write!(
1071            f,
1072            "XsoVec[{} types, {} items]",
1073            self.inner.len(),
1074            self.len()
1075        )
1076    }
1077}
1078
1079impl<T: ?Sized> Default for XsoVec<T> {
1080    fn default() -> Self {
1081        Self {
1082            inner: BTreeMap::default(),
1083        }
1084    }
1085}
1086
1087impl<T: DynXso + ?Sized + 'static> XsoVec<T> {
1088    /// Construct a new, empty `XsoVec`.
1089    ///
1090    /// ```
1091    #[doc = include_str!("xso_vec_test_prelude.rs")]
1092    /// let mut vec = XsoVec::<dyn Trait>::new();
1093    /// ```
1094    pub const fn new() -> Self {
1095        Self {
1096            inner: BTreeMap::new(),
1097        }
1098    }
1099
1100    /// Return a reference to the first item of type `U`.
1101    ///
1102    /// If the container does not hold any item of type `U`, return `None`.
1103    ///
1104    /// ```
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(u16);
1112    /// impl Trait for Bar {}
1113    ///
1114    /// #[derive(PartialEq, Debug)]
1115    /// struct Baz(u32);
1116    /// impl Trait for Baz {}
1117    ///
1118    /// let mut vec = XsoVec::<dyn Trait>::new();
1119    /// vec.push(Bar(1));
1120    /// vec.push(Foo(2));
1121    /// vec.push(Foo(1));
1122    /// assert_eq!(vec.get_first::<Foo>(), Some(&Foo(2)));
1123    /// assert_eq!(vec.get_first::<Bar>(), Some(&Bar(1)));
1124    /// assert_eq!(vec.get_first::<Baz>(), None);
1125    ///
1126    /// ```
1127    pub fn get_first<U: 'static>(&self) -> Option<&U>
1128    where
1129        T: MayContain<U>,
1130    {
1131        self.iter_typed::<U>().next()
1132    }
1133
1134    /// Return a mutable reference to the first item of type `U`.
1135    ///
1136    /// If the container does not hold any item of type `U`, return `None`.
1137    ///
1138    /// ```
1139    #[doc = include_str!("xso_vec_test_prelude.rs")]
1140    /// #[derive(PartialEq, Debug)]
1141    /// struct Foo(u8);
1142    /// impl Trait for Foo {}
1143    ///
1144    /// let mut vec = XsoVec::<dyn Trait>::new();
1145    /// vec.push(Foo(1));
1146    /// vec.get_first_mut::<Foo>().unwrap().0 = 2;
1147    /// assert_eq!(vec.get_first::<Foo>(), Some(&Foo(2)));
1148    /// ```
1149    pub fn get_first_mut<U: 'static>(&mut self) -> Option<&mut U>
1150    where
1151        T: MayContain<U>,
1152    {
1153        self.iter_typed_mut::<U>().next()
1154    }
1155
1156    /// Take and return exactly one item of type `U`.
1157    ///
1158    /// If no item of type `U` is present in the container, return Ok(None).
1159    /// If more than one item of type `U` is present in the container,
1160    /// return an error.
1161    /// ```
1162    #[doc = include_str!("xso_vec_test_prelude.rs")]
1163    /// #[derive(PartialEq, Debug)]
1164    /// struct Foo(u8);
1165    /// impl Trait for Foo {}
1166    ///
1167    /// #[derive(PartialEq, Debug)]
1168    /// struct Bar(u16);
1169    /// impl Trait for Bar {}
1170    ///
1171    /// #[derive(PartialEq, Debug)]
1172    /// struct Baz(u32);
1173    /// impl Trait for Baz {}
1174    ///
1175    /// let mut vec = XsoVec::<dyn Trait>::new();
1176    /// vec.push(Bar(1));
1177    /// vec.push(Foo(2));
1178    /// vec.push(Foo(1));
1179    /// assert_eq!(vec.take_one::<Foo>(), Err(TakeOneError::MultipleEntries));
1180    /// assert_eq!(*vec.take_one::<Bar>().unwrap().unwrap(), Bar(1));
1181    /// assert_eq!(vec.take_one::<Bar>(), Ok(None));
1182    /// assert_eq!(vec.take_one::<Baz>(), Ok(None));
1183    /// ```
1184    pub fn take_one<U: 'static>(&mut self) -> Result<Option<Box<U>>, TakeOneError>
1185    where
1186        T: MayContain<U>,
1187    {
1188        let source = match self.inner.get_mut(&TypeId::of::<U>()) {
1189            Some(v) => v,
1190            None => return Ok(None),
1191        };
1192        if source.len() > 1 {
1193            return Err(TakeOneError::MultipleEntries);
1194        }
1195        Ok(source.pop().map(Xso::force_downcast))
1196    }
1197
1198    /// Take and return the first item of type `U`.
1199    ///
1200    /// If no item of type `U` is present in the container, return None.
1201    /// ```
1202    #[doc = include_str!("xso_vec_test_prelude.rs")]
1203    /// #[derive(PartialEq, Debug)]
1204    /// struct Foo(u8);
1205    /// impl Trait for Foo {}
1206    ///
1207    /// #[derive(PartialEq, Debug)]
1208    /// struct Bar(u16);
1209    /// impl Trait for Bar {}
1210    ///
1211    /// #[derive(PartialEq, Debug)]
1212    /// struct Baz(u32);
1213    /// impl Trait for Baz {}
1214    ///
1215    /// let mut vec = XsoVec::<dyn Trait>::new();
1216    /// vec.push(Bar(1));
1217    /// vec.push(Foo(2));
1218    /// vec.push(Foo(1));
1219    /// assert_eq!(*vec.take_first::<Foo>().unwrap(), Foo(2));
1220    /// assert_eq!(*vec.take_first::<Foo>().unwrap(), Foo(1));
1221    /// assert_eq!(*vec.take_first::<Bar>().unwrap(), Bar(1));
1222    /// assert_eq!(vec.take_first::<Bar>(), None);
1223    /// assert_eq!(vec.take_first::<Baz>(), None);
1224    /// ```
1225    pub fn take_first<U: 'static>(&mut self) -> Option<Box<U>>
1226    where
1227        T: MayContain<U>,
1228    {
1229        let source = self.inner.get_mut(&TypeId::of::<U>())?;
1230        if source.len() == 0 {
1231            return None;
1232        }
1233        Some(source.remove(0).force_downcast())
1234    }
1235
1236    /// Take and return the last item of type `U`.
1237    ///
1238    /// If no item of type `U` is present in the container, return None.
1239    /// ```
1240    #[doc = include_str!("xso_vec_test_prelude.rs")]
1241    /// #[derive(PartialEq, Debug)]
1242    /// struct Foo(u8);
1243    /// impl Trait for Foo {}
1244    ///
1245    /// #[derive(PartialEq, Debug)]
1246    /// struct Bar(u16);
1247    /// impl Trait for Bar {}
1248    ///
1249    /// #[derive(PartialEq, Debug)]
1250    /// struct Baz(u32);
1251    /// impl Trait for Baz {}
1252    ///
1253    /// let mut vec = XsoVec::<dyn Trait>::new();
1254    /// vec.push(Bar(1));
1255    /// vec.push(Foo(2));
1256    /// vec.push(Foo(1));
1257    /// assert_eq!(*vec.take_last::<Foo>().unwrap(), Foo(1));
1258    /// assert_eq!(*vec.take_last::<Foo>().unwrap(), Foo(2));
1259    /// assert_eq!(*vec.take_last::<Bar>().unwrap(), Bar(1));
1260    /// assert_eq!(vec.take_last::<Bar>(), None);
1261    /// assert_eq!(vec.take_last::<Baz>(), None);
1262    /// ```
1263    pub fn take_last<U: 'static>(&mut self) -> Option<Box<U>>
1264    where
1265        T: MayContain<U>,
1266    {
1267        let source = self.inner.get_mut(&TypeId::of::<U>())?;
1268        source.pop().map(Xso::force_downcast)
1269    }
1270
1271    /// Iterate all items of type `U` as references.
1272    ///
1273    /// ```
1274    #[doc = include_str!("xso_vec_test_prelude.rs")]
1275    /// #[derive(PartialEq, Debug)]
1276    /// struct Foo(u8);
1277    /// impl Trait for Foo {}
1278    ///
1279    /// #[derive(PartialEq, Debug)]
1280    /// struct Bar(u16);
1281    /// impl Trait for Bar {}
1282    ///
1283    /// #[derive(PartialEq, Debug)]
1284    /// struct Baz(u32);
1285    /// impl Trait for Baz {}
1286    ///
1287    /// let mut vec = XsoVec::<dyn Trait>::new();
1288    /// vec.push(Bar(1));
1289    /// vec.push(Foo(2));
1290    /// vec.push(Foo(1));
1291    ///
1292    /// let foos: Vec<_> = vec.iter_typed::<Foo>().collect();
1293    /// assert_eq!(&foos[..], &[&Foo(2), &Foo(1)]);
1294    /// ```
1295    pub fn iter_typed<U: 'static>(&self) -> impl Iterator<Item = &U>
1296    where
1297        T: MayContain<U>,
1298    {
1299        let iter = match self.inner.get(&TypeId::of::<U>()) {
1300            Some(v) => v.deref().iter(),
1301            None => (&[]).iter(),
1302        };
1303        // UNWRAP: We group the values by TypeId, so the downcast should never
1304        // fail, but I am too chicken to use the unchecked variants :).
1305        iter.map(|x| x.downcast_ref::<U>().unwrap())
1306    }
1307
1308    /// Iterate all items of type `U` as mutable references.
1309    ///
1310    /// ```
1311    #[doc = include_str!("xso_vec_test_prelude.rs")]
1312    /// #[derive(PartialEq, Debug)]
1313    /// struct Foo(u8);
1314    /// impl Trait for Foo {}
1315    ///
1316    /// #[derive(PartialEq, Debug)]
1317    /// struct Bar(u16);
1318    /// impl Trait for Bar {}
1319    ///
1320    /// #[derive(PartialEq, Debug)]
1321    /// struct Baz(u32);
1322    /// impl Trait for Baz {}
1323    ///
1324    /// let mut vec = XsoVec::<dyn Trait>::new();
1325    /// vec.push(Bar(1));
1326    /// vec.push(Foo(2));
1327    /// vec.push(Foo(1));
1328    ///
1329    /// let foos: Vec<_> = vec.iter_typed_mut::<Foo>().collect();
1330    /// assert_eq!(&foos[..], &[&mut Foo(2), &mut Foo(1)]);
1331    /// ```
1332    pub fn iter_typed_mut<U: 'static>(&mut self) -> impl Iterator<Item = &mut U>
1333    where
1334        T: MayContain<U>,
1335    {
1336        let iter = match self.inner.get_mut(&TypeId::of::<U>()) {
1337            Some(v) => v.deref_mut().iter_mut(),
1338            None => (&mut []).iter_mut(),
1339        };
1340        // UNWRAP: We group the values by TypeId, so the downcast should never
1341        // fail, but I am too chicken to use the unchecked variants :).
1342        iter.map(|x| x.downcast_mut::<U>().unwrap())
1343    }
1344
1345    /// Drain all items of type `U` out of the container.
1346    ///
1347    /// If the result is dropped before the end of the iterator has been
1348    /// reached, the remaining items are still dropped out of the container.
1349    ///
1350    /// ```
1351    #[doc = include_str!("xso_vec_test_prelude.rs")]
1352    /// #[derive(PartialEq, Debug)]
1353    /// struct Foo(u8);
1354    /// impl Trait for Foo {}
1355    ///
1356    /// #[derive(PartialEq, Debug)]
1357    /// struct Bar(u16);
1358    /// impl Trait for Bar {}
1359    ///
1360    /// #[derive(PartialEq, Debug)]
1361    /// struct Baz(u32);
1362    /// impl Trait for Baz {}
1363    ///
1364    /// let mut vec = XsoVec::<dyn Trait>::new();
1365    /// vec.push(Bar(1));
1366    /// vec.push(Foo(2));
1367    /// vec.push(Foo(1));
1368    ///
1369    /// let foos: Vec<_> = vec.drain_typed::<Foo>().map(|x| *x).collect();
1370    /// //                             converts Box<T> to T ↑
1371    /// assert_eq!(&foos[..], &[Foo(2), Foo(1)]);
1372    /// ```
1373    pub fn drain_typed<U: 'static>(&mut self) -> impl Iterator<Item = Box<U>>
1374    where
1375        T: MayContain<U>,
1376    {
1377        let iter = match self.inner.remove(&TypeId::of::<U>()) {
1378            Some(v) => v.into_iter(),
1379            None => Vec::new().into_iter(),
1380        };
1381        // UNWRAP: We group the values by TypeId, so the downcast should never
1382        // fail, but I am too chicken to use the unchecked variants :).
1383        iter.map(|x| match x.downcast::<U>() {
1384            Ok(v) => v,
1385            Err(_) => {
1386                unreachable!("TypeId disagrees with Xso<_>::downcast, or internal state corruption")
1387            }
1388        })
1389    }
1390
1391    fn ensure_vec_mut_for(&mut self, type_id: TypeId) -> &mut Vec<Xso<T>> {
1392        match self.inner.entry(type_id) {
1393            Entry::Vacant(v) => v.insert(Vec::new()),
1394            Entry::Occupied(o) => o.into_mut(),
1395        }
1396    }
1397
1398    /// Push a new item of type `U` to the end of the section of `U` inside
1399    /// the container.
1400    ///
1401    /// Please note the information about iteration order of the `XsoVec`
1402    /// at [`XsoVec::iter`][`Self::iter`].
1403    ///
1404    /// ```
1405    #[doc = include_str!("xso_vec_test_prelude.rs")]
1406    /// #[derive(PartialEq, Debug)]
1407    /// struct Foo(u8);
1408    /// impl Trait for Foo {}
1409    ///
1410    /// let mut vec = XsoVec::<dyn Trait>::new();
1411    /// vec.push(Foo(1));
1412    /// ```
1413    pub fn push<U: 'static>(&mut self, value: U)
1414    where
1415        T: MayContain<U>,
1416    {
1417        self.ensure_vec_mut_for(TypeId::of::<U>())
1418            .push(Xso::wrap(value));
1419    }
1420
1421    /// Push a new dynamically typed item to the end of the section of values
1422    /// with the same type inside the container.
1423    ///
1424    /// Please note the information about iteration order of the `XsoVec`
1425    /// at [`XsoVec::iter`][`Self::iter`].
1426    ///
1427    /// ```
1428    /// # use xso::dynxso::Xso;
1429    #[doc = include_str!("xso_vec_test_prelude.rs")]
1430    /// #[derive(PartialEq, Debug)]
1431    /// struct Foo(u8);
1432    /// impl Trait for Foo {}
1433    ///
1434    /// #[derive(PartialEq, Debug)]
1435    /// struct Bar(u8);
1436    /// impl Trait for Bar {}
1437    ///
1438    /// let mut vec = XsoVec::<dyn Trait>::new();
1439    /// vec.push(Foo(1));
1440    /// vec.push_dyn(Xso::wrap(Foo(2)));
1441    /// vec.push_dyn(Xso::wrap(Bar(1)));
1442    /// vec.push(Bar(2));
1443    ///
1444    /// let foos: Vec<_> = vec.iter_typed::<Foo>().collect();
1445    /// assert_eq!(&foos[..], &[&Foo(1), &Foo(2)]);
1446    ///
1447    /// let bars: Vec<_> = vec.iter_typed::<Bar>().collect();
1448    /// assert_eq!(&bars[..], &[&Bar(1), &Bar(2)]);
1449    /// ```
1450    pub fn push_dyn(&mut self, value: Xso<T>) {
1451        self.ensure_vec_mut_for(value.inner_type_id()).push(value);
1452    }
1453}
1454
1455impl<T: ?Sized> XsoVec<T> {
1456    /// Clear all contents, without deallocating memory.
1457    ///
1458    /// ```
1459    #[doc = include_str!("xso_vec_test_prelude.rs")]
1460    /// #[derive(PartialEq, Debug)]
1461    /// struct Foo(u8);
1462    /// impl Trait for Foo {}
1463    ///
1464    /// let mut vec = XsoVec::<dyn Trait>::new();
1465    /// vec.push(Foo(1));
1466    /// vec.push(Foo(2));
1467    /// vec.clear();
1468    /// assert_eq!(vec.len(), 0);
1469    /// ```
1470    pub fn clear(&mut self) {
1471        self.inner.values_mut().for_each(|x| x.clear());
1472    }
1473
1474    /// Return true if there are no items in the container.
1475    ///
1476    /// ```
1477    #[doc = include_str!("xso_vec_test_prelude.rs")]
1478    /// #[derive(PartialEq, Debug)]
1479    /// struct Foo(u8);
1480    /// impl Trait for Foo {}
1481    ///
1482    /// let mut vec = XsoVec::<dyn Trait>::new();
1483    /// assert!(vec.is_empty());
1484    /// vec.push(Foo(1));
1485    /// assert!(!vec.is_empty());
1486    /// ```
1487    pub fn is_empty(&self) -> bool {
1488        self.inner.values().all(|x| x.is_empty())
1489    }
1490
1491    /// Reduce memory use of the container to the minimum required to hold
1492    /// the current data.
1493    ///
1494    /// This may be expensive if lots of data needs to be shuffled.
1495    pub fn shrink_to_fit(&mut self) {
1496        self.inner.retain(|_, x| {
1497            if x.is_empty() {
1498                return false;
1499            }
1500            x.shrink_to_fit();
1501            true
1502        });
1503    }
1504
1505    /// Return the total amount of items in the container.
1506    ///
1507    /// ```
1508    #[doc = include_str!("xso_vec_test_prelude.rs")]
1509    /// #[derive(PartialEq, Debug)]
1510    /// struct Foo(u8);
1511    /// impl Trait for Foo {}
1512    ///
1513    /// let mut vec = XsoVec::<dyn Trait>::new();
1514    /// assert_eq!(vec.len(), 0);
1515    /// vec.push(Foo(1));
1516    /// assert_eq!(vec.len(), 1);
1517    /// ```
1518    pub fn len(&self) -> usize {
1519        self.inner.values().map(|x| x.len()).sum()
1520    }
1521
1522    /// Iterate the items inside the container.
1523    ///
1524    /// This iterator (unlike the iterator returned by
1525    /// [`iter_typed()`][`Self::iter_typed`]) yields references to **untyped**
1526    /// [`Xso<dyn Trait>`][`Xso`].
1527    ///
1528    /// # Iteration order
1529    ///
1530    /// Items which have the same concrete type are grouped and their ordering
1531    /// with respect to one another is preserved. However, the ordering of
1532    /// items with *different* concrete types is unspecified.
1533    ///
1534    /// # Example
1535    ///
1536    /// ```
1537    #[doc = include_str!("xso_vec_test_prelude.rs")]
1538    /// #[derive(PartialEq, Debug)]
1539    /// struct Foo(u8);
1540    /// impl Trait for Foo {}
1541    ///
1542    /// #[derive(PartialEq, Debug)]
1543    /// struct Bar(u16);
1544    /// impl Trait for Bar {}
1545    ///
1546    /// let mut vec = XsoVec::<dyn Trait>::new();
1547    /// vec.push(Foo(1));
1548    /// vec.push(Bar(1));
1549    /// vec.push(Foo(2));
1550    ///
1551    /// for item in vec.iter() {
1552    ///     println!("{:?}", item);
1553    /// }
1554    /// ```
1555    pub fn iter(&self) -> XsoVecIter<'_, T> {
1556        XsoVecIter {
1557            remaining: self.len(),
1558            outer: self.inner.values(),
1559            inner: None,
1560        }
1561    }
1562
1563    /// Iterate the items inside the container, mutably.
1564    ///
1565    /// This iterator (unlike the iterator returned by
1566    /// [`iter_typed_mut()`][`Self::iter_typed_mut`]) yields mutable
1567    /// references to **untyped** [`Xso<dyn Trait>`][`Xso`].
1568    ///
1569    /// Please note the information about iteration order of the `XsoVec`
1570    /// at [`XsoVec::iter`][`Self::iter`].
1571    pub fn iter_mut(&mut self) -> XsoVecIterMut<'_, T> {
1572        XsoVecIterMut {
1573            remaining: self.len(),
1574            outer: self.inner.values_mut(),
1575            inner: None,
1576        }
1577    }
1578}
1579
1580impl<T: ?Sized> IntoIterator for XsoVec<T> {
1581    type Item = Xso<T>;
1582    type IntoIter = XsoVecIntoIter<T>;
1583
1584    fn into_iter(self) -> Self::IntoIter {
1585        XsoVecIntoIter {
1586            remaining: self.len(),
1587            outer: self.inner.into_values(),
1588            inner: None,
1589        }
1590    }
1591}
1592
1593impl<'x, T: ?Sized> IntoIterator for &'x XsoVec<T> {
1594    type Item = &'x Xso<T>;
1595    type IntoIter = XsoVecIter<'x, T>;
1596
1597    fn into_iter(self) -> Self::IntoIter {
1598        self.iter()
1599    }
1600}
1601
1602impl<'x, T: ?Sized> IntoIterator for &'x mut XsoVec<T> {
1603    type Item = &'x mut Xso<T>;
1604    type IntoIter = XsoVecIterMut<'x, T>;
1605
1606    fn into_iter(self) -> Self::IntoIter {
1607        self.iter_mut()
1608    }
1609}
1610
1611impl<T: DynXso + ?Sized + 'static> Extend<Xso<T>> for XsoVec<T> {
1612    fn extend<I: IntoIterator<Item = Xso<T>>>(&mut self, iter: I) {
1613        for item in iter {
1614            self.ensure_vec_mut_for(item.inner_type_id()).push(item);
1615        }
1616    }
1617}
1618
1619/// Helper types for [`XsoVec`].
1620pub mod xso_vec {
1621    use super::*;
1622
1623    /// Iterator over the contents of an [`XsoVec`].
1624    pub struct XsoVecIter<'x, T: ?Sized> {
1625        pub(super) outer: btree_map::Values<'x, TypeId, Vec<Xso<T>>>,
1626        pub(super) inner: Option<slice::Iter<'x, Xso<T>>>,
1627        pub(super) remaining: usize,
1628    }
1629
1630    impl<'x, T: ?Sized> Iterator for XsoVecIter<'x, T> {
1631        type Item = &'x Xso<T>;
1632
1633        fn next(&mut self) -> Option<Self::Item> {
1634            loop {
1635                if let Some(inner) = self.inner.as_mut() {
1636                    if let Some(item) = inner.next() {
1637                        self.remaining = self.remaining.saturating_sub(1);
1638                        return Some(item);
1639                    }
1640                    // Inner is exhausted, so equivalent to None, fall through.
1641                }
1642                // The `?` in there is our exit condition.
1643                self.inner = Some(self.outer.next()?.deref().iter())
1644            }
1645        }
1646
1647        fn size_hint(&self) -> (usize, Option<usize>) {
1648            (self.remaining, Some(self.remaining))
1649        }
1650    }
1651
1652    /// Mutable iterator over the contents of an [`XsoVec`].
1653    pub struct XsoVecIterMut<'x, T: ?Sized> {
1654        pub(super) outer: btree_map::ValuesMut<'x, TypeId, Vec<Xso<T>>>,
1655        pub(super) inner: Option<slice::IterMut<'x, Xso<T>>>,
1656        pub(super) remaining: usize,
1657    }
1658
1659    impl<'x, T: ?Sized> Iterator for XsoVecIterMut<'x, T> {
1660        type Item = &'x mut Xso<T>;
1661
1662        fn next(&mut self) -> Option<Self::Item> {
1663            loop {
1664                if let Some(inner) = self.inner.as_mut() {
1665                    if let Some(item) = inner.next() {
1666                        self.remaining = self.remaining.saturating_sub(1);
1667                        return Some(item);
1668                    }
1669                    // Inner is exhausted, so equivalent to None, fall through.
1670                }
1671                // The `?` in there is our exit condition.
1672                self.inner = Some(self.outer.next()?.deref_mut().iter_mut())
1673            }
1674        }
1675
1676        fn size_hint(&self) -> (usize, Option<usize>) {
1677            (self.remaining, Some(self.remaining))
1678        }
1679    }
1680
1681    /// Iterator over the owned contents of an [`XsoVec`].
1682    pub struct XsoVecIntoIter<T: ?Sized> {
1683        pub(super) outer: btree_map::IntoValues<TypeId, Vec<Xso<T>>>,
1684        pub(super) inner: Option<vec::IntoIter<Xso<T>>>,
1685        pub(super) remaining: usize,
1686    }
1687
1688    impl<T: ?Sized> Iterator for XsoVecIntoIter<T> {
1689        type Item = Xso<T>;
1690
1691        fn next(&mut self) -> Option<Self::Item> {
1692            loop {
1693                if let Some(inner) = self.inner.as_mut() {
1694                    if let Some(item) = inner.next() {
1695                        self.remaining = self.remaining.saturating_sub(1);
1696                        return Some(item);
1697                    }
1698                    // Inner is exhausted, so equivalent to None, fall through.
1699                }
1700                // The `?` in there is our exit condition.
1701                self.inner = Some(self.outer.next()?.into_iter())
1702            }
1703        }
1704
1705        fn size_hint(&self) -> (usize, Option<usize>) {
1706            (self.remaining, Some(self.remaining))
1707        }
1708    }
1709}
1710
1711use xso_vec::*;
1712
1713#[cfg(test)]
1714mod tests {
1715    use super::*;
1716
1717    #[test]
1718    fn xso_inner_type_id_is_correct() {
1719        trait Trait: Any {}
1720        crate::derive_dyn_traits!(Trait use () = ());
1721        struct Foo;
1722        impl Trait for Foo {}
1723
1724        let ty_id = TypeId::of::<Foo>();
1725        let x: Xso<dyn Trait> = Xso::wrap(Foo);
1726        assert_eq!(x.inner_type_id(), ty_id);
1727    }
1728}