rmcp_openapi/
spec_location.rs1use crate::error::OpenApiError;
2use crate::openapi_spec::OpenApiSpec;
3use std::fmt;
4use std::path::PathBuf;
5use std::str::FromStr;
6use url::Url;
7
8#[derive(Debug, Clone)]
9pub enum OpenApiSpecLocation {
10 File(PathBuf),
11 Url(Url),
12}
13
14impl FromStr for OpenApiSpecLocation {
15 type Err = OpenApiError;
16
17 fn from_str(s: &str) -> Result<Self, Self::Err> {
18 if s.starts_with("http://") || s.starts_with("https://") {
19 let url =
20 Url::parse(s).map_err(|e| OpenApiError::InvalidUrl(format!("Invalid URL: {e}")))?;
21 Ok(OpenApiSpecLocation::Url(url))
22 } else {
23 let path = PathBuf::from(s);
24 Ok(OpenApiSpecLocation::File(path))
25 }
26 }
27}
28
29impl OpenApiSpecLocation {
30 pub async fn load_spec(&self) -> Result<OpenApiSpec, OpenApiError> {
31 match self {
32 OpenApiSpecLocation::File(path) => {
33 OpenApiSpec::from_file(path.to_str().ok_or_else(|| {
34 OpenApiError::InvalidPath("Invalid file path encoding".to_string())
35 })?)
36 .await
37 }
38 OpenApiSpecLocation::Url(url) => OpenApiSpec::from_url(url).await,
39 }
40 }
41}
42
43impl fmt::Display for OpenApiSpecLocation {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 match self {
46 OpenApiSpecLocation::File(path) => write!(f, "{}", path.display()),
47 OpenApiSpecLocation::Url(url) => write!(f, "{url}"),
48 }
49 }
50}