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}
41
42/// How often a declaration wants its fields written.
43#[derive(Schema, Copy, Clone, Debug, PartialEq, Eq)]
44pub enum Rate {
45    /// Every `n` ticks (1: every tick).
46    Every(u32),
47    /// When its provider says the mirror changed.
48    Changes,
49}
50
51/// A field's place for its readers.
52#[derive(Copy, Clone, Debug, PartialEq, Eq)]
53pub struct Linked {
54    /// Its column.
55    pub column: *const yog_abi::YogColumn,
56    /// How many parents up its column's space is (0: the mirror's own): a
57    /// row's key is looked up there through the parent keys.
58    pub depth: u8,
59}
60
61/// What a declaration gets.
62#[derive(Clone, Debug)]
63pub struct Declared {
64    pub id: u32,
65    /// The mirror's key space.
66    pub space: *const yog_abi::YogKeySpace,
67    /// The mirror's rows: a bit a space row its provider fills.
68    pub rows: *const yog_abi::YogColumn,
69    /// Each field's place, `None` when it wasn't asked for.
70    pub fields: Vec<Option<Linked>>,
71}
72
73/// A provider's turn to write: its mirror, the fields due (a bit each, in
74/// the mirror's field order) and where they go.
75#[derive(Clone, Debug, PartialEq, Eq)]
76pub struct Due {
77    pub writer: u32,
78    pub mirror: yog_sync::Arc<str>,
79    pub fields: u64,
80    /// The mirror's key space (`*const YogKeySpace`).
81    pub space: u64,
82    /// Its name.
83    pub space_name: yog_sync::Arc<str>,
84    /// The mirror's rows (`*const YogColumn`).
85    pub rows: u64,
86    /// Its due fields' columns in [`DueList::columns`], in field order.
87    pub columns: std::ops::Range<usize>,
88    /// What its declarations asked it to cover, in [`DueList::scopes`].
89    pub scopes: std::ops::Range<usize>,
90}
91
92/// What's due a tick: every provider's turn, their columns in one list —
93/// kept from tick to tick, so nothing is allocated once it's grown.
94#[derive(Clone, Debug, Default)]
95pub struct DueList {
96    pub turns: Vec<Due>,
97    columns: Vec<u64>,
98    scopes: Vec<yog_sync::Arc<[u8]>>,
99}
100
101impl DueList {
102    /// `due`'s columns (`*const YogColumn` each).
103    pub fn columns(&self, due: &Due) -> &[u64] {
104        &self.columns[due.columns.clone()]
105    }
106
107    /// `due`'s scopes (each its mirror's scope type, as Yog Data).
108    pub fn scopes(&self, due: &Due) -> &[yog_sync::Arc<[u8]>] {
109        &self.scopes[due.scopes.clone()]
110    }
111
112    pub(crate) fn clear(&mut self) {
113        self.turns.clear();
114        self.columns.clear();
115        self.scopes.clear();
116    }
117
118    pub(crate) fn push_scope(&mut self, scope: yog_sync::Arc<[u8]>) {
119        self.scopes.push(scope);
120    }
121
122    pub(crate) fn next_scope(&self) -> usize {
123        self.scopes.len()
124    }
125
126    pub(crate) fn push_column(&mut self, column: u64) {
127        self.columns.push(column);
128    }
129
130    pub(crate) fn next_column(&self) -> usize {
131        self.columns.len()
132    }
133}