noether_engine/index/
text.rs1#![warn(clippy::unwrap_used)]
2#![cfg_attr(test, allow(clippy::unwrap_used))]
3
4use noether_core::stage::Stage;
5
6pub fn signature_text(stage: &Stage) -> String {
8 format!("{} -> {}", stage.signature.input, stage.signature.output)
9}
10
11pub fn description_text(stage: &Stage) -> String {
15 let mut parts = vec![stage.description.clone()];
16 if !stage.aliases.is_empty() {
17 parts.push(format!("Aliases: {}", stage.aliases.join(", ")));
18 }
19 if !stage.tags.is_empty() {
20 parts.push(format!("Tags: {}", stage.tags.join(", ")));
21 }
22 parts.join("\n")
23}
24
25pub fn examples_text(stage: &Stage) -> String {
27 stage
28 .examples
29 .iter()
30 .map(|ex| format!("{} => {}", ex.input, ex.output))
31 .collect::<Vec<_>>()
32 .join("\n")
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38 use noether_core::effects::EffectSet;
39 use noether_core::stage::{CostEstimate, Example, StageId, StageLifecycle, StageSignature};
40 use noether_core::types::NType;
41 use std::collections::BTreeSet;
42
43 fn test_stage() -> Stage {
44 Stage {
45 id: StageId("test".into()),
46 signature_id: None,
47 signature: StageSignature {
48 input: NType::Text,
49 output: NType::Number,
50 effects: EffectSet::pure(),
51 implementation_hash: "impl".into(),
52 },
53 capabilities: BTreeSet::new(),
54 cost: CostEstimate {
55 time_ms_p50: None,
56 tokens_est: None,
57 memory_mb: None,
58 },
59 description: "Convert text to number".into(),
60 examples: vec![
61 Example {
62 input: serde_json::json!("42"),
63 output: serde_json::json!(42),
64 },
65 Example {
66 input: serde_json::json!("3"),
67 output: serde_json::json!(3),
68 },
69 ],
70 lifecycle: StageLifecycle::Active,
71 ed25519_signature: None,
72 signer_public_key: None,
73 implementation_code: None,
74 implementation_language: None,
75 ui_style: None,
76 tags: vec![],
77 aliases: vec![],
78 name: None,
79 properties: Vec::new(),
80 }
81 }
82
83 #[test]
84 fn signature_text_formats_types() {
85 let stage = test_stage();
86 assert_eq!(signature_text(&stage), "Text -> Number");
87 }
88
89 #[test]
90 fn description_text_returns_description() {
91 let stage = test_stage();
92 assert_eq!(description_text(&stage), "Convert text to number");
93 }
94
95 #[test]
96 fn description_text_appends_aliases_and_tags() {
97 let mut stage = test_stage();
98 stage.aliases = vec!["parse_float".into(), "atof".into()];
99 stage.tags = vec!["scalar".into(), "pure".into()];
100 let text = description_text(&stage);
101 assert!(text.starts_with("Convert text to number"));
102 assert!(text.contains("Aliases: parse_float, atof"));
103 assert!(text.contains("Tags: scalar, pure"));
104 }
105
106 #[test]
107 fn examples_text_formats_pairs() {
108 let stage = test_stage();
109 let text = examples_text(&stage);
110 assert!(text.contains("\"42\" => 42"));
111 assert!(text.contains("\"3\" => 3"));
112 }
113}