cloud_filter/filter/
info.rs1use std::{ffi::OsString, fmt::Debug, ops::Range, path::PathBuf};
2
3use nt_time::FileTime;
4use widestring::U16CStr;
5use windows::Win32::Storage::CloudFilters::{
6 self, CF_CALLBACK_DEHYDRATION_REASON, CF_CALLBACK_PARAMETERS_0_0, CF_CALLBACK_PARAMETERS_0_1,
7 CF_CALLBACK_PARAMETERS_0_10, CF_CALLBACK_PARAMETERS_0_11, CF_CALLBACK_PARAMETERS_0_2,
8 CF_CALLBACK_PARAMETERS_0_3, CF_CALLBACK_PARAMETERS_0_4, CF_CALLBACK_PARAMETERS_0_5,
9 CF_CALLBACK_PARAMETERS_0_6, CF_CALLBACK_PARAMETERS_0_7, CF_CALLBACK_PARAMETERS_0_8,
10 CF_CALLBACK_PARAMETERS_0_9,
11};
12
13pub struct FetchData(pub(crate) CF_CALLBACK_PARAMETERS_0_6);
15
16impl FetchData {
17 pub fn interrupted_hydration(&self) -> bool {
19 (self.0.Flags & CloudFilters::CF_CALLBACK_FETCH_DATA_FLAG_RECOVERY).0 != 0
20 }
21
22 pub fn explicit_hydration(&self) -> bool {
25 (self.0.Flags & CloudFilters::CF_CALLBACK_FETCH_DATA_FLAG_EXPLICIT_HYDRATION).0 != 0
26 }
27
28 pub fn required_file_range(&self) -> Range<u64> {
30 (self.0.RequiredFileOffset as u64)
31 ..(self.0.RequiredFileOffset + self.0.RequiredLength) as u64
32 }
33
34 pub fn optional_file_range(&self) -> Range<u64> {
40 (self.0.OptionalFileOffset as u64)
41 ..(self.0.OptionalFileOffset + self.0.OptionalLength) as u64
42 }
43
44 pub fn last_dehydration_time(&self) -> FileTime {
46 self.0.LastDehydrationTime.try_into().unwrap()
47 }
48
49 pub fn last_dehydration_reason(&self) -> Option<DehydrationReason> {
51 DehydrationReason::from_win32(self.0.LastDehydrationReason)
52 }
53}
54
55impl Debug for FetchData {
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 f.debug_struct("FetchData")
58 .field("interrupted_hydration", &self.interrupted_hydration())
59 .field("required_file_range", &self.required_file_range())
60 .field("optional_file_range", &self.optional_file_range())
61 .field("last_dehydration_time", &self.last_dehydration_time())
62 .field("last_dehydration_reason", &self.last_dehydration_reason())
63 .finish()
64 }
65}
66
67pub struct CancelFetchData(pub(crate) CF_CALLBACK_PARAMETERS_0_0);
69
70impl CancelFetchData {
71 pub fn timeout(&self) -> bool {
73 (self.0.Flags & CloudFilters::CF_CALLBACK_CANCEL_FLAG_IO_TIMEOUT).0 != 0
74 }
75
76 pub fn user_cancelled(&self) -> bool {
80 (self.0.Flags & CloudFilters::CF_CALLBACK_CANCEL_FLAG_IO_ABORTED).0 != 0
81 }
82
83 pub fn file_range(&self) -> Range<u64> {
85 let range = unsafe { self.0.Anonymous.FetchData };
86 (range.FileOffset as u64)..(range.FileOffset + range.Length) as u64
87 }
88}
89
90impl Debug for CancelFetchData {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 f.debug_struct("CancelFetchData")
93 .field("timeout", &self.timeout())
94 .field("user_cancelled", &self.user_cancelled())
95 .field("file_range", &self.file_range())
96 .finish()
97 }
98}
99
100pub struct ValidateData(pub(crate) CF_CALLBACK_PARAMETERS_0_11);
102
103impl ValidateData {
104 pub fn explicit_hydration(&self) -> bool {
106 (self.0.Flags & CloudFilters::CF_CALLBACK_VALIDATE_DATA_FLAG_EXPLICIT_HYDRATION).0 != 0
107 }
108
109 pub fn file_range(&self) -> Range<u64> {
111 (self.0.RequiredFileOffset as u64)
112 ..(self.0.RequiredFileOffset + self.0.RequiredLength) as u64
113 }
114}
115
116impl Debug for ValidateData {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 f.debug_struct("ValidateData")
119 .field("explicit_hydration", &self.explicit_hydration())
120 .field("file_range", &self.file_range())
121 .finish()
122 }
123}
124
125pub struct FetchPlaceholders(pub(crate) CF_CALLBACK_PARAMETERS_0_7);
128
129impl FetchPlaceholders {
130 #[cfg(feature = "globs")]
134 pub fn pattern(&self) -> Result<globset::Glob, globset::Error> {
135 let pattern = unsafe { U16CStr::from_ptr_str(self.0.Pattern.0) }.to_string_lossy();
136 globset::Glob::new(&pattern)
137 }
138
139 #[cfg(not(feature = "globs"))]
143 pub fn pattern(&self) -> String {
144 unsafe { U16CStr::from_ptr_str(self.0.Pattern.0) }.to_string_lossy()
145 }
146}
147
148impl Debug for FetchPlaceholders {
149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150 f.debug_struct("FetchPlaceholders")
151 .field("pattern", &self.pattern())
152 .finish()
153 }
154}
155
156pub struct CancelFetchPlaceholders(pub(crate) CF_CALLBACK_PARAMETERS_0_0);
159
160impl CancelFetchPlaceholders {
161 pub fn timeout(&self) -> bool {
165 (self.0.Flags & CloudFilters::CF_CALLBACK_CANCEL_FLAG_IO_TIMEOUT).0 != 0
166 }
167
168 pub fn user_cancelled(&self) -> bool {
172 (self.0.Flags & CloudFilters::CF_CALLBACK_CANCEL_FLAG_IO_ABORTED).0 != 0
173 }
174}
175
176impl Debug for CancelFetchPlaceholders {
177 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178 f.debug_struct("CancelFetchPlaceholders")
179 .field("timeout", &self.timeout())
180 .field("user_cancelled", &self.user_cancelled())
181 .finish()
182 }
183}
184
185pub struct Opened(pub(crate) CF_CALLBACK_PARAMETERS_0_8);
187
188impl Opened {
189 pub fn metadata_corrupt(&self) -> bool {
191 (self.0.Flags & CloudFilters::CF_CALLBACK_OPEN_COMPLETION_FLAG_PLACEHOLDER_UNKNOWN).0 != 0
192 }
193
194 pub fn metadata_unsupported(&self) -> bool {
196 (self.0.Flags & CloudFilters::CF_CALLBACK_OPEN_COMPLETION_FLAG_PLACEHOLDER_UNSUPPORTED).0
197 != 0
198 }
199}
200
201impl Debug for Opened {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 f.debug_struct("Opened")
204 .field("metadata_corrupt", &self.metadata_corrupt())
205 .field("metadata_unsupported", &self.metadata_unsupported())
206 .finish()
207 }
208}
209
210pub struct Closed(pub(crate) CF_CALLBACK_PARAMETERS_0_1);
212
213impl Closed {
214 pub fn deleted(&self) -> bool {
216 (self.0.Flags & CloudFilters::CF_CALLBACK_CLOSE_COMPLETION_FLAG_DELETED).0 != 0
217 }
218}
219
220impl Debug for Closed {
221 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
222 f.debug_struct("Closed")
223 .field("deleted", &self.deleted())
224 .finish()
225 }
226}
227
228pub struct Dehydrate(pub(crate) CF_CALLBACK_PARAMETERS_0_3);
230
231impl Dehydrate {
232 pub fn background(&self) -> bool {
234 (self.0.Flags & CloudFilters::CF_CALLBACK_DEHYDRATE_FLAG_BACKGROUND).0 != 0
235 }
236
237 pub fn reason(&self) -> Option<DehydrationReason> {
239 DehydrationReason::from_win32(self.0.Reason)
240 }
241}
242
243impl Debug for Dehydrate {
244 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245 f.debug_struct("Dehydrate")
246 .field("background", &self.background())
247 .field("reason", &self.reason())
248 .finish()
249 }
250}
251
252pub struct Dehydrated(pub(crate) CF_CALLBACK_PARAMETERS_0_2);
254
255impl Dehydrated {
256 pub fn background(&self) -> bool {
258 (self.0.Flags & CloudFilters::CF_CALLBACK_DEHYDRATE_COMPLETION_FLAG_BACKGROUND).0 != 0
259 }
260
261 pub fn already_hydrated(&self) -> bool {
263 (self.0.Flags & CloudFilters::CF_CALLBACK_DEHYDRATE_COMPLETION_FLAG_DEHYDRATED).0 != 0
264 }
265
266 pub fn reason(&self) -> Option<DehydrationReason> {
268 DehydrationReason::from_win32(self.0.Reason)
269 }
270}
271
272impl Debug for Dehydrated {
273 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274 f.debug_struct("Dehydrated")
275 .field("background", &self.background())
276 .field("already_hydrated", &self.already_hydrated())
277 .field("reason", &self.reason())
278 .finish()
279 }
280}
281
282pub struct Delete(pub(crate) CF_CALLBACK_PARAMETERS_0_5);
284
285impl Delete {
286 pub fn is_directory(&self) -> bool {
288 (self.0.Flags & CloudFilters::CF_CALLBACK_DELETE_FLAG_IS_DIRECTORY).0 != 0
289 }
290
291 pub fn is_undelete(&self) -> bool {
294 (self.0.Flags & CloudFilters::CF_CALLBACK_DELETE_FLAG_IS_UNDELETE).0 != 0
295 }
296}
297
298impl Debug for Delete {
299 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
300 f.debug_struct("Delete")
301 .field("is_directory", &self.is_directory())
302 .field("is_undelete", &self.is_undelete())
303 .finish()
304 }
305}
306
307#[derive(Debug)]
309#[allow(dead_code)]
310pub struct Deleted(pub(crate) CF_CALLBACK_PARAMETERS_0_4);
311
312pub struct Rename(pub(crate) CF_CALLBACK_PARAMETERS_0_10, pub(crate) OsString);
314
315impl Rename {
316 pub fn is_directory(&self) -> bool {
318 (self.0.Flags & CloudFilters::CF_CALLBACK_RENAME_FLAG_IS_DIRECTORY).0 != 0
319 }
320
321 pub fn source_in_scope(&self) -> bool {
323 (self.0.Flags & CloudFilters::CF_CALLBACK_RENAME_FLAG_SOURCE_IN_SCOPE).0 != 0
324 }
325
326 pub fn target_in_scope(&self) -> bool {
328 (self.0.Flags & CloudFilters::CF_CALLBACK_RENAME_FLAG_TARGET_IN_SCOPE).0 != 0
329 }
330
331 pub fn target_path(&self) -> PathBuf {
333 let mut path = PathBuf::from(&self.1);
334 path.push(unsafe { U16CStr::from_ptr_str(self.0.TargetPath.0) }.to_os_string());
335 path
336 }
337}
338
339impl Debug for Rename {
340 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
341 f.debug_struct("Rename")
342 .field("is_directory", &self.is_directory())
343 .field("source_in_scope", &self.source_in_scope())
344 .field("target_in_scope", &self.target_in_scope())
345 .field("target_path", &self.target_path())
346 .finish()
347 }
348}
349
350pub struct Renamed(pub(crate) CF_CALLBACK_PARAMETERS_0_9, pub(crate) OsString);
352
353impl Renamed {
354 pub fn source_path(&self) -> PathBuf {
356 let mut path = PathBuf::from(&self.1);
357 path.push(unsafe { U16CStr::from_ptr_str(self.0.SourcePath.0) }.to_os_string());
358 path
359 }
360}
361
362impl Debug for Renamed {
363 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
364 f.debug_struct("Renamed")
365 .field("source_path", &self.source_path())
366 .finish()
367 }
368}
369
370#[derive(Debug, Clone, Copy, PartialEq, Eq)]
372pub enum DehydrationReason {
373 UserManually,
375 LowSpace,
378 Inactive,
382 OsUpgrade,
385}
386
387impl DehydrationReason {
388 fn from_win32(reason: CF_CALLBACK_DEHYDRATION_REASON) -> Option<DehydrationReason> {
389 match reason {
390 CloudFilters::CF_CALLBACK_DEHYDRATION_REASON_USER_MANUAL => Some(Self::UserManually),
391 CloudFilters::CF_CALLBACK_DEHYDRATION_REASON_SYSTEM_LOW_SPACE => Some(Self::LowSpace),
392 CloudFilters::CF_CALLBACK_DEHYDRATION_REASON_SYSTEM_INACTIVITY => Some(Self::Inactive),
393 CloudFilters::CF_CALLBACK_DEHYDRATION_REASON_SYSTEM_OS_UPGRADE => Some(Self::OsUpgrade),
394 _ => None,
395 }
396 }
397}