1use crate::{UtilsError, UtilsResult};
7use scirs2_core::ndarray::{Array1, Array2};
8use std::collections::HashMap;
9use std::fs::{File, OpenOptions};
10use std::io::{BufRead, BufReader, BufWriter, Read, Write};
11use std::path::Path;
12
13pub struct EfficientFileReader {
17 reader: BufReader<File>,
18 #[allow(dead_code)]
19 buffer_size: usize,
20}
21
22impl EfficientFileReader {
23 pub fn new<P: AsRef<Path>>(path: P, buffer_size: Option<usize>) -> UtilsResult<Self> {
25 let file = File::open(path)
26 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to open file: {e}")))?;
27
28 let buffer_size = buffer_size.unwrap_or(8192);
29 let reader = BufReader::with_capacity(buffer_size, file);
30
31 Ok(Self {
32 reader,
33 buffer_size,
34 })
35 }
36
37 pub fn read_lines(&mut self) -> impl Iterator<Item = UtilsResult<String>> + '_ {
39 std::io::BufRead::lines(&mut self.reader).map(|line| {
40 line.map_err(|e| UtilsError::InvalidParameter(format!("Failed to read line: {e}")))
41 })
42 }
43
44 pub fn read_chunk(&mut self, size: usize) -> UtilsResult<Vec<u8>> {
46 let mut buffer = vec![0u8; size];
47 let bytes_read = self
48 .reader
49 .read(&mut buffer)
50 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to read chunk: {e}")))?;
51
52 buffer.truncate(bytes_read);
53 Ok(buffer)
54 }
55
56 pub fn read_all(&mut self) -> UtilsResult<Vec<u8>> {
58 let mut content = Vec::new();
59 self.reader
60 .read_to_end(&mut content)
61 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to read file: {e}")))?;
62 Ok(content)
63 }
64
65 pub fn read_array1(&mut self, delimiter: &str) -> UtilsResult<Array1<f64>> {
67 let mut line = String::new();
68 self.reader
69 .read_line(&mut line)
70 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to read line: {e}")))?;
71
72 let values: Result<Vec<f64>, _> = line
73 .trim()
74 .split(delimiter)
75 .filter(|s| !s.is_empty())
76 .map(|s| s.parse::<f64>())
77 .collect();
78
79 let values = values
80 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to parse numbers: {e}")))?;
81
82 Ok(Array1::from_vec(values))
83 }
84
85 pub fn read_array2(&mut self, delimiter: &str) -> UtilsResult<Array2<f64>> {
87 let mut rows = Vec::new();
88 let mut line = String::new();
89
90 while self.reader.read_line(&mut line).unwrap_or(0) > 0 {
91 if line.trim().is_empty() {
92 line.clear();
93 continue;
94 }
95
96 let values: Result<Vec<f64>, _> = line
97 .trim()
98 .split(delimiter)
99 .filter(|s| !s.is_empty())
100 .map(|s| s.parse::<f64>())
101 .collect();
102
103 let values = values.map_err(|e| {
104 UtilsError::InvalidParameter(format!("Failed to parse numbers: {e}"))
105 })?;
106
107 rows.push(values);
108 line.clear();
109 }
110
111 if rows.is_empty() {
112 return Err(UtilsError::EmptyInput);
113 }
114
115 let ncols = rows[0].len();
116 let nrows = rows.len();
117
118 for row in &rows {
120 if row.len() != ncols {
121 return Err(UtilsError::ShapeMismatch {
122 expected: vec![ncols],
123 actual: vec![row.len()],
124 });
125 }
126 }
127
128 let flat: Vec<f64> = rows.into_iter().flatten().collect();
129 Array2::from_shape_vec((nrows, ncols), flat)
130 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to create array: {e}")))
131 }
132}
133
134pub struct EfficientFileWriter {
136 writer: BufWriter<File>,
137}
138
139impl EfficientFileWriter {
140 pub fn new<P: AsRef<Path>>(path: P, buffer_size: Option<usize>) -> UtilsResult<Self> {
142 let file = OpenOptions::new()
143 .write(true)
144 .create(true)
145 .truncate(true)
146 .open(path)
147 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to create file: {e}")))?;
148
149 let buffer_size = buffer_size.unwrap_or(8192);
150 let writer = BufWriter::with_capacity(buffer_size, file);
151
152 Ok(Self { writer })
153 }
154
155 pub fn append<P: AsRef<Path>>(path: P, buffer_size: Option<usize>) -> UtilsResult<Self> {
157 let file = OpenOptions::new()
158 .create(true)
159 .append(true)
160 .open(path)
161 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to open file: {e}")))?;
162
163 let buffer_size = buffer_size.unwrap_or(8192);
164 let writer = BufWriter::with_capacity(buffer_size, file);
165
166 Ok(Self { writer })
167 }
168
169 pub fn write_data(&mut self, data: &[u8]) -> UtilsResult<()> {
171 self.writer
172 .write_all(data)
173 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to write data: {e}")))?;
174 Ok(())
175 }
176
177 pub fn write_lines<I>(&mut self, lines: I) -> UtilsResult<()>
179 where
180 I: IntoIterator<Item = String>,
181 {
182 for line in lines {
183 writeln!(self.writer, "{line}")
184 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to write line: {e}")))?;
185 }
186 Ok(())
187 }
188
189 pub fn write_array1(&mut self, array: &Array1<f64>, delimiter: &str) -> UtilsResult<()> {
191 let line = array
192 .iter()
193 .map(|x| x.to_string())
194 .collect::<Vec<_>>()
195 .join(delimiter);
196
197 writeln!(self.writer, "{line}")
198 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to write array: {e}")))?;
199 Ok(())
200 }
201
202 pub fn write_array2(&mut self, array: &Array2<f64>, delimiter: &str) -> UtilsResult<()> {
204 for row in array.outer_iter() {
205 let line = row
206 .iter()
207 .map(|x| x.to_string())
208 .collect::<Vec<_>>()
209 .join(delimiter);
210
211 writeln!(self.writer, "{line}")
212 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to write row: {e}")))?;
213 }
214 Ok(())
215 }
216
217 pub fn flush(&mut self) -> UtilsResult<()> {
219 self.writer
220 .flush()
221 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to flush: {e}")))?;
222 Ok(())
223 }
224}
225
226pub struct CompressionUtils;
230
231impl CompressionUtils {
232 #[cfg(feature = "compression")]
234 pub fn compress_gzip(data: &[u8]) -> UtilsResult<Vec<u8>> {
235 oxiarc_deflate::gzip_compress(data, 6)
236 .map_err(|e| UtilsError::InvalidParameter(format!("Compression failed: {e}")))
237 }
238
239 #[cfg(feature = "compression")]
241 pub fn decompress_gzip(data: &[u8]) -> UtilsResult<Vec<u8>> {
242 oxiarc_deflate::gzip_decompress(data)
243 .map_err(|e| UtilsError::InvalidParameter(format!("Decompression failed: {e}")))
244 }
245
246 pub fn run_length_encode(data: &[u8]) -> Vec<(u8, usize)> {
248 if data.is_empty() {
249 return Vec::new();
250 }
251
252 let mut result = Vec::new();
253 let mut current_value = data[0];
254 let mut count = 1;
255
256 for &byte in &data[1..] {
257 if byte == current_value {
258 count += 1;
259 } else {
260 result.push((current_value, count));
261 current_value = byte;
262 count = 1;
263 }
264 }
265 result.push((current_value, count));
266 result
267 }
268
269 pub fn run_length_decode(encoded: &[(u8, usize)]) -> Vec<u8> {
271 let mut result = Vec::new();
272 for &(value, count) in encoded {
273 result.extend(std::iter::repeat_n(value, count));
274 }
275 result
276 }
277}
278
279pub struct StreamProcessor<R: Read> {
283 reader: R,
284 chunk_size: usize,
285}
286
287impl<R: Read> StreamProcessor<R> {
288 pub fn new(reader: R, chunk_size: usize) -> Self {
290 Self { reader, chunk_size }
291 }
292
293 pub fn process_chunks<F>(&mut self, mut processor: F) -> UtilsResult<()>
295 where
296 F: FnMut(&[u8]) -> UtilsResult<()>,
297 {
298 let mut buffer = vec![0u8; self.chunk_size];
299
300 loop {
301 let bytes_read = self
302 .reader
303 .read(&mut buffer)
304 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to read chunk: {e}")))?;
305
306 if bytes_read == 0 {
307 break;
308 }
309
310 processor(&buffer[..bytes_read])?;
311 }
312
313 Ok(())
314 }
315
316 pub fn process_lines<F>(&mut self, mut processor: F) -> UtilsResult<()>
318 where
319 F: FnMut(&str) -> UtilsResult<()>,
320 R: BufRead,
321 {
322 let mut line = String::new();
323
324 loop {
325 line.clear();
326 let bytes_read = self
327 .reader
328 .read_line(&mut line)
329 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to read line: {e}")))?;
330
331 if bytes_read == 0 {
332 break;
333 }
334
335 processor(line.trim_end())?;
336 }
337
338 Ok(())
339 }
340}
341
342pub struct FormatConverter;
346
347impl FormatConverter {
348 pub fn csv_to_arrays<P: AsRef<Path>>(
350 path: P,
351 delimiter: char,
352 has_header: bool,
353 ) -> UtilsResult<(Option<Vec<String>>, Array2<f64>)> {
354 let mut reader = EfficientFileReader::new(path, None)?;
355 let mut lines = reader.read_lines();
356
357 let header = if has_header {
358 if let Some(line_result) = lines.next() {
359 let line = line_result?;
360 Some(
361 line.split(delimiter)
362 .map(|s| s.trim().to_string())
363 .collect(),
364 )
365 } else {
366 return Err(UtilsError::EmptyInput);
367 }
368 } else {
369 None
370 };
371
372 let mut rows = Vec::new();
373 for line_result in lines {
374 let line = line_result?;
375 if line.trim().is_empty() {
376 continue;
377 }
378
379 let values: Result<Vec<f64>, _> = line
380 .split(delimiter)
381 .map(|s| s.trim().parse::<f64>())
382 .collect();
383
384 let values = values.map_err(|e| {
385 UtilsError::InvalidParameter(format!("Failed to parse CSV values: {e}"))
386 })?;
387
388 rows.push(values);
389 }
390
391 if rows.is_empty() {
392 return Err(UtilsError::EmptyInput);
393 }
394
395 let ncols = rows[0].len();
396 let nrows = rows.len();
397
398 for row in &rows {
399 if row.len() != ncols {
400 return Err(UtilsError::ShapeMismatch {
401 expected: vec![ncols],
402 actual: vec![row.len()],
403 });
404 }
405 }
406
407 let flat: Vec<f64> = rows.into_iter().flatten().collect();
408 let array = Array2::from_shape_vec((nrows, ncols), flat)
409 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to create array: {e}")))?;
410
411 Ok((header, array))
412 }
413
414 pub fn arrays_to_csv<P: AsRef<Path>>(
416 path: P,
417 data: &Array2<f64>,
418 header: Option<&[String]>,
419 delimiter: char,
420 ) -> UtilsResult<()> {
421 let mut writer = EfficientFileWriter::new(path, None)?;
422
423 if let Some(header) = header {
424 let header_line = header.join(&delimiter.to_string());
425 writeln!(writer.writer, "{header_line}").map_err(|e| {
426 UtilsError::InvalidParameter(format!("Failed to write header: {e}"))
427 })?;
428 }
429
430 for row in data.outer_iter() {
431 let line = row
432 .iter()
433 .map(|x| x.to_string())
434 .collect::<Vec<_>>()
435 .join(&delimiter.to_string());
436
437 writeln!(writer.writer, "{line}")
438 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to write row: {e}")))?;
439 }
440
441 writer.flush()?;
442 Ok(())
443 }
444
445 pub fn json_to_map(json_str: &str) -> UtilsResult<HashMap<String, serde_json::Value>> {
447 serde_json::from_str(json_str)
448 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to parse JSON: {e}")))
449 }
450
451 pub fn map_to_json(map: &HashMap<String, serde_json::Value>) -> UtilsResult<String> {
453 serde_json::to_string_pretty(map)
454 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to serialize JSON: {e}")))
455 }
456
457 #[cfg(feature = "yaml")]
459 pub fn yaml_to_map(yaml_str: &str) -> UtilsResult<HashMap<String, serde_json::Value>> {
460 let yaml_value: serde_yaml::Value = serde_yaml::from_str(yaml_str)
461 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to parse YAML: {e}")))?;
462
463 let json_str = serde_json::to_string(&yaml_value).map_err(|e| {
465 UtilsError::InvalidParameter(format!("Failed to convert YAML to JSON: {e}"))
466 })?;
467
468 Self::json_to_map(&json_str)
469 }
470
471 #[cfg(feature = "yaml")]
473 pub fn map_to_yaml(map: &HashMap<String, serde_json::Value>) -> UtilsResult<String> {
474 serde_yaml::to_string(map)
475 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to serialize YAML: {e}")))
476 }
477
478 #[cfg(feature = "toml_support")]
480 pub fn toml_to_map(toml_str: &str) -> UtilsResult<HashMap<String, serde_json::Value>> {
481 let toml_value: toml::Value = toml::from_str(toml_str)
482 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to parse TOML: {e}")))?;
483
484 let json_str = serde_json::to_string(&toml_value).map_err(|e| {
486 UtilsError::InvalidParameter(format!("Failed to convert TOML to JSON: {e}"))
487 })?;
488
489 Self::json_to_map(&json_str)
490 }
491
492 #[cfg(feature = "toml_support")]
494 pub fn map_to_toml(map: &HashMap<String, serde_json::Value>) -> UtilsResult<String> {
495 let toml_value = serde_json::from_str::<toml::Value>(&serde_json::to_string(map)?)
497 .map_err(|e| {
498 UtilsError::InvalidParameter(format!("Failed to convert to TOML value: {e}"))
499 })?;
500
501 toml::to_string_pretty(&toml_value)
502 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to serialize TOML: {e}")))
503 }
504
505 #[cfg(feature = "xml")]
507 pub fn xml_to_simple_map(xml_str: &str) -> UtilsResult<HashMap<String, String>> {
508 use quick_xml::escape::unescape;
509 use quick_xml::events::Event;
510 use quick_xml::Reader;
511
512 let mut reader = Reader::from_str(xml_str);
513 reader.config_mut().trim_text(true);
514
515 let mut result = HashMap::new();
516 let mut current_element = String::new();
517 let mut buf = Vec::new();
518
519 loop {
520 match reader.read_event_into(&mut buf) {
521 Ok(Event::Start(ref e)) => {
522 current_element = String::from_utf8_lossy(e.name().as_ref()).to_string();
523 }
524 Ok(Event::Text(e)) if !current_element.is_empty() => {
525 let raw_text = e.decode().map_err(|e| {
526 UtilsError::InvalidParameter(format!("Failed to decode XML text: {}", e))
527 })?;
528 let text = unescape(&raw_text).map_err(|e| {
529 UtilsError::InvalidParameter(format!("Failed to unescape XML text: {}", e))
530 })?;
531 result.insert(current_element.clone(), text.into_owned());
532 }
533 Ok(Event::Text(_)) => {
534 }
536 Ok(Event::End(_)) => {
537 current_element.clear();
538 }
539 Ok(Event::Eof) => break,
540 Err(e) => {
541 return Err(UtilsError::InvalidParameter(format!(
542 "Failed to parse XML: {}",
543 e
544 )));
545 }
546 _ => {}
547 }
548 buf.clear();
549 }
550
551 Ok(result)
552 }
553
554 #[cfg(feature = "xml")]
556 pub fn simple_map_to_xml(
557 map: &HashMap<String, String>,
558 root_name: &str,
559 ) -> UtilsResult<String> {
560 use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
561 use quick_xml::Writer;
562 use std::io::Cursor;
563
564 let mut writer = Writer::new(Cursor::new(Vec::new()));
565
566 writer
568 .write_event(Event::Decl(quick_xml::events::BytesDecl::new(
569 "1.0",
570 Some("UTF-8"),
571 None,
572 )))
573 .map_err(|e| {
574 UtilsError::InvalidParameter(format!("Failed to write XML declaration: {e}"))
575 })?;
576
577 writer
579 .write_event(Event::Start(BytesStart::new(root_name)))
580 .map_err(|e| {
581 UtilsError::InvalidParameter(format!("Failed to write root element: {e}"))
582 })?;
583
584 for (key, value) in map {
586 writer
587 .write_event(Event::Start(BytesStart::new(key)))
588 .map_err(|e| {
589 UtilsError::InvalidParameter(format!("Failed to write element start: {e}"))
590 })?;
591
592 writer
593 .write_event(Event::Text(BytesText::new(value)))
594 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to write text: {e}")))?;
595
596 writer
597 .write_event(Event::End(BytesEnd::new(key)))
598 .map_err(|e| {
599 UtilsError::InvalidParameter(format!("Failed to write element end: {e}"))
600 })?;
601 }
602
603 writer
605 .write_event(Event::End(BytesEnd::new(root_name)))
606 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to write root end: {e}")))?;
607
608 let result = writer.into_inner().into_inner();
609 String::from_utf8(result).map_err(|e| {
610 UtilsError::InvalidParameter(format!("Failed to convert XML to string: {e}"))
611 })
612 }
613
614 pub fn json_to_arrays(json_str: &str) -> UtilsResult<HashMap<String, Array2<f64>>> {
616 let data: HashMap<String, Vec<Vec<f64>>> = serde_json::from_str(json_str).map_err(|e| {
617 UtilsError::InvalidParameter(format!("Failed to parse JSON arrays: {e}"))
618 })?;
619
620 let mut result = HashMap::new();
621 for (key, matrix) in data {
622 if matrix.is_empty() {
623 continue;
624 }
625
626 let nrows = matrix.len();
627 let ncols = matrix[0].len();
628
629 for row in matrix.iter() {
631 if row.len() != ncols {
632 return Err(UtilsError::ShapeMismatch {
633 expected: vec![ncols],
634 actual: vec![row.len()],
635 });
636 }
637 }
638
639 let flat: Vec<f64> = matrix.into_iter().flatten().collect();
640 let array = Array2::from_shape_vec((nrows, ncols), flat).map_err(|e| {
641 UtilsError::InvalidParameter(format!("Failed to create array: {e}"))
642 })?;
643
644 result.insert(key, array);
645 }
646
647 Ok(result)
648 }
649
650 pub fn arrays_to_json(arrays: &HashMap<String, &Array2<f64>>) -> UtilsResult<String> {
652 let mut data = HashMap::new();
653
654 for (key, array) in arrays {
655 let matrix: Vec<Vec<f64>> = array.outer_iter().map(|row| row.to_vec()).collect();
656 data.insert(key.clone(), matrix);
657 }
658
659 serde_json::to_string_pretty(&data).map_err(|e| {
660 UtilsError::InvalidParameter(format!("Failed to serialize arrays to JSON: {e}"))
661 })
662 }
663}
664
665pub struct SerializationUtils;
669
670impl SerializationUtils {
671 pub fn serialize_array2(array: &Array2<f64>) -> UtilsResult<Vec<u8>> {
673 let shape = array.shape();
674 let mut data = Vec::new();
675
676 data.extend_from_slice(&(shape[0] as u64).to_le_bytes());
678 data.extend_from_slice(&(shape[1] as u64).to_le_bytes());
679
680 for &value in array.iter() {
682 data.extend_from_slice(&value.to_le_bytes());
683 }
684
685 Ok(data)
686 }
687
688 pub fn deserialize_array2(data: &[u8]) -> UtilsResult<Array2<f64>> {
690 if data.len() < 16 {
691 return Err(UtilsError::InvalidParameter(
692 "Insufficient data for array header".to_string(),
693 ));
694 }
695
696 let nrows = u64::from_le_bytes([
698 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
699 ]) as usize;
700
701 let ncols = u64::from_le_bytes([
702 data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
703 ]) as usize;
704
705 let expected_len = 16 + nrows * ncols * 8;
706 if data.len() != expected_len {
707 return Err(UtilsError::InvalidParameter(format!(
708 "Data length mismatch: expected {}, got {}",
709 expected_len,
710 data.len()
711 )));
712 }
713
714 let mut values = Vec::with_capacity(nrows * ncols);
716 for i in 0..(nrows * ncols) {
717 let start = 16 + i * 8;
718 let bytes = [
719 data[start],
720 data[start + 1],
721 data[start + 2],
722 data[start + 3],
723 data[start + 4],
724 data[start + 5],
725 data[start + 6],
726 data[start + 7],
727 ];
728 values.push(f64::from_le_bytes(bytes));
729 }
730
731 Array2::from_shape_vec((nrows, ncols), values)
732 .map_err(|e| UtilsError::InvalidParameter(format!("Failed to create array: {e}")))
733 }
734
735 pub fn serialize_to_file<P: AsRef<Path>>(path: P, array: &Array2<f64>) -> UtilsResult<()> {
737 let data = Self::serialize_array2(array)?;
738 let mut writer = EfficientFileWriter::new(path, None)?;
739 writer.write_data(&data)?;
740 writer.flush()?;
741 Ok(())
742 }
743
744 pub fn deserialize_from_file<P: AsRef<Path>>(path: P) -> UtilsResult<Array2<f64>> {
746 let mut reader = EfficientFileReader::new(path, None)?;
747 let data = reader.read_all()?;
748 Self::deserialize_array2(&data)
749 }
750}
751
752#[allow(non_snake_case)]
753#[cfg(test)]
754mod tests {
755 use super::*;
756 use std::io::Cursor;
757 use tempfile::NamedTempFile;
758
759 #[test]
760 fn test_efficient_file_reader_writer() {
761 let temp_file = NamedTempFile::new().expect("operation should succeed");
762 let path = temp_file.path();
763
764 let mut writer = EfficientFileWriter::new(path, None).expect("operation should succeed");
766 writer
767 .write_lines(vec!["line1".to_string(), "line2".to_string()])
768 .expect("operation should succeed");
769 writer.flush().expect("operation should succeed");
770 drop(writer);
771
772 let mut reader = EfficientFileReader::new(path, None).expect("operation should succeed");
774 let lines: Result<Vec<_>, _> = reader.read_lines().collect();
775 let lines = lines.expect("operation should succeed");
776
777 assert_eq!(lines.len(), 2);
778 assert_eq!(lines[0], "line1");
779 assert_eq!(lines[1], "line2");
780 }
781
782 #[test]
783 fn test_array_io() {
784 let temp_file = NamedTempFile::new().expect("operation should succeed");
785 let path = temp_file.path();
786
787 let original = Array2::from_shape_vec((2, 3), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
789 .expect("operation should succeed");
790
791 FormatConverter::arrays_to_csv(path, &original, None, ',')
793 .expect("operation should succeed");
794
795 let (header, loaded) =
797 FormatConverter::csv_to_arrays(path, ',', false).expect("operation should succeed");
798 assert!(header.is_none());
799 assert_eq!(original.shape(), loaded.shape());
800 assert!((original - loaded).mapv(f64::abs).sum() < 1e-10);
801 }
802
803 #[test]
804 fn test_serialization() {
805 let original = Array2::from_shape_vec((2, 3), vec![1.1, 2.2, 3.3, 4.4, 5.5, 6.6])
806 .expect("operation should succeed");
807
808 let serialized =
810 SerializationUtils::serialize_array2(&original).expect("operation should succeed");
811 let deserialized =
812 SerializationUtils::deserialize_array2(&serialized).expect("operation should succeed");
813
814 assert_eq!(original.shape(), deserialized.shape());
815 assert!((original - deserialized).mapv(f64::abs).sum() < 1e-10);
816 }
817
818 #[test]
819 fn test_compression() {
820 let data = b"Hello, World! This is a test string for compression.";
821
822 let encoded = CompressionUtils::run_length_encode(data);
823 let decoded = CompressionUtils::run_length_decode(&encoded);
824
825 assert_eq!(data.to_vec(), decoded);
826 }
827
828 #[test]
829 fn test_stream_processor() {
830 let data = b"chunk1chunk2chunk3";
831 let cursor = Cursor::new(data);
832 let mut processor = StreamProcessor::new(cursor, 6);
833
834 let mut chunks = Vec::new();
835 processor
836 .process_chunks(|chunk| {
837 chunks.push(chunk.to_vec());
838 Ok(())
839 })
840 .expect("operation should succeed");
841
842 assert_eq!(chunks.len(), 3);
843 assert_eq!(&chunks[0], b"chunk1");
844 assert_eq!(&chunks[1], b"chunk2");
845 assert_eq!(&chunks[2], b"chunk3");
846 }
847
848 #[test]
849 fn test_format_conversion() {
850 let temp_file = NamedTempFile::new().expect("operation should succeed");
851 let path = temp_file.path();
852
853 std::fs::write(path, "age,score\n25,95.5\n30,87.2").expect("operation should succeed");
855
856 let (header, data) =
857 FormatConverter::csv_to_arrays(path, ',', true).expect("operation should succeed");
858
859 assert!(header.is_some());
860 let header = header.expect("operation should succeed");
861 assert_eq!(header, vec!["age", "score"]);
862
863 assert_eq!(data.shape(), &[2, 2]);
864 assert!((data[[0, 0]] - 25.0).abs() < 1e-10);
865 assert!((data[[0, 1]] - 95.5).abs() < 1e-10);
866 assert!((data[[1, 0]] - 30.0).abs() < 1e-10);
867 assert!((data[[1, 1]] - 87.2).abs() < 1e-10);
868 }
869
870 #[test]
871 fn test_enhanced_json_arrays() {
872 let json_data = r#"
874 {
875 "features": [[1.0, 2.0], [3.0, 4.0]],
876 "targets": [[5.0], [6.0]]
877 }"#;
878
879 let arrays = FormatConverter::json_to_arrays(json_data).expect("operation should succeed");
880
881 assert_eq!(arrays.len(), 2);
882 assert!(arrays.contains_key("features"));
883 assert!(arrays.contains_key("targets"));
884
885 let features = &arrays["features"];
886 assert_eq!(features.shape(), &[2, 2]);
887 assert!((features[[0, 0]] - 1.0).abs() < 1e-10);
888 assert!((features[[1, 1]] - 4.0).abs() < 1e-10);
889
890 let mut array_refs = HashMap::new();
892 array_refs.insert("features".to_string(), features);
893
894 let json_result =
895 FormatConverter::arrays_to_json(&array_refs).expect("operation should succeed");
896 assert!(json_result.contains("features"));
897 assert!(json_result.contains("1.0"));
898 }
899
900 #[test]
901 #[cfg(feature = "yaml")]
902 fn test_yaml_conversion() {
903 let yaml_data = r#"
904 name: test
905 value: 42
906 nested:
907 key: "hello"
908 "#;
909
910 let map = FormatConverter::yaml_to_map(yaml_data).expect("operation should succeed");
911 assert!(map.contains_key("name"));
912 assert!(map.contains_key("value"));
913
914 let yaml_result = FormatConverter::map_to_yaml(&map).expect("operation should succeed");
915 assert!(yaml_result.contains("name"));
916 assert!(yaml_result.contains("42"));
917 }
918
919 #[test]
920 #[cfg(feature = "toml_support")]
921 fn test_toml_conversion() {
922 let toml_data = r#"
923 name = "test"
924 value = 42
925
926 [nested]
927 key = "hello"
928 "#;
929
930 let map = FormatConverter::toml_to_map(toml_data).expect("operation should succeed");
931 assert!(map.contains_key("name"));
932 assert!(map.contains_key("value"));
933
934 let toml_result = FormatConverter::map_to_toml(&map).expect("operation should succeed");
935 assert!(toml_result.contains("name"));
936 assert!(toml_result.contains("42"));
937 }
938
939 #[test]
940 #[cfg(feature = "xml")]
941 fn test_xml_conversion() {
942 let xml_data = r#"<?xml version="1.0" encoding="UTF-8"?>
943 <root>
944 <name>test</name>
945 <value>42</value>
946 </root>"#;
947
948 let map = FormatConverter::xml_to_simple_map(xml_data).expect("operation should succeed");
949 assert!(map.contains_key("name"));
950 assert!(map.contains_key("value"));
951 assert_eq!(map["name"], "test");
952 assert_eq!(map["value"], "42");
953
954 let xml_result =
955 FormatConverter::simple_map_to_xml(&map, "root").expect("operation should succeed");
956 assert!(xml_result.contains("<name>test</name>"));
957 assert!(xml_result.contains("<value>42</value>"));
958 }
959}