// compressedChunkGreaterN like compressedChunk produces a single, compressed, // snappy-framed block. The returned block will have decoded length at most n // and encoded length greater than n. func compressedChunkGreaterN(t *testing.T, n int) []byte { decoded := make([]byte, n) var numTries int var encoded []byte for len(encoded) <= n && numTries < 3 { numTries++ nrd, err := io.ReadFull(rand.Reader, decoded) if err != nil { t.Errorf("crypto/rand: %v", err) return nil } if nrd != n { t.Errorf("crypto/rand: bad read (%d bytes)", nrd) return nil } encoded, err = snappy.Encode(encoded[:cap(encoded)], decoded) if err != nil { t.Errorf("snappy: %v", err) return nil } } if len(encoded) <= n { t.Error(errNotEnoughEntropy) return nil } return compressedChunk(t, decoded) }
// write attempts to encode p as a block and write it to the underlying writer. // The returned int may not equal p's length if compression below // MaxBlockSize-4 could not be achieved. func (w *writer) write(p []byte) (int, error) { var err error if len(p) > MaxBlockSize { return 0, errors.New(fmt.Sprintf("block too large %d > %d", len(p), MaxBlockSize)) } w.dst = w.dst[:cap(w.dst)] // Encode does dumb resize w/o context. reslice avoids alloc. w.dst, err = snappy.Encode(w.dst, p) if err != nil { return 0, err } block := w.dst n := len(p) compressed := true // check for data which is better left uncompressed. this is determined if // the encoded content is longer than the source. if len(w.dst) >= len(p) { compressed = false block = p[:n] } if !w.sentStreamID { _, err := w.writer.Write(streamID) if err != nil { return 0, err } w.sentStreamID = true } // set the block type if compressed { writeHeader(w.hdr, blockCompressed, block, p[:n]) } else { writeHeader(w.hdr, blockUncompressed, block, p[:n]) } _, err = w.writer.Write(w.hdr) if err != nil { return 0, err } _, err = w.writer.Write(block) if err != nil { return 0, err } return n, nil }
// compressedChunk encodes b returning a single, compressed, snappy-framed // block. compressedChunk can encode source data larger than allowed in the // specification. func compressedChunk(t *testing.T, src []byte) []byte { encoded, err := snappy.Encode(nil, src) if err != nil { t.Errorf("snappy: %v", err) return nil } if len(encoded) > (1<<24)-5 { // account for the 4-byte checksum t.Errorf("block data too large %d", len(src)) return nil } chunk := make([]byte, len(encoded)+8) writeHeader(chunk[:8], blockCompressed, encoded, src) copy(chunk[8:], encoded) return chunk }