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