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, }
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 }
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 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 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 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 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 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 }), )?,
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 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 }) })?
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 }) })?;
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((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)) })
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 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, 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 }
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 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}