src/client/pkg/grpcutil/stream.go
func ChunkReader(r io.Reader, f func([]byte) error) (int, error) {
	var total int
	buf := GetBuffer()
	defer PutBuffer(buf)
	for {
		n, err := r.Read(buf)
		if n == 0 && err != nil {
			if err == io.EOF {
				return total, nil
			}
			return total, err
		}
		if err := f(buf[:n]); err != nil {
			return total, err
		}
		total += n
	}
}
func ChunkReader(r io.Reader, f func([]byte) error) (int, error) {
	var total int
	buf := GetBuffer()
	defer PutBuffer(buf)
	for {
		n, err := r.Read(buf)
		if n == 0 && err != nil {
			if err == io.EOF {
				return total, nil
			}
			return total, err
		}
		if err := f(buf[:n]); err != nil {
			return total, err
		}
		total += n
	}
}
// ChunkReader splits a reader into reasonably sized chunks for the purpose
// of transmitting the chunks over gRPC. For each chunk, it calls the given
// function.