ringbuffer.go raw

   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