defmodule BitFlagger do @moduledoc """ A set of functions that manipulate bit flags. """ use Bitwise, only_operators: true @doc """ Converts an integer to a list of boolean values. ## Examples iex> parse(0b1010, 4) [false, true, false, true] """ @spec parse(non_neg_integer, non_neg_integer) :: list(boolean) def parse(state, size) when is_integer(state) and is_integer(size) do for index <- 0..(size - 1), do: on?(state, index) end @doc """ Checks if the flag is turned on at a specified index. ## Examples iex> on?(0b0010, 1) true iex> on?(0b0010, 3) false """ @spec on?(non_neg_integer, non_neg_integer) :: boolean def on?(state, index) when is_integer(state) and is_integer(index) do (state >>> index &&& 0x01) == 1 end @doc """ Checks if the flag is turned off at a specified index. ## Examples iex> off?(0b0001, 1) true iex> off?(0b0001, 0) false """ @spec off?(non_neg_integer, non_neg_integer) :: boolean def off?(state, index), do: !on?(state, index) @doc """ Turns on the flag at a specified index. ## Examples iex> on(0b0000, 2) 0b0100 """ @spec on(non_neg_integer, non_neg_integer) :: non_neg_integer def on(state, index) when is_integer(state) and is_integer(index) do state ||| 0x01 <<< index end @doc """ Turns off the flag at a specified index. ## Examples iex> off(0b1111, 2) 0b1011 """ @spec off(non_neg_integer, non_neg_integer) :: non_neg_integer def off(state, index) when is_integer(state) and is_integer(index) do state &&& ~~~(0x01 <<< index) end end