mod parser

module parser

Functions

fn parse_frame_header<'a>(lines: &mut impl Iterator<Item = &'a str>) -> Result<FrameHeader, ParseError>

Parses the 9-line header of a .con file frame from an iterator.

This function consumes the next 9 lines from the given line iterator to construct a FrameHeader. The iterator is advanced by 9 lines on success.

Arguments

  • lines - A mutable reference to an iterator that yields string slices.

Errors

  • ParseError::IncompleteHeader if the iterator has fewer than 9 lines remaining.

  • Propagates any errors from parse_line_of_n if the numeric data within the header is malformed.

Panics

This function will panic if the intermediate vectors for box dimensions or angles, after being successfully parsed, cannot be converted into fixed-size arrays. This should not happen if parse_line_of_n is used correctly with n=3.

fn parse_line_of_n<T: std::str::FromStr>(line: &str, n: usize) -> Result<Vec<T>, ParseError>
where
    ParseError: From<std::str::FromStr::Err>

Parses a line of whitespace-separated values into a vector of a specific type.

This generic helper function takes a string slice, splits it by whitespace, and attempts to parse each substring into the target type T. The type T must implement std::str::FromStr.

Arguments

  • line - A string slice representing a single line of data.

  • n - The exact number of values expected on the line.

Errors

  • ParseError::InvalidVectorLength if the number of parsed values is not equal to n.

  • Propagates any error from the parse() method of the target type T.

Example

use readcon_core::parser::parse_line_of_n;
let line = "10.5 20.0 30.5";
let values: Vec<f64> = parse_line_of_n(line, 3).unwrap();
assert_eq!(values, vec![10.5, 20.0, 30.5]);

let result = parse_line_of_n::<i32>(line, 2);
assert!(result.is_err());
fn parse_line_of_n_f64(line: &str, n: usize) -> Result<Vec<f64>, ParseError>

Parses a line of whitespace-separated f64 values using fast-float2.

This is the hot-path parser for coordinate and velocity lines. It uses fast_float2::parse instead of str::parse::<f64>() for better throughput on the numeric-heavy atom data lines.

Arguments

  • line - A string slice representing a single line of data.

  • n - The exact number of f64 values expected on the line.

fn parse_single_frame<'a>(lines: &mut impl Iterator<Item = &'a str>) -> Result<ConFrame, ParseError>

Parses a complete frame from a .con file, including its header and atomic data.

This function first parses the complete frame header and then uses the information within it (specifically the number of atom types and atoms per type) to parse the subsequent atom coordinate blocks.

Arguments

  • lines - A mutable reference to an iterator that yields string slices for the frame.

Errors

  • ParseError::IncompleteFrame if the iterator ends before all expected atomic data has been read.

  • Propagates any errors from the underlying calls to parse_frame_header and parse_line_of_n.

Example

use readcon_core::parser::parse_single_frame;

let frame_text = r#"
PREBOX LINE 1
PREBOX LINE 2
10.0 10.0 10.0
90.0 90.0 90.0
POSTBOX LINE 1
POSTBOX LINE 2
2
1 1
12.011 1.008
C
Coordinates of Component 1
1.0 1.0 1.0 0.0 1
H
Coordinates of Component 2
2.0 2.0 2.0 0.0 2
"#;

let mut lines = frame_text.trim().lines();
let con_frame = parse_single_frame(&mut lines).unwrap();

assert_eq!(con_frame.header.natm_types, 2);
assert_eq!(con_frame.atom_data.len(), 2);
assert_eq!(&*con_frame.atom_data[0].symbol, "C");
assert_eq!(con_frame.atom_data[1].atom_id, 2);
fn parse_velocity_section<'a, I>(lines: &mut Peekable<I>, header: &FrameHeader, atom_data: &mut [AtomDatum]) -> Result<bool, ParseError>
where
    I: Iterator<Item = &'a str>

Attempts to parse an optional velocity section following coordinate blocks.

In .convel files, after all coordinate blocks there is a blank separator line followed by per-component velocity blocks with the same structure as coordinate blocks (symbol line, “Velocities of Component N” line, then atom lines with vx vy vz fixed atomID).

This function peeks at the next line. If it is blank (or contains only whitespace), it consumes the blank line and parses velocity data into the existing atom_data. If the next line is not blank (or is absent), no velocities are parsed.

Returns Ok(true) if velocities were found and parsed, Ok(false) otherwise.