unlit_ecs/info.rs
1//! Plain-data summaries of a world's shape.
2//!
3//! A world stores components behind type-erased columns, so a caller that only
4//! has a scope can count entities and archetypes but cannot name a component:
5//! the names live in a side table keyed by [`TypeId`]. These structures put a
6//! name back on every column and borrow nothing from the world, which is what a
7//! bridge that reports a world over JSON needs.
8//!
9//! Every count here is what one scope sees, not what the world holds: a scope of a
10//! scene reports that scene. The two root entities are reported by handle so
11//! that a caller can tell why the count is two higher than the content.
12//!
13//! They are deliberately shallow. Nothing here reaches into a component's own
14//! fields -- that is the caller's business, and a caller that wants it derives
15//! its own reflection.
16//!
17//! [`TypeId`]: core::any::TypeId
18
19use crate::entity::Entity;
20
21/// A live entity's location and component names.
22///
23/// Only a live, visible entity has one: [`Scope::entity_info`] answers
24/// [`EntityAccessError::NotAlive`] or [`EntityAccessError::NotVisible`] for a
25/// handle that is neither, so there is no `alive` field to report.
26///
27/// [`EntityAccessError::NotAlive`]: crate::EntityAccessError::NotAlive
28/// [`EntityAccessError::NotVisible`]: crate::EntityAccessError::NotVisible
29///
30/// [`Scope::entity_info`]: crate::Scope::entity_info
31#[derive(Clone, Debug, PartialEq, Eq)]
32#[cfg_attr(feature = "reflect", derive(facet::Facet))]
33pub struct EntityInfo {
34 /// The entity's handle.
35 #[cfg_attr(feature = "reflect", facet(opaque, proxy = crate::EntityProxy))]
36 pub entity: Entity,
37 /// The entity's name, which its handle carries but its bits do not, so a
38 /// reader of this listing sees the label the entity was spawned with even
39 /// though the handle travels as a bare integer.
40 pub name: &'static str,
41 /// The archetype the entity lives in, as [`Location::archetype`].
42 ///
43 /// [`Location::archetype`]: crate::Location::archetype
44 pub archetype: u32,
45 /// The entity's row in that archetype, as [`Location::row`].
46 ///
47 /// [`Location::row`]: crate::Location::row
48 pub row: usize,
49 /// The entity's scope: the entity it lives in, which is its parent in the
50 /// scope tree.
51 ///
52 /// An entity's scope is deliberately not a component, so it is reported
53 /// here instead: a client reading a listing sees the same relation a
54 /// [`Scope`](crate::Scope) traverses.
55 #[cfg_attr(feature = "reflect", facet(opaque, proxy = crate::EntityProxy))]
56 pub scope: Entity,
57 /// The component names of the entity's archetype, in column order.
58 pub components: Vec<&'static str>,
59}
60
61/// One archetype: its id, how many of its rows a scope sees, and its component
62/// names.
63#[derive(Clone, Debug, PartialEq, Eq)]
64#[cfg_attr(feature = "reflect", derive(facet::Facet))]
65pub struct ArchetypeInfo {
66 /// The archetype id, the value [`EntityInfo::archetype`] carries.
67 pub index: u32,
68 /// The number of rows visible from the scope, not the archetype's total.
69 ///
70 /// This is the only definition under which the lengths sum to
71 /// [`WorldInfo::entities`].
72 pub len: usize,
73 /// Its component names, in column order.
74 pub components: Vec<&'static str>,
75}
76
77/// A scope's high-level shape.
78#[derive(Clone, Debug, PartialEq, Eq)]
79#[cfg_attr(feature = "reflect", derive(facet::Facet))]
80pub struct WorldInfo {
81 /// The number of live entities visible from the scope, the roots included.
82 pub entities: usize,
83 /// The number of archetypes with at least one visible row.
84 pub archetypes: usize,
85 /// The names of the component types this scope can see, sorted.
86 ///
87 /// A type is named here when an archetype holding at least one visible row
88 /// carries it, which is the same rule as [`WorldInfo::archetypes`]: the two
89 /// describe the rows the scope reaches, not the types that ever entered the
90 /// world.
91 pub components: Vec<&'static str>,
92 /// The root entity, which owns everything.
93 #[cfg_attr(feature = "reflect", facet(opaque, proxy = crate::EntityProxy))]
94 pub root: Entity,
95 /// The shared entity, whose subtree every scope sees.
96 #[cfg_attr(feature = "reflect", facet(opaque, proxy = crate::EntityProxy))]
97 pub shared: Entity,
98}