use super::{ image::Image, symbol::{Symbol, SymbolType}, sys, Config, }; #[derive(thiserror::Error, Debug)] pub enum ImageScannerError { #[error("Unable to set Image Scanner configuration")] UnableToSetConfig, } pub struct ImageScanner { inner: *mut sys::zbar_image_scanner_t, } impl ImageScanner { /// Link: [`sys::zbar_image_scanner_create`] pub fn new() -> Self { Self { inner: unsafe { sys::zbar_image_scanner_create() }, } } /// Link: [`sys::zbar_image_scanner_set_config`] pub fn set_config( &mut self, symbol: SymbolType, config: Config, value: i32, ) -> Result<(), ImageScannerError> { let result = unsafe { sys::zbar_image_scanner_set_config(self.inner, symbol, config, value) }; if result != 0 { return Err(ImageScannerError::UnableToSetConfig); } Ok(()) } /// Link: [`sys::zbar_scan_image`] /// /// TODO: move `image` to newtype, offering conversions /// to and from image::Image /// /// TODO: return an iterator over scanned values pub fn scan_image( &mut self, image: &Image, ) -> Vec { unsafe { sys::zbar_scan_image(self.inner, image.inner) }; let mut result = vec![]; let mut symbol = unsafe { sys::zbar_image_first_symbol(image.inner) }; while !symbol.is_null() { let symbol_type = unsafe { sys::zbar_symbol_get_type(symbol) }; let symbol_data = unsafe { sys::zbar_symbol_get_data(symbol) }; let symbol_data_len = unsafe { sys::zbar_symbol_get_data_length(symbol) }; let symbol_slice = unsafe { std::slice::from_raw_parts(symbol_data as *const u8, symbol_data_len as usize) }; result.push(Symbol::new(symbol_type, symbol_slice)); symbol = unsafe { sys::zbar_symbol_next(symbol) }; } result } } impl Default for ImageScanner { fn default() -> Self { Self::new() } } impl Drop for ImageScanner { fn drop(&mut self) { unsafe { sys::zbar_image_scanner_destroy(self.inner) } } }