1use std::{
5 fmt::{self, Display, Formatter},
6 marker::PhantomData,
7 sync::{
8 Arc,
9 atomic::{AtomicU32, Ordering},
10 },
11};
12
13use super::worker::{Column, Worker, WorkerError};
14use crate::{PickerItem, SegmentableItem, nucleo::variants::ColumnIndexable};
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: PickerItem, 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
100#[derive(Debug, Clone, Hash, Eq, PartialEq)]
102pub struct Segmented<T: SegmentableItem> {
103 pub inner: T,
104 ranges: Arc<[(usize, usize)]>,
105}
106
107impl<T: SegmentableItem> ColumnIndexable for Segmented<T> {
108 fn index(&self, index: usize) -> &str {
109 if let Some((start, end)) = self.ranges.get(index) {
110 &self.inner[*start..*end]
111 } else {
112 ""
113 }
114 }
115}
116
117impl<T: Display + SegmentableItem> Display for Segmented<T> {
118 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
119 write!(f, "{}", self.inner)
120 }
121}
122
123impl<T: Display> Display for Indexed<T> {
124 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
125 write!(f, "{}", self.inner)
126 }
127}
128
129#[derive(Debug, Clone, Hash, Eq, PartialEq)]
130pub struct Indexed<T> {
131 pub index: u32,
132 pub inner: T,
133}
134
135impl<T: Clone> Indexed<T> {
136 pub fn identifier(&self) -> (u32, T) {
137 (self.index, self.inner.clone())
138 }
139}
140
141impl<T: ColumnIndexable> ColumnIndexable for Indexed<T> {
142 fn index(&self, index: usize) -> &str {
143 self.inner.index(index)
144 }
145}
146
147pub struct IndexedInjector<T, I: Injector<InputItem = Indexed<T>>> {
150 injector: I,
151 count: Arc<AtomicU32>,
152 input_type: PhantomData<T>,
153}
154
155impl<T, I: Injector<InputItem = Indexed<T>>> Injector for IndexedInjector<T, I> {
156 type InputItem = T;
157 type Inner = I;
158 type Context = ();
159
160 fn new(injector: Self::Inner, _data: Self::Context) -> Self {
161 Self {
162 injector,
163 count: Arc::new(AtomicU32::new(0)),
164 input_type: PhantomData,
165 }
166 }
167
168 fn wrap(
169 &self,
170 item: Self::InputItem,
171 ) -> Result<<Self::Inner as Injector>::InputItem, WorkerError> {
172 let index = self.count.fetch_add(1, Ordering::Relaxed);
173 Ok(Indexed { index, inner: item })
174 }
175
176 fn inner(&self) -> &Self::Inner {
177 &self.injector
178 }
179}
180
181pub struct SegmentedInjector<T: SegmentableItem, I: Injector<InputItem = Segmented<T>>> {
182 injector: I,
183 splitter: Arc<dyn Fn(&T) -> Vec<(usize, usize)> + Send + Sync + 'static>,
184 input_type: PhantomData<T>,
185}
186
187impl<T: SegmentableItem, I: Injector<InputItem = Segmented<T>>> Injector
188 for SegmentedInjector<T, I>
189{
190 type InputItem = T;
191 type Inner = I;
192 type Context = Arc<dyn Fn(&T) -> Vec<(usize, usize)> + Send + Sync + 'static>;
193
194 fn new(injector: Self::Inner, data: Self::Context) -> Self {
195 Self {
196 injector,
197 splitter: data,
198 input_type: PhantomData,
199 }
200 }
201
202 fn wrap(
203 &self,
204 item: Self::InputItem,
205 ) -> Result<<Self::Inner as Injector>::InputItem, WorkerError> {
206 let ranges = Arc::from((self.splitter)(&item).into_boxed_slice());
207 Ok(Segmented {
208 inner: item,
209 ranges,
210 })
211 }
212
213 fn inner(&self) -> &Self::Inner {
214 &self.injector
215 }
216}
217
218
219impl<T, C> Clone for WorkerInjector<T, C> {
221 fn clone(&self) -> Self {
222 Self {
223 inner: self.inner.clone(),
224 columns: Arc::clone(&self.columns),
225 context: Arc::clone(&self.context),
226 version: self.version,
227 picker_version: Arc::clone(&self.picker_version),
228 }
229 }
230}
231
232impl<T, I: Injector<InputItem = Indexed<T>>> Clone for IndexedInjector<T, I> {
233 fn clone(&self) -> Self {
234 Self {
235 injector: self.injector.clone(),
236 count: Arc::clone(&self.count),
237 input_type: PhantomData,
238 }
239 }
240}
241
242impl<T: SegmentableItem, I: Injector<InputItem = Segmented<T>>> Clone for SegmentedInjector<T, I> {
243 fn clone(&self) -> Self {
244 Self {
245 injector: self.injector.clone(),
246 splitter: Arc::clone(&self.splitter),
247 input_type: PhantomData,
248 }
249 }
250}