royalcat refactoring
This commit is contained in:
parent
1da835cea6
commit
b245c9f451
81 changed files with 1476 additions and 1580 deletions
64
src/iio/disk.go
Normal file
64
src/iio/disk.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package iio
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type DiskTeeReader struct {
|
||||
io.ReaderAt
|
||||
io.Closer
|
||||
io.Reader
|
||||
|
||||
m sync.Mutex
|
||||
|
||||
fo int64
|
||||
fr *os.File
|
||||
to int64
|
||||
tr io.Reader
|
||||
}
|
||||
|
||||
func NewDiskTeeReader(r io.Reader) (Reader, error) {
|
||||
fr, err := os.CreateTemp("", "dtb_tmp")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tr := io.TeeReader(r, fr)
|
||||
return &DiskTeeReader{fr: fr, tr: tr}, nil
|
||||
}
|
||||
|
||||
func (dtr *DiskTeeReader) ReadAt(p []byte, off int64) (int, error) {
|
||||
dtr.m.Lock()
|
||||
defer dtr.m.Unlock()
|
||||
tb := off + int64(len(p))
|
||||
|
||||
if tb > dtr.fo {
|
||||
w, err := io.CopyN(io.Discard, dtr.tr, tb-dtr.fo)
|
||||
dtr.to += w
|
||||
if err != nil && err != io.EOF {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
n, err := dtr.fr.ReadAt(p, off)
|
||||
dtr.fo += int64(n)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (dtr *DiskTeeReader) Read(p []byte) (n int, err error) {
|
||||
dtr.m.Lock()
|
||||
defer dtr.m.Unlock()
|
||||
// use directly tee reader here
|
||||
n, err = dtr.tr.Read(p)
|
||||
dtr.to += int64(n)
|
||||
return
|
||||
}
|
||||
|
||||
func (dtr *DiskTeeReader) Close() error {
|
||||
if err := dtr.fr.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.Remove(dtr.fr.Name())
|
||||
}
|
50
src/iio/disk_test.go
Normal file
50
src/iio/disk_test.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package iio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var testData []byte = []byte("Hello World")
|
||||
|
||||
func TestReadData(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require := require.New(t)
|
||||
|
||||
br := bytes.NewReader(testData)
|
||||
r, err := NewDiskTeeReader(br)
|
||||
require.NoError(err)
|
||||
|
||||
toRead := make([]byte, 5)
|
||||
|
||||
n, err := r.ReadAt(toRead, 6)
|
||||
require.NoError(err)
|
||||
require.Equal(5, n)
|
||||
require.Equal("World", string(toRead))
|
||||
|
||||
r.ReadAt(toRead, 0)
|
||||
require.NoError(err)
|
||||
require.Equal(5, n)
|
||||
require.Equal("Hello", string(toRead))
|
||||
}
|
||||
|
||||
func TestReadDataEOF(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require := require.New(t)
|
||||
|
||||
br := bytes.NewReader(testData)
|
||||
r, err := NewDiskTeeReader(br)
|
||||
require.NoError(err)
|
||||
|
||||
toRead := make([]byte, 6)
|
||||
|
||||
n, err := r.ReadAt(toRead, 6)
|
||||
require.Equal(io.EOF, err)
|
||||
require.Equal(5, n)
|
||||
require.Equal("World\x00", string(toRead))
|
||||
}
|
14
src/iio/reader.go
Normal file
14
src/iio/reader.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package iio
|
||||
|
||||
import "io"
|
||||
|
||||
type Reader interface {
|
||||
io.ReaderAt
|
||||
io.Closer
|
||||
io.Reader
|
||||
}
|
||||
|
||||
type ReaderSeeker interface {
|
||||
Reader
|
||||
io.Seeker
|
||||
}
|
45
src/iio/wrapper.go
Normal file
45
src/iio/wrapper.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package iio
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type seekerWrapper struct {
|
||||
mu sync.Mutex
|
||||
pos int64
|
||||
size int64
|
||||
|
||||
io.Seeker
|
||||
Reader
|
||||
}
|
||||
|
||||
func NewSeekerWrapper(r Reader, size int64) *seekerWrapper {
|
||||
return &seekerWrapper{Reader: r}
|
||||
}
|
||||
|
||||
func (r *seekerWrapper) Seek(offset int64, whence int) (int64, error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
switch whence {
|
||||
case io.SeekStart:
|
||||
r.pos = offset
|
||||
case io.SeekCurrent:
|
||||
r.pos = r.pos + offset
|
||||
case io.SeekEnd:
|
||||
r.pos = r.size + offset
|
||||
}
|
||||
|
||||
return r.pos, nil
|
||||
}
|
||||
|
||||
func (r *seekerWrapper) Read(p []byte) (int, error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
n, err := r.ReadAt(p, r.pos)
|
||||
r.pos += int64(n)
|
||||
|
||||
return n, err
|
||||
}
|
33
src/iio/wrapper_test.go
Normal file
33
src/iio/wrapper_test.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package iio_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"git.kmsign.ru/royalcat/tstor/src/fs"
|
||||
"git.kmsign.ru/royalcat/tstor/src/iio"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var testData []byte = []byte("Hello World")
|
||||
|
||||
func TestSeekerWrapper(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require := require.New(t)
|
||||
|
||||
mf := fs.NewMemoryFile(testData)
|
||||
|
||||
r := iio.NewSeekerWrapper(mf, mf.Size())
|
||||
defer r.Close()
|
||||
|
||||
n, err := r.Seek(6, io.SeekStart)
|
||||
require.NoError(err)
|
||||
require.Equal(int64(6), n)
|
||||
|
||||
toRead := make([]byte, 5)
|
||||
nn, err := r.Read(toRead)
|
||||
require.NoError(err)
|
||||
require.Equal(5, nn)
|
||||
require.Equal("World", string(toRead))
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue