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}