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}