Files
OpenList/pkg/buffer/utils.go
Ovear 7e9082f90e fix(stream): allow seeking beyond file size per Go convention (#2667)
Remove `offset > size` guard from RangeReadReadAtSeeker.Seek and
DynamicReadAtSeeker.Seek. Go's io.Seeker convention allows seeking
past EOF.

Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-07 22:53:49 +08:00

94 lines
1.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package buffer
import (
"errors"
"io"
)
func WriteAtSeekerOf(b Block) WriteAtSeeker {
if p, ok := b.(WriteAtSeekerProvider); ok {
return p.GetWriteAtSeeker()
}
return io.NewOffsetWriter(b, 0)
}
// 将一个Block包装为ReadAtSeeker。
// 固定大小当前Block的Size()。
func ReadAtSeekerOf(b Block) ReadAtSeeker {
if p, ok := b.(ReadAtSeekerProvider); ok {
return p.GetReadAtSeeker()
}
return io.NewSectionReader(b, 0, b.Size())
}
type blockAdapter struct {
WriteAtSeeker
SizedReadAtSeeker
}
func (b *blockAdapter) GetWriteAtSeeker() WriteAtSeeker {
return b.WriteAtSeeker
}
func (b *blockAdapter) GetReadAtSeeker() ReadAtSeeker {
return b.SizedReadAtSeeker
}
func NewBlockAdapter(w WriteAtSeeker, r SizedReadAtSeeker) Block {
return &blockAdapter{
WriteAtSeeker: w,
SizedReadAtSeeker: r,
}
}
var _ Block = (*blockAdapter)(nil)
// 将一个Block包装为ReadAtSeeker。
// 动态大小Size() 是动态跟随底层 Block。
type DynamicReadAtSeeker struct {
block Block
offset int64
}
func (r *DynamicReadAtSeeker) ReadAt(p []byte, off int64) (n int, err error) {
return r.block.ReadAt(p, off)
}
func (r *DynamicReadAtSeeker) Read(p []byte) (n int, err error) {
n, err = r.block.ReadAt(p, r.offset)
if n > 0 {
r.offset += int64(n)
}
return n, err
}
func (r *DynamicReadAtSeeker) Size() int64 {
return r.block.Size()
}
func (r *DynamicReadAtSeeker) Seek(offset int64, whence int) (int64, error) {
switch whence {
case io.SeekStart:
case io.SeekCurrent:
if offset == 0 {
return r.offset, nil
}
offset = r.offset + offset
case io.SeekEnd:
offset = r.block.Size() + offset
default:
return 0, errors.New("Seek: invalid whence")
}
if offset < 0 {
return 0, errors.New("Seek: invalid offset")
}
r.offset = offset
return offset, nil
}
func NewDynamicReadAtSeeker(block Block) *DynamicReadAtSeeker {
return &DynamicReadAtSeeker{
block: block,
}
}