fission_shell_winit/
barcode.rs1use fission_core::{
2 BarcodeFormat, BarcodeImageDecodeRequest, BarcodePoint, BarcodeScanRequest, BarcodeScanResult,
3 BarcodeScanResults, BarcodeScannerError, CANCEL_BARCODE_SCAN, DECODE_BARCODE_IMAGE,
4 SCAN_BARCODE,
5};
6use fission_shell::async_host::AsyncRegistry;
7use std::sync::Arc;
8
9pub trait BarcodeScannerHost: Send + Sync + 'static {
11 fn scan(&self, request: BarcodeScanRequest) -> Result<BarcodeScanResults, BarcodeScannerError>;
13 fn decode_image(
15 &self,
16 request: BarcodeImageDecodeRequest,
17 ) -> Result<BarcodeScanResults, BarcodeScannerError>;
18 fn cancel_scan(&self) -> Result<(), BarcodeScannerError>;
20}
21
22#[derive(Debug, Default)]
23pub struct UnsupportedBarcodeScannerHost;
24
25impl BarcodeScannerHost for UnsupportedBarcodeScannerHost {
26 fn scan(
27 &self,
28 _request: BarcodeScanRequest,
29 ) -> Result<BarcodeScanResults, BarcodeScannerError> {
30 Err(BarcodeScannerError::unsupported("scan"))
31 }
32
33 fn decode_image(
34 &self,
35 _request: BarcodeImageDecodeRequest,
36 ) -> Result<BarcodeScanResults, BarcodeScannerError> {
37 Err(BarcodeScannerError::unsupported("decode_image"))
38 }
39
40 fn cancel_scan(&self) -> Result<(), BarcodeScannerError> {
41 Err(BarcodeScannerError::unsupported("cancel_scan"))
42 }
43}
44
45#[derive(Debug, Clone)]
46pub struct MemoryBarcodeScannerHost {
47 results: BarcodeScanResults,
48}
49
50impl MemoryBarcodeScannerHost {
51 pub fn new(results: BarcodeScanResults) -> Self {
52 Self { results }
53 }
54}
55
56impl Default for MemoryBarcodeScannerHost {
57 fn default() -> Self {
58 Self {
59 results: BarcodeScanResults {
60 items: vec![BarcodeScanResult {
61 value: "fission://barcode/memory".into(),
62 format: BarcodeFormat::QrCode,
63 raw_bytes: b"fission://barcode/memory".to_vec(),
64 bounds: vec![
65 BarcodePoint { x: 0, y: 0 },
66 BarcodePoint { x: 64, y: 0 },
67 BarcodePoint { x: 64, y: 64 },
68 BarcodePoint { x: 0, y: 64 },
69 ],
70 symbology_identifier: None,
71 }],
72 },
73 }
74 }
75}
76
77impl BarcodeScannerHost for MemoryBarcodeScannerHost {
78 fn scan(
79 &self,
80 _request: BarcodeScanRequest,
81 ) -> Result<BarcodeScanResults, BarcodeScannerError> {
82 Ok(self.results.clone())
83 }
84
85 fn decode_image(
86 &self,
87 _request: BarcodeImageDecodeRequest,
88 ) -> Result<BarcodeScanResults, BarcodeScannerError> {
89 Ok(self.results.clone())
90 }
91
92 fn cancel_scan(&self) -> Result<(), BarcodeScannerError> {
93 Ok(())
94 }
95}
96
97pub(crate) fn register_barcode_scanner_capabilities(
98 async_registry: &mut AsyncRegistry,
99 host: Arc<dyn BarcodeScannerHost>,
100) {
101 let scan_host = host.clone();
102 async_registry.register_operation_capability(SCAN_BARCODE, move |request, _| {
103 let host = scan_host.clone();
104 async move { host.scan(request) }
105 });
106
107 let decode_host = host.clone();
108 async_registry.register_operation_capability(DECODE_BARCODE_IMAGE, move |request, _| {
109 let host = decode_host.clone();
110 async move { host.decode_image(request) }
111 });
112
113 async_registry.register_operation_capability(CANCEL_BARCODE_SCAN, move |(), _| {
114 let host = host.clone();
115 async move { host.cancel_scan() }
116 });
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn unsupported_host_reports_errors() {
125 let host = UnsupportedBarcodeScannerHost;
126 assert!(host.scan(BarcodeScanRequest::default()).is_err());
127 assert!(host
128 .decode_image(BarcodeImageDecodeRequest::default())
129 .is_err());
130 }
131
132 #[test]
133 fn memory_host_scans_and_decodes() {
134 let host = MemoryBarcodeScannerHost::default();
135 let scan = host.scan(BarcodeScanRequest::default()).unwrap();
136 let decode = host
137 .decode_image(BarcodeImageDecodeRequest::default())
138 .unwrap();
139 assert_eq!(scan, decode);
140 assert_eq!(scan.items[0].format, BarcodeFormat::QrCode);
141 }
142}