cognis_core/output_parsers/
boolean.rs1use async_trait::async_trait;
4
5use crate::output_parsers::OutputParser;
6use crate::runnable::{Runnable, RunnableConfig};
7use crate::{CognisError, Result};
8
9#[derive(Debug, Default, Clone, Copy)]
13pub struct BooleanParser;
14
15impl BooleanParser {
16 pub fn new() -> Self {
18 Self
19 }
20}
21
22impl OutputParser<bool> for BooleanParser {
23 fn parse(&self, text: &str) -> Result<bool> {
24 let t = text.trim().to_lowercase();
25 match t.as_str() {
26 "yes" | "true" | "y" | "1" => Ok(true),
27 "no" | "false" | "n" | "0" => Ok(false),
28 other => Err(CognisError::Serialization(format!(
29 "BooleanParser: cannot parse `{other}` as bool"
30 ))),
31 }
32 }
33 fn format_instructions(&self) -> Option<String> {
34 Some("Reply with exactly one word: `yes` or `no`.".into())
35 }
36}
37
38#[async_trait]
39impl Runnable<String, bool> for BooleanParser {
40 async fn invoke(&self, input: String, _: RunnableConfig) -> Result<bool> {
41 OutputParser::parse(self, &input)
42 }
43 fn name(&self) -> &str {
44 "BooleanParser"
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn parses_truthy() {
54 let p = BooleanParser::new();
55 for s in ["yes", "YES", "true", "TRUE", "y", "1", " yes "] {
56 assert!(p.parse(s).unwrap(), "expected true for {s}");
57 }
58 }
59
60 #[test]
61 fn parses_falsy() {
62 let p = BooleanParser::new();
63 for s in ["no", "NO", "false", "n", "0"] {
64 assert!(!p.parse(s).unwrap(), "expected false for {s}");
65 }
66 }
67
68 #[test]
69 fn invalid_errors() {
70 let p = BooleanParser::new();
71 assert!(p.parse("maybe").is_err());
72 }
73}