pcloud/file/
mod.rs

1use std::{borrow::Cow, cmp::Ordering};
2
3use serde::ser::SerializeStruct;
4
5use crate::entry::EntryBase;
6
7pub mod checksum;
8pub mod delete;
9pub mod movefile; // Can't name it "move" as it's a reserved keyword
10pub mod rename;
11pub mod upload;
12
13/// Response returned when moving or copying a file.
14///
15/// This struct wraps file metadata after an operation that results
16/// in a file being created or relocated (e.g., move, copy).
17#[derive(Debug, serde::Deserialize)]
18pub struct FileResponse {
19    /// Metadata of the resulting file after the operation.
20    pub metadata: File,
21}
22
23/// A file identifier used in API calls.
24///
25/// Files on pCloud can be referenced either by their **file ID** or by their **path**.
26/// File IDs are preferred for reliability and performance.
27///
28/// This enum allows you to pass either type of identifier interchangeably.
29#[derive(Clone, Debug)]
30pub enum FileIdentifier<'a> {
31    /// A file path (e.g., `"folder/subfolder/file.txt"`).
32    Path(Cow<'a, str>),
33
34    /// A file ID assigned by pCloud.
35    FileId(u64),
36}
37
38impl<'a> FileIdentifier<'a> {
39    /// Creates a [`FileIdentifier`] from a path.
40    #[inline]
41    pub fn path<P: Into<Cow<'a, str>>>(path: P) -> Self {
42        Self::Path(path.into())
43    }
44
45    /// Creates a [`FileIdentifier`] from a file ID.
46    #[inline]
47    pub fn file_id(fileid: u64) -> Self {
48        Self::FileId(fileid)
49    }
50}
51
52impl Default for FileIdentifier<'_> {
53    fn default() -> Self {
54        Self::FileId(0)
55    }
56}
57
58impl<'a> From<Cow<'a, str>> for FileIdentifier<'a> {
59    fn from(value: Cow<'a, str>) -> Self {
60        Self::Path(value)
61    }
62}
63
64impl<'a> From<&'a str> for FileIdentifier<'a> {
65    fn from(value: &'a str) -> Self {
66        Self::Path(Cow::Borrowed(value))
67    }
68}
69
70impl<'a> From<&'a String> for FileIdentifier<'a> {
71    fn from(value: &'a String) -> Self {
72        Self::Path(Cow::Borrowed(value))
73    }
74}
75
76impl From<String> for FileIdentifier<'_> {
77    fn from(value: String) -> Self {
78        Self::Path(Cow::Owned(value))
79    }
80}
81
82impl From<u64> for FileIdentifier<'_> {
83    fn from(value: u64) -> Self {
84        Self::FileId(value)
85    }
86}
87
88impl serde::Serialize for FileIdentifier<'_> {
89    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
90    where
91        S: serde::Serializer,
92    {
93        let mut builder = serializer.serialize_struct(stringify!(FileIdentifier), 1)?;
94        match self {
95            Self::FileId(file_id) => {
96                builder.serialize_field("fileid", file_id)?;
97            }
98            Self::Path(path) => {
99                builder.serialize_field("path", path)?;
100            }
101        }
102        builder.end()
103    }
104}
105
106/// A structure representing a file stored on pCloud.
107///
108/// Includes metadata such as the file's unique ID, size, content type, and other attributes.
109///
110/// This struct implements comparison traits so files can be sorted or compared by name.
111#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
112pub struct File {
113    /// Base metadata common to all entries (files and folders).
114    #[serde(flatten)]
115    pub base: EntryBase,
116
117    /// The unique file ID assigned by pCloud.
118    #[serde(rename = "fileid")]
119    pub file_id: u64,
120
121    /// The size of the file in bytes.
122    pub size: Option<usize>,
123
124    /// A hash of the file content (may be used for caching or deduplication).
125    pub hash: Option<usize>,
126
127    /// The MIME type of the file (e.g., `"image/jpeg"`, `"application/pdf"`).
128    #[serde(rename = "contenttype")]
129    pub content_type: Option<String>,
130}
131
132impl Eq for File {}
133
134impl PartialEq for File {
135    fn eq(&self, other: &Self) -> bool {
136        self.base.id.eq(&other.base.id)
137    }
138}
139
140impl Ord for File {
141    fn cmp(&self, other: &Self) -> Ordering {
142        self.base.name.cmp(&other.base.name)
143    }
144}
145
146impl PartialOrd for File {
147    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
148        Some(self.cmp(other))
149    }
150}