keypropdecode/props/mod.rs
1mod implementations;
2#[cfg(test)]
3mod tests;
4
5use crate::error::*;
6
7/// This struct is the one that gives you the desired behaviour.
8///
9/// It implements the following traits:
10/// 1. Display for Props
11/// 2. From<u32> for Props
12/// 3. From<Props> for u32
13/// 4. TryFrom<Pathbuf> for Props
14/// 5. TryFrom<&Pathbuf> for Props
15/// 6. TryFrom<&str> for Props
16/// (The TryFrom ones won't appear in the documentation because they use Windows specific behaviour and it is put behind a conditional flag because docs.rs only uses a Linux container)
17#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Default)]
18pub struct Props {
19 element_type: ArcDir,
20 hidden: bool, // 2 -> bit 2
21 system: bool, // 4 -> bit 3
22 device: bool, // 64 -> bit 7
23 reparse: bool, // 1024 -> bit 11
24 compressed: bool, // 2048 -> bit 12
25 not_content_indexed: bool, // 8192 -> bit 14
26 encrypted: bool, // 16384 -> bit 15
27 integrity_stream: bool, // 32768 -> bit 16
28 virtual_file: bool, //For system reserved use 65536 -> bit 17
29 no_scrub_data: bool, // 131072 -> bit 18
30 extended_attributes: bool, // 262144 -> bit 19
31 pinned: bool, // 524288 -> bit 20
32 unpinned: bool, // 1048576 -> bit 21
33 recall_on_open: bool, // 262144 -> bit 22
34 recall_on_data_access: bool, // 4194304 -> bit 23
35}
36/// This enum stores the state of the file system element.
37/// Because it can't be a file and a directory at the same time, an enum here makes the most sense.
38/// Even so when it's a file it has some special properties, so that is hold in the enum variant of
39/// the file.
40/// Neither this enum or the struct that holds has any custom implementations, only the ones
41/// derived from macros
42#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Default)]
43pub enum ArcDir {
44 #[default]
45 Directory, // 16 -> bit 5
46 Archive(ArchiveProps), // 32 -> bit 6
47}
48/// This struct holds the values of the file-exclusive elements
49/// It only has the implementation derived by the macros
50#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Default)]
51pub struct ArchiveProps {
52 read_only: bool, // 1 -> bit 1
53 normal: bool, // 128 -> bit 8
54 temporary: bool, // 256 -> bit 9
55 sparse: bool, // 512 -> bit 10
56 offline: bool, // 4096 -> bit 13
57}
58impl Props {
59 /// Returns true if the element is read_only. Not available on folders.
60 /// ```
61 /// use keypropdecode::props::*;
62 /// let mut props = Props::default();
63 /// props.change_element_type(ArcDir::Archive(ArchiveProps::default()));
64 /// props.read_only(true).unwrap();
65 ///
66 /// assert_eq!(props.is_read_only(), Ok(true));
67 /// ```
68 pub fn is_read_only(&self) -> Result<bool> {
69 match self.element_type {
70 ArcDir::Archive(arc_props) => Ok(arc_props.read_only),
71 ArcDir::Directory => Err(Error {
72 kind: ErrorKind::NotAFile(
73 "The read_only property is exclusive for files".to_string(),
74 ),
75 }),
76 }
77 }
78 /// Allows to change the read_only state. Not available on folder.
79 pub fn read_only(&mut self, read_only: bool) -> Result<()> {
80 match self.element_type {
81 ArcDir::Archive(mut arc_props) => {
82 arc_props.read_only = read_only;
83 arc_props.normal = false;
84 self.element_type = ArcDir::Archive(arc_props);
85 Ok(())
86 }
87 ArcDir::Directory => Err(Error {
88 kind: ErrorKind::NotAFile(
89 "The read_only property is exclusive for files".to_string(),
90 ),
91 }),
92 }
93 }
94 /// Returns true if the element is hidden.
95 /// ```
96 /// use keypropdecode::props::*;
97 /// let mut props = Props::default();
98 /// props.hidden(true);
99 ///
100 /// assert_eq!(props.is_hidden(), true);
101 /// ```
102 pub fn is_hidden(&self) -> bool {
103 self.hidden
104 }
105 /// Allows to change the hidden state.
106 pub fn hidden(&mut self, hidden: bool) {
107 if let ArcDir::Archive(mut arc_props) = self.element_type {
108 if hidden {
109 arc_props.normal = false;
110 self.element_type = ArcDir::Archive(arc_props);
111 }
112 }
113 self.hidden = hidden;
114 }
115 /// Returns true if the element is used for system purposes.
116 /// ```
117 /// use keypropdecode::props::*;
118 /// let mut props = Props::from(0x4);
119 ///
120 /// assert_eq!(props.is_system(), true);
121 /// ```
122 pub fn is_system(&self) -> bool {
123 self.system
124 }
125 fn _system(&mut self, system: bool) {
126 if let ArcDir::Archive(mut arc_props) = self.element_type {
127 if system {
128 arc_props.normal = false;
129 self.element_type = ArcDir::Archive(arc_props);
130 }
131 }
132 self.system = system;
133 }
134 /// Returns true if the element is a file.
135 /// ```
136 /// use keypropdecode::props::*;
137 /// let mut props = Props::default();
138 /// props.change_element_type(ArcDir::Archive(ArchiveProps::default()));
139 ///
140 /// assert_eq!(props.is_archive(), true);
141 /// ```
142 pub fn is_archive(&self) -> bool {
143 match self.element_type {
144 ArcDir::Archive(_) => true,
145 ArcDir::Directory => false,
146 }
147 }
148 /// Returns true if the element is a folder.
149 /// ```
150 /// use keypropdecode::props::*;
151 /// let mut props = Props::default();
152 /// props.change_element_type(ArcDir::Directory);
153 ///
154 /// assert_eq!(props.is_directory(), true);
155 /// ```
156 pub fn is_directory(&self) -> bool {
157 match self.element_type {
158 ArcDir::Directory => true,
159 ArcDir::Archive(_) => false,
160 }
161 }
162 /// Allows to change the state archive state.
163 /// You give the enum with the properties neccesary, no error checking neccesary.
164 pub fn change_element_type(&mut self, element_type: ArcDir) {
165 self.element_type = element_type;
166 }
167 /// Returns true if the element represents a physical device in the file system. Reserved for system use
168 /// ```
169 /// use keypropdecode::props::*;
170 /// let mut props = Props::from(0x40);
171 ///
172 /// assert_eq!(props.is_device(), true);
173 /// ```
174 pub fn is_device(&self) -> bool {
175 self.device
176 }
177 fn _device(&mut self, device: bool) {
178 if let ArcDir::Archive(mut arc_props) = self.element_type {
179 if device {
180 arc_props.normal = false;
181 self.element_type = ArcDir::Archive(arc_props);
182 }
183 }
184 self.device = device;
185 }
186 /// Returns true if the element represents a normal file (a file that doesn't have any properties except being a file(check docs for more info)).
187 /// ```
188 /// use keypropdecode::props::*;
189 /// let mut props = Props::default();
190 /// props.change_element_type(ArcDir::Archive(ArchiveProps::default()));
191 /// props.normal(true);
192 ///
193 /// assert_eq!(props.is_normal(), Ok(true));
194 /// ```
195 pub fn is_normal(&self) -> Result<bool> {
196 match self.element_type {
197 ArcDir::Archive(arc_props) => Ok(arc_props.normal),
198 ArcDir::Directory => Err(Error {
199 kind: ErrorKind::NotAFile("The normal property is exclusive for files".to_string()),
200 }),
201 }
202 }
203 /// Allows to change the normal state.
204 pub fn normal(&mut self, normal: bool) -> Result<()> {
205 let comp_arc_props = ArchiveProps {
206 normal: true,
207 ..Default::default()
208 };
209 let comp_arc_props_2 = ArchiveProps::default();
210 match self.element_type {
211 ArcDir::Archive(mut arc_props) => {
212 if arc_props == comp_arc_props || arc_props == comp_arc_props_2 {
213 arc_props.normal = normal;
214 self.element_type = ArcDir::Archive(arc_props);
215 } else {
216 return Err(Error { kind: ErrorKind::Other("The normal file property must be only applied in a file with only itself set to true".to_string()) });
217 }
218 Ok(())
219 }
220 ArcDir::Directory => Err(Error {
221 kind: ErrorKind::NotAFile("The normal property is exclusive for files".to_string()),
222 }),
223 }
224 }
225 /// Returns true if the element represents a temporary file.
226 /// ```
227 /// use keypropdecode::props::*;
228 /// let mut props = Props::default();
229 /// props.change_element_type(ArcDir::Archive(ArchiveProps::default()));
230 /// props.temporary(true).unwrap();
231 ///
232 /// assert_eq!(props.is_temporary(), Ok(true));
233 /// ```
234 pub fn is_temporary(&self) -> Result<bool> {
235 match self.element_type {
236 ArcDir::Archive(arc_props) => Ok(arc_props.temporary),
237 ArcDir::Directory => Err(Error {
238 kind: ErrorKind::NotAFile(
239 "The temporary property is exclusive for files".to_string(),
240 ),
241 }),
242 }
243 }
244 /// Allows to change the temporary state
245 pub fn temporary(&mut self, temporary: bool) -> Result<()> {
246 match self.element_type {
247 ArcDir::Archive(mut arc_props) => {
248 arc_props.temporary = temporary;
249 arc_props.normal = false;
250 self.element_type = ArcDir::Archive(arc_props);
251 Ok(())
252 }
253 ArcDir::Directory => Err(Error {
254 kind: ErrorKind::NotAFile(
255 "The temporary property is exclusive for files".to_string(),
256 ),
257 }),
258 }
259 }
260 /// Returns true if the element represents a sparse file (made small for space saving purposes).
261 /// ```
262 /// use keypropdecode::props::*;
263 /// let mut props = Props::default();
264 /// props.change_element_type(ArcDir::Archive(ArchiveProps::default()));
265 /// props.sparse(true).unwrap();
266 ///
267 /// assert_eq!(props.is_sparse(), Ok(true));
268 /// ```
269 pub fn is_sparse(&self) -> Result<bool> {
270 match self.element_type {
271 ArcDir::Archive(arc_props) => Ok(arc_props.sparse),
272 ArcDir::Directory => Err(Error {
273 kind: ErrorKind::NotAFile("The sparse property is exclusive for files".to_string()),
274 }),
275 }
276 }
277 /// Allows to change the sparse state.
278 pub fn sparse(&mut self, sparse: bool) -> Result<()> {
279 match self.element_type {
280 ArcDir::Archive(mut arc_props) => {
281 arc_props.sparse = sparse;
282 arc_props.normal = false;
283 self.element_type = ArcDir::Archive(arc_props);
284 Ok(())
285 }
286 ArcDir::Directory => Err(Error {
287 kind: ErrorKind::NotAFile("The sparse property is exclusive for files".to_string()),
288 }),
289 }
290 }
291 /// Returns true if the element represents a reparse point in the file system (e.g. a symbolic link).
292 /// ```
293 /// use keypropdecode::props::*;
294 /// let mut props = Props::default();
295 /// props.reparse(true);
296 ///
297 /// assert_eq!(props.is_reparse(), true);
298 /// ```
299 pub fn is_reparse(&self) -> bool {
300 self.reparse
301 }
302 /// Allows to change the reparse state.
303 pub fn reparse(&mut self, reparse: bool) {
304 if let ArcDir::Archive(mut arc_props) = self.element_type {
305 if reparse {
306 arc_props.normal = false;
307 self.element_type = ArcDir::Archive(arc_props);
308 }
309 }
310 self.reparse = reparse;
311 }
312 /// Returns true if the element represents a compressed file
313 /// ```
314 /// use keypropdecode::props::*;
315 /// let mut props = Props::default();
316 /// props.compressed(true);
317 ///
318 /// assert_eq!(props.is_compressed(), true);
319 /// ```
320 pub fn is_compressed(&self) -> bool {
321 self.compressed
322 }
323 /// Allows to change the compressed state
324 pub fn compressed(&mut self, compressed: bool) {
325 if let ArcDir::Archive(mut arc_props) = self.element_type {
326 if compressed {
327 arc_props.normal = false;
328 self.element_type = ArcDir::Archive(arc_props);
329 }
330 }
331 self.compressed = compressed;
332 }
333 /// Returns true if the element is not available inmediately. Aplications should not change this value in an arbitrary way.
334 /// ```
335 /// use keypropdecode::props::*;
336 /// let mut props = Props::default();
337 /// props.change_element_type(ArcDir::Archive(ArchiveProps::default()));
338 /// props.offline(true).unwrap();
339 ///
340 /// assert_eq!(props.is_offline(), Ok(true));
341 /// ```
342 pub fn is_offline(&self) -> Result<bool> {
343 match self.element_type {
344 ArcDir::Archive(arc_props) => Ok(arc_props.offline),
345 ArcDir::Directory => Err(Error {
346 kind: ErrorKind::NotAFile("The offline property is exclusive to files".to_string()),
347 }),
348 }
349 }
350 /// Allows to change the offline state
351 pub fn offline(&mut self, offline: bool) -> Result<()> {
352 match self.element_type {
353 ArcDir::Archive(mut arc_props) => {
354 arc_props.offline = offline;
355 arc_props.normal = false;
356 self.element_type = ArcDir::Archive(arc_props);
357 Ok(())
358 }
359 ArcDir::Directory => Err(Error {
360 kind: ErrorKind::NotAFile("The offline property is exclusive to files".to_string()),
361 }),
362 }
363 }
364 /// Returns true if the element isn't indexed by the content indexing service
365 /// ```
366 /// use keypropdecode::props::*;
367 /// let mut props = Props::default();
368 /// props.not_content_indexed(true);
369 ///
370 /// assert_eq!(props.is_not_content_indexed(), true);
371 /// ```
372 pub fn is_not_content_indexed(&self) -> bool {
373 self.not_content_indexed
374 }
375 /// Allows to change the not_content_indexed state
376 pub fn not_content_indexed(&mut self, not_content_indexed: bool) {
377 if let ArcDir::Archive(mut arc_props) = self.element_type {
378 if not_content_indexed {
379 arc_props.normal = false;
380 self.element_type = ArcDir::Archive(arc_props);
381 }
382 }
383 self.not_content_indexed = not_content_indexed;
384 }
385 /// Returns true if the element is encrypted
386 /// ```
387 /// use keypropdecode::props::*;
388 /// let mut props = Props::default();
389 /// props.encrypted(true);
390 ///
391 /// assert_eq!(props.is_encrypted(), true);
392 /// ```
393 pub fn is_encrypted(&self) -> bool {
394 self.encrypted
395 }
396 /// Allows to change the encrypted state
397 pub fn encrypted(&mut self, encrypted: bool) {
398 if let ArcDir::Archive(mut arc_props) = self.element_type {
399 if encrypted {
400 arc_props.normal = false;
401 self.element_type = ArcDir::Archive(arc_props);
402 }
403 }
404 self.encrypted = encrypted;
405 }
406 /// Returns true if the directory or user data stream is configured with integrity
407 /// ```
408 /// use keypropdecode::props::*;
409 /// let mut props = Props::default();
410 /// props.integrity_stream(true);
411 ///
412 /// assert_eq!(props.is_integrity_stream(), true);
413 /// ```
414 pub fn is_integrity_stream(&self) -> bool {
415 self.integrity_stream
416 }
417 /// Allows to change the integrity_stream state
418 pub fn integrity_stream(&mut self, integrity_stream: bool) {
419 if let ArcDir::Archive(mut arc_props) = self.element_type {
420 if integrity_stream {
421 arc_props.normal = false;
422 self.element_type = ArcDir::Archive(arc_props);
423 }
424 }
425 self.integrity_stream = integrity_stream;
426 }
427 /// Returns true if the element is a virtual file. This value is reserver for system use
428 /// ```
429 /// use keypropdecode::props::*;
430 /// let mut props = Props::from(0x10000);
431 ///
432 /// assert_eq!(props.is_virtual_file(), true);
433 /// ```
434 pub fn is_virtual_file(&self) -> bool {
435 self.virtual_file
436 }
437 fn _virtual_file(&mut self, virtual_file: bool) {
438 if let ArcDir::Archive(mut arc_props) = self.element_type {
439 if virtual_file {
440 arc_props.normal = false;
441 self.element_type = ArcDir::Archive(arc_props);
442 }
443 }
444 self.virtual_file = virtual_file;
445 }
446 /// Returns true if the user data stream not to be read by the background data integrity scanner (AKA scrubber)
447 /// ```
448 /// use keypropdecode::props::*;
449 /// let mut props = Props::default();
450 /// props.no_scrub_data(true);
451 ///
452 /// assert_eq!(props.is_no_scrub_data(), true);
453 /// ```
454 pub fn is_no_scrub_data(&self) -> bool {
455 self.no_scrub_data
456 }
457 /// Allows to change the virtual_file state
458 pub fn no_scrub_data(&mut self, no_scrub_data: bool) {
459 if let ArcDir::Archive(mut arc_props) = self.element_type {
460 if no_scrub_data {
461 arc_props.normal = false;
462 self.element_type = ArcDir::Archive(arc_props);
463 }
464 }
465 self.no_scrub_data = no_scrub_data;
466 }
467 /// Returns true if the element has got extended attributes. System internal use only.
468 /// ```
469 /// use keypropdecode::props::*;
470 /// let mut props = Props::from(0x40000);
471 ///
472 /// assert_eq!(props.is_extended_attributes(), true);
473 /// ```
474 pub fn is_extended_attributes(&self) -> bool {
475 self.extended_attributes
476 }
477 fn _extended_attributes(&mut self, extended_attributes: bool) {
478 if let ArcDir::Archive(mut arc_props) = self.element_type {
479 if extended_attributes {
480 arc_props.normal = false;
481 self.element_type = ArcDir::Archive(arc_props);
482 }
483 }
484 self.extended_attributes = extended_attributes;
485 }
486 /// Returns true if the element is indicated user intent that the file or directory should be kept fully present locally even when not being actively accessed.
487 /// ```
488 /// use keypropdecode::props::*;
489 /// let mut props = Props::default();
490 /// props.pinned(true);
491 ///
492 /// assert_eq!(props.is_pinned(), true);
493 /// ```
494 pub fn is_pinned(&self) -> bool {
495 self.pinned
496 }
497 /// Allows to change the pinned state
498 pub fn pinned(&mut self, pinned: bool) {
499 if let ArcDir::Archive(mut arc_props) = self.element_type {
500 if pinned {
501 arc_props.normal = false;
502 self.element_type = ArcDir::Archive(arc_props);
503 }
504 }
505 self.pinned = pinned;
506 }
507 /// Returns true if the element is indicated user intent that the file or directory shouldn't be kept fully present locally except when being actively accessed.
508 /// ```
509 /// use keypropdecode::props::*;
510 /// let mut props = Props::default();
511 /// props.unpinned(true);
512 ///
513 /// assert_eq!(props.is_unpinned(), true);
514 /// ```
515 pub fn is_unpinned(&self) -> bool {
516 self.unpinned
517 }
518 /// Allows to change the unpinned state
519 pub fn unpinned(&mut self, unpinned: bool) {
520 self.unpinned = unpinned;
521 }
522 /// Returns true if the element hasn't got any physical representation on the local system; the item is vitual. Opening the item will be more expensive than normal, e.g., a file in a remote storage
523 /// ```
524 /// use keypropdecode::props::*;
525 /// let mut props = Props::default();
526 /// props.recall_on_open(true);
527 ///
528 /// assert_eq!(props.is_recall_on_open(), true);
529 /// ```
530 pub fn is_recall_on_open(&self) -> bool {
531 self.recall_on_open
532 }
533 /// Allows to change the recall_on_open state
534 pub fn recall_on_open(&mut self, recall_on_open: bool) {
535 if let ArcDir::Archive(mut arc_props) = self.element_type {
536 if recall_on_open {
537 arc_props.normal = false;
538 self.element_type = ArcDir::Archive(arc_props);
539 }
540 }
541 self.recall_on_open = recall_on_open;
542 }
543 /// Returns true if the element isn't fully present locally.
544 /// ```
545 /// use keypropdecode::props::*;
546 /// let mut props = Props::default();
547 /// props.recall_on_data_access(true);
548 ///
549 /// assert_eq!(props.is_recall_on_data_access(), true);
550 /// ```
551 pub fn is_recall_on_data_access(&self) -> bool {
552 self.recall_on_data_access
553 }
554 /// Allows to change the recall_on_data_access state
555 pub fn recall_on_data_access(&mut self, recall_on_data_access: bool) {
556 if let ArcDir::Archive(mut arc_props) = self.element_type {
557 if recall_on_data_access {
558 arc_props.normal = false;
559 self.element_type = ArcDir::Archive(arc_props);
560 }
561 }
562 self.recall_on_data_access = recall_on_data_access;
563 }
564}