graph_http/core/file_config.rs
1use bytes::BytesMut;
2use graph_error::GraphFailure;
3use std::ffi::{OsStr, OsString};
4use std::io::Read;
5use std::path::{Path, PathBuf};
6
7/// Config for downloading files using Microsoft Graph File and OneDrive APIs.
8/// FileConfig can also be used for uploads but all fields except for the provided
9/// path are ignored.
10///
11/// # Example
12/// ```rust
13/// use std::ffi::{OsStr, OsString};
14/// use std::path::Path;
15/// use graph_http::api_impl::FileConfig;
16///
17/// let config = FileConfig::new("./examples")
18/// .file_name(OsStr::new("example.json"));
19///
20/// # assert_eq!(Path::new("./examples"), config.path.as_path());
21/// # assert!(config.create_directory_all);
22/// # assert_eq!(Some(&OsString::from("example.json")), config.file_name.as_ref());
23/// ```
24///
25/// # Example
26/// ```rust
27/// use std::ffi::{OsStr, OsString};
28/// use std::path::Path;
29/// use graph_http::api_impl::FileConfig;
30///
31/// let config = FileConfig::new("./examples")
32/// .overwrite_existing_file(true)
33/// .extension(OsStr::new("pdf"));
34///
35/// # assert_eq!(Path::new("./examples"), config.path.as_path());
36/// # assert!(config.overwrite_existing_file);
37/// # assert_eq!(Some(&OsString::from("pdf")), config.extension.as_ref());
38/// ```
39#[derive(Clone, Debug, Default)]
40pub struct FileConfig {
41 pub path: PathBuf,
42 /// Used only when downloading files. Default is true.
43 pub create_directory_all: bool,
44 /// Used only when downloading files
45 pub overwrite_existing_file: bool,
46 /// Used only when downloading files
47 pub file_name: Option<OsString>,
48 /// Used only when downloading files
49 pub extension: Option<OsString>,
50}
51
52impl FileConfig {
53 /// Create the file configuration for downloading files.
54 ///
55 /// # Example
56 /// ```rust
57 /// use std::ffi::{OsStr, OsString};
58 /// use std::path::Path;
59 /// use graph_http::api_impl::FileConfig;
60 ///
61 /// let config = FileConfig::new("./examples")
62 /// .create_directories(true)
63 /// .file_name(OsStr::new("example.json"));
64 ///
65 /// # assert_eq!(Path::new("./examples"), config.path.as_path());
66 /// # assert!(config.create_directory_all);
67 /// # assert_eq!(Some(&OsString::from("example.json")), config.file_name.as_ref());
68 /// ```
69 ///
70 /// # Example
71 /// ```rust
72 /// use std::ffi::{OsStr, OsString};
73 /// use std::path::Path;
74 /// use graph_http::api_impl::FileConfig;
75 ///
76 /// let config = FileConfig::new("./examples")
77 /// .overwrite_existing_file(true)
78 /// .extension(OsStr::new("pdf"));
79 ///
80 /// # assert_eq!(Path::new("./examples"), config.path.as_path());
81 /// # assert!(config.overwrite_existing_file);
82 /// # assert_eq!(Some(&OsString::from("pdf")), config.extension.as_ref());
83 /// ```
84 pub fn new<P: AsRef<Path>>(path: P) -> FileConfig {
85 FileConfig {
86 path: path.as_ref().to_path_buf(),
87 create_directory_all: true,
88 overwrite_existing_file: false,
89 file_name: None,
90 extension: None,
91 }
92 }
93
94 /// Create all directories in the path given if they do not exist.
95 ///
96 /// # Example
97 /// ```rust
98 /// use graph_http::api_impl::FileConfig;
99 ///
100 /// let config = FileConfig::new("./examples")
101 /// .create_directories(true);
102 ///
103 /// # assert!(config.create_directory_all);
104 /// ```
105 pub fn create_directories(mut self, create_directories: bool) -> FileConfig {
106 self.create_directory_all = create_directories;
107 self
108 }
109
110 /// Overwrite an existing file of the same file name and path.
111 /// This is true by default.
112 ///
113 /// # Example
114 /// ```rust
115 /// use graph_http::api_impl::FileConfig;
116 ///
117 /// let config = FileConfig::new("./examples")
118 /// .overwrite_existing_file(true);
119 ///
120 /// # assert!(config.overwrite_existing_file);
121 /// ```
122 pub fn overwrite_existing_file(mut self, overwrite_file: bool) -> FileConfig {
123 self.overwrite_existing_file = overwrite_file;
124 self
125 }
126
127 /// Set the file name and extension. If you use the format ODataQuery to change
128 /// the file type such as from JSON to PDF then you must provide a name for the
129 /// file or the download will fail.
130 ///
131 /// # Example
132 /// ```rust
133 /// use std::ffi::{OsStr, OsString};
134 /// use graph_http::api_impl::FileConfig;
135 ///
136 /// let config = FileConfig::new("./examples")
137 /// .file_name(OsStr::new("example.pdf"));
138 ///
139 /// # assert_eq!(Some(&OsString::from("example.pdf")), config.file_name.as_ref());
140 /// ```
141 pub fn file_name(mut self, file_name: &OsStr) -> FileConfig {
142 self.file_name = Some(file_name.to_os_string());
143 self
144 }
145
146 /// Set the extension of the file being downloaded. This only changes the extension name
147 /// of the file and does not change the format of the file. You can change the format of
148 /// the file using the ODataQuery format method such as changing from JSONto PDF
149 ///
150 /// # Example
151 /// ```rust
152 /// use std::ffi::{OsStr, OsString};
153 /// use graph_http::api_impl::FileConfig;
154 ///
155 /// let config = FileConfig::new("./examples")
156 /// .extension(OsStr::new("pdf"));
157 ///
158 /// # assert_eq!(Some(&OsString::from("pdf")), config.extension.as_ref());
159 /// ```
160 pub fn extension(mut self, ext: &OsStr) -> FileConfig {
161 self.extension = Some(ext.to_os_string());
162 self
163 }
164
165 /// Create all directories in the path if they do not exist.
166 ///
167 /// # Example
168 /// ```rust
169 /// use std::path::Path;
170 /// use graph_http::api_impl::FileConfig;
171 ///
172 /// let mut config = FileConfig::default();
173 /// config.set_path("./examples");
174 ///
175 /// # assert_eq!(Path::new("./examples"), config.path.as_path())
176 /// ```
177 pub fn set_path<P: AsRef<Path>>(&mut self, path: P) {
178 self.path = path.as_ref().to_path_buf();
179 }
180
181 /// Create all directories in the path given if they do not exist.
182 ///
183 /// # Example
184 /// ```
185 /// use graph_http::api_impl::FileConfig;
186 ///
187 /// let mut config = FileConfig::new("./examples");
188 /// config.set_create_directories(true);
189 ///
190 /// # assert!(config.create_directory_all);
191 /// ```
192 pub fn set_create_directories(&mut self, create_directories: bool) {
193 self.create_directory_all = create_directories;
194 }
195
196 /// Overwrite an existing file of the same file name and path.
197 ///
198 /// # Example
199 /// ```rust
200 /// use graph_http::api_impl::FileConfig;
201 ///
202 /// let mut config = FileConfig::new("./examples");
203 /// config.set_overwrite_existing_file(true);
204 ///
205 /// # assert!(config.overwrite_existing_file);
206 /// ```
207 pub fn set_overwrite_existing_file(&mut self, overwrite_file: bool) {
208 self.overwrite_existing_file = overwrite_file;
209 }
210
211 /// Set the file name and extension. If you use the format ODataQuery to change
212 /// the file type such as from JSON to PDF then you must provide a name for the
213 /// file or the download will fail.
214 ///
215 /// # Example
216 /// ```rust
217 /// use std::ffi::{OsStr, OsString};
218 /// use graph_http::api_impl::FileConfig;
219 ///
220 /// let mut config = FileConfig::new("./examples");
221 /// config.set_file_name(OsStr::new("example.pdf"));
222 ///
223 /// # assert_eq!(Some(&OsString::from("example.pdf")), config.file_name.as_ref());
224 /// ```
225 pub fn set_file_name(&mut self, file_name: &OsStr) {
226 self.file_name = Some(file_name.to_os_string());
227 }
228
229 /// Set the extension of the file being downloaded. This only changes the extension name
230 /// of the file and does not change the format of the file. You can change the format of
231 /// the file using the ODataQuery format method such as changing from JSONto PDF
232 ///
233 /// # Example
234 /// ```rust
235 /// use std::ffi::{OsStr, OsString};
236 /// use graph_http::api_impl::FileConfig;
237 ///
238 /// let mut config = FileConfig::new("./examples")
239 /// .extension(OsStr::new("pdf"));
240 ///
241 /// # assert_eq!(Some(&OsString::from("pdf")), config.extension.as_ref());
242 /// ```
243 pub fn set_extension(&mut self, ext: &OsStr) {
244 self.extension = Some(ext.to_os_string());
245 }
246}
247
248impl From<PathBuf> for FileConfig {
249 fn from(path_buf: PathBuf) -> Self {
250 FileConfig::new(path_buf.as_path())
251 }
252}
253
254impl From<&Path> for FileConfig {
255 fn from(path: &Path) -> Self {
256 FileConfig::new(path)
257 }
258}
259
260impl TryFrom<FileConfig> for BytesMut {
261 type Error = GraphFailure;
262
263 fn try_from(file_config: FileConfig) -> Result<Self, Self::Error> {
264 let mut file = std::fs::File::open(file_config.path.as_path())?;
265 let mut buf: Vec<u8> = Vec::new();
266 file.read_to_end(&mut buf)?;
267 Ok(BytesMut::from_iter(buf))
268 }
269}