use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::error::Error;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceMetadata {
pub uri: String,
pub description: String,
pub mime_type: Option<String>,
pub metadata: HashMap<String, serde_json::Value>,
}
impl ResourceMetadata {
pub fn new(uri: impl Into<String>, description: impl Into<String>) -> Self {
Self {
uri: uri.into(),
description: description.into(),
mime_type: None,
metadata: HashMap::new(),
}
}
pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
self.mime_type = Some(mime_type.into());
self
}
pub fn with_metadata(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
self.metadata.insert(key.into(), value);
self
}
}
#[async_trait]
pub trait ResourceProtocol: Send + Sync {
async fn list_resources(&self) -> Result<Vec<ResourceMetadata>, Box<dyn Error + Send + Sync>>;
async fn read_resource(&self, uri: &str) -> Result<String, Box<dyn Error + Send + Sync>>;
fn protocol_name(&self) -> &str {
"resource"
}
async fn initialize(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
Ok(())
}
async fn shutdown(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
Ok(())
}
}
#[derive(Debug, Clone)]
pub enum ResourceError {
NotFound(String),
PermissionDenied(String),
InvalidUri(String),
ProtocolError(String),
}
impl std::fmt::Display for ResourceError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ResourceError::NotFound(uri) => write!(f, "Resource not found: {}", uri),
ResourceError::PermissionDenied(uri) => write!(f, "Permission denied: {}", uri),
ResourceError::InvalidUri(uri) => write!(f, "Invalid URI: {}", uri),
ResourceError::ProtocolError(msg) => write!(f, "Protocol error: {}", msg),
}
}
}
impl std::error::Error for ResourceError {}