exon_mzml/mzml_reader/
binary_conversion.rs1use flate2::read::ZlibDecoder;
16use std::io::prelude::*;
17
18use byteorder::{LittleEndian, ReadBytesExt};
19use std::io::Cursor;
20
21use base64::Engine;
22
23use super::types::{Binary, CompressionType, DataType};
24
25pub fn decode_binary_array(
27 b: &Binary,
28 ct: &CompressionType,
29 dt: &DataType,
30) -> std::io::Result<Vec<f64>> {
31 let decoded = match &b.content {
32 Some(c) => c,
33 None => {
34 return Err(std::io::Error::new(
35 std::io::ErrorKind::InvalidData,
36 "No binary content found.",
37 ))
38 }
39 };
40
41 let decoded = base64::engine::general_purpose::STANDARD
42 .decode(decoded)
43 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
44
45 match (ct, dt) {
46 (CompressionType::NoCompression, DataType::Float32Bit) => {
47 Ok(binary_string_to_array_f32(decoded))
48 }
49 (CompressionType::NoCompression, DataType::Float64Bit) => {
50 Ok(binary_string_to_array_f64(decoded))
51 }
52 (CompressionType::ZlibCompression, DataType::Float64Bit) => {
53 let mut decoded_bytes = Vec::<u8>::new();
54
55 let rdr = Cursor::new(decoded);
56
57 let mut d = ZlibDecoder::new(rdr);
58 d.read_to_end(&mut decoded_bytes).unwrap();
59
60 Ok(binary_string_to_array_f64(decoded_bytes))
61 }
62 (CompressionType::ZlibCompression, DataType::Float32Bit) => {
63 let mut decoded_bytes = Vec::<u8>::new();
64
65 let rdr = Cursor::new(decoded);
66
67 let mut d = ZlibDecoder::new(rdr);
68 d.read_to_end(&mut decoded_bytes).unwrap();
69
70 Ok(binary_string_to_array_f32(decoded_bytes))
71 }
72 }
73}
74
75pub fn binary_string_to_array_f32(decoded: Vec<u8>) -> Vec<f64> {
76 let mut rdr = Cursor::new(decoded);
77
78 let mut peaks = Vec::<f64>::new();
79 while let Ok(fl) = rdr.read_f32::<LittleEndian>() {
80 peaks.push(f64::from(fl));
81 }
82
83 peaks
84}
85
86pub fn binary_string_to_array_f64(decoded: Vec<u8>) -> Vec<f64> {
87 let mut rdr = Cursor::new(decoded);
88
89 let mut peaks = Vec::<f64>::new();
90 while let Ok(fl) = rdr.read_f64::<LittleEndian>() {
91 peaks.push(fl);
92 }
93
94 peaks
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn parse_mzml_test() {
103 struct TestData {
104 binary: Binary,
105 compression_type: CompressionType,
106 data_type: DataType,
107 expected_array: Vec<f64>,
108 }
109
110 impl TestData {
111 pub fn new(
112 binary: Binary,
113 compression_type: CompressionType,
114 data_type: DataType,
115 expected_array: Vec<f64>,
116 ) -> Self {
117 Self {
118 binary,
119 compression_type,
120 data_type,
121 expected_array,
122 }
123 }
124 }
125
126 let tests = [
127 TestData::new(Binary::new(Some(String::from("AAAAAAAALkAAAAAAAAAsQAAAAAAAACpAAAAAAAAAKEAAAAAAAAAmQAAAAAAAACRAAAAAAAAAIkAAAAAAAAAgQAAAAAAAABxAAAAAAAAAGEAAAAAAAAAUQAAAAAAAABBAAAAAAAAACEAAAAAAAAAAQAAAAAAAAPA/"))), CompressionType::NoCompression, DataType::Float64Bit, vec![15.0, 14.0, 13.0, 12.0, 11.0, 10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0]),
128 TestData::new(Binary::new(Some(String::from("eJxjYEABDhBKAEpLQGkFKK0CpTWgtA6UNoDSRg4AZlQDYw=="))), CompressionType::ZlibCompression, DataType::Float64Bit, vec![0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0])
129 ];
130
131 for test in tests.iter() {
132 let array =
133 decode_binary_array(&test.binary, &test.compression_type, &test.data_type).unwrap();
134 assert_eq!(array, test.expected_array);
135 }
136 }
137}