toolbox_rs/
io.rs

1use std::{
2    fs::File,
3    io::{self, BufRead, BufReader},
4    path::Path,
5};
6
7use bincode::deserialize_from;
8use itertools::Itertools;
9
10use crate::edge::{InputEdge, TrivialEdge};
11
12// The output is wrapped in a Result to allow matching on errors
13// Returns an Iterator to the Reader of the lines of the file.
14pub fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
15where
16    P: AsRef<Path>,
17{
18    let file = File::open(filename)?;
19    Ok(io::BufReader::new(file).lines())
20}
21
22pub fn read_graph_into_trivial_edges(filename: &str) -> Vec<TrivialEdge> {
23    let reader = BufReader::new(File::open(filename).unwrap());
24
25    let input_edges: Vec<InputEdge<usize>> = deserialize_from(reader).unwrap();
26    let edges = input_edges
27        .iter()
28        .map(|edge| TrivialEdge {
29            source: edge.source,
30            target: edge.target,
31        })
32        .collect_vec();
33
34    edges
35}
36
37pub fn read_vec_from_file<T: serde::de::DeserializeOwned>(filename: &str) -> Vec<T> {
38    let reader = BufReader::new(File::open(filename).unwrap());
39    deserialize_from(reader).unwrap()
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45    use serde::{Deserialize, Serialize};
46    use std::io::Write;
47    use tempfile::NamedTempFile;
48
49    // Test `read_lines` function
50    #[test]
51    fn test_read_lines() {
52        // Create a temporary file with some lines
53        let mut file = NamedTempFile::new().unwrap();
54        writeln!(file, "line1").unwrap();
55        writeln!(file, "line2").unwrap();
56        writeln!(file, "line3").unwrap();
57
58        // Read lines from the file
59        let lines = read_lines(file.path()).unwrap();
60        let lines: Vec<String> = lines.map(|line| line.unwrap()).collect();
61
62        // Verify the lines are read correctly
63        assert_eq!(lines, vec!["line1", "line2", "line3"]);
64    }
65
66    // Test `read_lines` with a non-existent file
67    #[test]
68    fn test_read_lines_nonexistent_file() {
69        let result = read_lines("nonexistent_file.txt");
70        assert!(result.is_err());
71    }
72
73    // Test `read_graph_into_trivial_edges` function
74    #[test]
75    fn test_read_graph_into_trivial_edges() {
76        // Define test input edges
77        #[derive(Serialize)]
78        struct TestEdge {
79            source: usize,
80            target: usize,
81            weight: f64,
82        }
83
84        let input_edges = vec![
85            TestEdge {
86                source: 1,
87                target: 2,
88                weight: 1.0,
89            },
90            TestEdge {
91                source: 2,
92                target: 3,
93                weight: 2.0,
94            },
95        ];
96
97        // Serialize the input edges to a temporary file
98        let mut file = NamedTempFile::new().unwrap();
99        bincode::serialize_into(&mut file, &input_edges).unwrap();
100
101        // Read the graph into trivial edges
102        let trivial_edges = read_graph_into_trivial_edges(file.path().to_str().unwrap());
103
104        // Verify the output
105        assert_eq!(trivial_edges.len(), 2);
106        assert_eq!(trivial_edges[0].source, 1);
107        assert_eq!(trivial_edges[0].target, 2);
108        assert_eq!(trivial_edges[1].source, 2);
109        assert_eq!(trivial_edges[1].target, 3);
110    }
111
112    // Test `read_graph_into_trivial_edges` with a non-existent file
113    #[test]
114    #[should_panic]
115    fn test_read_graph_into_trivial_edges_nonexistent_file() {
116        read_graph_into_trivial_edges("nonexistent_file.bin");
117    }
118
119    // Test `read_vec_from_file` function
120    #[test]
121    fn test_read_vec_from_file() {
122        // Define test data
123        let test_data = vec![1, 2, 3, 4, 5];
124
125        // Serialize the test data to a temporary file
126        let mut file = NamedTempFile::new().unwrap();
127        bincode::serialize_into(&mut file, &test_data).unwrap();
128
129        // Read the vector from the file
130        let result: Vec<i32> = read_vec_from_file(file.path().to_str().unwrap());
131
132        // Verify the output
133        assert_eq!(result, test_data);
134    }
135
136    // Test `read_vec_from_file` with a custom struct
137    #[test]
138    fn test_read_vec_from_file_with_custom_struct() {
139        // Define a custom struct for testing
140        #[derive(Serialize, Deserialize, Debug, PartialEq)]
141        struct TestStruct {
142            id: u64,
143            name: String,
144        }
145
146        let test_data = vec![
147            TestStruct {
148                id: 1,
149                name: "Alice".to_string(),
150            },
151            TestStruct {
152                id: 2,
153                name: "Bob".to_string(),
154            },
155        ];
156
157        // Serialize the test data to a temporary file
158        let mut file = NamedTempFile::new().unwrap();
159        bincode::serialize_into(&mut file, &test_data).unwrap();
160
161        // Read the vector from the file
162        let result: Vec<TestStruct> = read_vec_from_file(file.path().to_str().unwrap());
163
164        // Verify the output
165        assert_eq!(result, test_data);
166    }
167
168    // Test `read_vec_from_file` with a non-existent file
169    #[test]
170    #[should_panic]
171    fn test_read_vec_from_file_nonexistent_file() {
172        read_vec_from_file::<i32>("nonexistent_file.bin");
173    }
174
175    // Test `read_vec_from_file` with invalid data
176    #[test]
177    #[should_panic]
178    fn test_read_vec_from_file_invalid_data() {
179        // Create a temporary file with invalid binary data
180        let mut file = NamedTempFile::new().unwrap();
181        file.write_all(b"invalid binary data").unwrap();
182
183        // Attempt to read the invalid data
184        let _: Vec<i32> = read_vec_from_file(file.path().to_str().unwrap());
185    }
186}