1use std::fmt;
4use std::str::FromStr;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Protocol {
12 OpenAi,
14 OpenAiResponses,
16 Anthropic,
18}
19
20#[derive(Debug, Clone)]
22pub struct ProtocolParseError(String);
23
24impl fmt::Display for ProtocolParseError {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 write!(f, "unknown protocol: '{}'", self.0)
27 }
28}
29
30impl std::error::Error for ProtocolParseError {}
31
32impl FromStr for Protocol {
33 type Err = ProtocolParseError;
34
35 fn from_str(s: &str) -> Result<Self, Self::Err> {
36 match s.to_lowercase().as_str() {
37 "openai" | "openai-chat" => Ok(Self::OpenAi),
38 "openai-responses" | "responses" => Ok(Self::OpenAiResponses),
39 "anthropic" | "claude" => Ok(Self::Anthropic),
40 _ => Err(ProtocolParseError(s.to_string())),
41 }
42 }
43}
44
45impl Protocol {
46 pub fn as_str(&self) -> &str {
47 match self {
48 Self::OpenAi => "openai",
49 Self::OpenAiResponses => "openai-responses",
50 Self::Anthropic => "anthropic",
51 }
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn protocol_from_str() {
61 assert_eq!("openai".parse::<Protocol>().unwrap(), Protocol::OpenAi);
62 assert_eq!("openai-chat".parse::<Protocol>().unwrap(), Protocol::OpenAi);
63 assert_eq!(
64 "anthropic".parse::<Protocol>().unwrap(),
65 Protocol::Anthropic
66 );
67 assert_eq!("claude".parse::<Protocol>().unwrap(), Protocol::Anthropic);
68 assert_eq!(
69 "openai-responses".parse::<Protocol>().unwrap(),
70 Protocol::OpenAiResponses
71 );
72 assert_eq!(
73 "responses".parse::<Protocol>().unwrap(),
74 Protocol::OpenAiResponses
75 );
76 assert!("unknown".parse::<Protocol>().is_err());
77 }
78
79 #[test]
80 fn protocol_as_str() {
81 assert_eq!(Protocol::OpenAi.as_str(), "openai");
82 assert_eq!(Protocol::Anthropic.as_str(), "anthropic");
83 assert_eq!(Protocol::OpenAiResponses.as_str(), "openai-responses");
84 }
85
86 #[test]
87 fn protocol_parse_error_display_names_input() {
88 let err = "grpc".parse::<Protocol>().unwrap_err();
89 assert_eq!(err.to_string(), "unknown protocol: 'grpc'");
90 let dyn_err: &dyn std::error::Error = &err;
92 assert!(dyn_err.to_string().contains("grpc"));
93 }
94
95 #[test]
96 fn protocol_from_str_case_insensitive() {
97 assert_eq!("OpenAI".parse::<Protocol>().unwrap(), Protocol::OpenAi);
98 assert_eq!(
99 "ANTHROPIC".parse::<Protocol>().unwrap(),
100 Protocol::Anthropic
101 );
102 }
103}