use crate::prelude::*;
#[derive(Clone, Copy)]
pub struct ReaderInfo {
pub name: &'static str,
pub display: &'static str,
pub extension: &'static str,
pub aliases: &'static [&'static str],
}
impl ReaderInfo {
pub fn extension_without_dot(&self) -> &'static str {
self.extension.trim_start_matches('.')
}
pub fn is_alias(&self, name: &str) -> bool {
self.aliases.iter().any(|a| a.eq_ignore_ascii_case(name))
}
}
#[derive(Clone, Copy)]
struct ReaderEntry {
name: &'static str,
display: &'static str,
extension: &'static str,
names: &'static [&'static str],
function: fn(&str) -> Result<BseBasisMinimal, BseError>,
}
const READER_ENTRIES: &[ReaderEntry] = &[
ReaderEntry {
name: "nwchem",
display: "NWChem",
extension: ".nw",
names: &["nwchem", "nw"],
function: readers::nwchem::read_nwchem,
},
ReaderEntry {
name: "gaussian94",
display: "Gaussian94",
extension: ".gbs",
names: &["gaussian94", "gaussian", "g94", "gbs", "gau"],
function: readers::g94::read_g94,
},
ReaderEntry {
name: "turbomole",
display: "Turbomole",
extension: ".tm",
names: &["turbomole", "tm"],
function: readers::turbomole::read_turbomole,
},
ReaderEntry {
name: "dalton",
display: "Dalton",
extension: ".mol",
names: &["dalton", "mol"],
function: readers::dalton::read_dalton,
},
ReaderEntry {
name: "molcas",
display: "Molcas",
extension: ".molcas",
names: &["molcas"],
function: readers::molcas::read_molcas,
},
ReaderEntry {
name: "molcas_library",
display: "Molcas basis library",
extension: ".molcas",
names: &["molcas_library"],
function: readers::molcas::read_molcas,
},
ReaderEntry {
name: "molpro",
display: "Molpro",
extension: ".mpro",
names: &["molpro", "mpro"],
function: readers::molpro::read_molpro,
},
ReaderEntry {
name: "libmol",
display: "Molpro system library",
extension: ".libmol",
names: &["libmol"],
function: readers::libmol::read_libmol,
},
ReaderEntry {
name: "cfour",
display: "CFOUR",
extension: ".c4bas",
names: &["cfour"],
function: readers::genbas::read_genbas,
},
ReaderEntry {
name: "genbas",
display: "Genbas",
extension: ".genbas",
names: &["genbas"],
function: readers::genbas::read_genbas,
},
ReaderEntry {
name: "gbasis",
display: "GBasis",
extension: ".gbasis",
names: &["gbasis"],
function: readers::gbasis::read_gbasis,
},
ReaderEntry {
name: "demon2k",
display: "deMon2k",
extension: ".d2k",
names: &["demon2k", "d2k"],
function: readers::demon2k::read_demon2k,
},
ReaderEntry {
name: "ricdlib",
display: "MolCAS RICDlib",
extension: ".ricdlib",
names: &["ricdlib", "ricd"],
function: readers::ricdlib::read_ricdlib,
},
ReaderEntry {
name: "gamess_us",
display: "GAMESS US",
extension: ".bas",
names: &["gamess_us"],
function: readers::gamess_us::read_gamess_us,
},
ReaderEntry {
name: "cp2k",
display: "CP2K",
extension: ".cp2k",
names: &["cp2k"],
function: readers::cp2k::read_cp2k,
},
ReaderEntry {
name: "crystal",
display: "Crystal",
extension: ".crystal",
names: &["crystal"],
function: readers::crystal::read_crystal,
},
ReaderEntry {
name: "veloxchem",
display: "VeloxChem",
extension: ".vlx",
names: &["veloxchem", "vlx"],
function: readers::veloxchem::read_veloxchem,
},
ReaderEntry {
name: "json",
display: "JSON",
extension: ".json",
names: &["json", "bsejson"],
function: readers::bsejson::read_bsejson,
},
];
lazy_static::lazy_static! {
static ref READER_MAP: HashMap<String, usize> = {
let mut map = HashMap::new();
for (idx, entry) in READER_ENTRIES.iter().enumerate() {
for name in entry.names {
map.insert(name.to_lowercase(), idx);
}
}
map
};
static ref READER_EXTENSION_MAP: HashMap<String, &'static str> = {
let mut map = HashMap::new();
for entry in READER_ENTRIES.iter() {
let ext = entry.extension.trim_start_matches('.').to_lowercase();
map.insert(ext, entry.name);
}
map
};
}
fn get_reader_entry(fmt: &str) -> Option<&ReaderEntry> {
let fmt_lower = fmt.to_lowercase();
READER_MAP.get(&fmt_lower).map(|idx| &READER_ENTRIES[*idx])
}
pub fn get_reader_format_by_extension(ext: &str) -> Option<&'static str> {
let ext_lower = ext.to_lowercase();
READER_EXTENSION_MAP.get(&ext_lower).copied()
}
pub fn get_reader_info(fmt: &str) -> Option<ReaderInfo> {
get_reader_entry(fmt).map(|e| ReaderInfo {
name: e.name,
display: e.display,
extension: e.extension,
aliases: e.names,
})
}
pub fn get_reader_formats() -> HashMap<String, String> {
READER_ENTRIES.iter().map(|entry| (entry.name.to_string(), entry.display.to_string())).collect()
}
pub fn get_reader_formats_with_aliases() -> HashMap<String, (String, String, Vec<String>)> {
READER_ENTRIES
.iter()
.map(|entry| {
let aliases: Vec<String> =
entry.names.iter().filter(|n| **n != entry.name).map(|n| n.to_string()).collect();
(entry.name.to_string(), (entry.display.to_string(), entry.extension.to_string(), aliases))
})
.collect()
}
pub fn read_formatted_basis_str(basis_str: &str, fmt: &str) -> BseBasisMinimal {
read_formatted_basis_str_f(basis_str, fmt).unwrap()
}
pub fn read_formatted_basis_str_f(basis_str: &str, fmt: &str) -> Result<BseBasisMinimal, BseError> {
let entry = get_reader_entry(fmt).ok_or_else(|| BseError::ValueError(format!("Unknown reader format: {}", fmt)))?;
(entry.function)(basis_str)
}