github.com/hoffie/larasync@v0.0.0-20151025221940-0384d2bddcef/repository/chunker/chunker.go (about)

     1  package chunker
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  )
     7  
     8  // Chunker returns the contents of the given file path in chunkSize-sized
     9  // chunks.
    10  type Chunker struct {
    11  	file      *os.File
    12  	finished  bool
    13  	chunkSize uint64
    14  }
    15  
    16  // New returns a new chunker instance for the given file path
    17  // and the given chunk size.
    18  func New(path string, chunkSize uint64) (*Chunker, error) {
    19  	file, err := os.Open(path)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  
    24  	if chunkSize < 16 {
    25  		return nil, ErrBadChunkSize
    26  	}
    27  
    28  	c := &Chunker{
    29  		file:      file,
    30  		finished:  false,
    31  		chunkSize: chunkSize,
    32  	}
    33  	return c, nil
    34  }
    35  
    36  // HasNext returns true if an upcoming Next() call is expected
    37  // to return more data.
    38  func (c *Chunker) HasNext() bool {
    39  	return !c.finished
    40  }
    41  
    42  // Next returns the next part of the file, with at most chunkSize bytes.
    43  func (c *Chunker) Next() ([]byte, error) {
    44  	buf := make([]byte, c.chunkSize)
    45  	numBytes, err := c.file.Read(buf)
    46  	if uint64(numBytes) < c.chunkSize || err != nil {
    47  		c.finished = true
    48  	}
    49  	if err != nil || numBytes == 0 {
    50  		c.file.Close()
    51  	}
    52  	if err != nil && err != io.EOF {
    53  		return nil, err
    54  	}
    55  	return buf[:numBytes], nil
    56  }
    57  
    58  // Close cleans up the chunker after usage.
    59  //
    60  // Use the c := NewChunker(); defer c.Close() pattern
    61  func (c *Chunker) Close() {
    62  	c.file.Close()
    63  }