flipperzero-rs / flipperzero

Rust on the Flipper Zero
MIT License
459 stars 31 forks source link

Better string formatting #129

Open dcoles opened 5 months ago

dcoles commented 5 months ago

As a developer, there are currently three main options for formatting strings in Flipper apps:

Safe Expressiveness Binary size overhead
std::fmt High High[^1]
ufmt Low Low
sys::furi_string_printf High None[^2]

Using std::fmt is the most flexible and familiar option for developers, but it can add 10+ KB to the overall binary size simply by formatting a single string. While this may be a reasonable trade-off made by an app developer, it's not something we can impose on all users of the flipperzero crates.

Enter ufmt which has substantially lower binary overhead, but comes at the expense of expressiveness (no padding/alignment/formatting options, no support for floats) and requires implementing the non-standard ufmt::uDisplay and ufmt::uWrite traits.

Finally there is the built-in sys::furi_string_printf C function, which has no binary-size overhead (it's provided by the Furi runtime), but is problematic to use in Rust because it has a variadic-based interface which is both unsafe and difficult to support in Rust (Rust currently only has limited support for C-variadic functions).

It would be nice to provide an option somewhere in the middle.

[^1]: See #48 and Formatting is Unreasonably Expensive for Embedded Rust [^2]: Provided by Furi runtime

dcoles commented 5 months ago

One thought that came to mind was to provide a mechanism for safely using printf-style functions from Rust (e.g. a procedural macro that generates safe printf calls).

Another possibility would be for us to provide Display / Write traits that allow printf-style calls to be made internally (while still providing a safe external interface).