1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
4#[serde(rename_all = "snake_case")]
5pub enum Harness {
6 Opencode,
7 Pi,
8}
9
10impl Harness {
11 pub fn as_str(self) -> &'static str {
12 match self {
13 Harness::Opencode => "opencode",
14 Harness::Pi => "pi",
15 }
16 }
17}
18
19impl std::fmt::Display for Harness {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 f.write_str(self.as_str())
22 }
23}
24
25impl std::str::FromStr for Harness {
26 type Err = String;
27
28 fn from_str(value: &str) -> Result<Self, Self::Err> {
29 match value {
30 "opencode" => Ok(Harness::Opencode),
31 "pi" => Ok(Harness::Pi),
32 other => Err(format!(
33 "unsupported harness '{other}'; expected 'opencode' or 'pi'"
34 )),
35 }
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::Harness;
42
43 #[test]
44 fn harness_enum_serde_roundtrip() {
45 assert_eq!(
46 serde_json::to_string(&Harness::Opencode).unwrap(),
47 "\"opencode\""
48 );
49 assert_eq!(serde_json::to_string(&Harness::Pi).unwrap(), "\"pi\"");
50
51 assert_eq!(
52 serde_json::from_str::<Harness>("\"opencode\"").unwrap(),
53 Harness::Opencode
54 );
55 assert_eq!(
56 serde_json::from_str::<Harness>("\"pi\"").unwrap(),
57 Harness::Pi
58 );
59 assert!(serde_json::from_str::<Harness>("\"claude_code\"").is_err());
60 }
61}