elementary-row-operation-verifier 0.0.1

A tool to verify the correctness of elementary row operations on matrices
Documentation
//! 公共:定位符 → 列位置,数字提取

use crate::error::MatrixError;

/// 列定义
pub struct ColDef {
    pub pos: usize,
    pub is_num: bool,
}

/// 从定位符行提取列位置。> → 数字列,| _ → 操作列
pub fn parse_marker(line: &str) -> Result<Vec<ColDef>, MatrixError> {
    let mut defs = Vec::new();
    for (idx, ch) in line.chars().enumerate() {
        match ch {
            '>' => defs.push(ColDef {
                pos: idx,
                is_num: true,
            }),
            '|' | '_' => defs.push(ColDef {
                pos: idx,
                is_num: false,
            }),
            _ => {}
        }
    }
    if defs.is_empty() {
        return Err(MatrixError::InvalidFormat("No column markers".into()));
    }
    Ok(defs)
}

/// 按列定义切割一行,返回数字列表
pub fn slice_numbers(line: &str, defs: &[ColDef]) -> Result<Vec<f64>, MatrixError> {
    let chars: Vec<char> = line.chars().collect();
    let mut nums = Vec::new();
    for (i, d) in defs.iter().enumerate() {
        if !d.is_num {
            continue;
        }
        let end = if i + 1 < defs.len() {
            defs[i + 1].pos
        } else {
            chars.len()
        };
        if d.pos >= chars.len() {
            continue;
        }
        let s: String = chars[d.pos..end.min(chars.len())].iter().collect();
        let s = s.trim();
        if s.is_empty() {
            continue;
        }
        match s.parse::<f64>() {
            Ok(n) => nums.push(n),
            Err(_) => {
                return Err(MatrixError::InvalidFormat(format!(
                    "expected number at col {}, got '{}'",
                    i, s
                )));
            }
        }
    }
    Ok(nums)
}

/// 按列定义切割一行,返回每列的文本(自有)
pub fn slice_all(line: &str, defs: &[ColDef]) -> Vec<String> {
    let chars: Vec<char> = line.chars().collect();
    let mut result = Vec::new();
    for (i, d) in defs.iter().enumerate() {
        let end = if i + 1 < defs.len() {
            defs[i + 1].pos
        } else {
            chars.len()
        };
        if d.pos >= chars.len() {
            result.push(String::new());
        } else {
            let s: String = chars[d.pos..end.min(chars.len())].iter().collect();
            result.push(s.trim().to_string());
        }
    }
    result
}

/// 提取操作文本(最后一个非数字列的文本)
pub fn slice_op(slices: &[String], defs: &[ColDef]) -> String {
    for (i, d) in defs.iter().enumerate() {
        if !d.is_num {
            return slices.get(i).cloned().unwrap_or_default();
        }
    }
    String::new()
}

/// 从列定义计算每列宽度
pub fn col_widths(defs: &[ColDef]) -> Vec<usize> {
    let mut ws = vec![];
    for i in 0..defs.len() {
        let end = if i + 1 < defs.len() {
            defs[i + 1].pos
        } else {
            defs[i].pos + 6
        };
        ws.push(end.saturating_sub(defs[i].pos));
    }
    ws
}