Outside of the Wuffs base package, every Wuffs struct has an implicit initialize
method, which needs to be called before any other method. In Wuffs' C language form, the initialize
function for the foo
package's bar
struct is called wuffs_foo__bar__initialize
. The function takes four arguments (or, in C++, the initialize
method takes three arguments, with the implicit this
pointer argument):
wuffs_foo__bar
object: the this
pointer.sizeof(wuffs_foo__bar{})
, but that expression generally won't compile, as wuffs_foo__bar
is deliberately an incomplete type. Its size is not part of the stable ABI. Instead, call the sizeof__wuffs_foo__bar
function, whose return value can change across Wuffs versions, even across point releases. For an example, look for sizeof__wuffs_json__decoder
in the example/jsonptr program.WUFFS_VERSION
.Initialization can fail if the caller and callee disagree on the size or the Wuffs version, or if unsupported flag bits are passed.
There are no destructor functions. Just free the memory. Wuffs structs don't store or otherwise own file descriptors, pointers to dynamically allocated memory or anything else that needs explicit releasing.
As a consequence, to restore a Wuffs object to its initial state (e.g. to re-use a Wuffs image decoder's memory to decode a different image), just call the initialize
function again.
The flags are a bitmask of options. Zero (or equivalently, WUFFS_INITIALIZE__DEFAULT_OPTIONS
) means that none of the options are set.
WUFFS_INITIALIZE__ALREADY_ZEROED
bit tells the initialize
function to assume that the entire struct has already been zero-initialized. This can make the initialize
call a little faster.WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED
bit means to partially, not fully, zero-initialize the struct. Again, this can make the call a little faster. See the “Partial Zero-Initialization” section below for details. This bit is ignored if the WUFFS_INITIALIZE__ALREADY_ZEROED
bit is also set.Memory-safe programming languages typically initialize their variables and fields to zero, so that there is no way to read an uninitialized value. By default, Wuffs does so too, but in Wuffs' C/C++ form, there is the option (the WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED
flag bit) to leave some struct fields uninitialized (although local variables are always zero-initialized), for performance reasons.
With or without this flag bit set, the Wuffs compiler still enforces bounds and arithmetic overflow checks. It's just that for potentially-uninitialized struct fields, the compiler has weaker starting assumptions: their numeric types cannot be refined.
Even with this flag bit set, the Wuffs standard library also considers reading from an uninitialized buffer to be a bug, and strives to never do so, but unlike buffer out-of-bounds reads or writes, it is not a bug class that the Wuffs compiler eliminates.
For those paranoid about security, leave this flag bit unset, so that wuffs_foo__bar__initialize
will zero-initialize the entire struct (unless the WUFFS_INITIALIZE__ALREADY_ZEROED
flag bit is also set).
Setting this flag bit (avoiding a fixed-size cost) gives a small absolute improvement on micro-benchmarks, mostly noticeable (in relative terms) only when the actual work to do (the input) is also small. Look for WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED
in the benchmarks for performance numbers.
In Wuffs code, a struct definition has two parts, although the second part's ()
parentheses may be omitted if empty:
pub struct bar?( // Fields in the first part are always zero-initialized. x : etc, y : etc, )( // Fields in the second part are optionally uninitialized, but are still // zero-initialized by default. // // Valid types for these fields are either unrefined numerical types, or // arrays of a valid type. // - "base.u8" is ok. // - "array[123] base.u8" is ok. // - "array[123] base.u8[0 ..= 99]" is not, due to the refinement. z : etc, )