Check-in [47b221d5b4]
Overview
Comment:Added MinReader to ioutils, CC at 100%
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 47b221d5b405e27881cf8846370ca5025aade422
User & Date: spaskalev on 2014-12-23 10:38:30
Other Links: manifest | tags
Context
2014-12-23
14:27
minReader fixes check-in: 4195e7817d user: spaskalev tags: trunk
10:38
Added MinReader to ioutils, CC at 100% check-in: 47b221d5b4 user: spaskalev tags: trunk
09:32
Removed the compressor alias type from predictor, use ioutil.WriterFunc check-in: c62581c2a6 user: spaskalev tags: trunk
Changes

Modified src/0dev.org/ioutil/ioutil.go from [404db9969d] to [edab0c9e76].

     1      1   // Package ioutil contains various constructs for io operations
     2      2   package ioutil
            3  +
            4  +import (
            5  +	"io"
            6  +)
     3      7   
     4      8   // An function alias type that implements io.Writer
     5      9   type WriterFunc func([]byte) (int, error)
     6     10   
     7     11   // Delegates the call to the WriterFunc while implementing io.Writer
     8     12   func (w WriterFunc) Write(b []byte) (int, error) {
     9     13   	return w(b)
................................................................................
    12     16   // An function alias type that implements io.Reader
    13     17   type ReaderFunc func([]byte) (int, error)
    14     18   
    15     19   // Delegates the call to the WriterFunc while implementing io.Reader
    16     20   func (r ReaderFunc) Read(b []byte) (int, error) {
    17     21   	return r(b)
    18     22   }
           23  +
           24  +// Returns a reader that will delegate calls to Read(...) while ensuring
           25  +// that the output buffer will never be smaller than the required size
           26  +func MinReader(reader io.Reader, size int) io.Reader {
           27  +	var buffer []byte = make([]byte, 0, size)
           28  +
           29  +	return ReaderFunc(func(output []byte) (readCount int, e error) {
           30  +		var (
           31  +			bufferLength int = len(buffer)
           32  +			err          error
           33  +		)
           34  +
           35  +	start:
           36  +		// Reply with the buffered data if there is any
           37  +		if bufferLength > 0 {
           38  +			readCount = copy(output, buffer)
           39  +
           40  +			if readCount < bufferLength {
           41  +				// Advance the data in the buffer
           42  +				buffer = buffer[:copy(buffer, buffer[:readCount])]
           43  +			} else {
           44  +				// Clear the buffer
           45  +				buffer = buffer[:0]
           46  +			}
           47  +
           48  +			// Stage any error for returning
           49  +			e, err = err, nil
           50  +
           51  +			return readCount, e
           52  +		}
           53  +
           54  +		// Delegate if the buffer is empty and the destination buffer is large enough
           55  +		if len(output) >= size {
           56  +			return reader.Read(output)
           57  +		}
           58  +
           59  +		// Extend the buffer up to the desired size and perform a Read
           60  +		buffer = buffer[:size]
           61  +		readCount, err = reader.Read(buffer)
           62  +
           63  +		// Size the buffer down to the read data size and restart
           64  +		buffer = buffer[:readCount]
           65  +		bufferLength = len(buffer)
           66  +		goto start
           67  +	})
           68  +}

Modified src/0dev.org/ioutil/ioutil_test.go from [e21bc31120] to [8530a31260].

     1      1   package ioutil
     2      2   
     3      3   import (
     4      4   	diff "0dev.org/diff"
     5      5   	"bytes"
            6  +	"io"
     6      7   	"testing"
     7      8   )
     8      9   
     9     10   func TestWriter(t *testing.T) {
    10     11   	var (
    11     12   		input  []byte = []byte{0, 1, 2, 3, 4, 5, 6, 7}
    12     13   		output []byte
................................................................................
    41     42   	// Diff the result against the initial input
    42     43   	delta := diff.Diff(diff.D{len(input), len(output),
    43     44   		func(i, j int) bool { return input[i] == output[j] }})
    44     45   	if len(delta.Added) > 0 || len(delta.Removed) > 0 {
    45     46   		t.Error("Differences detected ", delta)
    46     47   	}
    47     48   }
           49  +
           50  +func TestMinReader(t *testing.T) {
           51  +	var (
           52  +		input  []byte = []byte{0, 1, 2, 3, 4, 5, 6, 7}
           53  +		output []byte = make([]byte, 16)
           54  +
           55  +		reader *bytes.Reader = bytes.NewReader(input)
           56  +		min    io.Reader     = MinReader(reader, 4)
           57  +	)
           58  +
           59  +	// Expecting a read count of 2
           60  +	count, err := min.Read(output[:2])
           61  +	if count != 2 {
           62  +		t.Error("Invalid read count from MinReader", count)
           63  +	}
           64  +	if err != nil {
           65  +		t.Error("Unexpected error from MinReader", err)
           66  +	}
           67  +
           68  +	// Expecting a read count of 2 as it should have 2 bytes in its buffer
           69  +	count, err = min.Read(output[:3])
           70  +	if count != 2 {
           71  +		t.Error("Invalid read count from MinReader", count)
           72  +	}
           73  +	if err != nil {
           74  +		t.Error("Unexpected error from MinReader", err)
           75  +	}
           76  +
           77  +	// Expecting a read count of 4 as the buffer should be empty
           78  +	count, err = min.Read(output[:4])
           79  +	if count != 4 {
           80  +		t.Error("Invalid read count from MinReader", count)
           81  +	}
           82  +	if err != nil {
           83  +		t.Error("Unexpected error from MinReader", err)
           84  +	}
           85  +
           86  +	// Expecting a read count of 0 with an EOF as the buffer should be empty
           87  +	count, err = min.Read(output[:4])
           88  +	if count != 0 {
           89  +		t.Error("Invalid read count from MinReader", count)
           90  +	}
           91  +	if err != io.EOF {
           92  +		t.Error("Unexpected error from MinReader", err)
           93  +	}
           94  +}