@@ -9,17 +9,21 @@ defmodule CircularBuffer do
99 ```
1010 """
1111
12+ defstruct [ :q , :max_size , :count ]
13+
14+ alias __MODULE__ , as: CB
15+
1216 @ doc """
1317 Creates a new circular buffer with a given size.
1418 """
1519 def new ( size ) when is_integer ( size ) and size > 0 do
16- % { q: :queue . new ( ) , max_size: size , count: 0 }
20+ % CB { q: :queue . new ( ) , max_size: size , count: 0 }
1721 end
1822
1923 @ doc """
2024 Inserts a new item into the next location of the circular buffer
2125 """
22- def insert ( cb , item ) do
26+ def insert ( % CB { } = cb , item ) do
2327 if cb . count < cb . max_size do
2428 % { cb | q: :queue . cons ( item , cb . q ) , count: cb . count + 1 }
2529 else
@@ -28,15 +32,15 @@ defmodule CircularBuffer do
2832 |> :queue . drop_r
2933 |> ( fn q -> :queue . cons ( item , q ) end ) . ( )
3034
31- % { cb | q: new_q }
35+ % CB { cb | q: new_q }
3236 end
3337 end
3438
3539 @ doc """
3640 Converts a circular buffer to a list. The list is ordered from oldest to newest
3741 elements based on their insertion order.
3842 """
39- def to_list ( cb ) do
43+ def to_list ( % CB { } = cb ) do
4044 cb . q
4145 |> :queue . reverse
4246 |> :queue . to_list
@@ -45,7 +49,7 @@ defmodule CircularBuffer do
4549 @ doc """
4650 Returns the newest element in the buffer
4751 """
48- def newest ( cb ) do
52+ def newest ( % CB { } = cb ) do
4953 case :queue . peek ( cb . q ) do
5054 { _ , val } -> val
5155 :empty -> nil
@@ -55,10 +59,55 @@ defmodule CircularBuffer do
5559 @ doc """
5660 Returns the oldest element in the buffer
5761 """
58- def oldest ( cb ) do
62+ def oldest ( % CB { } = cb ) do
5963 case :queue . peek_r ( cb . q ) do
6064 { _ , val } -> val
6165 :empty -> nil
6266 end
6367 end
68+
69+ @ doc """
70+ Checks the buffer to see if its empty
71+ """
72+ def empty? ( % CB { } = cb ) do
73+ :queue . is_empty ( cb . q )
74+ end
75+
76+ defimpl Enumerable do
77+ def count ( cb ) do
78+ { :ok , cb . count }
79+ end
80+
81+ def member? ( cb , element ) do
82+ { :ok , :queue . member ( element , cb . q ) }
83+ end
84+
85+ def reduce ( cb , acc , fun ) do
86+ Enumerable.List . reduce ( CB . to_list ( cb ) , acc , fun )
87+ end
88+
89+ def slice ( cb ) do
90+ { :ok , cb . count , & Enumerable.List . slice ( CB . to_list ( cb ) , & 1 , & 2 ) }
91+ end
92+ end
93+
94+ defimpl Collectable do
95+ def into ( original ) do
96+ collector_fn = fn
97+ cb , { :cont , elem } -> CB . insert ( cb , elem )
98+ cb , :done -> cb
99+ _cb , :halt -> :ok
100+ end
101+
102+ { original , collector_fn }
103+ end
104+ end
105+
106+ defimpl Inspect do
107+ import Inspect.Algebra
108+
109+ def inspect ( cb , opts ) do
110+ concat ( [ "#CircularBuffer<" , to_doc ( CB . to_list ( cb ) , opts ) , ">" ] )
111+ end
112+ end
64113end
0 commit comments