tauri_plugin_persistence/api/
types.rs

1use std::fs::{FileType, Metadata};
2
3use chrono::Utc;
4use mime_guess::MimeGuess;
5use serde::{Deserialize, Serialize};
6use specta::Type;
7use tokio::fs::DirEntry;
8
9use super::state::FileHandleMode;
10
11#[derive(Serialize, Deserialize, Clone, Debug, Type)]
12#[serde(untagged)]
13/// A model used to specify an existing or closed context
14pub enum ContextSpecifier {
15    /// Open a new context
16    Direct { alias: String, path: String },
17
18    /// Return an existing context
19    Aliased { alias: String },
20}
21
22#[derive(Serialize, Deserialize, Clone, Debug, Type)]
23/// A model containing serializable information about a [crate::Context]
24pub struct ContextInfo {
25    /// Context name
26    pub name: String,
27
28    /// Context path
29    pub path: String,
30}
31
32#[derive(Serialize, Deserialize, Clone, Debug, Type)]
33#[serde(untagged)]
34/// A model used to specify an existing or closed database
35pub enum DatabaseSpecifier {
36    /// Open a new database
37    Direct { alias: String, path: String },
38
39    /// Return an existing database
40    Aliased { alias: String },
41}
42
43#[derive(Serialize, Deserialize, Clone, Debug, Type)]
44/// A model containing serializable information about a [crate::Database]
45pub struct DatabaseInfo {
46    /// Database name
47    pub name: String,
48
49    /// Database path
50    pub path: String,
51}
52
53#[derive(Serialize, Deserialize, Clone, Debug, Type)]
54#[serde(untagged)]
55/// A model used to specify an existing or closed file handle
56pub enum FileHandleSpecifier {
57    /// Return an existing file handle
58    Aliased { id: bson::Uuid },
59
60    /// Open a new file handle
61    Direct { path: String, mode: FileHandleMode },
62}
63
64#[derive(Serialize, Deserialize, Clone, Debug, Type)]
65/// A model containing serializable information about a [crate::FileHandle]
66pub struct FileHandleInfo {
67    /// File handle ID
68    pub id: bson::Uuid,
69
70    /// File handle path
71    pub path: String,
72
73    /// Open mode
74    pub mode: FileHandleMode,
75}
76
77#[derive(Serialize, Deserialize, Clone, Debug, Type)]
78#[serde(untagged)]
79/// A model used to specify a collection
80pub enum CollectionSpecifier {
81    /// Open a collection in a transaction
82    Transaction {
83        /// Transaction ID
84        transaction: bson::Uuid,
85
86        /// Collection name
87        name: String,
88    },
89
90    /// Open a non-transacted collection
91    Global {
92
93        /// Collection name
94        name: String,
95    }
96}
97
98#[derive(Serialize, Deserialize, Clone, Debug, Type)]
99/// A model containing serializable information about a [crate::Collection]
100pub struct CollectionInfo {
101    /// Database info
102    pub database: DatabaseInfo,
103
104    /// Collection name
105    pub name: String,
106
107    /// Transaction ID
108    pub transaction_id: Option<bson::Uuid>,
109}
110
111#[derive(Serialize, Deserialize, Clone, Debug, Type)]
112#[serde(rename_all = "snake_case")]
113/// Whether to do one operation or multiple (in a database context)
114pub enum OperationCount {
115    ///
116    One,
117    ///
118    Many,
119}
120
121#[derive(Serialize, Deserialize, Clone, Debug, Type)]
122/// Serializable version of [polodb_core::results::UpdateResult]
123pub struct UpdateResult {
124    #[specta(type = u32)]
125    /// How many documents matched the filter
126    pub matched: u64,
127    #[specta(type = u32)]
128    /// How many documents were updated
129    pub modified: u64,
130}
131
132impl From<polodb_core::results::UpdateResult> for UpdateResult {
133    fn from(value: polodb_core::results::UpdateResult) -> Self {
134        UpdateResult {
135            matched: value.matched_count,
136            modified: value.modified_count,
137        }
138    }
139}
140
141#[derive(Serialize, Deserialize, Clone, Debug)]
142/// Specta version of [bson::Bson]
143pub struct JsonBson(bson::Bson);
144
145impl Type for JsonBson {
146    fn inline(
147        type_map: &mut specta::TypeCollection,
148        generics: specta::Generics,
149    ) -> specta::datatype::DataType {
150        serde_json::Value::inline(type_map, generics)
151    }
152}
153
154impl From<bson::Bson> for JsonBson {
155    fn from(value: bson::Bson) -> Self {
156        Self(value)
157    }
158}
159
160impl Into<bson::Bson> for JsonBson {
161    fn into(self) -> bson::Bson {
162        self.0.clone()
163    }
164}
165
166#[derive(Serialize, Deserialize, Clone, Debug)]
167/// Specta version of [bson::Document]
168pub struct JsonDocument(bson::Document);
169
170impl Type for JsonDocument {
171    fn inline(
172        type_map: &mut specta::TypeCollection,
173        generics: specta::Generics,
174    ) -> specta::datatype::DataType {
175        serde_json::Value::inline(type_map, generics)
176    }
177}
178
179impl From<bson::Document> for JsonDocument {
180    fn from(value: bson::Document) -> Self {
181        Self(value)
182    }
183}
184
185impl Into<bson::Document> for JsonDocument {
186    fn into(self) -> bson::Document {
187        self.0.clone()
188    }
189}
190
191#[derive(Serialize, Deserialize, Clone, Debug, Type)]
192#[serde(rename_all = "snake_case")]
193/// Description of the type of a file/directory/symlink
194pub enum PathFileType {
195    ///
196    Directory,
197    ///
198    File,
199    ///
200    Symlink
201}
202
203impl From<FileType> for PathFileType {
204    fn from(value: FileType) -> Self {
205        if value.is_dir() {
206            Self::Directory
207        } else if value.is_file() {
208            Self::File
209        } else {
210            Self::Symlink
211        }
212    }
213}
214
215#[derive(Serialize, Deserialize, Clone, Debug, Type)]
216/// File or folder metadata
217pub struct PathMetadata {
218    pub file_type: PathFileType,
219    pub size: u64,
220    pub last_modified: Option<chrono::DateTime<Utc>>,
221    pub last_accessed: Option<chrono::DateTime<Utc>>,
222    pub created: Option<chrono::DateTime<Utc>>,
223}
224
225impl From<Metadata> for PathMetadata {
226    fn from(value: Metadata) -> Self {
227        Self {
228            file_type: PathFileType::from(value.file_type()),
229            size: value.len(),
230            last_modified: value.modified().and_then(|systime| Ok(Some(chrono::DateTime::<Utc>::from(systime)))).unwrap_or(None),
231            last_accessed: value.accessed().and_then(|systime| Ok(Some(chrono::DateTime::<Utc>::from(systime)))).unwrap_or(None),
232            created: value.created().and_then(|systime| Ok(Some(chrono::DateTime::<Utc>::from(systime)))).unwrap_or(None)
233        }
234    }
235}
236
237#[derive(Serialize, Deserialize, Clone, Debug, Type)]
238/// General info about a path
239pub struct PathInformation {
240    pub file_name: String,
241    pub absolute_path: String,
242    pub media_type: String,
243}
244
245impl From<DirEntry> for PathInformation {
246    fn from(value: DirEntry) -> Self {
247        Self {
248            file_name: String::from_utf8_lossy(value.file_name().as_encoded_bytes()).to_string(),
249            absolute_path: String::from_utf8_lossy(value.path().into_os_string().as_encoded_bytes()).to_string(),
250            media_type: MimeGuess::from_path(value.path()).first_or_octet_stream().to_string()
251        }
252    }
253}