Make Utf8CStr a first class citizen in C++ codebase

Utf8CStr is in many cases a better string view class than
std::string_view, because it provides "view" access to a string buffer
that is guaranteed to be null terminated. It also has the additional
benefit of being UTF-8 verified and can seemlessly cross FFI boundaries.

We would want to start use more Utf8CStr in our existing C++ codebase.
This commit is contained in:
topjohnwu
2025-08-25 14:53:49 -07:00
committed by John Wu
parent e2abb648ac
commit 2e4fa6864c
25 changed files with 105 additions and 124 deletions

View File

@@ -156,7 +156,7 @@ void dyn_img_hdr::dump_hdr_file() const {
}
void dyn_img_hdr::load_hdr_file() {
parse_prop_file(HEADER_FILE, [=, this](string_view key, string_view value) -> bool {
parse_prop_file(HEADER_FILE, [=, this](Utf8CStr key, Utf8CStr value) -> bool {
if (key == "name" && name()) {
memset(name(), 0, 16);
memcpy(name(), value.data(), value.length() > 15 ? 15 : value.length());
@@ -166,7 +166,7 @@ void dyn_img_hdr::load_hdr_file() {
if (value.length() > BOOT_ARGS_SIZE) {
memcpy(cmdline(), value.data(), BOOT_ARGS_SIZE);
auto len = std::min(value.length() - BOOT_ARGS_SIZE, (size_t) BOOT_EXTRA_ARGS_SIZE);
memcpy(extra_cmdline(), &value[BOOT_ARGS_SIZE], len);
memcpy(extra_cmdline(), value.data() + BOOT_ARGS_SIZE, len);
} else {
memcpy(cmdline(), value.data(), value.length());
}
@@ -583,7 +583,7 @@ bool boot_img::parse_image(const uint8_t *p, FileFormat type) {
return true;
}
int split_image_dtb(rust::Utf8CStr filename, bool skip_decomp) {
int split_image_dtb(Utf8CStr filename, bool skip_decomp) {
mmap_data img(filename.data());
if (size_t off = find_dtb_offset(img.data(), img.size()); off > 0) {
@@ -603,7 +603,7 @@ int split_image_dtb(rust::Utf8CStr filename, bool skip_decomp) {
}
}
int unpack(rust::Utf8CStr image, bool skip_decomp, bool hdr) {
int unpack(Utf8CStr image, bool skip_decomp, bool hdr) {
const boot_img boot(image.data());
if (hdr)
@@ -688,7 +688,7 @@ write_zero(fd, align_padding(lseek(fd, 0, SEEK_CUR) - off.header, page_size))
#define file_align() file_align_with(boot.hdr->page_size())
void repack(rust::Utf8CStr src_img, rust::Utf8CStr out_img, bool skip_comp) {
void repack(Utf8CStr src_img, Utf8CStr out_img, bool skip_comp) {
const boot_img boot(src_img.data());
fprintf(stderr, "Repack to boot image: [%s]\n", out_img.data());

View File

@@ -685,7 +685,7 @@ struct boot_img {
std::pair<const uint8_t *, dyn_img_hdr *> create_hdr(const uint8_t *addr, FileFormat type);
// Rust FFI
static std::unique_ptr<boot_img> create(rust::Utf8CStr name) { return std::make_unique<boot_img>(name.c_str()); }
static std::unique_ptr<boot_img> create(Utf8CStr name) { return std::make_unique<boot_img>(name.c_str()); }
rust::Slice<const uint8_t> get_payload() const { return payload; }
rust::Slice<const uint8_t> get_tail() const { return tail; }
bool is_signed() const { return flags[AVB1_SIGNED_FLAG]; }

View File

@@ -49,15 +49,11 @@ pub mod ffi {
}
unsafe extern "C++" {
include!("../base/include/base.hpp");
include!("magiskboot.hpp");
#[namespace = "rust"]
#[cxx_name = "Utf8CStr"]
type Utf8CStrRef<'a> = base::ffi::Utf8CStrRef<'a>;
}
unsafe extern "C++" {
include!("magiskboot.hpp");
fn cleanup();
fn unpack(image: Utf8CStrRef, skip_decomp: bool, hdr: bool) -> i32;
fn repack(src_img: Utf8CStrRef, out_img: Utf8CStrRef, skip_comp: bool);

View File

@@ -1,5 +1,7 @@
#pragma once
#include <base.hpp>
#define HEADER_FILE "header"
#define KERNEL_FILE "kernel"
#define RAMDISK_FILE "ramdisk.cpio"
@@ -47,11 +49,11 @@
#define AVB_MAGIC "AVB0"
#define ZIMAGE_MAGIC "\x18\x28\x6f\x01"
enum class FileFormat : ::std::uint8_t;
enum class FileFormat : uint8_t;
int unpack(rust::Utf8CStr image, bool skip_decomp = false, bool hdr = false);
void repack(rust::Utf8CStr src_img, rust::Utf8CStr out_img, bool skip_comp = false);
int split_image_dtb(rust::Utf8CStr filename, bool skip_decomp = false);
int unpack(Utf8CStr image, bool skip_decomp = false, bool hdr = false);
void repack(Utf8CStr src_img, Utf8CStr out_img, bool skip_comp = false);
int split_image_dtb(Utf8CStr filename, bool skip_decomp = false);
void cleanup();
FileFormat check_fmt(const void *buf, size_t len);