replicate_client/models/
file.rs1use bytes::Bytes;
4use serde::{Deserialize, Serialize};
5use std::path::{Path, PathBuf};
6
7#[derive(Debug, Clone)]
9pub enum FileInput {
10 Url(String),
12 Path(PathBuf),
14 Bytes {
16 data: Bytes,
17 filename: Option<String>,
18 content_type: Option<String>,
19 },
20}
21
22impl FileInput {
23 pub fn from_url(url: impl Into<String>) -> Self {
25 Self::Url(url.into())
26 }
27
28 pub fn from_path(path: impl AsRef<Path>) -> Self {
30 Self::Path(path.as_ref().to_path_buf())
31 }
32
33 pub fn from_bytes(data: impl Into<Bytes>) -> Self {
35 Self::Bytes {
36 data: data.into(),
37 filename: None,
38 content_type: None,
39 }
40 }
41
42 pub fn from_bytes_with_metadata(
44 data: impl Into<Bytes>,
45 filename: Option<String>,
46 content_type: Option<String>,
47 ) -> Self {
48 Self::Bytes {
49 data: data.into(),
50 filename,
51 content_type,
52 }
53 }
54
55 pub fn is_url(&self) -> bool {
57 matches!(self, Self::Url(_))
58 }
59
60 pub fn is_path(&self) -> bool {
62 matches!(self, Self::Path(_))
63 }
64
65 pub fn is_bytes(&self) -> bool {
67 matches!(self, Self::Bytes { .. })
68 }
69
70 pub fn as_url(&self) -> Option<&str> {
72 match self {
73 Self::Url(url) => Some(url),
74 _ => None,
75 }
76 }
77
78 pub fn as_path(&self) -> Option<&Path> {
80 match self {
81 Self::Path(path) => Some(path),
82 _ => None,
83 }
84 }
85}
86
87impl From<String> for FileInput {
88 fn from(s: String) -> Self {
89 if s.starts_with("http://") || s.starts_with("https://") {
90 Self::Url(s)
91 } else {
92 Self::Path(PathBuf::from(s))
93 }
94 }
95}
96
97impl From<&str> for FileInput {
98 fn from(s: &str) -> Self {
99 Self::from(s.to_string())
100 }
101}
102
103impl From<PathBuf> for FileInput {
104 fn from(path: PathBuf) -> Self {
105 Self::Path(path)
106 }
107}
108
109impl From<&Path> for FileInput {
110 fn from(path: &Path) -> Self {
111 Self::Path(path.to_path_buf())
112 }
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct FileOutput {
118 pub url: String,
120 pub filename: Option<String>,
122 pub content_type: Option<String>,
124 pub size: Option<u64>,
126}
127
128impl FileOutput {
129 pub fn new(url: impl Into<String>) -> Self {
131 Self {
132 url: url.into(),
133 filename: None,
134 content_type: None,
135 size: None,
136 }
137 }
138
139 pub fn with_filename(mut self, filename: impl Into<String>) -> Self {
141 self.filename = Some(filename.into());
142 self
143 }
144
145 pub fn with_content_type(mut self, content_type: impl Into<String>) -> Self {
147 self.content_type = Some(content_type.into());
148 self
149 }
150
151 pub fn with_size(mut self, size: u64) -> Self {
153 self.size = Some(size);
154 self
155 }
156
157 pub async fn download(&self) -> crate::Result<Bytes> {
159 let response = reqwest::get(&self.url).await?;
160 let bytes = response.bytes().await?;
161 Ok(bytes)
162 }
163
164 pub async fn save_to_path(&self, path: impl AsRef<Path>) -> crate::Result<()> {
166 let bytes = self.download().await?;
167 tokio::fs::write(path, bytes).await?;
168 Ok(())
169 }
170}
171
172impl From<String> for FileOutput {
173 fn from(url: String) -> Self {
174 Self::new(url)
175 }
176}
177
178impl From<&str> for FileOutput {
179 fn from(url: &str) -> Self {
180 Self::new(url)
181 }
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize)]
186#[serde(rename_all = "snake_case")]
187pub enum FileEncodingStrategy {
188 Base64DataUrl,
190 Multipart,
192}
193
194impl Default for FileEncodingStrategy {
195 fn default() -> Self {
196 Self::Multipart
197 }
198}