proka_exec/lib.rs
1//! # `proka-exec`
2//!
3//! [](https://www.rust-lang.org/)
4//! [](https://opensource.org/license/gpl-3.0)
5//! [](https://github.com/RainSTR-Studio/proka-exec/stargazers)
6//! [](https://github.com/RainSTR-Studio/proka-exec/issues)
7//! [](https://github.com/RainSTR-Studio/proka-exec/pulls)
8//! [](https://prokadoc.pages.dev/)
9//!
10//! Copyright (C) 2026 RainSTR Studio. Licensed under GNU GPLv3.
11//!
12//! ---
13//!
14//! ## Introduction
15//! This crate provides the definitions of headers, section index, section metadata,
16//! and some utils to help you parse the executable easily.
17//!
18//! ## Structures of this executable
19//! This executable is structured as follows:
20//! - PKE headers - Records the basic information of this executable;
21//! - Section index - Records the section header's offset and section name's length;
22//! - Section metadata- Records the section flags, data offset and its length;
23//! - Data - The binary content.
24//!
25//! We can use this picture to explain their segmented structure:
26//!
27//! `[Headers] [Section Index 1] [Section Index 2] ... [Section Metadata 1] [Section Metadata 2] ... [Data]`
28//!
29//! Simultaneously, the `[Section Metadata]` can be separated as follows:
30//!
31//! `[Section Headers] [Section Name]`
32//!
33//! In the picture above, the `[Section Headers]`'s length is fixed, which is recorded in [`SECTION_HDR_SIZE`];
34//! The section name is different - It's dynamic, so you can store almost infinite words in it!
35//!
36//! ## Steps to use this crate
37//! ### Parsing
38//! Before you parse it, you should do these steps:
39//!
40//! - Read the executable file content;
41//! - Make this file's content to a slice (`&[u8]`)
42//! - Use [`Parser`] to parse the executable.
43//!
44//! After this, you can do further operations through this parser by
45//! calling its functions.
46//!
47//! ### Building
48//! Here we provided a tool [`Builder`] to help you do building process easily.
49//!
50//! Before parsing, make sure you have enabled feature `alloc`, or you can't find where [`Builder`] is.
51//!
52//! Then you can do these steps:
53//! - Set up author name (32 bytes limit);
54//! - Set up program name (32 bytes limit);
55//! - Set up the executable type (UserApp/CoreDrv);
56//! - Append section content (Can push multiple sections);
57//! - Build the executable.
58//!
59//! ## Example Usage
60//! ### Parsing
61//! ```rust
62//! use proka_exec::Parser;
63//! use std::path::PathBuf;
64//!
65//! let file = PathBuf::from("tests/testbin/sample.pke");
66//! let content = std::fs::read(file).expect("Failed to read file");
67//! let parser = Parser::init(&content).expect("Failed to parse PKE format");
68//!
69//! // More API see below
70//! ```
71//!
72//! ### Building
73//! ```rust
74//! use proka_exec::{Builder, header::ExecMode};
75//! use std::path::PathBuf;
76//!
77//! static EXAMPLE_CONTENT: &[u8] = b"Hello, World!";
78//!
79//! let mut builder = Builder::new();
80//! builder.set_author("example");
81//! builder.set_name("appname");
82//! builder.set_mode(ExecMode::UserApp);
83//! builder.append(EXAMPLE_CONTENT, ".example.section", false, false, None); // (data, name, is_loadable, is_execable, entry)
84//! let content = builder.build().expect("Failed to build executable");
85//! std::fs::write("example.pke", &content).expect("Failed to write file");
86//! ```
87//!
88//!
89//! # LICENSE
90//! This crate is under license [GPL-v3](https://github.com/RainSTR-Studio/proka-exec/blob/main/LICENSE),
91//! and you must follow its rules.
92//!
93//! See [LICENSE](https://github.com/RainSTR-Studio/proka-exec/blob/main/LICENSE) file for more details.
94//!
95//! ## MSRV
96//! This crate's MSRV is `1.85.0` stable.
97#![no_std]
98
99// Alloc features...
100#[cfg(feature = "alloc")]
101extern crate alloc;
102
103pub mod header;
104pub mod sections;
105pub mod utils;
106
107use header::{HeaderError, Header};
108use sections::{SectionError, SectionHdr, SectionIndex};
109pub use utils::*;
110pub use utils::{builder::Builder, parser::Parser};
111
112/// Generic result type in this crate
113pub type Result<T> = core::result::Result<T, Error>;
114
115/// The header size.
116pub const HEADER_SIZE: usize = core::mem::size_of::<Header>();
117
118/// The section header size.
119pub const SECTION_HDR_SIZE: usize = core::mem::size_of::<SectionHdr>();
120
121/// The section entry size.
122pub const SECTION_INDEX_SIZE: usize = core::mem::size_of::<SectionIndex>();
123
124/// The version of this crate.
125pub const VERSION_CURRENT: u32 = 3;
126
127/// The minimum version of this crate.
128pub const VERSION_MINIMAL: u32 = 3;
129
130/// The error type of parsing header.
131#[repr(C)]
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
133pub enum Error {
134 /// Section inner error.
135 ///
136 /// See [`SectionError`] for more details.
137 SectionError(SectionError),
138
139 /// Header inner error.
140 ///
141 /// See [`HeaderError`] for more details.
142 HeaderError(HeaderError),
143
144 /// The executable is not valid
145 ///
146 /// Will appear if magic is not correct.
147 NotValidExecutable,
148
149 /// The section which is corrupted.
150 ///
151 /// Will appear if:
152 /// - The buffer size is lower than specified length;
153 /// - Append an unexecable and unloadable section within an entry address (`Builder` only).
154 ExecutableCorrupted,
155
156 /// The version that was written in file is incorrect.
157 ///
158 /// Will appear if:
159 /// - The max version is lower than the min version;
160 /// - Passing a max version which is lower than min version (`Builder` only).
161 ///
162 /// # Arguments
163 /// - 0: The min version;
164 /// - 1: The max version.
165 VersionIncorrect([u16; 3], [u16; 3]),
166
167 /// An unknown character in UTF-8 was found in
168 /// parsing arrays
169 ///
170 /// May appear in converting slice to `&str`.
171 UnknownCharacter,
172
173 /// No sections in the current executable.
174 ///
175 /// Will appear if you try to build without any appending.
176 NoSections,
177}