nuts_archive/
entry.rs

1// MIT License
2//
3// Copyright (c) 2023,2024 Robin Doer
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to
7// deal in the Software without restriction, including without limitation the
8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9// sell copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21// IN THE SOFTWARE.
22
23pub mod immut;
24pub mod mode;
25pub mod r#mut;
26pub(crate) mod tstamp;
27
28use nuts_backend::Backend;
29use nuts_bytes::{FromBytes, ToBytes, Writer};
30
31use crate::entry::mode::Mode;
32use crate::entry::tstamp::Timestamps;
33use crate::error::ArchiveResult;
34use crate::id::Id;
35use crate::pager::Pager;
36
37#[cfg(test)]
38const HALF: u8 = 53;
39#[cfg(test)]
40const FULL: u8 = 106;
41
42#[derive(Debug, FromBytes, ToBytes)]
43struct Inner {
44    name: String,
45    mode: Mode,
46    tstamps: Timestamps,
47    size: u64,
48}
49
50impl Inner {
51    fn new(name: String, mode: Mode) -> Inner {
52        Inner {
53            name,
54            mode,
55            tstamps: Timestamps::new(),
56            size: 0,
57        }
58    }
59
60    fn load<B: Backend>(pager: &mut Pager<B>, id: &Id<B>) -> ArchiveResult<Inner, B> {
61        let mut reader = pager.read_buf(id)?;
62        let inner = reader.read()?;
63
64        Ok(inner)
65    }
66
67    fn flush<B: Backend>(&self, pager: &mut Pager<B>, id: &Id<B>) -> ArchiveResult<(), B> {
68        let buf = {
69            let mut writer = Writer::new(vec![]);
70
71            writer.write(self)?;
72
73            writer.into_target()
74        };
75
76        pager.write(id, &buf)?;
77
78        Ok(())
79    }
80}
81
82macro_rules! populate_mode_api {
83    () => {
84        /// Tests whether a member of the given `group` has read access.
85        pub fn can_read(&self, group: crate::Group) -> bool {
86            self.inner().mode.can_read(group)
87        }
88
89        /// Tests whether a member of the given `group` has write access.
90        pub fn can_write(&self, group: crate::Group) -> bool {
91            self.inner().mode.can_write(group)
92        }
93
94        /// Tests whether a member of the given `group` has execute access.
95        pub fn can_execute(&self, group: crate::Group) -> bool {
96            self.inner().mode.can_execute(group)
97        }
98    };
99
100    (mut) => {
101        /// Updates the read access attribute.
102        ///
103        /// If `readable` is set to `true`, a member of the given `group` becomes
104        /// read access. If set to `false`, the read access is revoked.
105        pub fn set_readable(&mut self, group: crate::Group, readable: bool) {
106            self.inner_mut().mode.set_readable(group, readable)
107        }
108
109        /// Updates the write access attribute.
110        ///
111        /// If `writable` is set to `true`, a member of the given `group` becomes
112        /// write access. If set to `false`, the write access is revoked.
113        pub fn set_writable(&mut self, group: crate::Group, writable: bool) {
114            self.inner_mut().mode.set_writable(group, writable)
115        }
116
117        /// Updates the execute access attribute.
118        ///
119        /// If `executable` is set to `true`, a member of the given `group` becomes
120        /// execute access. If set to `false`, the execute access is revoked.
121        pub fn set_executable(&mut self, group: crate::Group, executable: bool) {
122            self.inner_mut().mode.set_executable(group, executable)
123        }
124    };
125}
126
127macro_rules! populate_tstamp_api {
128    () => {
129        /// Returns the time when the entry was appened to the archive.
130        pub fn appended(&self) -> &chrono::DateTime<chrono::Utc> {
131            self.inner().tstamps.appended()
132        }
133
134        /// Returns the time when the originating filesystem entry was created.
135        pub fn created(&self) -> &chrono::DateTime<chrono::Utc> {
136            self.inner().tstamps.created()
137        }
138
139        /// Returns the time when the originating filesystem entry was changed
140        /// the last time.
141        pub fn changed(&self) -> &chrono::DateTime<chrono::Utc> {
142            self.inner().tstamps.changed()
143        }
144
145        /// Returns the time when the originating filesystem entry was modified
146        /// the last time.
147        pub fn modified(&self) -> &chrono::DateTime<chrono::Utc> {
148            self.inner().tstamps.modified()
149        }
150    };
151
152    (mut) => {
153        populate_tstamp_api!();
154
155        /// Updates the creation time of the archive entry.
156        pub fn set_created(&mut self, created: chrono::DateTime<chrono::Utc>) {
157            self.inner_mut().tstamps.set_created(created)
158        }
159
160        /// Updates the changed time of the archive entry.
161        pub fn set_changed(&mut self, changed: chrono::DateTime<chrono::Utc>) {
162            self.inner_mut().tstamps.set_changed(changed)
163        }
164
165        /// Updates the modification time of the archive entry.
166        pub fn set_modified(&mut self, modified: chrono::DateTime<chrono::Utc>) {
167            self.inner_mut().tstamps.set_modified(modified)
168        }
169    };
170}
171
172use {populate_mode_api, populate_tstamp_api};