docs: function roll(data, checksums, blockSize) {
    var results = [];
    var hashtable = createHashtable(checksums);
    var length = data.length;
    var start = 0;
    var end = blockSize > length ? length : blockSize;
    // Updated when a block matches
    var lastMatchedEnd = 0;
    // This gets updated every iteration with the previous weak 32bit hash
    var prevRollingWeak = null;
    var weak;
    var weak16;
    var match;
    var d;
    var len;
    var mightMatch;
    var chunk;
    var strong;
    var hashtable_weak16;
    var hashtable_weak16i;
  
    for (; end <= length; start++, end++) {
      weak = calcWeak32(data, prevRollingWeak, start, end);
      weak16 = calcWeak16(weak.sum);
      match = false;
      d = null;
      prevRollingWeak = weak;
      hashtable_weak16 = hashtable[weak16];
  
      if (hashtable_weak16) {
        len = hashtable_weak16.length;
        for (var i = 0; i < len; i++) {
          hashtable_weak16i = hashtable_weak16[i];
          if (hashtable_weak16i.weak === weak.sum) {
            mightMatch = hashtable_weak16i;
            chunk = data.slice(start, end);
            strong = md5sum(chunk);
  
            if (mightMatch.strong === strong) {
              match = mightMatch;
              break;
            }
          }
        }
      }
      if (match) {
        if(start < lastMatchedEnd) {
          d = data.slice(lastMatchedEnd - 1, end);
          results.push({
            data: d,
            index: match.index
          });
        } else if (start - lastMatchedEnd > 0) {
          d = data.slice(lastMatchedEnd, start);
          results.push({
            data: d,
            index: match.index
          });
        } else {
          results.push({
            index: match.index
          });
        }
        lastMatchedEnd = end;
      } else if (end === length) {
        // No match and last block
        d = data.slice(lastMatchedEnd);
        results.push({
          data: d
        });
      }
    }
    return results;
  }