ringbuffer.go (2124B)
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 }