haddock_restraints/core/
input.rs

1use crate::Interactor;
2use std::fs::File;
3use std::io::BufReader;
4
5/// Reads and processes a JSON file containing Interactor data.
6///
7/// This function reads a JSON file, deserializes it into a vector of Interactors,
8/// and updates the file paths for any structures referenced in the Interactors.
9///
10/// # Arguments
11///
12/// * `file_path` - A string slice that holds the path to the JSON file.
13///
14/// # Returns
15///
16/// * `Ok(Vec<Interactor>)` - A vector of Interactor objects if successful.
17/// * `Err(Box<dyn std::error::Error>)` - An error if file reading or JSON parsing fails.
18///
19pub fn read_json_file(file_path: &str) -> Result<Vec<Interactor>, Box<dyn std::error::Error>> {
20    // Open the file and create a buffered reader
21    let file = File::open(file_path)?;
22    let reader = BufReader::new(file);
23
24    // Deserialize the JSON into a vector of Interactors
25    let mut data: Vec<Interactor> = serde_json::from_reader(reader)?;
26
27    // Get the directory of the input file
28    let wd = std::path::Path::new(file_path).parent().unwrap();
29
30    // Process each Interactor
31    data.iter_mut().for_each(|interactor| {
32        // If the `structure` field was found, load the structure into the
33        //  interactor as a PDB object
34        if !interactor.structure().is_empty() {
35            // Construct the full path to the structure file
36            let pdb_path = wd.join(interactor.structure());
37
38            // Update the structure path to the full path
39            match interactor.load_structure(pdb_path.to_str().unwrap()) {
40                Ok(_) => {}
41                Err(e) => {
42                    eprintln!("Error opening {:?}", pdb_path);
43                    eprintln!("{:?}", e);
44                    std::process::exit(1)
45                }
46            }
47        }
48    });
49
50    Ok(data)
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56    use std::io::Write;
57    use tempfile::NamedTempFile;
58
59    #[test]
60    fn test_read_json_file_success() {
61        // Create a temporary JSON file
62        let json_content = r#"
63        [
64            {
65                "id": 1,
66                "target": [1, 2, 3],
67                "structure": "test.pdb",
68                "chain": "A",
69                "active": [],
70                "passive": []
71            }
72        ]
73        "#;
74
75        let mut json_file = NamedTempFile::new().unwrap();
76        write!(json_file, "{}", json_content).unwrap();
77
78        // Create a mock PDB file in the same directory
79        let pdb_path = json_file.path().parent().unwrap().join("test.pdb");
80        let mut pdb_file = File::create(&pdb_path).unwrap();
81        write!(
82            pdb_file,
83            "ATOM      1  N   MET A   1      11.111  22.222  33.333  1.00  0.00           N"
84        )
85        .unwrap();
86
87        // Test the function
88        let result = read_json_file(json_file.path().to_str().unwrap());
89        println!("{:?}", result);
90        assert!(result.is_ok());
91
92        let interactors = result.unwrap();
93        assert_eq!(interactors.len(), 1);
94        assert_eq!(interactors[0].structure(), pdb_path.to_string_lossy());
95        assert!(interactors[0].pdb().is_some());
96    }
97
98    #[test]
99    fn test_read_json_file_invalid_json() {
100        // Create invalid JSON file
101        let json_content = "invalid json";
102        let mut json_file = NamedTempFile::new().unwrap();
103        write!(json_file, "{}", json_content).unwrap();
104
105        // Test the function
106        let result = read_json_file(json_file.path().to_str().unwrap());
107        assert!(result.is_err());
108    }
109
110    #[test]
111    fn test_read_json_file_no_structure() {
112        // Create JSON with no structure field
113        let json_content = r#"
114        [
115            {
116                "id": 1,
117                "target": [1, 2, 3],
118                "chain": "A",
119                "active": [],
120                "passive": []
121            }
122        ]
123        "#;
124
125        let mut json_file = NamedTempFile::new().unwrap();
126        write!(json_file, "{}", json_content).unwrap();
127
128        // Test the function
129        let result = read_json_file(json_file.path().to_str().unwrap());
130        assert!(result.is_ok());
131
132        let interactors = result.unwrap();
133        assert_eq!(interactors.len(), 1);
134        assert!(interactors[0].structure().is_empty());
135        assert!(interactors[0].pdb().is_none());
136    }
137}