aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/aws/smithy-go/io/ringbuffer.go
blob: 06b476add8a230ee1e4113c868247a1adda29e3a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package io

import (
	"bytes"
	"io"
)

// RingBuffer struct satisfies io.ReadWrite interface.
//
// ReadBuffer is a revolving buffer data structure, which can be used to store snapshots of data in a
// revolving window.
type RingBuffer struct {
	slice []byte
	start int
	end   int
	size  int
}

// NewRingBuffer method takes in a byte slice as an input and returns a RingBuffer.
func NewRingBuffer(slice []byte) *RingBuffer {
	ringBuf := RingBuffer{
		slice: slice,
	}
	return &ringBuf
}

// Write method inserts the elements in a byte slice, and returns the number of bytes written along with any error.
func (r *RingBuffer) Write(p []byte) (int, error) {
	for _, b := range p {
		// check if end points to invalid index, we need to circle back
		if r.end == len(r.slice) {
			r.end = 0
		}
		// check if start points to invalid index, we need to circle back
		if r.start == len(r.slice) {
			r.start = 0
		}
		// if ring buffer is filled, increment the start index
		if r.size == len(r.slice) {
			r.size--
			r.start++
		}

		r.slice[r.end] = b
		r.end++
		r.size++
	}
	return len(p), nil
}

// Read copies the data on the ring buffer into the byte slice provided to the method.
// Returns the read count along with any error encountered while reading.
func (r *RingBuffer) Read(p []byte) (int, error) {
	// readCount keeps track of the number of bytes read
	var readCount int
	for j := 0; j < len(p); j++ {
		// if ring buffer is empty or completely read
		// return EOF error.
		if r.size == 0 {
			return readCount, io.EOF
		}

		if r.start == len(r.slice) {
			r.start = 0
		}

		p[j] = r.slice[r.start]
		readCount++
		// increment the start pointer for ring buffer
		r.start++
		// decrement the size of ring buffer
		r.size--
	}
	return readCount, nil
}

// Len returns the number of unread bytes in the buffer.
func (r *RingBuffer) Len() int {
	return r.size
}

// Bytes returns a copy of the RingBuffer's bytes.
func (r RingBuffer) Bytes() []byte {
	var b bytes.Buffer
	io.Copy(&b, &r)
	return b.Bytes()
}

// Reset resets the ring buffer.
func (r *RingBuffer) Reset() {
	*r = RingBuffer{
		slice: r.slice,
	}
}