mirror of
https://github.com/siderolabs/talos.git
synced 2025-08-18 12:37:05 +02:00
Most of the fixes were automatically applied. Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
105 lines
1.8 KiB
Go
105 lines
1.8 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package circular
|
|
|
|
import (
|
|
"io"
|
|
"sync/atomic"
|
|
)
|
|
|
|
// Reader implements seekable reader with local position in the Buffer which
|
|
// reads from the fixed part of the buffer.
|
|
//
|
|
// Reader is not safe to be used with concurrent Read/Seek operations.
|
|
type Reader struct {
|
|
buf *Buffer
|
|
|
|
startOff, endOff int64
|
|
off int64
|
|
|
|
closed uint32
|
|
}
|
|
|
|
// Read implements io.Reader.
|
|
func (r *Reader) Read(p []byte) (n int, err error) {
|
|
if atomic.LoadUint32(&r.closed) > 0 {
|
|
err = ErrClosed
|
|
|
|
return
|
|
}
|
|
|
|
r.buf.mu.Lock()
|
|
defer r.buf.mu.Unlock()
|
|
|
|
if r.off < r.buf.off-int64(r.buf.opt.MaxCapacity) {
|
|
// reader is falling too much behind
|
|
err = ErrOutOfSync
|
|
|
|
return
|
|
}
|
|
|
|
if r.off == r.endOff {
|
|
err = io.EOF
|
|
|
|
return
|
|
}
|
|
|
|
if len(p) == 0 {
|
|
return
|
|
}
|
|
|
|
n = int(r.endOff - r.off)
|
|
if n > len(p) {
|
|
n = len(p)
|
|
}
|
|
|
|
i := int(r.off % int64(r.buf.opt.MaxCapacity))
|
|
l := r.buf.opt.MaxCapacity - i
|
|
|
|
if l < n {
|
|
copy(p, r.buf.data[i:])
|
|
copy(p[l:], r.buf.data[:n-l])
|
|
} else {
|
|
copy(p, r.buf.data[i:i+n])
|
|
}
|
|
|
|
r.off += int64(n)
|
|
|
|
return n, err
|
|
}
|
|
|
|
// Close implements io.Closer.
|
|
func (r *Reader) Close() error {
|
|
atomic.StoreUint32(&r.closed, 1)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Seek implements io.Seeker.
|
|
func (r *Reader) Seek(offset int64, whence int) (int64, error) {
|
|
newOff := r.off
|
|
|
|
switch whence {
|
|
case io.SeekCurrent:
|
|
newOff += offset
|
|
case io.SeekEnd:
|
|
newOff = r.endOff + offset
|
|
case io.SeekStart:
|
|
newOff = r.startOff + offset
|
|
}
|
|
|
|
if newOff < r.startOff {
|
|
return r.off - r.startOff, ErrSeekBeforeStart
|
|
}
|
|
|
|
if newOff > r.endOff {
|
|
newOff = r.endOff
|
|
}
|
|
|
|
r.off = newOff
|
|
|
|
return r.off - r.startOff, nil
|
|
}
|