1#![allow(clippy::module_name_repetitions)] use crate::{
14 resource::{ResourceField, Tag},
15 util::RequestBuilderTransformer,
16 ConflictBehavior,
17};
18use reqwest::{header, RequestBuilder};
19use std::{fmt::Write, marker::PhantomData};
20
21#[derive(Debug, Default, Clone, PartialEq, Eq)]
22struct AccessOption {
23 if_match: Option<String>,
24 if_none_match: Option<String>,
25}
26
27impl AccessOption {
28 fn if_match(mut self, tag: &Tag) -> Self {
29 self.if_match = Some(tag.0.clone());
30 self
31 }
32
33 fn if_none_match(mut self, tag: &Tag) -> Self {
34 self.if_none_match = Some(tag.0.clone());
35 self
36 }
37}
38
39impl RequestBuilderTransformer for AccessOption {
40 fn trans(self, mut req: RequestBuilder) -> RequestBuilder {
41 if let Some(v) = self.if_match {
42 req = req.header(header::IF_MATCH, v);
43 }
44 if let Some(v) = self.if_none_match {
45 req = req.header(header::IF_NONE_MATCH, v);
46 }
47 req
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq)]
53pub struct ObjectOption<Field> {
54 access_opt: AccessOption,
55 select_buf: String,
56 expand_buf: String,
57 _marker: PhantomData<dyn Fn(&Field) + Send + Sync>,
58}
59
60impl<Field: ResourceField> ObjectOption<Field> {
61 #[must_use]
63 pub fn new() -> Self {
64 Self {
65 access_opt: AccessOption::default(),
66 select_buf: String::new(),
67 expand_buf: String::new(),
68 _marker: PhantomData,
69 }
70 }
71
72 #[must_use]
81 pub fn if_match(mut self, tag: &Tag) -> Self {
82 self.access_opt = self.access_opt.if_match(tag);
83 self
84 }
85
86 #[must_use]
95 pub fn if_none_match(mut self, tag: &Tag) -> Self {
96 self.access_opt = self.access_opt.if_none_match(tag);
97 self
98 }
99
100 #[must_use]
112 pub fn select(mut self, fields: &[Field]) -> Self {
113 for sel in fields {
114 self = self.select_raw(&[sel.__raw_name()]);
115 }
116 self
117 }
118
119 fn select_raw(mut self, fields: &[&str]) -> Self {
120 for sel in fields {
121 write!(self.select_buf, ",{sel}").unwrap();
122 }
123 self
124 }
125
126 #[must_use]
139 pub fn expand(self, field: Field, select_children: Option<&[&str]>) -> Self {
140 self.expand_raw(field.__raw_name(), select_children)
141 }
142
143 fn expand_raw(mut self, field: &str, select_children: Option<&[&str]>) -> Self {
144 let buf = &mut self.expand_buf;
145 write!(buf, ",{field}").unwrap();
146 if let Some(children) = select_children {
147 write!(buf, "($select=").unwrap();
148 for sel in children {
149 write!(buf, "{sel},").unwrap();
150 }
151 write!(buf, ")").unwrap();
152 }
153 self
154 }
155}
156
157impl<Field: ResourceField> RequestBuilderTransformer for ObjectOption<Field> {
158 fn trans(self, mut req: RequestBuilder) -> RequestBuilder {
159 req = self.access_opt.trans(req);
160 if let Some(s) = self.select_buf.get(1..) {
161 req = req.query(&[("$select", s)]);
162 }
163 if let Some(s) = self.expand_buf.get(1..) {
164 req = req.query(&[("$expand", s)]);
165 }
166 req
167 }
168}
169
170impl<Field: ResourceField> Default for ObjectOption<Field> {
171 fn default() -> Self {
172 Self::new()
173 }
174}
175
176#[derive(Debug, Clone, PartialEq, Eq)]
178pub struct CollectionOption<Field> {
179 obj_option: ObjectOption<Field>,
180 order_buf: Option<String>,
181 page_size_buf: Option<String>,
182 get_count_buf: bool,
183}
184
185impl<Field: ResourceField> CollectionOption<Field> {
186 #[must_use]
188 pub fn new() -> Self {
189 Self {
190 obj_option: ObjectOption::default(),
191 order_buf: None,
192 page_size_buf: None,
193 get_count_buf: false,
194 }
195 }
196
197 #[must_use]
204 pub fn if_match(mut self, tag: &Tag) -> Self {
205 self.obj_option = self.obj_option.if_match(tag);
206 self
207 }
208
209 #[must_use]
216 pub fn if_none_match(mut self, tag: &Tag) -> Self {
217 self.obj_option = self.obj_option.if_none_match(tag);
218 self
219 }
220
221 #[must_use]
231 pub fn select(mut self, fields: &[Field]) -> Self {
232 self.obj_option = self.obj_option.select(fields);
233 self
234 }
235
236 #[must_use]
246 pub fn expand(mut self, field: Field, select_children: Option<&[&str]>) -> Self {
247 self.obj_option = self.obj_option.expand(field, select_children);
248 self
249 }
250
251 #[must_use]
259 pub fn order_by(mut self, field: Field, order: Order) -> Self {
260 let order = match order {
261 Order::Ascending => "asc",
262 Order::Descending => "desc",
263 };
264 self.order_buf = Some(format!("{} {}", field.__raw_name(), order));
265 self
266 }
267
268 #[must_use]
276 pub fn page_size(mut self, size: usize) -> Self {
277 self.page_size_buf = Some(size.to_string());
278 self
279 }
280
281 #[must_use]
294 pub fn get_count(mut self, get_count: bool) -> Self {
295 self.get_count_buf = get_count;
296 self
297 }
298
299 pub(crate) fn has_get_count(&self) -> bool {
300 self.get_count_buf
301 }
302}
303
304impl<Field: ResourceField> RequestBuilderTransformer for CollectionOption<Field> {
305 fn trans(self, mut req: RequestBuilder) -> RequestBuilder {
306 req = self.obj_option.trans(req);
307 if let Some(s) = &self.order_buf {
308 req = req.query(&[("$orderby", s)]);
309 }
310 if let Some(s) = &self.page_size_buf {
311 req = req.query(&[("$top", s)]);
312 }
313 if self.get_count_buf {
314 req = req.query(&[("$count", "true")]);
315 }
316 req
317 }
318}
319
320impl<Field: ResourceField> Default for CollectionOption<Field> {
321 fn default() -> Self {
322 Self::new()
323 }
324}
325
326#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
332pub enum Order {
333 Ascending,
335 Descending,
337}
338
339#[derive(Debug, Default, Clone, PartialEq, Eq)]
341pub struct DriveItemPutOption {
342 access_opt: AccessOption,
343 conflict_behavior: Option<ConflictBehavior>,
344}
345
346impl DriveItemPutOption {
347 #[must_use]
349 pub fn new() -> Self {
350 Self::default()
351 }
352
353 #[must_use]
360 pub fn if_match(mut self, tag: &Tag) -> Self {
361 self.access_opt = self.access_opt.if_match(tag);
362 self
363 }
364
365 #[must_use]
375 pub fn conflict_behavior(mut self, conflict_behavior: ConflictBehavior) -> Self {
376 self.conflict_behavior = Some(conflict_behavior);
377 self
378 }
379
380 pub(crate) fn get_conflict_behavior(&self) -> Option<ConflictBehavior> {
381 self.conflict_behavior
382 }
383}
384
385impl RequestBuilderTransformer for DriveItemPutOption {
386 fn trans(self, req: RequestBuilder) -> RequestBuilder {
387 self.access_opt.trans(req)
388 }
389}
390
391#[cfg(test)]
392#[allow(dead_code)]
394mod tests {
395 use super::*;
396 use crate::resource;
397
398 fn assert_send_sync<T: Send + Sync>() {}
399
400 fn assert_object_option_is_send_sync() {
401 assert_send_sync::<ObjectOption<resource::DriveField>>();
402 assert_send_sync::<ObjectOption<resource::DriveItemField>>();
403 }
404
405 fn assert_collection_option_is_send_sync() {
406 assert_send_sync::<CollectionOption<resource::DriveField>>();
407 assert_send_sync::<CollectionOption<resource::DriveItemField>>();
408 }
409
410 fn assert_drive_item_put_option_is_send_sync() {
411 assert_send_sync::<DriveItemPutOption>();
412 }
413}