1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use flate2::Compression;

use super::*;
use crate::structs::PDB;
use crate::StrictnessLevel;
use crate::{check_extension, error::*};

/// Save the given PDB struct to the given file, validating it beforehand.
/// If validation gives rise to problems, use the `save_raw` function. The correct file
/// type (pdb or mmCIF/PDBx) will be determined based on the given file extension.
/// # Errors
/// Fails if the validation fails with the given `level`.
pub fn save(
    pdb: &PDB,
    filename: impl AsRef<str>,
    level: StrictnessLevel,
) -> Result<(), Vec<PDBError>> {
    if check_extension(&filename, "pdb") {
        save_pdb(pdb, filename, level)
    } else if check_extension(&filename, "cif") {
        save_mmcif(pdb, filename, level)
    } else {
        Err(vec![PDBError::new(
            ErrorLevel::BreakingError,
            "Incorrect extension",
            "Could not determine the type of the given file, make it .pdb or .cif",
            Context::show(filename.as_ref()),
        )])
    }
}

/// Save the given PDB struct to the given file and compressing to gz, validating it beforehand.
/// If validation gives rise to problems, use the `save_raw` function. The correct file
/// type (pdb or mmCIF/PDBx) will be determined based on the given file extension.
/// # Errors
/// Fails if the validation fails with the given `level`.
pub fn save_gz(
    pdb: &PDB,
    filename: impl AsRef<str>,
    level: StrictnessLevel,
    compression_level: Option<Compression>,
) -> Result<(), Vec<PDBError>> {
    let filename = filename.as_ref();
    if check_extension(filename, "gz") {
        // safety check to prevent out of bounds indexing
        if filename.len() < 3 {
            return Err(vec![PDBError::new(
                ErrorLevel::BreakingError,
                "Filename too short",
                "Could not determine the type of the given file, make it .pdb.gz or .cif.gz",
                Context::show(filename),
            )]);
        }

        if check_extension(&filename[..filename.len() - 3], "pdb") {
            save_pdb_gz(pdb, filename, level, compression_level)
        } else if check_extension(&filename[..filename.len() - 3], "cif") {
            save_mmcif_gz(pdb, filename, level, compression_level)
        } else {
            Err(vec![PDBError::new(
                ErrorLevel::BreakingError,
                "Incorrect extension",
                "Could not determine the type of the given file, make it .pdb.gz or .cif.gz",
                Context::show(filename),
            )])
        }
    } else {
        Err(vec![PDBError::new(
            ErrorLevel::BreakingError,
            "Incorrect extension",
            "Could not determine the type of the given file, make it .pdb.gz or .cif.gz",
            Context::show(filename),
        )])
    }
}