Skip to main content

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}