teldrive/internal/reader/tg_reader.go
2024-06-29 15:07:54 +05:30

97 lines
1.6 KiB
Go

package reader
import (
"context"
"io"
)
type tgReader struct {
ctx context.Context
cur *buffer
offset int64
limit int64
chunkSize int64
leftCut int64
rightCut int64
totalParts int
currentPart int
chunkSrc ChunkSource
err error
}
func newTGReader(
ctx context.Context,
start int64,
end int64,
chunkSrc ChunkSource,
) (io.ReadCloser, error) {
chunkSize := chunkSrc.ChunkSize(start, end)
offset := start - (start % chunkSize)
r := &tgReader{
ctx: ctx,
leftCut: start - offset,
rightCut: (end % chunkSize) + 1,
totalParts: int((end - offset + chunkSize) / chunkSize),
offset: offset,
limit: end - start + 1,
chunkSize: chunkSize,
chunkSrc: chunkSrc,
currentPart: 1,
}
return r, nil
}
func (r *tgReader) Read(p []byte) (int, error) {
if r.limit <= 0 {
return 0, io.EOF
}
if r.cur.isEmpty() {
r.cur, r.err = r.next()
if r.err != nil {
return 0, r.err
}
}
n := copy(p, r.cur.buffer())
r.cur.increment(n)
r.limit -= int64(n)
if r.limit <= 0 {
return n, io.EOF
}
return n, nil
}
func (*tgReader) Close() error {
return nil
}
func (r *tgReader) next() (*buffer, error) {
if r.currentPart > r.totalParts {
return nil, io.EOF
}
chunk, err := r.chunkSrc.Chunk(r.ctx, r.offset, r.chunkSize)
if err != nil {
return nil, err
}
if r.totalParts == 1 {
chunk = chunk[r.leftCut:r.rightCut]
} else if r.currentPart == 1 {
chunk = chunk[r.leftCut:]
} else if r.currentPart == r.totalParts {
chunk = chunk[:r.rightCut]
}
r.currentPart++
r.offset += r.chunkSize
return &buffer{buf: chunk}, nil
}