diff --git a/lib/circular_buffer.ex b/lib/circular_buffer.ex index e2a6ec3..152602f 100644 --- a/lib/circular_buffer.ex +++ b/lib/circular_buffer.ex @@ -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() } @@ -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 @@ -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. diff --git a/test/circular_buffer_test.exs b/test/circular_buffer_test.exs index 4fb3871..9f01299 100644 --- a/test/circular_buffer_test.exs +++ b/test/circular_buffer_test.exs @@ -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 @@ -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 @@ -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