limage - internal/bufioToReader.go
1 package internal // import "vimagination.zapto.org/limage/internal"
2
3 import (
4 "bufio"
5 "io"
6 "sync"
7 "unsafe"
8 )
9
10 // copied from bufio
11 type bufioReader struct {
12 buf []byte
13 rd io.Reader
14 r, w int
15 err error
16 lastByte int
17 lastRuneSize int
18 }
19
20 type readerAt struct {
21 readMutex sync.Mutex
22 ReadSeeker io.ReadSeeker
23 pos int64
24 }
25
26 func (r *readerAt) ReadAt(p []byte, offset int64) (int, error) {
27 r.readMutex.Lock()
28 var (
29 n int
30 err error
31 )
32 if offset != r.pos {
33 r.pos, err = r.ReadSeeker.Seek(offset, io.SeekStart)
34 if err != nil {
35 return 0, err
36 }
37 }
38 n, err = r.ReadSeeker.Read(p)
39 r.pos += int64(n)
40 r.readMutex.Unlock()
41 return n, err
42 }
43
44 func bufioToReader(b *bufio.Reader) io.ReaderAt {
45 br := (*bufioReader)(unsafe.Pointer(b))
46 if ra, ok := br.rd.(io.ReaderAt); ok {
47 return ra
48 } else if rs, ok := br.rd.(io.ReadSeeker); ok {
49 rs.Seek(0, 0)
50 return &readerAt{
51 ReadSeeker: rs,
52 }
53 }
54 return nil
55 }
56
57 // GetReaderAt tries to make a io.ReaderAt from an io.Reader
58 func GetReaderAt(r io.Reader) io.ReaderAt {
59 if bb, ok := r.(*bufio.Reader); ok {
60 return bufioToReader(bb)
61 } else if ra, ok := r.(io.ReaderAt); ok {
62 return ra
63 } else if rs, ok := r.(io.ReadSeeker); ok {
64 return &readerAt{ReadSeeker: rs}
65 }
66 return nil
67 }
68