rust_stdf/
stdf_types.rs

1//
2// stdf_types.rs
3// Author: noonchen - chennoon233@foxmail.com
4// Created Date: October 3rd 2022
5// -----
6// Last Modified: Wed Nov 16 2022
7// Modified By: noonchen
8// -----
9// Copyright (c) 2022 noonchen
10//
11
12use crate::stdf_error::StdfError;
13extern crate smart_default;
14use smart_default::SmartDefault;
15use std::convert::From;
16
17#[cfg(feature = "serialize")]
18use serde::Serialize;
19#[cfg(feature = "serialize")]
20use struct_field_names_as_array::FieldNamesAsArray;
21
22macro_rules! read_optional {
23    ($var:expr, [$func:ident($raw:expr, $pos:expr)], $min_bytes:expr) => {{
24        if *$pos + $min_bytes > $raw.len() {
25            $var = None;
26            return;
27        } else {
28            $var = Some([$func($raw, $pos)]);
29        }
30    }};
31    ($var:expr, $func:ident($raw:expr, $pos:expr), $min_bytes:expr) => {{
32        if *$pos + $min_bytes > $raw.len() {
33            $var = None;
34            return;
35        } else {
36            $var = Some($func($raw, $pos));
37        }
38    }};
39    ($var:expr, $func:ident($raw:expr, $pos:expr, $order:expr), $min_bytes:expr) => {{
40        if *$pos + $min_bytes > $raw.len() {
41            $var = None;
42        } else {
43            $var = Some($func($raw, $pos, $order));
44        }
45    }};
46    ($var:expr, $func:ident($raw:expr, $pos:expr, $order:expr, $cnt:expr), $element_bytes:expr) => {{
47        if *$pos + $element_bytes * $cnt as usize > $raw.len() {
48            $var = None;
49        } else {
50            $var = Some($func($raw, $pos, $order, $cnt));
51        }
52    }};
53}
54
55// Common Type
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub enum ByteOrder {
58    LittleEndian,
59    BigEndian,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum CompressType {
64    Uncompressed,
65    #[cfg(feature = "gzip")]
66    GzipCompressed,
67    #[cfg(feature = "bzip")]
68    BzipCompressed,
69    #[cfg(feature = "zipfile")]
70    ZipCompressed,
71}
72
73#[derive(SmartDefault, Debug, Clone, Copy, PartialEq, Eq)]
74pub struct RecordHeader {
75    pub len: u16,
76    pub typ: u8,
77    pub sub: u8,
78}
79
80// Data Types
81
82/// Altough B1 can be treated as u8, but its representation
83/// in ATDF is differ from U1, so I used a array of one u8 for B1
84pub type B1 = [u8; 1];
85/// Rust char is 4 bytes long, however STDF char is only 1 byte
86/// we will read u8 from file stream and convert to Rust char during parse step
87pub type C1 = char;
88pub type U1 = u8;
89pub type U2 = u16;
90pub type U4 = u32;
91pub type U8 = u64;
92pub type I1 = i8;
93pub type I2 = i16;
94pub type I4 = i32;
95pub type R4 = f32;
96pub type R8 = f64;
97
98// Cn;	//first byte = unsigned count of bytes to follow (maximum of 255 bytes)
99pub type Cn = String;
100
101// Variable length character string, string length is stored in another field
102pub type Cf = String;
103
104// first two bytes = unsigned count of bytes to follow (maximum of 65535 bytes)
105pub type Sn = String;
106
107// Bn;	//First byte = unsigned count of bytes to follow (maximum of 255 bytes)
108pub type Bn = Vec<u8>;
109
110// Dn;	//First two bytes = unsigned count of bits to follow (maximum of 65,535 bits)
111pub type Dn = Vec<u8>;
112
113pub type KxCn = Vec<Cn>;
114pub type KxSn = Vec<Sn>;
115pub type KxCf = Vec<Cf>;
116pub type KxU1 = Vec<U1>;
117pub type KxU2 = Vec<U2>;
118pub type KxU4 = Vec<U4>;
119pub type KxU8 = Vec<U8>;
120pub type KxR4 = Vec<R4>;
121pub type KxN1 = Vec<U1>;
122
123/// This enum is for STR that
124/// introduced in STDF V4-2007.
125///
126/// the nested data is a vector of Uf type,
127/// where f = 1, 2, 4 or 8
128#[cfg_attr(feature = "serialize", derive(Serialize))]
129#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
130pub enum KxUf {
131    #[default]
132    F1(KxU1),
133    F2(KxU2),
134    F4(KxU4),
135    F8(KxU8),
136}
137
138/// This enum is for storing
139/// generic data V1, the data type
140/// is the field name.
141#[cfg_attr(feature = "serialize", derive(Serialize))]
142#[derive(Debug, Clone, PartialEq)]
143pub enum V1 {
144    B0,
145    U1(U1),
146    U2(U2),
147    U4(U4),
148    I1(I1),
149    I2(I2),
150    I4(I4),
151    R4(R4),
152    R8(R8),
153    Cn(Cn),
154    Bn(Bn),
155    Dn(Dn),
156    N1(U1),
157    Invalid,
158}
159
160pub type Vn = Vec<V1>;
161
162// Record Types
163
164/// This module contains constants
165/// for STDF Record type check and
166/// some help functions
167///
168/// # Example
169///
170/// ```
171/// use rust_stdf::{StdfRecord, stdf_record_type::*};
172///
173/// // use constant for record initializing
174/// let mut rec = StdfRecord::new(REC_MIR);
175///
176/// // for type check
177/// let t = REC_MIR | REC_MRR | REC_PTR;
178/// let is_t = rec.is_type(t);      // true
179/// ```
180pub mod stdf_record_type {
181    use crate::stdf_error::StdfError;
182
183    // rec type 0
184    pub const REC_FAR: u64 = 1;
185    pub const REC_ATR: u64 = 1 << 1;
186    pub const REC_VUR: u64 = 1 << 2;
187    // rec type 1
188    pub const REC_MIR: u64 = 1 << 3;
189    pub const REC_MRR: u64 = 1 << 4;
190    pub const REC_PCR: u64 = 1 << 5;
191    pub const REC_HBR: u64 = 1 << 6;
192    pub const REC_SBR: u64 = 1 << 7;
193    pub const REC_PMR: u64 = 1 << 8;
194    pub const REC_PGR: u64 = 1 << 9;
195    pub const REC_PLR: u64 = 1 << 10;
196    pub const REC_RDR: u64 = 1 << 11;
197    pub const REC_SDR: u64 = 1 << 12;
198    pub const REC_PSR: u64 = 1 << 13;
199    pub const REC_NMR: u64 = 1 << 14;
200    pub const REC_CNR: u64 = 1 << 15;
201    pub const REC_SSR: u64 = 1 << 16;
202    pub const REC_CDR: u64 = 1 << 17;
203    // rec type 2
204    pub const REC_WIR: u64 = 1 << 18;
205    pub const REC_WRR: u64 = 1 << 19;
206    pub const REC_WCR: u64 = 1 << 20;
207    // rec type 5
208    pub const REC_PIR: u64 = 1 << 21;
209    pub const REC_PRR: u64 = 1 << 22;
210    // rec type 10
211    pub const REC_TSR: u64 = 1 << 23;
212    // rec type 15
213    pub const REC_PTR: u64 = 1 << 24;
214    pub const REC_MPR: u64 = 1 << 25;
215    pub const REC_FTR: u64 = 1 << 26;
216    pub const REC_STR: u64 = 1 << 27;
217    // rec type 20
218    pub const REC_BPS: u64 = 1 << 28;
219    pub const REC_EPS: u64 = 1 << 29;
220    // rec type 50
221    pub const REC_GDR: u64 = 1 << 30;
222    pub const REC_DTR: u64 = 1 << 31;
223    // rec type 180: Reserved
224    // rec type 181: Reserved
225    pub const REC_RESERVE: u64 = 1 << 32;
226    pub const REC_INVALID: u64 = 1 << 33;
227
228    /// This function convert record type constant to
229    /// STDF record (typ, sub)
230    ///
231    /// ```
232    /// use rust_stdf::stdf_record_type::*;
233    ///
234    /// let ptr_typ_sub = get_typ_sub_from_code(REC_PTR).unwrap();
235    /// assert_eq!((15, 10), ptr_typ_sub);
236    /// ```
237    #[inline(always)]
238    pub fn get_typ_sub_from_code(code: u64) -> Result<(u8, u8), StdfError> {
239        match code {
240            // rec type 15
241            REC_PTR => Ok((15, 10)),
242            REC_MPR => Ok((15, 15)),
243            REC_FTR => Ok((15, 20)),
244            REC_STR => Ok((15, 30)),
245            // rec type 5
246            REC_PIR => Ok((5, 10)),
247            REC_PRR => Ok((5, 20)),
248            // rec type 2
249            REC_WIR => Ok((2, 10)),
250            REC_WRR => Ok((2, 20)),
251            REC_WCR => Ok((2, 30)),
252            // rec type 50
253            REC_GDR => Ok((50, 10)),
254            REC_DTR => Ok((50, 30)),
255            // rec type 0
256            REC_FAR => Ok((0, 10)),
257            REC_ATR => Ok((0, 20)),
258            REC_VUR => Ok((0, 30)),
259            // rec type 1
260            REC_MIR => Ok((1, 10)),
261            REC_MRR => Ok((1, 20)),
262            REC_PCR => Ok((1, 30)),
263            REC_HBR => Ok((1, 40)),
264            REC_SBR => Ok((1, 50)),
265            REC_PMR => Ok((1, 60)),
266            REC_PGR => Ok((1, 62)),
267            REC_PLR => Ok((1, 63)),
268            REC_RDR => Ok((1, 70)),
269            REC_SDR => Ok((1, 80)),
270            REC_PSR => Ok((1, 90)),
271            REC_NMR => Ok((1, 91)),
272            REC_CNR => Ok((1, 92)),
273            REC_SSR => Ok((1, 93)),
274            REC_CDR => Ok((1, 94)),
275            // rec type 10
276            REC_TSR => Ok((10, 30)),
277            // rec type 20
278            REC_BPS => Ok((20, 10)),
279            REC_EPS => Ok((20, 20)),
280            // rec type 180: Reserved
281            // rec type 181: Reserved
282            // REC_RESERVE,(180 | 181, _)
283            // not matched
284            // REC_INVALID,(_, _)
285            _ => Err(StdfError {
286                code: 2,
287                msg: "unknown type constant".to_string(),
288            }),
289        }
290    }
291
292    /// This function convert (typ, sub) to
293    /// STDF record type constant
294    ///
295    /// ```
296    /// use rust_stdf::stdf_record_type::*;
297    ///
298    /// let type_code = get_code_from_typ_sub(15, 10);
299    /// assert_eq!(REC_PTR, type_code);
300    /// ```
301    #[inline(always)]
302    pub fn get_code_from_typ_sub(typ: u8, sub: u8) -> u64 {
303        match (typ, sub) {
304            // rec type 15
305            (15, 10) => REC_PTR,
306            (15, 15) => REC_MPR,
307            (15, 20) => REC_FTR,
308            (15, 30) => REC_STR,
309            // rec type 5
310            (5, 10) => REC_PIR,
311            (5, 20) => REC_PRR,
312            // rec type 2
313            (2, 10) => REC_WIR,
314            (2, 20) => REC_WRR,
315            (2, 30) => REC_WCR,
316            // rec type 50
317            (50, 10) => REC_GDR,
318            (50, 30) => REC_DTR,
319            // rec type 0
320            (0, 10) => REC_FAR,
321            (0, 20) => REC_ATR,
322            (0, 30) => REC_VUR,
323            // rec type 1
324            (1, 10) => REC_MIR,
325            (1, 20) => REC_MRR,
326            (1, 30) => REC_PCR,
327            (1, 40) => REC_HBR,
328            (1, 50) => REC_SBR,
329            (1, 60) => REC_PMR,
330            (1, 62) => REC_PGR,
331            (1, 63) => REC_PLR,
332            (1, 70) => REC_RDR,
333            (1, 80) => REC_SDR,
334            (1, 90) => REC_PSR,
335            (1, 91) => REC_NMR,
336            (1, 92) => REC_CNR,
337            (1, 93) => REC_SSR,
338            (1, 94) => REC_CDR,
339            // rec type 10
340            (10, 30) => REC_TSR,
341            // rec type 20
342            (20, 10) => REC_BPS,
343            (20, 20) => REC_EPS,
344            // rec type 180: Reserved
345            // rec type 181: Reserved
346            (180 | 181, _) => REC_RESERVE,
347            // not matched
348            (_, _) => REC_INVALID,
349        }
350    }
351
352    /// This function convert record type constant to
353    /// STDF record name string
354    ///
355    /// ```
356    /// use rust_stdf::stdf_record_type::*;
357    ///
358    /// let rec_name = get_rec_name_from_code(REC_PTR);
359    /// assert_eq!("PTR", rec_name);
360    /// ```
361    #[inline(always)]
362    pub fn get_rec_name_from_code(rec_type: u64) -> &'static str {
363        match rec_type {
364            // rec type 15
365            REC_PTR => "PTR",
366            REC_MPR => "MPR",
367            REC_FTR => "FTR",
368            REC_STR => "STR",
369            // rec type 5
370            REC_PIR => "PIR",
371            REC_PRR => "PRR",
372            // rec type 2
373            REC_WIR => "WIR",
374            REC_WRR => "WRR",
375            REC_WCR => "WCR",
376            // rec type 50
377            REC_GDR => "GDR",
378            REC_DTR => "DTR",
379            // rec type 0
380            REC_FAR => "FAR",
381            REC_ATR => "ATR",
382            REC_VUR => "VUR",
383            // rec type 1
384            REC_MIR => "MIR",
385            REC_MRR => "MRR",
386            REC_PCR => "PCR",
387            REC_HBR => "HBR",
388            REC_SBR => "SBR",
389            REC_PMR => "PMR",
390            REC_PGR => "PGR",
391            REC_PLR => "PLR",
392            REC_RDR => "RDR",
393            REC_SDR => "SDR",
394            REC_PSR => "PSR",
395            REC_NMR => "NMR",
396            REC_CNR => "CNR",
397            REC_SSR => "SSR",
398            REC_CDR => "CDR",
399            // rec type 10
400            REC_TSR => "TSR",
401            // rec type 20
402            REC_BPS => "BPS",
403            REC_EPS => "EPS",
404            // rec type 180: Reserved
405            // rec type 181: Reserved
406            REC_RESERVE => "ReservedRec",
407            // not matched
408            _ => "InvalidRec",
409        }
410    }
411
412    /// This function convert record name string to
413    /// STDF record type constant
414    ///
415    /// ```
416    /// use rust_stdf::stdf_record_type::*;
417    ///
418    /// let type_code = get_code_from_rec_name("PTR");
419    /// assert_eq!(REC_PTR, type_code);
420    /// ```
421    ///
422    #[inline(always)]
423    pub fn get_code_from_rec_name(rec_name: &str) -> u64 {
424        match rec_name {
425            "FAR" => REC_FAR,
426            "ATR" => REC_ATR,
427            "VUR" => REC_VUR,
428            "MIR" => REC_MIR,
429            "MRR" => REC_MRR,
430            "PCR" => REC_PCR,
431            "HBR" => REC_HBR,
432            "SBR" => REC_SBR,
433            "PMR" => REC_PMR,
434            "PGR" => REC_PGR,
435            "PLR" => REC_PLR,
436            "RDR" => REC_RDR,
437            "SDR" => REC_SDR,
438            "PSR" => REC_PSR,
439            "NMR" => REC_NMR,
440            "CNR" => REC_CNR,
441            "SSR" => REC_SSR,
442            "CDR" => REC_CDR,
443            "WIR" => REC_WIR,
444            "WRR" => REC_WRR,
445            "WCR" => REC_WCR,
446            "PIR" => REC_PIR,
447            "PRR" => REC_PRR,
448            "TSR" => REC_TSR,
449            "PTR" => REC_PTR,
450            "MPR" => REC_MPR,
451            "FTR" => REC_FTR,
452            "STR" => REC_STR,
453            "BPS" => REC_BPS,
454            "EPS" => REC_EPS,
455            "GDR" => REC_GDR,
456            "DTR" => REC_DTR,
457            _ => REC_INVALID,
458        }
459    }
460}
461
462/// `StdfRecord` is the data that returned from StdfReader iterator.
463///
464/// it contains the actually structs
465/// that contain STDF data.
466///
467/// use `match` structure to access the nested data.
468///
469/// # Example
470///
471/// ```
472/// use rust_stdf::{StdfRecord, stdf_record_type::*};
473///
474/// let mut rec = StdfRecord::new(REC_PTR);
475/// if let StdfRecord::PTR(ref mut ptr_data) = rec {
476///     ptr_data.result = 100.0;
477/// }
478/// println!("{:?}", rec);
479/// ```
480#[derive(Debug, Clone, PartialEq)]
481pub enum StdfRecord {
482    // rec type 0
483    FAR(FAR),
484    ATR(ATR),
485    VUR(VUR),
486    // rec type 1
487    MIR(MIR),
488    MRR(MRR),
489    PCR(PCR),
490    HBR(HBR),
491    SBR(SBR),
492    PMR(PMR),
493    PGR(PGR),
494    PLR(PLR),
495    RDR(RDR),
496    SDR(SDR),
497    PSR(PSR),
498    NMR(NMR),
499    CNR(CNR),
500    SSR(SSR),
501    CDR(CDR),
502    // rec type 2
503    WIR(WIR),
504    WRR(WRR),
505    WCR(WCR),
506    // rec type 5
507    PIR(PIR),
508    PRR(PRR),
509    // rec type 10
510    TSR(TSR),
511    // rec type 15
512    PTR(PTR),
513    MPR(MPR),
514    FTR(FTR),
515    STR(STR),
516    // rec type 20
517    BPS(BPS),
518    EPS(EPS),
519    // rec type 50
520    GDR(GDR),
521    DTR(DTR),
522    // rec type 180: Reserved
523    // rec type 181: Reserved
524    ReservedRec(ReservedRec),
525    InvalidRec(RecordHeader),
526}
527
528#[derive(Debug, Clone, PartialEq, Eq)]
529/// unprocessed STDF record data, contains:
530///  - offset
531///  - type_code
532///  - raw_data
533///  - byte_order
534///
535/// it can be converted back to `StdfRecord`
536/// ```
537/// use rust_stdf::{RawDataElement, ByteOrder, StdfRecord, RecordHeader, stdf_record_type::REC_FAR};
538///
539/// let rde = RawDataElement {
540///     offset: 0,
541///     header: RecordHeader {typ: 0, sub: 10, len: 2},
542///     raw_data: vec![0u8; 0],
543///     byte_order: ByteOrder::LittleEndian
544/// };
545/// let rec: StdfRecord = (&rde).into();    // not consume
546/// let rec: StdfRecord = rde.into();       // consume
547/// println!("{:?}", rec);
548/// assert!(rec.is_type(REC_FAR));
549/// ```
550pub struct RawDataElement {
551    /// file offset of `raw_data` in file,
552    /// after header.len and before raw_data
553    ///
554    /// |-typ-|-sub-|--len--⬇️--raw..data--|
555    ///
556    /// note that the offset is relative to the
557    /// file position that runs `get_rawdata_iter`,
558    ///
559    /// it can be treated as file position **only if**
560    /// the iteration starts from beginning of the file.
561    pub offset: u64,
562
563    /// used for identifying StdfRecord types
564    pub header: RecordHeader,
565
566    /// field data of current STDF Record
567    pub raw_data: Vec<u8>,
568    pub byte_order: ByteOrder,
569}
570
571#[cfg_attr(
572    feature = "serialize",
573    derive(Serialize, FieldNamesAsArray),
574    serde(rename_all = "UPPERCASE"),
575    field_names_as_array(rename_all = "UPPERCASE")
576)]
577#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
578pub struct FAR {
579    pub cpu_type: U1, // CPU type that wrote this file
580    pub stdf_ver: U1, // STDF version number
581}
582
583#[cfg_attr(
584    feature = "serialize",
585    derive(Serialize, FieldNamesAsArray),
586    serde(rename_all = "UPPERCASE"),
587    field_names_as_array(rename_all = "UPPERCASE")
588)]
589#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
590pub struct ATR {
591    pub mod_tim: U4,  //Date and time of STDF file modification
592    pub cmd_line: Cn, //Command line of program
593}
594
595#[cfg_attr(
596    feature = "serialize",
597    derive(Serialize, FieldNamesAsArray),
598    serde(rename_all = "UPPERCASE"),
599    field_names_as_array(rename_all = "UPPERCASE")
600)]
601#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
602pub struct VUR {
603    pub upd_nam: Cn, //Update Version Name
604}
605
606#[cfg_attr(
607    feature = "serialize",
608    derive(Serialize, FieldNamesAsArray),
609    serde(rename_all = "UPPERCASE"),
610    field_names_as_array(rename_all = "UPPERCASE")
611)]
612#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
613pub struct MIR {
614    pub setup_t: U4,  // Date and time of job setup
615    pub start_t: U4,  // Date and time first part tested
616    pub stat_num: U1, // Tester station number
617    #[default = ' ']
618    pub mode_cod: C1, // Test mode code (e.g. prod, dev)
619    #[default = ' ']
620    pub rtst_cod: C1, // Lot retest code
621    #[default = ' ']
622    pub prot_cod: C1, // Data protection code
623    #[default = 65535]
624    pub burn_tim: U2, // Burn-in time (in minutes)
625    #[default = ' ']
626    pub cmod_cod: C1, // Command mode code
627    pub lot_id: Cn,   // Lot ID (customer specified)
628    pub part_typ: Cn, // Part Type (or product ID)
629    pub node_nam: Cn, // Name of node that generated data
630    pub tstr_typ: Cn, // Tester type
631    pub job_nam: Cn,  // Job name (test program name)
632    pub job_rev: Cn,  // Job (test program) revision number
633    pub sblot_id: Cn, // Sublot ID
634    pub oper_nam: Cn, // Operator name or ID (at setup time)
635    pub exec_typ: Cn, // Tester executive software type
636    pub exec_ver: Cn, // Tester exec software version number
637    pub test_cod: Cn, // Test phase or step code
638    pub tst_temp: Cn, // Test temperature
639    pub user_txt: Cn, // Generic user text
640    pub aux_file: Cn, // Name of auxiliary data file
641    pub pkg_typ: Cn,  // Package type
642    pub famly_id: Cn, // Product family ID
643    pub date_cod: Cn, // Date code
644    pub facil_id: Cn, // Test facility ID
645    pub floor_id: Cn, // Test floor ID
646    pub proc_id: Cn,  // Fabrication process ID
647    pub oper_frq: Cn, // Operation frequency or step
648    pub spec_nam: Cn, // Test specification name
649    pub spec_ver: Cn, // Test specification version number
650    pub flow_id: Cn,  // Test flow ID
651    pub setup_id: Cn, // Test setup ID
652    pub dsgn_rev: Cn, // Device design revision
653    pub eng_id: Cn,   // Engineering lot ID
654    pub rom_cod: Cn,  // ROM code ID
655    pub serl_num: Cn, // Tester serial number
656    pub supr_nam: Cn, // Supervisor name or ID
657}
658
659#[cfg_attr(
660    feature = "serialize",
661    derive(Serialize, FieldNamesAsArray),
662    serde(rename_all = "UPPERCASE"),
663    field_names_as_array(rename_all = "UPPERCASE")
664)]
665#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
666pub struct MRR {
667    pub finish_t: U4, // Date and time last part tested
668    #[default = ' ']
669    pub disp_cod: C1, // Lot disposition code,default: space
670    pub usr_desc: Cn, // Lot description supplied by user
671    pub exc_desc: Cn, // Lot description supplied by exec
672}
673
674#[cfg_attr(
675    feature = "serialize",
676    derive(Serialize, FieldNamesAsArray),
677    serde(rename_all = "UPPERCASE"),
678    field_names_as_array(rename_all = "UPPERCASE")
679)]
680#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
681pub struct PCR {
682    pub head_num: U1, // Test head number
683    pub site_num: U1, // Test site number
684    pub part_cnt: U4, // Number of parts tested
685    #[default = 4_294_967_295]
686    pub rtst_cnt: U4, // Number of parts retested
687    #[default = 4_294_967_295]
688    pub abrt_cnt: U4, // Number of aborts during testing
689    #[default = 4_294_967_295]
690    pub good_cnt: U4, // Number of good (passed) parts tested
691    #[default = 4_294_967_295]
692    pub func_cnt: U4, // Number of functional parts tested
693}
694
695#[cfg_attr(
696    feature = "serialize",
697    derive(Serialize, FieldNamesAsArray),
698    serde(rename_all = "UPPERCASE"),
699    field_names_as_array(rename_all = "UPPERCASE")
700)]
701#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
702pub struct HBR {
703    pub head_num: U1, // Test head number
704    pub site_num: U1, // Test site number
705    pub hbin_num: U2, // Hardware bin number
706    pub hbin_cnt: U4, // Number of parts in bin
707    #[default = ' ']
708    pub hbin_pf: C1, // Pass/fail indication
709    pub hbin_nam: Cn, // Name of hardware bin
710}
711
712#[cfg_attr(
713    feature = "serialize",
714    derive(Serialize, FieldNamesAsArray),
715    serde(rename_all = "UPPERCASE"),
716    field_names_as_array(rename_all = "UPPERCASE")
717)]
718#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
719pub struct SBR {
720    pub head_num: U1, // Test head number
721    pub site_num: U1, // Test site number
722    pub sbin_num: U2, // Software bin number
723    pub sbin_cnt: U4, // Number of parts in bin
724    #[default = ' ']
725    pub sbin_pf: C1, // Pass/fail indication
726    pub sbin_nam: Cn, // Name of software bin
727}
728
729#[cfg_attr(
730    feature = "serialize",
731    derive(Serialize, FieldNamesAsArray),
732    serde(rename_all = "UPPERCASE"),
733    field_names_as_array(rename_all = "UPPERCASE")
734)]
735#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
736pub struct PMR {
737    pub pmr_indx: U2, // Unique index associated with pin
738    #[default = 0]
739    pub chan_typ: U2, // Channel type
740    pub chan_nam: Cn, // Channel name
741    pub phy_nam: Cn,  // Physical name of pin
742    pub log_nam: Cn,  // Logical name of pin
743    #[default = 1]
744    pub head_num: U1, // Head number associated with channel
745    #[default = 1]
746    pub site_num: U1, // Site number associated with channel
747}
748
749#[cfg_attr(
750    feature = "serialize",
751    derive(Serialize, FieldNamesAsArray),
752    serde(rename_all = "UPPERCASE"),
753    field_names_as_array(rename_all = "UPPERCASE")
754)]
755#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
756pub struct PGR {
757    pub grp_indx: U2,   // Unique index associated with pin group
758    pub grp_nam: Cn,    // Name of pin group
759    pub indx_cnt: U2,   // Count of PMR indexes
760    pub pmr_indx: KxU2, // Array of indexes for pins in the group
761}
762
763#[cfg_attr(
764    feature = "serialize",
765    derive(Serialize, FieldNamesAsArray),
766    serde(rename_all = "UPPERCASE"),
767    field_names_as_array(rename_all = "UPPERCASE")
768)]
769#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
770pub struct PLR {
771    pub grp_cnt: U2,    // Count (k) of pins or pin groups
772    pub grp_indx: KxU2, // Array of pin or pin group indexes
773    pub grp_mode: KxU2, // Operating mode of pin group
774    pub grp_radx: KxU1, // Display radix of pin group
775    pub pgm_char: KxCn, // Program state encoding characters
776    pub rtn_char: KxCn, // Return state encoding characters
777    pub pgm_chal: KxCn, // Program state encoding characters
778    pub rtn_chal: KxCn, // Return state encoding characters
779}
780
781#[cfg_attr(
782    feature = "serialize",
783    derive(Serialize, FieldNamesAsArray),
784    serde(rename_all = "UPPERCASE"),
785    field_names_as_array(rename_all = "UPPERCASE")
786)]
787#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
788pub struct RDR {
789    pub num_bins: U2,   // Number (k) of bins being retested
790    pub rtst_bin: KxU2, // Array of retest bin numbers
791}
792
793#[cfg_attr(
794    feature = "serialize",
795    derive(Serialize, FieldNamesAsArray),
796    serde(rename_all = "UPPERCASE"),
797    field_names_as_array(rename_all = "UPPERCASE")
798)]
799#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
800pub struct SDR {
801    pub head_num: U1,   // Test head number
802    pub site_grp: U1,   // Site group number
803    pub site_cnt: U1,   // Number (k) of test sites in site group
804    pub site_num: KxU1, // Array of test site numbers
805    pub hand_typ: Cn,   // Handler or prober type
806    pub hand_id: Cn,    // Handler or prober ID
807    pub card_typ: Cn,   // Probe card type
808    pub card_id: Cn,    // Probe card ID
809    pub load_typ: Cn,   // Load board type
810    pub load_id: Cn,    // Load board ID
811    pub dib_typ: Cn,    // DIB board type
812    pub dib_id: Cn,     // DIB board ID
813    pub cabl_typ: Cn,   // Interface cable type
814    pub cabl_id: Cn,    // Interface cable ID
815    pub cont_typ: Cn,   // Handler contactor type
816    pub cont_id: Cn,    // Handler contactor ID
817    pub lasr_typ: Cn,   // Laser type
818    pub lasr_id: Cn,    // Laser ID
819    pub extr_typ: Cn,   // Extra equipment type field
820    pub extr_id: Cn,    // Extra equipment ID
821}
822
823#[cfg_attr(
824    feature = "serialize",
825    derive(Serialize, FieldNamesAsArray),
826    serde(rename_all = "UPPERCASE"),
827    field_names_as_array(rename_all = "UPPERCASE")
828)]
829#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
830pub struct PSR {
831    pub cont_flg: B1,   // Continuation PSR record exist
832    pub psr_indx: U2,   // PSR Record Index (used by STR records)
833    pub psr_nam: Cn,    // Symbolic name of PSR record
834    pub opt_flg: B1, // Contains PAT_LBL, FILE_UID, ATPG_DSC, and SRC_ID field missing flag bits and flag for start index for first cycle number.
835    pub totp_cnt: U2, // Count of total pattern file information sets in the complete PSR data set
836    pub locp_cnt: U2, // Count (k) of pattern file information sets in this record
837    pub pat_bgn: KxU8, // Array of Cycle #’s patterns begins on
838    pub pat_end: KxU8, // Array of Cycle #’s patterns stops at
839    pub pat_file: KxCn, // Array of Pattern File Names
840    pub pat_lbl: KxCn, // Optional pattern symbolic name
841    pub file_uid: KxCn, // Optional array of file identifier code
842    pub atpg_dsc: KxCn, // Optional array of ATPG information
843    pub src_id: KxCn, // Optional array of PatternInSrcFileID
844}
845
846#[cfg_attr(
847    feature = "serialize",
848    derive(Serialize, FieldNamesAsArray),
849    serde(rename_all = "UPPERCASE"),
850    field_names_as_array(rename_all = "UPPERCASE")
851)]
852#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
853pub struct NMR {
854    pub cont_flg: B1,   // Continuation NMR record follows if not 0
855    pub totm_cnt: U2,   // Count of PMR indexes and ATPG_NAM entries
856    pub locm_cnt: U2,   // Count of (k) PMR indexes and ATPG_NAM entries in this record
857    pub pmr_indx: KxU2, // Array of PMR indexes
858    pub atpg_nam: KxCn, // Array of ATPG signal names
859}
860
861#[cfg_attr(
862    feature = "serialize",
863    derive(Serialize, FieldNamesAsArray),
864    serde(rename_all = "UPPERCASE"),
865    field_names_as_array(rename_all = "UPPERCASE")
866)]
867#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
868pub struct CNR {
869    pub chn_num: U2,  // Chain number. Referenced by the CHN_NUM array in an STR record
870    pub bit_pos: U4,  // Bit position in the chain
871    pub cell_nam: Sn, // Scan Cell Name
872}
873
874#[cfg_attr(
875    feature = "serialize",
876    derive(Serialize, FieldNamesAsArray),
877    serde(rename_all = "UPPERCASE"),
878    field_names_as_array(rename_all = "UPPERCASE")
879)]
880#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
881pub struct SSR {
882    pub ssr_nam: Cn,    // Name of the STIL Scan pub structure for reference
883    pub chn_cnt: U2,    // Count (k) of number of Chains listed in CHN_LIST
884    pub chn_list: KxU2, // Array of CDR Indexes
885}
886
887#[cfg_attr(
888    feature = "serialize",
889    derive(Serialize, FieldNamesAsArray),
890    serde(rename_all = "UPPERCASE"),
891    field_names_as_array(rename_all = "UPPERCASE")
892)]
893#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
894pub struct CDR {
895    pub cont_flg: B1, // Continuation CDR record follows if not 0
896    pub cdr_indx: U2, // SCR Index
897    pub chn_nam: Cn,  // Chain Name
898    pub chn_len: U4,  // Chain Length (# of scan cells in chain)
899    pub sin_pin: U2,  // PMR index of the chain's Scan In Signal
900    pub sout_pin: U2, // PMR index of the chain's Scan Out Signal
901    pub mstr_cnt: U1, // Count (m) of master clock pins specified for this scan chain
902    pub m_clks: KxU2, // Array of PMR indexes for the master clocks assigned to this chain
903    pub slav_cnt: U1, // Count (n) of slave clock pins specified for this scan chain
904    pub s_clks: KxU2, // Array of PMR indexes for the slave clocks assigned to this chain
905    #[default = 255]
906    pub inv_val: U1, // 0: No Inversion, 1: Inversion
907    pub lst_cnt: U2,  // Count (k) of scan cells listed in this record
908    pub cell_lst: KxSn, // Array of Scan Cell Names
909}
910
911#[cfg_attr(
912    feature = "serialize",
913    derive(Serialize, FieldNamesAsArray),
914    serde(rename_all = "UPPERCASE"),
915    field_names_as_array(rename_all = "UPPERCASE")
916)]
917#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
918pub struct WIR {
919    pub head_num: U1, // Test head number
920    #[default = 255]
921    pub site_grp: U1, // Site group number
922    pub start_t: U4,  // Date and time first part tested
923    pub wafer_id: Cn, // Wafer ID length byte = 0
924}
925
926#[cfg_attr(
927    feature = "serialize",
928    derive(Serialize, FieldNamesAsArray),
929    serde(rename_all = "UPPERCASE"),
930    field_names_as_array(rename_all = "UPPERCASE")
931)]
932#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
933pub struct WRR {
934    pub head_num: U1, // Test head number
935    #[default = 255]
936    pub site_grp: U1, // Site group number
937    pub finish_t: U4, // Date and time last part tested
938    pub part_cnt: U4, // Number of parts tested
939    #[default = 4_294_967_295]
940    pub rtst_cnt: U4, // Number of parts retested
941    #[default = 4_294_967_295]
942    pub abrt_cnt: U4, // Number of aborts during testing
943    #[default = 4_294_967_295]
944    pub good_cnt: U4, // Number of good (passed) parts tested
945    #[default = 4_294_967_295]
946    pub func_cnt: U4, // Number of functional parts tested
947    pub wafer_id: Cn, // Wafer ID
948    pub fabwf_id: Cn, // Fab wafer ID
949    pub frame_id: Cn, // Wafer frame ID
950    pub mask_id: Cn,  // Wafer mask ID
951    pub usr_desc: Cn, // Wafer description supplied by user
952    pub exc_desc: Cn, // Wafer description supplied by exec
953}
954
955#[cfg_attr(
956    feature = "serialize",
957    derive(Serialize, FieldNamesAsArray),
958    serde(rename_all = "UPPERCASE"),
959    field_names_as_array(rename_all = "UPPERCASE")
960)]
961#[derive(SmartDefault, Debug, Clone, PartialEq)]
962pub struct WCR {
963    #[default = 0.0]
964    pub wafr_siz: R4, // Diameter of wafer in WF_UNITS
965    #[default = 0.0]
966    pub die_ht: R4, // Height of die in WF_UNITS
967    #[default = 0.0]
968    pub die_wid: R4, // Width of die in WF_UNITS
969    #[default = 0]
970    pub wf_units: U1, // Units for wafer and die dimensions
971    #[default = ' ']
972    pub wf_flat: C1, // Orientation of wafer flat
973    #[default(-32768)]
974    pub center_x: I2, // X coordinate of center die on wafer
975    #[default(-32768)]
976    pub center_y: I2, // Y coordinate of center die on wafer
977    #[default = ' ']
978    pub pos_x: C1, // Positive X direction of wafer
979    #[default = ' ']
980    pub pos_y: C1, // Positive Y direction of wafer
981}
982
983#[cfg_attr(
984    feature = "serialize",
985    derive(Serialize, FieldNamesAsArray),
986    serde(rename_all = "UPPERCASE"),
987    field_names_as_array(rename_all = "UPPERCASE")
988)]
989#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
990pub struct PIR {
991    pub head_num: U1, // Test head number
992    pub site_num: U1, // Test site number
993}
994
995#[cfg_attr(
996    feature = "serialize",
997    derive(Serialize, FieldNamesAsArray),
998    serde(rename_all = "UPPERCASE"),
999    field_names_as_array(rename_all = "UPPERCASE")
1000)]
1001#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
1002pub struct PRR {
1003    pub head_num: U1, //Test head number
1004    pub site_num: U1, //Test site number
1005    pub part_flg: B1, //Part information flag
1006    pub num_test: U2, //Number of tests executed
1007    pub hard_bin: U2, //Hardware bin number
1008    #[default = 65535]
1009    pub soft_bin: U2, //Software bin number
1010    #[default(-32768)]
1011    pub x_coord: I2, //(Wafer) X coordinate
1012    #[default(-32768)]
1013    pub y_coord: I2, //(Wafer) Y coordinate
1014    #[default = 0]
1015    pub test_t: U4, //Elapsed test time in milliseconds
1016    pub part_id: Cn,  //Part identification
1017    pub part_txt: Cn, //Part description text
1018    pub part_fix: Bn, //Part repair information
1019}
1020
1021#[cfg_attr(
1022    feature = "serialize",
1023    derive(Serialize, FieldNamesAsArray),
1024    serde(rename_all = "UPPERCASE"),
1025    field_names_as_array(rename_all = "UPPERCASE")
1026)]
1027#[derive(SmartDefault, Debug, Clone, PartialEq)]
1028pub struct TSR {
1029    pub head_num: U1, // Test head number
1030    pub site_num: U1, // Test site number
1031    #[default = ' ']
1032    pub test_typ: C1, // Test type
1033    pub test_num: U4, // Test number
1034    #[default = 4_294_967_295]
1035    pub exec_cnt: U4, // Number of test executions
1036    #[default = 4_294_967_295]
1037    pub fail_cnt: U4, // Number of test failures
1038    #[default = 4_294_967_295]
1039    pub alrm_cnt: U4, // Number of alarmed tests
1040    pub test_nam: Cn, // Test name
1041    pub seq_name: Cn, // Sequencer (program segment/flow) name
1042    pub test_lbl: Cn, // Test label or text
1043    pub opt_flag: B1, // Optional data flag
1044    pub test_tim: R4, // Average test execution time in seconds
1045    pub test_min: R4, // Lowest test result value
1046    pub test_max: R4, // Highest test result value
1047    pub tst_sums: R4, // Sum of test result values
1048    pub tst_sqrs: R4, // Sum of squares of test result values
1049}
1050
1051#[cfg_attr(
1052    feature = "serialize",
1053    derive(Serialize, FieldNamesAsArray),
1054    serde(rename_all = "UPPERCASE"),
1055    field_names_as_array(rename_all = "UPPERCASE")
1056)]
1057#[derive(SmartDefault, Debug, Clone, PartialEq)]
1058pub struct PTR {
1059    pub test_num: U4,         // Test number
1060    pub head_num: U1,         // Test head number
1061    pub site_num: U1,         // Test site number
1062    pub test_flg: B1,         // Test flags (fail, alarm, etc.)
1063    pub parm_flg: B1,         // Parametric test flags (drift, etc.)
1064    pub result: R4,           // Test result
1065    pub test_txt: Cn,         // Test description text or label
1066    pub alarm_id: Cn,         // Name of alarm
1067    pub opt_flag: Option<B1>, // Optional data flag
1068    pub res_scal: Option<I1>, // Test results scaling exponent
1069    pub llm_scal: Option<I1>, // Low limit scaling exponent
1070    pub hlm_scal: Option<I1>, // High limit scaling exponent
1071    pub lo_limit: Option<R4>, // Low test limit value
1072    pub hi_limit: Option<R4>, // High test limit value
1073    pub units: Option<Cn>,    // Test units
1074    pub c_resfmt: Option<Cn>, // ANSI C result format string
1075    pub c_llmfmt: Option<Cn>, // ANSI C low limit format string
1076    pub c_hlmfmt: Option<Cn>, // ANSI C high limit format string
1077    pub lo_spec: Option<R4>,  // Low specification limit value
1078    pub hi_spec: Option<R4>,  // High specification limit value
1079}
1080
1081#[cfg_attr(
1082    feature = "serialize",
1083    derive(Serialize, FieldNamesAsArray),
1084    serde(rename_all = "UPPERCASE"),
1085    field_names_as_array(rename_all = "UPPERCASE")
1086)]
1087#[derive(SmartDefault, Debug, Clone, PartialEq)]
1088pub struct MPR {
1089    pub test_num: U4,           // Test number
1090    pub head_num: U1,           // Test head number
1091    pub site_num: U1,           // Test site number
1092    pub test_flg: B1,           // Test flags (fail, alarm, etc.)
1093    pub parm_flg: B1,           // Parametric test flags (drift, etc.)
1094    pub rtn_icnt: U2,           // Count of PMR indexes
1095    pub rslt_cnt: U2,           // Count of returned results
1096    pub rtn_stat: KxN1,         // Array of returned states
1097    pub rtn_rslt: KxR4,         // Array of returned results
1098    pub test_txt: Cn,           // Descriptive text or label
1099    pub alarm_id: Cn,           // Name of alarm
1100    pub opt_flag: Option<B1>,   // Optional data flag
1101    pub res_scal: Option<I1>,   // Test result scaling exponent
1102    pub llm_scal: Option<I1>,   // Test low limit scaling exponent
1103    pub hlm_scal: Option<I1>,   // Test high limit scaling exponent
1104    pub lo_limit: Option<R4>,   // Test low limit value
1105    pub hi_limit: Option<R4>,   // Test high limit value
1106    pub start_in: Option<R4>,   // Starting input value (condition)
1107    pub incr_in: Option<R4>,    // Increment of input condition
1108    pub rtn_indx: Option<KxU2>, // Array of PMR indexes
1109    pub units: Option<Cn>,      // Units of returned results
1110    pub units_in: Option<Cn>,   // Input condition units
1111    pub c_resfmt: Option<Cn>,   // ANSI C result format string
1112    pub c_llmfmt: Option<Cn>,   // ANSI C low limit format string
1113    pub c_hlmfmt: Option<Cn>,   // ANSI C high limit format string
1114    pub lo_spec: Option<R4>,    // Low specification limit value
1115    pub hi_spec: Option<R4>,    // High specification limit value
1116}
1117
1118#[cfg_attr(
1119    feature = "serialize",
1120    derive(Serialize, FieldNamesAsArray),
1121    serde(rename_all = "UPPERCASE"),
1122    field_names_as_array(rename_all = "UPPERCASE")
1123)]
1124#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
1125pub struct FTR {
1126    pub test_num: U4,   // Test number
1127    pub head_num: U1,   // Test head number
1128    pub site_num: U1,   // Test site number
1129    pub test_flg: B1,   // Test flags (fail, alarm, etc.)
1130    pub opt_flag: B1,   // Optional data flag
1131    pub cycl_cnt: U4,   // Cycle count of vector
1132    pub rel_vadr: U4,   // Relative vector address
1133    pub rept_cnt: U4,   // Repeat count of vector
1134    pub num_fail: U4,   // Number of pins with 1 or more failures
1135    pub xfail_ad: I4,   // X logical device failure address
1136    pub yfail_ad: I4,   // Y logical device failure address
1137    pub vect_off: I2,   // Offset from vector of interest
1138    pub rtn_icnt: U2,   // Count j of return data PMR indexes
1139    pub pgm_icnt: U2,   // Count k of programmed state indexes
1140    pub rtn_indx: KxU2, // Array j of return data PMR indexes
1141    pub rtn_stat: KxN1, // Array j of returned states
1142    pub pgm_indx: KxU2, // Array k of programmed state indexes
1143    pub pgm_stat: KxN1, // Array k of programmed states
1144    pub fail_pin: Dn,   // Failing pin bitfield
1145    pub vect_nam: Cn,   // Vector module pattern name
1146    pub time_set: Cn,   // Time set name
1147    pub op_code: Cn,    // Vector Op Code
1148    pub test_txt: Cn,   // Descriptive text or label
1149    pub alarm_id: Cn,   // Name of alarm
1150    pub prog_txt: Cn,   // Additional programmed information
1151    pub rslt_txt: Cn,   // Additional result information
1152    #[default = 255]
1153    pub patg_num: U1, // Pattern generator number
1154    pub spin_map: Dn,   // Bit map of enabled comparators
1155}
1156
1157#[cfg_attr(
1158    feature = "serialize",
1159    derive(Serialize, FieldNamesAsArray),
1160    serde(rename_all = "UPPERCASE"),
1161    field_names_as_array(rename_all = "UPPERCASE")
1162)]
1163#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
1164pub struct STR {
1165    pub cont_flg: B1,   // Continuation STR follows if not 0
1166    pub test_num: U4,   // Test number
1167    pub head_num: U1,   // Test head number
1168    pub site_num: U1,   // Test site number
1169    pub psr_ref: U2,    // PSR Index (Pattern Sequence Record)
1170    pub test_flg: B1,   // Test flags (fail, alarm, etc.)
1171    pub log_typ: Cn,    // User defined description of datalog
1172    pub test_txt: Cn,   // Descriptive text or label
1173    pub alarm_id: Cn,   // Name of alarm
1174    pub prog_txt: Cn,   // Additional Programmed information
1175    pub rslt_txt: Cn,   // Additional result information
1176    pub z_val: U1,      // Z Handling Flag
1177    pub fmu_flg: B1,    // MASK_MAP & FAL_MAP field status & Pattern Changed flag
1178    pub mask_map: Dn,   // Bit map of Globally Masked Pins
1179    pub fal_map: Dn,    // Bit map of failures after buffer full
1180    pub cyc_cnt_t: U8,  // Total cycles executed in test
1181    pub totf_cnt: U4,   // Total failures (pin x cycle) detected in test execution
1182    pub totl_cnt: U4,   // Total fails logged across the complete STR data set
1183    pub cyc_base: U8,   // Cycle offset to apply for the values in the CYCL_NUM array
1184    pub bit_base: U4,   // Offset to apply for the values in the BIT_POS array
1185    pub cond_cnt: U2, // Count (g) of Test Conditions and optional data specifications in present record
1186    pub lim_cnt: U2,  // Count (j) of LIM Arrays in present record, 1 for global specification
1187    pub cyc_size: U1, // Size (f) of data (1,2,4, or 8 byes) in CYC_OFST field
1188    pub pmr_size: U1, // Size (f) of data (1 or 2 bytes) in PMR_INDX field
1189    pub chn_size: U1, // Size (f) of data (1, 2 or 4 bytes) in CHN_NUM field
1190    pub pat_size: U1, // Size (f) of data (1,2, or 4 bytes) in PAT_NUM field
1191    pub bit_size: U1, // Size (f) of data (1,2, or 4 bytes) in BIT_POS field
1192    pub u1_size: U1,  // Size (f) of data (1,2,4 or 8 bytes) in USR1 field
1193    pub u2_size: U1,  // Size (f) of data (1,2,4 or 8 bytes) in USR2 field
1194    pub u3_size: U1,  // Size (f) of data (1,2,4 or 8 bytes) in USR3 field
1195    pub utx_size: U1, // Size (f) of each string entry in USER_TXT array
1196    pub cap_bgn: U2,  // Offset added to BIT_POS value to indicate capture cycles
1197    pub lim_indx: KxU2, // Array of PMR indexes that require unique limit specifications
1198    pub lim_spec: KxU4, // Array of fail datalogging limits for the PMRs listed in LIM_INDX
1199    pub cond_lst: KxCn, // Array of test condition (Name=value) pairs
1200    pub cyc_cnt: U2,  // Count (k) of entries in CYC_OFST array
1201    pub cyc_ofst: KxUf, // Array of cycle numbers relative to CYC_BASE
1202    pub pmr_cnt: U2,  // Count (k) of entries in the PMR_INDX array
1203    pub pmr_indx: KxUf, // Array of PMR Indexes (All Formats)
1204    pub chn_cnt: U2,  // Count (k) of entries in the CHN_NUM array
1205    pub chn_num: KxUf, // Array of Chain No for FF Name Mapping
1206    pub exp_cnt: U2,  // Count (k) of EXP_DATA array entries
1207    pub exp_data: KxU1, // Array of expected vector data
1208    pub cap_cnt: U2,  // Count (k) of CAP_DATA array entries
1209    pub cap_data: KxU1, // Array of captured data
1210    pub new_cnt: U2,  // Count (k) of NEW_DATA array entries
1211    pub new_data: KxU1, // Array of new vector data
1212    pub pat_cnt: U2,  // Count (k) of PAT_NUM array entries
1213    pub pat_num: KxUf, // Array of pattern # (Ptn/Chn/Bit format)
1214    pub bpos_cnt: U2, // Count (k) of BIT_POS array entries
1215    pub bit_pos: KxUf, // Array of chain bit positions (Ptn/Chn/Bit format)
1216    pub usr1_cnt: U2, // Count (k) of USR1 array entries
1217    pub usr1: KxUf,   // Array of user defined data for each logged fail
1218    pub usr2_cnt: U2, // Count (k) of USR2 array entries
1219    pub usr2: KxUf,   // Array of user defined data for each logged fail
1220    pub usr3_cnt: U2, // Count (k) of USR3 array entries
1221    pub usr3: KxUf,   // Array of user defined data for each logged fail
1222    pub txt_cnt: U2,  // Count (k) of USER_TXT array entries
1223    pub user_txt: KxCf, // Array of user defined fixed length strings for each logged fail
1224}
1225
1226#[cfg_attr(
1227    feature = "serialize",
1228    derive(Serialize, FieldNamesAsArray),
1229    serde(rename_all = "UPPERCASE"),
1230    field_names_as_array(rename_all = "UPPERCASE")
1231)]
1232#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
1233pub struct BPS {
1234    pub seq_name: Cn, // Program section (or sequencer) name length byte = 0
1235}
1236
1237#[cfg_attr(
1238    feature = "serialize",
1239    derive(Serialize, FieldNamesAsArray),
1240    serde(rename_all = "UPPERCASE"),
1241    field_names_as_array(rename_all = "UPPERCASE")
1242)]
1243#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
1244pub struct EPS {}
1245
1246#[cfg_attr(
1247    feature = "serialize",
1248    derive(Serialize, FieldNamesAsArray),
1249    serde(rename_all = "UPPERCASE"),
1250    field_names_as_array(rename_all = "UPPERCASE")
1251)]
1252#[derive(SmartDefault, Debug, Clone, PartialEq)]
1253pub struct GDR {
1254    pub fld_cnt: U2,  // Count of data fields in record
1255    pub gen_data: Vn, // Data type code and data for one field(Repeat GEN_DATA for each data field)
1256}
1257
1258#[cfg_attr(
1259    feature = "serialize",
1260    derive(Serialize, FieldNamesAsArray),
1261    serde(rename_all = "UPPERCASE"),
1262    field_names_as_array(rename_all = "UPPERCASE")
1263)]
1264#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
1265pub struct DTR {
1266    pub text_dat: Cn, // ASCII text string
1267}
1268
1269#[cfg_attr(
1270    feature = "serialize",
1271    derive(Serialize, FieldNamesAsArray),
1272    serde(rename_all = "UPPERCASE"),
1273    field_names_as_array(rename_all = "UPPERCASE")
1274)]
1275#[derive(SmartDefault, Debug, Clone, PartialEq, Eq)]
1276pub struct ReservedRec {
1277    pub raw_data: Vec<u8>, // unparsed data
1278}
1279
1280// implementation
1281
1282impl RecordHeader {
1283    #[inline(always)]
1284    pub fn new() -> Self {
1285        RecordHeader::default()
1286    }
1287
1288    /// Construct a STDF record header from first 4 elements of given byte array,
1289    /// no error would occur even if the header is invalid.
1290    ///
1291    /// Unless the array size is less than 4, StdfError of
1292    /// `EOF` or `Unexpected EOF` will be returned
1293    #[inline(always)]
1294    pub fn read_from_bytes(
1295        mut self,
1296        raw_data: &[u8],
1297        order: &ByteOrder,
1298    ) -> Result<Self, StdfError> {
1299        match raw_data.len() {
1300            0 => Err(StdfError {
1301                code: 4,
1302                msg: String::from("No bytes to read"),
1303            }),
1304            1..=3 => Err(StdfError {
1305                code: 5,
1306                msg: String::from("Not enough data to construct record header"),
1307            }),
1308            _ => {
1309                let len_bytes = [raw_data[0], raw_data[1]];
1310                self.len = match order {
1311                    ByteOrder::LittleEndian => u16::from_le_bytes(len_bytes),
1312                    ByteOrder::BigEndian => u16::from_be_bytes(len_bytes),
1313                };
1314                self.typ = raw_data[2];
1315                self.sub = raw_data[3];
1316                // return even if we have a invalid record type, let other code to handle it
1317                Ok(self)
1318            }
1319        }
1320    }
1321
1322    /// return the type_code of current header
1323    pub fn get_type(&self) -> u64 {
1324        stdf_record_type::get_code_from_typ_sub(self.typ, self.sub)
1325    }
1326}
1327
1328impl FAR {
1329    #[inline(always)]
1330    pub fn new() -> Self {
1331        FAR::default()
1332    }
1333
1334    #[inline(always)]
1335    pub fn read_from_bytes(&mut self, raw_data: &[u8], _order: &ByteOrder) {
1336        let pos = &mut 0;
1337        self.cpu_type = read_uint8(raw_data, pos);
1338        self.stdf_ver = read_uint8(raw_data, pos);
1339    }
1340}
1341
1342impl ATR {
1343    #[inline(always)]
1344    pub fn new() -> Self {
1345        ATR::default()
1346    }
1347
1348    #[inline(always)]
1349    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1350        let pos = &mut 0;
1351        self.mod_tim = read_u4(raw_data, pos, order);
1352        self.cmd_line = read_cn(raw_data, pos);
1353    }
1354}
1355
1356impl VUR {
1357    #[inline(always)]
1358    pub fn new() -> Self {
1359        VUR::default()
1360    }
1361
1362    #[inline(always)]
1363    pub fn read_from_bytes(&mut self, raw_data: &[u8], _order: &ByteOrder) {
1364        let pos = &mut 0;
1365        self.upd_nam = read_cn(raw_data, pos);
1366    }
1367}
1368
1369impl MIR {
1370    #[inline(always)]
1371    pub fn new() -> Self {
1372        MIR::default()
1373    }
1374
1375    #[inline(always)]
1376    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1377        let pos = &mut 0;
1378        self.setup_t = read_u4(raw_data, pos, order);
1379        self.start_t = read_u4(raw_data, pos, order);
1380        self.stat_num = read_uint8(raw_data, pos);
1381        // if raw_data is completely parsed,
1382        // don't overwrite fields with default data
1383        if *pos < raw_data.len() {
1384            self.mode_cod = read_uint8(raw_data, pos) as char;
1385        }
1386        if *pos < raw_data.len() {
1387            self.rtst_cod = read_uint8(raw_data, pos) as char;
1388        }
1389        if *pos < raw_data.len() {
1390            self.prot_cod = read_uint8(raw_data, pos) as char;
1391        }
1392        if *pos + 2 <= raw_data.len() {
1393            self.burn_tim = read_u2(raw_data, pos, order);
1394        }
1395        if *pos < raw_data.len() {
1396            self.cmod_cod = read_uint8(raw_data, pos) as char;
1397        }
1398        self.lot_id = read_cn(raw_data, pos);
1399        self.part_typ = read_cn(raw_data, pos);
1400        self.node_nam = read_cn(raw_data, pos);
1401        self.tstr_typ = read_cn(raw_data, pos);
1402        self.job_nam = read_cn(raw_data, pos);
1403        self.job_rev = read_cn(raw_data, pos);
1404        self.sblot_id = read_cn(raw_data, pos);
1405        self.oper_nam = read_cn(raw_data, pos);
1406        self.exec_typ = read_cn(raw_data, pos);
1407        self.exec_ver = read_cn(raw_data, pos);
1408        self.test_cod = read_cn(raw_data, pos);
1409        self.tst_temp = read_cn(raw_data, pos);
1410        self.user_txt = read_cn(raw_data, pos);
1411        self.aux_file = read_cn(raw_data, pos);
1412        self.pkg_typ = read_cn(raw_data, pos);
1413        self.famly_id = read_cn(raw_data, pos);
1414        self.date_cod = read_cn(raw_data, pos);
1415        self.facil_id = read_cn(raw_data, pos);
1416        self.floor_id = read_cn(raw_data, pos);
1417        self.proc_id = read_cn(raw_data, pos);
1418        self.oper_frq = read_cn(raw_data, pos);
1419        self.spec_nam = read_cn(raw_data, pos);
1420        self.spec_ver = read_cn(raw_data, pos);
1421        self.flow_id = read_cn(raw_data, pos);
1422        self.setup_id = read_cn(raw_data, pos);
1423        self.dsgn_rev = read_cn(raw_data, pos);
1424        self.eng_id = read_cn(raw_data, pos);
1425        self.rom_cod = read_cn(raw_data, pos);
1426        self.serl_num = read_cn(raw_data, pos);
1427        self.supr_nam = read_cn(raw_data, pos);
1428    }
1429}
1430
1431impl MRR {
1432    #[inline(always)]
1433    pub fn new() -> Self {
1434        MRR::default()
1435    }
1436
1437    #[inline(always)]
1438    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1439        let pos = &mut 0;
1440        self.finish_t = read_u4(raw_data, pos, order);
1441        if *pos < raw_data.len() {
1442            self.disp_cod = read_uint8(raw_data, pos) as char;
1443        }
1444        self.usr_desc = read_cn(raw_data, pos);
1445        self.exc_desc = read_cn(raw_data, pos);
1446    }
1447}
1448
1449impl PCR {
1450    #[inline(always)]
1451    pub fn new() -> Self {
1452        PCR::default()
1453    }
1454
1455    #[inline(always)]
1456    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1457        let pos = &mut 0;
1458        self.head_num = read_uint8(raw_data, pos);
1459        self.site_num = read_uint8(raw_data, pos);
1460        self.part_cnt = read_u4(raw_data, pos, order);
1461        if *pos + 4 <= raw_data.len() {
1462            self.rtst_cnt = read_u4(raw_data, pos, order);
1463        }
1464        if *pos + 4 <= raw_data.len() {
1465            self.abrt_cnt = read_u4(raw_data, pos, order);
1466        }
1467        if *pos + 4 <= raw_data.len() {
1468            self.good_cnt = read_u4(raw_data, pos, order);
1469        }
1470        if *pos + 4 <= raw_data.len() {
1471            self.func_cnt = read_u4(raw_data, pos, order);
1472        }
1473    }
1474}
1475
1476impl HBR {
1477    #[inline(always)]
1478    pub fn new() -> Self {
1479        HBR::default()
1480    }
1481
1482    #[inline(always)]
1483    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1484        let pos = &mut 0;
1485        self.head_num = read_uint8(raw_data, pos);
1486        self.site_num = read_uint8(raw_data, pos);
1487        self.hbin_num = read_u2(raw_data, pos, order);
1488        self.hbin_cnt = read_u4(raw_data, pos, order);
1489        if *pos < raw_data.len() {
1490            self.hbin_pf = read_uint8(raw_data, pos) as char;
1491        }
1492        self.hbin_nam = read_cn(raw_data, pos);
1493    }
1494}
1495
1496impl SBR {
1497    #[inline(always)]
1498    pub fn new() -> Self {
1499        SBR::default()
1500    }
1501
1502    #[inline(always)]
1503    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1504        let pos = &mut 0;
1505        self.head_num = read_uint8(raw_data, pos);
1506        self.site_num = read_uint8(raw_data, pos);
1507        self.sbin_num = read_u2(raw_data, pos, order);
1508        self.sbin_cnt = read_u4(raw_data, pos, order);
1509        if *pos < raw_data.len() {
1510            self.sbin_pf = read_uint8(raw_data, pos) as char;
1511        }
1512        self.sbin_nam = read_cn(raw_data, pos);
1513    }
1514}
1515
1516impl PMR {
1517    #[inline(always)]
1518    pub fn new() -> Self {
1519        PMR::default()
1520    }
1521
1522    #[inline(always)]
1523    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1524        let pos = &mut 0;
1525        self.pmr_indx = read_u2(raw_data, pos, order);
1526        if *pos + 2 <= raw_data.len() {
1527            self.chan_typ = read_u2(raw_data, pos, order);
1528        }
1529        self.chan_nam = read_cn(raw_data, pos);
1530        self.phy_nam = read_cn(raw_data, pos);
1531        self.log_nam = read_cn(raw_data, pos);
1532        if *pos < raw_data.len() {
1533            self.head_num = read_uint8(raw_data, pos)
1534        };
1535        if *pos < raw_data.len() {
1536            self.site_num = read_uint8(raw_data, pos)
1537        };
1538    }
1539}
1540
1541impl PGR {
1542    #[inline(always)]
1543    pub fn new() -> Self {
1544        PGR::default()
1545    }
1546
1547    #[inline(always)]
1548    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1549        let pos = &mut 0;
1550        self.grp_indx = read_u2(raw_data, pos, order);
1551        self.grp_nam = read_cn(raw_data, pos);
1552        self.indx_cnt = read_u2(raw_data, pos, order);
1553        self.pmr_indx = read_kx_u2(raw_data, pos, order, self.indx_cnt);
1554    }
1555}
1556
1557impl PLR {
1558    #[inline(always)]
1559    pub fn new() -> Self {
1560        PLR::default()
1561    }
1562
1563    #[inline(always)]
1564    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1565        let pos = &mut 0;
1566        self.grp_cnt = read_u2(raw_data, pos, order);
1567        self.grp_indx = read_kx_u2(raw_data, pos, order, self.grp_cnt);
1568        self.grp_mode = read_kx_u2(raw_data, pos, order, self.grp_cnt);
1569        self.grp_radx = read_kx_u1(raw_data, pos, self.grp_cnt);
1570        self.pgm_char = read_kx_cn(raw_data, pos, self.grp_cnt);
1571        self.rtn_char = read_kx_cn(raw_data, pos, self.grp_cnt);
1572        self.pgm_chal = read_kx_cn(raw_data, pos, self.grp_cnt);
1573        self.rtn_chal = read_kx_cn(raw_data, pos, self.grp_cnt);
1574    }
1575}
1576
1577impl RDR {
1578    #[inline(always)]
1579    pub fn new() -> Self {
1580        RDR::default()
1581    }
1582
1583    #[inline(always)]
1584    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1585        let pos = &mut 0;
1586        self.num_bins = read_u2(raw_data, pos, order);
1587        self.rtst_bin = read_kx_u2(raw_data, pos, order, self.num_bins);
1588    }
1589}
1590
1591impl SDR {
1592    #[inline(always)]
1593    pub fn new() -> Self {
1594        SDR::default()
1595    }
1596
1597    #[inline(always)]
1598    pub fn read_from_bytes(&mut self, raw_data: &[u8], _order: &ByteOrder) {
1599        let pos = &mut 0;
1600        self.head_num = read_uint8(raw_data, pos);
1601        self.site_grp = read_uint8(raw_data, pos);
1602        self.site_cnt = read_uint8(raw_data, pos);
1603        self.site_num = read_kx_u1(raw_data, pos, self.site_cnt as u16);
1604        self.hand_typ = read_cn(raw_data, pos);
1605        self.hand_id = read_cn(raw_data, pos);
1606        self.card_typ = read_cn(raw_data, pos);
1607        self.card_id = read_cn(raw_data, pos);
1608        self.load_typ = read_cn(raw_data, pos);
1609        self.load_id = read_cn(raw_data, pos);
1610        self.dib_typ = read_cn(raw_data, pos);
1611        self.dib_id = read_cn(raw_data, pos);
1612        self.cabl_typ = read_cn(raw_data, pos);
1613        self.cabl_id = read_cn(raw_data, pos);
1614        self.cont_typ = read_cn(raw_data, pos);
1615        self.cont_id = read_cn(raw_data, pos);
1616        self.lasr_typ = read_cn(raw_data, pos);
1617        self.lasr_id = read_cn(raw_data, pos);
1618        self.extr_typ = read_cn(raw_data, pos);
1619        self.extr_id = read_cn(raw_data, pos);
1620    }
1621}
1622
1623impl PSR {
1624    #[inline(always)]
1625    pub fn new() -> Self {
1626        PSR::default()
1627    }
1628
1629    #[inline(always)]
1630    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1631        let pos = &mut 0;
1632        self.cont_flg = [read_uint8(raw_data, pos)];
1633        self.psr_indx = read_u2(raw_data, pos, order);
1634        self.psr_nam = read_cn(raw_data, pos);
1635        self.opt_flg = [read_uint8(raw_data, pos)];
1636        self.totp_cnt = read_u2(raw_data, pos, order);
1637        self.locp_cnt = read_u2(raw_data, pos, order);
1638        self.pat_bgn = read_kx_u8(raw_data, pos, order, self.locp_cnt);
1639        self.pat_end = read_kx_u8(raw_data, pos, order, self.locp_cnt);
1640        self.pat_file = read_kx_cn(raw_data, pos, self.locp_cnt);
1641        self.pat_lbl = read_kx_cn(raw_data, pos, self.locp_cnt);
1642        self.file_uid = read_kx_cn(raw_data, pos, self.locp_cnt);
1643        self.atpg_dsc = read_kx_cn(raw_data, pos, self.locp_cnt);
1644        self.src_id = read_kx_cn(raw_data, pos, self.locp_cnt);
1645    }
1646}
1647
1648impl NMR {
1649    #[inline(always)]
1650    pub fn new() -> Self {
1651        NMR::default()
1652    }
1653
1654    #[inline(always)]
1655    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1656        let pos = &mut 0;
1657        self.cont_flg = [read_uint8(raw_data, pos)];
1658        self.totm_cnt = read_u2(raw_data, pos, order);
1659        self.locm_cnt = read_u2(raw_data, pos, order);
1660        self.pmr_indx = read_kx_u2(raw_data, pos, order, self.locm_cnt);
1661        self.atpg_nam = read_kx_cn(raw_data, pos, self.locm_cnt);
1662    }
1663}
1664
1665impl CNR {
1666    #[inline(always)]
1667    pub fn new() -> Self {
1668        CNR::default()
1669    }
1670
1671    #[inline(always)]
1672    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1673        let pos = &mut 0;
1674        self.chn_num = read_u2(raw_data, pos, order);
1675        self.bit_pos = read_u4(raw_data, pos, order);
1676        self.cell_nam = read_sn(raw_data, pos, order);
1677    }
1678}
1679
1680impl SSR {
1681    #[inline(always)]
1682    pub fn new() -> Self {
1683        SSR::default()
1684    }
1685
1686    #[inline(always)]
1687    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1688        let pos = &mut 0;
1689        self.ssr_nam = read_cn(raw_data, pos);
1690        self.chn_cnt = read_u2(raw_data, pos, order);
1691        self.chn_list = read_kx_u2(raw_data, pos, order, self.chn_cnt);
1692    }
1693}
1694
1695impl CDR {
1696    #[inline(always)]
1697    pub fn new() -> Self {
1698        CDR::default()
1699    }
1700
1701    #[inline(always)]
1702    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1703        let pos = &mut 0;
1704        self.cont_flg = [read_uint8(raw_data, pos)];
1705        self.cdr_indx = read_u2(raw_data, pos, order);
1706        self.chn_nam = read_cn(raw_data, pos);
1707        self.chn_len = read_u4(raw_data, pos, order);
1708        self.sin_pin = read_u2(raw_data, pos, order);
1709        self.sout_pin = read_u2(raw_data, pos, order);
1710        self.mstr_cnt = read_uint8(raw_data, pos);
1711        self.m_clks = read_kx_u2(raw_data, pos, order, self.mstr_cnt as u16);
1712        self.slav_cnt = read_uint8(raw_data, pos);
1713        self.s_clks = read_kx_u2(raw_data, pos, order, self.slav_cnt as u16);
1714        if *pos < raw_data.len() {
1715            self.inv_val = read_uint8(raw_data, pos);
1716        }
1717        self.lst_cnt = read_u2(raw_data, pos, order);
1718        self.cell_lst = read_kx_sn(raw_data, pos, order, self.lst_cnt);
1719    }
1720}
1721
1722impl WIR {
1723    #[inline(always)]
1724    pub fn new() -> Self {
1725        WIR::default()
1726    }
1727
1728    #[inline(always)]
1729    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1730        let pos = &mut 0;
1731        self.head_num = read_uint8(raw_data, pos);
1732        if *pos < raw_data.len() {
1733            self.site_grp = read_uint8(raw_data, pos);
1734        }
1735        self.start_t = read_u4(raw_data, pos, order);
1736        self.wafer_id = read_cn(raw_data, pos);
1737    }
1738}
1739
1740impl WRR {
1741    #[inline(always)]
1742    pub fn new() -> Self {
1743        WRR::default()
1744    }
1745
1746    #[inline(always)]
1747    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1748        let pos = &mut 0;
1749        self.head_num = read_uint8(raw_data, pos);
1750        if *pos < raw_data.len() {
1751            self.site_grp = read_uint8(raw_data, pos);
1752        }
1753        self.finish_t = read_u4(raw_data, pos, order);
1754        self.part_cnt = read_u4(raw_data, pos, order);
1755        if *pos + 4 <= raw_data.len() {
1756            self.rtst_cnt = read_u4(raw_data, pos, order);
1757        }
1758        if *pos + 4 <= raw_data.len() {
1759            self.abrt_cnt = read_u4(raw_data, pos, order);
1760        }
1761        if *pos + 4 <= raw_data.len() {
1762            self.good_cnt = read_u4(raw_data, pos, order);
1763        }
1764        if *pos + 4 <= raw_data.len() {
1765            self.func_cnt = read_u4(raw_data, pos, order);
1766        }
1767        self.wafer_id = read_cn(raw_data, pos);
1768        self.fabwf_id = read_cn(raw_data, pos);
1769        self.frame_id = read_cn(raw_data, pos);
1770        self.mask_id = read_cn(raw_data, pos);
1771        self.usr_desc = read_cn(raw_data, pos);
1772        self.exc_desc = read_cn(raw_data, pos);
1773    }
1774}
1775
1776impl WCR {
1777    #[inline(always)]
1778    pub fn new() -> Self {
1779        WCR::default()
1780    }
1781
1782    #[inline(always)]
1783    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1784        let pos = &mut 0;
1785        self.wafr_siz = read_r4(raw_data, pos, order);
1786        self.die_ht = read_r4(raw_data, pos, order);
1787        self.die_wid = read_r4(raw_data, pos, order);
1788        self.wf_units = read_uint8(raw_data, pos);
1789        if *pos < raw_data.len() {
1790            self.wf_flat = read_uint8(raw_data, pos) as char;
1791        }
1792        if *pos + 2 <= raw_data.len() {
1793            self.center_x = read_i2(raw_data, pos, order);
1794        }
1795        if *pos + 2 <= raw_data.len() {
1796            self.center_y = read_i2(raw_data, pos, order);
1797        }
1798        if *pos < raw_data.len() {
1799            self.pos_x = read_uint8(raw_data, pos) as char;
1800        }
1801        if *pos < raw_data.len() {
1802            self.pos_y = read_uint8(raw_data, pos) as char;
1803        }
1804    }
1805}
1806
1807impl PIR {
1808    #[inline(always)]
1809    pub fn new() -> Self {
1810        PIR::default()
1811    }
1812
1813    #[inline(always)]
1814    pub fn read_from_bytes(&mut self, raw_data: &[u8], _order: &ByteOrder) {
1815        let pos = &mut 0;
1816        self.head_num = read_uint8(raw_data, pos);
1817        self.site_num = read_uint8(raw_data, pos);
1818    }
1819}
1820
1821impl PRR {
1822    #[inline(always)]
1823    pub fn new() -> Self {
1824        PRR::default()
1825    }
1826
1827    #[inline(always)]
1828    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1829        let pos = &mut 0;
1830        self.head_num = read_uint8(raw_data, pos);
1831        self.site_num = read_uint8(raw_data, pos);
1832        self.part_flg = [read_uint8(raw_data, pos)];
1833        self.num_test = read_u2(raw_data, pos, order);
1834        self.hard_bin = read_u2(raw_data, pos, order);
1835        if *pos + 2 <= raw_data.len() {
1836            self.soft_bin = read_u2(raw_data, pos, order);
1837        }
1838        if *pos + 2 <= raw_data.len() {
1839            self.x_coord = read_i2(raw_data, pos, order);
1840        }
1841        if *pos + 2 <= raw_data.len() {
1842            self.y_coord = read_i2(raw_data, pos, order);
1843        }
1844        if *pos + 4 <= raw_data.len() {
1845            self.test_t = read_u4(raw_data, pos, order);
1846        }
1847        self.part_id = read_cn(raw_data, pos);
1848        self.part_txt = read_cn(raw_data, pos);
1849        self.part_fix = read_bn(raw_data, pos);
1850    }
1851}
1852
1853impl TSR {
1854    #[inline(always)]
1855    pub fn new() -> Self {
1856        TSR::default()
1857    }
1858
1859    #[inline(always)]
1860    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1861        let pos = &mut 0;
1862        self.head_num = read_uint8(raw_data, pos);
1863        self.site_num = read_uint8(raw_data, pos);
1864        if *pos < raw_data.len() {
1865            self.test_typ = read_uint8(raw_data, pos) as char;
1866        }
1867        self.test_num = read_u4(raw_data, pos, order);
1868        if *pos + 4 <= raw_data.len() {
1869            self.exec_cnt = read_u4(raw_data, pos, order);
1870        }
1871        if *pos + 4 <= raw_data.len() {
1872            self.fail_cnt = read_u4(raw_data, pos, order);
1873        }
1874        if *pos + 4 <= raw_data.len() {
1875            self.alrm_cnt = read_u4(raw_data, pos, order);
1876        }
1877        self.test_nam = read_cn(raw_data, pos);
1878        self.seq_name = read_cn(raw_data, pos);
1879        self.test_lbl = read_cn(raw_data, pos);
1880        self.opt_flag = [read_uint8(raw_data, pos)];
1881        self.test_tim = read_r4(raw_data, pos, order);
1882        self.test_min = read_r4(raw_data, pos, order);
1883        self.test_max = read_r4(raw_data, pos, order);
1884        self.tst_sums = read_r4(raw_data, pos, order);
1885        self.tst_sqrs = read_r4(raw_data, pos, order);
1886    }
1887}
1888
1889impl PTR {
1890    #[inline(always)]
1891    pub fn new() -> Self {
1892        PTR::default()
1893    }
1894
1895    #[inline(always)]
1896    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1897        let pos = &mut 0;
1898        self.test_num = read_u4(raw_data, pos, order);
1899        self.head_num = read_uint8(raw_data, pos);
1900        self.site_num = read_uint8(raw_data, pos);
1901        self.test_flg = [read_uint8(raw_data, pos)];
1902        self.parm_flg = [read_uint8(raw_data, pos)];
1903        self.result = read_r4(raw_data, pos, order);
1904        self.test_txt = read_cn(raw_data, pos);
1905        self.alarm_id = read_cn(raw_data, pos);
1906        read_optional!(self.opt_flag, [read_uint8(raw_data, pos)], 1);
1907        read_optional!(self.res_scal, read_i1(raw_data, pos), 1);
1908        read_optional!(self.llm_scal, read_i1(raw_data, pos), 1);
1909        read_optional!(self.hlm_scal, read_i1(raw_data, pos), 1);
1910        read_optional!(self.lo_limit, read_r4(raw_data, pos, order), 4);
1911        read_optional!(self.hi_limit, read_r4(raw_data, pos, order), 4);
1912        read_optional!(self.units, read_cn(raw_data, pos), 1);
1913        read_optional!(self.c_resfmt, read_cn(raw_data, pos), 1);
1914        read_optional!(self.c_llmfmt, read_cn(raw_data, pos), 1);
1915        read_optional!(self.c_hlmfmt, read_cn(raw_data, pos), 1);
1916        read_optional!(self.lo_spec, read_r4(raw_data, pos, order), 4);
1917        read_optional!(self.hi_spec, read_r4(raw_data, pos, order), 4);
1918    }
1919}
1920
1921impl MPR {
1922    #[inline(always)]
1923    pub fn new() -> Self {
1924        MPR::default()
1925    }
1926
1927    #[inline(always)]
1928    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1929        let pos = &mut 0;
1930        self.test_num = read_u4(raw_data, pos, order);
1931        self.head_num = read_uint8(raw_data, pos);
1932        self.site_num = read_uint8(raw_data, pos);
1933        self.test_flg = [read_uint8(raw_data, pos)];
1934        self.parm_flg = [read_uint8(raw_data, pos)];
1935        self.rtn_icnt = read_u2(raw_data, pos, order);
1936        self.rslt_cnt = read_u2(raw_data, pos, order);
1937        self.rtn_stat = read_kx_n1(raw_data, pos, self.rtn_icnt);
1938        self.rtn_rslt = read_kx_r4(raw_data, pos, order, self.rslt_cnt);
1939        self.test_txt = read_cn(raw_data, pos);
1940        self.alarm_id = read_cn(raw_data, pos);
1941        read_optional!(self.opt_flag, [read_uint8(raw_data, pos)], 1);
1942        read_optional!(self.res_scal, read_i1(raw_data, pos), 1);
1943        read_optional!(self.llm_scal, read_i1(raw_data, pos), 1);
1944        read_optional!(self.hlm_scal, read_i1(raw_data, pos), 1);
1945        read_optional!(self.lo_limit, read_r4(raw_data, pos, order), 4);
1946        read_optional!(self.hi_limit, read_r4(raw_data, pos, order), 4);
1947        read_optional!(self.start_in, read_r4(raw_data, pos, order), 4);
1948        read_optional!(self.incr_in, read_r4(raw_data, pos, order), 4);
1949        read_optional!(
1950            self.rtn_indx,
1951            read_kx_u2(raw_data, pos, order, self.rtn_icnt),
1952            2
1953        );
1954        read_optional!(self.units, read_cn(raw_data, pos), 1);
1955        read_optional!(self.units_in, read_cn(raw_data, pos), 1);
1956        read_optional!(self.c_resfmt, read_cn(raw_data, pos), 1);
1957        read_optional!(self.c_llmfmt, read_cn(raw_data, pos), 1);
1958        read_optional!(self.c_hlmfmt, read_cn(raw_data, pos), 1);
1959        read_optional!(self.lo_spec, read_r4(raw_data, pos, order), 4);
1960        read_optional!(self.hi_spec, read_r4(raw_data, pos, order), 4);
1961    }
1962}
1963
1964impl FTR {
1965    #[inline(always)]
1966    pub fn new() -> Self {
1967        FTR::default()
1968    }
1969
1970    #[inline(always)]
1971    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
1972        let pos = &mut 0;
1973        self.test_num = read_u4(raw_data, pos, order);
1974        self.head_num = read_uint8(raw_data, pos);
1975        self.site_num = read_uint8(raw_data, pos);
1976        self.test_flg = [read_uint8(raw_data, pos)];
1977        self.opt_flag = [read_uint8(raw_data, pos)];
1978        self.cycl_cnt = read_u4(raw_data, pos, order);
1979        self.rel_vadr = read_u4(raw_data, pos, order);
1980        self.rept_cnt = read_u4(raw_data, pos, order);
1981        self.num_fail = read_u4(raw_data, pos, order);
1982        self.xfail_ad = read_i4(raw_data, pos, order);
1983        self.yfail_ad = read_i4(raw_data, pos, order);
1984        self.vect_off = read_i2(raw_data, pos, order);
1985        self.rtn_icnt = read_u2(raw_data, pos, order);
1986        self.pgm_icnt = read_u2(raw_data, pos, order);
1987        self.rtn_indx = read_kx_u2(raw_data, pos, order, self.rtn_icnt);
1988        self.rtn_stat = read_kx_n1(raw_data, pos, self.rtn_icnt);
1989        self.pgm_indx = read_kx_u2(raw_data, pos, order, self.pgm_icnt);
1990        self.pgm_stat = read_kx_n1(raw_data, pos, self.pgm_icnt);
1991        self.fail_pin = read_dn(raw_data, pos, order);
1992        self.vect_nam = read_cn(raw_data, pos);
1993        self.time_set = read_cn(raw_data, pos);
1994        self.op_code = read_cn(raw_data, pos);
1995        self.test_txt = read_cn(raw_data, pos);
1996        self.alarm_id = read_cn(raw_data, pos);
1997        self.prog_txt = read_cn(raw_data, pos);
1998        self.rslt_txt = read_cn(raw_data, pos);
1999        if *pos < raw_data.len() {
2000            self.patg_num = read_uint8(raw_data, pos);
2001        }
2002        self.spin_map = read_dn(raw_data, pos, order);
2003    }
2004}
2005
2006impl STR {
2007    #[inline(always)]
2008    pub fn new() -> Self {
2009        STR::default()
2010    }
2011
2012    #[inline(always)]
2013    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
2014        let pos = &mut 0;
2015        self.cont_flg = [read_uint8(raw_data, pos)];
2016        self.test_num = read_u4(raw_data, pos, order);
2017        self.head_num = read_uint8(raw_data, pos);
2018        self.site_num = read_uint8(raw_data, pos);
2019        self.psr_ref = read_u2(raw_data, pos, order);
2020        self.test_flg = [read_uint8(raw_data, pos)];
2021        self.log_typ = read_cn(raw_data, pos);
2022        self.test_txt = read_cn(raw_data, pos);
2023        self.alarm_id = read_cn(raw_data, pos);
2024        self.prog_txt = read_cn(raw_data, pos);
2025        self.rslt_txt = read_cn(raw_data, pos);
2026        self.z_val = read_uint8(raw_data, pos);
2027        self.fmu_flg = [read_uint8(raw_data, pos)];
2028        self.mask_map = read_dn(raw_data, pos, order);
2029        self.fal_map = read_dn(raw_data, pos, order);
2030        self.cyc_cnt_t = read_u8(raw_data, pos, order);
2031        self.totf_cnt = read_u4(raw_data, pos, order);
2032        self.totl_cnt = read_u4(raw_data, pos, order);
2033        self.cyc_base = read_u8(raw_data, pos, order);
2034        self.bit_base = read_u4(raw_data, pos, order);
2035        self.cond_cnt = read_u2(raw_data, pos, order);
2036        self.lim_cnt = read_u2(raw_data, pos, order);
2037        self.cyc_size = read_uint8(raw_data, pos);
2038        self.pmr_size = read_uint8(raw_data, pos);
2039        self.chn_size = read_uint8(raw_data, pos);
2040        self.pat_size = read_uint8(raw_data, pos);
2041        self.bit_size = read_uint8(raw_data, pos);
2042        self.u1_size = read_uint8(raw_data, pos);
2043        self.u2_size = read_uint8(raw_data, pos);
2044        self.u3_size = read_uint8(raw_data, pos);
2045        self.utx_size = read_uint8(raw_data, pos);
2046        self.cap_bgn = read_u2(raw_data, pos, order);
2047        // k: LIM_CNT
2048        self.lim_indx = read_kx_u2(raw_data, pos, order, self.lim_cnt);
2049        self.lim_spec = read_kx_u4(raw_data, pos, order, self.lim_cnt);
2050        // k: COND_CNT
2051        self.cond_lst = read_kx_cn(raw_data, pos, self.cond_cnt);
2052        self.cyc_cnt = read_u2(raw_data, pos, order);
2053        // k: CYC_CNT, f: CYC_SIZE
2054        self.cyc_ofst = read_kx_uf(raw_data, pos, order, self.cyc_cnt, self.cyc_size);
2055        self.pmr_cnt = read_u2(raw_data, pos, order);
2056        // k: PMR_CNT, f: PMR_SIZE
2057        self.pmr_indx = read_kx_uf(raw_data, pos, order, self.pmr_cnt, self.pmr_size);
2058        self.chn_cnt = read_u2(raw_data, pos, order);
2059        // k: CHN_CNT, f: CHN_SIZE
2060        self.chn_num = read_kx_uf(raw_data, pos, order, self.chn_cnt, self.chn_size);
2061        self.exp_cnt = read_u2(raw_data, pos, order);
2062        // k: EXP_CNT
2063        self.exp_data = read_kx_u1(raw_data, pos, self.exp_cnt);
2064        self.cap_cnt = read_u2(raw_data, pos, order);
2065        // k: CAP_CNT
2066        self.cap_data = read_kx_u1(raw_data, pos, self.cap_cnt);
2067        self.new_cnt = read_u2(raw_data, pos, order);
2068        // k: NEW_CNT
2069        self.new_data = read_kx_u1(raw_data, pos, self.new_cnt);
2070        self.pat_cnt = read_u2(raw_data, pos, order);
2071        // k: PAT_CNT, f: PAT_SIZE
2072        self.pat_num = read_kx_uf(raw_data, pos, order, self.pat_cnt, self.pat_size);
2073        self.bpos_cnt = read_u2(raw_data, pos, order);
2074        // k: BPOS_CNT, f: BIT_SIZE
2075        self.bit_pos = read_kx_uf(raw_data, pos, order, self.bpos_cnt, self.bit_size);
2076        self.usr1_cnt = read_u2(raw_data, pos, order);
2077        // k: USR1_CNT, f: U1_SIZE
2078        self.usr1 = read_kx_uf(raw_data, pos, order, self.usr1_cnt, self.u1_size);
2079        self.usr2_cnt = read_u2(raw_data, pos, order);
2080        // k: USR2_CNT, f: U2_SIZE
2081        self.usr2 = read_kx_uf(raw_data, pos, order, self.usr2_cnt, self.u2_size);
2082        self.usr3_cnt = read_u2(raw_data, pos, order);
2083        // k: USR3_CNT, f: U3_SIZE
2084        self.usr3 = read_kx_uf(raw_data, pos, order, self.usr3_cnt, self.u3_size);
2085        self.txt_cnt = read_u2(raw_data, pos, order);
2086        // k: TXT_CNT
2087        self.user_txt = read_kx_cf(raw_data, pos, self.txt_cnt, self.utx_size);
2088    }
2089}
2090
2091impl BPS {
2092    #[inline(always)]
2093    pub fn new() -> Self {
2094        BPS::default()
2095    }
2096
2097    #[inline(always)]
2098    pub fn read_from_bytes(&mut self, raw_data: &[u8], _order: &ByteOrder) {
2099        let pos = &mut 0;
2100        self.seq_name = read_cn(raw_data, pos);
2101    }
2102}
2103
2104impl EPS {
2105    pub fn new() -> Self {
2106        EPS::default()
2107    }
2108
2109    pub fn read_from_bytes(&mut self, _raw_data: &[u8], _order: &ByteOrder) {}
2110}
2111
2112impl GDR {
2113    #[inline(always)]
2114    pub fn new() -> Self {
2115        GDR::default()
2116    }
2117
2118    #[inline(always)]
2119    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
2120        let pos = &mut 0;
2121        self.fld_cnt = read_u2(raw_data, pos, order);
2122        self.gen_data = read_vn(raw_data, pos, order, self.fld_cnt);
2123    }
2124}
2125
2126impl DTR {
2127    #[inline(always)]
2128    pub fn new() -> Self {
2129        DTR::default()
2130    }
2131
2132    #[inline(always)]
2133    pub fn read_from_bytes(&mut self, raw_data: &[u8], _order: &ByteOrder) {
2134        let pos = &mut 0;
2135        self.text_dat = read_cn(raw_data, pos);
2136    }
2137}
2138
2139impl ReservedRec {
2140    pub fn new() -> Self {
2141        ReservedRec::default()
2142    }
2143
2144    pub fn read_from_bytes(&mut self, raw_data: &[u8], _order: &ByteOrder) {
2145        let mut dataclone = Vec::with_capacity(raw_data.len());
2146        dataclone.extend_from_slice(raw_data);
2147        self.raw_data = dataclone;
2148    }
2149}
2150
2151impl StdfRecord {
2152    /// Create a StdfRecord of a given type with default data
2153    ///
2154    /// ```
2155    /// use rust_stdf::{StdfRecord, stdf_record_type::REC_PMR};
2156    ///
2157    /// // create StdfRecord with a nested PMR
2158    /// let new_rec = StdfRecord::new(REC_PMR);
2159    ///
2160    /// if let StdfRecord::PMR(pmr_rec) = new_rec {
2161    ///     assert_eq!(pmr_rec.head_num, 1);
2162    ///     assert_eq!(pmr_rec.site_num, 1);
2163    /// } else {
2164    ///     // this case will not be hit
2165    /// }
2166    /// ```
2167    #[inline(always)]
2168    pub fn new(rec_type: u64) -> Self {
2169        match rec_type {
2170            // rec type 15
2171            stdf_record_type::REC_PTR => StdfRecord::PTR(PTR::new()),
2172            stdf_record_type::REC_MPR => StdfRecord::MPR(MPR::new()),
2173            stdf_record_type::REC_FTR => StdfRecord::FTR(FTR::new()),
2174            stdf_record_type::REC_STR => StdfRecord::STR(STR::new()),
2175            // rec type 5
2176            stdf_record_type::REC_PIR => StdfRecord::PIR(PIR::new()),
2177            stdf_record_type::REC_PRR => StdfRecord::PRR(PRR::new()),
2178            // rec type 2
2179            stdf_record_type::REC_WIR => StdfRecord::WIR(WIR::new()),
2180            stdf_record_type::REC_WRR => StdfRecord::WRR(WRR::new()),
2181            stdf_record_type::REC_WCR => StdfRecord::WCR(WCR::new()),
2182            // rec type 50
2183            stdf_record_type::REC_GDR => StdfRecord::GDR(GDR::new()),
2184            stdf_record_type::REC_DTR => StdfRecord::DTR(DTR::new()),
2185            // rec type 0
2186            stdf_record_type::REC_FAR => StdfRecord::FAR(FAR::new()),
2187            stdf_record_type::REC_ATR => StdfRecord::ATR(ATR::new()),
2188            stdf_record_type::REC_VUR => StdfRecord::VUR(VUR::new()),
2189            // rec type 1
2190            stdf_record_type::REC_MIR => StdfRecord::MIR(MIR::new()),
2191            stdf_record_type::REC_MRR => StdfRecord::MRR(MRR::new()),
2192            stdf_record_type::REC_PCR => StdfRecord::PCR(PCR::new()),
2193            stdf_record_type::REC_HBR => StdfRecord::HBR(HBR::new()),
2194            stdf_record_type::REC_SBR => StdfRecord::SBR(SBR::new()),
2195            stdf_record_type::REC_PMR => StdfRecord::PMR(PMR::new()),
2196            stdf_record_type::REC_PGR => StdfRecord::PGR(PGR::new()),
2197            stdf_record_type::REC_PLR => StdfRecord::PLR(PLR::new()),
2198            stdf_record_type::REC_RDR => StdfRecord::RDR(RDR::new()),
2199            stdf_record_type::REC_SDR => StdfRecord::SDR(SDR::new()),
2200            stdf_record_type::REC_PSR => StdfRecord::PSR(PSR::new()),
2201            stdf_record_type::REC_NMR => StdfRecord::NMR(NMR::new()),
2202            stdf_record_type::REC_CNR => StdfRecord::CNR(CNR::new()),
2203            stdf_record_type::REC_SSR => StdfRecord::SSR(SSR::new()),
2204            stdf_record_type::REC_CDR => StdfRecord::CDR(CDR::new()),
2205            // rec type 10
2206            stdf_record_type::REC_TSR => StdfRecord::TSR(TSR::new()),
2207            // rec type 20
2208            stdf_record_type::REC_BPS => StdfRecord::BPS(BPS::new()),
2209            stdf_record_type::REC_EPS => StdfRecord::EPS(EPS::new()),
2210            // rec type 180: Reserved
2211            // rec type 181: Reserved
2212            stdf_record_type::REC_RESERVE => StdfRecord::ReservedRec(ReservedRec::new()),
2213            // not matched
2214            _ => StdfRecord::InvalidRec(RecordHeader::new()),
2215        }
2216    }
2217
2218    /// Create a `StdfRecord` from a `RecordHeader` with default data
2219    ///
2220    /// The difference between `new()` is that this method can save
2221    /// the info of an invalid record header, help the caller to
2222    /// debug
2223    ///
2224    /// ```
2225    /// use rust_stdf::{StdfRecord, RecordHeader, stdf_record_type::REC_PMR};
2226    ///
2227    /// // create a PMR StdfRecord from header
2228    /// // (1, 60)
2229    /// let pmr_header = RecordHeader {typ: 1, sub: 60, len: 0 };
2230    /// let new_rec = StdfRecord::new_from_header(pmr_header);
2231    ///
2232    /// if let StdfRecord::PMR(pmr_rec) = new_rec {
2233    ///     assert_eq!(pmr_rec.head_num, 1);
2234    ///     assert_eq!(pmr_rec.site_num, 1);
2235    /// } else {
2236    ///     // this case will not be hit
2237    /// }
2238    /// ```
2239    #[inline(always)]
2240    pub fn new_from_header(header: RecordHeader) -> Self {
2241        // I can use `header.get_type_code()` to get type_code
2242        // and reuse the code from `new()`
2243        // but match a tuple directly may be more efficient?
2244        match (header.typ, header.sub) {
2245            // rec type 15
2246            (15, 10) => StdfRecord::PTR(PTR::new()),
2247            (15, 15) => StdfRecord::MPR(MPR::new()),
2248            (15, 20) => StdfRecord::FTR(FTR::new()),
2249            (15, 30) => StdfRecord::STR(STR::new()),
2250            // rec type 5
2251            (5, 10) => StdfRecord::PIR(PIR::new()),
2252            (5, 20) => StdfRecord::PRR(PRR::new()),
2253            // rec type 2
2254            (2, 10) => StdfRecord::WIR(WIR::new()),
2255            (2, 20) => StdfRecord::WRR(WRR::new()),
2256            (2, 30) => StdfRecord::WCR(WCR::new()),
2257            // rec type 50
2258            (50, 10) => StdfRecord::GDR(GDR::new()),
2259            (50, 30) => StdfRecord::DTR(DTR::new()),
2260            // rec type 0
2261            (0, 10) => StdfRecord::FAR(FAR::new()),
2262            (0, 20) => StdfRecord::ATR(ATR::new()),
2263            (0, 30) => StdfRecord::VUR(VUR::new()),
2264            // rec type 1
2265            (1, 10) => StdfRecord::MIR(MIR::new()),
2266            (1, 20) => StdfRecord::MRR(MRR::new()),
2267            (1, 30) => StdfRecord::PCR(PCR::new()),
2268            (1, 40) => StdfRecord::HBR(HBR::new()),
2269            (1, 50) => StdfRecord::SBR(SBR::new()),
2270            (1, 60) => StdfRecord::PMR(PMR::new()),
2271            (1, 62) => StdfRecord::PGR(PGR::new()),
2272            (1, 63) => StdfRecord::PLR(PLR::new()),
2273            (1, 70) => StdfRecord::RDR(RDR::new()),
2274            (1, 80) => StdfRecord::SDR(SDR::new()),
2275            (1, 90) => StdfRecord::PSR(PSR::new()),
2276            (1, 91) => StdfRecord::NMR(NMR::new()),
2277            (1, 92) => StdfRecord::CNR(CNR::new()),
2278            (1, 93) => StdfRecord::SSR(SSR::new()),
2279            (1, 94) => StdfRecord::CDR(CDR::new()),
2280            // rec type 10
2281            (10, 30) => StdfRecord::TSR(TSR::new()),
2282            // rec type 20
2283            (20, 10) => StdfRecord::BPS(BPS::new()),
2284            (20, 20) => StdfRecord::EPS(EPS::new()),
2285            // rec type 180: Reserved
2286            // rec type 181: Reserved
2287            (180 | 181, _) => StdfRecord::ReservedRec(ReservedRec::new()),
2288            // not matched
2289            _ => StdfRecord::InvalidRec(header),
2290        }
2291    }
2292
2293    /// returns the record type cdoe of the given StdfRecord,
2294    /// which is defined in `rust_stdf::stdf_record_type::*` module.
2295    ///
2296    /// ```
2297    /// use rust_stdf::{StdfRecord, stdf_record_type::*};
2298    ///
2299    /// // `REC_PTR` type code can be used for creating a new StdfRecord
2300    /// let new_rec = StdfRecord::new(REC_PTR);
2301    /// let returned_code = new_rec.get_type();
2302    ///
2303    /// assert_eq!(REC_PTR, returned_code);
2304    ///
2305    /// // type code can be used in variety of functions
2306    /// // get record (typ, sub)
2307    /// assert_eq!((15, 10), get_typ_sub_from_code(returned_code).unwrap());
2308    /// // get record name
2309    /// assert_eq!("PTR", get_rec_name_from_code(returned_code));
2310    /// ```
2311    #[inline(always)]
2312    pub fn get_type(&self) -> u64 {
2313        match &self {
2314            // rec type 15
2315            StdfRecord::PTR(_) => stdf_record_type::REC_PTR,
2316            StdfRecord::MPR(_) => stdf_record_type::REC_MPR,
2317            StdfRecord::FTR(_) => stdf_record_type::REC_FTR,
2318            StdfRecord::STR(_) => stdf_record_type::REC_STR,
2319            // rec type 5
2320            StdfRecord::PIR(_) => stdf_record_type::REC_PIR,
2321            StdfRecord::PRR(_) => stdf_record_type::REC_PRR,
2322            // rec type 2
2323            StdfRecord::WIR(_) => stdf_record_type::REC_WIR,
2324            StdfRecord::WRR(_) => stdf_record_type::REC_WRR,
2325            StdfRecord::WCR(_) => stdf_record_type::REC_WCR,
2326            // rec type 50
2327            StdfRecord::GDR(_) => stdf_record_type::REC_GDR,
2328            StdfRecord::DTR(_) => stdf_record_type::REC_DTR,
2329            // rec type 10
2330            StdfRecord::TSR(_) => stdf_record_type::REC_TSR,
2331            // rec type 1
2332            StdfRecord::MIR(_) => stdf_record_type::REC_MIR,
2333            StdfRecord::MRR(_) => stdf_record_type::REC_MRR,
2334            StdfRecord::PCR(_) => stdf_record_type::REC_PCR,
2335            StdfRecord::HBR(_) => stdf_record_type::REC_HBR,
2336            StdfRecord::SBR(_) => stdf_record_type::REC_SBR,
2337            StdfRecord::PMR(_) => stdf_record_type::REC_PMR,
2338            StdfRecord::PGR(_) => stdf_record_type::REC_PGR,
2339            StdfRecord::PLR(_) => stdf_record_type::REC_PLR,
2340            StdfRecord::RDR(_) => stdf_record_type::REC_RDR,
2341            StdfRecord::SDR(_) => stdf_record_type::REC_SDR,
2342            StdfRecord::PSR(_) => stdf_record_type::REC_PSR,
2343            StdfRecord::NMR(_) => stdf_record_type::REC_NMR,
2344            StdfRecord::CNR(_) => stdf_record_type::REC_CNR,
2345            StdfRecord::SSR(_) => stdf_record_type::REC_SSR,
2346            StdfRecord::CDR(_) => stdf_record_type::REC_CDR,
2347            // rec type 0
2348            StdfRecord::FAR(_) => stdf_record_type::REC_FAR,
2349            StdfRecord::ATR(_) => stdf_record_type::REC_ATR,
2350            StdfRecord::VUR(_) => stdf_record_type::REC_VUR,
2351            // rec type 20
2352            StdfRecord::BPS(_) => stdf_record_type::REC_BPS,
2353            StdfRecord::EPS(_) => stdf_record_type::REC_EPS,
2354            // rec type 180: Reserved
2355            // rec type 181: Reserved
2356            StdfRecord::ReservedRec(_) => stdf_record_type::REC_RESERVE,
2357            // not matched
2358            StdfRecord::InvalidRec(_) => stdf_record_type::REC_INVALID,
2359        }
2360    }
2361
2362    /// check the StdfRecord belongs the given type code(s),
2363    /// it is useful for filtering the records during the parsing iteration.
2364    /// ```
2365    /// use rust_stdf::{StdfRecord, stdf_record_type::*};
2366    ///
2367    /// let new_rec = StdfRecord::new(REC_PTR);
2368    ///
2369    /// assert!(new_rec.is_type(REC_PTR));
2370    /// assert!(new_rec.is_type(REC_PTR | REC_FTR | REC_MPR));
2371    /// assert!(!new_rec.is_type(REC_FTR | REC_MPR));
2372    /// ```
2373    #[inline(always)]
2374    pub fn is_type(&self, rec_type: u64) -> bool {
2375        (self.get_type() & rec_type) != 0
2376    }
2377
2378    /// parse StdfRecord from byte data which **DOES NOT**
2379    /// contain the record header (len, typ, sub),
2380    ///
2381    /// requires a mutable StdfRecord to store the parsed data
2382    ///
2383    /// ```
2384    /// use rust_stdf::{StdfRecord, ByteOrder, stdf_record_type::*};
2385    ///
2386    /// let raw_with_no_header: [u8; 2] = [1, 4];
2387    /// let mut new_rec = StdfRecord::new(REC_FAR);
2388    /// new_rec.read_from_bytes(&raw_with_no_header, &ByteOrder::LittleEndian);
2389    ///
2390    /// if let StdfRecord::FAR(ref far_rec) = new_rec {
2391    ///     assert_eq!(4, far_rec.stdf_ver);
2392    /// }
2393    /// ```
2394    #[inline(always)]
2395    pub fn read_from_bytes(&mut self, raw_data: &[u8], order: &ByteOrder) {
2396        match self {
2397            // rec type 15
2398            StdfRecord::PTR(ptr_rec) => ptr_rec.read_from_bytes(raw_data, order),
2399            StdfRecord::MPR(mpr_rec) => mpr_rec.read_from_bytes(raw_data, order),
2400            StdfRecord::FTR(ftr_rec) => ftr_rec.read_from_bytes(raw_data, order),
2401            StdfRecord::STR(str_rec) => str_rec.read_from_bytes(raw_data, order),
2402            // rec type 5
2403            StdfRecord::PIR(pir_rec) => pir_rec.read_from_bytes(raw_data, order),
2404            StdfRecord::PRR(prr_rec) => prr_rec.read_from_bytes(raw_data, order),
2405            // rec type 2
2406            StdfRecord::WIR(wir_rec) => wir_rec.read_from_bytes(raw_data, order),
2407            StdfRecord::WRR(wrr_rec) => wrr_rec.read_from_bytes(raw_data, order),
2408            StdfRecord::WCR(wcr_rec) => wcr_rec.read_from_bytes(raw_data, order),
2409            // rec type 50
2410            StdfRecord::GDR(gdr_rec) => gdr_rec.read_from_bytes(raw_data, order),
2411            StdfRecord::DTR(dtr_rec) => dtr_rec.read_from_bytes(raw_data, order),
2412            // rec type 10
2413            StdfRecord::TSR(tsr_rec) => tsr_rec.read_from_bytes(raw_data, order),
2414            // rec type 1
2415            StdfRecord::MIR(mir_rec) => mir_rec.read_from_bytes(raw_data, order),
2416            StdfRecord::MRR(mrr_rec) => mrr_rec.read_from_bytes(raw_data, order),
2417            StdfRecord::PCR(pcr_rec) => pcr_rec.read_from_bytes(raw_data, order),
2418            StdfRecord::HBR(hbr_rec) => hbr_rec.read_from_bytes(raw_data, order),
2419            StdfRecord::SBR(sbr_rec) => sbr_rec.read_from_bytes(raw_data, order),
2420            StdfRecord::PMR(pmr_rec) => pmr_rec.read_from_bytes(raw_data, order),
2421            StdfRecord::PGR(pgr_rec) => pgr_rec.read_from_bytes(raw_data, order),
2422            StdfRecord::PLR(plr_rec) => plr_rec.read_from_bytes(raw_data, order),
2423            StdfRecord::RDR(rdr_rec) => rdr_rec.read_from_bytes(raw_data, order),
2424            StdfRecord::SDR(sdr_rec) => sdr_rec.read_from_bytes(raw_data, order),
2425            StdfRecord::PSR(psr_rec) => psr_rec.read_from_bytes(raw_data, order),
2426            StdfRecord::NMR(nmr_rec) => nmr_rec.read_from_bytes(raw_data, order),
2427            StdfRecord::CNR(cnr_rec) => cnr_rec.read_from_bytes(raw_data, order),
2428            StdfRecord::SSR(ssr_rec) => ssr_rec.read_from_bytes(raw_data, order),
2429            StdfRecord::CDR(cdr_rec) => cdr_rec.read_from_bytes(raw_data, order),
2430            // rec type 0
2431            StdfRecord::FAR(far_rec) => far_rec.read_from_bytes(raw_data, order),
2432            StdfRecord::ATR(atr_rec) => atr_rec.read_from_bytes(raw_data, order),
2433            StdfRecord::VUR(vur_rec) => vur_rec.read_from_bytes(raw_data, order),
2434            // rec type 20
2435            StdfRecord::BPS(bps_rec) => bps_rec.read_from_bytes(raw_data, order),
2436            StdfRecord::EPS(eps_rec) => eps_rec.read_from_bytes(raw_data, order),
2437            // rec type 180: Reserved
2438            // rec type 181: Reserved
2439            StdfRecord::ReservedRec(reserve_rec) => reserve_rec.read_from_bytes(raw_data, order),
2440            // not matched, invalid rec do not parse anything
2441            StdfRecord::InvalidRec(_) => (),
2442        };
2443    }
2444
2445    /// parse StdfRecord from byte data which
2446    /// **contains** the record header (len, typ, sub).
2447    ///
2448    /// ## Error
2449    /// if the input data is not a valid (wrong typ, sub),
2450    /// incomplete data or incorrect byte order, `StdfError` will be
2451    /// returned instead.
2452    ///
2453    /// ```
2454    /// use rust_stdf::{StdfRecord, ByteOrder, stdf_record_type::*};
2455    ///
2456    /// let raw_with_header: [u8; 6] = [0, 2, 0, 10, 1, 4];
2457    /// let new_rec = StdfRecord::read_from_bytes_with_header(&raw_with_header, &ByteOrder::BigEndian).unwrap();
2458    ///
2459    /// if let StdfRecord::FAR(far_rec) = new_rec {
2460    ///     assert_eq!(4, far_rec.stdf_ver);
2461    /// }
2462    /// ```
2463    #[inline(always)]
2464    pub fn read_from_bytes_with_header(
2465        raw_data: &[u8],
2466        order: &ByteOrder,
2467    ) -> Result<StdfRecord, StdfError> {
2468        let header = RecordHeader::new().read_from_bytes(raw_data, order)?;
2469
2470        let expected_end_pos = 4 + header.len as usize;
2471        if raw_data.len() < expected_end_pos {
2472            return Err(StdfError {
2473                code: 5,
2474                msg: format!(
2475                    "Length of stdf field data ({} - 4 = {}) is less than what header specified ({})",
2476                    raw_data.len(),
2477                    raw_data.len() - 4,
2478                    header.len
2479                ),
2480            });
2481        }
2482
2483        let data_slice = &raw_data[4..expected_end_pos];
2484        let mut rec = StdfRecord::new(header.get_type());
2485        rec.read_from_bytes(data_slice, order);
2486        Ok(rec)
2487    }
2488}
2489
2490impl RawDataElement {
2491    #[inline(always)]
2492    pub fn is_type(&self, rec_type: u64) -> bool {
2493        (self.header.get_type() & rec_type) != 0
2494    }
2495}
2496
2497impl From<&RawDataElement> for StdfRecord {
2498    /// it will NOT consume the input RawDataElement
2499    #[inline(always)]
2500    fn from(raw_element: &RawDataElement) -> Self {
2501        let mut rec = StdfRecord::new_from_header(raw_element.header);
2502        rec.read_from_bytes(&raw_element.raw_data, &raw_element.byte_order);
2503        rec
2504    }
2505}
2506
2507impl From<RawDataElement> for StdfRecord {
2508    /// it will consume the input RawDataElement
2509    #[inline(always)]
2510    fn from(raw_element: RawDataElement) -> Self {
2511        let mut rec = StdfRecord::new_from_header(raw_element.header);
2512        rec.read_from_bytes(&raw_element.raw_data, &raw_element.byte_order);
2513        rec
2514    }
2515}
2516
2517// data type functions
2518macro_rules! read_multi_byte_num {
2519    ($num_type:ty, $length:expr, $raw:ident, $pos:expr, $order:expr, $default:expr) => {{
2520        let pos_after_read = *$pos + $length;
2521        if pos_after_read <= $raw.len() {
2522            let mut tmp = [0u8; $length];
2523            tmp.copy_from_slice(&$raw[*$pos..pos_after_read]);
2524            *$pos = pos_after_read;
2525            match $order {
2526                ByteOrder::LittleEndian => <$num_type>::from_le_bytes(tmp),
2527                ByteOrder::BigEndian => <$num_type>::from_be_bytes(tmp),
2528            }
2529        } else {
2530            $default
2531        }
2532    }};
2533}
2534
2535macro_rules! read_multi_element {
2536    ($count:expr, $default:expr, $func:ident($($arg:tt)+)) => {
2537        {
2538            if $count != 0 {
2539                let mut value = Vec::with_capacity($count as usize);
2540                for _ in 0..$count {
2541                    value.push( $func($($arg)+) );
2542                }
2543                value
2544            } else {
2545                vec![$default; 0]
2546            }
2547        }
2548    }
2549}
2550
2551/// Read uint8 from byte array with offset "pos", compatible with B1, C1 and U1
2552#[inline(always)]
2553pub(crate) fn read_uint8(raw_data: &[u8], pos: &mut usize) -> u8 {
2554    if *pos < raw_data.len() {
2555        let value = (*raw_data)[*pos];
2556        *pos += 1;
2557        value
2558    } else {
2559        0
2560    }
2561}
2562
2563/// Read U2 (u16) from byte array with offset "pos"
2564#[inline(always)]
2565pub(crate) fn read_u2(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> U2 {
2566    read_multi_byte_num!(U2, 2, raw_data, pos, order, 0)
2567}
2568
2569/// Read U4 (u32) from byte array with offset "pos"
2570#[inline(always)]
2571pub(crate) fn read_u4(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> U4 {
2572    read_multi_byte_num!(U4, 4, raw_data, pos, order, 0)
2573}
2574
2575/// Read U8 (u64) from byte array with offset "pos"
2576#[inline(always)]
2577pub(crate) fn read_u8(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> U8 {
2578    read_multi_byte_num!(U8, 8, raw_data, pos, order, 0)
2579}
2580
2581/// Read I1 (i8) from byte array with offset "pos"
2582#[inline(always)]
2583pub(crate) fn read_i1(raw_data: &[u8], pos: &mut usize) -> I1 {
2584    if *pos < raw_data.len() {
2585        let value = (*raw_data)[*pos] as I1;
2586        *pos += 1;
2587        value
2588    } else {
2589        0
2590    }
2591}
2592
2593/// Read I2 (i16) from byte array with offset "pos"
2594#[inline(always)]
2595pub(crate) fn read_i2(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> I2 {
2596    read_multi_byte_num!(I2, 2, raw_data, pos, order, 0)
2597}
2598
2599/// Read I4 (i32) from byte array with offset "pos"
2600#[inline(always)]
2601pub(crate) fn read_i4(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> I4 {
2602    read_multi_byte_num!(I4, 4, raw_data, pos, order, 0)
2603}
2604
2605/// Read R4 (f32) from byte array with offset "pos"
2606#[inline(always)]
2607pub(crate) fn read_r4(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> R4 {
2608    read_multi_byte_num!(R4, 4, raw_data, pos, order, 0.0)
2609}
2610
2611/// Read R8 (f64) from byte array with offset "pos"
2612#[inline(always)]
2613pub(crate) fn read_r8(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> R8 {
2614    read_multi_byte_num!(R8, 8, raw_data, pos, order, 0.0)
2615}
2616
2617/// Read Cn (u8 + String) from byte array with offset "pos"
2618#[inline(always)]
2619pub(crate) fn read_cn(raw_data: &[u8], pos: &mut usize) -> Cn {
2620    let count = read_uint8(raw_data, pos) as usize;
2621    let mut value = String::default();
2622    if count != 0 {
2623        let min_pos = std::cmp::min(*pos + count, raw_data.len());
2624        value = bytes_to_string(&raw_data[*pos..min_pos]);
2625        *pos = min_pos;
2626    }
2627    value
2628}
2629
2630/// Read Sn (u16 + String) from byte array with offset "pos"
2631#[inline(always)]
2632pub(crate) fn read_sn(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> Sn {
2633    let count = read_u2(raw_data, pos, order) as usize;
2634    let mut value = String::default();
2635    if count != 0 {
2636        let min_pos = std::cmp::min(*pos + count, raw_data.len());
2637        value = bytes_to_string(&raw_data[*pos..min_pos]);
2638        *pos = min_pos;
2639    }
2640    value
2641}
2642
2643/// Read Cf (String) from byte array with offset "pos", String length is provide by "f"
2644#[inline(always)]
2645pub(crate) fn read_cf(raw_data: &[u8], pos: &mut usize, f: u8) -> Cf {
2646    let mut value = String::default();
2647    if f != 0 {
2648        let pos_after_read = *pos + (f as usize);
2649        if pos_after_read <= raw_data.len() {
2650            // read count
2651            value = bytes_to_string(&raw_data[*pos..pos_after_read]);
2652            *pos = pos_after_read;
2653        } else {
2654            // read all
2655            value = bytes_to_string(&raw_data[*pos..]);
2656            *pos = raw_data.len();
2657        }
2658    }
2659    value
2660}
2661
2662/// Read Bn (u8 + Vec<u8>) from byte array with offset "pos"
2663#[inline(always)]
2664pub(crate) fn read_bn(raw_data: &[u8], pos: &mut usize) -> Bn {
2665    let count = read_uint8(raw_data, pos) as usize;
2666    if count != 0 {
2667        let min_pos = std::cmp::min(*pos + count, raw_data.len());
2668        let data_slice = &raw_data[*pos..min_pos];
2669        *pos = min_pos;
2670        let mut value = vec![0u8; data_slice.len()];
2671        value.copy_from_slice(data_slice);
2672        value
2673    } else {
2674        vec![0u8; 0]
2675    }
2676}
2677
2678/// Read Dn (u16 + Vec<u8>) from byte array with offset "pos", u16 is bit counts
2679#[inline(always)]
2680pub(crate) fn read_dn(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> Dn {
2681    let bitcount = read_u2(raw_data, pos, order) as usize;
2682    let bytecount = bitcount / 8 + bitcount % 8;
2683    if bytecount != 0 {
2684        let min_pos = std::cmp::min(*pos + bytecount, raw_data.len());
2685        let data_slice = &raw_data[*pos..min_pos];
2686        *pos = min_pos;
2687        let mut value = vec![0u8; data_slice.len()];
2688        value.copy_from_slice(data_slice);
2689        value
2690    } else {
2691        vec![0u8; 0]
2692    }
2693}
2694
2695/// Read KxCn (Vec<Cn>) from byte array with offset "pos", vector size is provide by "k"
2696#[inline(always)]
2697pub(crate) fn read_kx_cn(raw_data: &[u8], pos: &mut usize, k: u16) -> KxCn {
2698    read_multi_element!(k, String::new(), read_cn(raw_data, pos))
2699}
2700
2701/// Read KxSn (Vec<Sn>) from byte array with offset "pos", vector size is provide by "k"
2702#[inline(always)]
2703pub(crate) fn read_kx_sn(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> KxSn {
2704    read_multi_element!(k, String::new(), read_sn(raw_data, pos, order))
2705}
2706
2707/// Read KxCf (Vec<Cf>) from byte array with offset "pos", vector size is provide by "k", String size is "f"
2708#[inline(always)]
2709pub(crate) fn read_kx_cf(raw_data: &[u8], pos: &mut usize, k: u16, f: u8) -> KxCf {
2710    if k != 0 {
2711        let mut value = Vec::with_capacity(k as usize);
2712        for _ in 0..k {
2713            value.push(read_cf(raw_data, pos, f));
2714        }
2715        value
2716    } else {
2717        vec!["".to_string(); 0]
2718    }
2719}
2720
2721/// Read KxU1 (Vec<u8>) from byte array with offset "pos", vector size is provide by "k"
2722#[inline(always)]
2723pub(crate) fn read_kx_u1(raw_data: &[u8], pos: &mut usize, k: u16) -> KxU1 {
2724    read_multi_element!(k, 0, read_uint8(raw_data, pos))
2725}
2726
2727/// Read KxU2 (Vec<u16>) from byte array with offset "pos", vector size is provide by "k"
2728#[inline(always)]
2729pub(crate) fn read_kx_u2(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> KxU2 {
2730    read_multi_element!(k, 0, read_u2(raw_data, pos, order))
2731}
2732
2733/// Read KxU4 (Vec<u32>) from byte array with offset "pos", vector size is provide by "k"
2734#[inline(always)]
2735pub(crate) fn read_kx_u4(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> KxU4 {
2736    read_multi_element!(k, 0, read_u4(raw_data, pos, order))
2737}
2738
2739/// Read KxU8 (Vec<u64>) from byte array with offset "pos", vector size is provide by "k"
2740#[inline(always)]
2741pub(crate) fn read_kx_u8(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> KxU8 {
2742    read_multi_element!(k, 0, read_u8(raw_data, pos, order))
2743}
2744
2745/// Read KxUf (Vec<u8|u16|u32|u64>) from byte array with offset "pos", vector size is provide by "k", size of number is "f"
2746#[inline(always)]
2747pub(crate) fn read_kx_uf(
2748    raw_data: &[u8],
2749    pos: &mut usize,
2750    order: &ByteOrder,
2751    k: u16,
2752    f: u8,
2753) -> KxUf {
2754    if k != 0 {
2755        match f {
2756            1 => KxUf::F1(read_kx_u1(raw_data, pos, k)),
2757            2 => KxUf::F2(read_kx_u2(raw_data, pos, order, k)),
2758            4 => KxUf::F4(read_kx_u4(raw_data, pos, order, k)),
2759            8 => KxUf::F8(read_kx_u8(raw_data, pos, order, k)),
2760            _ => KxUf::F1(vec![0u8; 0]),
2761        }
2762    } else {
2763        KxUf::F1(vec![0u8; 0])
2764    }
2765}
2766
2767/// Read KxR4 (Vec<f32>) from byte array with offset "pos", vector size is provide by "k"
2768#[inline(always)]
2769pub(crate) fn read_kx_r4(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> KxR4 {
2770    read_multi_element!(k, 0.0, read_r4(raw_data, pos, order))
2771}
2772
2773/// Read KxN1 (Vec<u8>) from byte array with offset "pos", vector size is provide by "k"
2774///
2775/// size of N1 = 4 bits, hence total bytes of k * N1 = k/2 + k%2
2776#[inline(always)]
2777pub(crate) fn read_kx_n1(raw_data: &[u8], pos: &mut usize, k: u16) -> KxN1 {
2778    if k != 0 {
2779        let bytecount = k / 2 + k % 2; // k = nibble counts, 1 byte = 2 nibble
2780        let mut value = Vec::with_capacity(k as usize);
2781        for i in 0..bytecount {
2782            let tmp = read_uint8(raw_data, pos);
2783            value.push(tmp & 0x0F);
2784            if (2 * i + 1) < k {
2785                value.push((tmp & 0xF0) >> 4);
2786            }
2787        }
2788        value
2789    } else {
2790        vec![0u8; 0]
2791    }
2792}
2793
2794/// Read V1 (u8 + generic value) from byte array with offset "pos"
2795#[inline(always)]
2796pub(crate) fn read_v1(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> V1 {
2797    let type_byte = if (*pos as usize) < raw_data.len() {
2798        read_uint8(raw_data, pos)
2799    } else {
2800        0xF
2801    };
2802
2803    match type_byte {
2804        0 => V1::B0,
2805        1 => V1::U1(read_uint8(raw_data, pos)),
2806        2 => V1::U2(read_u2(raw_data, pos, order)),
2807        3 => V1::U4(read_u4(raw_data, pos, order)),
2808        4 => V1::I1(read_i1(raw_data, pos)),
2809        5 => V1::I2(read_i2(raw_data, pos, order)),
2810        6 => V1::I4(read_i4(raw_data, pos, order)),
2811        7 => V1::R4(read_r4(raw_data, pos, order)),
2812        8 => V1::R8(read_r8(raw_data, pos, order)),
2813        10 => V1::Cn(read_cn(raw_data, pos)),
2814        11 => V1::Bn(read_bn(raw_data, pos)),
2815        12 => V1::Dn(read_dn(raw_data, pos, order)),
2816        13 => V1::N1(read_uint8(raw_data, pos) & 0x0F),
2817        _ => V1::Invalid,
2818    }
2819}
2820
2821/// Read Vn (Vec<V1>) from byte array with offset "pos", vector size is provide by "k"
2822#[inline(always)]
2823pub(crate) fn read_vn(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> Vn {
2824    read_multi_element!(k, V1::Invalid, read_v1(raw_data, pos, order))
2825}
2826
2827#[inline(always)]
2828pub(crate) fn bytes_to_string(data: &[u8]) -> String {
2829    data.iter().map(|&x| x as char).collect()
2830}