#![allow(clippy::module_name_repetitions)] use crate::{
resource::{ResourceField, Tag},
util::RequestBuilderTransformer,
ConflictBehavior,
};
use reqwest::{header, RequestBuilder};
use std::{fmt::Write, marker::PhantomData};
#[derive(Debug, Default, Clone, PartialEq, Eq)]
struct AccessOption {
if_match: Option<String>,
if_none_match: Option<String>,
}
impl AccessOption {
fn if_match(mut self, tag: &Tag) -> Self {
self.if_match = Some(tag.0.clone());
self
}
fn if_none_match(mut self, tag: &Tag) -> Self {
self.if_none_match = Some(tag.0.clone());
self
}
}
impl RequestBuilderTransformer for AccessOption {
fn trans(self, mut req: RequestBuilder) -> RequestBuilder {
if let Some(v) = self.if_match {
req = req.header(header::IF_MATCH, v);
}
if let Some(v) = self.if_none_match {
req = req.header(header::IF_NONE_MATCH, v);
}
req
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ObjectOption<Field> {
access_opt: AccessOption,
select_buf: String,
expand_buf: String,
_marker: PhantomData<dyn Fn(&Field) + Send + Sync>,
}
impl<Field: ResourceField> ObjectOption<Field> {
#[must_use]
pub fn new() -> Self {
Self {
access_opt: AccessOption::default(),
select_buf: String::new(),
expand_buf: String::new(),
_marker: PhantomData,
}
}
#[must_use]
pub fn if_match(mut self, tag: &Tag) -> Self {
self.access_opt = self.access_opt.if_match(tag);
self
}
#[must_use]
pub fn if_none_match(mut self, tag: &Tag) -> Self {
self.access_opt = self.access_opt.if_none_match(tag);
self
}
#[must_use]
pub fn select(mut self, fields: &[Field]) -> Self {
for sel in fields {
self = self.select_raw(&[sel.__raw_name()]);
}
self
}
fn select_raw(mut self, fields: &[&str]) -> Self {
for sel in fields {
write!(self.select_buf, ",{sel}").unwrap();
}
self
}
#[must_use]
pub fn expand(self, field: Field, select_children: Option<&[&str]>) -> Self {
self.expand_raw(field.__raw_name(), select_children)
}
fn expand_raw(mut self, field: &str, select_children: Option<&[&str]>) -> Self {
let buf = &mut self.expand_buf;
write!(buf, ",{field}").unwrap();
if let Some(children) = select_children {
write!(buf, "($select=").unwrap();
for sel in children {
write!(buf, "{sel},").unwrap();
}
write!(buf, ")").unwrap();
}
self
}
}
impl<Field: ResourceField> RequestBuilderTransformer for ObjectOption<Field> {
fn trans(self, mut req: RequestBuilder) -> RequestBuilder {
req = self.access_opt.trans(req);
if let Some(s) = self.select_buf.get(1..) {
req = req.query(&[("$select", s)]);
}
if let Some(s) = self.expand_buf.get(1..) {
req = req.query(&[("$expand", s)]);
}
req
}
}
impl<Field: ResourceField> Default for ObjectOption<Field> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CollectionOption<Field> {
obj_option: ObjectOption<Field>,
order_buf: Option<String>,
page_size_buf: Option<String>,
get_count_buf: bool,
}
impl<Field: ResourceField> CollectionOption<Field> {
#[must_use]
pub fn new() -> Self {
Self {
obj_option: ObjectOption::default(),
order_buf: None,
page_size_buf: None,
get_count_buf: false,
}
}
#[must_use]
pub fn if_match(mut self, tag: &Tag) -> Self {
self.obj_option = self.obj_option.if_match(tag);
self
}
#[must_use]
pub fn if_none_match(mut self, tag: &Tag) -> Self {
self.obj_option = self.obj_option.if_none_match(tag);
self
}
#[must_use]
pub fn select(mut self, fields: &[Field]) -> Self {
self.obj_option = self.obj_option.select(fields);
self
}
#[must_use]
pub fn expand(mut self, field: Field, select_children: Option<&[&str]>) -> Self {
self.obj_option = self.obj_option.expand(field, select_children);
self
}
#[must_use]
pub fn order_by(mut self, field: Field, order: Order) -> Self {
let order = match order {
Order::Ascending => "asc",
Order::Descending => "desc",
};
self.order_buf = Some(format!("{} {}", field.__raw_name(), order));
self
}
#[must_use]
pub fn page_size(mut self, size: usize) -> Self {
self.page_size_buf = Some(size.to_string());
self
}
#[must_use]
pub fn get_count(mut self, get_count: bool) -> Self {
self.get_count_buf = get_count;
self
}
pub(crate) fn has_get_count(&self) -> bool {
self.get_count_buf
}
}
impl<Field: ResourceField> RequestBuilderTransformer for CollectionOption<Field> {
fn trans(self, mut req: RequestBuilder) -> RequestBuilder {
req = self.obj_option.trans(req);
if let Some(s) = &self.order_buf {
req = req.query(&[("$orderby", s)]);
}
if let Some(s) = &self.page_size_buf {
req = req.query(&[("$top", s)]);
}
if self.get_count_buf {
req = req.query(&[("$count", "true")]);
}
req
}
}
impl<Field: ResourceField> Default for CollectionOption<Field> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Order {
Ascending,
Descending,
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct DriveItemPutOption {
access_opt: AccessOption,
conflict_behavior: Option<ConflictBehavior>,
}
impl DriveItemPutOption {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn if_match(mut self, tag: &Tag) -> Self {
self.access_opt = self.access_opt.if_match(tag);
self
}
#[must_use]
pub fn conflict_behavior(mut self, conflict_behavior: ConflictBehavior) -> Self {
self.conflict_behavior = Some(conflict_behavior);
self
}
pub(crate) fn get_conflict_behavior(&self) -> Option<ConflictBehavior> {
self.conflict_behavior
}
}
impl RequestBuilderTransformer for DriveItemPutOption {
fn trans(self, req: RequestBuilder) -> RequestBuilder {
self.access_opt.trans(req)
}
}
#[cfg(test)]
#[allow(dead_code)]
mod tests {
use super::*;
use crate::resource;
fn assert_send_sync<T: Send + Sync>() {}
fn assert_object_option_is_send_sync() {
assert_send_sync::<ObjectOption<resource::DriveField>>();
assert_send_sync::<ObjectOption<resource::DriveItemField>>();
}
fn assert_collection_option_is_send_sync() {
assert_send_sync::<CollectionOption<resource::DriveField>>();
assert_send_sync::<CollectionOption<resource::DriveItemField>>();
}
fn assert_drive_item_put_option_is_send_sync() {
assert_send_sync::<DriveItemPutOption>();
}
}