brood/registry/debug/
sealed.rs

1//! Functions for the `Debug` implementation of `Archetype`.
2//!
3//! The `Sealed` trait is implemented on any `Registry` where each `Component` implements
4//! `Debug`. It is a "public-in-private" trait, so external users can't implement it. These methods
5//! should not be considered a part of the public API. The methods are used in the implementation
6//! of `Debug` on `Archetype`.
7
8use crate::{
9    archetype,
10    component::Component,
11    registry::{
12        Null,
13        Registry,
14    },
15};
16use alloc::vec::Vec;
17use core::{
18    any::type_name,
19    fmt::{
20        Debug,
21        DebugMap,
22    },
23    mem::size_of,
24};
25
26/// Functions for the `Debug` implementation of `Archetype`.
27///
28/// These functions are for performing row-wise debug formatting.
29pub trait Sealed: Registry {
30    /// Returns pointers to the components stored at the given index.
31    ///
32    /// This function handles the offset arithmetic required to obtain each component and stores a
33    /// byte pointer for each one in `pointers`.
34    ///
35    /// # Safety
36    /// `components` must contain the same number of values as there are set bits in the
37    /// `identifier_iter`.
38    ///
39    /// Each `(*mut u8, usize)` in `components` must be the pointer and capacity respectively of a
40    /// `Vec<C>` where `C` is the component corresponding to the set bit in `identifier_iter`.
41    ///
42    /// `index` must be within the length of each `Vec<C>` defined in `components`.
43    ///
44    /// When called externally, the `Registry` `R` provided to the method must by the same as the
45    /// `Registry` on which this method is being called.
46    ///
47    /// When called internally, the `identifier_iter` must have the same amount of bits left as
48    /// there are components remaining.
49    unsafe fn extract_component_pointers<R>(
50        index: usize,
51        components: &[(*mut u8, usize)],
52        pointers: &mut Vec<*const u8>,
53        identifier_iter: archetype::identifier::Iter<R>,
54    ) where
55        R: Registry;
56
57    /// Populates a [`DebugMap`] with key-value pairs of component type name and component value
58    /// for a single row in an archetype table.
59    ///
60    /// This function is meant to be called multiple times, once for each row in an archetype
61    /// table, and is only meant to be used in debugging contexts. The type name used here is not
62    /// guaranteed to be in any specific form. Therefore, the output is not guaranteed as a part of
63    /// the public API.
64    ///
65    /// # Safety
66    /// `pointers` must contain the same number of values as there are bits set in the
67    /// `identifier_iter`.
68    ///
69    /// Each pointer in `pointers` must point to a valid properly initialized value of type `C`,
70    /// where `C` is the component corresponding to the set bit in `identiifer_iter`.
71    ///
72    /// When called externally, the `Registry` `R` provided to the method must by the same as the
73    /// `Registry` on which this method is being called.
74    ///
75    /// When called internally, the `identifier_iter` must have the same amount of bits left as
76    /// there are components remaining.
77    ///
78    /// [`DebugMap`]: core::fmt::DebugMap
79    unsafe fn debug_components<R>(
80        pointers: &[*const u8],
81        debug_map: &mut DebugMap,
82        identifier_iter: archetype::identifier::Iter<R>,
83    ) where
84        R: Registry;
85}
86
87impl Sealed for Null {
88    unsafe fn extract_component_pointers<R>(
89        _index: usize,
90        _components: &[(*mut u8, usize)],
91        _pointers: &mut Vec<*const u8>,
92        _identifier_iter: archetype::identifier::Iter<R>,
93    ) where
94        R: Registry,
95    {
96    }
97
98    unsafe fn debug_components<R>(
99        _pointers: &[*const u8],
100        _debug_map: &mut DebugMap,
101        _identifier_iter: archetype::identifier::Iter<R>,
102    ) where
103        R: Registry,
104    {
105    }
106}
107
108impl<C, R> Sealed for (C, R)
109where
110    C: Component + Debug,
111    R: Sealed,
112{
113    unsafe fn extract_component_pointers<R_>(
114        index: usize,
115        mut components: &[(*mut u8, usize)],
116        pointers: &mut Vec<*const u8>,
117        mut identifier_iter: archetype::identifier::Iter<R_>,
118    ) where
119        R_: Registry,
120    {
121        if
122        // SAFETY: `identifier_iter` is guaranteed by the safety contract of this method to
123        // return a value for every component within the registry.
124        unsafe { identifier_iter.next().unwrap_unchecked() } {
125            pointers.push(
126                // SAFETY: `components` is guaranteed to have the same number of values as there
127                // set bits in `identifier_iter`. Since a bit must have been set to enter this
128                // block, there must be at least one component column. Additionally, `index` is
129                // within the bounds of each component's `Vec<C>`, so the offset will still result
130                // in a valid pointer within the allocation.
131                unsafe { components.get_unchecked(0).0.add(index * size_of::<C>()) },
132            );
133            components =
134                // SAFETY: `components` is guaranteed to have the same number of values as
135                // there set bits in `identifier_iter`. Since a bit must have been set to enter
136                // this block, there must be at least one component column.
137                unsafe { components.get_unchecked(1..) };
138        }
139
140        // SAFETY: At this point, one bit of `identifier_iter` has been consumed. There are two
141        // possibilities here: either the bit was set or it was not.
142        //
143        // If the bit was set, then the `components` slice will no longer include the first value,
144        // which means the slice will still contain the same number of pointer and capacity tuples
145        // as there are set bits in `identifier_iter`. Additionally, since the first value was
146        // removed from the slice, which corresponded to the component identified by the consumed
147        // bit, all remaining component values will still correspond to valid `Vec<C>`s identified
148        // by the remaining set bits in `identifier_iter`.
149        //
150        // If the bit was not set, then `components` is unaltered, and there are still the same
151        // number of elements as there are set bits in `identifier_iter`, which still make valid
152        // `Vec<C>`s for each `C` identified by the remaining set bits in `identifier_iter`.
153        //
154        // Furthermore, regardless of whether the bit was set or not, `R` is one component smaller
155        // than `(C, R)`, and since `identifier_iter` has had one bit consumed, it still has the
156        // same number of bits remaining as `R` has components remaining.
157        //
158        // Since each `Vec<C>` is still valid for the remaining set components, then `index` is
159        // still a valid index into those allocations.
160        unsafe { R::extract_component_pointers(index, components, pointers, identifier_iter) };
161    }
162
163    unsafe fn debug_components<R_>(
164        mut pointers: &[*const u8],
165        debug_map: &mut DebugMap,
166        mut identifier_iter: archetype::identifier::Iter<R_>,
167    ) where
168        R_: Registry,
169    {
170        if
171        // SAFETY: `identifier_iter` is guaranteed by the safety contract of this method to
172        // return a value for every component within the registry.
173        unsafe { identifier_iter.next().unwrap_unchecked() } {
174            debug_map.entry(
175                &type_name::<C>(),
176                // SAFETY: Since a set bit was found, there must invariantly be at least one valid
177                // pointer within pointers which points to a properly-initialized value of the
178                // corresponding component type `C`.
179                unsafe { &*pointers.get_unchecked(0).cast::<C>() },
180            );
181            pointers =
182                // SAFETY: `pointers` is guaranteed to have the same number of values as there are 
183                // set bits in `identifier_iter`. Since a bit must have been set to enter this
184                // block, there must be at least one valid pointer remaining.
185                unsafe {pointers.get_unchecked(1..)};
186        }
187
188        // SAFETY: At this point, one bit of `identifier_iter` has been consumed. There are two
189        // possibilities here: either the bit was set or it was not.
190        //
191        // If the bit was set, then the `pointers` slice will no longer include the first value,
192        // which means the slice will still contain the same number of values as there are set bits
193        // in `identifier_iter`. Additionally, since the first value was removed from the slice,
194        // which corresponded to the component identified by the consumed bit, all remaining
195        // pointer values will still correspond to valid `C` component types identified by the
196        // remaining set bits in `identifier_iter`.
197        //
198        // If the bit was not set, then `pointers` is unaltered, and there are still the same
199        // number of elements as there are set bits in `identifier_iter`, which still point to
200        // valid properly-initialized values of type `C` for each remaining `C` identified by the
201        // remaining set bits in `identifier_iter`.
202        //
203        // Furthermore, regardless of whether the bit was set or not, `R` is one component smaller
204        // than `(C, R)`, and since `identifier_iter` has had one bit consumed, it still has the
205        // same number of bits remaining as `R` has components remaining.
206        unsafe { R::debug_components(pointers, debug_map, identifier_iter) };
207    }
208}