matlab_mat/
parse.rs

1use bytes::BytesMut;
2use libflate::zlib::Decoder;
3use nom::branch::alt;
4use nom::bytes::complete::take;
5use nom::bytes::streaming::tag;
6use nom::character::complete::alpha0;
7use nom::combinator::map;
8use nom::combinator::map_res;
9use nom::combinator::peek;
10use nom::combinator::value;
11use nom::multi::count;
12use nom::number::complete::{
13    be_f32, be_f64, be_i16, be_i32, be_i64, be_i8, be_u16, be_u32, be_u64, be_u8, i32, le_f32,
14    le_f64, le_i16, le_i32, le_i64, le_i8, le_u16, le_u32, le_u64, le_u8, u32,
15};
16use nom::number::Endianness;
17use nom::sequence::tuple;
18use nom::IResult;
19use num_traits::FromPrimitive;
20use std::io::Read;
21#[derive(Debug, Clone)]
22pub struct Header {
23    pub version: u16,
24    pub mat_identifier: String,
25    pub description: String,
26    pub byte_order: Endianness,
27    pub subsys_offset: u64,
28    pub deflate_level: i8, //NO_COMPRESSION:0,COMPRESSION:1
29}
30
31#[derive(Clone, Debug, PartialEq)]
32pub enum NumericData {
33    Int8(Vec<i8>),
34    UInt8(Vec<u8>),
35    Int16(Vec<i16>),
36    UInt16(Vec<u16>),
37    Int32(Vec<i32>),
38    UInt32(Vec<u32>),
39    Int64(Vec<i64>),
40    UInt64(Vec<u64>),
41    Single(Vec<f32>),
42    Double(Vec<f64>),
43}
44
45impl NumericData {
46    pub fn try_from(mat_type: MatlabType, rows: usize, cols: usize) -> Option<Self> {
47        let nums = rows * cols;
48        let data: Option<NumericData> = match mat_type {
49            MatlabType::Int8 => {
50                let mut v = Vec::new();
51                v.resize(nums, 0_i8);
52                Some(NumericData::Int8(v))
53            }
54            MatlabType::UInt8 => {
55                let mut v = Vec::new();
56                v.resize(nums, 0_u8);
57                Some(NumericData::UInt8(v))
58            }
59            MatlabType::Int16 => {
60                let mut v = Vec::new();
61                v.resize(nums, 0_i16);
62                Some(NumericData::Int16(v))
63            }
64            MatlabType::UInt16 => {
65                let mut v = Vec::new();
66                v.resize(nums, 0_u16);
67                Some(NumericData::UInt16(v))
68            }
69            MatlabType::Int32 => {
70                let mut v = Vec::new();
71                v.resize(nums, 0_i32);
72                Some(NumericData::Int32(v))
73            }
74            MatlabType::UInt32 => {
75                let mut v = Vec::new();
76                v.resize(nums, 0_u32);
77                Some(NumericData::UInt32(v))
78            }
79            MatlabType::Int64 => {
80                let mut v = Vec::new();
81                v.resize(nums, 0_i64);
82                Some(NumericData::Int64(v))
83            }
84            MatlabType::UInt64 => {
85                let mut v = Vec::new();
86                v.resize(nums, 0_u64);
87                Some(NumericData::UInt64(v))
88            }
89            MatlabType::Single => {
90                let mut v = Vec::new();
91                v.resize(nums, 0_f32);
92                Some(NumericData::Single(v))
93            }
94            MatlabType::Double => {
95                let mut v = Vec::new();
96                v.resize(nums, 0_f64);
97                Some(NumericData::Double(v))
98            }
99            _ => None,
100        };
101        data
102    }
103    fn len(&self) -> usize {
104        match self {
105            NumericData::Single(vec) => vec.len(),
106            NumericData::Double(vec) => vec.len(),
107            NumericData::Int8(vec) => vec.len(),
108            NumericData::UInt8(vec) => vec.len(),
109            NumericData::Int16(vec) => vec.len(),
110            NumericData::UInt16(vec) => vec.len(),
111            NumericData::Int32(vec) => vec.len(),
112            NumericData::UInt32(vec) => vec.len(),
113            NumericData::Int64(vec) => vec.len(),
114            NumericData::UInt64(vec) => vec.len(),
115        }
116    }
117
118    fn data_type(&self) -> DataType {
119        match self {
120            NumericData::Single(_) => DataType::Single,
121            NumericData::Double(_) => DataType::Double,
122            NumericData::Int8(_) => DataType::Int8,
123            NumericData::UInt8(_) => DataType::UInt8,
124            NumericData::Int16(_) => DataType::Int16,
125            NumericData::UInt16(_) => DataType::UInt16,
126            NumericData::Int32(_) => DataType::Int32,
127            NumericData::UInt32(_) => DataType::UInt32,
128            NumericData::Int64(_) => DataType::Int64,
129            NumericData::UInt64(_) => DataType::UInt64,
130        }
131    }
132}
133
134#[derive(Clone, Copy, Debug)]
135pub struct ArrayFlags {
136    pub complex: bool,
137    pub global: bool,
138    pub logical: bool,
139    pub class: MatlabType,
140    pub nzmax: usize,
141}
142
143impl ArrayFlags {
144    fn to_bytes(&self, endianness: nom::number::Endianness) -> BytesMut {
145        let bytes = BytesMut::new();
146
147        bytes
148    }
149}
150
151#[derive(Debug, PartialEq, Clone, Copy, Primitive)]
152pub enum DataType {
153    Int8 = 1,
154    UInt8 = 2,
155    Int16 = 3,
156    UInt16 = 4,
157    Int32 = 5,
158    UInt32 = 6,
159    Single = 7,
160    Double = 9,
161    Int64 = 12,
162    UInt64 = 13,
163    Matrix = 14,
164    Compressed = 15,
165    Utf8 = 16,
166    Utf16 = 17,
167    Utf32 = 18,
168}
169
170impl DataType {
171    pub fn byte_size(&self) -> u32 {
172        match self {
173            DataType::Int8 | DataType::UInt8 | DataType::Utf8 => 1,
174            DataType::Int16 | DataType::UInt16 | DataType::Utf16 => 2,
175            DataType::Int32 | DataType::UInt32 | DataType::Single | DataType::Utf32 => 4,
176            DataType::Int64 | DataType::UInt64 | DataType::Double => 8,
177            _ => 1,
178        }
179    }
180    pub fn get_padding(&self, num_bytes: u32, packed: bool) -> u32 {
181        match self {
182            DataType::Matrix | DataType::Compressed => 0,
183            _ => {
184                let tag_size = if packed { 4 } else { 8 };
185                let padding = (tag_size + num_bytes) % 8;
186                if padding == 0 {
187                    0
188                } else {
189                    8 - padding
190                }
191            }
192        }
193    }
194    pub fn get_numbytes(&self, num_elements: u32) -> u32 {
195        self.byte_size() * num_elements
196    }
197    pub fn is_packable(&self, num_bytes: u32) -> bool {
198        if num_bytes < 4 {
199            true
200        } else {
201            false
202        }
203    }
204    pub fn computer_array_size(&self, num_elements: u32) -> u32 {
205        let num_bytes = self.get_numbytes(num_elements);
206        let packed = self.is_packable(num_elements);
207        let tag_size = if packed { 4 } else { 8 };
208        let padding = self.get_padding(num_bytes, packed);
209        tag_size + num_bytes + padding
210    }
211    // fn write_padding(&self, num_elements: u32) -> BytesMut {
212    //     let mut bytes = BytesMut::new();
213    //     let num_bytes = self.get_numbytes(num_elements);
214    //     let padding = self.get_padding(num_bytes, self.is_packabl(num_bytes));
215    //     if padding == 0 {
216    //         bytes
217    //     } else {
218    //         bytes
219    //     }
220    // }
221}
222
223#[derive(Debug, PartialEq, Clone, Copy, Primitive)]
224pub enum MatlabType {
225    Cell = 1,
226    Struct = 2,
227    Object = 3,
228    Char = 4,
229    Sparse = 5,
230    Double = 6,
231    Single = 7,
232    Int8 = 8,
233    UInt8 = 9,
234    Int16 = 10,
235    UInt16 = 11,
236    Int32 = 12,
237    UInt32 = 13,
238    Int64 = 14,
239    UInt64 = 15,
240    Function = 16,
241    Opaque = 17,
242}
243impl MatlabType {
244    pub fn numeric_data_type(&self) -> Option<DataType> {
245        match self {
246            MatlabType::Double => Some(DataType::Double),
247            MatlabType::Single => Some(DataType::Single),
248            MatlabType::Int8 => Some(DataType::Int8),
249            MatlabType::UInt8 => Some(DataType::UInt8),
250            MatlabType::Int16 => Some(DataType::Int16),
251            MatlabType::UInt16 => Some(DataType::UInt16),
252            MatlabType::Int32 => Some(DataType::UInt32),
253            MatlabType::UInt32 => Some(DataType::UInt32),
254            MatlabType::Int64 => Some(DataType::Int64),
255            MatlabType::UInt64 => Some(DataType::UInt64),
256            _ => None,
257        }
258    }
259}
260pub type Dimensions = Vec<i32>;
261pub type RowIndex = Vec<usize>;
262pub type ColumnShift = Vec<usize>;
263
264#[derive(Clone, Debug)]
265pub enum DataElement {
266    NumericMatrix(
267        ArrayFlags,
268        Dimensions,
269        String,
270        NumericData,
271        Option<NumericData>,
272    ),
273    SparseMatrix(
274        ArrayFlags,
275        Dimensions,
276        String,
277        RowIndex,
278        ColumnShift,
279        NumericData,
280        Option<NumericData>,
281    ),
282    // CharacterMatrix,
283    // Cell Matrix,
284    // Structure Matrix,
285    // Object Matrix,
286    Unsupported,
287}
288#[derive(Clone, Debug)]
289pub struct DataElementTag {
290    pub data_type: DataType,
291    pub data_byte_size: u32,
292    pub padding_byte_size: u32,
293}
294pub struct ParseResult {
295    pub header: Header,
296    pub data_elements: Vec<DataElement>,
297}
298
299pub fn parse_header(i: &[u8]) -> IResult<&[u8], Header> {
300    let text = take(116usize)(i)?;
301    let _ssdo = take(8usize)(text.0)?;
302    let (input, (text, ssdo, version)) = tuple((take(116usize), take(8usize), take(2usize)))(i)?;
303    let (input, is_little_endian) = alt((value(true, tag("IM")), value(false, tag("MI"))))(input)?;
304    let mut v_ssdo = ssdo.to_vec();
305    v_ssdo.reverse();
306    let sub_sys_offset = v_ssdo.iter().fold(0, |x, &i| x << 8 | i as u64);
307    let version = version.iter().fold(0, |x, &i| x << 8 | i as u64);
308    Ok((
309        input,
310        Header {
311            description: std::str::from_utf8(text).unwrap_or(&"").to_owned(),
312            byte_order: if is_little_endian {
313                Endianness::Little
314            } else {
315                Endianness::Big
316            },
317            subsys_offset: sub_sys_offset,
318            version: version as u16,
319            deflate_level: 1,
320            mat_identifier: "".to_lowercase(),
321        },
322    ))
323}
324fn ceil_to_multiple(x: u32, multiple: u32) -> u32 {
325    if x > 0 {
326        (((x - 1) / multiple) + 1) * multiple
327    } else {
328        0
329    }
330}
331fn get_padding(data_type: u32, byte_size: u32, packed: bool) -> u32 {
332    if data_type == 14 || data_type == 15 {
333        0
334    } else {
335        let tag_size = if packed == true { 4 } else { 8 };
336        let padding = (tag_size + byte_size) % 8;
337        if padding == 0 {
338            0
339        } else {
340            8 - padding
341        }
342    }
343}
344fn parse_data_element_tag(
345    i: &[u8],
346    endianness: nom::number::Endianness,
347) -> IResult<&[u8], DataElementTag> {
348    let (input, flag) = map(peek(u32(endianness)), |b| b & 0xFFFF0000)(i)?;
349    match flag {
350        0 => {
351            //Long Data Format
352            let (input, (data_type, byte_size)) = tuple((u32(endianness), u32(endianness)))(input)?;
353            let padding_size = get_padding(data_type, byte_size, false);
354            println!(
355                "Tag0 data_type={:?} byte_size={:?} padding={:?}",
356                data_type, byte_size, padding_size
357            );
358            Ok((
359                input,
360                DataElementTag {
361                    data_type: DataType::from_u32(data_type).ok_or(nom::Err::Failure(
362                        nom::error::Error {
363                            input: i,
364                            code: nom::error::ErrorKind::Tag,
365                        },
366                    ))?,
367                    data_byte_size: byte_size,
368                    padding_byte_size: padding_size,
369                },
370            ))
371        }
372        _ => {
373            //Small Data Format
374            let (input, data_type) = map(peek(u32(endianness)), |b| b & 0x0000FFFF)(input)?;
375            let (input, byte_size) = map(u32(endianness), |b| (b & 0xFFFF0000) >> 16)(input)?;
376            println!(
377                "Tag1 data_type={:?} byte_size={:?} padding={:?}",
378                data_type,
379                byte_size,
380                4 - byte_size as u32
381            );
382            Ok((
383                input,
384                DataElementTag {
385                    data_type: DataType::from_u32(data_type).ok_or(nom::Err::Failure(
386                        nom::error::Error {
387                            input: i,
388                            code: nom::error::ErrorKind::Tag,
389                        },
390                    ))?,
391                    // TODO: assert that byte_size is <= 4
392                    data_byte_size: byte_size as u32,
393                    padding_byte_size: 4 - byte_size as u32,
394                },
395            ))
396        }
397    }
398}
399
400pub fn replace_err_slice<'old, 'new>(
401    err: nom::Err<nom::error::Error<&'old [u8]>>,
402    new_slice: &'new [u8],
403) -> nom::Err<nom::error::Error<&'new [u8]>> {
404    match err {
405        nom::Err::Error(nom::error::Error { code, .. }) => nom::Err::Error(nom::error::Error {
406            code,
407            input: new_slice,
408        }),
409        nom::Err::Failure(nom::error::Error { code, .. }) => nom::Err::Failure(nom::error::Error {
410            code,
411            input: new_slice,
412        }),
413        nom::Err::Incomplete(needed) => nom::Err::Incomplete(needed),
414    }
415}
416
417fn assert(i: &[u8], v: bool) -> IResult<&[u8], ()> {
418    if v {
419        Ok((i, ()))
420    } else {
421        Err(nom::Err::Failure(error_position!(
422            i,
423            // TODO
424            nom::error::ErrorKind::Tag
425        )))
426    }
427}
428pub fn parse_array_flags_subelement(
429    i: &[u8],
430    endianness: nom::number::Endianness,
431) -> IResult<&[u8], ArrayFlags> {
432    let (input, (tag_data_type, tag_data_len, flags_and_class, nzmax)) = tuple((
433        u32(endianness),
434        u32(endianness),
435        u32(endianness),
436        u32(endianness),
437    ))(i)?;
438    println!(
439        "arrayflags==>tag_data_type={} tag_data_len={} flags_and_class={} nzmax={} ",
440        tag_data_type, tag_data_len, flags_and_class, nzmax
441    );
442    assert(
443        input,
444        tag_data_type == DataType::UInt32 as u32 && tag_data_len == 8,
445    )?;
446    Ok((
447        input,
448        ArrayFlags {
449            complex: (flags_and_class & 0x0800) != 0,
450            global: (flags_and_class & 0x0400) != 0,
451            logical: (flags_and_class & 0x0200) != 0,
452            class: MatlabType::from_u8((flags_and_class & 0xFF) as u8).ok_or(
453                nom::Err::Failure(nom::error::Error {
454                    input: i,
455                    code: nom::error::ErrorKind::Tag,
456                }), // TODO
457            )?,
458            nzmax: nzmax as usize,
459        },
460    ))
461}
462fn parse_row_index_array_subelement(
463    i: &[u8],
464    endianness: nom::number::Endianness,
465) -> IResult<&[u8], RowIndex> {
466    let (input, data_element_tag) = parse_data_element_tag(i, endianness)?;
467    let (input, row_index) = count(
468        i32(endianness),
469        (data_element_tag.data_byte_size / 4) as usize,
470    )(input)?;
471    let (input, _) = take(data_element_tag.padding_byte_size)(input)?;
472    let rows = row_index.iter().map(|&i| i as usize).collect();
473    Ok((input, rows))
474}
475fn parse_column_index_array_subelement(
476    i: &[u8],
477    endianness: nom::number::Endianness,
478) -> IResult<&[u8], ColumnShift> {
479    let (input, data_element_tag) = parse_data_element_tag(i, endianness)?;
480    let (input, column_index) = count(
481        i32(endianness),
482        (data_element_tag.data_byte_size / 4) as usize,
483    )(input)?;
484    let (input, _) = take(data_element_tag.padding_byte_size)(input)?;
485    let columns = column_index.iter().map(|&i| i as usize).collect();
486    Ok((input, columns))
487}
488
489fn parse_sparse_matrix_subelements(
490    i: &[u8],
491    endianness: nom::number::Endianness,
492    flags: ArrayFlags,
493) -> IResult<&[u8], DataElement> {
494    let (input, dimensions) = parse_dimensions_array_subelement(i, endianness)?;
495    let (input, name) = parse_array_name_subelement(input, endianness)?;
496    let (input, row_index) = parse_row_index_array_subelement(input, endianness)?;
497    let (input, column_index) = parse_column_index_array_subelement(input, endianness)?;
498    //先暂时不要插入检查语句
499    let (input, real_part) = parse_numeric_subelement(input, endianness)?;
500    let (input, imag_part) = if flags.complex {
501        let (input, imag_part) = parse_numeric_subelement(input, endianness)?;
502        (input, Some(imag_part))
503    } else {
504        (input, None)
505    };
506    Ok((
507        input,
508        DataElement::SparseMatrix(
509            flags,
510            dimensions,
511            name,
512            row_index.iter().map(|&i| i as usize).collect(),
513            column_index.iter().map(|&i| i as usize).collect(),
514            real_part,
515            imag_part,
516        ),
517    ))
518}
519fn parse_unsupported_data_element(
520    _i: &[u8],
521    _endianness: nom::number::Endianness,
522) -> IResult<&[u8], DataElement> {
523    Ok((&[], DataElement::Unsupported))
524}
525fn parse_matrix_data_element(
526    i: &[u8],
527    endianness: nom::number::Endianness,
528) -> IResult<&[u8], DataElement> {
529    let (input, flags) = parse_array_flags_subelement(i, endianness)?;
530    println!("arrayflags={:?}  class={:?}", flags, flags.class);
531    let (input, data_element) = match flags.class {
532        MatlabType::Cell => parse_unsupported_data_element(input, endianness)?,
533        MatlabType::Struct => parse_unsupported_data_element(input, endianness)?,
534        MatlabType::Object => parse_unsupported_data_element(input, endianness)?,
535        MatlabType::Char => parse_unsupported_data_element(input, endianness)?,
536        MatlabType::Sparse => parse_sparse_matrix_subelements(input, endianness, flags)?,
537        MatlabType::Opaque => parse_opaque_matrix_subelements(input, endianness)?,
538        _ => parse_numeric_matrix_subelements(input, endianness, flags)?,
539    };
540    Ok((input, data_element))
541}
542fn parse_opaque_matrix_subelements(
543    i: &[u8],
544    endianness: nom::number::Endianness,
545) -> IResult<&[u8], DataElement> {
546    println!("parse_opaque");
547    let (input, data_element_tag) = parse_data_element_tag(i, endianness)?;
548    let (input, name) = take(data_element_tag.data_byte_size)(input)?;
549    println!("name={:?}", String::from_utf8_lossy(name));
550    let (input, _) = take(data_element_tag.padding_byte_size)(input)?;
551
552    let (input, data_element_tag) = parse_data_element_tag(input, endianness)?;
553    let (input, object_type) = take(data_element_tag.data_byte_size)(input)?;
554    let (input, _) = take(data_element_tag.padding_byte_size)(input)?;
555    println!(
556        "objectType={:?} {:?}",
557        String::from_utf8_lossy(object_type),
558        data_element_tag.data_byte_size
559    );
560    let (input, data_element_tag) = parse_data_element_tag(input, endianness)?;
561    let (input, class_name) = take(data_element_tag.data_byte_size)(input)?;
562    let (input, _) = take(data_element_tag.padding_byte_size)(input)?;
563    println!(
564        "className={:?} {:?}",
565        String::from_utf8_lossy(class_name),
566        data_element_tag.data_byte_size
567    );
568    let (input, dimensions) = parse_dimensions_array_subelement(input, endianness)?;
569    println!("dimensions==>{:?}", dimensions);
570    Ok((input, DataElement::Unsupported))
571}
572
573pub fn parse_compressed_data_element(
574    i: &[u8],
575    endianness: nom::number::Endianness,
576    byte_size: u32,
577) -> IResult<&[u8], DataElement> {
578    let mut buf = Vec::new();
579    let (input, compress_data) = take(byte_size)(i)?;
580    Decoder::new(compress_data)
581        .map_err(|err| {
582            eprintln!("{:?}", err);
583            nom::Err::Failure(nom::error::Error {
584                input: i,
585                code: nom::error::ErrorKind::Tag,
586            }) // TODO
587        })?
588        .read_to_end(&mut buf)
589        .map_err(|err| {
590            eprintln!("{:?}", err);
591            nom::Err::Failure(nom::error::Error {
592                input: i,
593                code: nom::error::ErrorKind::Tag,
594            }) // TODO
595        })?;
596
597    println!("buf==>{:?}", buf);
598    let (_remaining, data_element) = parse_next_data_element(buf.as_slice(), endianness)
599        .map_err(|err| replace_err_slice(err, i))?;
600    // Ok((&[], data_element))
601    Ok((input, data_element))
602}
603fn parse_dimensions_array_subelement(
604    i: &[u8],
605    endianness: nom::number::Endianness,
606) -> IResult<&[u8], Dimensions> {
607    let (input, data_element_tag) = parse_data_element_tag(i, endianness)?;
608    let (input, dimensions) = count(
609        i32(endianness),
610        (data_element_tag.data_byte_size / 4) as usize,
611    )(input)?;
612    let (input, _) = take(data_element_tag.padding_byte_size)(input)?;
613    Ok((input, dimensions))
614}
615fn parse_array_name_subelement(
616    i: &[u8],
617    endianness: nom::number::Endianness,
618) -> IResult<&[u8], String> {
619    let (input, data_element_tag) = parse_data_element_tag(i, endianness)?;
620    let (input, name) = map_res(take(data_element_tag.data_byte_size), |b| {
621        std::str::from_utf8(b)
622            .map(|s| s.to_owned())
623            .map_err(|_err| {
624                nom::Err::Failure((i, nom::error::ErrorKind::Tag)) // TODO
625            })
626    })(input)?;
627    let (input, _) = take(data_element_tag.padding_byte_size)(input)?;
628    println!("name===>{:?}", name);
629    Ok((input, name))
630}
631
632fn parse_numeric_subelement(
633    i: &[u8],
634    endianness: nom::number::Endianness,
635) -> IResult<&[u8], NumericData> {
636    let (input, data_element_tag) = parse_data_element_tag(i, endianness)?;
637    println!("数据类型={:?}", data_element_tag);
638    let (input, numeric_data) = match data_element_tag.data_type {
639        DataType::Int8 => {
640            if endianness == Endianness::Big {
641                let (input, data) = count(be_i8, data_element_tag.data_byte_size as usize)(input)?;
642                (input, NumericData::Int8(data))
643            } else {
644                let (input, data) = count(le_i8, data_element_tag.data_byte_size as usize)(input)?;
645                (input, NumericData::Int8(data))
646            }
647        }
648        DataType::UInt8 => {
649            if endianness == Endianness::Big {
650                let (input, data) = count(be_u8, data_element_tag.data_byte_size as usize)(input)?;
651                (input, NumericData::UInt8(data))
652            } else {
653                let (input, data) = count(le_u8, data_element_tag.data_byte_size as usize)(input)?;
654                (input, NumericData::UInt8(data))
655            }
656        }
657        DataType::Int16 => {
658            if endianness == Endianness::Big {
659                let (input, data) =
660                    count(be_i16, data_element_tag.data_byte_size as usize / 2)(input)?;
661                (input, NumericData::Int16(data))
662            } else {
663                let (input, data) =
664                    count(le_i16, data_element_tag.data_byte_size as usize / 2)(input)?;
665                (input, NumericData::Int16(data))
666            }
667        }
668        DataType::UInt16 => {
669            if endianness == Endianness::Big {
670                let (input, data) =
671                    count(be_u16, data_element_tag.data_byte_size as usize / 2)(input)?;
672                (input, NumericData::UInt16(data))
673            } else {
674                let (input, data) =
675                    count(le_u16, data_element_tag.data_byte_size as usize / 2)(input)?;
676                (input, NumericData::UInt16(data))
677            }
678        }
679        DataType::Int32 => {
680            if endianness == Endianness::Big {
681                let (input, data) =
682                    count(be_i32, data_element_tag.data_byte_size as usize / 4)(input)?;
683                (input, NumericData::Int32(data))
684            } else {
685                let (input, data) =
686                    count(le_i32, data_element_tag.data_byte_size as usize / 4)(input)?;
687                (input, NumericData::Int32(data))
688            }
689        }
690        DataType::UInt32 => {
691            if endianness == Endianness::Big {
692                let (input, data) =
693                    count(be_u32, data_element_tag.data_byte_size as usize / 4)(input)?;
694                (input, NumericData::UInt32(data))
695            } else {
696                let (input, data) =
697                    count(le_u32, data_element_tag.data_byte_size as usize / 4)(input)?;
698                (input, NumericData::UInt32(data))
699            }
700        }
701        DataType::Int64 => {
702            if endianness == Endianness::Big {
703                let (input, data) =
704                    count(be_i64, data_element_tag.data_byte_size as usize / 8)(input)?;
705                (input, NumericData::Int64(data))
706            } else {
707                let (input, data) =
708                    count(le_i64, data_element_tag.data_byte_size as usize / 8)(input)?;
709                (input, NumericData::Int64(data))
710            }
711        }
712        DataType::UInt64 => {
713            if endianness == Endianness::Big {
714                let (input, data) =
715                    count(be_u64, data_element_tag.data_byte_size as usize / 8)(input)?;
716                (input, NumericData::UInt64(data))
717            } else {
718                let (input, data) =
719                    count(le_u64, data_element_tag.data_byte_size as usize / 8)(input)?;
720                (input, NumericData::UInt64(data))
721            }
722        }
723        DataType::Single => {
724            if endianness == Endianness::Big {
725                let (input, data) =
726                    count(be_f32, data_element_tag.data_byte_size as usize / 4)(input)?;
727                (input, NumericData::Single(data))
728            } else {
729                let (input, data) =
730                    count(le_f32, data_element_tag.data_byte_size as usize / 4)(input)?;
731                (input, NumericData::Single(data))
732            }
733        }
734        DataType::Double => {
735            if endianness == Endianness::Big {
736                let (input, data) =
737                    count(be_f64, data_element_tag.data_byte_size as usize / 8)(input)?;
738                (input, NumericData::Double(data))
739            } else {
740                let (input, data) =
741                    count(le_f64, data_element_tag.data_byte_size as usize / 8)(input)?;
742                (input, NumericData::Double(data))
743            }
744        }
745        _ => {
746            return Err(nom::Err::Failure(error_position!(
747                i,
748                // TODO
749                nom::error::ErrorKind::Tag
750            )));
751        }
752    };
753    take(data_element_tag.padding_byte_size)(input)?;
754    Ok((input, numeric_data))
755}
756
757fn parse_numeric_matrix_subelements(
758    i: &[u8],
759    endianness: nom::number::Endianness,
760    flags: ArrayFlags,
761) -> IResult<&[u8], DataElement> {
762    println!("dimensions");
763    let (input, dimensions) = parse_dimensions_array_subelement(i, endianness)?;
764    let (input, name) = parse_array_name_subelement(input, endianness)?;
765    let (input, real_part) = parse_numeric_subelement(input, endianness)?;
766    // let (input, n_required_elements) = value(dimensions.iter().product::<i32>(), alpha0)(input)?;
767    // let (input, array_data_type) = value(flags.class.numeric_data_type().unwrap(), alpha0)(input)?;
768    let (input, imag_part) = if flags.complex {
769        let (input, imag_part) = parse_numeric_subelement(input, endianness)?;
770        (input, Some(imag_part))
771    } else {
772        (input, None)
773    };
774    Ok((
775        input,
776        DataElement::NumericMatrix(flags, dimensions, name, real_part, imag_part),
777    ))
778}
779
780fn parse_next_data_element(
781    i: &[u8],
782    endianness: nom::number::Endianness,
783) -> IResult<&[u8], DataElement> {
784    let (input, data_element_tag) = parse_data_element_tag(i, endianness)?;
785    println!("data_element_tag=={:?}", data_element_tag);
786    let (input, data_element) = match data_element_tag.data_type {
787        DataType::Matrix => parse_matrix_data_element(input, endianness)?,
788        DataType::Compressed => {
789            parse_compressed_data_element(input, endianness, data_element_tag.data_byte_size)?
790        }
791        _ => parse_unsupported_data_element(input, endianness)?,
792    };
793    Ok((input, data_element))
794    // let (input, data) = take(data_element_tag.data_byte_size)(input)?;
795    // Ok((input, DataElement::Unsupported))
796}
797
798pub fn parse_all(i: &[u8]) -> IResult<&[u8], ParseResult> {
799    let (mut input, header) = parse_header(i)?;
800    println!("{:?}", header);
801    let mut data_elements = vec![];
802    loop {
803        match parse_next_data_element(input, header.byte_order) {
804            Ok((new_input, data_element)) => {
805                input = new_input;
806                data_elements.push(data_element);
807            }
808            _ => {
809                break;
810            }
811        };
812    }
813    // println!("matfile==>{:?}", data_elements);
814    Ok((
815        input,
816        ParseResult {
817            header: header,
818            data_elements: data_elements,
819        },
820    ))
821}
822
823mod tests {
824    use crate::parse::le_f64;
825    use crate::parse::DataElement;
826    use nom::multi::count;
827    use nom::IResult;
828
829    #[test]
830    fn name() {
831        let data = include_bytes!("d:/myfile.mat");
832        let r = super::parse_all(data).unwrap();
833    }
834    #[test]
835    fn test_product() {
836        let v = vec![1, 2, -3];
837        let s = v.iter().product::<i32>();
838        println!("{}", s);
839    }
840
841    #[test]
842    fn decode() {
843        let encoded_data = [
844            120, 156, 243, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73, 81, 4, 0, 28, 73, 4, 62,
845        ];
846        let decoder = libflate::zlib::Decoder::new(&encoded_data[..]).unwrap();
847        println!("decode=={:?}", decoder);
848    }
849    fn test_count(i: &[u8]) -> IResult<&[u8], DataElement> {
850        let array = &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..];
851        println!("{:?}", array);
852        let result = count(le_f64, 1)(array)?;
853        println!("{:?}", result);
854        Ok((&[], DataElement::Unsupported))
855    }
856}