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