Skip to main content

io_msgraph/v1/rest/users/events/
delta.rs

1//! Microsoft Graph calendar view delta (`GET /me/calendarView/delta` or
2//! `GET /me/calendars/{id}/calendarView/delta`).
3//!
4//! The changes to the lone events, occurrences and exceptions of a window
5//! since the previous round. The window is fixed by the round's first
6//! request and carried by every link after it.
7//!
8//! <https://learn.microsoft.com/en-us/graph/api/event-delta>
9
10use alloc::{format, string::String, vec::Vec};
11
12use io_http::rfc6750::bearer::HttpAuthBearer;
13use log::{debug, trace};
14use serde::{Deserialize, Serialize};
15use url::Url;
16
17use crate::{
18    coroutine::*,
19    msgraph_try,
20    v1::{
21        rest::users::{contacts::delta::MsgraphRemoved, events::MsgraphEvent},
22        send::{MSGRAPH_API_BASE, MsgraphSend, MsgraphSendError, MsgraphSendOutput, user_path},
23    },
24};
25
26/// One page of a calendar view delta round.
27///
28/// More pages follow through `next_link`; the round ends when
29/// `delta_link` arrives (the token of the next round).
30#[derive(Debug, Clone, Default, Deserialize, Serialize, Eq, PartialEq)]
31pub struct MsgraphEventsDeltaResponse {
32    /// The changed events of the page.
33    #[serde(default)]
34    pub value: Vec<MsgraphEventDelta>,
35    /// The URL of the next page of the round, when one exists.
36    #[serde(default, rename = "@odata.nextLink")]
37    pub next_link: Option<String>,
38    /// The URL closing the round, carrying the next round's token.
39    #[serde(default, rename = "@odata.deltaLink")]
40    pub delta_link: Option<String>,
41}
42
43/// One event row of a delta page: the event (only its id when the row is
44/// a removal), plus the `@removed` marker.
45#[derive(Debug, Clone, Default, Deserialize, Serialize, Eq, PartialEq)]
46pub struct MsgraphEventDelta {
47    /// The changed event.
48    #[serde(flatten)]
49    pub event: MsgraphEvent,
50    /// The removal marker, present when the row is a removal.
51    #[serde(default, rename = "@removed", skip_serializing_if = "Option::is_none")]
52    pub removed: Option<MsgraphRemoved>,
53}
54
55/// I/O-free coroutine for a calendar view delta request, opening a round
56/// with [`new`](Self::new) or continuing one with
57/// [`from_link`](Self::from_link).
58pub struct MsgraphEventsDelta {
59    send: MsgraphSend<MsgraphEventsDeltaResponse>,
60}
61
62impl MsgraphEventsDelta {
63    /// Starts a delta round over the view of the default calendar, or of
64    /// `calendar` when given, between `start` and `end`, ISO 8601
65    /// date-times.
66    pub fn new(
67        auth: &HttpAuthBearer,
68        user_id: &str,
69        calendar: Option<&str>,
70        start: &str,
71        end: &str,
72    ) -> Result<Self, MsgraphSendError> {
73        debug!("prepare microsoft graph calendar view delta");
74        trace!("calendar: {calendar:?}, start: {start}, end: {end}");
75
76        let user = user_path(user_id);
77        let path = match calendar {
78            Some(calendar) => format!("{user}/calendars/{calendar}/calendarView/delta"),
79            None => format!("{user}/calendarView/delta"),
80        };
81        let mut url = Url::parse(MSGRAPH_API_BASE)?.join(&path)?;
82        url.query_pairs_mut()
83            .append_pair("startDateTime", start)
84            .append_pair("endDateTime", end);
85
86        let send = MsgraphSend::get(auth, url);
87
88        Ok(Self { send })
89    }
90
91    /// Continues a round from an `@odata.nextLink`, or starts the next
92    /// round from a saved `@odata.deltaLink`, sent as-is.
93    pub fn from_link(auth: &HttpAuthBearer, link: &str) -> Result<Self, MsgraphSendError> {
94        debug!("prepare microsoft graph calendar view delta from link");
95        trace!("link: {link}");
96
97        let url = Url::parse(link)?;
98        let send = MsgraphSend::get(auth, url);
99
100        Ok(Self { send })
101    }
102}
103
104impl MsgraphCoroutine for MsgraphEventsDelta {
105    type Yield = MsgraphYield;
106    type Return = Result<MsgraphSendOutput<MsgraphEventsDeltaResponse>, MsgraphSendError>;
107
108    fn resume(&mut self, arg: Option<&[u8]>) -> MsgraphCoroutineState<Self::Yield, Self::Return> {
109        let out = msgraph_try!(&mut self.send, arg);
110        debug!("calendar view delta received");
111        trace!("out: {out:?}");
112        MsgraphCoroutineState::Complete(Ok(out))
113    }
114}