1use crate::{compression::Compression, path::BoxPath, AttrMap};
2
3use crate::file::{BoxMetadata, Inode};
4use std::num::NonZeroU64;
5
6#[derive(Debug, Clone)]
7pub enum Record {
8 File(FileRecord),
9 Directory(DirectoryRecord),
10 Link(LinkRecord),
11}
12
13impl Record {
14 #[inline(always)]
15 pub fn as_file(&self) -> Option<&FileRecord> {
16 match self {
17 Record::File(file) => Some(file),
18 _ => None,
19 }
20 }
21
22 #[inline(always)]
23 pub fn as_file_mut(&mut self) -> Option<&mut FileRecord> {
24 match self {
25 Record::File(file) => Some(file),
26 _ => None,
27 }
28 }
29
30 #[inline(always)]
31 pub fn as_directory(&self) -> Option<&DirectoryRecord> {
32 match self {
33 Record::Directory(dir) => Some(dir),
34 _ => None,
35 }
36 }
37
38 #[inline(always)]
39 pub fn as_directory_mut(&mut self) -> Option<&mut DirectoryRecord> {
40 match self {
41 Record::Directory(dir) => Some(dir),
42 _ => None,
43 }
44 }
45
46 #[inline(always)]
47 pub fn as_link(&self) -> Option<&LinkRecord> {
48 match self {
49 Record::Link(link) => Some(link),
50 _ => None,
51 }
52 }
53
54 #[inline(always)]
55 pub fn as_link_mut(&mut self) -> Option<&mut LinkRecord> {
56 match self {
57 Record::Link(link) => Some(link),
58 _ => None,
59 }
60 }
61
62 #[inline(always)]
63 pub fn name(&self) -> &str {
64 match self {
65 Record::File(file) => &*file.name,
66 Record::Directory(dir) => &*dir.name,
67 Record::Link(link) => &*link.name,
68 }
69 }
70
71 #[inline(always)]
72 pub fn attr<S: AsRef<str>>(&self, metadata: &BoxMetadata, key: S) -> Option<&[u8]> {
73 let key = metadata.attr_key(key.as_ref())?;
74 self.attrs().get(&key).map(|x| &**x)
75 }
76
77 #[inline(always)]
78 pub(crate) fn attrs(&self) -> &AttrMap {
79 match self {
80 Record::Directory(dir) => &dir.attrs,
81 Record::File(file) => &file.attrs,
82 Record::Link(link) => &link.attrs,
83 }
84 }
85
86 #[inline(always)]
87 pub(crate) fn attrs_mut(&mut self) -> &mut AttrMap {
88 match self {
89 Record::Directory(dir) => &mut dir.attrs,
90 Record::File(file) => &mut file.attrs,
91 Record::Link(link) => &mut link.attrs,
92 }
93 }
94}
95
96#[derive(Debug, Clone)]
97pub struct LinkRecord {
98 pub name: String,
99
100 pub target: BoxPath,
104
105 pub attrs: AttrMap,
107}
108
109impl LinkRecord {
110 #[inline(always)]
111 pub fn attr<S: AsRef<str>>(&self, metadata: &BoxMetadata, key: S) -> Option<&[u8]> {
112 let key = metadata.attr_key(key.as_ref())?;
113 self.attrs.get(&key).map(|x| &**x)
114 }
115
116 #[inline(always)]
117 pub fn upcast(self) -> Record {
118 Record::Link(self)
119 }
120}
121
122#[derive(Debug, Clone)]
123pub struct DirectoryRecord {
124 pub name: String, pub inodes: Vec<Inode>,
129
130 pub attrs: AttrMap,
132}
133
134impl DirectoryRecord {
135 pub fn new(name: String) -> DirectoryRecord {
136 DirectoryRecord {
137 name,
138 inodes: vec![],
139 attrs: AttrMap::new(),
140 }
141 }
142
143 #[inline(always)]
144 pub fn attr<S: AsRef<str>>(&self, metadata: &BoxMetadata, key: S) -> Option<&[u8]> {
145 let key = metadata.attr_key(key.as_ref())?;
146 self.attrs.get(&key).map(|x| &**x)
147 }
148
149 #[inline(always)]
150 pub fn upcast(self) -> Record {
151 Record::Directory(self)
152 }
153}
154
155#[derive(Debug, Clone)]
156pub struct FileRecord {
157 pub compression: Compression,
159
160 pub length: u64,
162
163 pub decompressed_length: u64,
165
166 pub data: NonZeroU64,
168
169 pub name: String, pub attrs: AttrMap,
174}
175
176impl FileRecord {
177 #[inline(always)]
178 pub fn compression(&self) -> Compression {
179 self.compression
180 }
181
182 #[inline(always)]
183 pub fn attr<S: AsRef<str>>(&self, metadata: &BoxMetadata, key: S) -> Option<&[u8]> {
184 let key = metadata.attr_key(key.as_ref())?;
185 self.attrs.get(&key).map(|x| &**x)
186 }
187
188 #[inline(always)]
189 pub fn upcast(self) -> Record {
190 Record::File(self)
191 }
192}