1use std::io::{Read, Seek, SeekFrom, Write};
8
9use byteorder::LittleEndian;
10
11use super::{XP3Error, XP3ErrorKind, XP3_CURRENT_VER_IDENTIFIER, XP3_VERSION_IDENTIFIER};
12use byteorder::{WriteBytesExt, ReadBytesExt};
13
14#[derive(Debug, Copy, Clone)]
15pub struct XP3Header {
16
17 version: XP3HeaderVersion
18
19}
20
21impl XP3Header {
22
23 pub fn new(version: XP3HeaderVersion) -> Self {
24 Self {
25 version
26 }
27 }
28
29 pub fn version(&self) -> XP3HeaderVersion {
30 self.version
31 }
32
33 pub fn set_version(&mut self, version: XP3HeaderVersion) {
34 self.version = version;
35 }
36
37 pub fn from_bytes<T: Read + Seek>(stream: &mut T) -> Result<(u64, Self), XP3Error> {
40 let current = stream.seek(SeekFrom::Current(0))?;
41
42 let identifier = stream.read_u64::<LittleEndian>()?;
43
44 let header: XP3Header;
45 let read: u64;
46 if identifier == XP3_CURRENT_VER_IDENTIFIER {
47 let minor_version = stream.read_u32::<LittleEndian>()?;
48
49 if stream.read_u8()? != XP3_VERSION_IDENTIFIER {
50 return Err(XP3Error::new(XP3ErrorKind::InvalidHeader, None));
51 }
52
53 header = XP3Header::new(
54 XP3HeaderVersion::Current {
55 minor_version,
56 index_size_offset: stream.read_u64::<LittleEndian>()?
57 }
58 );
59
60 read = 21;
61 } else {
62 stream.seek(SeekFrom::Start(current))?;
63 header = XP3Header::new(
64 XP3HeaderVersion::Old
65 );
66 read = 0;
67 }
68
69 Ok((read, header))
70 }
71
72 pub fn write_bytes(&self, stream: &mut impl Write) -> Result<u64, XP3Error> {
75 let ver_written: u64;
76 match self.version {
77 XP3HeaderVersion::Old => {
78 ver_written = 0;
79 },
80
81 XP3HeaderVersion::Current { minor_version, index_size_offset } => {
82 stream.write_u64::<LittleEndian>(XP3_CURRENT_VER_IDENTIFIER)?;
83 stream.write_u32::<LittleEndian>(minor_version)?;
84 stream.write_u8(XP3_VERSION_IDENTIFIER)?;
85 stream.write_u64::<LittleEndian>(index_size_offset)?;
86 ver_written = 21;
87 }
88 }
89
90 Ok(ver_written)
91 }
92
93}
94
95#[derive(Debug, Copy, Clone)]
96pub enum XP3HeaderVersion {
98
99 Old,
100
101 Current {
102
103 minor_version: u32,
104 index_size_offset: u64
105
106 }
107
108}