#[cfg(feature = "server")]
use crate::app::{
context::Context,
handler::{FromHandlerParams, HandlerParams},
};
#[cfg(feature = "server")]
use crate::error::Error;
#[cfg(feature = "server")]
use crate::types::request::FromRequest;
use crate::types::request::RequestParamsMeta;
use crate::types::{Annotations, Cursor, Icon};
#[cfg(feature = "server")]
use crate::types::{IntoResponse, Page, Request, RequestId, Response};
use serde::{Deserialize, Serialize};
pub use read_resource_result::{
BlobResourceContents, EmptyResourceContents, JsonResourceContents, ReadResourceResult,
ResourceContents, TextResourceContents,
};
pub use template::{
ListResourceTemplatesRequestParams, ListResourceTemplatesResult, ResourceTemplate,
};
pub use uri::Uri;
#[cfg(all(feature = "server", feature = "di"))]
pub(crate) use from_request::{Payload, ResourceArgument, Source};
#[cfg(feature = "server")]
pub(crate) use route::Route;
#[cfg(feature = "server")]
mod from_request;
mod read_resource_result;
#[cfg(feature = "server")]
pub(crate) mod route;
pub(crate) mod template;
mod uri;
pub mod commands {
pub const LIST: &str = "resources/list";
pub const LIST_CHANGED: &str = "notifications/resources/list_changed";
pub const TEMPLATES_LIST: &str = "resources/templates/list";
pub const READ: &str = "resources/read";
pub const SUBSCRIBE: &str = "resources/subscribe";
pub const UNSUBSCRIBE: &str = "resources/unsubscribe";
pub const UPDATED: &str = "notifications/resources/updated";
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Resource {
pub uri: Uri,
pub name: String,
#[serde(rename = "description", skip_serializing_if = "Option::is_none")]
pub descr: Option<String>,
#[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
pub mime: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub size: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub annotations: Option<Annotations>,
#[serde(skip_serializing_if = "Option::is_none")]
pub icons: Option<Vec<Icon>>,
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
pub meta: Option<serde_json::Value>,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct ListResourcesRequestParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub cursor: Option<Cursor>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ReadResourceRequestParams {
pub uri: Uri,
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
pub meta: Option<RequestParamsMeta>,
#[serde(skip)]
#[cfg(feature = "server")]
pub(crate) args: Option<Box<[String]>>,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct ListResourcesResult {
pub resources: Vec<Resource>,
#[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
pub next_cursor: Option<Cursor>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SubscribeRequestParams {
pub uri: Uri,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UnsubscribeRequestParams {
pub uri: Uri,
}
impl<T: Into<Uri>> From<T> for SubscribeRequestParams {
#[inline]
fn from(uri: T) -> Self {
Self { uri: uri.into() }
}
}
impl<T: Into<Uri>> From<T> for UnsubscribeRequestParams {
#[inline]
fn from(uri: T) -> Self {
Self { uri: uri.into() }
}
}
#[cfg(feature = "server")]
impl IntoResponse for ListResourcesResult {
#[inline]
fn into_response(self, req_id: RequestId) -> Response {
match serde_json::to_value(self) {
Ok(v) => Response::success(req_id, v),
Err(err) => Response::error(req_id, err.into()),
}
}
}
#[cfg(feature = "server")]
impl<const N: usize> From<[Resource; N]> for ListResourcesResult {
#[inline]
fn from(resources: [Resource; N]) -> Self {
Self {
next_cursor: None,
resources: resources.to_vec(),
}
}
}
#[cfg(feature = "server")]
impl From<Vec<Resource>> for ListResourcesResult {
#[inline]
fn from(resources: Vec<Resource>) -> Self {
Self {
next_cursor: None,
resources,
}
}
}
#[cfg(feature = "server")]
impl From<Page<'_, Resource>> for ListResourcesResult {
#[inline]
fn from(page: Page<'_, Resource>) -> Self {
Self {
next_cursor: page.next_cursor,
resources: page.items.to_vec(),
}
}
}
#[cfg(feature = "server")]
impl FromHandlerParams for ListResourcesRequestParams {
#[inline]
fn from_params(params: &HandlerParams) -> Result<Self, Error> {
let req = Request::from_params(params)?;
Self::from_request(req)
}
}
#[cfg(feature = "server")]
impl FromHandlerParams for ReadResourceRequestParams {
#[inline]
fn from_params(params: &HandlerParams) -> Result<Self, Error> {
let req = Request::from_params(params)?;
Self::from_request(req)
}
}
#[cfg(feature = "server")]
impl FromHandlerParams for SubscribeRequestParams {
#[inline]
fn from_params(params: &HandlerParams) -> Result<Self, Error> {
let req = Request::from_params(params)?;
Self::from_request(req)
}
}
#[cfg(feature = "server")]
impl FromHandlerParams for UnsubscribeRequestParams {
#[inline]
fn from_params(params: &HandlerParams) -> Result<Self, Error> {
let req = Request::from_params(params)?;
Self::from_request(req)
}
}
#[cfg(feature = "server")]
impl ListResourcesResult {
#[inline]
pub fn new() -> Self {
Default::default()
}
}
impl From<Uri> for Resource {
#[inline]
fn from(uri: Uri) -> Self {
Self {
name: uri.to_string(),
title: None,
descr: None,
mime: None,
size: None,
annotations: None,
meta: None,
icons: None,
uri,
}
}
}
impl From<String> for Resource {
#[inline]
fn from(uri: String) -> Self {
Self {
name: uri.clone(),
title: None,
uri: uri.into(),
descr: None,
mime: None,
size: None,
annotations: None,
icons: None,
meta: None,
}
}
}
impl From<Uri> for ReadResourceRequestParams {
#[inline]
fn from(uri: Uri) -> Self {
Self {
meta: None,
#[cfg(feature = "server")]
args: None,
uri,
}
}
}
#[cfg(feature = "server")]
impl ReadResourceRequestParams {
pub(crate) fn with_context(mut self, ctx: Context) -> Self {
self.meta.get_or_insert_default().context = Some(ctx);
self
}
#[cfg(feature = "server")]
pub(crate) fn with_args(mut self, args: Box<[String]>) -> Self {
self.args = Some(args);
self
}
}
#[cfg(feature = "server")]
impl Resource {
#[inline]
pub fn new<U: Into<Uri>, S: Into<String>>(uri: U, name: S) -> Self {
Self {
uri: uri.into(),
name: name.into(),
title: None,
descr: None,
mime: None,
size: None,
annotations: None,
icons: None,
meta: None,
}
}
pub fn with_name(mut self, name: impl Into<String>) -> Self {
self.name = name.into();
self
}
pub fn with_descr(mut self, description: impl Into<String>) -> Self {
self.descr = Some(description.into());
self
}
pub fn with_mime(mut self, mime: impl Into<String>) -> Self {
self.mime = Some(mime.into());
self
}
pub fn with_size(mut self, size: usize) -> Self {
self.size = Some(size);
self
}
pub fn with_annotations<F>(mut self, config: F) -> Self
where
F: FnOnce(Annotations) -> Annotations,
{
self.annotations = Some(config(Default::default()));
self
}
pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn with_icons(&mut self, icons: impl IntoIterator<Item = Icon>) -> &mut Self {
self.icons = Some(icons.into_iter().collect());
self
}
}
#[cfg(test)]
mod tests {}