BitwiseIp.Block.size

You're seeing just the function size, go back to BitwiseIp.Block module for more information.

Specs

size(t()) :: integer()

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