| 1 | use alloc::borrow::Cow; |
| 2 | use alloc::vec::Vec; |
| 3 | |
| 4 | use super::*; |
| 5 | use crate::{encoding_size, ExportKind, NameMap, SectionId}; |
| 6 | |
| 7 | /// Encoding for the `component-name` custom section which assigns |
| 8 | /// human-readable names to items within a component. |
| 9 | #[derive (Clone, Debug, Default)] |
| 10 | pub struct ComponentNameSection { |
| 11 | bytes: Vec<u8>, |
| 12 | } |
| 13 | |
| 14 | enum Subsection { |
| 15 | Component, |
| 16 | Decls, |
| 17 | } |
| 18 | |
| 19 | impl ComponentNameSection { |
| 20 | /// Creates a new blank `name` custom section. |
| 21 | pub fn new() -> Self { |
| 22 | Self::default() |
| 23 | } |
| 24 | |
| 25 | /// Appends a component name subsection to this section. |
| 26 | /// |
| 27 | /// This will indicate that the name of the entire component should be the |
| 28 | /// `name` specified. Note that this should be encoded first before other |
| 29 | /// subsections. |
| 30 | pub fn component(&mut self, name: &str) { |
| 31 | let len = encoding_size(u32::try_from(name.len()).unwrap()); |
| 32 | self.subsection_header(Subsection::Component, len + name.len()); |
| 33 | name.encode(&mut self.bytes); |
| 34 | } |
| 35 | |
| 36 | /// Appends a decls name subsection to name core functions within the |
| 37 | /// component. |
| 38 | pub fn core_funcs(&mut self, names: &NameMap) { |
| 39 | self.core_decls(ExportKind::Func as u8, names) |
| 40 | } |
| 41 | |
| 42 | /// Appends a decls name subsection to name core tables within the |
| 43 | /// component. |
| 44 | pub fn core_tables(&mut self, names: &NameMap) { |
| 45 | self.core_decls(ExportKind::Table as u8, names) |
| 46 | } |
| 47 | |
| 48 | /// Appends a decls name subsection to name core memories within the |
| 49 | /// component. |
| 50 | pub fn core_memories(&mut self, names: &NameMap) { |
| 51 | self.core_decls(ExportKind::Memory as u8, names) |
| 52 | } |
| 53 | |
| 54 | /// Appends a decls name subsection to name core globals within the |
| 55 | /// component. |
| 56 | pub fn core_globals(&mut self, names: &NameMap) { |
| 57 | self.core_decls(ExportKind::Global as u8, names) |
| 58 | } |
| 59 | |
| 60 | /// Appends a decls name subsection to name core types within the |
| 61 | /// component. |
| 62 | pub fn core_types(&mut self, names: &NameMap) { |
| 63 | self.core_decls(CORE_TYPE_SORT, names) |
| 64 | } |
| 65 | |
| 66 | /// Appends a decls name subsection to name core modules within the |
| 67 | /// component. |
| 68 | pub fn core_modules(&mut self, names: &NameMap) { |
| 69 | self.core_decls(CORE_MODULE_SORT, names) |
| 70 | } |
| 71 | |
| 72 | /// Appends a decls name subsection to name core instances within the |
| 73 | /// component. |
| 74 | pub fn core_instances(&mut self, names: &NameMap) { |
| 75 | self.core_decls(CORE_INSTANCE_SORT, names) |
| 76 | } |
| 77 | |
| 78 | /// Appends a decls name subsection to name component functions within the |
| 79 | /// component. |
| 80 | pub fn funcs(&mut self, names: &NameMap) { |
| 81 | self.component_decls(FUNCTION_SORT, names) |
| 82 | } |
| 83 | |
| 84 | /// Appends a decls name subsection to name component values within the |
| 85 | /// component. |
| 86 | pub fn values(&mut self, names: &NameMap) { |
| 87 | self.component_decls(VALUE_SORT, names) |
| 88 | } |
| 89 | |
| 90 | /// Appends a decls name subsection to name component type within the |
| 91 | /// component. |
| 92 | pub fn types(&mut self, names: &NameMap) { |
| 93 | self.component_decls(TYPE_SORT, names) |
| 94 | } |
| 95 | |
| 96 | /// Appends a decls name subsection to name components within the |
| 97 | /// component. |
| 98 | pub fn components(&mut self, names: &NameMap) { |
| 99 | self.component_decls(COMPONENT_SORT, names) |
| 100 | } |
| 101 | |
| 102 | /// Appends a decls name subsection to name component instances within the |
| 103 | /// component. |
| 104 | pub fn instances(&mut self, names: &NameMap) { |
| 105 | self.component_decls(INSTANCE_SORT, names) |
| 106 | } |
| 107 | |
| 108 | /// Appends a raw subsection with the given id and data. |
| 109 | pub fn raw(&mut self, id: u8, data: &[u8]) { |
| 110 | self.bytes.push(id); |
| 111 | data.encode(&mut self.bytes); |
| 112 | } |
| 113 | |
| 114 | fn component_decls(&mut self, kind: u8, names: &NameMap) { |
| 115 | self.subsection_header(Subsection::Decls, 1 + names.size()); |
| 116 | self.bytes.push(kind); |
| 117 | names.encode(&mut self.bytes); |
| 118 | } |
| 119 | |
| 120 | fn core_decls(&mut self, kind: u8, names: &NameMap) { |
| 121 | self.subsection_header(Subsection::Decls, 2 + names.size()); |
| 122 | self.bytes.push(CORE_SORT); |
| 123 | self.bytes.push(kind); |
| 124 | names.encode(&mut self.bytes); |
| 125 | } |
| 126 | |
| 127 | fn subsection_header(&mut self, id: Subsection, len: usize) { |
| 128 | self.bytes.push(id as u8); |
| 129 | len.encode(&mut self.bytes); |
| 130 | } |
| 131 | |
| 132 | /// Returns whether this section is empty, or nothing has been encoded. |
| 133 | pub fn is_empty(&self) -> bool { |
| 134 | self.bytes.is_empty() |
| 135 | } |
| 136 | |
| 137 | /// View the encoded section as a CustomSection. |
| 138 | pub fn as_custom<'a>(&'a self) -> CustomSection<'a> { |
| 139 | CustomSection { |
| 140 | name: "component-name" .into(), |
| 141 | data: Cow::Borrowed(&self.bytes), |
| 142 | } |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | impl Encode for ComponentNameSection { |
| 147 | fn encode(&self, sink: &mut Vec<u8>) { |
| 148 | self.as_custom().encode(sink); |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | impl ComponentSection for ComponentNameSection { |
| 153 | fn id(&self) -> u8 { |
| 154 | SectionId::Custom.into() |
| 155 | } |
| 156 | } |
| 157 | |