proka_exec/utils/
builder.rs1use super::str_to_array;
3use crate::header::{ExecMode, Header};
4use crate::sections::{SectionFlag, SectionHdr, SectionIndex};
5use crate::{Error, HEADER_SIZE, Result, SECTION_HDR_SIZE, SECTION_INDEX_SIZE};
6#[cfg(feature = "alloc")]
7use alloc::{
8 string::{String, ToString},
9 vec::Vec,
10};
11
12#[derive(Debug, Clone)]
14#[cfg(feature = "alloc")]
15pub struct Builder<'a> {
16 min: [u16; 3],
17 max: [u16; 3],
18 entry: (u32, usize), author: String,
20 name: String,
21 mode: ExecMode,
22 sections: Vec<InnerSections<'a>>,
23}
24
25#[cfg(feature = "alloc")]
26impl Default for Builder<'_> {
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32#[cfg(feature = "alloc")]
33impl<'a> Builder<'a> {
34 pub fn new() -> Self {
36 Self {
37 min: [0; 3],
38 max: [0; 3],
39 entry: (0, 0),
40 author: String::new(),
41 name: String::new(),
42 mode: ExecMode::UserApp,
43 sections: Vec::new(),
44 }
45 }
46
47 pub fn set_author(&mut self, author: &str) {
53 self.author = author.to_string();
54 }
55
56 pub fn set_name(&mut self, name: &str) {
62 self.name = name.to_string();
63 }
64
65 pub fn set_mode(&mut self, mode: ExecMode) {
67 self.mode = mode;
68 }
69
70 pub fn set_min(&mut self, min: [u16; 3]) {
72 self.min = min;
73 }
74
75 pub fn set_max(&mut self, max: [u16; 3]) {
77 self.max = max;
78 }
79
80 pub fn append(
98 &mut self,
99 data: &'a [u8],
100 name: &'a str,
101 is_loadable: bool,
102 is_execable: bool,
103 entry: Option<u32>,
104 ) -> Result<()> {
105 if entry.is_some() && !(is_execable && is_loadable) {
107 return Err(Error::ExecutableCorrupted);
108 }
109
110 let flag = match (is_loadable, is_execable) {
111 (true, true) => SectionFlag::LOADABLE | SectionFlag::EXECABLE,
112 (true, false) => SectionFlag::LOADABLE,
113 (false, true) => SectionFlag::EXECABLE,
114 (false, false) => SectionFlag::empty(),
115 };
116
117 let section = InnerSections {
118 secinfo: SectionHdr {
119 flag,
120 _pad1: [0; 3],
121 base: 0, size: data.len() as u32,
123 _pad2: [0; 4],
124 },
125 secindex: SectionIndex {
126 base: 0, name_len: name.len() as u32,
128 },
129 name,
130 data,
131 };
132 self.sections.push(section);
133
134 if let Some(ent_offset) = entry {
136 let sec_index = self.sections.len() - 1;
137 self.entry = (ent_offset, sec_index);
138 }
139 Ok(())
140 }
141
142 pub fn build(self) -> Result<Vec<u8>> {
146 if self.sections.is_empty() {
148 return Err(Error::NoSections);
149 }
150
151 for (&min, &max) in self.min.iter().zip(self.max.iter()) {
153 if min > max {
154 return Err(Error::VersionIncorrect(self.min, self.max));
155 }
156 }
157
158 let mut data: Vec<u8> = Vec::new();
160
161 {
164 let mut header = Header::default();
165 header.min = self.min;
166 header.max = self.max;
167 header.entry_off = self.entry.0;
168 header.entry_sec = self.entry.1 as u16;
169 header.mode = self.mode;
170 header.author = str_to_array(self.author.as_str());
171 header.name = str_to_array(self.name.as_str());
172 header.sections = self.sections.len() as u16;
173
174 let header_bytes = header.to_array();
175 data.extend_from_slice(&header_bytes);
176 }
177
178 let mut cnt = 0;
180 for section in &self.sections {
181 let mut secindex = section.secindex;
182 secindex.base = (HEADER_SIZE + self.sections.len() * SECTION_INDEX_SIZE + cnt) as u32;
183 data.extend_from_slice(&secindex.to_array());
184 cnt += SECTION_HDR_SIZE + secindex.name_len as usize;
185 }
186
187 for section in &self.sections {
191 let mut secinfo = section.secinfo;
192
193 secinfo.base = (HEADER_SIZE + self.sections.len() * SECTION_INDEX_SIZE + cnt) as u32;
196
197 data.extend_from_slice(&secinfo.to_array());
199 data.extend_from_slice(section.name.as_bytes());
200 cnt += section.data.len();
201 }
202
203 for section in &self.sections {
205 data.extend_from_slice(section.data);
206 }
207
208 Ok(data)
210 }
211}
212
213#[derive(Debug, Clone, Copy)]
215struct InnerSections<'a> {
216 pub secinfo: SectionHdr,
217 pub secindex: SectionIndex,
218 pub name: &'a str,
219 pub data: &'a [u8],
220}