Skip to main content

dotnetdll/binary/
stream.rs

1use scroll::{
2    Pread, Pwrite,
3    ctx::{StrCtx, TryFromCtx, TryIntoCtx},
4};
5
6/// One stream-header entry in the metadata root stream-header array.
7///
8/// Each entry declares a logical stream (for example `#~`, `#Strings`, `#US`,
9/// `#Blob`, or `#GUID`) by name, byte offset from the start of the metadata
10/// root, and stream size in bytes. Stream names are null-terminated and padded
11/// so the next header begins on a 4-byte boundary. See ECMA-335, II.24.2.2.
12#[derive(Debug)]
13pub struct Header<'a> {
14    /// Byte offset of the stream payload from the start of the metadata root.
15    pub offset: u32,
16    /// Stream payload size in bytes.
17    pub size: u32,
18    /// Stream name (`#~`, `#Strings`, `#US`, `#Blob`, `#GUID`, etc.).
19    pub name: &'a str,
20}
21
22impl<'a> TryFromCtx<'a> for Header<'a> {
23    type Error = scroll::Error;
24
25    fn try_from_ctx(from: &'a [u8], (): ()) -> Result<(Self, usize), Self::Error> {
26        let offset = &mut 0;
27        let stream_offset = from.gread_with(offset, scroll::LE)?;
28        let stream_size = from.gread_with(offset, scroll::LE)?;
29
30        let name = from.gread_with(offset, StrCtx::Delimiter(0))?;
31
32        *offset = crate::utils::round_up_to_4(*offset).0;
33
34        let obj = Header {
35            offset: stream_offset,
36            size: stream_size,
37            name,
38        };
39        Ok((obj, *offset))
40    }
41}
42impl TryIntoCtx for Header<'_> {
43    type Error = scroll::Error;
44
45    fn try_into_ctx(self, into: &mut [u8], (): ()) -> Result<usize, Self::Error> {
46        let offset = &mut 0;
47
48        into.gwrite_with(self.offset, offset, scroll::LE)?;
49        into.gwrite_with(self.size, offset, scroll::LE)?;
50
51        // name is null-terminated
52        into.gwrite(self.name, offset)?;
53        into.gwrite_with(0_u8, offset, scroll::LE)?;
54
55        // after initial null-termination, skip ahead to align to 4 bytes with nulls
56        *offset = crate::utils::round_up_to_4(*offset).0;
57
58        Ok(*offset)
59    }
60}