claudius/types/
document_block.rs1use serde::{Deserialize, Serialize};
2
3use crate::types::{
4 Base64PdfSource, CacheControlEphemeral, CitationsConfig, ContentBlockSourceParam,
5 PlainTextSource, UrlPdfSource,
6};
7
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
10#[serde(tag = "type")]
11pub enum DocumentSource {
12 #[serde(rename = "base64")]
14 Base64Pdf(Base64PdfSource),
15
16 #[serde(rename = "text")]
18 PlainText(PlainTextSource),
19
20 #[serde(rename = "content")]
22 ContentBlock(ContentBlockSourceParam),
23
24 #[serde(rename = "url")]
26 UrlPdf(UrlPdfSource),
27}
28
29impl From<Base64PdfSource> for DocumentSource {
30 fn from(source: Base64PdfSource) -> Self {
31 DocumentSource::Base64Pdf(source)
32 }
33}
34
35impl From<PlainTextSource> for DocumentSource {
36 fn from(source: PlainTextSource) -> Self {
37 DocumentSource::PlainText(source)
38 }
39}
40
41impl From<ContentBlockSourceParam> for DocumentSource {
42 fn from(source: ContentBlockSourceParam) -> Self {
43 DocumentSource::ContentBlock(source)
44 }
45}
46
47impl From<UrlPdfSource> for DocumentSource {
48 fn from(source: UrlPdfSource) -> Self {
49 DocumentSource::UrlPdf(source)
50 }
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
55pub struct DocumentBlock {
56 pub source: DocumentSource,
58
59 #[serde(skip_serializing_if = "Option::is_none")]
61 pub cache_control: Option<CacheControlEphemeral>,
62
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub citations: Option<CitationsConfig>,
66
67 #[serde(skip_serializing_if = "Option::is_none")]
69 pub context: Option<String>,
70
71 #[serde(skip_serializing_if = "Option::is_none")]
73 pub title: Option<String>,
74}
75
76impl DocumentBlock {
77 pub fn new(source: DocumentSource) -> Self {
79 Self {
80 source,
81 cache_control: None,
82 citations: None,
83 context: None,
84 title: None,
85 }
86 }
87
88 pub fn new_with_base64_pdf(source: Base64PdfSource) -> Self {
90 Self::new(DocumentSource::Base64Pdf(source))
91 }
92
93 pub fn new_with_plain_text(source: PlainTextSource) -> Self {
95 Self::new(DocumentSource::PlainText(source))
96 }
97
98 pub fn new_with_content_block(source: ContentBlockSourceParam) -> Self {
100 Self::new(DocumentSource::ContentBlock(source))
101 }
102
103 pub fn new_with_url_pdf(source: UrlPdfSource) -> Self {
105 Self::new(DocumentSource::UrlPdf(source))
106 }
107
108 pub fn with_cache_control(mut self, cache_control: CacheControlEphemeral) -> Self {
110 self.cache_control = Some(cache_control);
111 self
112 }
113
114 pub fn with_citations(mut self, citations: CitationsConfig) -> Self {
116 self.citations = Some(citations);
117 self
118 }
119
120 pub fn with_context(mut self, context: String) -> Self {
122 self.context = Some(context);
123 self
124 }
125
126 pub fn with_title(mut self, title: String) -> Self {
128 self.title = Some(title);
129 self
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use serde_json::{json, to_value};
137
138 #[test]
139 fn document_block_with_base64_pdf() {
140 let base64_source =
141 Base64PdfSource::new("data:application/pdf;base64,JVBERi0xLjcKJeLjz9MKN".to_string());
142
143 let document_block = DocumentBlock::new_with_base64_pdf(base64_source);
144 let json = to_value(&document_block).unwrap();
145
146 assert_eq!(
147 json,
148 json!({
149 "source": {
150 "type": "base64",
151 "data": "data:application/pdf;base64,JVBERi0xLjcKJeLjz9MKN",
152 "media_type": "application/pdf"
153 }
154 })
155 );
156 }
157
158 #[test]
159 fn document_block_with_plain_text() {
160 let text_source = PlainTextSource::new("Sample text content".to_string());
161
162 let document_block = DocumentBlock::new_with_plain_text(text_source);
163 let json = to_value(&document_block).unwrap();
164
165 assert_eq!(
166 json,
167 json!({
168 "source": {
169 "type": "text",
170 "data": "Sample text content",
171 "media_type": "text/plain"
172 }
173 })
174 );
175 }
176
177 #[test]
178 fn document_block_with_content_block() {
179 let content_source = ContentBlockSourceParam::from_string_ref("Sample content");
180
181 let document_block = DocumentBlock::new_with_content_block(content_source);
182 let json = to_value(&document_block).unwrap();
183
184 assert_eq!(
185 json,
186 json!({
187 "source": {
188 "type": "content",
189 "content": "Sample content"
190 }
191 })
192 );
193 }
194
195 #[test]
196 fn document_block_with_url_pdf() {
197 let url_source = UrlPdfSource::new("https://example.com/document.pdf".to_string());
198
199 let document_block = DocumentBlock::new_with_url_pdf(url_source);
200 let json = to_value(&document_block).unwrap();
201
202 assert_eq!(
203 json,
204 json!({
205 "source": {
206 "type": "url",
207 "url": "https://example.com/document.pdf"
208 }
209 })
210 );
211 }
212
213 #[test]
214 fn document_block_with_all_fields() {
215 let url_source = UrlPdfSource::new("https://example.com/document.pdf".to_string());
216 let cache_control = CacheControlEphemeral::new();
217 let citations = CitationsConfig::enabled();
218
219 let document_block = DocumentBlock::new_with_url_pdf(url_source)
220 .with_cache_control(cache_control)
221 .with_citations(citations)
222 .with_context("Document context".to_string())
223 .with_title("Document Title".to_string());
224
225 let json = to_value(&document_block).unwrap();
226
227 assert_eq!(
228 json,
229 json!({
230 "source": {
231 "type": "url",
232 "url": "https://example.com/document.pdf"
233 },
234 "cache_control": {
235 "type": "ephemeral"
236 },
237 "citations": {
238 "enabled": true
239 },
240 "context": "Document context",
241 "title": "Document Title"
242 })
243 );
244 }
245}