zlibcut

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 19, 2019 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package zlibcut produces zlib-formatted data subject to a maximum compressed size.

The typical compression problem is to encode all of the given source data in some number of bytes. This package's problem is finding a reasonably long prefix of the source data that encodes in up to a given number of bytes.

Index

Examples

Constants

View Source
const (
	// SmallestValidMaxEncodedLen is the length in bytes of the smallest valid
	// zlib-encoded data.
	SmallestValidMaxEncodedLen = 8
)

Variables

This section is empty.

Functions

func Cut

func Cut(w io.Writer, encoded []byte, maxEncodedLen int) (encodedLen int, decodedLen int, retErr error)

Cut modifies encoded's contents such that encoded[:encodedLen] is valid zlib-compressed data, assuming that encoded starts off containing valid zlib-compressed data.

If a nil error is returned, then encodedLen <= maxEncodedLen will hold.

Decompressing that modified, shorter byte slice produces a prefix (of length decodedLen) of the decompression of the original, longer byte slice.

If w is non-nil, that prefix is also written to w. If a non-nil error is returned, incomplete data might still be written to w.

It does not necessarily return the largest possible decodedLen.

Example
package main

import (
	"bytes"
	"compress/zlib"
	"fmt"
	"io/ioutil"
	"log"
	"strings"

	"github.com/google/wuffs/lib/zlibcut"
)

func main() {
	const sonnet18 = "" +
		"Shall I compare thee to a summer’s day?\n" +
		"Thou art more lovely and more temperate.\n" +
		"Rough winds do shake the darling buds of May,\n" +
		"And summer’s lease hath all too short a date.\n" +
		"Sometime too hot the eye of heaven shines,\n" +
		"And often is his gold complexion dimmed;\n" +
		"And every fair from fair sometime declines,\n" +
		"By chance, or nature’s changing course, untrimmed;\n" +
		"But thy eternal summer shall not fade,\n" +
		"Nor lose possession of that fair thou ow’st,\n" +
		"Nor shall death brag thou wand'rest in his shade,\n" +
		"When in eternal lines to Time thou grow'st.\n" +
		"So long as men can breathe, or eyes can see,\n" +
		"So long lives this, and this gives life to thee.\n"

	if n := len(sonnet18); n != 632 {
		log.Fatalf("len(sonnet18): got %d, want 632", n)
	}

	// Compress the input text, sonnet18.
	buffer := &bytes.Buffer{}
	w := zlib.NewWriter(buffer)
	w.Write([]byte(sonnet18))
	w.Close()
	compressed := buffer.Bytes()

	// The exact length of the zlib-compressed form of sonnet18 depends on the
	// compression algorithm used, which can change from version to version of
	// the Go standard library. Nonetheless, for a 632 byte input, we expect
	// the compressed form to be between 300 and 500 bytes.
	if n := len(compressed); (n < 300) || (500 < n) {
		log.Fatalf("len(compressed): got %d, want something in [300, 500]", n)
	}

	// Cut the 300-or-more bytes to be 200.
	encodedLen, decodedLen, err := zlibcut.Cut(nil, compressed, 200)
	if err != nil {
		log.Fatalf("Cut: %v", err)
	}

	// The encodedLen should be equal to or just under the requested 200.
	cut := compressed[:encodedLen]
	if n := len(cut); (n < 190) || (200 < n) {
		log.Fatalf("len(cut): got %d, want something in [190, 200]", n)
	}

	// At this point, a real program would write that cut slice somewhere. The
	// rest of this example verifies that the cut data has the properties we
	// expect, given the semantics of zlibcut.Cut.

	// Uncompress the cut data. It should be a valid zlib-compressed stream, so
	// no errors should be encountered.
	r, err := zlib.NewReader(bytes.NewReader(cut))
	if err != nil {
		log.Fatalf("NewReader: %v", err)
	}
	uncompressed, err := ioutil.ReadAll(r)
	if err != nil {
		log.Fatalf("ReadAll: %v", err)
	}
	err = r.Close()
	if err != nil {
		log.Fatalf("Close: %v", err)
	}

	// The uncompressed form of the cut data should be a prefix (of length
	// decodedLen) of the original input, sonnet18. Again, the exact length
	// depends on the zlib compression algorithm, but uncompressing 200 or so
	// bytes should give between 250 and 400 bytes.
	if n := len(uncompressed); n != decodedLen {
		log.Fatalf("len(uncompressed): got %d, want %d", n, decodedLen)
	} else if (n < 250) || (400 < n) {
		log.Fatalf("len(uncompressed): got %d, want something in [250, 400]", n)
	} else if !strings.HasPrefix(sonnet18, string(uncompressed)) {
		log.Fatalf("uncompressed was not a prefix of the original input")
	}

	// The first two lines of the sonnet take 83 bytes.
	fmt.Println(string(uncompressed[:83]))
}
Output:

Shall I compare thee to a summer’s day?
Thou art more lovely and more temperate.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL