BitwiseIp.Block.size
size
, go back to BitwiseIp.Block module for more information.
Specs
Computes the number of addresses contained in a block.
This value is wholly determined by the :mask
field. Taking the bitwise
complement of the mask gives us an unsigned integer where all the lower bits
are ones. Since these are the bits that are covered by the block, we can
interpret this as the number of possible values, minus one for the zeroth
address.
For example, the IPv4 prefix /29
leaves 3 bits to represent different
addresses in the block. So that's 2^3 = 8 possible addresses. To get there
from the mask 0b11111111111111111111111111111000
, we take its complement
and get 0b00000000000000000000000000000111
, which represents the integer
2^3 - 1 = 7. We add 1 and get the 8 possible addresses.
Because of the limited number of possible masks, we might want to implement this as a static lookup using pattern matched function clauses, thereby avoiding binary manipulation altogether. However, benchmarks indicate that pattern matching against structs is much slower than the required bitwise math. So, we negate the mask and add 1 to the resulting integer at run time.
Examples
iex> BitwiseIp.Block.parse!("1.2.3.4/32") |> BitwiseIp.Block.size()
1
iex> BitwiseIp.Block.parse!("1.2.3.4/31") |> BitwiseIp.Block.size()
2
iex> BitwiseIp.Block.parse!("1.2.3.4/30") |> BitwiseIp.Block.size()
4
iex> BitwiseIp.Block.parse!("1.2.3.4/29") |> BitwiseIp.Block.size()
8
iex> BitwiseIp.Block.parse!("::/124") |> BitwiseIp.Block.size()
16
iex> BitwiseIp.Block.parse!("::/123") |> BitwiseIp.Block.size()
32
iex> BitwiseIp.Block.parse!("::/122") |> BitwiseIp.Block.size()
64
iex> BitwiseIp.Block.parse!("::/121") |> BitwiseIp.Block.size()
128