poem_mcpserver/
content.rs

1//! Content types.
2
3use std::fmt::Display;
4
5use base64::{Engine, engine::general_purpose::STANDARD};
6use serde::Serialize;
7
8use crate::protocol::content::Content;
9
10/// Represents a type that can be converted into a content.
11pub trait IntoContent {
12    /// Consumes the object and converts it into a content.
13    fn into_content(self) -> Content;
14}
15
16impl IntoContent for Content {
17    #[inline]
18    fn into_content(self) -> Content {
19        self
20    }
21}
22
23/// Represents a type that can be converted into multiple contents.
24pub trait IntoContents {
25    /// Consumes the object and converts it into multiple contents.
26    fn into_contents(self) -> Vec<Content>;
27}
28
29impl<T> IntoContents for T
30where
31    T: IntoContent,
32{
33    fn into_contents(self) -> Vec<Content> {
34        vec![self.into_content()]
35    }
36}
37
38impl<T> IntoContents for Vec<T>
39where
40    T: IntoContent,
41{
42    fn into_contents(self) -> Vec<Content> {
43        self.into_iter().map(IntoContent::into_content).collect()
44    }
45}
46
47/// A wrapper type for multiple contents from an iterator.
48pub struct ContentsIter<T>(pub T);
49
50impl<T> IntoContents for ContentsIter<T>
51where
52    T: IntoIterator,
53    T::Item: IntoContent,
54{
55    fn into_contents(self) -> Vec<Content> {
56        self.0.into_iter().map(IntoContent::into_content).collect()
57    }
58}
59
60/// A text response.
61#[derive(Debug)]
62pub struct Text<T>(pub T);
63
64impl<T> IntoContent for Text<T>
65where
66    T: Display,
67{
68    fn into_content(self) -> Content {
69        Content::Text {
70            text: self.0.to_string(),
71        }
72    }
73}
74
75/// An image response.
76#[derive(Debug)]
77pub struct Image<T> {
78    data: T,
79    mime_type: String,
80}
81
82impl<T> Image<T> {
83    /// Creates a image content.
84    #[inline]
85    pub fn new(data: T, mime_type: impl Into<String>) -> Self {
86        Self {
87            data,
88            mime_type: mime_type.into(),
89        }
90    }
91}
92
93impl<T> IntoContent for Image<T>
94where
95    T: AsRef<[u8]>,
96{
97    fn into_content(self) -> Content {
98        Content::Image {
99            data: STANDARD.encode(self.data),
100            mime_type: self.mime_type,
101        }
102    }
103}
104
105/// A Json response.
106#[derive(Debug, Clone, Copy)]
107pub struct Json<T>(pub T);
108
109impl<T> IntoContent for Json<T>
110where
111    T: Serialize,
112{
113    fn into_content(self) -> Content {
114        Content::Text {
115            text: serde_json::to_string(&self.0).unwrap_or_default(),
116        }
117    }
118}