1#![allow(unknown_lints)] #![allow(unused_unsafe)]
8#![allow(clippy::useless_transmute)]
9#![allow(clippy::redundant_closure_call)]
10#![allow(clippy::missing_transmute_annotations)] mod tests;
13
14#[allow(dead_code)]
15#[allow(non_camel_case_types)]
16#[allow(non_snake_case)]
17#[allow(non_upper_case_globals)]
18mod bindings {
19 include!("bindings.rs");
20}
21
22use bindings::*;
23
24use paste::paste;
25use std::ffi::{c_char, c_int, c_void, CStr, CString, NulError};
26use std::fmt::{Display, Formatter};
27use std::marker::PhantomData;
28use std::mem::transmute;
29use std::ptr::null;
30use std::rc::Rc;
31use std::slice;
32use thiserror::Error;
33
34#[derive(Error, Debug)]
35pub enum Error {
36 #[error("{0}")]
37 InvalidInput(String),
38
39 #[error("NulError from CString::new")]
40 NulError(#[from] NulError),
41 }
54
55impl From<std::convert::Infallible> for Error {
57 fn from(_: std::convert::Infallible) -> Self {
58 unreachable!()
59 }
60}
61
62fn c2r_str(str: *mut c_char) -> String {
63 let mut res = String::new();
64 if !str.is_null() {
65 unsafe { res = CStr::from_ptr(str).to_string_lossy().to_string() };
66 unsafe { ZXing_free(str as *mut c_void) };
67 }
68 res
69}
70
71fn c2r_vec(buf: *mut u8, len: c_int) -> Vec<u8> {
72 let mut res = Vec::<u8>::new();
73 if !buf.is_null() && len > 0 {
74 unsafe { res = std::slice::from_raw_parts(buf, len as usize).to_vec() };
75 unsafe { ZXing_free(buf as *mut c_void) };
76 }
77 res
78}
79
80fn last_error() -> Error {
81 match unsafe { ZXing_LastErrorMsg().as_mut() } {
82 None => panic!("Internal error: ZXing_LastErrorMsg() returned NULL"),
83 Some(error) => Error::InvalidInput(c2r_str(error)),
84 }
85}
86
87macro_rules! last_error_or {
90 ($expr:expr) => {
91 match unsafe { ZXing_LastErrorMsg().as_mut() } {
92 None => Ok($expr),
93 Some(error) => Err(Error::InvalidInput(c2r_str(error))),
94 }
95 };
96}
97
98macro_rules! last_error_if_null_or {
99 ($ptr:ident, $expr:expr) => {
100 match $ptr.is_null() {
101 true => Err(last_error()),
102 false => Ok($expr),
103 }
104 };
105}
106
107macro_rules! make_zxing_class {
108 ($r_class:ident, $c_class:ident) => {
109 paste! {
110 pub struct $r_class(*mut $c_class);
111
112 impl Drop for $r_class {
113 fn drop(&mut self) {
114 unsafe { [<$c_class _delete>](self.0) }
115 }
116 }
117 }
118 };
119}
120
121macro_rules! make_zxing_class_with_default {
122 ($r_class:ident, $c_class:ident) => {
123 make_zxing_class!($r_class, $c_class);
124 paste! {
125 impl $r_class {
126 pub fn new() -> Self {
127 unsafe { $r_class([<$c_class _new>]()) }
128 }
129 }
130
131 impl Default for $r_class {
132 fn default() -> Self {
133 Self::new()
134 }
135 }
136 }
137 };
138}
139
140macro_rules! getter {
141 ($class:ident, $c_name:ident, $r_name:ident, $conv:expr, $type:ty) => {
142 pub fn $r_name(&self) -> $type {
143 paste! { unsafe { $conv([<ZXing_ $class _ $c_name>](self.0)) } }
144 }
145 };
146 ($class:ident, $c_name:ident, $conv:expr, $type:ty) => {
147 paste! { getter! { $class, $c_name, [<$c_name:snake>], $conv, $type } }
148 };
149}
150
151macro_rules! property {
159 ($class:ident, $c_name:ident, $r_name:ident, String) => {
160 pub fn $r_name(self, v: impl AsRef<str>) -> Self {
161 let cstr = CString::new(v.as_ref()).unwrap();
162 paste! { unsafe { [<ZXing_ $class _set $c_name>](self.0, cstr.as_ptr()) } };
163 self
164 }
165
166 paste! {
167 pub fn [<set_ $r_name>](&mut self, v : impl AsRef<str>) -> &mut Self {
168 let cstr = CString::new(v.as_ref()).unwrap();
169 unsafe { [<ZXing_ $class _set $c_name>](self.0, cstr.as_ptr()) };
170 self
171 }
172
173 pub fn [<get_ $r_name>](&self) -> String {
174 unsafe { c2r_str([<ZXing_ $class _get $c_name>](self.0)) }
175 }
176 }
177 };
178
179 ($class:ident, $c_name:ident, $r_name:ident, $type:ty) => {
180 pub fn $r_name(self, v: impl Into<$type>) -> Self {
181 paste! { unsafe { [<ZXing_ $class _set $c_name>](self.0, transmute(v.into())) } };
182 self
183 }
184
185 paste! {
186 pub fn [<set_ $r_name>](&mut self, v : impl Into<$type>) -> &mut Self {
187 unsafe { [<ZXing_ $class _set $c_name>](self.0, transmute(v.into())) };
188 self
189 }
190
191 pub fn [<get_ $r_name>](&self) -> $type {
192 unsafe { transmute([<ZXing_ $class _get $c_name>](self.0)) }
193 }
194 }
195 };
196
197 ($class:ident, $c_name:ident, $type:ty) => {
198 paste! { property! { $class, $c_name, [<$c_name:snake>], $type } }
199 };
200}
201
202macro_rules! make_zxing_enum {
203 ($name:ident { $($field:ident),* }) => {
204 #[repr(u32)]
205 #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
206 pub enum $name {
207 $($field = paste! { [<ZXing_ $name _ $field>] },)*
208 }
209 }
210}
211
212#[rustfmt::skip] make_zxing_enum!(ImageFormat { Lum, LumA, RGB, BGR, RGBA, ARGB, BGRA, ABGR });
216#[rustfmt::skip]
217make_zxing_enum!(ContentType { Text, Binary, Mixed, GS1, ISO15434, UnknownECI });
218#[rustfmt::skip]
219make_zxing_enum!(Binarizer { LocalAverage, GlobalHistogram, FixedThreshold, BoolCast });
220#[rustfmt::skip]
221make_zxing_enum!(TextMode { Plain, ECI, HRI, Escaped, Hex, HexECI });
222#[rustfmt::skip]
223make_zxing_enum!(EanAddOnSymbol { Ignore, Read, Require });
224
225#[rustfmt::skip]
226make_zxing_enum!(BarcodeFormat {
227 Invalid, None, All, AllReadable, AllCreatable, AllLinear, AllMatrix, AllGS1,
228 Codabar, Code39, PZN, Code93, Code128, ITF,
229 DataBar, DataBarOmni, DataBarStk, DataBarStkOmni, DataBarLtd, DataBarExp, DataBarExpStk,
230 EANUPC, EAN13, EAN8, EAN5, EAN2, ISBN, UPCA, UPCE,
231 Telepen, TelepenAlpha, TelepenNumeric, OtherBarcode, DXFilmEdge,
232 PDF417, CompactPDF417, MicroPDF417,
233 Aztec, AztecCode, AztecRune,
234 QRCode, QRCodeModel1, QRCodeModel2, MicroQRCode, RMQRCode,
235 DataMatrix, MaxiCode
236});
237
238impl Display for BarcodeFormat {
239 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
240 write!(f, "{}", unsafe { c2r_str(ZXing_BarcodeFormatToString(transmute(*self))) })
241 }
242}
243
244impl Display for ContentType {
245 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
246 write!(f, "{}", unsafe { c2r_str(ZXing_ContentTypeToString(transmute(*self))) })
247 }
248}
249
250impl BarcodeFormat {
251 pub fn symbology(self) -> BarcodeFormat {
252 unsafe { transmute(ZXing_BarcodeFormatSymbology(transmute(self))) }
253 }
254}
255
256#[derive(Clone, Debug, Default)]
259pub struct BarcodeFormats(pub Vec<BarcodeFormat>);
260
261impl BarcodeFormats {
262 pub fn as_slice(&self) -> &[BarcodeFormat] {
263 &self.0
264 }
265 pub fn is_empty(&self) -> bool {
266 self.0.is_empty()
267 }
268 pub fn len(&self) -> usize {
269 self.0.len()
270 }
271 pub fn contains(&self, f: BarcodeFormat) -> bool {
272 self.0.contains(&f)
273 }
274 pub fn iter(&self) -> std::slice::Iter<'_, BarcodeFormat> {
275 self.0.iter()
276 }
277
278 pub fn list(filter: BarcodeFormat) -> Self {
279 unsafe {
280 let mut size: c_int = 0;
281 let ptr = ZXing_BarcodeFormatsList(transmute(filter), &mut size) as *const BarcodeFormat;
282 if ptr.is_null() || size == 0 {
283 BarcodeFormats::default()
284 } else {
285 BarcodeFormats(slice::from_raw_parts(ptr, size as usize).to_vec())
286 }
287 }
288 }
289}
290
291impl PartialEq<[BarcodeFormat]> for BarcodeFormats {
292 fn eq(&self, other: &[BarcodeFormat]) -> bool {
293 self.0.as_slice() == other
294 }
295}
296
297impl PartialEq<BarcodeFormats> for [BarcodeFormat] {
298 fn eq(&self, other: &BarcodeFormats) -> bool {
299 self == other.0.as_slice()
300 }
301}
302
303impl Display for BarcodeFormats {
304 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
305 write!(f, "{}", unsafe {
306 c2r_str(ZXing_BarcodeFormatsToString(transmute(self.0.as_ptr()), self.0.len() as c_int))
307 })
308 }
309}
310
311impl From<Vec<BarcodeFormat>> for BarcodeFormats {
318 fn from(v: Vec<BarcodeFormat>) -> Self {
319 BarcodeFormats(v)
320 }
321}
322impl From<&[BarcodeFormat]> for BarcodeFormats {
323 fn from(s: &[BarcodeFormat]) -> Self {
324 BarcodeFormats(s.to_vec())
325 }
326}
327
328impl AsRef<[BarcodeFormat]> for BarcodeFormats {
329 fn as_ref(&self) -> &[BarcodeFormat] {
330 &self.0
331 }
332}
333
334impl AsRef<[BarcodeFormat]> for BarcodeFormat {
335 fn as_ref(&self) -> &[BarcodeFormat] {
336 std::slice::from_ref(self)
337 }
338}
339
340pub trait FromStr: Sized {
341 fn from_str(str: impl AsRef<str>) -> Result<Self, Error>;
342}
343
344impl FromStr for BarcodeFormat {
345 fn from_str(str: impl AsRef<str>) -> Result<BarcodeFormat, Error> {
346 let cstr = CString::new(str.as_ref())?;
347 let fmt = unsafe { ZXing_BarcodeFormatFromString(cstr.as_ptr()) };
348 if fmt == ZXing_BarcodeFormat_Invalid {
349 last_error_or!(BarcodeFormat::Invalid)
350 } else {
351 Ok(unsafe { transmute(fmt) })
352 }
353 }
354}
355
356impl FromStr for BarcodeFormats {
357 fn from_str(str: impl AsRef<str>) -> Result<BarcodeFormats, Error> {
358 let cstr = CString::new(str.as_ref())?;
359 let mut size: c_int = 0;
360 let ptr = unsafe { ZXing_BarcodeFormatsFromString(cstr.as_ptr(), &mut size) as *const BarcodeFormat };
361 if ptr.is_null() || size == 0 {
362 last_error_or!(BarcodeFormats::default())
363 } else {
364 Ok(BarcodeFormats(unsafe { slice::from_raw_parts(ptr, size as usize).to_vec() }))
365 }
366 }
367}
368
369#[derive(Debug, PartialEq)]
372struct ImageViewOwner<'a>(*mut ZXing_ImageView, PhantomData<&'a u8>);
373
374impl Drop for ImageViewOwner<'_> {
375 fn drop(&mut self) {
376 unsafe { ZXing_ImageView_delete(self.0) }
377 }
378}
379#[derive(Debug, Clone, PartialEq)]
380pub struct ImageView<'a>(Rc<ImageViewOwner<'a>>);
381
382impl<'a> From<&'a ImageView<'a>> for ImageView<'a> {
383 fn from(img: &'a ImageView) -> Self {
384 img.clone()
385 }
386}
387
388impl<'a> ImageView<'a> {
389 fn try_into_int<T: TryInto<c_int>>(val: T) -> Result<c_int, Error> {
390 val.try_into().map_err(|_| Error::InvalidInput("Could not convert Integer into c_int.".to_string()))
391 }
392
393 pub unsafe fn from_ptr<T: TryInto<c_int>, U: TryInto<c_int>>(
403 ptr: *const u8,
404 width: T,
405 height: T,
406 format: ImageFormat,
407 row_stride: U,
408 pix_stride: U,
409 ) -> Result<Self, Error> {
410 let iv = ZXing_ImageView_new(
411 ptr,
412 Self::try_into_int(width)?,
413 Self::try_into_int(height)?,
414 format as ZXing_ImageFormat,
415 Self::try_into_int(row_stride)?,
416 Self::try_into_int(pix_stride)?,
417 );
418 last_error_if_null_or!(iv, ImageView(Rc::new(ImageViewOwner(iv, PhantomData))))
419 }
420
421 pub fn from_slice<T: TryInto<c_int>>(data: &'a [u8], width: T, height: T, format: ImageFormat) -> Result<Self, Error> {
422 unsafe {
423 let iv = ZXing_ImageView_new_checked(
424 data.as_ptr(),
425 data.len() as c_int,
426 Self::try_into_int(width)?,
427 Self::try_into_int(height)?,
428 format as ZXing_ImageFormat,
429 0,
430 0,
431 );
432 last_error_if_null_or!(iv, ImageView(Rc::new(ImageViewOwner(iv, PhantomData))))
433 }
434 }
435
436 pub fn cropped(self, left: i32, top: i32, width: i32, height: i32) -> Self {
437 unsafe { ZXing_ImageView_crop((self.0).0, left, top, width, height) }
438 self
439 }
440
441 pub fn rotated(self, degree: i32) -> Self {
442 unsafe { ZXing_ImageView_rotate((self.0).0, degree) }
443 self
444 }
445}
446
447#[cfg(feature = "image")]
448use image;
449
450#[cfg(feature = "image")]
451impl<'a> From<&'a image::GrayImage> for ImageView<'a> {
452 fn from(img: &'a image::GrayImage) -> Self {
453 ImageView::from_slice(img.as_ref(), img.width(), img.height(), ImageFormat::Lum).unwrap()
454 }
455}
456
457#[cfg(feature = "image")]
458impl<'a> TryFrom<&'a image::DynamicImage> for ImageView<'a> {
459 type Error = Error;
460
461 fn try_from(img: &'a image::DynamicImage) -> Result<Self, Error> {
462 let format = match img {
463 image::DynamicImage::ImageLuma8(_) => Some(ImageFormat::Lum),
464 image::DynamicImage::ImageLumaA8(_) => Some(ImageFormat::LumA),
465 image::DynamicImage::ImageRgb8(_) => Some(ImageFormat::RGB),
466 image::DynamicImage::ImageRgba8(_) => Some(ImageFormat::RGBA),
467 _ => None,
468 };
469 match format {
470 Some(format) => Ok(ImageView::from_slice(img.as_bytes(), img.width(), img.height(), format)?),
471 None => Err(Error::InvalidInput("Invalid image format (must be either luma8|lumaA8|rgb8|rgba8)".to_string())),
472 }
473 }
474}
475
476make_zxing_class!(Image, ZXing_Image);
479
480impl Image {
481 getter!(Image, width, transmute, i32);
482 getter!(Image, height, transmute, i32);
483 getter!(Image, format, transmute, ImageFormat);
484
485 pub fn data(&self) -> Vec<u8> {
486 let ptr = unsafe { ZXing_Image_data(self.0) };
487 if ptr.is_null() {
488 Vec::<u8>::new()
489 } else {
490 unsafe { std::slice::from_raw_parts(ptr, (self.width() * self.height()) as usize).to_vec() }
491 }
492 }
493}
494
495#[cfg(feature = "image")]
496impl From<&Image> for image::GrayImage {
497 fn from(img: &Image) -> image::GrayImage {
498 image::GrayImage::from_vec(img.width() as u32, img.height() as u32, img.data()).unwrap()
499 }
500}
501
502#[derive(Error, Debug, PartialEq)]
503pub enum BarcodeError {
504 #[error("")]
505 None(),
506
507 #[error("{0}")]
508 Checksum(String),
509
510 #[error("{0}")]
511 Format(String),
512
513 #[error("{0}")]
514 Unsupported(String),
515}
516
517pub type PointI = ZXing_PointI;
520#[repr(C)]
521#[derive(Debug, Copy, Clone)]
522pub struct Position {
523 pub top_left: PointI,
524 pub top_right: PointI,
525 pub bottom_right: PointI,
526 pub bottom_left: PointI,
527}
528
529impl Display for PointI {
530 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
531 write!(f, "{}x{}", self.x, self.y)
532 }
533}
534
535impl Display for Position {
536 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
537 write!(f, "{}", unsafe {
538 c2r_str(ZXing_PositionToString(*(self as *const Position as *const ZXing_Position)))
539 })
540 }
541}
542
543make_zxing_class!(Barcode, ZXing_Barcode);
546
547impl Barcode {
548 getter!(Barcode, isValid, transmute, bool);
549 getter!(Barcode, format, transmute, BarcodeFormat);
550 getter!(Barcode, symbology, transmute, BarcodeFormat);
551 getter!(Barcode, contentType, transmute, ContentType);
552 getter!(Barcode, text, c2r_str, String);
553 getter!(Barcode, symbologyIdentifier, c2r_str, String);
554 getter!(Barcode, position, transmute, Position);
555 getter!(Barcode, orientation, transmute, i32);
556 getter!(Barcode, hasECI, has_eci, transmute, bool);
557 getter!(Barcode, isInverted, transmute, bool);
558 getter!(Barcode, isMirrored, transmute, bool);
559 getter!(Barcode, lineCount, transmute, i32);
560 getter!(Barcode, sequenceSize, transmute, i32);
561 getter!(Barcode, sequenceIndex, transmute, i32);
562 getter!(Barcode, sequenceId, c2r_str, String);
563
564 pub fn bytes(&self) -> Vec<u8> {
565 let mut len: c_int = 0;
566 unsafe { c2r_vec(ZXing_Barcode_bytes(self.0, &mut len), len) }
567 }
568 pub fn bytes_eci(&self) -> Vec<u8> {
569 let mut len: c_int = 0;
570 unsafe { c2r_vec(ZXing_Barcode_bytesECI(self.0, &mut len), len) }
571 }
572
573 pub fn extra(&self) -> String {
574 unsafe { c2r_str(ZXing_Barcode_extra(self.0, null())) }
575 }
576
577 pub fn extra_with_key(&self, key: impl AsRef<str>) -> String {
578 let cstr = CString::new(key.as_ref()).unwrap();
579 unsafe { c2r_str(ZXing_Barcode_extra(self.0, cstr.as_ptr())) }
580 }
581
582 pub fn error(&self) -> BarcodeError {
583 let error_type = unsafe { ZXing_Barcode_errorType(self.0) };
584 let error_msg = unsafe { c2r_str(ZXing_Barcode_errorMsg(self.0)) };
585 #[allow(non_upper_case_globals)]
586 match error_type {
587 ZXing_ErrorType_None => BarcodeError::None(),
588 ZXing_ErrorType_Format => BarcodeError::Format(error_msg),
589 ZXing_ErrorType_Checksum => BarcodeError::Checksum(error_msg),
590 ZXing_ErrorType_Unsupported => BarcodeError::Unsupported(error_msg),
591 _ => panic!("Internal error: invalid ZXing_ErrorType"),
592 }
593 }
594
595 pub fn to_svg_with(&self, opts: &BarcodeWriter) -> Result<String, Error> {
596 let str = unsafe { ZXing_WriteBarcodeToSVG(self.0, opts.0) };
597 last_error_if_null_or!(str, c2r_str(str))
598 }
599
600 pub fn to_svg(&self) -> Result<String, Error> {
601 self.to_svg_with(&BarcodeWriter::default())
602 }
603
604 pub fn to_image_with(&self, opts: &BarcodeWriter) -> Result<Image, Error> {
605 let img = unsafe { ZXing_WriteBarcodeToImage(self.0, opts.0) };
606 last_error_if_null_or!(img, Image(img))
607 }
608
609 pub fn to_image(&self) -> Result<Image, Error> {
610 self.to_image_with(&BarcodeWriter::default())
611 }
612}
613
614make_zxing_class_with_default!(BarcodeReader, ZXing_ReaderOptions);
617
618impl BarcodeReader {
619 property!(ReaderOptions, TryHarder, bool);
620 property!(ReaderOptions, TryRotate, bool);
621 property!(ReaderOptions, TryInvert, bool);
622 property!(ReaderOptions, TryDownscale, bool);
623 property!(ReaderOptions, IsPure, bool);
624 property!(ReaderOptions, ValidateOptionalChecksum, bool);
625 property!(ReaderOptions, ReturnErrors, bool);
626 property!(ReaderOptions, Binarizer, Binarizer);
627 property!(ReaderOptions, EanAddOnSymbol, EanAddOnSymbol);
628 property!(ReaderOptions, TextMode, TextMode);
629 property!(ReaderOptions, MinLineCount, i32);
630 property!(ReaderOptions, MaxNumberOfSymbols, i32);
631
632 pub fn formats(self, v: impl AsRef<[BarcodeFormat]>) -> Self {
633 unsafe { ZXing_ReaderOptions_setFormats(self.0, transmute(v.as_ref().as_ptr()), v.as_ref().len() as c_int) };
634 self
635 }
636
637 pub fn set_formats(&mut self, v: impl AsRef<[BarcodeFormat]>) -> &mut Self {
638 unsafe { ZXing_ReaderOptions_setFormats(self.0, transmute(v.as_ref().as_ptr()), v.as_ref().len() as c_int) };
639 self
640 }
641
642 pub fn get_formats(&self) -> BarcodeFormats {
643 unsafe {
644 let mut size: c_int = 0;
645 let ptr = ZXing_ReaderOptions_getFormats(self.0, &mut size) as *const BarcodeFormat;
646 if ptr.is_null() || size == 0 {
647 BarcodeFormats::default()
648 } else {
649 BarcodeFormats(slice::from_raw_parts(ptr, size as usize).to_vec())
650 }
651 }
652 }
653
654 pub fn from<'a, IV>(&self, image: IV) -> Result<Vec<Barcode>, Error>
655 where
656 IV: TryInto<ImageView<'a>>,
657 IV::Error: Into<Error>,
658 {
659 let iv_: ImageView = image.try_into().map_err(Into::into)?;
660 unsafe {
661 let results = ZXing_ReadBarcodes((iv_.0).0, self.0);
662 if !results.is_null() {
663 let size = ZXing_Barcodes_size(results);
664 let mut vec = Vec::<Barcode>::with_capacity(size as usize);
665 for i in 0..size {
666 vec.push(Barcode(ZXing_Barcodes_move(results, i)));
667 }
668 ZXing_Barcodes_delete(results);
669 Ok(vec)
670 } else {
671 Err(last_error())
672 }
673 }
674 }
675}
676
677make_zxing_class!(BarcodeCreator, ZXing_CreatorOptions);
680
681impl BarcodeCreator {
682 pub fn new(format: BarcodeFormat) -> Self {
683 unsafe { BarcodeCreator(ZXing_CreatorOptions_new(format as ZXing_BarcodeFormat)) }
684 }
685
686 property!(CreatorOptions, Options, String);
687
688 pub fn from_str(&self, str: impl AsRef<str>) -> Result<Barcode, Error> {
689 let cstr = CString::new(str.as_ref())?;
690 let bc = unsafe { ZXing_CreateBarcodeFromText(cstr.as_ptr(), 0, self.0) };
691 last_error_if_null_or!(bc, Barcode(bc))
692 }
693
694 pub fn from_slice(&self, data: impl AsRef<[u8]>) -> Result<Barcode, Error> {
695 let data = data.as_ref();
696 let bc = unsafe { ZXing_CreateBarcodeFromBytes(data.as_ptr() as *const c_void, data.len() as i32, self.0) };
697 last_error_if_null_or!(bc, Barcode(bc))
698 }
699}
700
701make_zxing_class_with_default!(BarcodeWriter, ZXing_WriterOptions);
704
705impl BarcodeWriter {
706 property!(WriterOptions, Scale, i32);
707 property!(WriterOptions, Rotate, i32);
708 property!(WriterOptions, AddHRT, add_hrt, bool);
709 property!(WriterOptions, AddQuietZones, bool);
710}
711
712pub fn read() -> BarcodeReader {
715 BarcodeReader::default()
716}
717
718pub fn create(format: BarcodeFormat) -> BarcodeCreator {
719 BarcodeCreator::new(format)
720}
721
722pub fn write() -> BarcodeWriter {
723 BarcodeWriter::default()
724}