//! Pure helpers for pipeline item ID parsing. //! //! Pipeline item IDs share the format `{number}_{type}_{slug}`, e.g. //! `"42_story_foo"`, `"7_bug_bar"`, `"100_refactor_baz"`. The functions here //! extract or validate the leading numeric segment without performing any I/O. /// Extract the numeric prefix from a pipeline item ID. /// /// Returns the leading digit sequence from IDs like `"42_story_foo"` → `"42"`. /// Returns `None` if the ID has no leading digit sequence. pub fn extract_item_number(item_id: &str) -> Option<&str> { item_id .split('_') .next() .filter(|s| !s.is_empty() && s.chars().all(|c| c.is_ascii_digit())) } #[allow(dead_code)] /// Return `true` if `item_id` has a valid `{digits}_` prefix format. /// /// Valid: `"42_story_foo"`, `"1_bug_bar"`. /// Invalid: `"story_without_number"`, `""`, `"abc_story"`. pub fn has_valid_id_prefix(item_id: &str) -> bool { extract_item_number(item_id).is_some() } // ── Tests ───────────────────────────────────────────────────────────────────── #[cfg(test)] mod tests { use super::*; #[test] fn extract_item_number_extracts_prefix() { assert_eq!(extract_item_number("42_story_foo"), Some("42")); assert_eq!(extract_item_number("1_bug_bar"), Some("1")); assert_eq!(extract_item_number("100_refactor_baz"), Some("100")); assert_eq!( extract_item_number("261_story_bot_notifications"), Some("261") ); assert_eq!(extract_item_number("1_spike_research"), Some("1")); } #[test] fn extract_item_number_returns_none_for_no_numeric_prefix() { assert_eq!(extract_item_number("story_without_number"), None); assert_eq!(extract_item_number("abc_story"), None); assert_eq!(extract_item_number("abc_story_thing"), None); assert_eq!(extract_item_number(""), None); } #[test] fn extract_item_number_returns_none_for_empty_first_segment() { // Leading underscore: first segment is "". assert_eq!(extract_item_number("_story_thing"), None); } #[test] fn has_valid_id_prefix_returns_true_for_valid_ids() { assert!(has_valid_id_prefix("42_story_foo")); assert!(has_valid_id_prefix("1_bug_bar")); } #[test] fn has_valid_id_prefix_returns_false_for_invalid_ids() { assert!(!has_valid_id_prefix("story_no_number")); assert!(!has_valid_id_prefix("")); } }