Skip to main content

rxing/
rxing_result.rs

1/*
2 * Copyright 2007 ZXing authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use std::{collections::HashMap, fmt};
18
19use crate::{
20    BarcodeFormat, MetadataDictionary, Point, RXingResultMetadataType, RXingResultMetadataValue,
21    common::cpp_essentials::DecoderResult,
22};
23
24pub type RXingResultMetaDataDictionary = HashMap<RXingResultMetadataType, RXingResultMetadataValue>;
25
26#[cfg(feature = "serde")]
27use serde::{Deserialize, Serialize};
28
29/**
30 * <p>Encapsulates the result of decoding a barcode within an image.</p>
31 *
32 * @author Sean Owen
33 */
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35#[derive(Clone, Debug, PartialEq, Eq)]
36pub struct RXingResult {
37    text: String,
38    rawBytes: Vec<u8>,
39    numBits: usize,
40    resultPoints: Vec<Point>,
41    format: BarcodeFormat,
42    resultMetadata: RXingResultMetaDataDictionary,
43    timestamp: u128,
44    line_count: usize,
45}
46impl RXingResult {
47    pub fn new(
48        text: &str,
49        rawBytes: Vec<u8>,
50        resultPoints: Vec<Point>,
51        format: BarcodeFormat,
52    ) -> Self {
53        Self::new_timestamp(
54            text,
55            rawBytes,
56            resultPoints,
57            format,
58            chrono::Utc::now().timestamp_millis() as u128,
59        )
60    }
61
62    pub fn new_timestamp(
63        text: &str,
64        rawBytes: Vec<u8>,
65        resultPoints: Vec<Point>,
66        format: BarcodeFormat,
67        timestamp: u128,
68    ) -> Self {
69        let l = rawBytes.len();
70        Self::new_complex(text, rawBytes, 8 * l, resultPoints, format, timestamp)
71    }
72
73    pub fn new_complex(
74        text: &str,
75        rawBytes: Vec<u8>,
76        numBits: usize,
77        resultPoints: Vec<Point>,
78        format: BarcodeFormat,
79        timestamp: u128,
80    ) -> Self {
81        Self {
82            text: text.to_owned(),
83            rawBytes,
84            numBits,
85            resultPoints,
86            format,
87            resultMetadata: HashMap::new(),
88            timestamp,
89            line_count: 0,
90        }
91    }
92
93    pub fn with_point(self, points: Vec<Point>) -> Self {
94        Self {
95            text: self.text,
96            rawBytes: self.rawBytes,
97            numBits: self.numBits,
98            resultPoints: points,
99            format: self.format,
100            resultMetadata: self.resultMetadata,
101            timestamp: self.timestamp,
102            line_count: self.line_count,
103        }
104    }
105
106    pub fn with_decoder_result<T>(
107        res: DecoderResult<T>,
108        resultPoints: &[Point],
109        format: BarcodeFormat,
110    ) -> Self
111    where
112        T: Copy + Clone + Default + Eq + PartialEq,
113    {
114        let mut new_res = Self::new(
115            &res.text(),
116            res.content().bytes().to_vec(),
117            resultPoints.to_vec(),
118            format,
119        );
120
121        let mut meta_data = MetadataDictionary::new();
122        meta_data.insert(
123            RXingResultMetadataType::ERROR_CORRECTION_LEVEL,
124            RXingResultMetadataValue::ErrorCorrectionLevel(res.ecLevel().to_owned()),
125        );
126        meta_data.insert(
127            RXingResultMetadataType::STRUCTURED_APPEND_PARITY,
128            RXingResultMetadataValue::StructuredAppendParity(res.structuredAppend().count),
129        );
130        meta_data.insert(
131            RXingResultMetadataType::STRUCTURED_APPEND_SEQUENCE,
132            RXingResultMetadataValue::StructuredAppendSequence(res.structuredAppend().index),
133        );
134        meta_data.insert(
135            RXingResultMetadataType::SYMBOLOGY_IDENTIFIER,
136            RXingResultMetadataValue::SymbologyIdentifier(res.symbologyIdentifier()),
137        );
138
139        new_res.putAllMetadata(meta_data);
140
141        new_res
142    }
143
144    /**
145     * @return raw text encoded by the barcode
146     */
147    pub fn getText(&self) -> &str {
148        &self.text
149    }
150
151    /**
152     * @return raw bytes encoded by the barcode, if applicable, otherwise {@code null}
153     */
154    pub fn getRawBytes(&self) -> &[u8] {
155        &self.rawBytes
156    }
157
158    /**
159     * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length
160     * @since 3.3.0
161     */
162    pub fn getNumBits(&self) -> usize {
163        self.numBits
164    }
165
166    /**
167     * @return points related to the barcode in the image. These are typically points
168     *         identifying finder patterns or the corners of the barcode. The exact meaning is
169     *         specific to the type of barcode that was decoded.
170     */
171    pub fn getPoints(&self) -> &[Point] {
172        &self.resultPoints
173    }
174
175    pub fn getPointsMut(&mut self) -> &mut [Point] {
176        &mut self.resultPoints
177    }
178
179    /** Currently necessary because the external OneDReader proc macro uses it. */
180    pub fn getRXingResultPoints(&self) -> &[Point] {
181        &self.resultPoints
182    }
183
184    /** Currently necessary because the external OneDReader proc macro uses it. */
185    pub fn getRXingResultPointsMut(&mut self) -> &mut [Point] {
186        &mut self.resultPoints
187    }
188
189    /**
190     * @return {@link BarcodeFormat} representing the format of the barcode that was decoded
191     */
192    pub fn getBarcodeFormat(&self) -> &BarcodeFormat {
193        &self.format
194    }
195
196    /**
197     * @return {@link Map} mapping {@link RXingResultMetadataType} keys to values. May be
198     *   {@code null}. This contains optional metadata about what was detected about the barcode,
199     *   like orientation.
200     */
201    pub fn getRXingResultMetadata(&self) -> &RXingResultMetaDataDictionary {
202        &self.resultMetadata
203    }
204
205    pub fn putMetadata(
206        &mut self,
207        md_type: RXingResultMetadataType,
208        value: RXingResultMetadataValue,
209    ) {
210        self.resultMetadata.insert(md_type, value);
211    }
212
213    pub fn putAllMetadata(&mut self, metadata: RXingResultMetaDataDictionary) {
214        if self.resultMetadata.is_empty() {
215            let _ = std::mem::replace(&mut self.resultMetadata, metadata);
216        } else {
217            for (key, value) in metadata.into_iter() {
218                self.resultMetadata.insert(key, value);
219            }
220        }
221    }
222
223    pub fn addPoints(&mut self, newPoints: &mut Vec<Point>) {
224        if !newPoints.is_empty() {
225            self.resultPoints.append(newPoints);
226        }
227    }
228
229    pub fn getTimestamp(&self) -> u128 {
230        self.timestamp
231    }
232
233    pub fn line_count(&self) -> usize {
234        self.line_count
235    }
236
237    pub fn set_line_count(&mut self, lc: usize) {
238        self.line_count = lc
239    }
240
241    pub fn replace_points(&mut self, points: Vec<Point>) {
242        self.resultPoints = points
243    }
244}
245
246impl fmt::Display for RXingResult {
247    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248        write!(f, "{}", self.text)
249    }
250}