Skip to main content

yog_api/mirror/
typed.rs

1//! Typed mirrors: what `#[yog_mirror]` implements on a struct — its spec,
2//! a view a row (`ThreatView`: a getter a field) and a writer a row
3//! (`ThreatWriter`: a setter a field, given a closure called only when due).
4
5use std::marker::PhantomData;
6
7use yog_data::{Diagnostic, Schema};
8use yog_ids::{sep, service_mirror};
9use yog_sync::Arc;
10
11use super::{Cell, Declared, FieldSpec, MirrorSpec, Rate, Writer};
12use crate::registry::Registry;
13
14/// A mirror's row type (`#[yog_mirror]` implements it).
15pub trait Mirror: Sized + 'static {
16    /// Its name's last part: `yog:mirror/<mod>/<NAME>`.
17    const NAME: &'static str;
18    /// The mod providing it; `None`: this one.
19    const OWNER: Option<&'static str>;
20    /// Its key space (`yog_ids::key_space::*`).
21    const SPACE: &'static str;
22    /// Every field's bit.
23    const ALL: u64;
24    /// Its key space is a family (a member each parameter, `declare_in`).
25    const FAMILY: bool = false;
26    /// A row read.
27    type View<'a>: From<Row<'a, Self>>;
28    /// A row written.
29    type Writer<'w>: From<RowWriter<'w, Self>>;
30
31    /// Its fields, in order.
32    fn fields() -> Vec<FieldSpec>;
33
34    /// The whole row (a field not asked for reads as its default).
35    fn read(row: &Row<'_, Self>) -> Self;
36
37    /// Every due field of `row` set from `self`.
38    fn write(&self, row: &mut RowWriter<'_, Self>);
39
40    /// Its address.
41    fn address() -> String {
42        let owner = Self::OWNER.unwrap_or_else(crate::mod_id);
43        format!(
44            "{}{owner}{}{}",
45            service_mirror::DOMAIN,
46            sep::PATH,
47            Self::NAME
48        )
49    }
50
51    fn spec() -> MirrorSpec {
52        MirrorSpec {
53            name: Self::address(),
54            space: Self::SPACE.to_owned(),
55            fields: Self::fields(),
56        }
57    }
58
59    /// Asks for `fields` (its bit consts or-ed) at `rate`.
60    fn declare(fields: u64, rate: Rate) -> Result<Mirrored<Self>, Diagnostic> {
61        Ok(Mirrored {
62            declared: Declared::new(&Self::spec(), fields, rate)?,
63            _mirror: PhantomData,
64        })
65    }
66
67    /// [`Mirror::declare`] in member `member` of its family (a dimension:
68    /// `minecraft:overworld`), covering `scope` (its scope type: a
69    /// `BlockScope`…).
70    fn declare_in<S: Schema>(
71        member: &str,
72        scope: Option<&S>,
73        fields: u64,
74        rate: Rate,
75    ) -> Result<Mirrored<Self>, Diagnostic> {
76        let mut spec = Self::spec();
77        spec.name = format!("{}{}{member}", spec.name, sep::PATH);
78        spec.space = format!("{}{}{member}", spec.space, sep::PATH);
79        let scope = scope.map(yog_data::frame::to_frame);
80        Ok(Mirrored {
81            declared: Declared::scoped(&spec, fields, rate, scope)?,
82            _mirror: PhantomData,
83        })
84    }
85}
86
87/// A typed declaration: its rows read in place; dropped, released.
88pub struct Mirrored<M: Mirror> {
89    declared: Declared,
90    _mirror: PhantomData<M>,
91}
92
93impl<M: Mirror> Mirrored<M> {
94    /// Every row its provider fills.
95    pub fn iter(&self) -> impl Iterator<Item = M::View<'_>> {
96        self.declared
97            .rows()
98            .map(|row| Row::new(&self.declared, row).into())
99    }
100
101    /// `key`'s row.
102    pub fn get(&self, key: u64) -> Option<M::View<'_>> {
103        Some(Row::new(&self.declared, self.declared.row_of(key)?).into())
104    }
105
106    pub fn declared(&self) -> &Declared {
107        &self.declared
108    }
109}
110
111/// A row being read (what a generated view wraps).
112pub struct Row<'a, M> {
113    declared: &'a Declared,
114    row: u32,
115    _mirror: PhantomData<M>,
116}
117
118impl<'a, M> Row<'a, M> {
119    fn new(declared: &'a Declared, row: u32) -> Self {
120        Row {
121            declared,
122            row,
123            _mirror: PhantomData,
124        }
125    }
126
127    pub fn row(&self) -> u32 {
128        self.row
129    }
130
131    /// Its key.
132    pub fn key(&self) -> Option<u64> {
133        self.declared.key_of(self.row)
134    }
135
136    /// Field `field`'s value; its default when it wasn't asked for.
137    #[inline]
138    pub fn field<T: Cell>(&self, field: usize) -> T {
139        self.declared.get(field, self.row).unwrap_or_default()
140    }
141}
142
143/// A row being written (what a generated writer wraps).
144pub struct RowWriter<'w, M> {
145    writer: &'w mut Writer,
146    row: u32,
147    _mirror: PhantomData<M>,
148}
149
150impl<M> RowWriter<'_, M> {
151    pub fn row(&self) -> u32 {
152        self.row
153    }
154
155    /// Sets field `field` to what `value` gives, if it's due.
156    #[inline]
157    pub fn set<T: Cell>(&mut self, field: usize, value: impl FnOnce() -> T) {
158        if self.writer.wants(field) {
159            self.writer.set(field, self.row, value);
160        }
161    }
162}
163
164/// A typed provider's turn.
165pub struct MirrorWriter<'w, M> {
166    writer: &'w mut Writer,
167    _mirror: PhantomData<M>,
168}
169
170impl<M: Mirror> MirrorWriter<'_, M> {
171    /// `key`'s row to write, marked as filled; `None` when its space hasn't the key.
172    pub fn row(&mut self, key: u64) -> Option<M::Writer<'_>> {
173        let row = self.writer.row(key)?;
174        Some(
175            RowWriter {
176                writer: &mut *self.writer,
177                row,
178                _mirror: PhantomData,
179            }
180            .into(),
181        )
182    }
183
184    /// Row `row` no longer filled.
185    pub fn leave(&mut self, row: u32) {
186        self.writer.leave(row);
187    }
188
189    /// The family member written now (a dimension), when its space is a family's.
190    pub fn member(&self) -> Option<&str> {
191        let base = M::address();
192        self.writer
193            .mirror()
194            .strip_prefix(&base)?
195            .strip_prefix(sep::PATH)
196    }
197
198    /// What the declarations asked it to cover.
199    pub fn scopes<S: Schema>(&self) -> impl Iterator<Item = S> + '_ {
200        self.writer
201            .scopes()
202            .iter()
203            .filter_map(|b| yog_data::frame::read_frame(b))
204    }
205
206    /// Makes the key space's keys `live` (a mod's own key space).
207    pub fn keep_keys(&mut self, live: &[(u64, Option<u64>)]) {
208        self.writer.keep_keys(live);
209    }
210
211    /// Whether any of `fields` is due.
212    pub fn wants(&self, fields: u64) -> bool {
213        (0..u64::BITS as usize).any(|i| fields >> i & 1 == 1 && self.writer.wants(i))
214    }
215}
216
217impl Registry {
218    /// Provides mirror `M`: `write` fills what's due each time it is.
219    pub fn provide_mirror_of<M: Mirror>(
220        &mut self,
221        write: impl Fn(&mut MirrorWriter<'_, M>) + Send + Sync + 'static,
222    ) -> bool {
223        let write = Arc::new(move |w: &mut Writer| {
224            write(&mut MirrorWriter {
225                writer: w,
226                _mirror: PhantomData,
227            })
228        });
229        self.providing_mirror(&M::spec(), M::FAMILY, write)
230    }
231}