1use crate::error::{Result, WmoError};
2use crate::types::ChunkId;
3use std::io::{Read, Seek, SeekFrom, Write};
4
5#[derive(Debug, Clone, Copy)]
7pub struct ChunkHeader {
8 pub id: ChunkId,
10 pub size: u32,
12}
13
14impl ChunkHeader {
15 pub const SIZE: usize = 8;
17
18 pub fn read<R: Read>(reader: &mut R) -> Result<Self> {
20 let mut id_bytes = [0u8; 4];
21 match reader.read_exact(&mut id_bytes) {
22 Ok(_) => {}
23 Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
24 return Err(WmoError::UnexpectedEof);
25 }
26 Err(e) => return Err(WmoError::Io(e)),
27 }
28
29 id_bytes.reverse();
32
33 let mut size_bytes = [0u8; 4];
34 match reader.read_exact(&mut size_bytes) {
35 Ok(_) => {}
36 Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
37 return Err(WmoError::UnexpectedEof);
38 }
39 Err(e) => return Err(WmoError::Io(e)),
40 }
41 let size = u32::from_le_bytes(size_bytes);
42
43 Ok(Self {
44 id: ChunkId(id_bytes),
45 size,
46 })
47 }
48
49 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
51 let mut id_bytes = self.id.0;
54 id_bytes.reverse();
55 writer.write_all(&id_bytes)?;
56 writer.write_all(&self.size.to_le_bytes())?;
57 Ok(())
58 }
59}
60
61#[derive(Debug)]
63pub struct Chunk {
64 pub header: ChunkHeader,
66 pub data_position: u64,
68}
69
70impl Chunk {
71 pub fn read<R: Read + Seek>(reader: &mut R) -> Result<Self> {
73 let header = ChunkHeader::read(reader)?;
74 let data_position = reader.stream_position()?;
75
76 reader.seek(SeekFrom::Current(header.size as i64))?;
78
79 Ok(Self {
80 header,
81 data_position,
82 })
83 }
84
85 pub fn read_expected<R: Read + Seek>(reader: &mut R, expected_id: ChunkId) -> Result<Self> {
87 let chunk = Self::read(reader)?;
88
89 if chunk.header.id != expected_id {
90 return Err(WmoError::InvalidMagic {
91 expected: *expected_id.as_bytes(),
92 found: chunk.header.id.0,
93 });
94 }
95
96 Ok(chunk)
97 }
98
99 pub fn seek_to_data<S: Seek>(&self, seeker: &mut S) -> Result<()> {
101 seeker.seek(SeekFrom::Start(self.data_position))?;
102 Ok(())
103 }
104
105 pub fn read_data<R: Read + Seek>(&self, reader: &mut R) -> Result<Vec<u8>> {
107 self.seek_to_data(reader)?;
108
109 let mut data = vec![0; self.header.size as usize];
110 reader.read_exact(&mut data)?;
111
112 Ok(data)
113 }
114}