package metainfo
 
 import (
-       "crypto/sha1"
        "errors"
        "fmt"
        "io"
 
 // Sets Pieces (the block of piece hashes in the Info) by using the passed
 // function to get at the torrent data.
-func (info *Info) GeneratePieces(open func(fi FileInfo) (io.ReadCloser, error)) error {
+func (info *Info) GeneratePieces(open func(fi FileInfo) (io.ReadCloser, error)) (err error) {
        if info.PieceLength == 0 {
                return errors.New("piece length must be non-zero")
        }
                pw.CloseWithError(err)
        }()
        defer pr.Close()
-       var pieces []byte
-       for {
-               hasher := sha1.New()
-               wn, err := io.CopyN(hasher, pr, info.PieceLength)
-               if err == io.EOF {
-                       err = nil
-               }
-               if err != nil {
-                       return err
-               }
-               if wn == 0 {
-                       break
-               }
-               pieces = hasher.Sum(pieces)
-               if wn < info.PieceLength {
-                       break
-               }
-       }
-       info.Pieces = pieces
-       return nil
+       info.Pieces, err = GeneratePieces(pr, info.PieceLength, nil)
+       return
 }
 
 func (info *Info) TotalLength() (ret int64) {
 
--- /dev/null
+package metainfo
+
+import (
+       "crypto/sha1"
+       "io"
+)
+
+func GeneratePieces(r io.Reader, pieceLength int64, b []byte) ([]byte, error) {
+       for {
+               h := sha1.New()
+               written, err := io.CopyN(h, r, pieceLength)
+               if written > 0 {
+                       b = h.Sum(b)
+               }
+               if err == io.EOF {
+                       return b, nil
+               }
+               if err != nil {
+                       return b, err
+               }
+       }
+}