Skip to main content

smart_package_tracker/
lib.rs

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