ringbuffer.go

 1package io
 2
 3import (
 4	"bytes"
 5	"io"
 6)
 7
 8// RingBuffer struct satisfies io.ReadWrite interface.
 9//
10// ReadBuffer is a revolving buffer data structure, which can be used to store snapshots of data in a
11// revolving window.
12type RingBuffer struct {
13	slice []byte
14	start int
15	end   int
16	size  int
17}
18
19// NewRingBuffer method takes in a byte slice as an input and returns a RingBuffer.
20func NewRingBuffer(slice []byte) *RingBuffer {
21	ringBuf := RingBuffer{
22		slice: slice,
23	}
24	return &ringBuf
25}
26
27// Write method inserts the elements in a byte slice, and returns the number of bytes written along with any error.
28func (r *RingBuffer) Write(p []byte) (int, error) {
29	for _, b := range p {
30		// check if end points to invalid index, we need to circle back
31		if r.end == len(r.slice) {
32			r.end = 0
33		}
34		// check if start points to invalid index, we need to circle back
35		if r.start == len(r.slice) {
36			r.start = 0
37		}
38		// if ring buffer is filled, increment the start index
39		if r.size == len(r.slice) {
40			r.size--
41			r.start++
42		}
43
44		r.slice[r.end] = b
45		r.end++
46		r.size++
47	}
48	return len(p), nil
49}
50
51// Read copies the data on the ring buffer into the byte slice provided to the method.
52// Returns the read count along with any error encountered while reading.
53func (r *RingBuffer) Read(p []byte) (int, error) {
54	// readCount keeps track of the number of bytes read
55	var readCount int
56	for j := 0; j < len(p); j++ {
57		// if ring buffer is empty or completely read
58		// return EOF error.
59		if r.size == 0 {
60			return readCount, io.EOF
61		}
62
63		if r.start == len(r.slice) {
64			r.start = 0
65		}
66
67		p[j] = r.slice[r.start]
68		readCount++
69		// increment the start pointer for ring buffer
70		r.start++
71		// decrement the size of ring buffer
72		r.size--
73	}
74	return readCount, nil
75}
76
77// Len returns the number of unread bytes in the buffer.
78func (r *RingBuffer) Len() int {
79	return r.size
80}
81
82// Bytes returns a copy of the RingBuffer's bytes.
83func (r RingBuffer) Bytes() []byte {
84	var b bytes.Buffer
85	io.Copy(&b, &r)
86	return b.Bytes()
87}
88
89// Reset resets the ring buffer.
90func (r *RingBuffer) Reset() {
91	*r = RingBuffer{
92		slice: r.slice,
93	}
94}