1use std::path::{Path, PathBuf};
4
5use crate::registration::{HomographicAlignment, TranslationalAlignment};
6
7pub type RequestProgressHandler = fn(f64);
10
11#[derive(Debug, Clone, Copy, Default)]
13pub struct RequestProgress {
14 progress_handler: Option<RequestProgressHandler>,
15 indeterminate: bool,
16}
17
18impl RequestProgress {
19 #[must_use]
20 pub const fn new() -> Self {
21 Self {
22 progress_handler: None,
23 indeterminate: false,
24 }
25 }
26
27 #[must_use]
28 pub const fn with_progress_handler(mut self, progress_handler: RequestProgressHandler) -> Self {
29 self.progress_handler = Some(progress_handler);
30 self
31 }
32
33 #[must_use]
34 pub const fn with_indeterminate(mut self, indeterminate: bool) -> Self {
35 self.indeterminate = indeterminate;
36 self
37 }
38
39 #[must_use]
40 pub const fn progress_handler(&self) -> Option<RequestProgressHandler> {
41 self.progress_handler
42 }
43
44 #[must_use]
45 pub const fn is_indeterminate(&self) -> bool {
46 self.indeterminate
47 }
48}
49
50pub trait RequestProgressProviding {
52 fn progress_handler(&self) -> Option<RequestProgressHandler>;
53 fn is_indeterminate(&self) -> bool;
54}
55
56impl RequestProgressProviding for RequestProgress {
57 fn progress_handler(&self) -> Option<RequestProgressHandler> {
58 self.progress_handler()
59 }
60
61 fn is_indeterminate(&self) -> bool {
62 self.is_indeterminate()
63 }
64}
65
66pub trait RequestRevisionProviding {
68 fn request_revision(&self) -> Option<usize>;
69}
70
71#[derive(Debug, Clone, Copy, PartialEq)]
73pub struct NormalizedRect {
74 pub x: f64,
75 pub y: f64,
76 pub width: f64,
77 pub height: f64,
78}
79
80impl NormalizedRect {
81 #[must_use]
82 pub const fn new(x: f64, y: f64, width: f64, height: f64) -> Self {
83 Self {
84 x,
85 y,
86 width,
87 height,
88 }
89 }
90}
91
92#[derive(Debug, Clone, PartialEq, Default)]
94pub struct ImageBasedRequest {
95 region_of_interest: Option<NormalizedRect>,
96 prefer_background_processing: bool,
97 uses_cpu_only: bool,
98 revision: Option<usize>,
99}
100
101impl ImageBasedRequest {
102 #[must_use]
103 pub const fn new() -> Self {
104 Self {
105 region_of_interest: None,
106 prefer_background_processing: false,
107 uses_cpu_only: false,
108 revision: None,
109 }
110 }
111
112 #[must_use]
113 pub const fn with_region_of_interest(mut self, region_of_interest: NormalizedRect) -> Self {
114 self.region_of_interest = Some(region_of_interest);
115 self
116 }
117
118 #[must_use]
119 pub const fn with_prefer_background_processing(mut self, enabled: bool) -> Self {
120 self.prefer_background_processing = enabled;
121 self
122 }
123
124 #[must_use]
125 pub const fn with_uses_cpu_only(mut self, enabled: bool) -> Self {
126 self.uses_cpu_only = enabled;
127 self
128 }
129
130 #[must_use]
131 pub const fn with_revision(mut self, revision: usize) -> Self {
132 self.revision = Some(revision);
133 self
134 }
135
136 #[must_use]
137 pub const fn region_of_interest(&self) -> Option<NormalizedRect> {
138 self.region_of_interest
139 }
140
141 #[must_use]
142 pub const fn prefer_background_processing(&self) -> bool {
143 self.prefer_background_processing
144 }
145
146 #[must_use]
147 pub const fn uses_cpu_only(&self) -> bool {
148 self.uses_cpu_only
149 }
150
151 #[must_use]
152 pub const fn revision(&self) -> Option<usize> {
153 self.revision
154 }
155}
156
157impl RequestRevisionProviding for ImageBasedRequest {
158 fn request_revision(&self) -> Option<usize> {
159 self.revision()
160 }
161}
162
163#[derive(Debug, Clone, PartialEq, Eq)]
165pub struct TargetedImageRequest {
166 targeted_image_path: PathBuf,
167}
168
169impl TargetedImageRequest {
170 #[must_use]
171 pub fn new(targeted_image_path: impl AsRef<Path>) -> Self {
172 Self {
173 targeted_image_path: targeted_image_path.as_ref().to_path_buf(),
174 }
175 }
176
177 #[must_use]
178 pub fn targeted_image_path(&self) -> &Path {
179 &self.targeted_image_path
180 }
181}
182
183impl RequestRevisionProviding for TargetedImageRequest {
184 fn request_revision(&self) -> Option<usize> {
185 None
186 }
187}
188
189#[derive(Debug, Clone, Copy, PartialEq)]
191pub struct StatefulRequest {
192 frame_analysis_spacing_seconds: Option<f64>,
193 minimum_latency_frame_count: usize,
194}
195
196impl Default for StatefulRequest {
197 fn default() -> Self {
198 Self::new()
199 }
200}
201
202impl StatefulRequest {
203 #[must_use]
204 pub const fn new() -> Self {
205 Self {
206 frame_analysis_spacing_seconds: None,
207 minimum_latency_frame_count: 0,
208 }
209 }
210
211 #[must_use]
212 pub const fn with_frame_analysis_spacing_seconds(mut self, seconds: f64) -> Self {
213 self.frame_analysis_spacing_seconds = Some(seconds);
214 self
215 }
216
217 #[must_use]
218 pub const fn with_minimum_latency_frame_count(mut self, frame_count: usize) -> Self {
219 self.minimum_latency_frame_count = frame_count;
220 self
221 }
222
223 #[must_use]
224 pub const fn frame_analysis_spacing_seconds(&self) -> Option<f64> {
225 self.frame_analysis_spacing_seconds
226 }
227
228 #[must_use]
229 pub const fn minimum_latency_frame_count(&self) -> usize {
230 self.minimum_latency_frame_count
231 }
232}
233
234impl RequestRevisionProviding for StatefulRequest {
235 fn request_revision(&self) -> Option<usize> {
236 None
237 }
238}
239
240#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
242pub enum TrackingLevel {
243 Accurate,
244 Fast,
245}
246
247#[derive(Debug, Clone, PartialEq)]
249pub struct TrackingRequest {
250 tracking_level: TrackingLevel,
251 last_frame: bool,
252 input_observation: Option<NormalizedRect>,
253}
254
255impl Default for TrackingRequest {
256 fn default() -> Self {
257 Self::new()
258 }
259}
260
261impl TrackingRequest {
262 #[must_use]
263 pub const fn new() -> Self {
264 Self {
265 tracking_level: TrackingLevel::Fast,
266 last_frame: false,
267 input_observation: None,
268 }
269 }
270
271 #[must_use]
272 pub const fn with_tracking_level(mut self, tracking_level: TrackingLevel) -> Self {
273 self.tracking_level = tracking_level;
274 self
275 }
276
277 #[must_use]
278 pub const fn with_last_frame(mut self, last_frame: bool) -> Self {
279 self.last_frame = last_frame;
280 self
281 }
282
283 #[must_use]
284 pub const fn with_input_observation(mut self, input_observation: NormalizedRect) -> Self {
285 self.input_observation = Some(input_observation);
286 self
287 }
288
289 #[must_use]
290 pub const fn tracking_level(&self) -> TrackingLevel {
291 self.tracking_level
292 }
293
294 #[must_use]
295 pub const fn is_last_frame(&self) -> bool {
296 self.last_frame
297 }
298
299 #[must_use]
300 pub const fn input_observation(&self) -> Option<NormalizedRect> {
301 self.input_observation
302 }
303}
304
305impl RequestRevisionProviding for TrackingRequest {
306 fn request_revision(&self) -> Option<usize> {
307 None
308 }
309}
310
311#[derive(Debug, Clone, PartialEq, Eq)]
313pub struct ImageRegistrationRequest {
314 targeted_image: TargetedImageRequest,
315}
316
317impl ImageRegistrationRequest {
318 #[must_use]
319 pub fn new(targeted_image_path: impl AsRef<Path>) -> Self {
320 Self {
321 targeted_image: TargetedImageRequest::new(targeted_image_path),
322 }
323 }
324
325 #[must_use]
326 pub const fn from_targeted_image_request(targeted_image: TargetedImageRequest) -> Self {
327 Self { targeted_image }
328 }
329
330 #[must_use]
331 pub const fn targeted_image_request(&self) -> &TargetedImageRequest {
332 &self.targeted_image
333 }
334}
335
336impl RequestRevisionProviding for ImageRegistrationRequest {
337 fn request_revision(&self) -> Option<usize> {
338 RequestRevisionProviding::request_revision(&self.targeted_image)
339 }
340}
341
342#[derive(Debug, Clone, Copy, PartialEq)]
344pub enum ImageAlignmentObservation {
345 Translational(TranslationalAlignment),
346 Homographic(HomographicAlignment),
347}
348
349impl ImageAlignmentObservation {
350 #[must_use]
351 pub const fn translational(alignment: TranslationalAlignment) -> Self {
352 Self::Translational(alignment)
353 }
354
355 #[must_use]
356 pub const fn homographic(alignment: HomographicAlignment) -> Self {
357 Self::Homographic(alignment)
358 }
359}
360
361#[derive(Debug, Clone, PartialEq, Eq)]
363pub struct PixelBufferObservation {
364 pub width: usize,
365 pub height: usize,
366 pub bytes_per_row: usize,
367 pub bytes: Vec<u8>,
368 pub feature_name: Option<String>,
369}
370
371impl PixelBufferObservation {
372 #[must_use]
373 pub const fn new(width: usize, height: usize, bytes_per_row: usize, bytes: Vec<u8>) -> Self {
374 Self {
375 width,
376 height,
377 bytes_per_row,
378 bytes,
379 feature_name: None,
380 }
381 }
382
383 #[must_use]
384 pub fn with_feature_name(mut self, feature_name: impl Into<String>) -> Self {
385 self.feature_name = Some(feature_name.into());
386 self
387 }
388
389 #[must_use]
390 pub fn as_bytes(&self) -> &[u8] {
391 &self.bytes
392 }
393}