diff --git a/src/corpus.rs b/src/corpus.rs index 4b0fd9d..5dd59ea 100644 --- a/src/corpus.rs +++ b/src/corpus.rs @@ -1 +1,43 @@ -// implemented in a later task +use crate::model::{AlphaIdEntry, AppError}; + +/// Normalize an ICD code field by removing classification marks. +pub fn normalize_code(raw: &str) -> String { + raw.trim().trim_end_matches(['+', '*', '!']).trim().to_string() +} + +pub fn parse_line(line: &str) -> Option { + let f: Vec<&str> = line.split('|').collect(); + if f.len() < 8 { return None; } + Some(AlphaIdEntry { + valid: f[0].trim() == "1", + alpha_id: f[1].trim().to_string(), + icd_primary: normalize_code(f[2]), + icd_star: normalize_code(f[3]), + icd_addon: normalize_code(f[4]), + icd_primary2: normalize_code(f[5]), + orpha: f[6].trim().to_string(), + text: f[7].trim().to_string(), + }) +} + +pub fn load(path: &str) -> Result, AppError> { + let raw = std::fs::read_to_string(path) + .map_err(|e| AppError::Io(format!("{path}: {e}")))?; + let entries: Vec = raw + .lines() + .filter(|l| !l.trim().is_empty()) + .filter_map(parse_line) + .collect(); + if entries.is_empty() { + return Err(AppError::Parse(format!("no entries parsed from {path}"))); + } + Ok(entries) +} + +/// The primary ICD code a matched entry contributes (falls back to star/addon). +pub fn primary_code(e: &AlphaIdEntry) -> Option<&str> { + for c in [&e.icd_primary, &e.icd_primary2, &e.icd_star, &e.icd_addon] { + if !c.is_empty() { return Some(c); } + } + None +} diff --git a/tests/corpus_tests.rs b/tests/corpus_tests.rs new file mode 100644 index 0000000..a47dfe3 --- /dev/null +++ b/tests/corpus_tests.rs @@ -0,0 +1,29 @@ +use alpha_id::corpus; + +#[test] +fn parses_pipe_line_into_entry() { + let line = "1|I69812|A01.0+|I39.8*|||99745|Typhus-Endokarditis"; + let e = corpus::parse_line(line).expect("should parse"); + assert_eq!(e.alpha_id, "I69812"); + assert!(e.valid); + assert_eq!(e.icd_primary, "A01.0"); // normalized: no '+' + assert_eq!(e.icd_star, "I39.8"); // normalized: no '*' + assert_eq!(e.orpha, "99745"); + assert_eq!(e.text, "Typhus-Endokarditis"); +} + +#[test] +fn invalid_flag_is_false() { + let line = "0|I97837|||U81!|||Bakterien mit Multiresistenz"; + let e = corpus::parse_line(line).unwrap(); + assert!(!e.valid); + assert_eq!(e.icd_addon, "U81"); // field 5, '!' stripped + assert_eq!(e.icd_primary, ""); +} + +#[test] +fn loads_full_real_corpus() { + let entries = corpus::load("data/icd10gm2026_alphaidse_edvtxt_20250926.txt").unwrap(); + assert_eq!(entries.len(), 90_898); + assert!(entries.iter().any(|e| e.text.contains("Diabetes mellitus Typ 2"))); +}