2020-06-08 03:29:51 +03:00
|
|
|
package progressreadseeker
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
2021-09-20 18:05:24 +03:00
|
|
|
type ProgressFn func(approxReadBytes int64, totalSize int64)
|
|
|
|
|
2021-09-27 12:01:14 +03:00
|
|
|
type ProgressReaderSeeker struct {
|
2020-06-08 03:29:51 +03:00
|
|
|
rs io.ReadSeeker
|
|
|
|
pos int64
|
2021-09-20 18:05:24 +03:00
|
|
|
totalSize int64
|
2020-06-08 03:29:51 +03:00
|
|
|
partitionSize int64
|
|
|
|
partitions []bool
|
|
|
|
partitionsReadCount int64
|
2021-09-20 18:05:24 +03:00
|
|
|
progressFn ProgressFn
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-09-27 12:01:14 +03:00
|
|
|
func New(rs io.ReadSeeker, precision int64, totalSize int64, fn ProgressFn) *ProgressReaderSeeker {
|
2021-09-20 18:05:24 +03:00
|
|
|
partitionSize := totalSize / precision
|
|
|
|
if totalSize%precision != 0 {
|
2020-06-08 03:29:51 +03:00
|
|
|
partitionSize++
|
|
|
|
}
|
2021-09-27 12:01:14 +03:00
|
|
|
return &ProgressReaderSeeker{
|
2020-06-08 03:29:51 +03:00
|
|
|
rs: rs,
|
2021-09-20 18:05:24 +03:00
|
|
|
totalSize: totalSize,
|
2020-06-08 03:29:51 +03:00
|
|
|
partitionSize: partitionSize,
|
|
|
|
partitions: make([]bool, precision),
|
|
|
|
progressFn: fn,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-27 12:01:14 +03:00
|
|
|
func (prs *ProgressReaderSeeker) Read(p []byte) (n int, err error) {
|
2020-06-08 03:29:51 +03:00
|
|
|
n, err = prs.rs.Read(p)
|
|
|
|
newPos := prs.pos + int64(n)
|
|
|
|
lastPartitionsReadCount := prs.partitionsReadCount
|
|
|
|
|
|
|
|
partStart := prs.pos / prs.partitionSize
|
|
|
|
partEnd := newPos / prs.partitionSize
|
|
|
|
|
|
|
|
for i := partStart; i < partEnd; i++ {
|
|
|
|
if prs.partitions[i] {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
prs.partitions[i] = true
|
|
|
|
prs.partitionsReadCount++
|
|
|
|
}
|
|
|
|
|
|
|
|
if lastPartitionsReadCount != prs.partitionsReadCount {
|
|
|
|
readBytes := prs.partitionSize * prs.partitionsReadCount
|
2021-09-20 18:05:24 +03:00
|
|
|
if readBytes > prs.totalSize {
|
|
|
|
readBytes = prs.totalSize
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
2021-09-20 18:05:24 +03:00
|
|
|
prs.progressFn(readBytes, prs.totalSize)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
prs.pos = newPos
|
|
|
|
|
|
|
|
return n, err
|
|
|
|
}
|
|
|
|
|
2021-09-27 12:01:14 +03:00
|
|
|
func (prs *ProgressReaderSeeker) Seek(offset int64, whence int) (int64, error) {
|
2020-06-08 03:29:51 +03:00
|
|
|
pos, err := prs.rs.Seek(offset, whence)
|
|
|
|
prs.pos = pos
|
|
|
|
return pos, err
|
|
|
|
}
|