ms_pdb/dbi/
optional_dbg.rs1use super::*;
11
12pub struct OptionalDebugHeader<'a> {
14 pub stream_indexes: &'a [StreamIndexU16],
16}
17
18impl<'a> OptionalDebugHeader<'a> {
19 pub fn parse(bytes: &'a [u8]) -> anyhow::Result<Self> {
21 let Ok(stream_indexes) = <[StreamIndexU16]>::ref_from_bytes(bytes) else {
22 bail!(
23 "The OptionalDebugHeader has an invalid size. The size is required to be a multiple of 2. Size: {}",
24 bytes.len()
25 );
26 };
27
28 Ok(Self { stream_indexes })
29 }
30
31 pub fn stream_by_index(&self, i: usize) -> Option<u32> {
33 self.stream_indexes.get(i)?.get()
34 }
35
36 pub fn stream(&self, s: OptionalDebugHeaderStream) -> Option<u32> {
38 self.stream_by_index(s as usize)
39 }
40
41 pub fn num_streams(&self) -> usize {
43 self.stream_indexes.len()
44 }
45
46 pub fn iter_streams(&self) -> IterStreams<'_> {
50 IterStreams {
51 stream_indexes: self.stream_indexes,
52 next: 0,
53 }
54 }
55}
56
57#[derive(Clone)]
59pub struct OptionalDebugHeaders {
60 pub streams: Vec<u16>,
62}
63
64impl OptionalDebugHeaders {
65 pub fn iter(&self) -> impl Iterator<Item = (OptionalDebugStream, u32)> + '_ {
67 self.streams.iter().enumerate().filter_map(|(i, &s)| {
68 if s != NIL_STREAM_INDEX {
69 Some((OptionalDebugStream(i as u32), s as u32))
70 } else {
71 None
72 }
73 })
74 }
75}
76
77#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, Ord, PartialOrd)]
79pub struct OptionalDebugStream(pub u32);
80
81#[allow(missing_docs)]
82impl OptionalDebugStream {
83 pub const FPO_DATA: Self = Self(0);
84 pub const EXCEPTION_DATA: Self = Self(1);
85 pub const FIXUP_DATA: Self = Self(2);
86 pub const OMAP_TO_SRC_DATA: Self = Self(3);
87 pub const OMAP_FROM_SRC_DATA: Self = Self(4);
88 pub const SECTION_HEADER_DATA: Self = Self(5);
89 pub const TOKEN_TO_RECORD_ID_MAP: Self = Self(6);
90 pub const XDATA: Self = Self(7);
91 pub const PDATA: Self = Self(8);
92 pub const NEW_FPO_DATA: Self = Self(9);
93 pub const ORIGINAL_SECTION_HEADER_DATA: Self = Self(10);
94}
95
96impl OptionalDebugStream {
97 pub fn name(&self) -> Option<&'static str> {
99 OPTIONAL_DEBUG_HEADER_STREAM_NAME
100 .get(self.0 as usize)
101 .copied()
102 }
103}
104
105pub struct IterStreams<'a> {
107 stream_indexes: &'a [StreamIndexU16],
108 next: usize,
109}
110
111impl<'a> Iterator for IterStreams<'a> {
112 type Item = (usize, u32);
113
114 fn next(&mut self) -> Option<Self::Item> {
115 while self.next < self.stream_indexes.len() {
116 let i = self.next;
117 let stream_index_or_nil = self.stream_indexes[i].get();
118 self.next += 1;
119
120 if let Some(stream_index) = stream_index_or_nil {
121 return Some((i, stream_index));
122 }
123 }
124 None
125 }
126}
127
128macro_rules! optional_debug_header_streams {
129 (
130 $(
131 $( #[$a:meta] )*
132 $index:literal, $name:ident, $description:expr;
133 )*
134 ) => {
135 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
137 #[repr(u8)]
138 #[allow(non_camel_case_types)]
139 #[allow(missing_docs)]
140 pub enum OptionalDebugHeaderStream {
141 $(
142 $( #[$a] )*
143 $name = $index,
144 )*
145 }
146
147 pub static OPTIONAL_DEBUG_HEADER_STREAM_NAME: [&str; 11] = [
149 $(
150 stringify!($name),
151 )*
152 ];
153
154 pub static OPTIONAL_DEBUG_HEADER_STREAM_DESCRIPTION: [&str; 11] = [
156 $(
157 $description,
158 )*
159 ];
160
161 impl TryFrom<usize> for OptionalDebugHeaderStream {
162 type Error = ();
163
164 fn try_from(i: usize) -> std::result::Result<Self, Self::Error> {
165 match i {
166 $( $index => Ok(Self::$name), )*
167 _ => Err(()),
168 }
169 }
170 }
171 }
172}
173
174optional_debug_header_streams! {
175 0, fpo_data, "";
178 1, exception_data, "";
180 2, fixup_data, "";
182 3, omap_to_src_data, "";
185 4, omap_from_src_data, "";
188 5, section_header_data, "";
190 6, token_to_record_id_map, "";
191 7, xdata, "";
193 8, pdata, "";
195 9, new_fpo_data, "";
196 10, original_section_header_data, "";
197}