1 package io
2 3 import (
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.
12 type 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.
20 func 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.
28 func (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.
53 func (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.
78 func (r *RingBuffer) Len() int {
79 return r.size
80 }
81 82 // Bytes returns a copy of the RingBuffer's bytes.
83 func (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.
90 func (r *RingBuffer) Reset() {
91 *r = RingBuffer{
92 slice: r.slice,
93 }
94 }
95