Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions lib/circular_buffer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ defmodule CircularBuffer do
@opaque t() :: %__MODULE__{
a: list(),
b: list(),
max_size: pos_integer(),
max_size: non_neg_integer(),
count: non_neg_integer()
}

Expand All @@ -43,8 +43,8 @@ defmodule CircularBuffer do
@doc """
Creates a new circular buffer with a given size.
"""
@spec new(pos_integer()) :: t()
def new(size) when is_integer(size) and size > 0 do
@spec new(non_neg_integer()) :: t()
def new(size) when is_integer(size) and size >= 0 do
%CB{a: [], b: [], max_size: size, count: 0}
end

Expand All @@ -60,11 +60,14 @@ defmodule CircularBuffer do
%{cb | a: [item | cb.a], count: cb.count + 1}
end

def insert(%CB{b: []} = cb, item) do
new_b = cb.a |> Enum.reverse() |> tl()
def insert(%CB{a: a, b: []} = cb, item) when a != [] do
new_b = a |> Enum.reverse() |> tl()
%{cb | a: [item], b: new_b}
end

# max_size==0 case
def insert(cb, _item), do: cb

@doc """
Converts a circular buffer to a list. The list is ordered from oldest to newest
elements based on their insertion order.
Expand Down
14 changes: 7 additions & 7 deletions test/circular_buffer_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ defmodule CircularBufferTest do

alias CircularBuffer, as: CB

property "new/1 returns an empty buffer for positive sizes" do
forall size <- pos_integer() do
property "new/1 returns an empty buffer for non-negative sizes" do
forall size <- non_neg_integer() do
cb = CB.new(size)

cb.max_size == size and
Expand All @@ -23,10 +23,10 @@ defmodule CircularBufferTest do
end
end

property "new/1 raises for non-positive sizes" do
forall n <- non_neg_integer() do
property "new/1 raises for negative sizes" do
forall n <- neg_integer() do
try do
CB.new(-n)
CB.new(n)
false
rescue
FunctionClauseError -> true
Expand All @@ -39,14 +39,14 @@ defmodule CircularBufferTest do
end

property "the count matches the number of elements in the buffer" do
forall {size, is} <- {pos_integer(), list(integer())} do
forall {size, is} <- {non_neg_integer(), list(integer())} do
buffer = Enum.reduce(is, CB.new(size), fn i, cb -> CB.insert(cb, i) end)
slow_cb_count(buffer) == buffer.count
end
end

property "can tell the current number of elements" do
forall {size, is} <- {pos_integer(), list(integer())} do
forall {size, is} <- {non_neg_integer(), list(integer())} do
buffer = Enum.reduce(is, CB.new(size), fn i, cb -> CB.insert(cb, i) end)
Enum.count(buffer) == min(size, length(is))
end
Expand Down