systemprompt_files/models/
metadata.rs1use serde::{Deserialize, Serialize};
15
16use systemprompt_traits::ImageMetadata;
17
18#[derive(Debug, Clone, Default, Serialize, Deserialize)]
19pub struct FileMetadata {
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub checksums: Option<FileChecksums>,
22
23 #[serde(default, skip_serializing_if = "Option::is_none")]
24 pub type_specific: Option<TypeSpecificMetadata>,
25
26 #[serde(flatten)]
27 pub extra: serde_json::Map<String, serde_json::Value>,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32#[serde(tag = "type", rename_all = "snake_case")]
33pub enum TypeSpecificMetadata {
34 Image(ImageMetadata),
35 Document(DocumentMetadata),
36 Audio(AudioMetadata),
37 Video(VideoMetadata),
38}
39
40#[derive(Debug, Clone, Default, Serialize, Deserialize)]
41pub struct DocumentMetadata {
42 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub title: Option<String>,
44
45 #[serde(default, skip_serializing_if = "Option::is_none")]
46 pub author: Option<String>,
47
48 #[serde(default, skip_serializing_if = "Option::is_none")]
49 pub page_count: Option<u32>,
50}
51
52#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
53pub struct AudioMetadata {
54 #[serde(default, skip_serializing_if = "Option::is_none")]
55 pub duration_seconds: Option<f32>,
56
57 #[serde(default, skip_serializing_if = "Option::is_none")]
58 pub sample_rate: Option<u32>,
59
60 #[serde(default, skip_serializing_if = "Option::is_none")]
61 pub channels: Option<u8>,
62}
63
64#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
65pub struct VideoMetadata {
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 pub width: Option<u32>,
68
69 #[serde(default, skip_serializing_if = "Option::is_none")]
70 pub height: Option<u32>,
71
72 #[serde(default, skip_serializing_if = "Option::is_none")]
73 pub duration_seconds: Option<f32>,
74
75 #[serde(default, skip_serializing_if = "Option::is_none")]
76 pub frame_rate: Option<f32>,
77}
78
79#[derive(Debug, Clone, Default, Serialize, Deserialize)]
80pub struct FileChecksums {
81 #[serde(default, skip_serializing_if = "Option::is_none")]
82 pub md5: Option<String>,
83
84 #[serde(default, skip_serializing_if = "Option::is_none")]
85 pub sha256: Option<String>,
86}
87
88impl FileMetadata {
89 pub fn new() -> Self {
90 Self::default()
91 }
92
93 pub fn with_image(mut self, image: ImageMetadata) -> Self {
94 self.type_specific = Some(TypeSpecificMetadata::Image(image));
95 self
96 }
97
98 pub fn with_document(mut self, doc: DocumentMetadata) -> Self {
99 self.type_specific = Some(TypeSpecificMetadata::Document(doc));
100 self
101 }
102
103 pub fn with_audio(mut self, audio: AudioMetadata) -> Self {
104 self.type_specific = Some(TypeSpecificMetadata::Audio(audio));
105 self
106 }
107
108 pub fn with_video(mut self, video: VideoMetadata) -> Self {
109 self.type_specific = Some(TypeSpecificMetadata::Video(video));
110 self
111 }
112
113 pub fn with_checksums(mut self, checksums: FileChecksums) -> Self {
114 self.checksums = Some(checksums);
115 self
116 }
117}
118
119impl DocumentMetadata {
120 pub const fn new() -> Self {
121 Self {
122 title: None,
123 author: None,
124 page_count: None,
125 }
126 }
127
128 pub fn with_title(mut self, title: impl Into<String>) -> Self {
129 self.title = Some(title.into());
130 self
131 }
132
133 pub fn with_author(mut self, author: impl Into<String>) -> Self {
134 self.author = Some(author.into());
135 self
136 }
137
138 pub const fn with_page_count(mut self, page_count: u32) -> Self {
139 self.page_count = Some(page_count);
140 self
141 }
142}
143
144impl AudioMetadata {
145 pub const fn new() -> Self {
146 Self {
147 duration_seconds: None,
148 sample_rate: None,
149 channels: None,
150 }
151 }
152
153 pub const fn with_duration_seconds(mut self, duration: f32) -> Self {
154 self.duration_seconds = Some(duration);
155 self
156 }
157
158 pub const fn with_sample_rate(mut self, sample_rate: u32) -> Self {
159 self.sample_rate = Some(sample_rate);
160 self
161 }
162
163 pub const fn with_channels(mut self, channels: u8) -> Self {
164 self.channels = Some(channels);
165 self
166 }
167}
168
169impl VideoMetadata {
170 pub const fn new() -> Self {
171 Self {
172 width: None,
173 height: None,
174 duration_seconds: None,
175 frame_rate: None,
176 }
177 }
178
179 pub const fn with_dimensions(mut self, width: u32, height: u32) -> Self {
180 self.width = Some(width);
181 self.height = Some(height);
182 self
183 }
184
185 pub const fn with_duration_seconds(mut self, duration: f32) -> Self {
186 self.duration_seconds = Some(duration);
187 self
188 }
189
190 pub const fn with_frame_rate(mut self, frame_rate: f32) -> Self {
191 self.frame_rate = Some(frame_rate);
192 self
193 }
194}
195
196impl FileChecksums {
197 pub const fn new() -> Self {
198 Self {
199 md5: None,
200 sha256: None,
201 }
202 }
203
204 pub fn with_md5(mut self, md5: impl Into<String>) -> Self {
205 self.md5 = Some(md5.into());
206 self
207 }
208
209 pub fn with_sha256(mut self, sha256: impl Into<String>) -> Self {
210 self.sha256 = Some(sha256.into());
211 self
212 }
213}