ultrafast_mcp_core/utils/
uri.rs1use crate::error::{MCPError, MCPResult, ResourceError};
2use serde::{Deserialize, Serialize};
3use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
7pub struct Uri(String);
8
9impl Uri {
10 pub fn new(uri: impl Into<String>) -> Self {
12 Self(uri.into())
13 }
14
15 pub fn as_str(&self) -> &str {
17 &self.0
18 }
19
20 pub fn is_file(&self) -> bool {
22 self.0.starts_with("file://")
23 }
24
25 pub fn is_http(&self) -> bool {
27 self.0.starts_with("http://") || self.0.starts_with("https://")
28 }
29
30 pub fn scheme(&self) -> Option<&str> {
32 self.0.split("://").next()
33 }
34
35 pub fn validate(&self) -> MCPResult<()> {
37 if self.0.is_empty() {
38 return Err(MCPError::Resource(ResourceError::InvalidUri(
39 "URI cannot be empty".to_string(),
40 )));
41 }
42
43 if !self.0.contains("://") && (self.0.starts_with('/') || !self.0.starts_with('/')) {
45 return Ok(());
46 }
47
48 if let Some(scheme) = self.scheme() {
50 if scheme.is_empty()
51 || !scheme
52 .chars()
53 .all(|c| c.is_ascii_alphanumeric() || c == '+' || c == '-' || c == '.')
54 {
55 return Err(MCPError::Resource(ResourceError::InvalidUri(format!(
56 "Invalid URI scheme: {scheme}"
57 ))));
58 }
59 }
60
61 Ok(())
62 }
63}
64
65impl fmt::Display for Uri {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 write!(f, "{}", self.0)
68 }
69}
70
71impl From<String> for Uri {
72 fn from(s: String) -> Self {
73 Uri::new(s)
74 }
75}
76
77impl From<&str> for Uri {
78 fn from(s: &str) -> Self {
79 Uri::new(s)
80 }
81}
82
83impl AsRef<str> for Uri {
84 fn as_ref(&self) -> &str {
85 &self.0
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn test_uri_creation() {
95 let uri = Uri::new("file:///path/to/file.txt");
96 assert_eq!(uri.as_str(), "file:///path/to/file.txt");
97 }
98
99 #[test]
100 fn test_uri_scheme() {
101 let file_uri = Uri::new("file:///path/to/file.txt");
102 assert_eq!(file_uri.scheme(), Some("file"));
103 assert!(file_uri.is_file());
104
105 let http_uri = Uri::new("https://example.com/path");
106 assert_eq!(http_uri.scheme(), Some("https"));
107 assert!(http_uri.is_http());
108 }
109
110 #[test]
111 fn test_uri_validation() {
112 assert!(Uri::new("file:///path").validate().is_ok());
113 assert!(Uri::new("https://example.com").validate().is_ok());
114 assert!(Uri::new("/absolute/path").validate().is_ok());
115 assert!(Uri::new("relative/path").validate().is_ok());
116 assert!(Uri::new("").validate().is_err());
117 }
118}