mirror of
https://github.com/storytold/craft-anything.git
synced 2026-11-02 18:06:58 +00:00
Bun text assets report their stored UTF-16LE encoding (R3.11) (#435)
Bun's stored-text encoding 2 is labelled utf16le, as Bun writes it, and member bytes are kept as stored. Fixes #257.
This commit is contained in:
@@ -283,7 +283,7 @@ impl PackedFormat for BunProgram {
|
||||
let kind = format!(
|
||||
"loader={loader} format={} encoding={} side={} sourcemap_bytes={} bytecode_bytes={}",
|
||||
label(&["none", "esm", "cjs"], m.format),
|
||||
label(&["binary", "latin1", "utf8"], m.encoding),
|
||||
label(&["binary", "latin1", "utf16le"], m.encoding),
|
||||
label(&["server", "client"], m.side),
|
||||
m.sourcemap.len,
|
||||
m.bytecode.len,
|
||||
@@ -345,7 +345,7 @@ mod tests {
|
||||
let app = &listing.entries[0];
|
||||
assert_eq!(app.path, "root/app.js");
|
||||
assert_eq!(BunProgram.read(data, app, 1000).unwrap(), b"console.log('app')");
|
||||
assert_eq!(app.kind.as_deref(), Some("loader=js format=esm encoding=utf8 side=server sourcemap_bytes=9 bytecode_bytes=10"));
|
||||
assert_eq!(app.kind.as_deref(), Some("loader=js format=esm encoding=latin1 side=server sourcemap_bytes=9 bytecode_bytes=10"));
|
||||
let logo = &listing.entries[1];
|
||||
assert_eq!(logo.path, "root/logo.png");
|
||||
assert_eq!(BunProgram.read(data, logo, 1000).unwrap(), b"\x89PNG");
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
use craft_anything_formats::bun_program::BunProgram;
|
||||
use craft_anything_formats::packed::PackedFormat;
|
||||
use craft_anything_testkit::packed::{BunModule, bun_appended, bun_graph, bun_module};
|
||||
|
||||
#[test]
|
||||
fn reports_stored_text_encodings_without_transcoding_bytes() {
|
||||
let text = "café 🍵\n";
|
||||
let wide: Vec<u8> = text.encode_utf16().flat_map(u16::to_le_bytes).collect();
|
||||
let modules = [
|
||||
BunModule { encoding: 2, loader: 13, format: 0, ..bun_module("/$bunfs/root/wide.txt", &wide) },
|
||||
BunModule { encoding: 1, loader: 13, format: 0, ..bun_module("/$bunfs/root/latin.txt", b"caf\xe9") },
|
||||
BunModule { encoding: 0, loader: 5, format: 0, ..bun_module("/$bunfs/root/raw.bin", b"\x00\xff\x80") },
|
||||
];
|
||||
for record_bytes in [36, 52] {
|
||||
for offsets_bytes in [24, 32] {
|
||||
let bytes = bun_appended(&bun_graph(&modules, 0, "", record_bytes, offsets_bytes));
|
||||
let listing = BunProgram.list(&bytes).unwrap();
|
||||
assert_eq!(listing.entries.len(), 3);
|
||||
for (entry, (encoding, expected)) in listing.entries.iter().zip([("utf16le", wide.as_slice()), ("latin1", b"caf\xe9"), ("binary", b"\x00\xff\x80")])
|
||||
{
|
||||
assert!(entry.kind.as_deref().unwrap().split_whitespace().any(|part| part == format!("encoding={encoding}")), "{:?}", entry.kind);
|
||||
assert_eq!(BunProgram.read(&bytes, entry, 1024).unwrap(), expected);
|
||||
}
|
||||
let raw = BunProgram.read(&bytes, &listing.entries[0], 1024).unwrap();
|
||||
assert!(std::str::from_utf8(&raw).is_err());
|
||||
let (pairs, remainder) = raw.as_chunks::<2>();
|
||||
assert!(remainder.is_empty());
|
||||
let units: Vec<u16> = pairs.iter().copied().map(u16::from_le_bytes).collect();
|
||||
assert_eq!(String::from_utf16(&units).unwrap(), text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -353,7 +353,7 @@ pub struct BunModule<'a> {
|
||||
|
||||
/// A JavaScript module as `bun build --compile` stores one.
|
||||
pub fn bun_module<'a>(name: &'a str, contents: &'a [u8]) -> BunModule<'a> {
|
||||
BunModule { name, contents, sourcemap: b"", bytecode: b"", encoding: 2, loader: 1, format: 1, side: 0 }
|
||||
BunModule { name, contents, sourcemap: b"", bytecode: b"", encoding: 1, loader: 1, format: 1, side: 0 }
|
||||
}
|
||||
|
||||
fn bun_put(o: &mut Vec<u8>, b: &[u8]) -> (u32, u32) {
|
||||
|
||||
@@ -1124,6 +1124,7 @@ should give away more of how it is set up.
|
||||
Owner: open · Status: in progress
|
||||
Read what real apps and games ship as (one file carrying the rest), and let a rebuilt website run
|
||||
against what its original was recorded answering.
|
||||
- [x] Identify Bun UTF-16LE text members (#257). — claimed: Afloat16, branch bugfix/r3.11-bun-text-encoding-20261102
|
||||
- [x] One seam for files packed inside a file (`formats::packed`), with `core_packed_files_list`
|
||||
and `core_packed_files_unpack`; a new kind is one reader and one table line
|
||||
- [x] Readers: Bun and Node.js single-file programs, .NET single-file apps, PyInstaller, Godot PCK.
|
||||
|
||||
@@ -29,6 +29,13 @@ workspace clippy, layers, fmt and the secret scan of all history were clean. Chi
|
||||
| CLI | Every tool, `--deep` or `--clean-room` for one run (never saved), `rebuild` (including `--continue-in`, and `--resume` to carry on a stopped build), `mcp --inbox`, `ai`, `setup`, `doctor`, `report` | CLI integration tests |
|
||||
| SQLite database files (`db_sqlite_show`) | A rowid alias column (`INTEGER PRIMARY KEY`, including the table-constraint form) shows the rowid; `DESC`, non-`INTEGER` and composite keys keep their stored values | Hand-built fixtures; generated files compared with the official SQLite library |
|
||||
|
||||
### Bun stored-text encoding
|
||||
|
||||
Packed Bun members with encoding value 2 are labelled `utf16le`, matching their stored UTF-16LE
|
||||
bytes. Reading or unpacking preserves those bytes. Synthetic graphs cover UTF-16LE (including a
|
||||
surrogate pair), Latin1 and binary members across both supported module-record and offsets-block
|
||||
sizes. A freshly compiled Bun program and the CLI/MCP transport were not run for this correction.
|
||||
|
||||
### Linux Unreal setup
|
||||
|
||||
Unreal installations registered in `~/.config/Epic/UnrealEngine/Install.ini` are found on Linux.
|
||||
|
||||
Reference in New Issue
Block a user