mod parser

module parser

Functions

fn parse_declared_sections<'a, I>(lines: &mut Peekable<I>, header: &mut FrameHeader, atom_data: &mut [AtomDatum]) -> Result<(), ParseError>
where
    I: Iterator<Item = &'a str>

Parses declared sections from a frame’s header metadata.

If header.sections is non-empty (v2 file with "sections" key in JSON), parses each declared section in order. Otherwise falls back to legacy blank-separator velocity detection.

fn parse_force_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 a force section following coordinate (and optional velocity) blocks.

Force sections mirror velocity sections: a blank separator line followed by per-component force blocks (symbol line, “Forces of Component N” line, then atom lines with fx fy fz fixed_flag atom_id).

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

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_line_of_range_f64(line: &str, min: usize, max: usize, defaults: &[f64]) -> Result<Vec<f64>, ParseError>

Parses a line of whitespace-separated f64 values, accepting between min and max values (inclusive). Returns a vector of exactly max elements, padding with values from defaults when fewer than max are present.

Used for atom lines where column 5 (atom_index) is optional.

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#"
Generated by test
{"con_spec_version":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.