hydrus_api/api_core/
common.rs

1use crate::wrapper::service::ServiceName;
2use serde::Serialize;
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct BasicServiceInfo {
7    pub name: String,
8    pub service_key: String,
9    #[serde(alias = "type")]
10    pub service_type: u64,
11    pub type_pretty: String,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct ServiceItem {
16    pub name: String,
17    #[serde(alias = "type")]
18    pub service_type: u64,
19    pub type_pretty: String,
20}
21
22impl BasicServiceInfo {
23    /// Converts the Service into into an identifier
24    /// that can be used for requests consuming service references
25    pub fn into_id(self) -> ServiceIdentifier {
26        ServiceIdentifier::Key(self.service_key)
27    }
28}
29
30#[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialOrd, PartialEq, Ord, Eq)]
31pub enum ServiceIdentifier {
32    /// Try to avoid using this variant as it will be removed from the interface
33    /// in the future
34    Name(String),
35    /// The key variant of a service which should be the preferred variant.
36    Key(String),
37}
38
39impl ServiceIdentifier {
40    /// Deprecation: use [ServiceIdentifier::key] instead.
41    #[deprecated(
42        note = "Deprecation in the official interface was mentioned. Use the service keys instead."
43    )]
44    pub fn name<S: ToString>(name: S) -> Self {
45        Self::Name(name.to_string())
46    }
47
48    /// Constructs a new type of the key variant.
49    pub fn key<S: ToString>(key: S) -> Self {
50        Self::Key(key.to_string())
51    }
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct BasicHashList {
56    pub hashes: Vec<String>,
57}
58
59#[derive(Clone, Debug)]
60pub enum FileIdentifier {
61    ID(u64),
62    Hash(String),
63}
64
65impl FileIdentifier {
66    pub fn hash<S: ToString>(hash: S) -> Self {
67        Self::Hash(hash.to_string())
68    }
69
70    pub fn as_hash(&self) -> Option<&String> {
71        if let Self::Hash(h) = &self {
72            Some(h)
73        } else {
74            None
75        }
76    }
77
78    pub fn as_id(&self) -> Option<u64> {
79        if let Self::ID(id) = &self {
80            Some(*id)
81        } else {
82            None
83        }
84    }
85}
86
87/// A generic selection for one or multiple files
88#[derive(Clone, Debug, Serialize, Default)]
89pub struct FileSelection {
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub(crate) hash: Option<String>,
92    #[serde(skip_serializing_if = "Vec::is_empty")]
93    pub(crate) hashes: Vec<String>,
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub(crate) file_id: Option<u64>,
96    #[serde(skip_serializing_if = "Vec::is_empty")]
97    pub(crate) file_ids: Vec<u64>,
98}
99
100impl From<FileIdentifier> for FileSelection {
101    fn from(id: FileIdentifier) -> Self {
102        let mut selection = Self::default();
103        match id {
104            FileIdentifier::ID(id) => selection.file_id = Some(id),
105            FileIdentifier::Hash(hash) => selection.hash = Some(hash),
106        }
107        selection
108    }
109}
110
111impl FileSelection {
112    /// Creates a new single hash file selection
113    pub fn by_hash<S: ToString>(hash: S) -> Self {
114        Self {
115            hash: Some(hash.to_string()),
116            ..Default::default()
117        }
118    }
119
120    /// Creates a new file selection with a single file id
121    pub fn by_file_id(file_id: u64) -> Self {
122        Self {
123            file_id: Some(file_id),
124            ..Default::default()
125        }
126    }
127
128    /// Creates a new file selection with several hashes
129    pub fn by_hashes(mut hashes: Vec<String>) -> Self {
130        if hashes.len() == 1 {
131            Self::by_hash(hashes.pop().unwrap())
132        } else {
133            Self {
134                hashes,
135                ..Default::default()
136            }
137        }
138    }
139
140    /// Creates a new file selection with several IDs
141    pub fn by_file_ids(mut file_ids: Vec<u64>) -> Self {
142        if file_ids.len() == 1 {
143            Self::by_file_id(file_ids.pop().unwrap())
144        } else {
145            Self {
146                file_ids,
147                ..Default::default()
148            }
149        }
150    }
151}
152
153/// A selection for a single file  service
154#[derive(Clone, Debug, Serialize, Default)]
155pub struct FileServiceSelection {
156    #[serde(skip_serializing_if = "Option::is_none")]
157    pub(crate) file_service_name: Option<String>,
158    #[serde(skip_serializing_if = "Option::is_none")]
159    pub(crate) file_service_key: Option<String>,
160}
161
162impl FileServiceSelection {
163    /// Creates a new file service selection by name
164    pub fn by_name<S: ToString>(name: S) -> Self {
165        Self {
166            file_service_name: Some(name.to_string()),
167            ..Default::default()
168        }
169    }
170
171    /// Creates a new file  service selection by service key
172    pub fn by_key<S: ToString>(key: S) -> Self {
173        Self {
174            file_service_key: Some(key.to_string()),
175            ..Default::default()
176        }
177    }
178
179    /// Selects no service
180    pub fn none() -> Self {
181        Self::default()
182    }
183}
184
185impl From<ServiceIdentifier> for FileServiceSelection {
186    fn from(id: ServiceIdentifier) -> Self {
187        match id {
188            ServiceIdentifier::Name(n) => Self::by_name(n),
189            ServiceIdentifier::Key(k) => Self::by_key(k),
190        }
191    }
192}
193
194impl From<ServiceName> for FileServiceSelection {
195    fn from(name: ServiceName) -> Self {
196        Self::by_name(name)
197    }
198}
199
200#[derive(Clone)]
201pub struct FileRecord {
202    pub bytes: Vec<u8>,
203    pub mime_type: String,
204}
205
206#[derive(Clone, Default, Debug, Deserialize)]
207pub struct FileMetadataServices {
208    pub current: HashMap<String, FileMetadataServiceCurrent>,
209    pub deleted: HashMap<String, FileMetadataServiceDeleted>,
210}
211
212#[derive(Clone, Debug, Deserialize)]
213pub struct FileMetadataServiceCurrent {
214    pub name: String,
215    #[serde(alias = "type")]
216    pub service_type: u64,
217    pub type_pretty: String,
218    pub time_imported: u64,
219}
220
221#[derive(Clone, Debug, Deserialize)]
222pub struct FileMetadataServiceDeleted {
223    pub time_deleted: u64,
224    pub time_imported: u64,
225}
226
227#[derive(Clone, Debug, Deserialize)]
228pub struct PageInformation {
229    pub name: String,
230    pub page_key: String,
231    pub page_type: u32,
232    #[serde(alias = "focused")]
233    pub selected: Option<bool>,
234    #[serde(default = "Vec::new")]
235    pub pages: Vec<PageInformation>,
236}
237
238#[derive(Clone, Debug, Serialize, Deserialize)]
239#[serde(untagged)]
240pub enum OptionalStringNumber {
241    String(String),
242    Number(u64),
243    None,
244}
245
246impl From<u64> for OptionalStringNumber {
247    fn from(value: u64) -> Self {
248        Self::Number(value)
249    }
250}
251
252impl From<String> for OptionalStringNumber {
253    fn from(value: String) -> Self {
254        Self::String(value)
255    }
256}
257
258impl OptionalStringNumber {
259    pub fn string(&self) -> Option<&str> {
260        if let Self::String(s) = &self {
261            Some(s)
262        } else {
263            None
264        }
265    }
266
267    pub fn number(&self) -> Option<u64> {
268        if let Self::Number(n) = &self {
269            Some(*n)
270        } else {
271            None
272        }
273    }
274}