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}