mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-26 09:02:46 +00:00
feat(rust,gui): RLE compression codec + Rust Lab desktop app
Rust kernel expansion: - rust/src/compress/mod.rs (new): memory-safe PackBits-style run-length encoding codec (rle_compress / rle_decompress) with C-ABI shims, registered in lib.rs. C fallbacks added to rust_fallback.c so aarch64/armv8i match. - include/kernel/rust.h: FFI declarations for the codec. - LazyBox: new `rle <text>` applet that compresses, decompresses, prints the ratio and verifies the round-trip is lossless. GUI expansion: - gui/gui_apps.c: "Rust Lab" app -- a live dashboard for the Rust subsystem. Shows CRC-32C/Adler-32 of a sample, measured ChaCha20/SHA3-256/AES-128 throughput as scaled bars plus a composite score (benchmark run once at launch and cached), and a live ChaCha20 CSPRNG byte stream refreshed periodically. Per-window state freed on close. - Registered "Rust Lab" (info icon) in the desktop app table and on the desktop; desktop icon indices updated for the new entry. Verified: clean build on x86_64/aarch64/armv8i; boots through the SUB login to the desktop with the new Rust Lab icon rendering (screenshotted); checksum self-test prints, 0 panics / 0 OOM. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
This commit is contained in:
1 parent
e93b994469
commit
c414c20b44
8 files changed
+262
-2
No files matched your search
@@ -0,0 +1,93 @@
|
||||
//! Memory-safe run-length encoding (RLE) codec for SUB-OS.
|
||||
//!
|
||||
//! A compact PackBits-style byte codec: the stream is a sequence of
|
||||
//! (count, value) pairs where `count` is 1..=255. It is intended for run-heavy
|
||||
//! data (framebuffer scanlines, zeroed pages, simple bitmaps) and is fully
|
||||
//! `no_std` with no allocation -- the caller owns both buffers.
|
||||
|
||||
/// Compress `input` into `output` as (count, value) pairs. Returns the number
|
||||
/// of bytes written, or -1 if `output` is too small.
|
||||
pub fn rle_compress(input: &[u8], output: &mut [u8]) -> isize {
|
||||
let mut out = 0usize;
|
||||
let mut i = 0usize;
|
||||
let len = input.len();
|
||||
|
||||
while i < len {
|
||||
let value = input[i];
|
||||
let mut run = 1usize;
|
||||
while i + run < len && input[i + run] == value && run < 255 {
|
||||
run += 1;
|
||||
}
|
||||
if out + 2 > output.len() {
|
||||
return -1;
|
||||
}
|
||||
output[out] = run as u8;
|
||||
output[out + 1] = value;
|
||||
out += 2;
|
||||
i += run;
|
||||
}
|
||||
out as isize
|
||||
}
|
||||
|
||||
/// Expand a (count, value) stream back into `output`. Returns the number of
|
||||
/// bytes written, or -1 on a malformed stream or an output overflow.
|
||||
pub fn rle_decompress(input: &[u8], output: &mut [u8]) -> isize {
|
||||
let mut out = 0usize;
|
||||
let mut i = 0usize;
|
||||
let len = input.len();
|
||||
|
||||
while i + 1 < len {
|
||||
let run = input[i] as usize;
|
||||
let value = input[i + 1];
|
||||
if run == 0 {
|
||||
return -1; // a zero run is never emitted by the compressor
|
||||
}
|
||||
if out + run > output.len() {
|
||||
return -1;
|
||||
}
|
||||
for _ in 0..run {
|
||||
output[out] = value;
|
||||
out += 1;
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
out as isize
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C ABI shims
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_rle_compress(
|
||||
in_buf: *const u8,
|
||||
in_len: usize,
|
||||
out_buf: *mut u8,
|
||||
max_out: usize,
|
||||
) -> i32 {
|
||||
if in_buf.is_null() || out_buf.is_null() {
|
||||
return -1;
|
||||
}
|
||||
unsafe {
|
||||
let input = core::slice::from_raw_parts(in_buf, in_len);
|
||||
let output = core::slice::from_raw_parts_mut(out_buf, max_out);
|
||||
rle_compress(input, output) as i32
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_rle_decompress(
|
||||
in_buf: *const u8,
|
||||
in_len: usize,
|
||||
out_buf: *mut u8,
|
||||
max_out: usize,
|
||||
) -> i32 {
|
||||
if in_buf.is_null() || out_buf.is_null() {
|
||||
return -1;
|
||||
}
|
||||
unsafe {
|
||||
let input = core::slice::from_raw_parts(in_buf, in_len);
|
||||
let output = core::slice::from_raw_parts_mut(out_buf, max_out);
|
||||
rle_decompress(input, output) as i32
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user