onedrive_api/resource.rs
1//! Resource Objects defined in the OneDrive API.
2//!
3//! # Field descriptors
4//!
5//! Resource object `struct`s have field descriper `enum`s representing
6//! all controllable fields of it, which may be used
7//! in [`onedrive_api::option`][option] to [`select`][select] or [`expand`][expand] it using
8//! `with_option` version API of [`OneDrive`][one_drive].
9//!
10//! ## Example
11//! Here is an example to use [`resource::DriveItemField`][drive_item_field].
12//! ```
13//! use onedrive_api::{OneDrive, ItemLocation, option::ObjectOption};
14//! use onedrive_api::resource::*;
15//!
16//! # async fn run(drive: &OneDrive) -> onedrive_api::Result<()> {
17//! // let drive: OneDrive;
18//! let item: Option<DriveItem> = drive
19//! .get_item_with_option(
20//! ItemLocation::root(),
21//! ObjectOption::new()
22//! .if_none_match(&Tag("<abcdABCD1234>".to_owned()))
23//! // Only response `id` and `e_tag` to reduce data transmission.
24//! .select(&[DriveItemField::id, DriveItemField::e_tag]),
25//! )
26//! .await?;
27//! match item {
28//! None => println!("Tag matched"),
29//! Some(item) => {
30//! println!("id: {:?}, e_tag: {:?}", item.id.unwrap(), item.e_tag.unwrap());
31//! }
32//! }
33//! # Ok(())
34//! # }
35//! ```
36//!
37//! # See also
38//! [Microsoft Docs](https://docs.microsoft.com/en-us/onedrive/developer/rest-api/resources/?view=odsp-graph-online)
39//!
40//! [option]: ../option/index.html
41//! [select]: ../option/struct.ObjectOption.html#method.select
42//! [expand]: ../option/struct.ObjectOption.html#method.expand
43//! [one_drive]: ../struct.OneDrive.html
44//! [drive_item_field]: ./enum.DriveItemField.html
45use serde::{Deserialize, Serialize};
46
47/// A semantic alias for URL string in resource objects.
48pub type Url = String;
49
50/// Boxed raw json value.
51pub type JsonValue = Box<serde_json::Value>;
52
53/// Timestamp string with ISO 8601 format.
54pub type TimestampString = String;
55
56macro_rules! define_string_wrapper {
57 ($($(#[$meta:meta])* $vis:vis $name:ident;)*) => { $(
58 $(#[$meta])*
59 #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
60 $vis struct $name(pub String);
61
62 impl $name {
63 /// View as str.
64 #[inline]
65 #[must_use]
66 pub fn as_str(&self) -> &str {
67 &self.0
68 }
69 }
70 )* };
71}
72
73define_string_wrapper! {
74 /// Wrapper for a unique identifier to a `Drive`.
75 ///
76 /// # See also
77 /// [Microsoft Docs: Drive resource type](https://docs.microsoft.com/en-us/graph/api/resources/drive?view=graph-rest-1.0)
78 pub DriveId;
79
80 /// Wrapper for a unique identifier for a `DriveItem`.
81 ///
82 /// # See also
83 /// [Microsoft Docs: driveItem resource type](https://docs.microsoft.com/en-us/graph/api/resources/driveitem?view=graph-rest-1.0)
84 pub ItemId;
85
86 /// Wrapper for a tag representing the state of an item.
87 ///
88 /// Used for avoid data transmission when a resource is not modified.
89 ///
90 /// The tag from [`DriveItem::c_tag`][c_tag] is for the content of the item,
91 /// while the one from [`DriveItem::e_tag`][e_tag] is for the entire item (metadata + content).
92 ///
93 /// # See also
94 /// [Microsoft Docs: driveItem resource type](https://docs.microsoft.com/en-us/graph/api/resources/driveitem?view=graph-rest-1.0)
95 ///
96 /// [e_tag]: ./struct.DriveItem.html#structfield.e_tag
97 /// [c_tag]: ./struct.DriveItem.html#structfield.c_tag
98 pub Tag;
99}
100
101// Used for generalization over any resource field enums in `option`.
102#[doc(hidden)]
103#[allow(clippy::module_name_repetitions)] // Internal trait.
104pub trait ResourceField: Copy {
105 fn __raw_name(self) -> &'static str;
106}
107
108macro_rules! define_resource_object {
109 ($(
110 $(#[$meta:meta])*
111 $vis:vis struct $struct_name:ident #$field_enum_name:ident {
112 $(
113 $(#[$field_meta:meta])*
114 pub $field_name:ident
115 $(@$field_rename:literal)?
116 : Option<$field_ty:ty>,
117 )*
118 }
119 )*) => {
120 $(
121 $(#[$meta])*
122 #[derive(Debug, Default, Clone, Deserialize, Serialize)]
123 #[serde(rename_all = "camelCase")]
124 #[non_exhaustive]
125 $vis struct $struct_name {
126 $(
127 #[allow(missing_docs)]
128 #[serde(skip_serializing_if="Option::is_none")]
129 $(#[$field_meta])*
130 $(#[serde(rename = $field_rename)])?
131 pub $field_name: Option<$field_ty>,
132 )*
133 }
134
135 /// Fields descriptors.
136 ///
137 /// More details in [mod documentation][mod].
138 ///
139 /// [mod]: ./index.html
140 #[derive(Debug, Clone, Copy, Eq, PartialEq, strum::VariantNames)]
141 #[strum(serialize_all = "camelCase")]
142 #[non_exhaustive]
143 #[allow(missing_docs, non_camel_case_types)]
144 $vis enum $field_enum_name {
145 $(
146 $(#[strum(serialize = $field_rename)])?
147 $field_name,
148 )*
149 }
150
151 impl $field_enum_name {
152 /// Get the raw camelCase name of the field.
153 #[must_use]
154 pub fn raw_name(self) -> &'static str {
155 <Self as strum::VariantNames>::VARIANTS[self as usize]
156 }
157 }
158
159 impl ResourceField for $field_enum_name {
160 #[inline]
161 fn __raw_name(self) -> &'static str {
162 self.raw_name()
163 }
164 }
165
166 )*
167 };
168}
169
170define_resource_object! {
171 /// Drive resource type
172 ///
173 /// The drive resource is the top level object representing a user's OneDrive
174 /// or a document library in SharePoint.
175 ///
176 /// # See also
177 /// [Microsoft Docs](https://docs.microsoft.com/en-us/graph/api/resources/drive?view=graph-rest-1.0)
178 pub struct Drive #DriveField {
179 pub id: Option<DriveId>,
180 pub created_by: Option<JsonValue>,
181 pub created_date_time: Option<TimestampString>,
182 pub description: Option<String>,
183 pub drive_type: Option<JsonValue>,
184 pub items: Option<Vec<DriveItem>>,
185 pub last_modified_by: Option<JsonValue>,
186 pub last_modified_date_time: Option<TimestampString>,
187 pub name: Option<String>,
188 pub owner: Option<JsonValue>,
189 pub quota: Option<JsonValue>,
190 pub root: Option<DriveItem>,
191 pub sharepoint_ids: Option<JsonValue>,
192 pub special: Option<Vec<DriveItem>>,
193 pub system: Option<JsonValue>,
194 pub web_url: Option<Url>,
195 }
196
197 /// DriveItem resource type
198 ///
199 /// The `DriveItem` resource represents a file, folder, or other item stored in a drive.
200 /// All file system objects in OneDrive and SharePoint are returned as `DriveItem` resources.
201 ///
202 /// # See also
203 /// [Microsoft Docs](https://docs.microsoft.com/en-us/graph/api/resources/driveitem?view=graph-rest-1.0)
204 pub struct DriveItem #DriveItemField {
205
206 // Drive item
207
208 pub audio: Option<JsonValue>,
209 pub bundle: Option<JsonValue>,
210 pub content: Option<JsonValue>,
211 pub c_tag: Option<Tag>,
212 pub deleted: Option<JsonValue>,
213 pub description: Option<String>,
214 pub file: Option<JsonValue>,
215 pub file_system_info: Option<JsonValue>,
216 pub folder: Option<JsonValue>,
217 pub image: Option<JsonValue>,
218 pub location: Option<JsonValue>,
219 pub package: Option<JsonValue>,
220 pub photo: Option<JsonValue>,
221 pub publication: Option<JsonValue>,
222 pub remote_item: Option<JsonValue>,
223 pub root: Option<JsonValue>,
224 pub search_result: Option<JsonValue>,
225 pub shared: Option<JsonValue>,
226 pub sharepoint_ids: Option<JsonValue>,
227 pub size: Option<i64>,
228 pub special_folder: Option<JsonValue>,
229 pub video: Option<JsonValue>,
230 pub web_dav_url: Option<Url>,
231
232 // Relationships
233
234 pub children: Option<Vec<DriveItem>>,
235 pub created_by_user: Option<JsonValue>,
236 pub last_modified_by_user: Option<JsonValue>,
237 pub permissions: Option<JsonValue>,
238 pub thumbnails: Option<JsonValue>,
239 pub versions: Option<JsonValue>,
240
241 // Base item
242
243 pub id: Option<ItemId>,
244 pub created_by: Option<JsonValue>,
245 pub created_date_time: Option<TimestampString>,
246 pub e_tag: Option<Tag>,
247 pub last_modified_by: Option<JsonValue>,
248 pub last_modified_date_time: Option<TimestampString>,
249 pub name: Option<String>,
250 pub parent_reference: Option<JsonValue>,
251 pub web_url: Option<Url>,
252
253 // Instance annotations
254
255 // `@microsoft.graph.conflictBehavior` is write-only.
256
257 /// The pre-authorized url for downloading the content.
258 ///
259 /// It is **NOT** selectable through [`ObjectOption::select`][select] and
260 /// only provided in the result of [`OneDrive::get_item`][get_item]
261 /// (or [`OneDrive::get_item_with_option`][get_item_with_opt]).
262 ///
263 /// [select]: ../option/struct.ObjectOption.html#method.select
264 /// [get_item]: ../struct.OneDrive.html#method.get_item
265 /// [get_item_with_opt]: ../struct.OneDrive.html#method.get_item_with_option
266 pub download_url @"@microsoft.graph.downloadUrl": Option<Url>,
267
268 // `@microsoft.graph.sourceUrl` is write-only
269 }
270}
271
272/// The error resource type, returned whenever an error occurs in the processing of a request.
273///
274/// Error responses follow the definition in the OData v4 specification for error responses.
275///
276/// **This struct is independent with [`OAuth2ErrorResponse`][oauth2_error_response] from OAuth2 API.**
277///
278/// It may be contained in [`onedrive_api::Error`][error] returned by storage API
279/// (methods of [`OneDrive`][one_drive], [`ListChildrenFetcher`][list_children_fetcher], etc.).
280///
281/// # See also
282/// [Microsoft Docs](https://docs.microsoft.com/en-us/graph/errors#error-resource-type)
283///
284/// [oauth2_error_response]: ./struct.OAuth2ErrorResponse.html
285/// [error]: ../struct.Error.html
286/// [one_drive]: ../struct.OneDrive.html
287/// [list_children_fetcher]: ../struct.ListChildrenFetcher.html
288#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
289#[non_exhaustive]
290pub struct ErrorResponse {
291 /// OData `code`. Non-exhaustive.
292 ///
293 /// Some possible values of `code` field can be found in:
294 /// - [Error resource type: code property](https://docs.microsoft.com/en-us/graph/errors#code-property)
295 /// - [Error codes for authorization endpoint errors](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#error-codes-for-authorization-endpoint-errors)
296 /// - And maybe more.
297 pub code: String,
298 /// OData `message`. Usually to be human-readable.
299 pub message: String,
300 /// OData `innererror`. An optional object with additional or more specific error codes.
301 #[serde(rename = "innererror")]
302 pub inner_error: Option<serde_json::Map<String, serde_json::Value>>,
303}
304
305/// OAuth2 error response.
306///
307/// **This struct is independent with [`ErrorResponse`][error_response] from storage API.**
308///
309/// It can only be contained in [`onedrive_api::Error`][error] returned by operations
310/// about OAuth2 (methods of [`Auth`][auth]).
311///
312/// # See also
313/// - [Microsoft Docs: Request an authorization code](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#error-response)
314/// - [Microsoft Docs: Request an access token](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#error-response-1)
315/// - [Microsoft Docs: Refresh the access token](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#error-response-2)
316///
317/// [error_response]: ./struct.ErrorResponse.html
318/// [error]: ../struct.Error.html
319/// [auth]: ../struct.Auth.html
320#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
321#[allow(missing_docs)]
322#[non_exhaustive]
323pub struct OAuth2ErrorResponse {
324 pub error: String,
325 pub error_description: String,
326 pub error_codes: Option<Vec<u32>>,
327 pub timestamp: Option<String>,
328 pub trace_id: Option<String>,
329 pub correlation_id: Option<String>,
330}
331
332#[cfg(test)]
333mod tests {
334 use super::*;
335
336 #[test]
337 fn test_raw_name() {
338 assert_eq!(DriveField::id.raw_name(), "id");
339 assert_eq!(DriveField::drive_type.raw_name(), "driveType");
340 assert_eq!(DriveField::owner.raw_name(), "owner");
341 assert_eq!(DriveField::web_url.raw_name(), "webUrl");
342
343 assert_eq!(DriveItemField::id.raw_name(), "id");
344 assert_eq!(
345 DriveItemField::file_system_info.raw_name(),
346 "fileSystemInfo"
347 );
348 assert_eq!(DriveItemField::size.raw_name(), "size");
349 assert_eq!(DriveItemField::web_dav_url.raw_name(), "webDavUrl");
350 assert_eq!(DriveItemField::web_url.raw_name(), "webUrl");
351
352 assert_eq!(
353 DriveItemField::download_url.raw_name(),
354 "@microsoft.graph.downloadUrl",
355 );
356 }
357}