toolbox_rs/
io.rs

1use std::{
2    fs::File,
3    io::{self, BufRead, BufReader},
4    path::Path,
5};
6
7use bincode::{config, decode_from_std_read};
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 mut reader = BufReader::new(File::open(filename).unwrap());
24    let config = config::standard();
25
26    let input_edges: Vec<InputEdge<usize>> = decode_from_std_read(&mut reader, config).unwrap();
27
28    input_edges
29        .iter()
30        .map(|edge| TrivialEdge {
31            source: edge.source,
32            target: edge.target,
33        })
34        .collect_vec()
35}
36
37pub fn read_vec_from_file<T: bincode::Decode<()>>(filename: &str) -> Vec<T> {
38    let mut reader = BufReader::new(File::open(filename).unwrap());
39    let config = config::standard();
40    decode_from_std_read(&mut reader, config).unwrap()
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
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(bincode::Encode)]
78        struct TestEdge {
79            source: usize,
80            target: usize,
81            weight: usize,
82        }
83
84        let input_edges = vec![
85            TestEdge {
86                source: 1,
87                target: 2,
88                weight: 10,
89            },
90            TestEdge {
91                source: 2,
92                target: 3,
93                weight: 20,
94            },
95        ];
96
97        // Serialize the input edges to a temporary file
98        let mut file = NamedTempFile::new().unwrap();
99        let config = config::standard();
100        bincode::encode_into_std_write(&input_edges, &mut file, config).unwrap();
101
102        // Read the graph into trivial edges
103        let trivial_edges = read_graph_into_trivial_edges(file.path().to_str().unwrap());
104
105        // Verify the output
106        assert_eq!(trivial_edges.len(), 2);
107        assert_eq!(trivial_edges[0].source, 1);
108        assert_eq!(trivial_edges[0].target, 2);
109        assert_eq!(trivial_edges[1].source, 2);
110        assert_eq!(trivial_edges[1].target, 3);
111    }
112
113    // Test `read_graph_into_trivial_edges` with a non-existent file
114    #[test]
115    #[should_panic]
116    fn test_read_graph_into_trivial_edges_nonexistent_file() {
117        read_graph_into_trivial_edges("nonexistent_file.bin");
118    }
119
120    // Test `read_vec_from_file` function
121    #[test]
122    fn test_read_vec_from_file() {
123        // Define test data
124        let test_data = vec![1, 2, 3, 4, 5];
125
126        // Serialize the test data to a temporary file
127        let mut file = NamedTempFile::new().unwrap();
128        let config = config::standard();
129        bincode::encode_into_std_write(&test_data, &mut file, config).unwrap();
130
131        // Read the vector from the file
132        let result: Vec<i32> = read_vec_from_file(file.path().to_str().unwrap());
133
134        // Verify the output
135        assert_eq!(result, test_data);
136    }
137
138    // Test `read_vec_from_file` with a custom struct
139    #[test]
140    fn test_read_vec_from_file_with_custom_struct() {
141        // Define a custom struct for testing
142        #[derive(Debug, PartialEq, bincode::Encode, bincode::Decode)]
143        struct TestStruct {
144            id: u64,
145            name: String,
146        }
147
148        let test_data = vec![
149            TestStruct {
150                id: 1,
151                name: "Alice".to_string(),
152            },
153            TestStruct {
154                id: 2,
155                name: "Bob".to_string(),
156            },
157        ];
158
159        // Serialize the test data to a temporary file
160        let mut file = NamedTempFile::new().unwrap();
161        let config = config::standard();
162        bincode::encode_into_std_write(&test_data, &mut file, config).unwrap();
163
164        // Read the vector from the file
165        let result: Vec<TestStruct> = read_vec_from_file(file.path().to_str().unwrap());
166
167        // Verify the output
168        assert_eq!(result, test_data);
169    }
170
171    // Test `read_vec_from_file` with a non-existent file
172    #[test]
173    #[should_panic]
174    fn test_read_vec_from_file_nonexistent_file() {
175        read_vec_from_file::<i32>("nonexistent_file.bin");
176    }
177
178    // Test `read_vec_from_file` with invalid data
179    #[test]
180    #[should_panic]
181    fn test_read_vec_from_file_invalid_data() {
182        // Create a temporary file with invalid binary data
183        let mut file = NamedTempFile::new().unwrap();
184        file.write_all(b"invalid binary data").unwrap();
185
186        // Attempt to read the invalid data
187        let _: Vec<i32> = read_vec_from_file(file.path().to_str().unwrap());
188    }
189}