1use std::io::{self, Read};
2
3mod consts;
4mod decompress;
5mod supermaster_decompressed;
6pub mod uc2_archive;
7
8#[derive(Debug, Clone, Copy, Default)]
10pub struct Location {
11 pub volume: u32,
12 pub offset: u32,
13}
14
15pub(crate) struct ExtendedHeader {
16 pub c_dir_loc: Location,
18}
19
20const EXT_HEADER_SIZE: usize = 16;
22
23impl ExtendedHeader {
24 pub fn load_from<T: Read>(reader: &mut T) -> io::Result<Self> {
25 let mut header_bytes = [0u8; EXT_HEADER_SIZE];
26 reader.read_exact(&mut header_bytes)?;
27 let c_dir_loc_volume = u32::from_le_bytes([
28 header_bytes[0],
29 header_bytes[1],
30 header_bytes[2],
31 header_bytes[3],
32 ]);
33 let c_dir_loc_offset = u32::from_le_bytes([
34 header_bytes[4],
35 header_bytes[5],
36 header_bytes[6],
37 header_bytes[7],
38 ]);
39 Ok(Self {
41 c_dir_loc: Location {
42 volume: c_dir_loc_volume,
43 offset: c_dir_loc_offset,
44 },
45 })
46 }
47}
48
49#[derive(Debug, Clone, Default)]
51pub struct CompressInfo {
52 pub compressed_length: u32,
53 pub method: u16,
54 pub master_prefix: u32,
55}
56
57impl CompressInfo {
58 pub fn load_from<T: Read>(reader: &mut T) -> io::Result<Self> {
59 let mut buf = [0u8; 10];
60 reader.read_exact(&mut buf)?;
61 let mut data = buf.as_slice();
62 convert_u32!(compressed_length, data);
63 convert_u16!(method, data);
64 convert_u32!(master_prefix, data);
65 Ok(Self {
66 compressed_length,
67 method,
68 master_prefix,
69 })
70 }
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75#[repr(u8)]
76pub enum EntryType {
77 DirEntry = 1,
78 FileEntry = 2,
79 MasterEntry = 3,
80 EndOfCdir = 4,
81}
82
83impl TryFrom<u8> for EntryType {
84 type Error = io::Error;
85
86 fn try_from(value: u8) -> Result<Self, Self::Error> {
87 match value {
88 1 => Ok(EntryType::DirEntry),
89 2 => Ok(EntryType::FileEntry),
90 3 => Ok(EntryType::MasterEntry),
91 4 => Ok(EntryType::EndOfCdir),
92 _ => Err(io::Error::new(
93 io::ErrorKind::InvalidData,
94 format!("invalid entry type: {}", value),
95 )),
96 }
97 }
98}
99
100#[derive(Debug, Clone, Copy, Default)]
102pub struct FileAttributes(u8);
103
104impl FileAttributes {
105 pub fn is_readonly(&self) -> bool {
106 self.0 & 0x01 != 0
107 }
108 pub fn is_hidden(&self) -> bool {
109 self.0 & 0x02 != 0
110 }
111 pub fn is_system(&self) -> bool {
112 self.0 & 0x04 != 0
113 }
114 pub fn is_directory(&self) -> bool {
115 self.0 & 0x10 != 0
116 }
117 pub fn is_archive(&self) -> bool {
118 self.0 & 0x20 != 0
119 }
120}
121
122impl From<u8> for FileAttributes {
123 fn from(value: u8) -> Self {
124 Self(value)
125 }
126}
127
128#[derive(Debug, Clone)]
130pub struct Uc2Entry {
131 pub parent_dir: u32,
133 pub attributes: FileAttributes,
135 pub dos_time: u32,
137 pub name: String,
139}