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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! # `hkid_ops` — HKID Toolkit
//!
//! This crate provides parsing, generation, and validation utilities for Hong Kong Identity Cards (HKID).
//!
//! ## HKID Check Digit Algorithm
//!
//! The HKID check digit is calculated using a weighted sum of the HKID body (prefix + 6 digits).
//! Each character is mapped to a numeric value (`A=10`, ..., `Z=35`, `0=0`, ..., `9=9`, space=`36`), then multiplied by a weight.
//!
//! The weights are defined in [`WEIGHTS`](crate::WEIGHTS):
//!
//! ```rust
//! pub const WEIGHTS: [u32; 8] = [9, 8, 7, 6, 5, 4, 3, 2];
//! ```
//!
//! - If the HKID body is 7 characters, it is left-padded with a space.
//! - Each character's value is multiplied by the corresponding weight.
//! - Add up the products, then compute the check digit as `(11 - (sum % 11)) % 11`.
//! - If the result is 10, the check digit is `'A'`; otherwise, it's the digit itself.
//!
//! ---
//!
//! ## Usage Examples
//!
//! ### 1. HKID Symbol Parsing
//!
//! ```rust
//! use hkid_ops::hkid_symbol::HKIDSymbol;
//!
//! let symbols = [
//! "***", "*", "A", "B", "C", "N", "O", "R", "U", "W", "X", "Y", "Z", "H1", "L2", "Unknown"
//! ];
//! for sym in symbols.iter() {
//! let parsed = HKIDSymbol::parse(sym);
//! println!("Input: {:?} => Parsed: {:?}", sym, parsed);
//! }
//! ```
//!
//! ### 2. HKID Prefix Parsing
//!
//! ```rust
//! use crate::hkid_ops::hkid_prefix::HKIDPrefix;
//!
//! let prefixes = [
//! "A", "C", "F", "K", "N", "R", "Z", "EC", "WX", "XA", "Unknown"
//! ];
//! for prefix in prefixes.iter() {
//! let parsed = HKIDPrefix::parse(prefix);
//! println!("Input: {:?} => Parsed: {:?}", prefix, parsed);
//! }
//! ```
//!
//! ### 3. HKID Generation and Validation (Known Prefixes)
//!
//! ```rust
//! use hkid_ops::hkid_ops::HKIDOps;
//!
//! let ops = HKIDOps::new();
//! let gen_prefixes = ["A", "K", "WX", "XA"];
//!
//! for prefix in gen_prefixes.iter() {
//! println!("\nGenerating HKID with prefix '{}':", prefix);
//! match ops.generate_hkid(Some(prefix), true) {
//! Ok(hkid) => {
//! println!("Generated: {}", hkid);
//! // Validate the generated HKID
//! match ops.validate_hkid(&hkid, true) {
//! Ok(valid) => println!(" Validation result: {}", if valid { "Valid" } else { "Invalid" }),
//! Err(e) => println!(" Validation error: {}", e),
//! }
//! }
//! Err(e) => println!("Error: {}", e),
//! }
//! }
//! ```
//!
//! ### 4. HKID Generation Allowing Unknown Prefixes
//!
//! ```rust
//! use hkid_ops::hkid_ops::HKIDOps;
//!
//! let ops = HKIDOps::new();
//! let test_prefixes = ["A", "WX", "ZZ"];
//!
//! for prefix in test_prefixes {
//! println!("Generating HKID with prefix '{}', must_exist_in_enum = true:", prefix);
//! match ops.generate_hkid(Some(prefix), true) {
//! Ok(hkid) => println!(" Generated: {}", hkid),
//! Err(e) => println!(" Error: {}", e),
//! }
//! println!("Generating HKID with prefix '{}', must_exist_in_enum = false:", prefix);
//! match ops.generate_hkid(Some(prefix), false) {
//! Ok(hkid) => println!(" Generated (allowed unknown): {}", hkid),
//! Err(e) => println!(" Error: {}", e),
//! }
//! }
//! ```
//!
//! ### 5. HKID Generation Using a Random Prefix
//!
//! ```rust
//! use hkid_ops::hkid_ops::HKIDOps;
//!
//! let ops = HKIDOps::new();
//!
//! // Random known prefix
//! match ops.generate_hkid(None, true) {
//! Ok(hkid) => {
//! println!("Generated with random known prefix: {}", hkid);
//! match ops.validate_hkid(&hkid, true) {
//! Ok(valid) => println!(" Validation result: {}", if valid { "Valid" } else { "Invalid" }),
//! Err(e) => println!(" Validation error: {}", e),
//! }
//! }
//! Err(e) => println!(" Error: {}", e),
//! }
//!
//! // Random unknown-or-known prefix
//! match ops.generate_hkid(None, false) {
//! Ok(hkid) => {
//! println!("Generated with random any prefix: {}", hkid);
//! match ops.validate_hkid(&hkid, false) {
//! Ok(valid) => println!(" Validation result: {}", if valid { "Valid" } else { "Invalid" }),
//! Err(e) => println!(" Validation error: {}", e),
//! }
//! }
//! Err(e) => println!(" Error: {}", e),
//! }
//! ```
//!
//! ### 6. HKID Validation (Various Samples)
//!
//! ```rust
//! use hkid_ops::hkid_ops::HKIDOps;
//!
//! let ops = HKIDOps::new();
//!
//! let samples = [
//! ("A123456(3)", true), // Valid, known prefix, correct check digit
//! ("AB123456(9)", true), // Valid, known prefix, correct check digit
//! ("ZZ123456(9)", false), // Unknown prefix, but allowed
//! ("A123456(8)", true), // Invalid check digit
//! ("A12345(7)", true), // Invalid length
//! ("A123456(3)", false), // Accept unknown prefix (should be fine)
//! ("PB100001(8)", false), // Valid for unknown prefix
//! ("PB100001(8)", true), // Unknown prefix, must_exist_in_enum
//! ];
//! for (hkid, must_exist) in samples.iter() {
//! println!("Validating HKID '{}', must_exist_in_enum = {}:", hkid, must_exist);
//! match ops.validate_hkid(hkid, *must_exist) {
//! Ok(valid) => println!("{}", if valid { "Valid" } else { "Invalid" }),
//! Err(e) => println!("Error: {}", e),
//! }
//! }
//! ```