use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TemplateRole {
Server,
#[allow(dead_code)]
Client,
}
impl TemplateRole {
pub fn as_str(&self) -> &'static str {
match self {
Self::Server => "server",
Self::Client => "client",
}
}
}
impl fmt::Display for TemplateRole {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum ServerTemplateKind {
#[default]
RustAxum,
PythonFastAPI,
TypeScriptExpress,
Custom,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum ClientTemplateKind {
#[default]
RustReqwest,
PythonRequests,
TypeScriptAxios,
Custom,
}
impl FromStr for ServerTemplateKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"rust_axum" => Ok(ServerTemplateKind::RustAxum),
"python_fastapi" => Ok(ServerTemplateKind::PythonFastAPI),
"typescript_express" => Ok(ServerTemplateKind::TypeScriptExpress),
"custom" => Ok(ServerTemplateKind::Custom),
_ => Err(format!("Unknown server template kind: {}", s)),
}
}
}
impl FromStr for ClientTemplateKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"rust_reqwest" => Ok(ClientTemplateKind::RustReqwest),
"python_requests" => Ok(ClientTemplateKind::PythonRequests),
"typescript_axios" => Ok(ClientTemplateKind::TypeScriptAxios),
"custom" => Ok(ClientTemplateKind::Custom),
_ => Err(format!("Unknown client template kind: {}", s)),
}
}
}
impl ServerTemplateKind {
pub fn as_str(&self) -> &'static str {
match self {
Self::RustAxum => "rust_axum",
Self::PythonFastAPI => "python_fastapi",
Self::TypeScriptExpress => "typescript_express",
Self::Custom => "custom",
}
}
pub fn role(&self) -> TemplateRole {
TemplateRole::Server
}
#[allow(dead_code)]
pub fn framework(&self) -> &'static str {
match self {
Self::RustAxum => "rust",
Self::PythonFastAPI => "python",
Self::TypeScriptExpress => "typescript",
Self::Custom => "custom",
}
}
#[allow(dead_code)]
pub fn all() -> impl Iterator<Item = Self> {
use ServerTemplateKind::*;
[RustAxum, PythonFastAPI, TypeScriptExpress, Custom]
.iter()
.copied()
}
}
impl ClientTemplateKind {
pub fn as_str(&self) -> &'static str {
match self {
Self::RustReqwest => "rust_reqwest",
Self::PythonRequests => "python_requests",
Self::TypeScriptAxios => "typescript_axios",
Self::Custom => "custom",
}
}
#[allow(dead_code)]
pub fn role(&self) -> TemplateRole {
TemplateRole::Client
}
#[allow(dead_code)]
pub fn framework(&self) -> &'static str {
match self {
Self::RustReqwest => "rust",
Self::PythonRequests => "python",
Self::TypeScriptAxios => "typescript",
Self::Custom => "custom",
}
}
#[allow(dead_code)]
pub fn all() -> impl Iterator<Item = Self> {
use ClientTemplateKind::*;
[RustReqwest, PythonRequests, TypeScriptAxios, Custom]
.iter()
.copied()
}
}
impl fmt::Display for ServerTemplateKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl fmt::Display for ClientTemplateKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[test]
fn test_server_as_str() {
assert_eq!(ServerTemplateKind::RustAxum.as_str(), "rust_axum");
assert_eq!(ServerTemplateKind::PythonFastAPI.as_str(), "python_fastapi");
assert_eq!(
ServerTemplateKind::TypeScriptExpress.as_str(),
"typescript_express"
);
assert_eq!(ServerTemplateKind::Custom.as_str(), "custom");
}
#[test]
fn test_server_display() {
assert_eq!(format!("{}", ServerTemplateKind::RustAxum), "rust_axum");
assert_eq!(
format!("{}", ServerTemplateKind::PythonFastAPI),
"python_fastapi"
);
assert_eq!(
format!("{}", ServerTemplateKind::TypeScriptExpress),
"typescript_express"
);
assert_eq!(format!("{}", ServerTemplateKind::Custom), "custom");
}
#[test]
fn test_server_from_str() {
assert_eq!(
"rust_axum".parse::<ServerTemplateKind>().unwrap(),
ServerTemplateKind::RustAxum
);
assert_eq!(
"python_fastapi".parse::<ServerTemplateKind>().unwrap(),
ServerTemplateKind::PythonFastAPI
);
assert_eq!(
"typescript_express".parse::<ServerTemplateKind>().unwrap(),
ServerTemplateKind::TypeScriptExpress
);
assert_eq!(
"custom".parse::<ServerTemplateKind>().unwrap(),
ServerTemplateKind::Custom
);
assert_eq!(
"RUST_AXUM".parse::<ServerTemplateKind>().unwrap(),
ServerTemplateKind::RustAxum
);
assert!("invalid".parse::<ServerTemplateKind>().is_err());
assert!("rust_reqwest".parse::<ServerTemplateKind>().is_err()); }
#[test]
fn test_server_default() {
assert_eq!(ServerTemplateKind::default(), ServerTemplateKind::RustAxum);
}
#[test]
fn test_server_all() {
let all_kinds: Vec<_> = ServerTemplateKind::all().collect();
assert_eq!(all_kinds.len(), 4);
let unique_kinds: HashSet<_> = ServerTemplateKind::all().collect();
assert_eq!(unique_kinds.len(), 4);
assert!(unique_kinds.contains(&ServerTemplateKind::RustAxum));
assert!(unique_kinds.contains(&ServerTemplateKind::PythonFastAPI));
assert!(unique_kinds.contains(&ServerTemplateKind::TypeScriptExpress));
assert!(unique_kinds.contains(&ServerTemplateKind::Custom));
}
#[test]
fn test_server_role() {
assert_eq!(ServerTemplateKind::RustAxum.role(), TemplateRole::Server);
assert_eq!(
ServerTemplateKind::PythonFastAPI.role(),
TemplateRole::Server
);
assert_eq!(
ServerTemplateKind::TypeScriptExpress.role(),
TemplateRole::Server
);
assert_eq!(ServerTemplateKind::Custom.role(), TemplateRole::Server);
}
#[test]
fn test_server_framework() {
assert_eq!(ServerTemplateKind::RustAxum.framework(), "rust");
assert_eq!(ServerTemplateKind::PythonFastAPI.framework(), "python");
assert_eq!(
ServerTemplateKind::TypeScriptExpress.framework(),
"typescript"
);
assert_eq!(ServerTemplateKind::Custom.framework(), "custom");
}
#[test]
fn test_client_as_str() {
assert_eq!(ClientTemplateKind::RustReqwest.as_str(), "rust_reqwest");
assert_eq!(
ClientTemplateKind::PythonRequests.as_str(),
"python_requests"
);
assert_eq!(
ClientTemplateKind::TypeScriptAxios.as_str(),
"typescript_axios"
);
assert_eq!(ClientTemplateKind::Custom.as_str(), "custom");
}
#[test]
fn test_client_display() {
assert_eq!(
format!("{}", ClientTemplateKind::RustReqwest),
"rust_reqwest"
);
assert_eq!(
format!("{}", ClientTemplateKind::PythonRequests),
"python_requests"
);
assert_eq!(
format!("{}", ClientTemplateKind::TypeScriptAxios),
"typescript_axios"
);
assert_eq!(format!("{}", ClientTemplateKind::Custom), "custom");
}
#[test]
fn test_client_from_str() {
assert_eq!(
"rust_reqwest".parse::<ClientTemplateKind>().unwrap(),
ClientTemplateKind::RustReqwest
);
assert_eq!(
"python_requests".parse::<ClientTemplateKind>().unwrap(),
ClientTemplateKind::PythonRequests
);
assert_eq!(
"typescript_axios".parse::<ClientTemplateKind>().unwrap(),
ClientTemplateKind::TypeScriptAxios
);
assert_eq!(
"custom".parse::<ClientTemplateKind>().unwrap(),
ClientTemplateKind::Custom
);
assert_eq!(
"RUST_REQWEST".parse::<ClientTemplateKind>().unwrap(),
ClientTemplateKind::RustReqwest
);
assert!("invalid".parse::<ClientTemplateKind>().is_err());
assert!("rust_axum".parse::<ClientTemplateKind>().is_err()); }
#[test]
fn test_client_default() {
assert_eq!(
ClientTemplateKind::default(),
ClientTemplateKind::RustReqwest
);
}
#[test]
fn test_client_all() {
let all_kinds: Vec<_> = ClientTemplateKind::all().collect();
assert_eq!(all_kinds.len(), 4);
let unique_kinds: HashSet<_> = ClientTemplateKind::all().collect();
assert_eq!(unique_kinds.len(), 4);
assert!(unique_kinds.contains(&ClientTemplateKind::RustReqwest));
assert!(unique_kinds.contains(&ClientTemplateKind::PythonRequests));
assert!(unique_kinds.contains(&ClientTemplateKind::TypeScriptAxios));
assert!(unique_kinds.contains(&ClientTemplateKind::Custom));
}
#[test]
fn test_client_role() {
assert_eq!(ClientTemplateKind::RustReqwest.role(), TemplateRole::Client);
assert_eq!(
ClientTemplateKind::PythonRequests.role(),
TemplateRole::Client
);
assert_eq!(
ClientTemplateKind::TypeScriptAxios.role(),
TemplateRole::Client
);
assert_eq!(ClientTemplateKind::Custom.role(), TemplateRole::Client);
}
#[test]
fn test_client_framework() {
assert_eq!(ClientTemplateKind::RustReqwest.framework(), "rust");
assert_eq!(ClientTemplateKind::PythonRequests.framework(), "python");
assert_eq!(
ClientTemplateKind::TypeScriptAxios.framework(),
"typescript"
);
assert_eq!(ClientTemplateKind::Custom.framework(), "custom");
}
#[test]
fn test_template_role_as_str() {
assert_eq!(TemplateRole::Server.as_str(), "server");
assert_eq!(TemplateRole::Client.as_str(), "client");
}
#[test]
fn test_template_role_display() {
assert_eq!(format!("{}", TemplateRole::Server), "server");
assert_eq!(format!("{}", TemplateRole::Client), "client");
}
#[test]
fn test_template_kind_with_protocol() {
use crate::core::protocol::Protocol;
let server_kind = ServerTemplateKind::RustAxum;
let protocol = Protocol::Mcp;
let expected_path = format!(
"templates/{}/{}/{}",
protocol.path_segment(),
server_kind.role().as_str(),
server_kind.as_str()
);
assert_eq!(expected_path, "templates/mcp/server/rust_axum");
let client_kind = ClientTemplateKind::RustReqwest;
let expected_client_path = format!(
"templates/{}/{}/{}",
protocol.path_segment(),
client_kind.role().as_str(),
client_kind.as_str()
);
assert_eq!(expected_client_path, "templates/mcp/client/rust_reqwest");
}
#[test]
fn test_template_kind_path_construction() {
use crate::core::protocol::Protocol;
let test_cases = vec![
(
Protocol::Mcp,
ServerTemplateKind::RustAxum,
"templates/mcp/server/rust_axum",
),
(
Protocol::Mcp,
ServerTemplateKind::PythonFastAPI,
"templates/mcp/server/python_fastapi",
),
(
Protocol::Mcp,
ServerTemplateKind::Custom,
"templates/mcp/server/custom",
),
];
for (protocol, template_kind, expected_path) in test_cases {
let path = format!(
"templates/{}/{}/{}",
protocol.path_segment(),
template_kind.role().as_str(),
template_kind.as_str()
);
assert_eq!(path, expected_path);
}
}
}