pcloud/file/movefile.rs
1use crate::folder::{FolderIdentifier, ToFolderIdentifier};
2
3use super::{File, FileIdentifier, FileResponse};
4
5/// Parameters required to move a file to a new folder.
6///
7/// This structure is serialized and sent to the `renamefile` endpoint.
8/// It flattens both the source file identifier and the target folder identifier
9/// into the request payload.
10#[derive(serde::Serialize)]
11struct FileMoveParams<'a> {
12 /// The file to move (by path or file ID).
13 #[serde(flatten)]
14 from: FileIdentifier<'a>,
15
16 /// The target folder to move the file into.
17 #[serde(flatten)]
18 to: ToFolderIdentifier<'a>,
19}
20
21impl crate::Client {
22 /// Moves a file to a different folder on pCloud.
23 ///
24 /// This function calls the `renamefile` API endpoint to move the specified file
25 /// to a new folder. The file is identified either by its file ID or by path.
26 ///
27 /// # Arguments
28 ///
29 /// * `file` - A value that can be converted into a [`FileIdentifier`] (e.g., file ID or path).
30 /// * `to_folder` - A value that can be converted into a [`FolderIdentifier`] representing the destination folder.
31 ///
32 /// # Returns
33 ///
34 /// On success, returns a [`File`] struct containing metadata about the moved file.
35 ///
36 /// # Errors
37 ///
38 /// Returns a [`crate::Error`] if the file or folder is not found, or if the API request fails.
39 ///
40 /// # Examples
41 ///
42 /// ```rust,no_run
43 /// # async fn example(client: &pcloud::Client) -> Result<(), pcloud::Error> {
44 /// let file = client.move_file(12345678u64, "/new/folder").await?;
45 /// println!("Moved file name: {}", file.base.name);
46 /// # Ok(())
47 /// # }
48 /// ```
49 pub async fn move_file(
50 &self,
51 file: impl Into<FileIdentifier<'_>>,
52 to_folder: impl Into<FolderIdentifier<'_>>,
53 ) -> crate::Result<File> {
54 self.get_request::<FileResponse, _>(
55 "renamefile",
56 FileMoveParams {
57 from: file.into(),
58 to: ToFolderIdentifier(to_folder.into()),
59 },
60 )
61 .await
62 .map(|res| res.metadata)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use crate::{Client, Credentials};
69 use mockito::Matcher;
70
71 #[tokio::test]
72 async fn success() {
73 let mut server = mockito::Server::new_async().await;
74 let m = server
75 .mock("GET", "/renamefile")
76 .match_query(Matcher::AllOf(vec![
77 Matcher::UrlEncoded("access_token".into(), "access-token".into()),
78 Matcher::UrlEncoded("fileid".into(), "42".into()),
79 Matcher::UrlEncoded("topath".into(), "/this/dir/".into()),
80 ]))
81 .with_status(200)
82 .with_body(
83 r#"{
84 "result": 0,
85 "metadata": {
86 "name": "yolo.bin",
87 "created": "Sat, 24 Jul 2021 07:38:41 +0000",
88 "thumb": false,
89 "modified": "Sat, 24 Jul 2021 07:38:41 +0000",
90 "isfolder": false,
91 "isdeleted": true,
92 "fileid": 42,
93 "hash": 9403476549337371523,
94 "comments": 0,
95 "category": 0,
96 "id": "f5257731387",
97 "isshared": false,
98 "ismine": true,
99 "size": 10485760,
100 "parentfolderid": 1075398908,
101 "contenttype": "application\/octet-stream",
102 "icon": "file"
103 }
104}"#,
105 )
106 .create();
107 let client = Client::new(server.url(), Credentials::access_token("access-token")).unwrap();
108 let result = client.move_file(42, "/this/dir/").await.unwrap();
109 assert_eq!(result.file_id, 42);
110 m.assert();
111 }
112}