Files
oak-editor/crates/oak-common/README.md
T
Mike-Solar 244d5e860f
CI / Build & test (Windows) (push) Failing after 7s
workspace: kebab-case crates, app under crates/oak-app, shared versions
All crates take the oak-* kebab-case naming (oak-audio, oak-codec,
oak-common, oak-core, oak-ffmpeg-link, oak-node, oak-otio, oak-plugin,
oak-render, oak-storage, oak-task, oak-timeline, oak-undo), with the
lib identifiers rewritten (oakrender:: -> oak_render::, oakcore_rs:: ->
oak_core::, ...) across all 226 referencing files.

The GUI application moves from the workspace root into
crates/oak-app/: src/, build.rs (paths fixed for the new location) and
tests/ travel with it, the root Cargo.toml becomes workspace-only
([workspace] + workspace.package + profiles), and the app package
inherits the workspace version. The screenshots example becomes a
standalone crate examples/simple_player/ with its own Cargo.toml.

Every crate now inherits the single workspace version
(version.workspace = true), and the workflows' crate paths and the
build docs follow the renames.

Validated with a clean cargo check --workspace.
2026-08-22 16:58:37 +08:00

105 lines
5.8 KiB
Markdown

# oakcommon Rust crate
> Status: **implemented**. All `include/common/*.h` contracts are
> implemented in Rust and covered by unit + C ABI integration tests
> (see [Testing](#testing)).
## Scope
Replaces the C++ oakcommon module (`src/common/src`): config store,
command-line parser, XML stream reader/writer, file functions,
debug/logging, ffmpeg/OCIO/OIIO utility queries, video/subtitle
params, color transform, misc utilities. Pure leaf module — depends
only on `oakcore-rs`, `quick-xml`, `log`, `ocio-rs`, `image`, and
system libraries.
Public contract: `include/common/*.h` (18 headers) — frozen,
implemented verbatim by `src/ffi.rs`.
## Third-party crates
| Crate | Version | License | Status |
|---|---|---|---|
| `quick-xml` | 0.41 | MIT | adopted — XML reader/writer (`xmlutils.rs`) |
| `log` | 0.4 | MIT / Apache-2.0 | adopted — logging facade (`debug.rs`); the stderr sink is retained as the always-available backend |
| `ocio-rs` | 0.2.1 | BSD-3-Clause | adopted — real OpenColorIO access for `ocioutils.rs` (`OcioConfig`/`OcioProcessor`, `BitDepth` mapping). Pulled in via `ocio-sys` built with `OCIO_RS_ENABLE_REAL=1` against the Homebrew OCIO install (see `.cargo/config.toml`) |
| `image` | 0.25 | MIT / Apache-2.0 | adopted — per-channel bit-depth tables and 32-bit float TIFF I/O for `oiioutils.rs` (`image_color_type_for`/`bits_per_channel`, `F32Image`). Default features off, `tiff` only |
| `oakcore-rs` | path | GPL-3.0 | adopted — `Rational::from_double` (the C++ `Rational::from_double` port of FFmpeg's `av_d2q`) for `get_pixel_aspect_ratio`; a hand-written port kept in the leaf crate instead of pulling in `ffmpeg-next` |
| `serde_json` | — | MIT / Apache-2.0 | **evaluated, not adopted** — the ConfigStore format is INI (QSettings-style `key=value` with `[group]` sections, `%g` doubles), not JSON; switching would break C++/Rust file interop |
| `pico-args` / `clap` | — | MIT / Apache-2.0 | **evaluated, not adopted**`commandlineparser.rs` must keep exact C++ quirks (case-insensitive names, first-match-wins, last-value-wins, argv[0] skipping, truncating getter copies, borrowed C ABI handles) that a generic parser cannot express without changing the C ABI shape |
## Architectural decisions
1. **Leaf module discipline**: no `bridge/` to other oak modules.
FFmpeg is reached through `ffmpeg_bridge`'s C ABI (narrow
`extern "C"` blocks in `ffmpegutils.rs`); OCIO and OIIO access is
pure Rust via the crates.io bindings listed in the table above
(`ocioutils.rs`, `oiioutils.rs`).
2. **`olive::Variant` disappears**: it exists in C++ only because
QVariant left a hole. Rust modules use closed enums; nothing in
common needs it. `variant.{h,cpp}` (C++) is retired when all
consumers are Rust.
3. **XML**: `XmlStreamReader/Writer` keep the C++ streaming API shape
(the C ABI is built on it), implemented over quick-xml — behavior
(attribute order, error semantics) pinned by tests against the C++
oracle.
4. **Config**: the ConfigStore is **INI-backed** (QSettings-style
`key=value` with `[group]` sections, `;`/`#` comments, `%g`
double formatting), keeping the exact C++ file format and lookup
order (user config → app defaults). It is *not* JSON — an earlier
draft described it as JSON-backed, which was wrong; that claim was
removed from this document.
5. **Logging**: `debug.rs` provides the leveled logger
(qWarning/qDebug/qCritical/qInfo replacement) with a printf-style C
ABI. Every record is written to stderr (the C++ `stderr_sink`
parity) and additionally forwarded to the `log` crate's global
logger when the host has installed one. oakcommon never installs a
global logger itself — the C ABI is loaded into hosts that set
their own, and `log::set_logger` can only be called once per
process.
6. **OCIO / OIIO / FFmpeg**: `ocioutils.rs` talks to real OpenColorIO
through the crates.io `ocio-rs` bindings (`OcioConfig`/`OcioProcessor`,
`BitDepth` enum — no hand-written constant tables); `oiioutils.rs`
derives its OIIO base-type mapping from the `image` crate's color-type
tables (HALF pinned from the frozen OIIO table — `image` has no f16
sample type) and converts aspect ratios with
`oakcore_rs::Rational::from_double` — a hand-written port of FFmpeg's
`av_d2q` matching the C++ `Rational::from_double` exactly, kept in the
leaf crate rather than adding `ffmpeg-next`/`ffmpeg-sys-next` (narrow
extern C discipline). 32-bit float image I/O (`F32Image`) is pure
`image`. All adopted crates are registered in the table above.
## Layout
```
src/
lib.rs crate doc + module map
error.rs error codes (include/common/error.h)
handle.rs refcounted-handle scaffolding
configstore.rs INI config (include/common/config.h)
commandlineparser.rs
xmlutils.rs streaming XML reader/writer
filefunctions.rs file/dir helpers
debug.rs leveled logging
ffmpegutils.rs pixfmt/samplefmt mapping (via ffmpeg_bridge C ABI)
ocioutils.rs OCIO queries
oiioutils.rs OIIO queries
videoparams.rs VideoParams plain data + queries
subtitleparams.rs SubtitleParams
colortransform.rs ColorTransform plain data
miscutils.rs misc (loop mode, drop behavior, power, current…)
ffi.rs export layer (one submodule per public header)
tests/ contract tests per module
```
## Testing
`cargo test --release --features test-stubs` runs the full suite:
unit tests, C ABI contract tests, and the integration tests (incl.
`tests/ffi_ffmpegutils.rs`). The `test-stubs` feature substitutes the
in-crate ffmpeg_bridge mock (`fb_find_best_pix_fmt_of_list` stub, see
`src/ffmpegutils.rs`) so the C ABI tests link without
libffmpeg_bridge; without the feature that symbol is imported from
`ffmpeg_bridge` at link time. This mirrors the `test-stubs`
convention of oakplugin / oaktimeline.