use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dimension {
Linear,
Postal,
Stacked,
Matrix,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
#[repr(u8)]
pub enum Symbology {
QrCode = 0,
MicroQrCode = 1,
RectMicroQrCode = 2,
Aztec = 3,
AztecRunes = 4,
DataMatrix = 5,
MaxiCode = 6,
HanXin = 7,
DotCode = 8,
GridMatrix = 9,
AppClipCode = 51,
Pdf417 = 10,
MicroPdf417 = 11,
Code16k = 12,
Code49 = 13,
CodablockF = 14,
Ean13 = 15,
Ean8 = 16,
UpcA = 17,
UpcE = 18,
Ean2 = 19,
Ean5 = 20,
Code128 = 21,
Gs1_128 = 22,
Code39 = 23,
Code93 = 24,
Code11 = 25,
Itf = 26,
Std2of5 = 27,
Iata2of5 = 28,
Matrix2of5 = 29,
Codabar = 30,
MsiPlessey = 31,
Plessey = 32,
Telepen = 33,
Pharmacode = 34,
PharmacodeTwoTrack = 35,
DxFilmEdge = 36,
DataBarOmni = 37,
DataBarStacked = 38,
DataBarStackedOmni = 39,
DataBarLimited = 40,
DataBarExpanded = 41,
DataBarExpandedStacked = 42,
Postnet = 43,
Planet = 44,
IntelligentMail = 45,
RoyalMail = 46,
Mailmark = 47,
AustraliaPost = 48,
JapanPost = 49,
KixCode = 50,
}
impl Symbology {
pub const ALL: &'static [Symbology] = {
use Symbology::*;
&[
QrCode,
MicroQrCode,
RectMicroQrCode,
Aztec,
AztecRunes,
DataMatrix,
MaxiCode,
HanXin,
DotCode,
GridMatrix,
AppClipCode,
Pdf417,
MicroPdf417,
Code16k,
Code49,
CodablockF,
Ean13,
Ean8,
UpcA,
UpcE,
Ean2,
Ean5,
Code128,
Gs1_128,
Code39,
Code93,
Code11,
Itf,
Std2of5,
Iata2of5,
Matrix2of5,
Codabar,
MsiPlessey,
Plessey,
Telepen,
Pharmacode,
PharmacodeTwoTrack,
DxFilmEdge,
DataBarOmni,
DataBarStacked,
DataBarStackedOmni,
DataBarLimited,
DataBarExpanded,
DataBarExpandedStacked,
Postnet,
Planet,
IntelligentMail,
RoyalMail,
Mailmark,
AustraliaPost,
JapanPost,
KixCode,
]
};
pub fn dimension(self) -> Dimension {
use Symbology::*;
match self {
QrCode | MicroQrCode | RectMicroQrCode | Aztec | AztecRunes | DataMatrix | MaxiCode
| HanXin | DotCode | GridMatrix | AppClipCode => Dimension::Matrix,
Pdf417
| MicroPdf417
| Code16k
| Code49
| CodablockF
| DataBarStacked
| DataBarStackedOmni
| DataBarExpandedStacked => Dimension::Stacked,
Postnet | Planet | IntelligentMail | RoyalMail | Mailmark | AustraliaPost
| JapanPost | KixCode => Dimension::Postal,
_ => Dimension::Linear,
}
}
pub fn is_implemented(self) -> bool {
use Symbology::*;
if self == AppClipCode {
return cfg!(feature = "appclip");
}
matches!(
self,
QrCode
| MicroQrCode
| RectMicroQrCode
| Aztec
| AztecRunes
| HanXin
| DotCode
| GridMatrix
| DataMatrix
| MaxiCode
| Pdf417
| MicroPdf417
| Code128
| Gs1_128
| Code39
| Code93
| Code11
| Ean13
| Ean8
| UpcA
| UpcE
| Ean2
| Ean5
| Itf
| Std2of5
| Iata2of5
| Matrix2of5
| Codabar
| MsiPlessey
| Plessey
| Telepen
| Pharmacode
| PharmacodeTwoTrack
| DataBarOmni
| DataBarLimited
| DataBarExpanded
| DataBarStacked
| DataBarStackedOmni
| DataBarExpandedStacked
| Code16k
| Code49
| CodablockF
| Postnet
| Planet
| IntelligentMail
| RoyalMail
| KixCode
| Mailmark
| AustraliaPost
| JapanPost
| DxFilmEdge
)
}
pub fn name(self) -> &'static str {
use Symbology::*;
match self {
QrCode => "QR Code",
MicroQrCode => "Micro QR Code",
RectMicroQrCode => "Rectangular Micro QR Code",
Aztec => "Aztec",
AztecRunes => "Aztec Runes",
DataMatrix => "Data Matrix",
MaxiCode => "MaxiCode",
HanXin => "Han Xin",
DotCode => "DotCode",
GridMatrix => "Grid Matrix",
AppClipCode => "App Clip Code",
Pdf417 => "PDF417",
MicroPdf417 => "MicroPDF417",
Code16k => "Code 16K",
Code49 => "Code 49",
CodablockF => "Codablock F",
Ean13 => "EAN-13",
Ean8 => "EAN-8",
UpcA => "UPC-A",
UpcE => "UPC-E",
Ean2 => "EAN-2 (add-on)",
Ean5 => "EAN-5 (add-on)",
Code128 => "Code 128",
Gs1_128 => "GS1-128",
Code39 => "Code 39",
Code93 => "Code 93",
Code11 => "Code 11",
Itf => "Interleaved 2 of 5",
Std2of5 => "Standard 2 of 5",
Iata2of5 => "IATA 2 of 5",
Matrix2of5 => "Matrix 2 of 5",
Codabar => "Codabar",
MsiPlessey => "MSI Plessey",
Plessey => "Plessey",
Telepen => "Telepen",
Pharmacode => "Pharmacode",
PharmacodeTwoTrack => "Pharmacode Two-Track",
DxFilmEdge => "DX Film Edge",
DataBarOmni => "GS1 DataBar Omnidirectional",
DataBarStacked => "GS1 DataBar Stacked",
DataBarStackedOmni => "GS1 DataBar Stacked Omnidirectional",
DataBarLimited => "GS1 DataBar Limited",
DataBarExpanded => "GS1 DataBar Expanded",
DataBarExpandedStacked => "GS1 DataBar Expanded Stacked",
Postnet => "POSTNET",
Planet => "PLANET",
IntelligentMail => "Intelligent Mail",
RoyalMail => "Royal Mail 4-State (RM4SCC)",
Mailmark => "Royal Mail Mailmark",
AustraliaPost => "Australia Post 4-State",
JapanPost => "Japan Post 4-State",
KixCode => "Dutch KIX",
}
}
}
impl fmt::Display for Symbology {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[test]
fn catalog_is_coherent() {
let mut names = HashSet::new();
for &s in Symbology::ALL {
assert!(!s.name().is_empty(), "{s:?} has an empty name");
assert!(names.insert(s.name()), "duplicate name: {}", s.name());
let _ = s.dimension();
}
assert!(Symbology::QrCode.is_implemented());
assert!(Symbology::ALL.iter().any(|s| s.is_implemented()));
}
#[test]
fn discriminants_are_stable() {
use Symbology::*;
for (sym, id) in [
(QrCode, 0u8),
(GridMatrix, 9),
(Pdf417, 10),
(CodablockF, 14),
(Ean13, 15),
(Code128, 21),
(Code39, 23),
(Itf, 26),
(Codabar, 30),
(DxFilmEdge, 36),
(DataBarOmni, 37),
(Postnet, 43),
(KixCode, 50),
(AppClipCode, 51),
] {
assert_eq!(sym as u8, id, "{sym:?} renumbered");
}
let mut seen = std::collections::HashSet::new();
for &s in Symbology::ALL {
assert!(seen.insert(s as u8), "duplicate discriminant for {s:?}");
}
assert_eq!(seen.len(), Symbology::ALL.len());
}
}