Skip to main content

io_webdav/rfc4918/
options.rs

1//! Generic `OPTIONS` coroutine (RFC 4918 §9.1, §15).
2//!
3//! Sends an `OPTIONS` against `path` and returns the raw response so
4//! the caller can inspect the `DAV` and `Allow` headers.
5//!
6//! # Example
7//!
8//! ```rust,no_run
9//! use std::{
10//!     io::{Read, Write},
11//!     net::TcpStream,
12//! };
13//!
14//! use io_webdav::{
15//!     coroutine::{WebdavCoroutine, WebdavCoroutineState, WebdavYield},
16//!     rfc4918::{WebdavAuth, options::Options},
17//! };
18//! use url::Url;
19//!
20//! // Ready stream needed (TCP-connected, TLS-negociated)
21//! let mut stream = TcpStream::connect("dav.example.org:443").unwrap();
22//! let mut buf = [0u8; 4096];
23//!
24//! let base_url: Url = "https://dav.example.org/".parse().unwrap();
25//! let auth = WebdavAuth::None;
26//! let mut coroutine = Options::new(&base_url, &auth, "io-webdav", "/dav/");
27//! let mut arg = None;
28//!
29//! let ok = loop {
30//!     match coroutine.resume(arg.take()) {
31//!         WebdavCoroutineState::Yielded(WebdavYield::WantsWrite(bytes)) => {
32//!             stream.write_all(&bytes).unwrap();
33//!         }
34//!         WebdavCoroutineState::Yielded(WebdavYield::WantsRead) => {
35//!             let n = stream.read(&mut buf).unwrap();
36//!             arg = Some(&buf[..n]);
37//!         }
38//!         WebdavCoroutineState::Complete(Ok(ok)) => break ok,
39//!         WebdavCoroutineState::Complete(Err(err)) => panic!("{err}"),
40//!     }
41//! };
42//!
43//! println!("DAV: {:?}", ok.response.header("dav"));
44//! ```
45
46use alloc::vec::Vec;
47
48use log::trace;
49use url::Url;
50
51use crate::{
52    coroutine::*,
53    rfc4918::{
54        WebdavAuth,
55        request::WebdavRequest,
56        send::{SendError, SendOk, SendRaw},
57    },
58};
59
60/// Coroutine that runs an `OPTIONS`.
61#[derive(Debug)]
62pub struct Options {
63    state: State,
64}
65
66impl Options {
67    /// Builds a new `OPTIONS` coroutine.
68    pub fn new(base_url: &Url, auth: &WebdavAuth, user_agent: &str, path: &str) -> Self {
69        let request = WebdavRequest::options(base_url, auth, user_agent, path).body(Vec::new());
70        Self {
71            state: State::Send(SendRaw::new(request)),
72        }
73    }
74}
75
76impl WebdavCoroutine for Options {
77    type Yield = WebdavYield;
78    type Return = Result<SendOk<Vec<u8>>, SendError>;
79
80    fn resume(&mut self, arg: Option<&[u8]>) -> WebdavCoroutineState<Self::Yield, Self::Return> {
81        trace!("sending request");
82        match &mut self.state {
83            State::Send(send) => send.resume(arg),
84        }
85    }
86}
87
88#[derive(Debug)]
89enum State {
90    Send(SendRaw),
91}