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}