1#![cfg_attr(not(feature = "std"), no_std)]
7
8#[repr(u8)]
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum DataType {
12 Numeric = 0,
14 Alpha = 1,
16 Alphanumeric = 2,
18 AlphanumericSpecial = 3,
20 Binary = 4,
22 Track2 = 5,
24 Track3 = 6,
26}
27
28#[repr(u8)]
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum LengthType {
32 Fixed = 0,
34 Llvar = 1,
36 Lllvar = 2,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42pub struct FieldDefinition {
43 pub data_type: DataType,
45 pub length_type: LengthType,
47 pub max_len: u16,
49}
50
51impl FieldDefinition {
52 #[inline]
54 pub const fn new(data_type: DataType, length_type: LengthType, max_len: u16) -> Self {
55 Self {
56 data_type,
57 length_type,
58 max_len,
59 }
60 }
61
62 #[inline]
64 pub const fn fixed(data_type: DataType, len: u16) -> Self {
65 Self::new(data_type, LengthType::Fixed, len)
66 }
67
68 #[inline]
70 pub const fn llvar(data_type: DataType, max_len: u16) -> Self {
71 Self::new(data_type, LengthType::Llvar, max_len)
72 }
73
74 #[inline]
76 pub const fn lllvar(data_type: DataType, max_len: u16) -> Self {
77 Self::new(data_type, LengthType::Lllvar, max_len)
78 }
79}
80
81macro_rules! iso_table {
83 ($($field:expr => $def:expr),* $(,)?) => {{
84 let mut table: [Option<FieldDefinition>; 129] = [None; 129];
85 $(
86 table[$field] = Some($def);
87 )*
88 table
89 }};
90}
91
92pub const ISO8583_1987_TABLE: [Option<FieldDefinition>; 129] = iso_table! {
97 1 => FieldDefinition::fixed(DataType::Binary, 8),
99
100 2 => FieldDefinition::llvar(DataType::Numeric, 19),
102
103 3 => FieldDefinition::fixed(DataType::Numeric, 6),
105
106 4 => FieldDefinition::fixed(DataType::Numeric, 12),
108
109 5 => FieldDefinition::fixed(DataType::Numeric, 12),
111
112 6 => FieldDefinition::fixed(DataType::Numeric, 12),
114
115 7 => FieldDefinition::fixed(DataType::Numeric, 10),
117
118 8 => FieldDefinition::fixed(DataType::Numeric, 8),
120
121 9 => FieldDefinition::fixed(DataType::Numeric, 8),
123
124 10 => FieldDefinition::fixed(DataType::Numeric, 8),
126
127 11 => FieldDefinition::fixed(DataType::Numeric, 6),
129
130 12 => FieldDefinition::fixed(DataType::Numeric, 6),
132
133 13 => FieldDefinition::fixed(DataType::Numeric, 4),
135
136 14 => FieldDefinition::fixed(DataType::Numeric, 4),
138
139 15 => FieldDefinition::fixed(DataType::Numeric, 4),
141
142 16 => FieldDefinition::fixed(DataType::Numeric, 4),
144
145 17 => FieldDefinition::fixed(DataType::Numeric, 4),
147
148 18 => FieldDefinition::fixed(DataType::Numeric, 4),
150
151 19 => FieldDefinition::fixed(DataType::Numeric, 3),
153
154 20 => FieldDefinition::fixed(DataType::Numeric, 3),
156
157 21 => FieldDefinition::fixed(DataType::Numeric, 3),
159
160 22 => FieldDefinition::fixed(DataType::Numeric, 3),
162
163 23 => FieldDefinition::fixed(DataType::Numeric, 3),
165
166 24 => FieldDefinition::fixed(DataType::Numeric, 3),
168
169 25 => FieldDefinition::fixed(DataType::Numeric, 2),
171
172 26 => FieldDefinition::fixed(DataType::Numeric, 2),
174
175 27 => FieldDefinition::fixed(DataType::Numeric, 1),
177
178 28 => FieldDefinition::fixed(DataType::Numeric, 9),
180
181 29 => FieldDefinition::fixed(DataType::Numeric, 9),
183
184 30 => FieldDefinition::fixed(DataType::Numeric, 9),
186
187 31 => FieldDefinition::fixed(DataType::Numeric, 9),
189
190 32 => FieldDefinition::llvar(DataType::Numeric, 11),
192
193 33 => FieldDefinition::llvar(DataType::Numeric, 11),
195
196 34 => FieldDefinition::llvar(DataType::Alphanumeric, 28),
198
199 35 => FieldDefinition::llvar(DataType::Track2, 37),
201
202 36 => FieldDefinition::lllvar(DataType::Track3, 104),
204
205 37 => FieldDefinition::fixed(DataType::Alphanumeric, 12),
207
208 38 => FieldDefinition::fixed(DataType::Alphanumeric, 6),
210
211 39 => FieldDefinition::fixed(DataType::Alphanumeric, 2),
213
214 40 => FieldDefinition::fixed(DataType::Alphanumeric, 3),
216
217 41 => FieldDefinition::fixed(DataType::AlphanumericSpecial, 8),
219
220 42 => FieldDefinition::fixed(DataType::AlphanumericSpecial, 15),
222
223 43 => FieldDefinition::fixed(DataType::AlphanumericSpecial, 40),
225
226 44 => FieldDefinition::llvar(DataType::AlphanumericSpecial, 25),
228
229 45 => FieldDefinition::llvar(DataType::AlphanumericSpecial, 76),
231
232 46 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
234
235 47 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
237
238 48 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
240
241 49 => FieldDefinition::fixed(DataType::Alphanumeric, 3),
243
244 50 => FieldDefinition::fixed(DataType::Alphanumeric, 3),
246
247 51 => FieldDefinition::fixed(DataType::Alphanumeric, 3),
249
250 52 => FieldDefinition::fixed(DataType::Binary, 8),
252
253 53 => FieldDefinition::fixed(DataType::Numeric, 16),
255
256 54 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 120),
258
259 55 => FieldDefinition::lllvar(DataType::Binary, 999),
261
262 56 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
264 57 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
265 58 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
266 59 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
267 60 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
268 61 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
269 62 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
270 63 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
271
272 64 => FieldDefinition::fixed(DataType::Binary, 8),
274
275 65 => FieldDefinition::fixed(DataType::Binary, 8),
277
278 66 => FieldDefinition::fixed(DataType::Numeric, 1),
280 67 => FieldDefinition::fixed(DataType::Numeric, 2),
281 68 => FieldDefinition::fixed(DataType::Numeric, 3),
282 69 => FieldDefinition::fixed(DataType::Numeric, 3),
283 70 => FieldDefinition::fixed(DataType::Numeric, 3),
284 71 => FieldDefinition::fixed(DataType::Numeric, 4),
285 72 => FieldDefinition::fixed(DataType::Numeric, 4),
286 73 => FieldDefinition::fixed(DataType::Numeric, 6),
287 74 => FieldDefinition::fixed(DataType::Numeric, 10),
288 75 => FieldDefinition::fixed(DataType::Numeric, 10),
289 76 => FieldDefinition::fixed(DataType::Numeric, 10),
290 77 => FieldDefinition::fixed(DataType::Numeric, 10),
291 78 => FieldDefinition::fixed(DataType::Numeric, 10),
292 79 => FieldDefinition::fixed(DataType::Numeric, 10),
293 80 => FieldDefinition::fixed(DataType::Numeric, 10),
294 81 => FieldDefinition::fixed(DataType::Numeric, 10),
295 82 => FieldDefinition::fixed(DataType::Numeric, 12),
296 83 => FieldDefinition::fixed(DataType::Numeric, 12),
297 84 => FieldDefinition::fixed(DataType::Numeric, 12),
298 85 => FieldDefinition::fixed(DataType::Numeric, 12),
299 86 => FieldDefinition::fixed(DataType::Numeric, 16),
300 87 => FieldDefinition::fixed(DataType::Numeric, 16),
301 88 => FieldDefinition::fixed(DataType::Numeric, 16),
302 89 => FieldDefinition::fixed(DataType::Numeric, 16),
303 90 => FieldDefinition::fixed(DataType::Numeric, 42),
304 91 => FieldDefinition::fixed(DataType::Alphanumeric, 1),
305 92 => FieldDefinition::fixed(DataType::Alphanumeric, 2),
306 93 => FieldDefinition::fixed(DataType::Alphanumeric, 5),
307 94 => FieldDefinition::fixed(DataType::Alphanumeric, 7),
308 95 => FieldDefinition::fixed(DataType::Alphanumeric, 42),
309 96 => FieldDefinition::fixed(DataType::Binary, 8),
310 97 => FieldDefinition::fixed(DataType::Numeric, 16),
311 98 => FieldDefinition::fixed(DataType::AlphanumericSpecial, 25),
312 99 => FieldDefinition::llvar(DataType::Numeric, 11),
313 100 => FieldDefinition::llvar(DataType::Numeric, 11),
314 101 => FieldDefinition::llvar(DataType::AlphanumericSpecial, 17),
315 102 => FieldDefinition::llvar(DataType::AlphanumericSpecial, 28),
316 103 => FieldDefinition::llvar(DataType::AlphanumericSpecial, 28),
317 104 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 100),
318 105 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
319 106 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
320 107 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
321 108 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
322 109 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
323 110 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
324 111 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
325 112 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
326 113 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
327 114 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
328 115 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
329 116 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
330 117 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
331 118 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
332 119 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
333 120 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
334 121 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
335 122 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
336 123 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
337 124 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 255),
338 125 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 50),
339 126 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 6),
340 127 => FieldDefinition::lllvar(DataType::AlphanumericSpecial, 999),
341 128 => FieldDefinition::fixed(DataType::Binary, 8),
342};
343
344pub trait IsoSpec {
346 const TABLE: &'static [Option<FieldDefinition>];
348
349 #[inline]
351 fn get_field(number: u8) -> Option<&'static FieldDefinition> {
352 if (number as usize) < Self::TABLE.len() {
353 Self::TABLE[number as usize].as_ref()
354 } else {
355 None
356 }
357 }
358}
359
360pub struct Iso1987;
362
363impl IsoSpec for Iso1987 {
364 const TABLE: &'static [Option<FieldDefinition>] = &ISO8583_1987_TABLE;
365}
366
367#[cfg(test)]
368mod tests {
369 use super::*;
370
371 #[test]
372 fn test_field_lookup() {
373 let field2 = Iso1987::get_field(2).unwrap();
375 assert_eq!(field2.data_type, DataType::Numeric);
376 assert_eq!(field2.length_type, LengthType::Llvar);
377 assert_eq!(field2.max_len, 19);
378
379 let field4 = Iso1987::get_field(4).unwrap();
381 assert_eq!(field4.data_type, DataType::Numeric);
382 assert_eq!(field4.length_type, LengthType::Fixed);
383 assert_eq!(field4.max_len, 12);
384 }
385
386 #[test]
387 fn test_invalid_field() {
388 assert!(Iso1987::get_field(0).is_none());
389 assert!(Iso1987::get_field(200).is_none());
390 }
391
392 #[test]
393 fn test_zero_overhead() {
394 assert_eq!(core::mem::size_of::<FieldDefinition>(), 4);
396
397 assert_eq!(core::mem::size_of::<DataType>(), 1);
399 assert_eq!(core::mem::size_of::<LengthType>(), 1);
400 }
401}