1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
16#[serde(tag = "type", rename_all = "snake_case")]
17pub enum ContentBlock {
18 Text { text: String },
20
21 Image {
23 data: String,
24 #[serde(rename = "mimeType")]
25 mime_type: String,
26 },
27
28 Audio {
30 data: String,
31 #[serde(rename = "mimeType")]
32 mime_type: String,
33 },
34
35 Resource(ResourceContent),
37
38 ResourceLink {
40 uri: String,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 name: Option<String>,
43 #[serde(skip_serializing_if = "Option::is_none", rename = "mimeType")]
44 mime_type: Option<String>,
45 },
46}
47
48impl ContentBlock {
49 pub fn text(text: impl Into<String>) -> Self {
51 Self::Text { text: text.into() }
52 }
53
54 pub fn image(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
56 Self::Image {
57 data: data.into(),
58 mime_type: mime_type.into(),
59 }
60 }
61
62 pub fn audio(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
64 Self::Audio {
65 data: data.into(),
66 mime_type: mime_type.into(),
67 }
68 }
69
70 pub fn resource(resource: ResourceContent) -> Self {
72 Self::Resource(resource)
73 }
74
75 pub fn resource_link(
77 uri: impl Into<String>,
78 name: Option<String>,
79 mime_type: Option<String>,
80 ) -> Self {
81 Self::ResourceLink {
82 uri: uri.into(),
83 name,
84 mime_type,
85 }
86 }
87
88 pub fn is_text(&self) -> bool {
90 matches!(self, Self::Text { .. })
91 }
92
93 pub fn is_image(&self) -> bool {
95 matches!(self, Self::Image { .. })
96 }
97
98 pub fn is_audio(&self) -> bool {
100 matches!(self, Self::Audio { .. })
101 }
102
103 pub fn is_resource(&self) -> bool {
105 matches!(self, Self::Resource(_))
106 }
107
108 pub fn is_resource_link(&self) -> bool {
110 matches!(self, Self::ResourceLink { .. })
111 }
112}
113
114#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
118pub struct ResourceContent {
119 pub uri: String,
121
122 #[serde(default, rename = "mimeType", skip_serializing_if = "Option::is_none")]
124 pub mime_type: Option<String>,
125
126 #[serde(default, skip_serializing_if = "Option::is_none")]
128 pub text: Option<String>,
129
130 #[serde(default, skip_serializing_if = "Option::is_none")]
132 pub blob: Option<String>,
133}
134
135impl ResourceContent {
136 pub fn new(uri: impl Into<String>) -> Self {
138 Self {
139 uri: uri.into(),
140 mime_type: None,
141 text: None,
142 blob: None,
143 }
144 }
145
146 pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
148 self.mime_type = Some(mime_type.into());
149 self
150 }
151
152 pub fn with_text(mut self, text: impl Into<String>) -> Self {
154 self.text = Some(text.into());
155 self
156 }
157
158 pub fn with_blob(mut self, blob: impl Into<String>) -> Self {
160 self.blob = Some(blob.into());
161 self
162 }
163
164 pub fn with_optional_mime(mut self, mime_type: Option<String>) -> Self {
166 if mime_type.is_some() {
167 self.mime_type = mime_type;
168 }
169 self
170 }
171}