matchmaker/nucleo/
injector.rs1use std::{
5 marker::PhantomData,
6 sync::{
7 Arc,
8 atomic::{AtomicU32, Ordering},
9 },
10};
11
12use super::worker::{Column, Worker, WorkerError};
13use super::{Indexed, Segmented};
14use crate::{SSS, SegmentableItem, SplitterFn};
15
16pub trait Injector: Clone {
17 type InputItem;
18 type Inner: Injector;
19 type Context;
20
21 fn new(injector: Self::Inner, data: Self::Context) -> Self;
22 fn inner(&self) -> &Self::Inner;
23 fn wrap(
24 &self,
25 item: Self::InputItem,
26 ) -> Result<<Self::Inner as Injector>::InputItem, WorkerError>;
27
28 fn push(&self, item: Self::InputItem) -> Result<(), WorkerError> {
29 let item = self.wrap(item)?;
30 self.inner().push(item)
31 }
32}
33
34impl Injector for () {
35 fn inner(&self) -> &Self::Inner {
36 unreachable!()
37 }
38 fn new(_: Self::Inner, _: Self::Context) -> Self {
39 unreachable!()
40 }
41 fn wrap(
42 &self,
43 _: Self::InputItem,
44 ) -> Result<<Self::Inner as Injector>::InputItem, WorkerError> {
45 unreachable!()
46 }
47
48 type Context = ();
49 type Inner = ();
50 type InputItem = ();
51}
52
53pub struct WorkerInjector<T> {
54 pub(super) inner: nucleo::Injector<T>,
55 pub(super) columns: Arc<[Column<T>]>,
56 pub(super) version: u32,
57 pub(super) picker_version: Arc<AtomicU32>,
58}
59
60impl<T: SSS> Injector for WorkerInjector<T> {
61 type InputItem = T;
62 type Inner = ();
63 type Context = Worker<T>;
64
65 fn new(_: Self::Inner, data: Self::Context) -> Self {
66 data.injector()
67 }
68
69 fn inner(&self) -> &Self::Inner {
70 &()
71 }
72
73 fn wrap(
74 &self,
75 _: Self::InputItem,
76 ) -> Result<<Self::Inner as Injector>::InputItem, WorkerError> {
77 Ok(())
78 }
79
80 fn push(&self, item: T) -> Result<(), WorkerError> {
81 if self.version != self.picker_version.load(Ordering::Relaxed) {
82 return Err(WorkerError::InjectorShutdown);
83 }
84 push_impl(&self.inner, &self.columns, item);
85 Ok(())
86 }
87}
88
89pub(super) fn push_impl<T>(injector: &nucleo::Injector<T>, columns: &[Column<T>], item: T) {
90 injector.push(item, |item, dst| {
91 for (column, text) in columns.iter().filter(|column| column.filter).zip(dst) {
92 *text = column.format_text(item).into()
93 }
94 });
95}
96
97pub struct IndexedInjector<T, I: Injector<InputItem = Indexed<T>>> {
100 injector: I,
101 count: Arc<AtomicU32>,
102 input_type: PhantomData<T>,
103}
104
105impl<T, I: Injector<InputItem = Indexed<T>>> Injector for IndexedInjector<T, I> {
106 type InputItem = T;
107 type Inner = I;
108 type Context = u32;
109
110 fn new(injector: Self::Inner, count: Self::Context) -> Self {
111 Self {
112 injector,
113 count: Arc::new(AtomicU32::new(count)),
114 input_type: PhantomData,
115 }
116 }
117
118 fn wrap(
119 &self,
120 item: Self::InputItem,
121 ) -> Result<<Self::Inner as Injector>::InputItem, WorkerError> {
122 let index = self.count.fetch_add(1, Ordering::Relaxed);
123 Ok(Indexed { index, inner: item })
124 }
125
126 fn inner(&self) -> &Self::Inner {
127 &self.injector
128 }
129}
130
131pub struct SegmentedInjector<T: SegmentableItem, I: Injector<InputItem = Segmented<T>>> {
132 injector: I,
133 splitter: SplitterFn<T>,
134 input_type: PhantomData<T>,
135}
136
137impl<T: SegmentableItem, I: Injector<InputItem = Segmented<T>>> Injector
138 for SegmentedInjector<T, I>
139{
140 type InputItem = T;
141 type Inner = I;
142 type Context = SplitterFn<T>;
143
144 fn new(injector: Self::Inner, data: Self::Context) -> Self {
145 Self {
146 injector,
147 splitter: data,
148 input_type: PhantomData,
149 }
150 }
151
152 fn wrap(
153 &self,
154 item: Self::InputItem,
155 ) -> Result<<Self::Inner as Injector>::InputItem, WorkerError> {
156 let ranges = (self.splitter)(&item);
157 Ok(Segmented {
158 inner: item,
159 ranges,
160 })
161 }
162
163 fn inner(&self) -> &Self::Inner {
164 &self.injector
165 }
166
167 fn push(&self, item: Self::InputItem) -> Result<(), WorkerError> {
168 let item = self.wrap(item)?;
169 self.inner().push(item)
170 }
171}
172
173impl<T> Clone for WorkerInjector<T> {
211 fn clone(&self) -> Self {
212 Self {
213 inner: self.inner.clone(),
214 columns: Arc::clone(&self.columns),
215 version: self.version,
216 picker_version: Arc::clone(&self.picker_version),
217 }
218 }
219}
220
221impl<T, I: Injector<InputItem = Indexed<T>>> Clone for IndexedInjector<T, I> {
222 fn clone(&self) -> Self {
223 Self {
224 injector: self.injector.clone(),
225 count: Arc::clone(&self.count),
226 input_type: PhantomData,
227 }
228 }
229}
230
231impl<T: SegmentableItem, I: Injector<InputItem = Segmented<T>>> Clone for SegmentedInjector<T, I> {
232 fn clone(&self) -> Self {
233 Self {
234 injector: self.injector.clone(),
235 splitter: Arc::clone(&self.splitter),
236 input_type: PhantomData,
237 }
238 }
239}