Wuffs is a memory-safe programming language, achieving that safety in part because Wuffs code is hermetic and doesn't even have the capability to dynamically allocate and free memory. Wuffs code is also transpiled to C (which is very portable and easy to bind to other, higher-level languages), but C lacks modern conveniences like a built-in string type that's safe and easy to use.
Wuffs' C/C++ form (a "single file library") also contains auxiliary C++ code
(in the wuffs_aux
namespace) that compensates for that. For example, the JSON
decoder that is written in the memory-safe Wuffs language works with low-level
tokens. The high-level wuffs_aux::DecodeJson
auxiliary
function instead uses e.g. a std::string
and a double
for the JSON inputs
"foo\tbar"
and 0.3
. This API is more convenient for the programmer who
uses Wuffs-the-library, but there are several trade-offs:
- Technically,
0.99999999999999999
and1.0
are different JSON values, and the low-level Wuffs JSON decoder can distinguish them, but the high-levelwuffs_aux
JSON decoder will treat them identically (as a C++double
). - The low-level API is more modular and can work with a variety of
StringToDouble implementations (which converts the string
"0.3"
, unquoted in the JSON input, to the number0.3
). The high-level API always uses Wuffs' own StringToDouble implementation, which makes one particular choice on the binary size versus runtime performance frontier. Other choices are viable too, especially when integrating with an existing C/C++ project that already uses another StringToDouble library. - In the worst case (when the JSON input is just one giant string),
wuffs_aux
requiresO(N)
memory, whereN
is the input length. In comparison, the example/jsonptr program, which works with the low-level token API, can process arbitrarily long input inO(1)
memory. - The auxiliary code is hand-written C++. It's carefully written and there's not a lot of it, but unlike code written in the Wuffs language, its memory-safety is not enforced by the Wuffs toolchain.
- For simplicity, it assumes that all I/O can be performed synchronously. This
is trivially true if the input is already entirely in memory (e.g. as a
std::string
or astd::vector
). However, the auxiliary code should not be used on e.g. the GUI main thread if it could block on network I/O (and make the GUI unresponsive). In such cases, use the low-level Wuffs API instead.
Similarly, decoding an image using the written-in-Wuffs low-level API involves
multiple steps and the
wuffs_aux::DecodeImage
high-level API provides something more convenient,
albeit with similar trade-offs.
Grepping the examples directory for wuffs_aux
should reveal code
examples with and without using the auxiliary code library.