Skip to content

Commit

Permalink
feat(read-opts): setup public functions with ReadOptions as arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
y1zhou committed May 17, 2024
1 parent ceb212e commit 97580c6
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 27 deletions.
18 changes: 14 additions & 4 deletions src/read/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ use std::io::{BufRead, Read, Seek};

use self::mmcif::open_mmcif_with_options;
use self::pdb::open_pdb_with_options;

use super::*;
use crate::error::*;
use crate::structs::PDB;
use crate::StrictnessLevel;

#[cfg(feature = "compression")]
use super::mmcif::open_mmcif_bufread;
use self::mmcif::open_mmcif_bufread_with_options;
#[cfg(feature = "compression")]
use flate2::read::GzDecoder;
#[cfg(feature = "compression")]
Expand Down Expand Up @@ -66,6 +65,17 @@ pub(in crate::read) fn open_with_options(
/// storing the data.
#[cfg(feature = "compression")]
pub fn open_gz(filename: impl AsRef<str>, level: StrictnessLevel) -> ReadResult {
open_gz_with_options(filename, ReadOptions::default().set_level(level))
}

/// Opens a compressed atomic data file with [`ReadOptions`].
///
/// # Related
/// See [`open_gz`] for a version of this function with sane defaults.
#[cfg(feature = "compression")]
pub fn open_gz_with_options(filename: impl AsRef<str>, options: &ReadOptions) -> ReadResult {
use self::pdb::open_pdb_raw_with_options;

let filename = filename.as_ref();

if check_extension(filename, "gz") {
Expand All @@ -84,9 +94,9 @@ pub fn open_gz(filename: impl AsRef<str>, level: StrictnessLevel) -> ReadResult
let reader = std::io::BufReader::new(decompressor);

if check_extension(&filename[..filename.len() - 3], "pdb") {
open_pdb_raw(reader, Context::show(filename), level)
open_pdb_raw_with_options(reader, Context::show(filename), options)
} else if check_extension(&filename[..filename.len() - 3], "cif") {
open_mmcif_bufread(reader, level)
open_mmcif_bufread_with_options(reader, options)
} else {
Err(vec![PDBError::new(
ErrorLevel::BreakingError,
Expand Down
62 changes: 51 additions & 11 deletions src/read/mmcif/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ use std::io::prelude::*;
pub fn open_mmcif(
filename: impl AsRef<str>,
level: StrictnessLevel,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
open_mmcif_with_options(filename, ReadOptions::default().set_level(level))
}

/// Parse the given mmCIF file into a PDB struct with [`ReadOptions`].
///
/// # Related
/// See [`open_mmcif`] for a version of this function with sane defaults.
pub fn open_mmcif_with_options(
filename: impl AsRef<str>,
options: &ReadOptions,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
let filename = filename.as_ref();
let mut file = if let Ok(f) = File::open(filename) {
Expand All @@ -33,22 +44,26 @@ pub fn open_mmcif(
Context::show(filename),
)]);
}
open_mmcif_raw(&contents, level)
}

pub fn open_mmcif_with_options(
filename: impl AsRef<str>,
options: &ReadOptions,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
todo!()
open_mmcif_raw_with_options(&contents, options)
}

/// Open's mmCIF file from a BufRead. This allows opening mmCIF files directly from memory.
///
/// This is particularly useful if you want to open a compressed file, as you can use the BufReader
pub fn open_mmcif_bufread(
mut bufreader: impl BufRead,
bufreader: impl BufRead,
level: StrictnessLevel,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
open_mmcif_bufread_with_options(bufreader, ReadOptions::default().set_level(level))
}

/// Opens mmCIF file from a BufRead with [`ReadOptions`].
///
/// # Related
/// See [`open_mmcif_bufread`] for a version of this function with sane defaults.
pub fn open_mmcif_bufread_with_options(
mut bufreader: impl BufRead,
options: &ReadOptions,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
let mut contents = String::new();
if let Err(e) = bufreader.read_to_string(&mut contents) {
Expand All @@ -59,7 +74,7 @@ pub fn open_mmcif_bufread(
Context::none(),
)]);
}
open_mmcif_raw(&contents, level)
open_mmcif_raw_with_options(&contents, options)
}

/// Parse the given mmCIF `&str` into a PDB struct. This allows opening mmCIF files directly from memory.
Expand All @@ -79,10 +94,35 @@ pub fn open_mmcif_raw(
}
}

/// Parse the given mmCIF `&str` into a PDB struct with [`ReadOptions`].
///
/// # Related
/// See [`open_mmcif_raw`] for a version of this function with sane defaults.
pub fn open_mmcif_raw_with_options(
input: &str,
options: &ReadOptions,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
match super::lexer::lex_cif(input) {
Ok(data_block) => parse_mmcif_with_options(&data_block, options),
Err(e) => Err(vec![e]),
}
}

/// Parse a CIF intermediate structure into a PDB
fn parse_mmcif(
input: &DataBlock,
level: StrictnessLevel,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
parse_mmcif_with_options(input, ReadOptions::default().set_level(level))
}

/// Parse a CIF intermediate structure into a PDB with [`ReadOptions`].
///
/// # Related
/// See [`parse_mmcif`] for a version of this function with sane defaults.
fn parse_mmcif_with_options(
input: &DataBlock,
options: &ReadOptions,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
let mut pdb = PDB::default();
let mut errors: Vec<PDBError> = Vec::new();
Expand Down Expand Up @@ -238,7 +278,7 @@ fn parse_mmcif(

reshuffle_conformers(&mut pdb);
errors.extend(validate(&pdb));
if errors.iter().any(|e| e.fails(level)) {
if errors.iter().any(|e| e.fails(options.level)) {
Err(errors)
} else {
Ok((pdb, errors))
Expand Down
5 changes: 3 additions & 2 deletions src/read/pdb/lexer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::lexitem::*;
use crate::error::*;
use crate::reference_tables;
use crate::ReadOptions;
use crate::StrictnessLevel;

use std::cmp;
Expand All @@ -12,12 +13,12 @@ use std::str::FromStr;
pub fn lex_line(
line: &str,
linenumber: usize,
level: StrictnessLevel,
options: &ReadOptions,
) -> Result<(LexItem, Vec<PDBError>), PDBError> {
if line.len() > 6 {
match &line[..6] {
"HEADER" => lex_header(linenumber, line),
"REMARK" => lex_remark(linenumber, line, level),
"REMARK" => lex_remark(linenumber, line, options.level),
"ATOM " => lex_atom(linenumber, line, false),
"ANISOU" => Ok(lex_anisou(linenumber, line)),
"HETATM" => lex_atom(linenumber, line, true),
Expand Down
39 changes: 29 additions & 10 deletions src/read/pdb/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ use std::io::{BufRead, BufReader};
pub fn open_pdb(
filename: impl AsRef<str>,
level: StrictnessLevel,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
open_pdb_with_options(filename, ReadOptions::default().set_level(level))
}

/// Parse the given file into a PDB struct with [`ReadOptions`].
///
/// # Related
/// See [`open_pdb`] for a version of this function with sane defaults.
pub fn open_pdb_with_options(
filename: impl AsRef<str>,
options: &ReadOptions,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
let filename = filename.as_ref();
// Open a file a use a buffered reader to minimise memory use while immediately lexing the line followed by adding it to the current PDB
Expand All @@ -31,14 +42,7 @@ pub fn open_pdb(
return Err(vec![PDBError::new(ErrorLevel::BreakingError, "Could not open file", "Could not open the specified file, make sure the path is correct, you have permission, and that it is not open in another program.", Context::show(filename))]);
};
let reader = BufReader::new(file);
open_pdb_raw(reader, Context::show(filename), level)
}

pub fn open_pdb_with_options(
filename: impl AsRef<str>,
options: &ReadOptions,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>> {
todo!()
open_pdb_raw_with_options(reader, Context::show(filename), options)
}

/// Parse the input stream into a PDB struct. To allow for direct streaming from sources, like from RCSB.org.
Expand All @@ -58,6 +62,21 @@ pub fn open_pdb_raw<T>(
context: Context,
level: StrictnessLevel,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>>
where
T: std::io::Read,
{
open_pdb_raw_with_options(input, context, ReadOptions::default().set_level(level))
}

/// Parse the input stream into a PDB struct with [`ReadOptions`].
///
/// # Related
/// See [`open_pdb_raw`] for a version of this function with sane defaults.
pub fn open_pdb_raw_with_options<T>(
input: std::io::BufReader<T>,
context: Context,
options: &ReadOptions,
) -> Result<(PDB, Vec<PDBError>), Vec<PDBError>>
where
T: std::io::Read,
{
Expand Down Expand Up @@ -96,7 +115,7 @@ where
context,
)]);
};
let line_result = lex_line(&line, linenumber, level);
let line_result = lex_line(&line, linenumber, options);
let line_context = Context::FullLine {
linenumber,
line: line.clone(),
Expand Down Expand Up @@ -489,7 +508,7 @@ where
errors.extend(add_bonds(&mut pdb, bonds));
errors.extend(validate(&pdb));

if errors.iter().any(|e| e.fails(level)) {
if errors.iter().any(|e| e.fails(options.level)) {
Err(errors)
} else {
Ok((pdb, errors))
Expand Down

0 comments on commit 97580c6

Please sign in to comment.