1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! Generate package tracking IDs and render them as barcodes.
//!
//! ```
//! # #[cfg(all(feature = "os-rng", feature = "code128", feature = "png", feature = "svg"))]
//! # fn main() -> Result<(), smart_package_tracker::Error> {
//! use smart_package_tracker::{Barcode, RenderOptions, TrackingId};
//!
//! // 1. Mint an identifier.
//! let id = TrackingId::generate()?; // e.g. PKG-9ED9285C
//!
//! // 2. Encode it as a Code 128 barcode.
//! let barcode = Barcode::code128(&id)?;
//!
//! // 3. Export it.
//! let options = RenderOptions::default(); // 300 dpi, 13 mil, 25 mm tall
//! let png: Vec<u8> = barcode.to_png(&options)?;
//! let svg: String = barcode.to_svg(&options)?;
//!
//! assert_eq!(&png[..8], b"\x89PNG\r\n\x1a\n");
//! assert!(svg.contains("<svg"));
//! # Ok(())
//! # }
//! # #[cfg(not(all(feature = "os-rng", feature = "code128", feature = "png", feature = "svg")))]
//! # fn main() {}
//! ```
//!
//! # Design
//!
//! The pipeline has two independent halves, joined by a dimension-agnostic bit
//! grid:
//!
//! ```text
//! TrackingId ──▶ Symbology::encode ──▶ Symbol ──▶ Renderer::render ──▶ bytes
//! (Code 128 | QR) (BitMatrix) (Png | Svg)
//! ```
//!
//! A linear barcode is a one-row [`BitMatrix`](symbology::BitMatrix); a matrix
//! symbology such as QR is a square one. Because renderers consume the grid
//! rather than the symbology, adding a format means implementing
//! [`Symbology`](symbology::Symbology) and nothing else — QR support landed
//! without a single change to the PNG or SVG renderers.
//!
//! Both renderers share one [`Layout`](render::Layout) calculation, so PNG and
//! SVG output describe identical geometry at identical physical size.
//!
//! Scanning runs the same pipeline backwards, meeting it at the same grid:
//!
//! ```text
//! image ──▶ GrayImage ──▶ binarize ──▶ BitMatrix ──▶ Decoder::decode ──▶ payload
//! ```
//!
//! ```
//! # #[cfg(all(feature = "scan", feature = "png"))]
//! # fn main() -> Result<(), smart_package_tracker::Error> {
//! use smart_package_tracker::{Barcode, RenderOptions, scan};
//!
//! let png = Barcode::code128("PKG-9ED9285C")?.to_png(&RenderOptions::default())?;
//! assert_eq!(scan::scan_png(&png)?.payload(), "PKG-9ED9285C");
//! # Ok(())
//! # }
//! # #[cfg(not(all(feature = "scan", feature = "png")))]
//! # fn main() {}
//! ```
//!
//! See the [`scan`] module for what image conditions that covers, and what it
//! does not.
//!
//! # Choosing an entropy width
//!
//! [`TrackingId::generate`] defaults to 32 bits of randomness — the familiar
//! `PKG-9ED9285C` shape — which collides with ~69% probability once 100,000
//! IDs have been issued. Production systems should configure 64 bits:
//!
//! ```
//! use smart_package_tracker::{Checksum, IdGenerator};
//!
//! let generator = IdGenerator::builder()
//! .entropy_bits(64)
//! .checksum(Checksum::Iso7064Mod37_36)
//! .build()?;
//! # Ok::<(), smart_package_tracker::Error>(())
//! ```
//!
//! See [`IdGenerator`] for the full collision table.
//!
//! # Feature flags
//!
//! | Feature | Default | Effect |
//! |---------|---------|--------|
//! | `std` | yes | File helpers and `std::error::Error`. Without it the crate is `no_std` + `alloc`. |
//! | `os-rng` | yes | Seed IDs from the OS CSPRNG. Turn off on targets `getrandom` does not support; `IdGenerator::generate_from_entropy` still works. |
//! | `code128` | yes | Code 128 encoding and decoding. |
//! | `qr` | yes | QR Code encoding. Implies `std`. |
//! | `png` | yes | PNG rendering. Implies `std`. |
//! | `svg` | yes | SVG rendering. No extra dependencies. |
//! | `scan` | yes | Read Code 128 barcodes back out of images. No extra dependencies; implies `code128`. |
//! | `serde` | no | `Serialize`/`Deserialize` for the public data types. |
//!
//! # Not yet implemented
//!
//! Shipment events and carrier integrations are deliberately absent, and
//! belong in separate crates so that network I/O, async runtimes and vendor
//! licence terms stay out of this dependency graph.
//!
//! Scanning reads linear symbologies only — there is no QR decoder here — and
//! targets rendered labels, flatbed scans and screenshots rather than camera
//! frames. The [`Symbology`](symbology::Symbology),
//! [`Decoder`](symbology::Decoder) and [`Renderer`](render::Renderer) traits
//! are the extension points for new formats.
//!
//! QR Code is a registered trademark of Denso Wave Incorporated.
// The test harness needs `std`, so only apply `no_std` outside of it.
extern crate alloc;
pub use Barcode;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use Code128;
pub use ;