rar_stream/formats/
mod.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Signature {
8 Rar15,
10 Rar50,
12}
13
14impl Signature {
15 pub const RAR15: &[u8; 7] = b"Rar!\x1a\x07\x00";
16 pub const RAR50: &[u8; 8] = b"Rar!\x1a\x07\x01\x00";
17
18 pub fn size(&self) -> u64 {
19 match self {
20 Self::Rar15 => 7,
21 Self::Rar50 => 8,
22 }
23 }
24
25 pub fn from_bytes(data: &[u8]) -> Option<Self> {
26 if data.len() >= 8 && data.starts_with(Self::RAR50) {
27 Some(Self::Rar50)
28 } else if data.len() >= 7 && data.starts_with(Self::RAR15) {
29 Some(Self::Rar15)
30 } else {
31 None
32 }
33 }
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
38pub struct RawTimestamp {
39 pub nanos: i64,
40}
41
42impl RawTimestamp {
43 pub fn from_unix_nanos(nanos: i64) -> Self {
44 Self { nanos }
45 }
46
47 pub fn from_dos(dos_time: u32) -> Self {
48 let second = ((dos_time & 0x1f) * 2) as i64;
49 let minute = ((dos_time >> 5) & 0x3f) as i64;
50 let hour = ((dos_time >> 11) & 0x1f) as i64;
51 let day = ((dos_time >> 16) & 0x1f) as i64;
52 let month = ((dos_time >> 21) & 0x0f) as i64;
53 let year = ((dos_time >> 25) + 1980) as i64;
54
55 let mut days: i64 = 0;
57 for y in 1970..year {
58 days += if y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) {
59 366
60 } else {
61 365
62 };
63 }
64 let is_leap = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
65 let month_days = [
66 31,
67 if is_leap { 29 } else { 28 },
68 31,
69 30,
70 31,
71 30,
72 31,
73 31,
74 30,
75 31,
76 30,
77 31,
78 ];
79 for m in 0..(month - 1).min(11) as usize {
80 days += month_days[m] as i64;
81 }
82 days += day - 1;
83
84 let secs = days * 86400 + hour * 3600 + minute * 60 + second;
85 Self {
86 nanos: secs * 1_000_000_000,
87 }
88 }
89
90 pub fn saturating_add(self, add_nanos: i64) -> Self {
91 Self {
92 nanos: self.nanos.saturating_add(add_nanos),
93 }
94 }
95}
96
97pub fn parse_dos_datetime(dos_time: u32) -> RawTimestamp {
98 RawTimestamp::from_dos(dos_time)
99}
100
101pub fn parse_windows_filetime(filetime: u64) -> RawTimestamp {
102 const WINDOWS_TICK_NS: i128 = 100;
103 const EPOCH_DIFF: i128 = 11_644_473_600_000_000_000;
104 let unix_ns = (filetime as i128) * WINDOWS_TICK_NS - EPOCH_DIFF;
105 RawTimestamp::from_unix_nanos(unix_ns as i64)
106}