Skip to main content

Mountain/ProcessManagement/
ExtractDevTag.rs

1#![allow(non_snake_case)]
2
3//! Cocoon stdout-line inspector. Detects the `[DEV:<TAG>]` prefix written by
4//! `Cocoon/Source/Services/DevLog.ts::CocoonDevLog` and returns the lower-
5//! cased tag for dispatch into Mountain's per-tag `dev_log!` sinks. Returns
6//! `None` for bare stdout so the caller falls back to the catch-all `cocoon`
7//! tag.
8
9pub fn Fn(Line:&str) -> Option<String> {
10	let Stripped = Line.strip_prefix("[DEV:")?;
11
12	let (TagUpper, _Rest) = Stripped.split_once(']')?;
13
14	if TagUpper.is_empty() {
15		return None;
16	}
17
18	// Reject anything that isn't a simple tag ident - prevents stray
19	// `[DEV: something with space]` headers from being treated as tags.
20	if !TagUpper.chars().all(|C| C.is_ascii_uppercase() || C == '-' || C == '_') {
21		return None;
22	}
23
24	Some(TagUpper.to_ascii_lowercase())
25}
26
27#[cfg(test)]
28mod Tests {
29
30	use super::Fn;
31
32	#[test]
33	fn StripsKnownTag() {
34		assert_eq!(
35			Fn("[DEV:BOOTSTRAP-STAGE] [Bootstrap] stage=Environment event=start"),
36			Some("bootstrap-stage".to_string())
37		);
38	}
39
40	#[test]
41	fn RejectsPlainText() {
42		assert_eq!(Fn("plain stdout line"), None);
43	}
44
45	#[test]
46	fn RejectsMalformed() {
47		assert_eq!(Fn("[DEV: BOOT] x"), None);
48
49		assert_eq!(Fn("[DEV:]"), None);
50
51		assert_eq!(Fn("[DEV:BOOT"), None);
52	}
53}