multi_any/
meta.rs

1use crate::TypedMetadata;
2use crate::ptr_metadata::*;
3use std::any::TypeId;
4
5/// Stores fat pointer metadata in a type-erased way.
6///
7/// Used internally by `MultiAny` to safely downcast to concrete types or trait objects.
8///
9/// # Fields
10/// - `meta_raw`: Raw metadata pointer stored as `usize`.
11/// - `data_id`: `TypeId` of the original data type.
12/// - `meta_id`: `TypeId` of the metadata type.
13///
14/// # Safety
15/// - `meta_raw` must have been created from a `DynMetadata<T>` or `()`.
16/// - `data_id` and `meta_id` must match the data and metadata types exactly.
17pub struct Meta {
18    pub(crate) meta_raw: usize,
19    pub(crate) data_id: TypeId,
20    pub(crate) meta_id: TypeId,
21}
22
23impl Meta {
24    /// Attempts to construct `Meta` for a requested type.
25    ///
26    /// # Parameters
27    /// - `data`: Reference to the concrete data.
28    /// - `requested_type_id`: TypeId of the requested type.
29    /// - `cast_fn`: Function to cast `&Data` to `&RequestedType`.
30    ///
31    /// # Returns
32    /// - `Some(Meta)` if `requested_type_id` matches `RequestedType`.
33    /// - `None` otherwise.
34    ///
35    /// # Type Parameters
36    /// - `Data`: Concrete type stored in the `MultiAny`.
37    /// - `RequestedType`: Type to attempt downcasting to.
38    pub fn try_from<Data, RequestedType>(
39        data: &Data,
40        requested_type_id: TypeId,
41        cast_fn: fn(&Data) -> &RequestedType,
42    ) -> Option<Meta>
43    where
44        Data: 'static,
45        RequestedType: Pointee + ?Sized + 'static,
46        RequestedType::Metadata: TypedMetadata,
47    {
48        if requested_type_id != TypeId::of::<RequestedType>() {
49            return None;
50        }
51
52        let dyn_trait = cast_fn(data);
53        let typed_meta = metadata(dyn_trait);
54
55        RequestedType::Metadata::into_meta::<Data>(typed_meta).into()
56    }
57
58    /// Converts this `Meta` into the concrete metadata type for a requested type.
59    ///
60    /// # Type Parameters
61    /// - `Data`: The concrete type stored in the `MultiAny`.
62    /// - `RequestedType`: The type whose metadata you want to reconstruct.
63    ///
64    /// # Returns
65    /// The metadata of type `RequestedType::Metadata`.
66    pub fn into_metadata<Data, RequestedType>(self) -> RequestedType::Metadata
67    where
68        Data: 'static,
69        RequestedType: Pointee + ?Sized + 'static,
70        RequestedType::Metadata: TypedMetadata,
71    {
72        assert_eq!(self.data_id, TypeId::of::<Data>(), "Wrong Data type");
73        RequestedType::Metadata::from_meta(self)
74    }
75}