rar_stream/parsing/
marker_header.rs1use crate::error::{RarError, Result};
8
9pub const RAR4_SIGNATURE: [u8; 7] = [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00];
11
12pub const RAR5_SIGNATURE: [u8; 8] = [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00];
14
15#[derive(Debug, Clone)]
16pub struct MarkerHeader {
17 pub crc: u16,
18 pub header_type: u8,
19 pub flags: u16,
20 pub size: u32,
21}
22
23pub struct MarkerHeaderParser;
24
25impl MarkerHeaderParser {
26 pub const HEADER_SIZE: usize = 7;
27
28 pub fn parse(buffer: &[u8]) -> Result<MarkerHeader> {
32 if buffer.len() < Self::HEADER_SIZE {
33 return Err(RarError::BufferTooSmall {
34 needed: Self::HEADER_SIZE,
35 have: buffer.len(),
36 });
37 }
38
39 if buffer[..7] != RAR4_SIGNATURE {
41 if buffer.len() >= 8 && buffer[..8] == RAR5_SIGNATURE {
43 return Err(RarError::InvalidSignature); }
45 return Err(RarError::InvalidSignature);
46 }
47
48 let crc = u16::from_le_bytes([buffer[0], buffer[1]]);
50 let header_type = buffer[2];
51 let flags = u16::from_le_bytes([buffer[3], buffer[4]]);
52 let size = u16::from_le_bytes([buffer[5], buffer[6]]) as u32;
53
54 Ok(MarkerHeader {
55 crc,
56 header_type,
57 flags,
58 size,
59 })
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn test_parse_rar4_marker() {
69 let buffer = [
71 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, ];
74 let header = MarkerHeaderParser::parse(&buffer).unwrap();
75 assert_eq!(header.header_type, b'r'); }
77
78 #[test]
79 fn test_invalid_signature() {
80 let buffer = [0x00; 11];
81 assert!(matches!(
82 MarkerHeaderParser::parse(&buffer),
83 Err(RarError::InvalidSignature)
84 ));
85 }
86
87 #[test]
88 fn test_buffer_too_small() {
89 let buffer = [0x52, 0x61, 0x72];
90 assert!(matches!(
91 MarkerHeaderParser::parse(&buffer),
92 Err(RarError::BufferTooSmall { .. })
93 ));
94 }
95}