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
2




3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18














































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


+
+
+
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
// Package ioutil contains various constructs for io operations
package ioutil

import (
	"io"
)

// An function alias type that implements io.Writer
type WriterFunc func([]byte) (int, error)

// Delegates the call to the WriterFunc while implementing io.Writer
func (w WriterFunc) Write(b []byte) (int, error) {
	return w(b)
}

// An function alias type that implements io.Reader
type ReaderFunc func([]byte) (int, error)

// Delegates the call to the WriterFunc while implementing io.Reader
func (r ReaderFunc) Read(b []byte) (int, error) {
	return r(b)
}

// Returns a reader that will delegate calls to Read(...) while ensuring
// that the output buffer will never be smaller than the required size
func MinReader(reader io.Reader, size int) io.Reader {
	var buffer []byte = make([]byte, 0, size)

	return ReaderFunc(func(output []byte) (readCount int, e error) {
		var (
			bufferLength int = len(buffer)
			err          error
		)

	start:
		// Reply with the buffered data if there is any
		if bufferLength > 0 {
			readCount = copy(output, buffer)

			if readCount < bufferLength {
				// Advance the data in the buffer
				buffer = buffer[:copy(buffer, buffer[:readCount])]
			} else {
				// Clear the buffer
				buffer = buffer[:0]
			}

			// Stage any error for returning
			e, err = err, nil

			return readCount, e
		}

		// Delegate if the buffer is empty and the destination buffer is large enough
		if len(output) >= size {
			return reader.Read(output)
		}

		// Extend the buffer up to the desired size and perform a Read
		buffer = buffer[:size]
		readCount, err = reader.Read(buffer)

		// Size the buffer down to the read data size and restart
		buffer = buffer[:readCount]
		bufferLength = len(buffer)
		goto start
	})
}

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

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
13





+







package ioutil

import (
	diff "0dev.org/diff"
	"bytes"
	"io"
	"testing"
)

func TestWriter(t *testing.T) {
	var (
		input  []byte = []byte{0, 1, 2, 3, 4, 5, 6, 7}
		output []byte
41
42
43
44
45
46
47














































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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
	// Diff the result against the initial input
	delta := diff.Diff(diff.D{len(input), len(output),
		func(i, j int) bool { return input[i] == output[j] }})
	if len(delta.Added) > 0 || len(delta.Removed) > 0 {
		t.Error("Differences detected ", delta)
	}
}

func TestMinReader(t *testing.T) {
	var (
		input  []byte = []byte{0, 1, 2, 3, 4, 5, 6, 7}
		output []byte = make([]byte, 16)

		reader *bytes.Reader = bytes.NewReader(input)
		min    io.Reader     = MinReader(reader, 4)
	)

	// Expecting a read count of 2
	count, err := min.Read(output[:2])
	if count != 2 {
		t.Error("Invalid read count from MinReader", count)
	}
	if err != nil {
		t.Error("Unexpected error from MinReader", err)
	}

	// Expecting a read count of 2 as it should have 2 bytes in its buffer
	count, err = min.Read(output[:3])
	if count != 2 {
		t.Error("Invalid read count from MinReader", count)
	}
	if err != nil {
		t.Error("Unexpected error from MinReader", err)
	}

	// Expecting a read count of 4 as the buffer should be empty
	count, err = min.Read(output[:4])
	if count != 4 {
		t.Error("Invalid read count from MinReader", count)
	}
	if err != nil {
		t.Error("Unexpected error from MinReader", err)
	}

	// Expecting a read count of 0 with an EOF as the buffer should be empty
	count, err = min.Read(output[:4])
	if count != 0 {
		t.Error("Invalid read count from MinReader", count)
	}
	if err != io.EOF {
		t.Error("Unexpected error from MinReader", err)
	}
}