Skip to main content

io_webdav/rfc4918/
copy.rs

1//! Generic `COPY` coroutine (RFC 4918 ยง9.8).
2//!
3//! # Example
4//!
5//! ```rust,no_run
6//! use std::{
7//!     io::{Read, Write},
8//!     net::TcpStream,
9//! };
10//!
11//! use io_webdav::{
12//!     coroutine::{WebdavCoroutine, WebdavCoroutineState, WebdavYield},
13//!     rfc4918::{WebdavAuth, copy::Copy},
14//! };
15//! use url::Url;
16//!
17//! // Ready stream needed (TCP-connected, TLS-negociated)
18//! let mut stream = TcpStream::connect("dav.example.org:443").unwrap();
19//! let mut buf = [0u8; 4096];
20//!
21//! let base_url: Url = "https://dav.example.org/".parse().unwrap();
22//! let auth = WebdavAuth::None;
23//! let mut coroutine = Copy::new(
24//!     &base_url,
25//!     &auth,
26//!     "io-webdav",
27//!     "/dav/calendars/personal/event-1.ics",
28//!     "/dav/calendars/work/event-1.ics",
29//!     false,
30//!     0,
31//! );
32//! let mut arg = None;
33//!
34//! loop {
35//!     match coroutine.resume(arg.take()) {
36//!         WebdavCoroutineState::Yielded(WebdavYield::WantsWrite(bytes)) => {
37//!             stream.write_all(&bytes).unwrap();
38//!         }
39//!         WebdavCoroutineState::Yielded(WebdavYield::WantsRead) => {
40//!             let n = stream.read(&mut buf).unwrap();
41//!             arg = Some(&buf[..n]);
42//!         }
43//!         WebdavCoroutineState::Complete(Ok(_)) => break,
44//!         WebdavCoroutineState::Complete(Err(err)) => panic!("{err}"),
45//!     }
46//! }
47//! ```
48
49use alloc::vec::Vec;
50
51use log::trace;
52use url::Url;
53
54use crate::{
55    coroutine::*,
56    rfc4918::{
57        WebdavAuth,
58        request::WebdavRequest,
59        send::{SendError, SendOk, SendRaw},
60    },
61};
62
63/// Coroutine that runs a `COPY` of `path` to `destination`.
64#[derive(Debug)]
65pub struct Copy {
66    state: State,
67}
68
69impl Copy {
70    /// Builds a new `COPY` coroutine. `depth` is the `Depth` header
71    /// (typically `0` for resources, `infinity` is encoded by the
72    /// server, expose only the `0` / `1` case here).
73    pub fn new(
74        base_url: &Url,
75        auth: &WebdavAuth,
76        user_agent: &str,
77        path: &str,
78        destination: &str,
79        overwrite: bool,
80        depth: u8,
81    ) -> Self {
82        let request = WebdavRequest::copy(base_url, auth, user_agent, path)
83            .destination(destination)
84            .overwrite(overwrite)
85            .depth(depth)
86            .body(Vec::new());
87        Self {
88            state: State::Send(SendRaw::new(request)),
89        }
90    }
91}
92
93impl WebdavCoroutine for Copy {
94    type Yield = WebdavYield;
95    type Return = Result<SendOk<Vec<u8>>, SendError>;
96
97    fn resume(&mut self, arg: Option<&[u8]>) -> WebdavCoroutineState<Self::Yield, Self::Return> {
98        trace!("sending request");
99        match &mut self.state {
100            State::Send(send) => send.resume(arg),
101        }
102    }
103}
104
105#[derive(Debug)]
106enum State {
107    Send(SendRaw),
108}