1use crate::schema::file_records;
2use diesel::prelude::*;
3use serde::{Deserialize, Serialize};
4use time::OffsetDateTime;
5
6use diesel::deserialize::FromSqlRow;
7use diesel::expression::AsExpression;
8use diesel::sql_types::Integer;
9
10#[repr(i32)]
11#[derive(Debug, Clone, Copy, AsExpression, FromSqlRow, PartialEq, Deserialize, Serialize)]
12#[diesel(sql_type = Integer)]
13pub enum FileFormat {
14 Binary = 1,
15 Text = 2,
16}
17
18#[derive(Debug)]
19pub enum IndexerUpdateEvent {
20 Updated,
21}
22
23#[derive(Queryable, Selectable, Identifiable, Debug, Clone)]
24#[diesel(table_name = file_records)]
25#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
26pub struct FileRecord {
27 pub id: i32,
28 pub jid: Option<i32>,
29 pub deleted: bool,
30 pub path: String,
31 pub size: i64,
32 pub modified_at: OffsetDateTime,
33 pub namespace_id: i32,
34}
35
36#[derive(Insertable, Debug, Clone)]
37#[diesel(table_name = file_records)]
38#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
39pub struct CreateForm {
40 pub jid: Option<i32>,
41 pub path: String,
42 pub deleted: bool,
43 pub size: i64,
44 pub modified_at: OffsetDateTime,
45 pub namespace_id: i32,
46}
47
48#[derive(Insertable, Debug, Clone)]
49#[diesel(table_name = file_records)]
50#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
51pub struct DeleteForm {
52 pub path: String,
53 pub jid: Option<i32>,
54 pub size: i64,
55 pub modified_at: OffsetDateTime,
56 pub deleted: bool,
57 pub namespace_id: i32,
58}
59
60#[derive(AsChangeset, Debug, Clone)]
61#[diesel(table_name = file_records)]
62#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
63pub struct FileRecordUpdateForm {
64 pub size: i64,
65 pub modified_at: OffsetDateTime,
66}
67
68#[derive(AsChangeset, Debug, Clone)]
69#[diesel(table_name = file_records)]
70#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
71pub struct FileRecordNonDeletedFilterForm {
72 pub deleted: bool,
73}
74
75#[derive(AsChangeset, Debug, Clone)]
76#[diesel(table_name = file_records)]
77#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
78pub struct FileRecordDeleteForm {
79 pub id: i32,
80 pub deleted: bool,
81 pub namespace_id: i32,
82}
83
84impl PartialEq<CreateForm> for FileRecord {
85 fn eq(&self, other: &CreateForm) -> bool {
86 self.path == other.path && self.size == other.size && self.modified_at == other.modified_at
87 }
88}
89
90#[derive(Debug, Clone)]
92#[cfg_attr(feature = "ffi", derive(uniffi::Enum))]
93pub enum SyncStatus {
94 Idle,
96 Syncing,
98 Indexing,
100 Downloading,
102 Uploading,
104 Error { message: String },
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111 use time::OffsetDateTime;
112
113 #[test]
114 fn test_file_format_values() {
115 assert_eq!(FileFormat::Binary as i32, 1);
116 assert_eq!(FileFormat::Text as i32, 2);
117 }
118
119 #[test]
120 fn test_file_format_equality() {
121 assert_eq!(FileFormat::Binary, FileFormat::Binary);
122 assert_eq!(FileFormat::Text, FileFormat::Text);
123 assert_ne!(FileFormat::Binary, FileFormat::Text);
124 }
125
126 #[test]
127 fn test_file_record_create_form_equality() {
128 let now = OffsetDateTime::now_utc();
129
130 let record = FileRecord {
131 id: 1,
132 jid: Some(100),
133 deleted: false,
134 path: "test/path.txt".to_string(),
135 size: 1024,
136 modified_at: now,
137 namespace_id: 1,
138 };
139
140 let form = CreateForm {
141 jid: Some(100),
142 path: "test/path.txt".to_string(),
143 deleted: false,
144 size: 1024,
145 modified_at: now,
146 namespace_id: 1,
147 };
148
149 assert_eq!(record, form);
151 }
152
153 #[test]
154 fn test_file_record_create_form_inequality_different_path() {
155 let now = OffsetDateTime::now_utc();
156
157 let record = FileRecord {
158 id: 1,
159 jid: Some(100),
160 deleted: false,
161 path: "test/path1.txt".to_string(),
162 size: 1024,
163 modified_at: now,
164 namespace_id: 1,
165 };
166
167 let form = CreateForm {
168 jid: Some(100),
169 path: "test/path2.txt".to_string(),
170 deleted: false,
171 size: 1024,
172 modified_at: now,
173 namespace_id: 1,
174 };
175
176 assert_ne!(record, form);
178 }
179
180 #[test]
181 fn test_file_record_create_form_inequality_different_size() {
182 let now = OffsetDateTime::now_utc();
183
184 let record = FileRecord {
185 id: 1,
186 jid: Some(100),
187 deleted: false,
188 path: "test/path.txt".to_string(),
189 size: 1024,
190 modified_at: now,
191 namespace_id: 1,
192 };
193
194 let form = CreateForm {
195 jid: Some(100),
196 path: "test/path.txt".to_string(),
197 deleted: false,
198 size: 2048,
199 modified_at: now,
200 namespace_id: 1,
201 };
202
203 assert_ne!(record, form);
205 }
206
207 #[test]
208 fn test_create_form_construction() {
209 let now = OffsetDateTime::now_utc();
210
211 let form = CreateForm {
212 jid: Some(42),
213 path: "recipes/test.cook".to_string(),
214 deleted: false,
215 size: 512,
216 modified_at: now,
217 namespace_id: 5,
218 };
219
220 assert_eq!(form.jid, Some(42));
221 assert_eq!(form.path, "recipes/test.cook");
222 assert_eq!(form.deleted, false);
223 assert_eq!(form.size, 512);
224 assert_eq!(form.namespace_id, 5);
225 }
226
227 #[test]
228 fn test_delete_form_construction() {
229 let now = OffsetDateTime::now_utc();
230
231 let form = DeleteForm {
232 path: "recipes/deleted.cook".to_string(),
233 jid: Some(99),
234 size: 0,
235 modified_at: now,
236 deleted: true,
237 namespace_id: 1,
238 };
239
240 assert_eq!(form.path, "recipes/deleted.cook");
241 assert_eq!(form.deleted, true);
242 assert_eq!(form.size, 0);
243 }
244
245 #[test]
246 fn test_file_record_update_form() {
247 let now = OffsetDateTime::now_utc();
248
249 let update_form = FileRecordUpdateForm {
250 size: 2048,
251 modified_at: now,
252 };
253
254 assert_eq!(update_form.size, 2048);
255 assert_eq!(update_form.modified_at, now);
256 }
257
258 #[test]
259 fn test_sync_status_variants() {
260 let idle = SyncStatus::Idle;
261 let syncing = SyncStatus::Syncing;
262 let indexing = SyncStatus::Indexing;
263 let downloading = SyncStatus::Downloading;
264 let uploading = SyncStatus::Uploading;
265 let error = SyncStatus::Error {
266 message: "Test error".to_string(),
267 };
268
269 assert!(matches!(idle, SyncStatus::Idle));
271 assert!(matches!(syncing, SyncStatus::Syncing));
272 assert!(matches!(indexing, SyncStatus::Indexing));
273 assert!(matches!(downloading, SyncStatus::Downloading));
274 assert!(matches!(uploading, SyncStatus::Uploading));
275 assert!(matches!(error, SyncStatus::Error { .. }));
276 }
277}