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}