Skip to main content

cloudreve_api/api/v4/models/
file.rs

1//! File-related models for Cloudreve API v4
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6/// File or folder metadata
7#[derive(Debug, Serialize, Deserialize, Clone)]
8pub struct File {
9    #[serde(rename = "type")]
10    pub r#type: FileType,
11    pub id: String,
12    pub name: String,
13    #[serde(default)]
14    pub permission: Option<String>,
15    pub created_at: String,
16    pub updated_at: String,
17    pub size: i64,
18    #[serde(default)]
19    pub metadata: Option<Value>,
20    pub path: String,
21    #[serde(default)]
22    pub capability: Option<String>,
23    pub owned: bool,
24    #[serde(default)]
25    pub primary_entity: Option<String>,
26}
27
28/// File type enum
29#[derive(Debug, Serialize, Clone, PartialEq)]
30pub enum FileType {
31    File = 0,
32    Folder = 1,
33}
34
35impl<'de> Deserialize<'de> for FileType {
36    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
37    where
38        D: serde::Deserializer<'de>,
39    {
40        let value = i32::deserialize(deserializer)?;
41        match value {
42            0 => Ok(FileType::File),
43            1 => Ok(FileType::Folder),
44            _ => Err(serde::de::Error::custom(format!(
45                "Invalid FileType value: {}",
46                value
47            ))),
48        }
49    }
50}
51
52/// File statistics
53#[derive(Debug, Serialize, Deserialize)]
54pub struct FileStat {
55    pub size: u64,
56    pub created_at: String,
57    pub updated_at: String,
58    pub mime_type: String,
59}
60
61/// Directory list response
62#[derive(Debug, Serialize, Deserialize, Clone)]
63pub struct ListResponse {
64    pub files: Vec<File>,
65    pub parent: File,
66    pub pagination: PaginationResults,
67    pub props: NavigatorProps,
68    pub context_hint: String,
69    pub mixed_type: bool,
70    #[serde(default)]
71    pub storage_policy: Option<super::storage::StoragePolicy>,
72    pub view: Option<ExplorerView>,
73}
74
75/// Pagination metadata
76#[derive(Debug, Serialize, Deserialize, Clone)]
77pub struct PaginationResults {
78    pub page: i32,
79    pub page_size: i32,
80    pub total_items: Option<i64>,
81    pub next_token: Option<String>,
82    pub is_cursor: bool,
83}
84
85/// Treats an explicit `null` as the type's default
86///
87/// Search responses send `"order_by_options": null` instead of omitting the
88/// field, and `#[serde(default)]` on its own only covers omission.
89fn null_as_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
90where
91    D: serde::Deserializer<'de>,
92    T: Deserialize<'de> + Default,
93{
94    Ok(Option::<T>::deserialize(deserializer)?.unwrap_or_default())
95}
96
97/// Navigator capabilities
98#[derive(Debug, Serialize, Deserialize, Clone)]
99pub struct NavigatorProps {
100    pub capability: String,
101    pub max_page_size: i32,
102    // Ordering is meaningless for search results, so the server nulls these out
103    #[serde(default, deserialize_with = "null_as_default")]
104    pub order_by_options: Vec<String>,
105    #[serde(default, deserialize_with = "null_as_default")]
106    pub order_direction_options: Vec<String>,
107}
108
109/// Explorer view settings
110#[derive(Debug, Serialize, Deserialize, Clone)]
111pub struct ExplorerView {
112    pub page_size: Option<i32>,
113    pub order: Option<String>,
114    pub order_direction: Option<OrderDirection>,
115    pub view: Option<ExplorerViewMode>,
116    pub thumbnail: Option<bool>,
117    pub gallery_width: Option<i32>,
118    pub columns: Option<Vec<ListViewColumn>>,
119}
120
121/// Sort direction enum
122#[derive(Debug, Serialize, Deserialize, Clone)]
123pub enum OrderDirection {
124    #[serde(rename = "asc")]
125    Asc,
126    #[serde(rename = "desc")]
127    Desc,
128}
129
130/// View mode enum
131#[derive(Debug, Serialize, Deserialize, Clone)]
132pub enum ExplorerViewMode {
133    #[serde(rename = "list")]
134    List,
135    #[serde(rename = "grid")]
136    Grid,
137    #[serde(rename = "gallery")]
138    Gallery,
139}
140
141/// List view column configuration
142#[derive(Debug, Serialize, Deserialize, Clone)]
143pub struct ListViewColumn {
144    pub r#type: i32,
145    pub width: Option<i32>,
146    pub props: Option<ColumnProps>,
147}
148
149/// Column properties
150#[derive(Debug, Serialize, Deserialize, Clone)]
151pub struct ColumnProps {
152    pub metadata_key: Option<String>,
153}
154
155/// Extended file information
156#[derive(Debug, Serialize, Deserialize, Clone)]
157pub struct ExtendedInfo {
158    #[serde(default)]
159    pub storage_policy: Option<super::storage::NewStoragePolicy>,
160    pub storage_policy_inherited: bool,
161    pub storage_used: i64,
162    #[serde(default)]
163    pub shares: Option<Vec<super::share::ShareLink>>,
164    #[serde(default)]
165    pub entities: Option<Vec<super::storage::NewEntity>>,
166    pub permissions: Option<PermissionSetting>,
167    #[serde(default)]
168    pub direct_links: Option<Vec<super::storage::DirectLink>>,
169}
170
171/// Folder summary
172#[derive(Debug, Serialize, Deserialize, Clone)]
173pub struct FolderSummary {
174    pub size: i64,
175    pub files: i64,
176    pub folders: i64,
177    pub completed: bool,
178    pub calculated_at: String,
179}
180
181/// Permission settings
182#[derive(Debug, Serialize, Deserialize, Clone)]
183pub struct PermissionSetting {
184    #[serde(rename = "user_explicit")]
185    pub user_explicit: Value,
186    #[serde(rename = "group_explicit")]
187    pub group_explicit: Value,
188    #[serde(rename = "same_group")]
189    pub same_group: String,
190    #[serde(rename = "other")]
191    pub other: String,
192    #[serde(rename = "anonymous")]
193    pub anonymous: String,
194    #[serde(rename = "everyone")]
195    pub everyone: String,
196}