# Integer as Bit-Fields

Note

Nothing here cannot be done via standard bit-manipulation (i.e. shifting and masking).

Built-in support is more elegant and performant since it usually replaces a sequence of multiple steps.

Since bit-wise operators are defined on integer numbers, individual bits can also be accessed and manipulated via an indexing syntax.

If a bit is set (i.e. `1`), the index access returns `true`.

If a bit is not set (i.e. `0`), the index access returns `false`.

When a range is used, the bits within the range are shifted and extracted as an integer value.

Bit-fields are very commonly used in embedded systems which must squeeze data into limited memory. Built-in support makes handling them efficient.

Indexing an integer as a bit-field is disabled for the `no_index` feature.

## Syntax

### From Least-Significant Bit (LSB)

Bits in a bit-field are accessed with zero-based, non-negative integer indices:

integer `[` index from 0 to 63 or 31 `]`

integer `[` index from 0 to 63 or 31 `] =` `true` or `false` ;

Ranges can also be used:

integer `[` start `..` end `]`
integer `[` start `..=` end `]`

integer `[` start `..` end `] =` new integer value ;
integer `[` start `..=` end `] =` new integer value ;

Number of bits

The maximum bit number that can be accessed is 63 (or 31 under `only_i32`).

Bits outside of the range are ignored.

### From Most-Significant Bit (MSB)

A negative index accesses a bit in the bit-field counting from the end, or from the most-significant bit, with −1 being the highest bit.

integer `[` index from −1 to −64 or −32 `]`

integer `[` index from −1 to −64 or −32 `] =` `true` or `false` ;

Ranges always count from the least-significant bit (LSB) and has no support for negative positions.

Number of bits

The maximum bit number that can be accessed is −64 (or −32 under `only_i32`).

## Bit-Field Functions

The following standard functions (defined in the `BitFieldPackage` but excluded when using a raw `Engine`) operate on `INT` bit-fields.

These functions are available even under the `no_index` feature.

FunctionParameter(s)Description
`get_bit`bit number, counting from MSB if < 0returns the state of a bit: `true` if `1`, `false` if `0`
`set_bit`
1. bit number, counting from MSB if < 0
2. new state: `true` if `1`, `false` if `0`
sets the state of a bit
`get_bits`
1. starting bit number, counting from MSB if < 0
2. number of bits to extract, none if < 1, to MSB if ≥ length
extracts a number of bits, shifted towards LSB
`get_bits`range of bitsextracts a number of bits, shifted towards LSB
`set_bits`
1. starting bit number, counting from MSB if < 0
2. number of bits to set, none if < 1, to MSB if ≥ length
3) new value
sets a number of bits from the new value
`set_bits`
1. range of bits
2. new value
sets a number of bits from the new value
`bits` method and property
1. (optional) starting bit number, counting from MSB if < 0
2. (optional) number of bits to extract, none if < 1, to MSB if ≥ length
allows iteration over the bits of a bit-field
`bits`range of bitsallows iteration over the bits of a bit-field

## Example

``````// Assume the following bits fields in a single 16-bit word:
// ┌─────────┬────────────┬──────┬─────────┐
// │  15-12  │    11-4    │  3   │   2-0   │
// ├─────────┼────────────┼──────┼─────────┤
// │    0    │ 0-255 data │ flag │ command │
// └─────────┴────────────┴──────┴─────────┘

let command = value.get_bits(0, 3);         // Command = bits 0-2

let flag = value[3];                        // Flag = bit 3

let data = value[4..=11];                   // Data = bits 4-11
let data = value.get_bits(4..=11);          // <- above is the same as this

let reserved = value.get_bits(-4);          // Reserved = last 4 bits

if reserved != 0 {
throw reserved;
}

switch command {
0 => print(`Data = \${data}`),
1 => value[4..=11] = data / 2,
2 => value[3] = !flag,
_ => print(`Unknown: \${command}`)
}
``````