use super::*;
use super::parser::*;
use std::str::FromStr;
#[derive(Debug, Clone, PartialEq)]
enum DataType {
Integer,
Real,
Logical,
Character1,
Character2,
}
impl DataType {
fn width(&self) -> usize {
use self::DataType::*;
match self {
Integer => 12,
Real => 16,
Logical => 1,
Character1 => 12,
Character2 => 8,
}
}
}
impl FromStr for DataType {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
let dt = match s.trim() {
"I" => DataType::Integer,
"R" => DataType::Real,
"C" => DataType::Character1,
"H" => DataType::Character2,
_ => {
bail!("unkown data type: {}", s.trim());
}
};
Ok(dt)
}
}
#[test]
fn test_fchk_data_type() {
let s = " I";
let dt = s.parse().expect("fchk data type: I");
assert_eq!(DataType::Integer, dt);
assert_eq!(dt.width(), 12);
let s = " R ";
let dt = s.parse().expect("fchk data type: R");
assert_eq!(DataType::Real, dt);
assert_eq!(dt.width(), 16);
}
#[derive(Debug, Clone)]
struct Section<'a> {
label: &'a str,
data_type: DataType,
is_array: bool,
value: &'a str,
data_array: Option<Vec<&'a str>>,
}
fn read_section_header(s: &str) -> IResult<&str, Section> {
let take40 = take_s(40);
let take7 = take_s(7);
let take2 = take_s(2);
do_parse!(
s,
label : take40 >> data_type : take7 >> array : take2 >> value : read_line >> ({
Section {
value: value.trim(),
label: label.trim(),
data_type: data_type.parse().expect("dt"),
is_array: array.trim() == "N=",
data_array: None,
}
})
)
}
#[test]
fn test_fchk_section_header() {
let line = "Nuclear charges R N= 11 \n";
let (_, s) = read_section_header(line).expect("fchk section header");
assert_eq!("Nuclear charges", s.label);
assert_eq!(DataType::Real, s.data_type);
assert_eq!("11", s.value);
assert!(s.is_array);
let line = "Number of alpha electrons I 225\n";
let (_, s) = read_section_header(line).expect("fchk section header");
assert!(!s.is_array);
let line = "Total Energy R -1.177266205968928E+02\n";
let (_, s) = read_section_header(line).expect("fchk section header");
assert!(!s.is_array);
}