1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-12-23 22:11:10 +02:00
Files
imgproxy/bufreader/bufreader.go

92 lines
1.9 KiB
Go
Raw Permalink Normal View History

2021-04-26 17:52:50 +06:00
package bufreader
2021-03-22 22:26:57 +06:00
import (
"errors"
2021-03-22 22:26:57 +06:00
"io"
"github.com/imgproxy/imgproxy/v3/ioutil"
2021-03-22 22:26:57 +06:00
)
// ReadPeeker is an interface that combines io.Reader and a method to peek at the next n bytes
type ReadPeeker interface {
io.Reader
Peek(n int) ([]byte, error) // Peek returns the next n bytes without advancing
}
// Reader is a buffered reader that reads from an io.Reader and caches the data.
2021-04-26 17:52:50 +06:00
type Reader struct {
2021-03-22 22:26:57 +06:00
r io.Reader
buf []byte
pos int
finished bool // Indicates if the reader has reached EOF
2021-03-22 22:26:57 +06:00
}
// New creates new buffered reader
func New(r io.Reader) *Reader {
2021-04-26 17:52:50 +06:00
br := Reader{
2021-03-22 22:26:57 +06:00
r: r,
buf: nil,
2021-03-22 22:26:57 +06:00
}
return &br
}
// Read reads data into p from the buffered reader.
2021-04-26 17:52:50 +06:00
func (br *Reader) Read(p []byte) (int, error) {
if err := br.fetch(br.pos + len(p)); err != nil {
2021-03-22 22:26:57 +06:00
return 0, err
}
if br.pos >= len(br.buf) {
return 0, io.EOF // No more data to read
}
n := copy(p, br.buf[br.pos:])
br.pos += n
2021-03-22 22:26:57 +06:00
return n, nil
}
// Peek returns the next n bytes from the buffered reader without advancing the position.
2021-04-26 17:52:50 +06:00
func (br *Reader) Peek(n int) ([]byte, error) {
if err := br.fetch(br.pos + n); err != nil {
return nil, err
2021-03-22 22:26:57 +06:00
}
if br.pos >= len(br.buf) {
return nil, io.EOF // No more data to read
2021-03-22 22:26:57 +06:00
}
// Return slice of buffered data without advancing position
available := br.buf[br.pos:]
return available[:min(len(available), n)], nil
2021-03-22 22:26:57 +06:00
}
// Rewind seeks buffer to the beginning
func (br *Reader) Rewind() {
br.pos = 0
2021-03-22 22:26:57 +06:00
}
// fetch ensures the buffer contains at least 'need' bytes
func (br *Reader) fetch(need int) error {
if br.finished || need <= len(br.buf) {
2021-03-22 22:26:57 +06:00
return nil
}
b := make([]byte, need-len(br.buf))
n, err := ioutil.TryReadFull(br.r, b)
2021-03-22 22:26:57 +06:00
if errors.Is(err, io.EOF) {
// If we reached EOF, we mark the reader as finished
br.finished = true
} else if err != nil {
return err
}
if n > 0 {
// append only those which we read in fact
br.buf = append(br.buf, b[:n]...)
}
2021-03-22 22:26:57 +06:00
return nil
}