use super::{comments, estimate_float_count};
use crate::parser::{is_step_space, parse_step_numeric, skip_step_trivia};
#[inline(always)]
pub(super) fn read_coordinate_list<T: fast_float2::FastFloat, const COMMENTS: bool>(
bytes: &[u8],
) -> Option<Vec<T>> {
let mut result = Vec::with_capacity(estimate_float_count(bytes));
let (mut pos, len) = (0, bytes.len());
let (mut after_item, mut after_comma, mut depth) = (false, false, 0usize);
loop {
if COMMENTS {
pos = skip_step_trivia(bytes, pos)?;
} else {
while pos < len && is_step_space(bytes[pos]) {
pos += 1;
}
}
let Some(&b) = bytes.get(pos) else { break };
match b {
b',' if after_item => {
(after_item, after_comma) = (false, true);
pos += 1;
}
b')' if !after_comma && depth > 0 => {
after_item = true;
depth -= 1;
pos += 1;
}
b'(' if !after_item => {
after_comma = false;
depth += 1;
pos += 1;
}
_ if !after_item => {
let (value, consumed) = parse_step_numeric::<T>(&bytes[pos..])?;
result.push(value);
(after_item, after_comma) = (true, false);
pos += consumed;
}
_ => return None,
}
}
(!after_comma && depth == 0).then_some(result)
}
#[inline]
pub(super) fn try_parse_coordinates_direct(bytes: &[u8]) -> Option<Vec<f32>> {
if comments::may_contain_step_comment(bytes) {
return comments::parse_coordinates(bytes);
}
read_coordinate_list::<f32, false>(bytes)
}
#[inline]
pub fn parse_coordinates_direct(bytes: &[u8]) -> Vec<f32> {
try_parse_coordinates_direct(bytes).unwrap_or_default()
}
#[inline]
pub fn parse_coordinates_direct_f64(bytes: &[u8]) -> Vec<f64> {
try_parse_coordinates_direct_f64(bytes).unwrap_or_default()
}
#[inline]
pub(super) fn try_parse_coordinates_direct_f64(bytes: &[u8]) -> Option<Vec<f64>> {
if comments::may_contain_step_comment(bytes) {
return comments::parse_coordinates_f64(bytes);
}
read_coordinate_list::<f64, false>(bytes)
}