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};