API Reference

Public API

The following symbols are considered API for the purposes of semver.

Macros

FieldFlags.@bitflagsMacro
@bitflags [mutable] struct MyFlags
    flagA
    flagB
    _ # padding
    flagC
end

Construct a struct representing various boolean flags, stored in a compact format where each flag takes up a single bit. Field access gives a Bool, explicit padding can be declared by naming a field _. Field names (other than padding) need to be unique. The struct can optionally be marked mutable.

See also @bitfield.

Struct size

Due to compiler limitations, the size of the resulting object will (currently) always be a multiple of 8 bits. The additional bits added due to this are considered padding and can not be relied on to exist. They may be removed in a future release without notice.

Examples

julia> @bitflags mutable struct MyFlags
           flagA
           flagB
           _ # padding
           flagC
       end

julia> flags = MyFlags(true, false, true)
MyFlags(flagA: true, flagB: false, flagC: true)

julia> flags.flagA
true

julia> flags.flagB
false

julia> flags.flagB = true
true

julia> flags.flagB
true

julia> sizeof(flags)
1
FieldFlags.@bitfieldMacro
@bitfield [mutable] struct MyBits
    a:2
    b:3
    _[:3] # padding; width is assumed 1 bit if the length is omitted
    c:1
end

Construct a struct representing various fields, with their size specified in bits. The struct can optionally be marked mutable.

See also @bitflags.

Extended Help

The fields are stored in a compact format where each field only takes up the specified number of bits. Field access gives an unsigned integer, whose lower bits are the bits of the accessed field. The upper bits are zeroed. As a special case, fields with size 1 return a Bool. Explicit padding can be specified by naming a field _, with freely chosen width. Field names (other than padding) need to be unique. The specified number of bits must be >= 0.

The order the fields are given in is the order the fields are stored in. The first field occupies the least significant bits, followed by the second field, up to the last field, which is stored in the most significant bits.

For example, the struct given above has this layout:

MSBLSB
c___bbbaa

where _ is padding, with undefined value.

The constructor created for structs defined with @bitfield takes any type in Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8, Bool} and converts it to the correct size by truncating the upper bits, before storing the truncated value in the object. This truncation also occurs when writing to a field of a mutable object.

Struct size

Due to compiler limitations, the size of the resulting object will (currently) always be a multiple of 8 bits. The additional bits added due to this are considered padding and can not be relied on to exist. They may be removed in a future release without notice. If you need padding up to a given size, explicitly specify a trailing padding field.

Field type

As there are no variable sized integers in Julia, it is only guaranteed that the return type on field access is large enough to hold all bits required by that field. While currently field sizes larger than 1 return an UInt, this is in particular not guaranteed and may be changed in the future, so that e.g. a field of size 2 returns an UInt8 instead.

Examples

julia> @bitfield struct MyBits
           a:2
           b:3
           _:3 # padding
           c:1
       end

julia> bits = MyBits(1,2,3)
MyBits(a: 0x1, b: 0x2, c: true)

julia> bits.a
0x0000000000000001

julia> bits.b
0x0000000000000002

julia> bits.c
true

Functions

These functions are explicitly not exported, to prevent confusion with Base.fieldoffset and similar field and property related functions.

FieldFlags.propertyoffsetFunction
propertyoffset(::Type{T}, s::Symbol) -> Int

Gives the offset (in bits) the field s is placed at in objects of type T.

See also FieldFlags.fieldsize.

julia> @bitflags mutable struct MyFlags
           flagA
           _ # padding
           flagB
       end

julia> FieldFlags.propertyoffset(MyFlags, :flagA)
0

julia> FieldFlags.propertyoffset(MyFlags, :flagB)
2
FieldFlags.fieldsizeFunction
fieldsize(::Type{T}, s::Symbol) -> Int

Gives the size (in bits) the field s takes up in objects of type T.

See also FieldFlags.propertyoffset.

julia> @bitfield mutable struct MyBits
           a:2
           _ # padding
           b:3
       end

julia> FieldFlags.fieldsize(MyBits, :a)
2

julia> FieldFlags.fieldsize(MyBits, :b)
3

Additional Supported API

These functions are listed because they are supported, but their docstrings can't be displayed without having an instance of a type created via @bitfield or @bitflags.

  • Base.propertynames
    • Gives a tuple of the properties given in the original expression given to @bitfield or @bitflags.
  • convert(::T, x::Union{Bool, Base.BitInteger})
    • Converts x to a T, originally created via the macros of this package. If the sizes don't match, x is either truncated or its bitrepresentation is zero-extended to fit the size of T.

Internal API

The following symbols are NOT considered API for the purposes of semver. They are documented here as a useful reference, not as a statement of semver guarantees.

FieldFlags.bitflagsFunction
bitflags(::Expr)

The given `Expr(:struct) has the following format

struct MyFlags
    a
    b
    _
end

which is turned into

struct MyFlags
    a:1
    b:1
    _:1
end

before being passed to FieldFlags.bitfield.

Some minimal expression filtering is performed.

See also @bitflags, @bitfield.

FieldFlags.bitfieldFunction
bitfield(expr::Expr)

Takes an Expr(:struct) of the form

struct MyStruct
    a:x
    b:y
    _
    _:z
end

where a, b are potential field names, x, y, and z are desired bitwidths for those fields as integer literals, _ is padding and returns the following expression:

Expr(:block,
    typedefs,
    typefuncs,
    conv,
    eqhash,
    shows,
    propsize,
    propoffset,
    getprop,
    setprop
)

Where typedefs are the new user-facing type definition and the internal type definitions, typefuncs are type related functions from Base for the new types, conv are convert methods to those types, propsize is the implementation for FieldFlags.fieldsize, propoffset is the implementation for FieldFlags.propertyoffset, getprop is the definition for the getproperty overload for the user facing type and setprop is the definition for the setproperty! overloda for the user facing type.

See also FieldFlags.bitflags.

FieldFlags.cast_extend_truncateFunction
cast_extend_truncate(T::DataType, x) -> T

Takes an object x of a primitive type and either bitcasts it to type T (if their sizes are egal), zero extends the bitrepresentation of x to the size of T, or truncates the bitrepresentation of x to sizeof(T).

Returns a T.

See also FieldFlags.cast_or_extend.

FieldFlags.cast_or_extendFunction
cast_or_extend(T::DataType, x) -> T

Takes an object x of a primitive type and either bitcasts it to T (if their sizes are egal) or zero-extends the bitrepresentation of x to the size of T. sizeof(x) <= sizeof(T) must hold.

Returns a T.

See also FieldFlags.cast_extend_truncate.