1use std::marker::PhantomData;
6
7use yog_data::{Diagnostic, Schema};
8use yog_ids::{sep, service_mirror};
9use yog_sync::Arc;
10
11use super::{Cell, Clock, Declared, FieldSpec, MirrorSpec, Rate, Writer};
12use crate::registry::Registry;
13
14pub trait Mirror: Sized + 'static {
16 const NAME: &'static str;
18 const OWNER: Option<&'static str>;
20 const SPACE: &'static str;
22 const ALL: u64;
24 const FAMILY: bool = false;
26 const CLOCK: Clock = Clock::Server;
28 type View<'a>: From<Row<'a, Self>>;
30 type Writer<'w>: From<RowWriter<'w, Self>>;
32
33 fn fields() -> Vec<FieldSpec>;
35
36 fn read(row: &Row<'_, Self>) -> Self;
38
39 fn write(&self, row: &mut RowWriter<'_, Self>);
41
42 fn address() -> String {
44 let owner = Self::OWNER.unwrap_or_else(crate::mod_id);
45 format!(
46 "{}{owner}{}{}",
47 service_mirror::DOMAIN,
48 sep::PATH,
49 Self::NAME
50 )
51 }
52
53 fn spec() -> MirrorSpec {
54 MirrorSpec {
55 name: Self::address(),
56 space: Self::SPACE.to_owned(),
57 fields: Self::fields(),
58 clock: Self::CLOCK,
59 }
60 }
61
62 fn declare(fields: u64, rate: Rate) -> Result<Mirrored<Self>, Diagnostic> {
64 Ok(Mirrored {
65 declared: Declared::new(&Self::spec(), fields, rate)?,
66 _mirror: PhantomData,
67 })
68 }
69
70 fn declare_scoped<S: Schema>(scope: &S, fields: u64, rate: Rate) -> Result<Mirrored<Self>, Diagnostic> {
73 let scope = Some(yog_data::frame::to_frame(scope));
74 Ok(Mirrored {
75 declared: Declared::scoped(&Self::spec(), fields, rate, scope)?,
76 _mirror: PhantomData,
77 })
78 }
79
80 fn declare_in<S: Schema>(
84 member: &str,
85 scope: Option<&S>,
86 fields: u64,
87 rate: Rate,
88 ) -> Result<Mirrored<Self>, Diagnostic> {
89 let mut spec = Self::spec();
90 spec.name = format!("{}{}{member}", spec.name, sep::PATH);
91 spec.space = format!("{}{}{member}", spec.space, sep::PATH);
92 let scope = scope.map(yog_data::frame::to_frame);
93 Ok(Mirrored {
94 declared: Declared::scoped(&spec, fields, rate, scope)?,
95 _mirror: PhantomData,
96 })
97 }
98}
99
100pub struct Mirrored<M: Mirror> {
102 declared: Declared,
103 _mirror: PhantomData<M>,
104}
105
106impl<M: Mirror> Mirrored<M> {
107 pub fn iter(&self) -> impl Iterator<Item = M::View<'_>> {
109 self.declared
110 .rows()
111 .map(|row| Row::new(&self.declared, row).into())
112 }
113
114 pub fn get(&self, key: u64) -> Option<M::View<'_>> {
116 Some(Row::new(&self.declared, self.declared.row_of(key)?).into())
117 }
118
119 pub fn declared(&self) -> &Declared {
120 &self.declared
121 }
122}
123
124pub struct Row<'a, M> {
126 declared: &'a Declared,
127 row: u32,
128 _mirror: PhantomData<M>,
129}
130
131impl<'a, M> Row<'a, M> {
132 fn new(declared: &'a Declared, row: u32) -> Self {
133 Row {
134 declared,
135 row,
136 _mirror: PhantomData,
137 }
138 }
139
140 pub fn row(&self) -> u32 {
141 self.row
142 }
143
144 pub fn key(&self) -> Option<u64> {
146 self.declared.key_of(self.row)
147 }
148
149 #[inline]
151 pub fn field<T: Cell>(&self, field: usize) -> T {
152 self.declared.get(field, self.row).unwrap_or_default()
153 }
154}
155
156pub struct RowWriter<'w, M> {
158 writer: &'w mut Writer,
159 row: u32,
160 _mirror: PhantomData<M>,
161}
162
163impl<M> RowWriter<'_, M> {
164 pub fn row(&self) -> u32 {
165 self.row
166 }
167
168 #[inline]
170 pub fn set<T: Cell>(&mut self, field: usize, value: impl FnOnce() -> T) {
171 if self.writer.wants(field) {
172 self.writer.set(field, self.row, value);
173 }
174 }
175}
176
177pub struct MirrorWriter<'w, M> {
179 writer: &'w mut Writer,
180 _mirror: PhantomData<M>,
181}
182
183impl<M: Mirror> MirrorWriter<'_, M> {
184 pub fn row(&mut self, key: u64) -> Option<M::Writer<'_>> {
186 let row = self.writer.row(key)?;
187 Some(
188 RowWriter {
189 writer: &mut *self.writer,
190 row,
191 _mirror: PhantomData,
192 }
193 .into(),
194 )
195 }
196
197 pub fn leave(&mut self, row: u32) {
199 self.writer.leave(row);
200 }
201
202 pub fn member(&self) -> Option<&str> {
204 let base = M::address();
205 self.writer
206 .mirror()
207 .strip_prefix(&base)?
208 .strip_prefix(sep::PATH)
209 }
210
211 pub fn scopes<S: Schema>(&self) -> impl Iterator<Item = S> + '_ {
213 self.writer
214 .scopes()
215 .iter()
216 .filter_map(|b| yog_data::frame::read_frame(b))
217 }
218
219 pub fn due_scopes<S: Schema>(&self) -> impl Iterator<Item = S> + '_ {
221 self.writer
222 .scopes()
223 .iter()
224 .enumerate()
225 .filter(|(i, _)| self.writer.writing(*i))
226 .filter_map(|(_, b)| yog_data::frame::read_frame(b))
227 }
228
229 pub fn keep_keys(&mut self, live: &[(u64, Option<u64>)]) {
231 self.writer.keep_keys(live);
232 }
233
234 pub fn wants(&self, fields: u64) -> bool {
236 (0..u64::BITS as usize).any(|i| fields >> i & 1 == 1 && self.writer.wants(i))
237 }
238}
239
240impl Registry {
241 pub fn provide_mirror_of<M: Mirror>(
243 &mut self,
244 write: impl Fn(&mut MirrorWriter<'_, M>) + Send + Sync + 'static,
245 ) -> bool {
246 let write = Arc::new(move |w: &mut Writer| {
247 write(&mut MirrorWriter {
248 writer: w,
249 _mirror: PhantomData,
250 })
251 });
252 self.providing_mirror(&M::spec(), M::FAMILY, write)
253 }
254}