gemini_rust/file_search/
upload_builder.rs

1use mime::Mime;
2use std::sync::Arc;
3use tracing::instrument;
4
5use crate::client::{Error, GeminiClient};
6use crate::file_search::model::{ChunkingConfig, CustomMetadata};
7use crate::file_search::OperationHandle;
8
9/// Builder for uploading files directly to a file search store.
10///
11/// This uploads file data and processes it in one step. The file is chunked,
12/// embedded, and indexed. A temporary file reference is created but deleted
13/// after 48 hours, while the indexed data persists in the store.
14///
15/// # Example
16///
17/// ```no_run
18/// use gemini_rust::prelude::*;
19/// use mime::TEXT_PLAIN;
20/// # async fn example(store: FileSearchStoreHandle) -> Result<(), Box<dyn std::error::Error>> {
21/// let data = b"Document content here";
22/// let mut operation = store
23///     .upload(data.to_vec())
24///     .with_display_name("My Document")
25///     .with_mime_type(TEXT_PLAIN)
26///     .execute()
27///     .await?;
28///
29/// // Wait for processing
30/// operation.wait_until_done(
31///     std::time::Duration::from_secs(5),
32///     Some(std::time::Duration::from_secs(60))
33/// ).await?;
34/// # Ok(())
35/// # }
36/// ```
37pub struct UploadBuilder {
38    pub(crate) client: Arc<GeminiClient>,
39    pub(crate) store_name: String,
40    pub(crate) file_data: Vec<u8>,
41    pub(crate) display_name: Option<String>,
42    pub(crate) mime_type: Option<Mime>,
43    pub(crate) custom_metadata: Option<Vec<CustomMetadata>>,
44    pub(crate) chunking_config: Option<ChunkingConfig>,
45}
46
47impl UploadBuilder {
48    pub fn with_display_name(mut self, name: impl Into<String>) -> Self {
49        self.display_name = Some(name.into());
50        self
51    }
52
53    pub fn with_mime_type(mut self, mime_type: Mime) -> Self {
54        self.mime_type = Some(mime_type);
55        self
56    }
57
58    pub fn with_custom_metadata(mut self, metadata: Vec<CustomMetadata>) -> Self {
59        self.custom_metadata = Some(metadata);
60        self
61    }
62
63    pub fn with_chunking_config(mut self, config: ChunkingConfig) -> Self {
64        self.chunking_config = Some(config);
65        self
66    }
67
68    #[instrument(skip_all, fields(
69        store.name = %self.store_name,
70        file.size = self.file_data.len(),
71        display_name = self.display_name.as_deref(),
72        mime.type = self.mime_type.as_ref().map(|m| m.to_string()),
73        metadata.present = self.custom_metadata.is_some(),
74        chunking.present = self.chunking_config.is_some(),
75    ))]
76    pub async fn execute(self) -> Result<OperationHandle, Error> {
77        let operation = self
78            .client
79            .upload_to_file_search_store(
80                &self.store_name,
81                self.file_data,
82                self.display_name,
83                self.mime_type,
84                self.custom_metadata,
85                self.chunking_config,
86            )
87            .await?;
88
89        Ok(OperationHandle::new(self.client, operation))
90    }
91}