Skip to main content

rust_stdf/
lib.rs

1//! `rust-stdf` is a library for parsing
2//! Standard Test Data Format (STDF) files
3//! of version V4 and V4-2007.
4//!
5//! Current capability:
6//!  - Reading & parsing STDF files with [`StdfReader`](crate::stdf_file::StdfReader).
7//!  - Writing STDF records with [`StdfWriter`](crate::stdf_file::StdfWriter).
8//!  - Reading & parsing ATDF files. (feature: `atdf`)
9//!  - Support several compressed formats.
10//!
11//! Available features:
12//!  - `gzip`: gzip compression (.gz) support powered by `flate2`
13//!  - `bzip`: bzip compression (.bz2) support powered by `bzip2`
14//!  - `zipfile`: zip compression (.zip) support powered by `zip`
15//!  - `atdf`: ATDF reader + STDF -> ATDF convertor (in dev)
16//!  - `serialize`: serialize STDF records by `serde`
17//!
18//! In development:
19//!  - (dev) Functions for ATDF <-> STDF format.
20
21// lib.rs
22// Author: noonchen - chennoon233@foxmail.com
23// Created Date: October 3rd 2022
24// -----
25// Last Modified: Thu Oct 06 2022
26// Modified By: noonchen
27// -----
28// Copyright (c) 2022 noonchen
29//
30
31extern crate smart_default;
32
33#[cfg(feature = "atdf")]
34mod atdf_types;
35mod records;
36mod stdf_codec;
37mod stdf_error;
38pub use records::*;
39pub use stdf_codec::*;
40pub use stdf_error::{StdfError, StdfErrorKind};
41
42/// This module contains STDF Reader/Writer
43/// and record iterator
44///
45/// For more detailed example, see [`StdfReader`](crate::stdf_file::StdfReader).
46pub mod stdf_file;
47
48/// This module contains ATDF Reader
49/// and record iterator
50///
51/// For more detailed example, click `AtdfReader`
52#[cfg(feature = "atdf")]
53pub mod atdf_file;
54
55#[cfg(test)]
56mod tests {
57    use crate::*;
58    use stdf_codec::ByteOrder;
59
60    // unsigned data type
61    #[test]
62    fn test_read_uint8() {
63        let raw_data = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8];
64        for i in 0..raw_data.len() {
65            let mut pos = i;
66            assert_eq!(raw_data[pos], stdf_codec::read_uint8(&raw_data, &mut pos));
67            assert_eq!(pos, i + 1);
68        }
69        let mut pos = raw_data.len();
70        assert_eq!(0, stdf_codec::read_uint8(&raw_data, &mut pos));
71        assert_eq!(pos, raw_data.len());
72    }
73
74    #[test]
75    fn test_read_u2_le() {
76        let byte_len = 2;
77        let raw_data = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8];
78        let expect = [0x0201, 0x0302, 0x0403, 0x0504, 0x0605, 0x0706, 0x0807, 0u16];
79        let order = ByteOrder::LittleEndian;
80        for i in 0..raw_data.len() {
81            let mut pos = i;
82            assert_eq!(
83                expect[pos],
84                stdf_codec::read_u2(&raw_data, &mut pos, &order)
85            );
86
87            if i <= raw_data.len() - byte_len {
88                assert_eq!(pos, i + byte_len);
89            } else {
90                assert_eq!(pos, i);
91            }
92        }
93        let mut pos = raw_data.len();
94        assert_eq!(0, stdf_codec::read_u2(&raw_data, &mut pos, &order));
95        assert_eq!(pos, raw_data.len());
96    }
97
98    #[test]
99    fn test_read_u2_be() {
100        let byte_len = 2;
101        let raw_data = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8];
102        let expect = [0x0102, 0x0203, 0x0304, 0x0405, 0x0506, 0x0607, 0x0708, 0u16];
103        let order = ByteOrder::BigEndian;
104        for i in 0..raw_data.len() {
105            let mut pos = i;
106            assert_eq!(
107                expect[pos],
108                stdf_codec::read_u2(&raw_data, &mut pos, &order)
109            );
110
111            if i <= raw_data.len() - byte_len {
112                assert_eq!(pos, i + byte_len);
113            } else {
114                assert_eq!(pos, i);
115            }
116        }
117        let mut pos = raw_data.len();
118        assert_eq!(0, stdf_codec::read_u2(&raw_data, &mut pos, &order));
119        assert_eq!(pos, raw_data.len());
120    }
121
122    #[test]
123    fn test_read_u4_le() {
124        let byte_len = 4;
125        let raw_data = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8];
126        let expect = [
127            0x4030201, 0x5040302, 0x6050403, 0x7060504, 0x8070605, 0, 0, 0u32,
128        ];
129        let order = ByteOrder::LittleEndian;
130        for i in 0..raw_data.len() {
131            let mut pos = i;
132            assert_eq!(
133                expect[pos],
134                stdf_codec::read_u4(&raw_data, &mut pos, &order)
135            );
136
137            if i <= raw_data.len() - byte_len {
138                assert_eq!(pos, i + byte_len);
139            } else {
140                assert_eq!(pos, i);
141            }
142        }
143        let mut pos = raw_data.len();
144        assert_eq!(0, stdf_codec::read_u4(&raw_data, &mut pos, &order));
145        assert_eq!(pos, raw_data.len());
146    }
147
148    #[test]
149    fn test_read_u4_be() {
150        let byte_len = 4;
151        let raw_data = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8];
152        let expect = [
153            0x1020304, 0x2030405, 0x3040506, 0x4050607, 0x5060708, 0, 0, 0u32,
154        ];
155        let order = ByteOrder::BigEndian;
156        for i in 0..raw_data.len() {
157            let mut pos = i;
158            assert_eq!(
159                expect[pos],
160                stdf_codec::read_u4(&raw_data, &mut pos, &order)
161            );
162
163            if i <= raw_data.len() - byte_len {
164                assert_eq!(pos, i + byte_len);
165            } else {
166                assert_eq!(pos, i);
167            }
168        }
169        let mut pos = raw_data.len();
170        assert_eq!(0, stdf_codec::read_u4(&raw_data, &mut pos, &order));
171        assert_eq!(pos, raw_data.len());
172    }
173
174    #[test]
175    fn test_read_u8_le() {
176        let byte_len = 8;
177        let raw_data = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
178        let expect = [0x807060504030201, 0x908070605040302, 0, 0, 0, 0, 0, 0, 0u64];
179        let order = ByteOrder::LittleEndian;
180        for i in 0..raw_data.len() {
181            let mut pos = i;
182            assert_eq!(
183                expect[pos],
184                stdf_codec::read_u8(&raw_data, &mut pos, &order)
185            );
186
187            if i <= raw_data.len() - byte_len {
188                assert_eq!(pos, i + byte_len);
189            } else {
190                assert_eq!(pos, i);
191            }
192        }
193        let mut pos = raw_data.len();
194        assert_eq!(0, stdf_codec::read_u8(&raw_data, &mut pos, &order));
195        assert_eq!(pos, raw_data.len());
196    }
197
198    #[test]
199    fn test_read_u8_be() {
200        let byte_len = 8;
201        let raw_data = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
202        let expect = [0x102030405060708, 0x203040506070809, 0, 0, 0, 0, 0, 0, 0u64];
203        let order = ByteOrder::BigEndian;
204        for i in 0..raw_data.len() {
205            let mut pos = i;
206            assert_eq!(
207                expect[pos],
208                stdf_codec::read_u8(&raw_data, &mut pos, &order)
209            );
210
211            if i <= raw_data.len() - byte_len {
212                assert_eq!(pos, i + byte_len);
213            } else {
214                assert_eq!(pos, i);
215            }
216        }
217        let mut pos = raw_data.len();
218        assert_eq!(0, stdf_codec::read_u8(&raw_data, &mut pos, &order));
219        assert_eq!(pos, raw_data.len());
220    }
221
222    // signed data type
223    #[test]
224    fn test_read_i1() {
225        let raw_data: [u8; 8] = [0x00, 0x01, 0x7F, 0xFE, 0x80, 0x81, 0x8F, 0xFF];
226        let expected: [i8; 8] = [0, 1, 127, -2, -128, -127, -113, -1];
227        for i in 0..raw_data.len() {
228            let mut pos = i;
229            assert_eq!(expected[pos], stdf_codec::read_i1(&raw_data, &mut pos));
230            assert_eq!(pos, i + 1);
231        }
232        let mut pos = raw_data.len();
233        assert_eq!(0, stdf_codec::read_uint8(&raw_data, &mut pos));
234        assert_eq!(pos, raw_data.len());
235    }
236
237    #[test]
238    fn test_read_i2_le() {
239        let byte_len = 2;
240        let raw_data: [u8; 8] = [0x00, 0x01, 0x7F, 0xFE, 0x80, 0x81, 0x8F, 0xFF];
241        let expected: [i16; 8] = [0x100, 0x7F01, -385, -32514, -32384, -28799, -113, 0];
242        let order = ByteOrder::LittleEndian;
243        for i in 0..raw_data.len() {
244            let mut pos = i;
245            assert_eq!(
246                expected[pos],
247                stdf_codec::read_i2(&raw_data, &mut pos, &order)
248            );
249
250            if i <= raw_data.len() - byte_len {
251                assert_eq!(pos, i + byte_len);
252            } else {
253                assert_eq!(pos, i);
254            }
255        }
256        let mut pos = raw_data.len();
257        assert_eq!(0, stdf_codec::read_i2(&raw_data, &mut pos, &order));
258        assert_eq!(pos, raw_data.len());
259    }
260
261    #[test]
262    fn test_read_i2_be() {
263        let byte_len = 2;
264        let raw_data: [u8; 8] = [0x00, 0x01, 0x7F, 0xFE, 0x80, 0x81, 0x8F, 0xFF];
265        let expected: [i16; 8] = [0x1, 0x17F, 0x7FFE, -384, -32639, -32369, -28673, 0];
266        let order = ByteOrder::BigEndian;
267        for i in 0..raw_data.len() {
268            let mut pos = i;
269            assert_eq!(
270                expected[pos],
271                stdf_codec::read_i2(&raw_data, &mut pos, &order)
272            );
273
274            if i <= raw_data.len() - byte_len {
275                assert_eq!(pos, i + byte_len);
276            } else {
277                assert_eq!(pos, i);
278            }
279        }
280        let mut pos = raw_data.len();
281        assert_eq!(0, stdf_codec::read_i2(&raw_data, &mut pos, &order));
282        assert_eq!(pos, raw_data.len());
283    }
284
285    #[test]
286    fn test_read_i4_le() {
287        let byte_len = 4;
288        let raw_data: [u8; 8] = [0x00, 0x01, 0x7F, 0xFE, 0x80, 0x81, 0x8F, 0xFF];
289        let expected: [i32; 8] = [
290            -25231104,
291            -2130804991,
292            -2122252673,
293            -1887338242,
294            -7372416,
295            0,
296            0,
297            0,
298        ];
299        let order = ByteOrder::LittleEndian;
300        for i in 0..raw_data.len() {
301            let mut pos = i;
302            assert_eq!(
303                expected[pos],
304                stdf_codec::read_i4(&raw_data, &mut pos, &order)
305            );
306
307            if i <= raw_data.len() - byte_len {
308                assert_eq!(pos, i + byte_len);
309            } else {
310                assert_eq!(pos, i);
311            }
312        }
313        let mut pos = raw_data.len();
314        assert_eq!(0, stdf_codec::read_i4(&raw_data, &mut pos, &order));
315        assert_eq!(pos, raw_data.len());
316    }
317
318    #[test]
319    fn test_read_i4_be() {
320        let byte_len = 4;
321        let raw_data: [u8; 8] = [0x00, 0x01, 0x7F, 0xFE, 0x80, 0x81, 0x8F, 0xFF];
322        let expected: [i32; 8] = [
323            0x17FFE,
324            0x17FFE80,
325            0x7FFE8081,
326            -25132657,
327            -2138992641,
328            0,
329            0,
330            0,
331        ];
332        let order = ByteOrder::BigEndian;
333        for i in 0..raw_data.len() {
334            let mut pos = i;
335            assert_eq!(
336                expected[pos],
337                stdf_codec::read_i4(&raw_data, &mut pos, &order)
338            );
339
340            if i <= raw_data.len() - byte_len {
341                assert_eq!(pos, i + byte_len);
342            } else {
343                assert_eq!(pos, i);
344            }
345        }
346        let mut pos = raw_data.len();
347        assert_eq!(0, stdf_codec::read_i4(&raw_data, &mut pos, &order));
348        assert_eq!(pos, raw_data.len());
349    }
350
351    // float
352    #[test]
353    fn test_read_r4_le() {
354        let byte_len = 4;
355        let raw_data: [u8; 8] = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8];
356        let expected: [f32; 8] = [
357            1.5399896e-36,
358            6.2071626e-36,
359            2.5017467e-35,
360            1.0082514e-34,
361            4.063216e-34,
362            0.0,
363            0.0,
364            0.0,
365        ];
366        let order = ByteOrder::LittleEndian;
367        for i in 0..raw_data.len() {
368            let mut pos = i;
369            assert_eq!(
370                expected[pos],
371                stdf_codec::read_r4(&raw_data, &mut pos, &order)
372            );
373
374            if i <= raw_data.len() - byte_len {
375                assert_eq!(pos, i + byte_len);
376            } else {
377                assert_eq!(pos, i);
378            }
379        }
380        let mut pos = raw_data.len();
381        assert_eq!(0.0, stdf_codec::read_r4(&raw_data, &mut pos, &order));
382        assert_eq!(pos, raw_data.len());
383    }
384
385    #[test]
386    fn test_read_r4_be() {
387        let byte_len = 4;
388        let raw_data: [u8; 8] = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8];
389        let expected: [f32; 8] = [
390            2.3879393e-38,
391            9.625514e-38,
392            3.879708e-37,
393            1.5636842e-36,
394            6.301941e-36,
395            0.0,
396            0.0,
397            0.0,
398        ];
399        let order = ByteOrder::BigEndian;
400        for i in 0..raw_data.len() {
401            let mut pos = i;
402            assert_eq!(
403                expected[pos],
404                stdf_codec::read_r4(&raw_data, &mut pos, &order)
405            );
406
407            if i <= raw_data.len() - byte_len {
408                assert_eq!(pos, i + byte_len);
409            } else {
410                assert_eq!(pos, i);
411            }
412        }
413        let mut pos = raw_data.len();
414        assert_eq!(0.0, stdf_codec::read_r4(&raw_data, &mut pos, &order));
415        assert_eq!(pos, raw_data.len());
416    }
417
418    #[test]
419    fn test_read_r8_le() {
420        let byte_len = 8;
421        let raw_data: [u8; 9] = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
422        let expected: [f64; 9] = [
423            5.447603722011605e-270,
424            3.7258146895053074e-265,
425            0.0,
426            0.0,
427            0.0,
428            0.0,
429            0.0,
430            0.0,
431            0.0,
432        ];
433        let order = ByteOrder::LittleEndian;
434        for i in 0..raw_data.len() {
435            let mut pos = i;
436            assert_eq!(
437                expected[pos],
438                stdf_codec::read_r8(&raw_data, &mut pos, &order)
439            );
440
441            if i <= raw_data.len() - byte_len {
442                assert_eq!(pos, i + byte_len);
443            } else {
444                assert_eq!(pos, i);
445            }
446        }
447        let mut pos = raw_data.len();
448        assert_eq!(0.0, stdf_codec::read_r8(&raw_data, &mut pos, &order));
449        assert_eq!(pos, raw_data.len());
450    }
451
452    #[test]
453    fn test_read_r8_be() {
454        let byte_len = 8;
455        let raw_data: [u8; 9] = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
456        let expected: [f64; 9] = [
457            8.20788039913184e-304,
458            5.678932010640861e-299,
459            0.0,
460            0.0,
461            0.0,
462            0.0,
463            0.0,
464            0.0,
465            0.0,
466        ];
467        let order = ByteOrder::BigEndian;
468        for i in 0..raw_data.len() {
469            let mut pos = i;
470            assert_eq!(
471                expected[pos],
472                stdf_codec::read_r8(&raw_data, &mut pos, &order)
473            );
474
475            if i <= raw_data.len() - byte_len {
476                assert_eq!(pos, i + byte_len);
477            } else {
478                assert_eq!(pos, i);
479            }
480        }
481        let mut pos = raw_data.len();
482        assert_eq!(0.0, stdf_codec::read_r8(&raw_data, &mut pos, &order));
483        assert_eq!(pos, raw_data.len());
484    }
485
486    // string & array
487    #[test]
488    fn test_read_cn() {
489        let raw_data: [u8; 9] = [7, 84, 101, 115, 116, 32, 79, 75, 0];
490        let mut pos = 0;
491        let expect_pos = |p: usize| std::cmp::min(1 + p + raw_data[p] as usize, raw_data.len());
492        assert_eq!(
493            "Test OK".to_string(),
494            stdf_codec::read_cn(&raw_data, &mut pos)
495        );
496        assert_eq!(pos, expect_pos(0));
497        let mut pos = 4;
498        assert_eq!(
499            " OK\0".to_string(),
500            stdf_codec::read_cn(&raw_data, &mut pos)
501        );
502        assert_eq!(pos, expect_pos(4));
503        let mut pos = 8;
504        assert_eq!("".to_string(), stdf_codec::read_cn(&raw_data, &mut pos));
505        assert_eq!(pos, expect_pos(8));
506        // latin1 check
507        let raw_data_latin: [u8; 7] = [6, 52, 50, 176, 67, 191, 255];
508        assert_eq!(
509            "42°C¿ÿ".to_string(),
510            stdf_codec::read_cn(&raw_data_latin, &mut 0)
511        );
512    }
513
514    #[test]
515    fn test_read_sn_le() {
516        let raw_data: [u8; 10] = [7, 0, 84, 101, 115, 116, 32, 79, 75, 0];
517        let mut pos = 0;
518        let order = ByteOrder::LittleEndian;
519        assert_eq!(
520            "Test OK".to_string(),
521            stdf_codec::read_sn(&raw_data, &mut pos, &order)
522        );
523        assert_eq!(pos, 9);
524        let mut pos = 4;
525        assert_eq!(
526            " OK\0".to_string(),
527            stdf_codec::read_sn(&raw_data, &mut pos, &order)
528        );
529        assert_eq!(pos, 10);
530        let mut pos = 9;
531        assert_eq!(
532            "".to_string(),
533            stdf_codec::read_sn(&raw_data, &mut pos, &order)
534        );
535        assert_eq!(pos, 9);
536    }
537
538    #[test]
539    fn test_read_sn_be() {
540        let raw_data: [u8; 10] = [0, 7, 84, 101, 115, 116, 32, 79, 75, 0];
541        let mut pos = 0;
542        let order = ByteOrder::BigEndian;
543        assert_eq!(
544            "Test OK".to_string(),
545            stdf_codec::read_sn(&raw_data, &mut pos, &order)
546        );
547        assert_eq!(pos, 9);
548        let mut pos = 4;
549        assert_eq!(
550            " OK\0".to_string(),
551            stdf_codec::read_sn(&raw_data, &mut pos, &order)
552        );
553        assert_eq!(pos, 10);
554        let mut pos = 9;
555        assert_eq!(
556            "".to_string(),
557            stdf_codec::read_sn(&raw_data, &mut pos, &order)
558        );
559        assert_eq!(pos, 9);
560    }
561
562    #[test]
563    fn test_read_cf() {
564        let raw_data: [u8; 9] = [7, 84, 101, 115, 116, 32, 79, 75, 0];
565        let mut pos = 1;
566        assert_eq!(
567            "Test OK".to_string(),
568            stdf_codec::read_cf(&raw_data, &mut pos, 7)
569        );
570        assert_eq!(pos, 8);
571        let mut pos = 5;
572        assert_eq!(
573            " OK\0".to_string(),
574            stdf_codec::read_cf(&raw_data, &mut pos, 100)
575        );
576        assert_eq!(pos, 9);
577        let mut pos = 8;
578        assert_eq!("".to_string(), stdf_codec::read_cf(&raw_data, &mut pos, 0));
579        assert_eq!(pos, 8);
580    }
581
582    #[test]
583    fn test_read_bn() {
584        let raw_data: [u8; 9] = [7, 84, 101, 115, 116, 32, 79, 75, 0];
585        let mut pos = 0;
586        assert_eq!(
587            vec![84, 101, 115, 116, 32, 79, 75],
588            stdf_codec::read_bn(&raw_data, &mut pos)
589        );
590        assert_eq!(pos, 8);
591        let mut pos = 4;
592        assert_eq!(
593            vec![32, 79, 75, 0],
594            stdf_codec::read_bn(&raw_data, &mut pos)
595        );
596        assert_eq!(pos, 9);
597        let mut pos = 100;
598        assert_eq!(vec![0u8; 0], stdf_codec::read_bn(&raw_data, &mut pos));
599        assert_eq!(pos, 100);
600    }
601
602    #[test]
603    fn test_read_dn() {
604        let raw_data: [u8; 10] = [56, 0, 84, 101, 115, 116, 32, 79, 75, 0];
605        let mut pos = 0;
606        let order = ByteOrder::LittleEndian;
607        assert_eq!(
608            Dn {
609                bit_count: 56,
610                bit_data: vec![84, 101, 115, 116, 32, 79, 75],
611            },
612            stdf_codec::read_dn(&raw_data, &mut pos, &order)
613        );
614        assert_eq!(pos, 9);
615        let mut pos = 4;
616        assert_eq!(
617            Dn {
618                bit_count: 0x7473,
619                bit_data: vec![32, 79, 75, 0],
620            },
621            stdf_codec::read_dn(&raw_data, &mut pos, &order)
622        );
623        assert_eq!(pos, 10);
624        let mut pos = 100;
625        assert_eq!(
626            Dn {
627                bit_count: 0,
628                bit_data: Vec::new(),
629            },
630            stdf_codec::read_dn(&raw_data, &mut pos, &order)
631        );
632        assert_eq!(pos, 100);
633    }
634
635    // Vec
636    #[test]
637    fn test_read_kx_cn() {
638        let raw_data: [u8; 12] = [2, 84, 101, 2, 115, 116, 1, 32, 2, 79, 75, 0];
639        let mut pos = 0;
640        assert_eq!(
641            vec![
642                "Te".to_string(),
643                "st".to_string(),
644                " ".to_string(),
645                "OK".to_string()
646            ],
647            stdf_codec::read_kx_cn(&raw_data, &mut pos, 4)
648        );
649        assert_eq!(pos, 11);
650        let mut pos = 3;
651        assert_eq!(
652            vec![
653                "st".to_string(),
654                " ".to_string(),
655                "OK".to_string(),
656                "".to_string()
657            ],
658            stdf_codec::read_kx_cn(&raw_data, &mut pos, 4)
659        );
660        assert_eq!(pos, 12);
661        assert_eq!(
662            Vec::<String>::new(),
663            stdf_codec::read_kx_cn(&raw_data, &mut pos, 0)
664        );
665    }
666
667    #[test]
668    fn test_read_kx_sn() {
669        let raw_data: [u8; 16] = [2, 0, 84, 101, 2, 0, 115, 116, 1, 0, 32, 2, 0, 79, 75, 0];
670        let mut pos = 0;
671        let order = ByteOrder::LittleEndian;
672        assert_eq!(
673            vec![
674                "Te".to_string(),
675                "st".to_string(),
676                " ".to_string(),
677                "OK".to_string()
678            ],
679            stdf_codec::read_kx_sn(&raw_data, &mut pos, &order, 4)
680        );
681        assert_eq!(pos, 15);
682        let mut pos = 4;
683        assert_eq!(
684            vec![
685                "st".to_string(),
686                " ".to_string(),
687                "OK".to_string(),
688                "".to_string()
689            ],
690            stdf_codec::read_kx_sn(&raw_data, &mut pos, &order, 4)
691        );
692        assert_eq!(pos, 15);
693        assert_eq!(
694            Vec::<String>::new(),
695            stdf_codec::read_kx_sn(&raw_data, &mut pos, &order, 0)
696        );
697    }
698
699    #[test]
700    fn test_read_kx_cf() {
701        let raw_data: [u8; 9] = [84, 101, 115, 116, 32, 32, 79, 75, 0];
702        let mut pos = 0;
703        assert_eq!(
704            vec![
705                "Te".to_string(),
706                "st".to_string(),
707                "  ".to_string(),
708                "OK".to_string()
709            ],
710            stdf_codec::read_kx_cf(&raw_data, &mut pos, 4, 2)
711        );
712        assert_eq!(pos, 8);
713        let mut pos = 3;
714        assert_eq!(
715            vec![
716                "".to_string(),
717                "".to_string(),
718                "".to_string(),
719                "".to_string()
720            ],
721            stdf_codec::read_kx_cf(&raw_data, &mut pos, 4, 0)
722        );
723        assert_eq!(pos, 3);
724        // k == 0 returns an empty vec without moving the cursor.
725        // Start from a distinct pos to prove non-advancement.
726        let mut pos = 5;
727        assert_eq!(
728            Vec::<String>::new(),
729            stdf_codec::read_kx_cf(&raw_data, &mut pos, 0, 0)
730        );
731        assert_eq!(pos, 5);
732    }
733
734    #[test]
735    fn test_read_kx_u1() {
736        let raw_data: [u8; 9] = [84, 101, 115, 116, 32, 32, 79, 75, 0];
737        let mut pos = 0;
738        assert_eq!(
739            vec![84, 101, 115, 116, 32, 32, 79, 75, 0],
740            stdf_codec::read_kx_u1(&raw_data, &mut pos, 9)
741        );
742        assert_eq!(pos, 9);
743        let mut pos = 3;
744        assert_eq!(vec![0u8; 0], stdf_codec::read_kx_u1(&raw_data, &mut pos, 0));
745        assert_eq!(pos, 3);
746    }
747
748    #[test]
749    fn test_read_kx_u2() {
750        let raw_data: [u8; 9] = [0x12, 0x23, 0x45, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0];
751        let mut pos = 0;
752        let order = ByteOrder::LittleEndian;
753        assert_eq!(
754            vec![0x2312, 0x7845, 0xBC9A, 0xFFDE, 0],
755            stdf_codec::read_kx_u2(&raw_data, &mut pos, &order, 5)
756        );
757        assert_eq!(pos, 8);
758        let mut pos = 3;
759        assert_eq!(
760            vec![0u16; 0],
761            stdf_codec::read_kx_u2(&raw_data, &mut pos, &order, 0)
762        );
763        assert_eq!(pos, 3);
764    }
765
766    #[test]
767    fn test_read_kx_u4() {
768        let raw_data: [u8; 9] = [0x12, 0x23, 0x45, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0];
769        let mut pos = 0;
770        let order = ByteOrder::LittleEndian;
771        assert_eq!(
772            vec![0x78452312, 0xFFDEBC9A, 0, 0, 0],
773            stdf_codec::read_kx_u4(&raw_data, &mut pos, &order, 5)
774        );
775        assert_eq!(pos, 8);
776        let mut pos = 3;
777        assert_eq!(
778            vec![0u32; 0],
779            stdf_codec::read_kx_u4(&raw_data, &mut pos, &order, 0)
780        );
781        assert_eq!(pos, 3);
782    }
783
784    #[test]
785    fn test_read_kx_u8() {
786        let raw_data: [u8; 9] = [0x12, 0x23, 0x45, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0];
787        let mut pos = 0;
788        let order = ByteOrder::LittleEndian;
789        assert_eq!(
790            vec![0xFFDEBC9A78452312, 0, 0, 0, 0],
791            stdf_codec::read_kx_u8(&raw_data, &mut pos, &order, 5)
792        );
793        assert_eq!(pos, 8);
794        let mut pos = 3;
795        assert_eq!(
796            vec![0u64; 0],
797            stdf_codec::read_kx_u8(&raw_data, &mut pos, &order, 0)
798        );
799        assert_eq!(pos, 3);
800    }
801
802    #[test]
803    fn test_read_kx_uf() {
804        let raw_data: [u8; 9] = [0x12, 0x23, 0x45, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0];
805        let mut pos = 0;
806        let order = ByteOrder::LittleEndian;
807        assert_eq!(
808            stdf_codec::KxUf::F1(vec![0x12, 0x23, 0x45, 0x78, 0x9A]),
809            stdf_codec::read_kx_uf(&raw_data, &mut pos, &order, 5, 1)
810        );
811        assert_eq!(pos, 5);
812        let mut pos = 0;
813        assert_eq!(
814            stdf_codec::KxUf::F2(vec![0x2312, 0x7845, 0xBC9A, 0xFFDE, 0]),
815            stdf_codec::read_kx_uf(&raw_data, &mut pos, &order, 5, 2)
816        );
817        assert_eq!(pos, 8);
818        let mut pos = 0;
819        assert_eq!(
820            stdf_codec::KxUf::F4(vec![0x78452312, 0xFFDEBC9A, 0, 0, 0]),
821            stdf_codec::read_kx_uf(&raw_data, &mut pos, &order, 5, 4)
822        );
823        assert_eq!(pos, 8);
824        let mut pos = 0;
825        assert_eq!(
826            stdf_codec::KxUf::F8(vec![0xFFDEBC9A78452312, 0, 0, 0, 0]),
827            stdf_codec::read_kx_uf(&raw_data, &mut pos, &order, 5, 8)
828        );
829        assert_eq!(pos, 8);
830        let mut pos = 3;
831        assert_eq!(
832            stdf_codec::KxUf::F1(vec![0u8; 0]),
833            stdf_codec::read_kx_uf(&raw_data, &mut pos, &order, 100, 0)
834        );
835        assert_eq!(pos, 3);
836    }
837
838    #[test]
839    fn test_read_kx_r4() {
840        let raw_data: [u8; 9] = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 0];
841        let mut pos = 0;
842        let order = ByteOrder::LittleEndian;
843        assert_eq!(
844            vec![1.5399896e-36, 4.063216e-34, 0.0, 0.0, 0.0],
845            stdf_codec::read_kx_r4(&raw_data, &mut pos, &order, 5)
846        );
847        assert_eq!(pos, 8);
848        let mut pos = 3;
849        assert_eq!(
850            vec![0.0; 0],
851            stdf_codec::read_kx_r4(&raw_data, &mut pos, &order, 0)
852        );
853        assert_eq!(pos, 3);
854    }
855
856    #[test]
857    fn test_read_kx_n1() {
858        let raw_data: [u8; 9] = [0x12, 0x23, 0x45, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0];
859        let mut pos = 0;
860        assert_eq!(
861            vec![0x2, 0x1, 0x3, 0x2, 0x5],
862            stdf_codec::read_kx_n1(&raw_data, &mut pos, 5)
863        );
864        assert_eq!(pos, 3);
865        let mut pos = 3;
866        assert_eq!(vec![0u8; 0], stdf_codec::read_kx_n1(&raw_data, &mut pos, 0));
867        assert_eq!(pos, 3);
868    }
869
870    // generic data
871    #[test]
872    fn test_read_vn() {
873        let raw_data: [u8; 14] = [
874            0x4, 0x0, 0xA, 0x2, 0x41, 0x42, 0x1, 0xFF, 0x0, 0x5, 0xFE, 0x1, 0xD, 0x45,
875        ];
876        let mut pos = 2;
877        let order = ByteOrder::LittleEndian;
878        assert_eq!(
879            vec![
880                stdf_codec::V1::Cn("AB".to_string()),
881                stdf_codec::V1::U1(0xFF),
882                stdf_codec::V1::B0,
883                stdf_codec::V1::I2(510),
884                stdf_codec::V1::N1(0x5),
885            ],
886            stdf_codec::read_vn(&raw_data, &mut pos, &order, 5)
887        );
888        assert_eq!(pos, 14);
889        let mut pos = 3;
890        assert_eq!(
891            vec![stdf_codec::V1::Invalid; 0],
892            stdf_codec::read_vn(&raw_data, &mut pos, &order, 0)
893        );
894        assert_eq!(pos, 3);
895    }
896
897    #[test]
898    fn test_record_type() {
899        for rec_type in (0..=33).map(|x| 1 << x) {
900            assert!(
901                StdfRecord::new(rec_type).is_type(rec_type),
902                "match type incorrect"
903            );
904        }
905    }
906
907    #[cfg(feature = "atdf")]
908    use atdf_types::atdf_record_field::*;
909
910    #[cfg(feature = "atdf")]
911    #[test]
912    fn test_atdf_timestamp_is_utc() {
913        // A fixed UTC instant, non-midnight so a local-tz or zeroed-time
914        // regression would change the rendered string.
915        let mut rec = ATR::new();
916        rec.mod_tim = 1_000_000_000;
917        let fields = atdf_types::atdf_data_from_atr(&rec);
918        assert_eq!(fields[0], "01:46:40 09-Sep-2001"); // MOD_TIM
919    }
920
921    #[cfg(feature = "atdf")]
922    #[test]
923    fn test_atdf_fields_duplicate() {
924        use std::collections::HashMap;
925        let find_dup = |arr: &[(&str, bool)], name: &str| {
926            arr.iter()
927                // .copied()
928                .fold(HashMap::new(), |mut map, val| {
929                    map.entry(val.0).and_modify(|frq| *frq += 1).or_insert(1);
930                    map
931                })
932                .iter()
933                .map(|(s, &n)| assert_eq!(n, 1, "dup field {} in {}", s, name))
934                .count()
935        };
936
937        find_dup(&FAR_FIELD, "FAR");
938        find_dup(&ATR_FIELD, "ATR");
939        find_dup(&MIR_FIELD, "MIR");
940        find_dup(&MRR_FIELD, "MRR");
941        find_dup(&PCR_FIELD, "PCR");
942        find_dup(&HBR_FIELD, "HBR");
943        find_dup(&SBR_FIELD, "SBR");
944        find_dup(&PMR_FIELD, "PMR");
945        find_dup(&PGR_FIELD, "PGR");
946        find_dup(&PLR_FIELD, "PLR");
947        find_dup(&RDR_FIELD, "RDR");
948        find_dup(&SDR_FIELD, "SDR");
949        find_dup(&WIR_FIELD, "WIR");
950        find_dup(&WRR_FIELD, "WRR");
951        find_dup(&WCR_FIELD, "WCR");
952        find_dup(&PIR_FIELD, "PIR");
953        find_dup(&PRR_FIELD, "PRR");
954        find_dup(&TSR_FIELD, "TSR");
955        find_dup(&PTR_FIELD, "PTR");
956        find_dup(&MPR_FIELD, "MPR");
957        find_dup(&FTR_FIELD, "FTR");
958        find_dup(&BPS_FIELD, "BPS");
959        find_dup(&EPS_FIELD, "EPS");
960        find_dup(&GDR_FIELD, "GDR");
961        find_dup(&DTR_FIELD, "DTR");
962    }
963
964    #[cfg(feature = "atdf")]
965    #[test]
966    fn test_atdf_field_req_count() {
967        assert_eq!(3, atdf_types::count_reqired(&PTR_FIELD));
968        assert_eq!(0, atdf_types::count_reqired(&GDR_FIELD));
969    }
970}