0.2.5: fix signed literals

This commit is contained in:
Adam 2025-08-17 17:52:15 +01:00
parent 077861f13c
commit 8054e10c7b
5 changed files with 95 additions and 43 deletions

2
Cargo.lock generated
View File

@ -4,7 +4,7 @@ version = 4
[[package]] [[package]]
name = "bin2hpp" name = "bin2hpp"
version = "0.2.4" version = "0.2.5"
dependencies = [ dependencies = [
"thiserror", "thiserror",
] ]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "bin2hpp" name = "bin2hpp"
version = "0.2.4" version = "0.2.5"
authors = ["Adam Macdonald"] authors = ["Adam Macdonald"]
edition = "2024" edition = "2024"
license = "GPL-3.0-only" license = "GPL-3.0-only"

View File

@ -6,7 +6,9 @@ CLI tool for converting files into header files which one can use to directly em
## Building ## Building
1. `cargo build` `cargo build`, or `cargo [build | run | install] --profile optimised` to build an optimised binary.
The performance (but potentially not the executable size) can be further optimised by telling the compiler to use a more modern instruction set: `RUSTFLAGS="-C target-cpu=native"`.
## Usage ## Usage
@ -15,11 +17,11 @@ CLI tool for converting files into header files which one can use to directly em
`$ bin2hpp -i my_library.dll -o c_header.h` will generate an `c_header.h` file in your current working directory containing something similar to the following: `$ bin2hpp -i my_library.dll -o c_header.h` will generate an `c_header.h` file in your current working directory containing something similar to the following:
```c ```c
// Generated by bin2hpp 0.2.4 // Generated by bin2hpp 0.2.5
#ifndef C_HEADER_H #ifndef C_HEADER_H
#define C_HEADER_H #define C_HEADER_H
#define MY_LIBRARY_DLL_LEN 9728 #define MY_LIBRARY_DLL_LEN 9728
const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN] = {0x4d,0x5a,0x90,0x0,0x3,0x0,0x0, ...}; const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN] = {77,90,144,0,3,0,0,0,4, ...};
#else #else
extern const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN]; extern const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN];
#endif #endif
@ -28,13 +30,13 @@ extern const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN];
Alternatively, in **C++ mode**: `bin2hpp -i my_library.dll -o cpp_header.hpp --cpp --constexpr --stdarray --i8` Alternatively, in **C++ mode**: `bin2hpp -i my_library.dll -o cpp_header.hpp --cpp --constexpr --stdarray --i8`
```cpp ```cpp
// Generated by bin2hpp 0.2.4 // Generated by bin2hpp 0.2.5
#if !defined(CPP_HEADER_HPP) #if !defined(CPP_HEADER_HPP)
#define CPP_HEADER_HPP #define CPP_HEADER_HPP
#include <cstdint> #include <cstdint>
#include <array> #include <array>
#define MY_LIBRARY_DLL_LEN 9728 #define MY_LIBRARY_DLL_LEN 9728
inline constexpr std::array<std::int8_t,MY_LIBRARY_DLL_LEN> MY_LIBRARY_DLL = {0x4d,0x5a,0x90,0x0,0x3,0x0,0x0, ...}; inline constexpr std::array<std::int8_t,MY_LIBRARY_DLL_LEN> MY_LIBRARY_DLL = {77,90,-112,0,3,0,0,0,4, ...};
#endif #endif
``` ```

View File

