File: progressreaderseeker.go

package info (click to toggle)
fq 0.9.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 106,624 kB
  • sloc: xml: 2,835; makefile: 250; sh: 241; exp: 57; ansic: 21
file content (70 lines) | stat: -rw-r--r-- 1,525 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package progressreadseeker

import (
	"io"
)

type ProgressFn func(approxReadBytes int64, totalSize int64)

type Reader struct {
	rs                  io.ReadSeeker
	pos                 int64
	totalSize           int64
	partitionSize       int64
	partitions          []bool
	partitionsReadCount int64
	progressFn          ProgressFn
}

func New(rs io.ReadSeeker, precision int64, totalSize int64, fn ProgressFn) *Reader {
	partitionSize := totalSize / precision
	if totalSize%precision != 0 {
		partitionSize++
	}
	return &Reader{
		rs:            rs,
		totalSize:     totalSize,
		partitionSize: partitionSize,
		partitions:    make([]bool, precision),
		progressFn:    fn,
	}
}

func (prs *Reader) Read(p []byte) (n int, err error) {
	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
		if readBytes > prs.totalSize {
			readBytes = prs.totalSize
		}
		prs.progressFn(readBytes, prs.totalSize)
	}

	prs.pos = newPos

	return n, err
}

func (prs *Reader) Seek(offset int64, whence int) (int64, error) {
	pos, err := prs.rs.Seek(offset, whence)
	prs.pos = pos
	return pos, err
}

func (prs *Reader) Unwrap() any {
	return prs.rs
}