From 14db71d3fa43194c7d14ad7c199704fe296aacef Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Sun, 31 Jul 2016 10:29:53 +0200 Subject: [PATCH] Move RandReader to repository package --- src/restic/repository/rand_reader.go | 79 ++++++++++++++++++++++++++++ src/restic/testing.go | 73 +------------------------ 2 files changed, 80 insertions(+), 72 deletions(-) create mode 100644 src/restic/repository/rand_reader.go diff --git a/src/restic/repository/rand_reader.go b/src/restic/repository/rand_reader.go new file mode 100644 index 000000000..201826a94 --- /dev/null +++ b/src/restic/repository/rand_reader.go @@ -0,0 +1,79 @@ +package repository + +import ( + "io" + "math/rand" +) + +// RandReader allows reading from a rand.Rand. +type RandReader struct { + rnd *rand.Rand + buf []byte +} + +// NewRandReader creates a new Reader from a random source. +func NewRandReader(rnd *rand.Rand) io.Reader { + return &RandReader{rnd: rnd, buf: make([]byte, 0, 7)} +} + +func (rd *RandReader) read(p []byte) (n int, err error) { + if len(p)%7 != 0 { + panic("invalid buffer length, not multiple of 7") + } + + rnd := rd.rnd + for i := 0; i < len(p); i += 7 { + val := rnd.Int63() + + p[i+0] = byte(val >> 0) + p[i+1] = byte(val >> 8) + p[i+2] = byte(val >> 16) + p[i+3] = byte(val >> 24) + p[i+4] = byte(val >> 32) + p[i+5] = byte(val >> 40) + p[i+6] = byte(val >> 48) + } + + return len(p), nil +} + +func (rd *RandReader) Read(p []byte) (int, error) { + // first, copy buffer to p + pos := copy(p, rd.buf) + copy(rd.buf, rd.buf[pos:]) + + // shorten buf and p accordingly + rd.buf = rd.buf[:len(rd.buf)-pos] + p = p[pos:] + + // if this is enough to fill p, return + if len(p) == 0 { + return pos, nil + } + + // load multiple of 7 byte + l := (len(p) / 7) * 7 + n, err := rd.read(p[:l]) + pos += n + if err != nil { + return pos, err + } + p = p[n:] + + // load 7 byte to temp buffer + rd.buf = rd.buf[:7] + n, err = rd.read(rd.buf) + if err != nil { + return pos, err + } + + // copy the remaining bytes from the buffer to p + n = copy(p, rd.buf) + pos += n + + // save the remaining bytes in rd.buf + n = copy(rd.buf, rd.buf[n:]) + rd.buf = rd.buf[:n] + + return pos, nil +} diff --git a/src/restic/testing.go b/src/restic/testing.go index fa2ab649d..c0f1a0f72 100644 --- a/src/restic/testing.go +++ b/src/restic/testing.go @@ -13,80 +13,9 @@ import ( "github.com/restic/chunker" ) -type randReader struct { - rnd *rand.Rand - buf []byte -} - -func newRandReader(rnd *rand.Rand) io.Reader { - return &randReader{rnd: rnd, buf: make([]byte, 0, 7)} -} - -func (rd *randReader) read(p []byte) (n int, err error) { - if len(p)%7 != 0 { - panic("invalid buffer length, not multiple of 7") - } - - rnd := rd.rnd - for i := 0; i < len(p); i += 7 { - val := rnd.Int63() - - p[i+0] = byte(val >> 0) - p[i+1] = byte(val >> 8) - p[i+2] = byte(val >> 16) - p[i+3] = byte(val >> 24) - p[i+4] = byte(val >> 32) - p[i+5] = byte(val >> 40) - p[i+6] = byte(val >> 48) - } - - return len(p), nil -} - -func (rd *randReader) Read(p []byte) (int, error) { - // first, copy buffer to p - pos := copy(p, rd.buf) - copy(rd.buf, rd.buf[pos:]) - - // shorten buf and p accordingly - rd.buf = rd.buf[:len(rd.buf)-pos] - p = p[pos:] - - // if this is enough to fill p, return - if len(p) == 0 { - return pos, nil - } - - // load multiple of 7 byte - l := (len(p) / 7) * 7 - n, err := rd.read(p[:l]) - pos += n - if err != nil { - return pos, err - } - p = p[n:] - - // load 7 byte to temp buffer - rd.buf = rd.buf[:7] - n, err = rd.read(rd.buf) - if err != nil { - return pos, err - } - - // copy the remaining bytes from the buffer to p - n = copy(p, rd.buf) - pos += n - - // save the remaining bytes in rd.buf - n = copy(rd.buf, rd.buf[n:]) - rd.buf = rd.buf[:n] - - return pos, nil -} - // fakeFile returns a reader which yields deterministic pseudo-random data. func fakeFile(t testing.TB, seed, size int64) io.Reader { - return io.LimitReader(newRandReader(rand.New(rand.NewSource(seed))), size) + return io.LimitReader(repository.NewRandReader(rand.New(rand.NewSource(seed))), size) } // saveFile reads from rd and saves the blobs in the repository. The list of