1use crate::FileTime;
2use std::borrow::Cow;
3use std::io::Cursor;
4use std::io::Read;
5
6#[derive(Debug)]
8pub struct Entry<'a> {
9 pub(crate) path: Box<[u8]>,
14 pub(crate) file_time: FileTime,
15 pub(crate) data: Cursor<Cow<'a, [u8]>>,
16}
17
18impl<'a> Entry<'a> {
19 fn get_file_name_start_index(&self) -> Option<usize> {
24 self.path
25 .iter()
26 .rev()
27 .position(|&b| b == b'/' || b == b'\\')
28 .map(|index| self.path.len() - index)
29 }
30
31 pub fn dir(&self) -> Option<&[u8]> {
33 let index = self.get_file_name_start_index()?.saturating_sub(1);
34 Some(&self.path[..index])
35 }
36
37 pub fn dir_str(&self) -> Option<Result<&str, std::str::Utf8Error>> {
42 self.dir().map(std::str::from_utf8)
43 }
44
45 pub fn name(&self) -> &[u8] {
47 let index = self.get_file_name_start_index().unwrap_or(0);
48 &self.path[index..]
49 }
50
51 pub fn name_str(&self) -> Result<&str, std::str::Utf8Error> {
56 std::str::from_utf8(self.name())
57 }
58
59 pub fn path(&self) -> &[u8] {
61 &self.path
62 }
63
64 pub fn path_str(&self) -> Result<&str, std::str::Utf8Error> {
69 std::str::from_utf8(self.path())
70 }
71
72 pub fn file_time(&self) -> FileTime {
76 self.file_time
77 }
78
79 pub fn iter_data(&self) -> impl Iterator<Item = u8> + '_ {
81 let borrowed = self.is_borrowed();
82
83 self.data
84 .get_ref()
85 .iter()
86 .copied()
87 .map(move |b| if borrowed { b ^ 0xf7 } else { b })
88 }
89
90 pub fn is_borrowed(&self) -> bool {
92 match self.data.get_ref() {
93 Cow::Owned(_) => false,
94 Cow::Borrowed(_) => true,
95 }
96 }
97
98 pub fn size(&self) -> usize {
100 self.data.get_ref().len()
101 }
102
103 pub fn into_owned(mut self) -> Entry<'static> {
107 Entry {
108 path: self.path,
109 file_time: self.file_time,
110 data: {
111 match self.data.get_mut() {
113 Cow::Owned(data) => Cursor::new(std::mem::take(data).into()),
114 Cow::Borrowed(data) => Cursor::new(data.iter().map(|b| b ^ 0xf7).collect()),
115 }
116 },
117 }
118 }
119}
120
121impl<'a> Read for Entry<'a> {
122 fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
123 let n = self.data.read(buf)?;
124 if self.is_borrowed() {
125 buf.iter_mut().for_each(|el| *el ^= 0xf7);
126 }
127 Ok(n)
128 }
129}
130
131impl<'a> PartialEq for Entry<'a> {
132 fn eq(&self, other: &Self) -> bool {
133 self.path == other.path && self.file_time == other.file_time
135 && self.iter_data().eq(other.iter_data())
136 }
137}