defmodule Excrc32c do @moduledoc """ A pure Elixir implementation of the CRC32C algorithm. ### Usage ```elixir iex> Excrc32c.crc32c("123456789") 3808858755 iex> Excrc32c.crc32c("DYB|O") 0 ``` """ import Bitwise @crc32c_poly 0x82F63B78 @uint32_mask 0xFFFFFFFF @crc32c_table (for byte <- 0..255 do Enum.reduce(1..8, byte, fn _bit, crc -> if (crc &&& 1) == 1 do bxor(crc >>> 1, @crc32c_poly) else crc >>> 1 end end) end) |> List.to_tuple() @compile {:inline, crc32c: 1, crc32c_loop: 2} @doc """ Calculates the CRC32C of the binary. """ @spec crc32c(binary()) :: non_neg_integer() def crc32c(data) when is_binary(data) do crc32c_loop(data, @uint32_mask) end defp crc32c_loop(<<>>, crc), do: bxor(crc, @uint32_mask) defp crc32c_loop(<>, crc) do table_index = bxor(crc, byte) &&& 0xFF crc32c_loop(rest, bxor(elem(@crc32c_table, table_index), crc >>> 8)) end end