func (r *Reader) readRawBlock(bh blockHandle, checksum bool) ([]byte, error) { data := r.bpool.Get(int(bh.length + blockTrailerLen)) if _, err := r.reader.ReadAt(data, int64(bh.offset)); err != nil && err != io.EOF { return nil, err } if checksum || r.checksum { if !verifyChecksum(data) { return nil, errors.New("leveldb/table: Reader: invalid block (checksum mismatch)") } } switch data[bh.length] { case blockTypeNoCompression: data = data[:bh.length] case blockTypeSnappyCompression: decLen, err := snappy.DecodedLen(data[:bh.length]) if err != nil { return nil, err } tmp := data data, err = snappy.Decode(r.bpool.Get(decLen), tmp[:bh.length]) r.bpool.Put(tmp) if err != nil { return nil, err } default: return nil, fmt.Errorf("leveldb/table: Reader: unknown block compression type: %d", data[bh.length]) } return data, nil }
// decodeDataBlock assumes r.hdr[0] to be either blockCompressed or // blockUncompressed. func (r *reader) decodeBlock() error { // read compressed block data and determine if uncompressed data is too // large. buf, err := r.readBlock() if err != nil { return err } declen := len(buf[4:]) if r.hdr[0] == blockCompressed { declen, err = snappy.DecodedLen(buf[4:]) if err != nil { return err } } if declen > MaxBlockSize { return fmt.Errorf("decoded block data too large %d > %d", declen, MaxBlockSize) } // decode data and verify its integrity using the little-endian crc32 // preceding encoded data crc32le, blockdata := buf[:4], buf[4:] if r.hdr[0] == blockCompressed { r.dst, err = snappy.Decode(r.dst, blockdata) if err != nil { return err } blockdata = r.dst } if r.verifyChecksum { checksum := unmaskChecksum(uint32(crc32le[0]) | uint32(crc32le[1])<<8 | uint32(crc32le[2])<<16 | uint32(crc32le[3])<<24) actualChecksum := crc32.Checksum(blockdata, crcTable) if checksum != actualChecksum { return fmt.Errorf("checksum does not match %x != %x", checksum, actualChecksum) } } _, err = r.buf.Write(blockdata) return err }