Dreamacro:erofs-rs 先消除 sync/async builder 重复,再推进并行压缩

Dreamacro 认为 erofs-rs 应让共享逻辑集中在一处,优先采用更 sans-I/O 的 option 1;sync/async builder 已出现 append_flat 行为漂移,建议先从 build/sync.rs 与 build/async.rs 去重,再处理 #15 的并行压缩。reader 保留借用式零拷贝与 no_std,sync API 不应被 AsyncRead 的 Send 约束拖累。

作者原文

Thanks for the survey. It matches my understanding, and reducing duplication matters a lot to me. I'd like shared logic to live in one place as much as possible.

The builder already shows the cost of keeping two copies: they have started to drift. For example, the sync append_flat has a single-block fast path that the async version doesn't have. Every future change, including the parallel compression in #15, would also have to be made twice.

On the approaches: I lean toward option 1 (more sans-I/O). It matches the reader's design, which already has plan_inode_read / BlockPlan. It also keeps the code in plain Rust, with readable rustdoc and error messages. Option 4 on its own doesn't solve the problem. A shared behavioural test suite is a good safety net either way, but it only catches drift and doesn't remove the duplication. Option 3 worries me even for the builder. The sync Builder currently accepts any Read, while our AsyncRead requires Send, so routing sync through an async core would add bounds to the sync API.

On your questions:

  1. Yes. Zero-copy access via mmap/slices and no_std support are core features of the reader, so the sync path must keep the borrowed Image::get path.
  2. I'd prefer plain Rust. A small in-house macro_rules! is acceptable if it is clearly smaller and easier to read than the alternative. I'd avoid maybe-async-style crates, though. maybe-async, for example, chooses sync or async with a crate-wide feature, but we expose both at the same time.
  3. Starting with the builder makes sense. build/sync.rs and build/async.rs are nearly line-for-line copies around the same State, so that's the cheapest win and the clearest signal. The reader is less of a pain point because its sans-I/O core already exists.
  4. Nothing is pending from me in build/. The main overlap is with #15, since both touch the compression path (append_compressed). I'd suggest landing the deduplication first. That way the parallel pipeline only has to be written once instead of separately for sync and async.

The evaluation criteria look good to me. A draft PR with the comparison table is a good way to start. Feel free to go ahead.