1use crate::{BinaryReader, Result};
2use core::fmt;
3use core::ops::Range;
4
5/// A reader for custom sections of a WebAssembly module.
6#[derive(Clone)]
7pub struct CustomSectionReader<'a> {
8 name: &'a str,
9 reader: BinaryReader<'a>,
10}
11
12impl<'a> CustomSectionReader<'a> {
13 /// Constructs a new `CustomSectionReader` for the given data and offset.
14 pub fn new(mut reader: BinaryReader<'a>) -> Result<CustomSectionReader<'a>> {
15 let name = reader.read_string()?;
16 Ok(CustomSectionReader { name, reader })
17 }
18
19 /// The name of the custom section.
20 pub fn name(&self) -> &'a str {
21 self.name
22 }
23
24 /// The offset, relative to the start of the original module or component,
25 /// that the `data` payload for this custom section starts at.
26 pub fn data_offset(&self) -> usize {
27 self.reader.original_position()
28 }
29
30 /// The actual contents of the custom section.
31 pub fn data(&self) -> &'a [u8] {
32 self.reader.remaining_buffer()
33 }
34
35 /// The range of bytes that specify this whole custom section (including
36 /// both the name of this custom section and its data) specified in
37 /// offsets relative to the start of the byte stream.
38 pub fn range(&self) -> Range<usize> {
39 self.reader.range()
40 }
41
42 /// Attempts to match and see if this custom section is statically known to
43 /// `wasmparser` with any known section reader.
44 ///
45 /// This will inspect `self.name()` and return a [`KnownCustom`] if the name
46 /// matches a known custom section where there is a parser available for it.
47 /// This can also be used as a convenience function for creating such
48 /// parsers.
49 ///
50 /// If the custom section name is not known, or if a reader could not be
51 /// created, then `KnownCustom::Unknown` is returned.
52 pub fn as_known(&self) -> KnownCustom<'a> {
53 match self.name() {
54 "name" => KnownCustom::Name(crate::NameSectionReader::new(self.reader.shrink())),
55 #[cfg(feature = "component-model")]
56 "component-name" => KnownCustom::ComponentName(crate::ComponentNameSectionReader::new(
57 self.reader.shrink(),
58 )),
59 "metadata.code.branch_hint" => {
60 match crate::BranchHintSectionReader::new(self.reader.shrink()) {
61 Ok(s) => KnownCustom::BranchHints(s),
62 Err(_) => KnownCustom::Unknown,
63 }
64 }
65 "producers" => match crate::ProducersSectionReader::new(self.reader.shrink()) {
66 Ok(s) => KnownCustom::Producers(s),
67 Err(_) => KnownCustom::Unknown,
68 },
69 "dylink.0" => {
70 KnownCustom::Dylink0(crate::Dylink0SectionReader::new(self.reader.shrink()))
71 }
72 "core" => match crate::CoreDumpSection::new(self.reader.shrink()) {
73 Ok(s) => KnownCustom::CoreDump(s),
74 Err(_) => KnownCustom::Unknown,
75 },
76 "coremodules" => match crate::CoreDumpModulesSection::new(self.reader.shrink()) {
77 Ok(s) => KnownCustom::CoreDumpModules(s),
78 Err(_) => KnownCustom::Unknown,
79 },
80 "coreinstances" => match crate::CoreDumpInstancesSection::new(self.reader.shrink()) {
81 Ok(s) => KnownCustom::CoreDumpInstances(s),
82 Err(_) => KnownCustom::Unknown,
83 },
84 "corestack" => match crate::CoreDumpStackSection::new(self.reader.shrink()) {
85 Ok(s) => KnownCustom::CoreDumpStack(s),
86 Err(_) => KnownCustom::Unknown,
87 },
88 "linking" => match crate::LinkingSectionReader::new(self.reader.shrink()) {
89 Ok(s) => KnownCustom::Linking(s),
90 Err(_) => KnownCustom::Unknown,
91 },
92 s if s.starts_with("reloc.") => {
93 match crate::RelocSectionReader::new(self.reader.shrink()) {
94 Ok(s) => KnownCustom::Reloc(s),
95 Err(_) => KnownCustom::Unknown,
96 }
97 }
98 _ => KnownCustom::Unknown,
99 }
100 }
101}
102
103/// Return value of [`CustomSectionReader::as_known`].
104///
105/// Note that this is `#[non_exhaustive]` because depending on crate features
106/// this enumeration will different entries.
107#[allow(missing_docs)]
108#[non_exhaustive]
109pub enum KnownCustom<'a> {
110 Name(crate::NameSectionReader<'a>),
111 #[cfg(feature = "component-model")]
112 ComponentName(crate::ComponentNameSectionReader<'a>),
113 BranchHints(crate::BranchHintSectionReader<'a>),
114 Producers(crate::ProducersSectionReader<'a>),
115 Dylink0(crate::Dylink0SectionReader<'a>),
116 CoreDump(crate::CoreDumpSection<'a>),
117 CoreDumpStack(crate::CoreDumpStackSection<'a>),
118 CoreDumpInstances(crate::CoreDumpInstancesSection),
119 CoreDumpModules(crate::CoreDumpModulesSection<'a>),
120 Linking(crate::LinkingSectionReader<'a>),
121 Reloc(crate::RelocSectionReader<'a>),
122 Unknown,
123}
124
125impl<'a> fmt::Debug for CustomSectionReader<'a> {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 f&mut DebugStruct<'_, '_>.debug_struct("CustomSectionReader")
128 .field("name", &self.name)
129 .field("data_offset", &self.data_offset())
130 .field("data", &"...")
131 .field(name:"range", &self.range())
132 .finish()
133 }
134}
135