claude_api/files/
types.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7#[non_exhaustive]
8pub struct FileMetadata {
9 pub id: String,
11 #[serde(rename = "type", default = "default_file_kind")]
13 pub kind: String,
14 pub filename: String,
16 pub mime_type: String,
18 pub size_bytes: u64,
20 pub created_at: String,
22 #[serde(default)]
25 pub downloadable: bool,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
29 pub scope: Option<FileScope>,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
37#[non_exhaustive]
38pub struct FileScope {
39 #[serde(rename = "type")]
41 pub kind: String,
42 pub id: String,
44}
45
46fn default_file_kind() -> String {
47 "file".to_owned()
48}
49
50#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
52#[non_exhaustive]
53pub struct FileDeleted {
54 pub id: String,
56 #[serde(rename = "type", default)]
58 pub kind: String,
59}
60
61#[derive(Debug, Clone, Default, Serialize)]
63#[non_exhaustive]
64pub struct ListFilesParams {
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub before_id: Option<String>,
68 #[serde(skip_serializing_if = "Option::is_none")]
70 pub after_id: Option<String>,
71 #[serde(skip_serializing_if = "Option::is_none")]
73 pub limit: Option<u32>,
74}
75
76impl ListFilesParams {
77 #[must_use]
79 pub fn after_id(mut self, id: impl Into<String>) -> Self {
80 self.after_id = Some(id.into());
81 self
82 }
83
84 #[must_use]
86 pub fn before_id(mut self, id: impl Into<String>) -> Self {
87 self.before_id = Some(id.into());
88 self
89 }
90
91 #[must_use]
93 pub fn limit(mut self, limit: u32) -> Self {
94 self.limit = Some(limit);
95 self
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use pretty_assertions::assert_eq;
103 use serde_json::json;
104
105 #[test]
106 fn file_metadata_round_trips() {
107 let raw = json!({
108 "id": "file_011ABC",
109 "type": "file",
110 "filename": "report.pdf",
111 "mime_type": "application/pdf",
112 "size_bytes": 12345,
113 "created_at": "2026-04-30T00:00:00Z",
114 "downloadable": true
115 });
116 let parsed: FileMetadata = serde_json::from_value(raw.clone()).unwrap();
117 assert_eq!(parsed.id, "file_011ABC");
118 assert_eq!(parsed.kind, "file");
119 assert_eq!(parsed.filename, "report.pdf");
120 assert_eq!(parsed.size_bytes, 12345);
121 assert!(parsed.downloadable);
122 assert_eq!(serde_json::to_value(&parsed).unwrap(), raw);
123 }
124
125 #[test]
126 fn file_metadata_kind_defaults_when_missing() {
127 let raw = json!({
128 "id": "file_X",
129 "filename": "x.txt",
130 "mime_type": "text/plain",
131 "size_bytes": 1,
132 "created_at": "2026"
133 });
134 let parsed: FileMetadata = serde_json::from_value(raw).unwrap();
135 assert_eq!(parsed.kind, "file");
136 }
137
138 #[test]
139 fn file_deleted_round_trips() {
140 let raw = json!({"id": "file_X", "type": "file_deleted"});
141 let parsed: FileDeleted = serde_json::from_value(raw).unwrap();
142 assert_eq!(parsed.id, "file_X");
143 assert_eq!(parsed.kind, "file_deleted");
144 }
145}