1use 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
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 type View<'a>: From<Row<'a, Self>>;
28 type Writer<'w>: From<RowWriter<'w, Self>>;
30
31 fn fields() -> Vec<FieldSpec>;
33
34 fn read(row: &Row<'_, Self>) -> Self;
36
37 fn write(&self, row: &mut RowWriter<'_, Self>);
39
40 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 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 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
87pub struct Mirrored<M: Mirror> {
89 declared: Declared,
90 _mirror: PhantomData<M>,
91}
92
93impl<M: Mirror> Mirrored<M> {
94 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 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
111pub 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 pub fn key(&self) -> Option<u64> {
133 self.declared.key_of(self.row)
134 }
135
136 #[inline]
138 pub fn field<T: Cell>(&self, field: usize) -> T {
139 self.declared.get(field, self.row).unwrap_or_default()
140 }
141}
142
143pub 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 #[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
164pub struct MirrorWriter<'w, M> {
166 writer: &'w mut Writer,
167 _mirror: PhantomData<M>,
168}
169
170impl<M: Mirror> MirrorWriter<'_, M> {
171 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 pub fn leave(&mut self, row: u32) {
186 self.writer.leave(row);
187 }
188
189 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 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 pub fn keep_keys(&mut self, live: &[(u64, Option<u64>)]) {
208 self.writer.keep_keys(live);
209 }
210
211 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 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}