flags
Defining struct with flags using integer mask
Current implementation support flags extraction up to 64 bits long integer
iex> defmodule IntegerMaskFlags do
...> use BinStruct
...> field :value, {
...> :flags,
...> %{
...> type: :uint32_le,
...> values: [
...> { 0x00000001, :info_mouse },
...> { 0x00000002, :info_disablectrlaltdel }
...> ]
...> }
...> }
...> end
...>
...> IntegerMaskFlags.new(value: [:info_mouse, :info_disablectrlaltdel])
...> |> IntegerMaskFlags.dump_binary()
...> |> IntegerMaskFlags.parse()
...> |> then(fn {:ok, struct, _rest } -> struct end)
...> |> IntegerMaskFlags.decode()
%{ value: [:info_mouse, :info_disablectrlaltdel] }
I found it's counterintuitively but preferred way to define flags using mask, not position. You can change endianness from little to big and it will be work the same, automatically reversing all positions.
Below is list of supported masks for developers to copy and paste from. Library checks its valid mask, (covering only 1 bit and never overlaps) so don't worry you will not be able to mistaken it.
def supported_masking_values(value) do
case value do
0x01 -> 1
0x02 -> 2
0x04 -> 3
0x08 -> 4
0x10 -> 5
0x20 -> 6
0x40 -> 7
0x80 -> 8
0x100 -> 9
0x200 -> 10
0x400 -> 11
0x800 -> 12
0x1000 -> 13
0x2000 -> 14
0x4000 -> 15
0x8000 -> 16
0x10000 -> 17
0x20000 -> 18
0x40000 -> 19
0x80000 -> 20
0x100000 -> 21
0x200000 -> 22
0x400000 -> 23
0x800000 -> 24
0x1000000 -> 25
0x2000000 -> 26
0x4000000 -> 27
0x8000000 -> 28
0x10000000 -> 29
0x20000000 -> 30
0x40000000 -> 31
0x80000000 -> 32
0x100000000 -> 33
0x200000000 -> 34
0x400000000 -> 35
0x800000000 -> 36
0x1000000000 -> 37
0x2000000000 -> 38
0x4000000000 -> 39
0x8000000000 -> 40
0x10000000000 -> 41
0x20000000000 -> 42
0x40000000000 -> 43
0x80000000000 -> 44
0x100000000000 -> 45
0x200000000000 -> 46
0x400000000000 -> 47
0x800000000000 -> 48
0x1000000000000 -> 49
0x2000000000000 -> 50
0x4000000000000 -> 51
0x8000000000000 -> 52
0x10000000000000 -> 53
0x20000000000000 -> 54
0x40000000000000 -> 55
0x80000000000000 -> 56
0x100000000000000 -> 57
0x200000000000000 -> 58
0x400000000000000 -> 59
0x800000000000000 -> 60
0x1000000000000000 -> 61
0x2000000000000000 -> 62
0x4000000000000000 -> 63
0x8000000000000000 -> 64
end
end
Variable bit size
iex> defmodule IntegerVariableBitSizeMaskFlags do
...> use BinStruct
...> field :value, {
...> :flags,
...> %{
...> type: :uint_le,
...> values: [
...> { 0x00000001, :info_mouse },
...> { 0x00000002, :info_disablectrlaltdel }
...> ]
...> }
...> }, bits: 24
...> end
...>
...> IntegerVariableBitSizeMaskFlags.new(value: [:info_mouse, :info_disablectrlaltdel])
...> |> IntegerVariableBitSizeMaskFlags.dump_binary()
...> |> IntegerVariableBitSizeMaskFlags.parse()
...> |> then(fn {:ok, struct, _rest } -> struct end)
...> |> IntegerVariableBitSizeMaskFlags.decode()
%{ value: [:info_mouse, :info_disablectrlaltdel] }