1use 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::{MMItem, 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, C = ()> {
54 pub(super) inner: nucleo::Injector<T>,
55 pub(super) columns: Arc<[Column<T, C>]>,
56 pub(super) context: Arc<C>,
57 pub(super) version: u32,
58 pub(super) picker_version: Arc<AtomicU32>,
59}
60
61
62
63impl<T: MMItem, C> Injector for WorkerInjector<T, C> {
64 type InputItem = T;
65 type Inner = ();
66 type Context = Worker<T, C>;
67
68 fn new(_: Self::Inner, data: Self::Context) -> Self {
69 data.injector()
70 }
71
72 fn inner(&self) -> &Self::Inner {
73 &()
74 }
75
76 fn wrap(
77 &self,
78 _: Self::InputItem,
79 ) -> Result<<Self::Inner as Injector>::InputItem, WorkerError> {
80 Ok(())
81 }
82
83 fn push(&self, item: T) -> Result<(), WorkerError> {
84 if self.version != self.picker_version.load(Ordering::Relaxed) {
85 return Err(WorkerError::InjectorShutdown);
86 }
87 push_impl(&self.inner, &self.columns, item, &self.context);
88 Ok(())
89 }
90}
91
92pub(super) fn push_impl<T, C>(injector: &nucleo::Injector<T>, columns: &[Column<T, C>], item: T, context: &C) {
93 injector.push(item, |item, dst| {
94 for (column, text) in columns.iter().filter(|column| column.filter).zip(dst) {
95 *text = column.format_text(item, context).into()
96 }
97 });
98}
99
100pub struct IndexedInjector<T, I: Injector<InputItem = Indexed<T>>> {
103 injector: I,
104 count: Arc<AtomicU32>,
105 input_type: PhantomData<T>,
106}
107
108impl<T, I: Injector<InputItem = Indexed<T>>> Injector for IndexedInjector<T, I> {
109 type InputItem = T;
110 type Inner = I;
111 type Context = ();
112
113 fn new(injector: Self::Inner, _data: Self::Context) -> Self {
114 Self {
115 injector,
116 count: Arc::new(AtomicU32::new(0)),
117 input_type: PhantomData,
118 }
119 }
120
121 fn wrap(
122 &self,
123 item: Self::InputItem,
124 ) -> Result<<Self::Inner as Injector>::InputItem, WorkerError> {
125 let index = self.count.fetch_add(1, Ordering::Relaxed);
126 Ok(Indexed { index, inner: item })
127 }
128
129 fn inner(&self) -> &Self::Inner {
130 &self.injector
131 }
132}
133
134
135pub struct SegmentedInjector<T: SegmentableItem, I: Injector<InputItem = Segmented<T>>> {
136 injector: I,
137 splitter: SplitterFn<T>,
138 input_type: PhantomData<T>,
139}
140
141impl<T: SegmentableItem, I: Injector<InputItem = Segmented<T>>> Injector
142 for SegmentedInjector<T, I>
143{
144 type InputItem = T;
145 type Inner = I;
146 type Context = SplitterFn<T>;
147
148 fn new(injector: Self::Inner, data: Self::Context) -> Self {
149 Self {
150 injector,
151 splitter: data,
152 input_type: PhantomData,
153 }
154 }
155
156 fn wrap(
157 &self,
158 item: Self::InputItem,
159 ) -> Result<<Self::Inner as Injector>::InputItem, WorkerError> {
160 let ranges = Arc::from((self.splitter)(&item).into_boxed_slice());
161 Ok(Segmented {
162 inner: item,
163 ranges,
164 })
165 }
166
167 fn inner(&self) -> &Self::Inner {
168 &self.injector
169 }
170
171 fn push(&self, item: Self::InputItem) -> Result<(), WorkerError> {
172 let item = self.wrap(item)?;
173 self.inner().push(item)
174 }
175}
176
177
178impl<T, C> Clone for WorkerInjector<T, C> {
180 fn clone(&self) -> Self {
181 Self {
182 inner: self.inner.clone(),
183 columns: Arc::clone(&self.columns),
184 context: Arc::clone(&self.context),
185 version: self.version,
186 picker_version: Arc::clone(&self.picker_version),
187 }
188 }
189}
190
191impl<T, I: Injector<InputItem = Indexed<T>>> Clone for IndexedInjector<T, I> {
192 fn clone(&self) -> Self {
193 Self {
194 injector: self.injector.clone(),
195 count: Arc::clone(&self.count),
196 input_type: PhantomData,
197 }
198 }
199}
200
201impl<T: SegmentableItem, I: Injector<InputItem = Segmented<T>>> Clone for SegmentedInjector<T, I> {
202 fn clone(&self) -> Self {
203 Self {
204 injector: self.injector.clone(),
205 splitter: Arc::clone(&self.splitter),
206 input_type: PhantomData,
207 }
208 }
209}