@ -20,6 +20,26 @@ pub enum ByteType {
I8, I8,
} }
impl ByteType {
pub fn to_c_type(&self) -> &'static str {
match self {
ByteType::UnsignedChar => "unsigned char",
ByteType::Char => "char",
ByteType::U8 => "uint8_t",
ByteType::I8 => "int8_t",
}
}
pub fn to_cpp_type(&self) -> &'static str {
match self {
ByteType::UnsignedChar => self.to_c_type(),
ByteType::Char => self.to_c_type(),
ByteType::U8 => "std::uint8_t",
ByteType::I8 => "std::int8_t",
}
}
}
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
pub enum ContainerType { pub enum ContainerType {
CArray(ByteType), CArray(ByteType),

View File

@ -175,8 +175,8 @@ pub fn with_definition(
modifiers, modifiers,
data_type_and_symbol(config), data_type_and_symbol(config),
match config.container_type { match config.container_type {
ContainerType::CArray(_) => with_array_initialiser(in_data), ContainerType::CArray(_) => with_array_initialiser(config, in_data),
ContainerType::StdArray(_) => with_array_initialiser(in_data), ContainerType::StdArray(_) => with_array_initialiser(config, in_data),
_ => with_string_initialiser(config, in_data)?, _ => with_string_initialiser(config, in_data)?,
}, },
config.line_ending config.line_ending
@ -199,12 +199,34 @@ pub fn with_declaration(config: &Config, buf: &mut String) {
.unwrap(); .unwrap();
} }
pub fn with_array_initialiser(in_data: &[u8]) -> String { pub fn with_array_initialiser(config: &Config, in_data: &[u8]) -> String {
let mut out_str: String = String::with_capacity(in_data.len() * 6 + 16); let mut out_str: String = String::with_capacity(in_data.len() * 6 + 16);
let signed_literals = match config.container_type {
ContainerType::CArray(byte_type) => match byte_type {
ByteType::Char => true,
ByteType::I8 => true,
_ => false,
},
ContainerType::StdArray(byte_type) => match byte_type {
ByteType::Char => true,
ByteType::I8 => true,
_ => false,
},
_ => false,
};
write!(out_str, "{{").unwrap(); write!(out_str, "{{").unwrap();
for b in in_data {
write!(out_str, "{:#x},", b).unwrap(); if signed_literals {
for b in in_data {
let b = i8::from_ne_bytes([*b; 1]);
write!(out_str, "{},", b).unwrap();
}
} else {
for b in in_data {
write!(out_str, "{},", b).unwrap();
}
} }
let _ = out_str.pop(); let _ = out_str.pop();
write!(out_str, "}}").unwrap(); write!(out_str, "}}").unwrap();
@ -249,40 +271,48 @@ pub fn length_symbol(config: &Config) -> String {
} }
pub fn data_type_and_symbol(config: &Config) -> String { pub fn data_type_and_symbol(config: &Config) -> String {
let u8_type = match config.language { let mut out_str = String::with_capacity(config.symbol_name.len() + 20);
Language::C => "uint8_t",
Language::Cpp => "std::uint8_t",
};
let i8_type = match config.language {
Language::C => "int8_t",
Language::Cpp => "std::int8_t",
};
let length_sym = length_symbol(config); let length_sym = length_symbol(config);
match config.container_type { match config.container_type {
ContainerType::CArray(byte_type) => match byte_type { ContainerType::CArray(byte_type) => write!(
ByteType::UnsignedChar => { out_str,
format!("unsigned char {}[{}]", config.symbol_name, length_sym) "{} {}[{}]",
} if config.language == Language::Cpp {
ByteType::Char => format!("char {}[{}]", config.symbol_name, length_sym), byte_type.to_cpp_type()
_ => format!("{} {}[{}]", u8_type, config.symbol_name, length_sym), } else {
}, byte_type.to_c_type()
ContainerType::StdArray(byte_type) => { },
format!( config.symbol_name,
"std::array<{},{}> {}", length_sym
match byte_type { )
ByteType::UnsignedChar => "unsigned char", .unwrap(),
ByteType::Char => "char", ContainerType::StdArray(byte_type) => write!(
ByteType::U8 => u8_type, out_str,
ByteType::I8 => i8_type, "std::array<{},{}> {}",
}, if config.language == Language::Cpp {
length_sym, byte_type.to_cpp_type()
config.symbol_name } else {
) byte_type.to_c_type()
},
length_sym,
config.symbol_name
)
.unwrap(),
ContainerType::CString => write!(
out_str,
"{} {}[{}]",
ByteType::Char.to_c_type(),
config.symbol_name,
length_sym
)
.unwrap(),
ContainerType::StdString => write!(out_str, "std::string {}", config.symbol_name).unwrap(),
ContainerType::StdStringView => {
write!(out_str, "std::string_view {}", config.symbol_name).unwrap()
} }
ContainerType::CString => format!("char {}[{}]", config.symbol_name, length_sym), };
ContainerType::StdString => format!("std::string {}", config.symbol_name),
ContainerType::StdStringView => format!("std::string_view {}", config.symbol_name), out_str
}
} }