1use serde::{Deserialize, Serialize};
7use strum::AsRefStr;
8use time::OffsetDateTime;
9
10use crate::common::serde::{
11 deserialize_optional_string_to_i64, deserialize_string_to_i64, mime_as_string,
12};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
19#[serde(rename_all = "camelCase")]
20pub struct FileSearchStore {
21 pub name: String,
23
24 #[serde(skip_serializing_if = "Option::is_none")]
26 pub display_name: Option<String>,
27
28 #[serde(with = "time::serde::rfc3339")]
30 pub create_time: OffsetDateTime,
31
32 #[serde(with = "time::serde::rfc3339")]
34 pub update_time: OffsetDateTime,
35
36 #[serde(
38 default,
39 skip_serializing_if = "Option::is_none",
40 deserialize_with = "deserialize_optional_string_to_i64"
41 )]
42 pub active_documents_count: Option<i64>,
43
44 #[serde(
46 default,
47 skip_serializing_if = "Option::is_none",
48 deserialize_with = "deserialize_optional_string_to_i64"
49 )]
50 pub pending_documents_count: Option<i64>,
51
52 #[serde(
54 default,
55 skip_serializing_if = "Option::is_none",
56 deserialize_with = "deserialize_optional_string_to_i64"
57 )]
58 pub failed_documents_count: Option<i64>,
59
60 #[serde(
62 default,
63 skip_serializing_if = "Option::is_none",
64 deserialize_with = "deserialize_optional_string_to_i64"
65 )]
66 pub size_bytes: Option<i64>,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70#[serde(rename_all = "camelCase")]
71pub struct CreateFileSearchStoreRequest {
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub display_name: Option<String>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
80#[serde(rename_all = "camelCase")]
81pub struct Document {
82 pub name: String,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
87 pub display_name: Option<String>,
88
89 #[serde(skip_serializing_if = "Option::is_none")]
91 pub custom_metadata: Option<Vec<CustomMetadata>>,
92
93 #[serde(with = "time::serde::rfc3339")]
95 pub update_time: OffsetDateTime,
96
97 #[serde(with = "time::serde::rfc3339")]
99 pub create_time: OffsetDateTime,
100
101 pub state: DocumentState,
103
104 #[serde(deserialize_with = "deserialize_string_to_i64")]
106 pub size_bytes: i64,
107
108 #[serde(with = "mime_as_string")]
110 pub mime_type: mime::Mime,
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, AsRefStr)]
115#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
116#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
117pub enum DocumentState {
118 StateUnspecified,
120 StatePending,
122 StateActive,
124 StateFailed,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
133#[serde(rename_all = "camelCase")]
134pub struct CustomMetadata {
135 pub key: String,
137 #[serde(flatten)]
139 pub value: CustomMetadataValue,
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize)]
143#[serde(untagged)]
144pub enum CustomMetadataValue {
145 StringValue { string_value: String },
146 StringListValue { string_list_value: StringList },
147 NumericValue { numeric_value: f64 },
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct StringList {
152 pub values: Vec<String>,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
159#[serde(rename_all = "camelCase")]
160pub struct ChunkingConfig {
161 #[serde(skip_serializing_if = "Option::is_none")]
163 pub white_space_config: Option<WhiteSpaceConfig>,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
167#[serde(rename_all = "camelCase")]
168pub struct WhiteSpaceConfig {
169 pub max_tokens_per_chunk: u32,
171
172 pub max_overlap_tokens: u32,
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
181#[serde(rename_all = "camelCase")]
182pub struct Operation {
183 pub name: String,
185
186 #[serde(skip_serializing_if = "Option::is_none")]
188 pub metadata: Option<serde_json::Value>,
189
190 #[serde(default, skip_serializing_if = "Option::is_none")]
192 pub done: Option<bool>,
193
194 #[serde(flatten)]
196 pub result: Option<OperationResult>,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
200#[serde(untagged)]
201pub enum OperationResult {
202 Error { error: Status },
203 Response { response: serde_json::Value },
204}
205
206#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct Status {
208 pub code: i32,
209 pub message: String,
210 #[serde(skip_serializing_if = "Option::is_none")]
211 pub details: Option<Vec<serde_json::Value>>,
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize)]
215#[serde(rename_all = "camelCase")]
216pub struct UploadToFileSearchStoreRequest {
217 #[serde(skip_serializing_if = "Option::is_none")]
218 pub display_name: Option<String>,
219
220 #[serde(skip_serializing_if = "Option::is_none")]
221 pub custom_metadata: Option<Vec<CustomMetadata>>,
222
223 #[serde(skip_serializing_if = "Option::is_none")]
224 pub chunking_config: Option<ChunkingConfig>,
225
226 #[serde(
227 with = "mime_as_string::optional",
228 skip_serializing_if = "Option::is_none"
229 )]
230 pub mime_type: Option<mime::Mime>,
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
234#[serde(rename_all = "camelCase")]
235pub struct ImportFileRequest {
236 pub file_name: String,
238
239 #[serde(skip_serializing_if = "Option::is_none")]
240 pub custom_metadata: Option<Vec<CustomMetadata>>,
241
242 #[serde(skip_serializing_if = "Option::is_none")]
243 pub chunking_config: Option<ChunkingConfig>,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
247#[serde(rename_all = "camelCase")]
248pub struct ListFileSearchStoresResponse {
249 pub file_search_stores: Vec<FileSearchStore>,
250
251 #[serde(skip_serializing_if = "Option::is_none")]
252 pub next_page_token: Option<String>,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
256#[serde(rename_all = "camelCase")]
257pub struct ListDocumentsResponse {
258 pub documents: Vec<Document>,
259
260 #[serde(skip_serializing_if = "Option::is_none")]
261 pub next_page_token: Option<String>,
262}
263
264pub fn extract_store_name(full_name: &str) -> Result<String, crate::client::Error> {
265 let mut parts = full_name.split('/');
267 if parts.next() == Some("fileSearchStores") {
268 if let Some(store_id) = parts.next() {
269 return Ok(format!("fileSearchStores/{}", store_id));
270 }
271 }
272 Err(crate::client::Error::InvalidResourceName {
273 name: full_name.to_string(),
274 })
275}
276
277pub fn extract_document_id(full_name: &str) -> Result<String, crate::client::Error> {
278 let mut parts = full_name.split('/');
280 if parts.next() == Some("fileSearchStores") {
281 if let Some(_store) = parts.next() {
282 if parts.next() == Some("documents") {
283 if let Some(doc_id) = parts.next() {
284 return Ok(doc_id.to_string());
285 }
286 }
287 }
288 }
289 Err(crate::client::Error::InvalidResourceName {
290 name: full_name.to_string(),
291 })
292}