Skip to content

Commit

Permalink
Pull byte operations into its own module
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesduncombe committed Oct 28, 2020
1 parent e11cf42 commit 638ae48
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 33 deletions.
15 changes: 15 additions & 0 deletions lib/petal/bitfield.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,28 @@ defmodule Petal.Bitfield do
Bitfield is the core structure about the Bloom filter.
"""

import Petal.Bytes, only: [generate_n_bytes: 1, byte_size_of_field: 1]

@typedoc "Defines the core type"
@type t :: %__MODULE__{
bitfield: binary(),
size: pos_integer()
}

defstruct bitfield: <<>>, size: 64

@doc """
Creates a new Bitfield.
"""
@spec new(size :: pos_integer()) :: t()
def new(size) do
bitfield =
size
|> byte_size_of_field()
|> generate_n_bytes()

%__MODULE__{bitfield: bitfield, size: size}
end
end

defimpl String.Chars, for: Petal.Bitfield do
Expand Down
44 changes: 44 additions & 0 deletions lib/petal/bytes.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
defmodule Petal.Bytes do
@moduledoc """
Collection of functions for working with byte arrays.
"""

@doc """
Return the size in bytes from bits.
"""
@spec byte_size_of_field(size :: pos_integer()) :: pos_integer()
def byte_size_of_field(size), do: div(size, 8)

@doc """
Pad the `encoded` payload to `n` bytes.
"""
@spec pad_encoded_payload(n :: pos_integer(), encoded :: binary()) :: binary()
def pad_encoded_payload(0, encoded), do: encoded

def pad_encoded_payload(n, encoded) do
padder = generate_n_bytes(n)
padder <> encoded
end

@doc """
Generate a binary that is `n` bytes long.
"""
@spec generate_n_bytes(n :: pos_integer()) :: binary()
def generate_n_bytes(n) do
for _n <- 1..n, into: <<>>, do: <<0>>
end

@doc """
Check for the existance of the set bit from `offset` in `bitfield`.
"""
@spec exists?(offset :: pos_integer(), bitfield :: binary()) :: true | false
def exists?(offset, bitfield) do
case bitfield do
<<_head::bitstring-size(offset), 1::1, _rest::bitstring>> ->
true

_ ->
false
end
end
end
36 changes: 3 additions & 33 deletions lib/petal/worker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ defmodule Petal.Worker do

require Logger

import Petal.Bytes

alias Petal.Bitfield

@hashers Application.fetch_env!(:petal, :hashers)
Expand Down Expand Up @@ -50,13 +52,7 @@ defmodule Petal.Worker do
def init(args) do
# Init the bitfield
size_of_field = Keyword.get(args, :size, 64)

bitfield =
size_of_field
|> byte_size_of_field()
|> generate_n_bytes()

state = %Bitfield{bitfield: bitfield, size: size_of_field}
state = Bitfield.new(size_of_field)

{:ok, state}
end
Expand Down Expand Up @@ -110,33 +106,7 @@ defmodule Petal.Worker do

# Helpers

defp byte_size_of_field(size), do: div(size, 8)

# Pad the encoded payload
defp pad_encoded_payload(0, encoded), do: encoded

defp pad_encoded_payload(n, encoded) do
padder = generate_n_bytes(n)
padder <> encoded
end

defp generate_n_bytes(n) do
for _n <- 1..n, into: <<>>, do: <<0>>
end

# Simply map from true|false to a decent return term
defp format_return(true), do: :ok
defp format_return(_false), do: {:error, "Not found"}

# Check for the existance of the set bit from `offset` in `bitfield`
@spec exists?(offset :: pos_integer(), bitfield :: binary()) :: true | false
defp exists?(offset, bitfield) do
case bitfield do
<<_head::bitstring-size(offset), 1::1, _rest::bitstring>> ->
true

_ ->
false
end
end
end

0 comments on commit 638ae48

Please sign in to comment.