yog_mirror/spec.rs
1//! What a mirror is, as `#[yog_mirror]` describes it and the bus carries it:
2//! its fields, the facts they are, how often they're wanted.
3
4use yog_data::Schema;
5
6use crate::cell::Kind;
7
8/// A mirror field.
9#[derive(Schema, Clone, Debug, PartialEq, Eq)]
10pub struct FieldSpec {
11 pub name: String,
12 /// The fact it is (`yog_ids::fact::*`, or a mod's own): fields naming
13 /// the same fact share its column. `None`: the mirror's own value.
14 pub fact: Option<String>,
15 /// [`Kind::code`] of its numbers.
16 pub kind: u8,
17 /// Numbers a row.
18 pub count: u32,
19}
20
21impl FieldSpec {
22 pub fn kind(&self) -> Option<Kind> {
23 Kind::from_code(self.kind)
24 }
25
26 /// Bytes a row.
27 pub fn width(&self) -> Option<u32> {
28 Some(self.kind()?.size() as u32 * self.count)
29 }
30}
31
32/// A mirror: `yog:mirror/<mod>/<name>`, rows of one key space.
33#[derive(Schema, Clone, Debug, PartialEq, Eq)]
34pub struct MirrorSpec {
35 /// Its address.
36 pub name: String,
37 /// Its key space (`yog_ids::key_space::*`).
38 pub space: String,
39 pub fields: Vec<FieldSpec>,
40 /// Whose ticks write it.
41 #[data(default)]
42 pub clock: Clock,
43}
44
45/// Whose ticks a mirror is written after: the server's (the world as it
46/// is), or a client's (the world as that player sees it — what a client
47/// mod reads on any server).
48#[derive(Schema, Copy, Clone, Debug, PartialEq, Eq, Default)]
49pub enum Clock {
50 #[default]
51 Server,
52 Client,
53}
54
55/// How often a declaration wants its fields written.
56#[derive(Schema, Copy, Clone, Debug, PartialEq, Eq)]
57pub enum Rate {
58 /// Every `n` ticks (1: every tick).
59 Every(u32),
60 /// When its provider says the mirror changed.
61 Changes,
62}
63
64/// A field's place for its readers.
65#[derive(Copy, Clone, Debug, PartialEq, Eq)]
66pub struct Linked {
67 /// Its column.
68 pub column: *const yog_abi::YogColumn,
69 /// How many parents up its column's space is (0: the mirror's own): a
70 /// row's key is looked up there through the parent keys.
71 pub depth: u8,
72}
73
74/// What a declaration gets.
75#[derive(Clone, Debug)]
76pub struct Declared {
77 pub id: u32,
78 /// The mirror's key space.
79 pub space: *const yog_abi::YogKeySpace,
80 /// The mirror's rows: a bit a space row its provider fills.
81 pub rows: *const yog_abi::YogColumn,
82 /// Each field's place, `None` when it wasn't asked for.
83 pub fields: Vec<Option<Linked>>,
84}
85
86/// A provider's turn to write: its mirror, the fields due (a bit each, in
87/// the mirror's field order) and where they go.
88#[derive(Clone, Debug, PartialEq, Eq)]
89pub struct Due {
90 pub writer: u32,
91 pub mirror: yog_sync::Arc<str>,
92 pub fields: u64,
93 /// The mirror's key space (`*const YogKeySpace`).
94 pub space: u64,
95 /// Its name.
96 pub space_name: yog_sync::Arc<str>,
97 /// The mirror's rows (`*const YogColumn`).
98 pub rows: u64,
99 /// Its due fields' columns in [`DueList::columns`], in field order.
100 pub columns: std::ops::Range<usize>,
101 /// What its declarations asked it to cover, in [`DueList::scopes`].
102 pub scopes: std::ops::Range<usize>,
103 /// Which of those are due (bit `i`: scope `i`, at its declaration's
104 /// rate); the rest are only kept as keys. Past [`SCOPE_PACES`], every
105 /// scope is due every turn.
106 pub writing: u64,
107}
108
109/// Scopes that keep their own pace (a bit each in [`Due::writing`]).
110pub const SCOPE_PACES: usize = u64::BITS as usize;
111
112/// What's due a tick: every provider's turn, their columns in one list —
113/// kept from tick to tick, so nothing is allocated once it's grown.
114#[derive(Clone, Debug, Default)]
115pub struct DueList {
116 pub turns: Vec<Due>,
117 columns: Vec<u64>,
118 scopes: Vec<yog_sync::Arc<[u8]>>,
119}
120
121impl DueList {
122 /// `due`'s columns (`*const YogColumn` each).
123 pub fn columns(&self, due: &Due) -> &[u64] {
124 &self.columns[due.columns.clone()]
125 }
126
127 /// `due`'s scopes (each its mirror's scope type, as Yog Data).
128 pub fn scopes(&self, due: &Due) -> &[yog_sync::Arc<[u8]>] {
129 &self.scopes[due.scopes.clone()]
130 }
131
132 pub(crate) fn clear(&mut self) {
133 self.turns.clear();
134 self.columns.clear();
135 self.scopes.clear();
136 }
137
138 pub(crate) fn push_scope(&mut self, scope: yog_sync::Arc<[u8]>) {
139 self.scopes.push(scope);
140 }
141
142 pub(crate) fn next_scope(&self) -> usize {
143 self.scopes.len()
144 }
145
146 pub(crate) fn push_column(&mut self, column: u64) {
147 self.columns.push(column);
148 }
149
150 pub(crate) fn next_column(&self) -> usize {
151 self.columns.len()
152 }
153}