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.
7//!  - Reading & parsing ATDF files. (feature: `atdf`)
8//!  - Support several compressed formats.
9//!
10//! Available features:
11//!  - `gzip`: gzip compression (.gz) support powered by `flate2`
12//!  - `bzip`: bzip compression (.bz2) support powered by `bzip2`
13//!  - `zipfile`: zip compression (.zip) support powered by `zip`
14//!  - `atdf`: ATDF reader + STDF -> ATDF convertor (in dev)
15//!  - `serialize`: serialize STDF records by `serde`
16//!
17//! In development:
18//!  - (dev) Dump `StdfRecord` to a new stdf file.
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;
41
42/// This module contains STDF Reader
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            vec![84, 101, 115, 116, 32, 79, 75],
609            stdf_codec::read_dn(&raw_data, &mut pos, &order)
610        );
611        assert_eq!(pos, 9);
612        let mut pos = 4;
613        assert_eq!(
614            vec![32, 79, 75, 0],
615            stdf_codec::read_dn(&raw_data, &mut pos, &order)
616        );
617        assert_eq!(pos, 10);
618        let mut pos = 100;
619        assert_eq!(
620            vec![0u8; 0],
621            stdf_codec::read_dn(&raw_data, &mut pos, &order)
622        );
623        assert_eq!(pos, 100);
624    }
625
626    // Vec
627    #[test]
628    fn test_read_kx_cn() {
629        let raw_data: [u8; 12] = [2, 84, 101, 2, 115, 116, 1, 32, 2, 79, 75, 0];
630        let mut pos = 0;
631        assert_eq!(
632            vec![
633                "Te".to_string(),
634                "st".to_string(),
635                " ".to_string(),
636                "OK".to_string()
637            ],
638            stdf_codec::read_kx_cn(&raw_data, &mut pos, 4)
639        );
640        assert_eq!(pos, 11);
641        let mut pos = 3;
642        assert_eq!(
643            vec![
644                "st".to_string(),
645                " ".to_string(),
646                "OK".to_string(),
647                "".to_string()
648            ],
649            stdf_codec::read_kx_cn(&raw_data, &mut pos, 4)
650        );
651        assert_eq!(pos, 12);
652        assert_eq!(
653            Vec::<String>::new(),
654            stdf_codec::read_kx_cn(&raw_data, &mut pos, 0)
655        );
656    }
657
658    #[test]
659    fn test_read_kx_sn() {
660        let raw_data: [u8; 16] = [2, 0, 84, 101, 2, 0, 115, 116, 1, 0, 32, 2, 0, 79, 75, 0];
661        let mut pos = 0;
662        let order = ByteOrder::LittleEndian;
663        assert_eq!(
664            vec![
665                "Te".to_string(),
666                "st".to_string(),
667                " ".to_string(),
668                "OK".to_string()
669            ],
670            stdf_codec::read_kx_sn(&raw_data, &mut pos, &order, 4)
671        );
672        assert_eq!(pos, 15);
673        let mut pos = 4;
674        assert_eq!(
675            vec![
676                "st".to_string(),
677                " ".to_string(),
678                "OK".to_string(),
679                "".to_string()
680            ],
681            stdf_codec::read_kx_sn(&raw_data, &mut pos, &order, 4)
682        );
683        assert_eq!(pos, 15);
684        assert_eq!(
685            Vec::<String>::new(),
686            stdf_codec::read_kx_sn(&raw_data, &mut pos, &order, 0)
687        );
688    }
689
690    #[test]
691    fn test_read_kx_cf() {
692        let raw_data: [u8; 9] = [84, 101, 115, 116, 32, 32, 79, 75, 0];
693        let mut pos = 0;
694        assert_eq!(
695            vec![
696                "Te".to_string(),
697                "st".to_string(),
698                "  ".to_string(),
699                "OK".to_string()
700            ],
701            stdf_codec::read_kx_cf(&raw_data, &mut pos, 4, 2)
702        );
703        assert_eq!(pos, 8);
704        let mut pos = 3;
705        assert_eq!(
706            vec![
707                "".to_string(),
708                "".to_string(),
709                "".to_string(),
710                "".to_string()
711            ],
712            stdf_codec::read_kx_cf(&raw_data, &mut pos, 4, 0)
713        );
714        assert_eq!(pos, 3);
715        // k == 0 returns an empty vec without moving the cursor.
716        // Start from a distinct pos to prove non-advancement.
717        let mut pos = 5;
718        assert_eq!(
719            Vec::<String>::new(),
720            stdf_codec::read_kx_cf(&raw_data, &mut pos, 0, 0)
721        );
722        assert_eq!(pos, 5);
723    }
724
725    #[test]
726    fn test_read_kx_u1() {
727        let raw_data: [u8; 9] = [84, 101, 115, 116, 32, 32, 79, 75, 0];
728        let mut pos = 0;
729        assert_eq!(
730            vec![84, 101, 115, 116, 32, 32, 79, 75, 0],
731            stdf_codec::read_kx_u1(&raw_data, &mut pos, 9)
732        );
733        assert_eq!(pos, 9);
734        let mut pos = 3;
735        assert_eq!(vec![0u8; 0], stdf_codec::read_kx_u1(&raw_data, &mut pos, 0));
736        assert_eq!(pos, 3);
737    }
738
739    #[test]
740    fn test_read_kx_u2() {
741        let raw_data: [u8; 9] = [0x12, 0x23, 0x45, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0];
742        let mut pos = 0;
743        let order = ByteOrder::LittleEndian;
744        assert_eq!(
745            vec![0x2312, 0x7845, 0xBC9A, 0xFFDE, 0],
746            stdf_codec::read_kx_u2(&raw_data, &mut pos, &order, 5)
747        );
748        assert_eq!(pos, 8);
749        let mut pos = 3;
750        assert_eq!(
751            vec![0u16; 0],
752            stdf_codec::read_kx_u2(&raw_data, &mut pos, &order, 0)
753        );
754        assert_eq!(pos, 3);
755    }
756
757    #[test]
758    fn test_read_kx_u4() {
759        let raw_data: [u8; 9] = [0x12, 0x23, 0x45, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0];
760        let mut pos = 0;
761        let order = ByteOrder::LittleEndian;
762        assert_eq!(
763            vec![0x78452312, 0xFFDEBC9A, 0, 0, 0],
764            stdf_codec::read_kx_u4(&raw_data, &mut pos, &order, 5)
765        );
766        assert_eq!(pos, 8);
767        let mut pos = 3;
768        assert_eq!(
769            vec![0u32; 0],
770            stdf_codec::read_kx_u4(&raw_data, &mut pos, &order, 0)
771        );
772        assert_eq!(pos, 3);
773    }
774
775    #[test]
776    fn test_read_kx_u8() {
777        let raw_data: [u8; 9] = [0x12, 0x23, 0x45, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0];
778        let mut pos = 0;
779        let order = ByteOrder::LittleEndian;
780        assert_eq!(
781            vec![0xFFDEBC9A78452312, 0, 0, 0, 0],
782            stdf_codec::read_kx_u8(&raw_data, &mut pos, &order, 5)
783        );
784        assert_eq!(pos, 8);
785        let mut pos = 3;
786        assert_eq!(
787            vec![0u64; 0],
788            stdf_codec::read_kx_u8(&raw_data, &mut pos, &order, 0)
789        );
790        assert_eq!(pos, 3);
791    }
792
793    #[test]
794    fn test_read_kx_uf() {
795        let raw_data: [u8; 9] = [0x12, 0x23, 0x45, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0];
796        let mut pos = 0;
797        let order = ByteOrder::LittleEndian;
798        assert_eq!(
799            stdf_codec::KxUf::F1(vec![0x12, 0x23, 0x45, 0x78, 0x9A]),
800            stdf_codec::read_kx_uf(&raw_data, &mut pos, &order, 5, 1)
801        );
802        assert_eq!(pos, 5);
803        let mut pos = 0;
804        assert_eq!(
805            stdf_codec::KxUf::F2(vec![0x2312, 0x7845, 0xBC9A, 0xFFDE, 0]),
806            stdf_codec::read_kx_uf(&raw_data, &mut pos, &order, 5, 2)
807        );
808        assert_eq!(pos, 8);
809        let mut pos = 0;
810        assert_eq!(
811            stdf_codec::KxUf::F4(vec![0x78452312, 0xFFDEBC9A, 0, 0, 0]),
812            stdf_codec::read_kx_uf(&raw_data, &mut pos, &order, 5, 4)
813        );
814        assert_eq!(pos, 8);
815        let mut pos = 0;
816        assert_eq!(
817            stdf_codec::KxUf::F8(vec![0xFFDEBC9A78452312, 0, 0, 0, 0]),
818            stdf_codec::read_kx_uf(&raw_data, &mut pos, &order, 5, 8)
819        );
820        assert_eq!(pos, 8);
821        let mut pos = 3;
822        assert_eq!(
823            stdf_codec::KxUf::F1(vec![0u8; 0]),
824            stdf_codec::read_kx_uf(&raw_data, &mut pos, &order, 100, 0)
825        );
826        assert_eq!(pos, 3);
827    }
828
829    #[test]
830    fn test_read_kx_r4() {
831        let raw_data: [u8; 9] = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 0];
832        let mut pos = 0;
833        let order = ByteOrder::LittleEndian;
834        assert_eq!(
835            vec![1.5399896e-36, 4.063216e-34, 0.0, 0.0, 0.0],
836            stdf_codec::read_kx_r4(&raw_data, &mut pos, &order, 5)
837        );
838        assert_eq!(pos, 8);
839        let mut pos = 3;
840        assert_eq!(
841            vec![0.0; 0],
842            stdf_codec::read_kx_r4(&raw_data, &mut pos, &order, 0)
843        );
844        assert_eq!(pos, 3);
845    }
846
847    #[test]
848    fn test_read_kx_n1() {
849        let raw_data: [u8; 9] = [0x12, 0x23, 0x45, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0];
850        let mut pos = 0;
851        assert_eq!(
852            vec![0x2, 0x1, 0x3, 0x2, 0x5],
853            stdf_codec::read_kx_n1(&raw_data, &mut pos, 5)
854        );
855        assert_eq!(pos, 3);
856        let mut pos = 3;
857        assert_eq!(vec![0u8; 0], stdf_codec::read_kx_n1(&raw_data, &mut pos, 0));
858        assert_eq!(pos, 3);
859    }
860
861    // generic data
862    #[test]
863    fn test_read_vn() {
864        let raw_data: [u8; 14] = [
865            0x4, 0x0, 0xA, 0x2, 0x41, 0x42, 0x1, 0xFF, 0x0, 0x5, 0xFE, 0x1, 0xD, 0x45,
866        ];
867        let mut pos = 2;
868        let order = ByteOrder::LittleEndian;
869        assert_eq!(
870            vec![
871                stdf_codec::V1::Cn("AB".to_string()),
872                stdf_codec::V1::U1(0xFF),
873                stdf_codec::V1::B0,
874                stdf_codec::V1::I2(510),
875                stdf_codec::V1::N1(0x5),
876            ],
877            stdf_codec::read_vn(&raw_data, &mut pos, &order, 5)
878        );
879        assert_eq!(pos, 14);
880        let mut pos = 3;
881        assert_eq!(
882            vec![stdf_codec::V1::Invalid; 0],
883            stdf_codec::read_vn(&raw_data, &mut pos, &order, 0)
884        );
885        assert_eq!(pos, 3);
886    }
887
888    #[test]
889    fn test_record_type() {
890        for rec_type in (0..=33).map(|x| 1 << x) {
891            assert!(
892                StdfRecord::new(rec_type).is_type(rec_type),
893                "match type incorrect"
894            );
895        }
896    }
897
898    #[cfg(feature = "atdf")]
899    use atdf_types::atdf_record_field::*;
900
901    #[cfg(feature = "atdf")]
902    #[test]
903    fn test_atdf_timestamp_is_utc() {
904        // A fixed UTC instant, non-midnight so a local-tz or zeroed-time
905        // regression would change the rendered string.
906        let mut rec = ATR::new();
907        rec.mod_tim = 1_000_000_000;
908        let fields = atdf_types::atdf_data_from_atr(&rec);
909        assert_eq!(fields[0], "01:46:40 09-Sep-2001"); // MOD_TIM
910    }
911
912    #[cfg(feature = "atdf")]
913    #[test]
914    fn test_atdf_fields_duplicate() {
915        use std::collections::HashMap;
916        let find_dup = |arr: &[(&str, bool)], name: &str| {
917            arr.iter()
918                // .copied()
919                .fold(HashMap::new(), |mut map, val| {
920                    map.entry(val.0).and_modify(|frq| *frq += 1).or_insert(1);
921                    map
922                })
923                .iter()
924                .map(|(s, &n)| assert_eq!(n, 1, "dup field {} in {}", s, name))
925                .count()
926        };
927
928        find_dup(&FAR_FIELD, "FAR");
929        find_dup(&ATR_FIELD, "ATR");
930        find_dup(&MIR_FIELD, "MIR");
931        find_dup(&MRR_FIELD, "MRR");
932        find_dup(&PCR_FIELD, "PCR");
933        find_dup(&HBR_FIELD, "HBR");
934        find_dup(&SBR_FIELD, "SBR");
935        find_dup(&PMR_FIELD, "PMR");
936        find_dup(&PGR_FIELD, "PGR");
937        find_dup(&PLR_FIELD, "PLR");
938        find_dup(&RDR_FIELD, "RDR");
939        find_dup(&SDR_FIELD, "SDR");
940        find_dup(&WIR_FIELD, "WIR");
941        find_dup(&WRR_FIELD, "WRR");
942        find_dup(&WCR_FIELD, "WCR");
943        find_dup(&PIR_FIELD, "PIR");
944        find_dup(&PRR_FIELD, "PRR");
945        find_dup(&TSR_FIELD, "TSR");
946        find_dup(&PTR_FIELD, "PTR");
947        find_dup(&MPR_FIELD, "MPR");
948        find_dup(&FTR_FIELD, "FTR");
949        find_dup(&BPS_FIELD, "BPS");
950        find_dup(&EPS_FIELD, "EPS");
951        find_dup(&GDR_FIELD, "GDR");
952        find_dup(&DTR_FIELD, "DTR");
953    }
954
955    #[cfg(feature = "atdf")]
956    #[test]
957    fn test_atdf_field_req_count() {
958        assert_eq!(3, atdf_types::count_reqired(&PTR_FIELD));
959        assert_eq!(0, atdf_types::count_reqired(&GDR_FIELD));
960    }
961}