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
//! 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.
//!
//! # 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. |
//! | `serde` | no | `Serialize`/`Deserialize` for the public data types. |
//!
//! # Not yet implemented
//!
//! Image scanning, shipment events, and carrier integrations are deliberately
//! absent. The [`Symbology`](symbology::Symbology) and
//! [`Renderer`](render::Renderer) traits are the extension points for new
//! formats; carrier integrations belong in separate crates, so that network
//! I/O and vendor licence terms stay out of this dependency graph.
//!
//! 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 Code128;
pub use ;