~samwhited/xmpp

cd1167e62efefe945af8a2f1fc97c076b118e8b8 — Sam Whited 3 years ago 6f0b2ee
compress: Add support for LZW stream compression

Also tweak some comments to make later diffs smaller.

Fixes #15
2 files changed, 39 insertions(+), 10 deletions(-)

M compress/compression.go
M compress/methods.go
M compress/compression.go => compress/compression.go +5 -3
@@ 2,7 2,8 @@
// Use of this source code is governed by the BSD 2-clause license that can be
// found in the LICENSE file.

// Package compress implements stream compression as specified in XEP-0138.
// Package compress implements XEP-0138: Stream Compression and XEP-0229: Stream
// Compression with LZW.
package compress

import (


@@ 27,8 28,9 @@ var (
)

// New returns a new xmpp.StreamFeature that can be used to negotiate stream
// compression. The returned stream feature always supports ZLIB compression;
// other compression methods are optional.
// compression.
// The returned stream feature always supports ZLIB compression; other
// compression methods are optional.
func New(methods ...Method) xmpp.StreamFeature {
	// TODO: Throw them into a map to dedup and then iterate over that?
	methods = append(methods, zlibMethod)

M compress/methods.go => compress/methods.go +34 -7
@@ 5,15 5,41 @@
package compress

import (
	"compress/lzw"
	"compress/zlib"
	"io"
	"sync"
)

// Method is a stream compression method. Custom methods may be defined, but
// generally speaking the only supported methods will be those with names
// defined in the "Stream Compression Methods Registry" maintained by the XSF
// Editor: https://xmpp.org/registrar/compress.html
var (
	// LZW implements stream compression using the Lempel-Ziv-Welch (DCLZ)
	// compressed data format.
	LZW Method = lzwMethod
)

var lzwMethod = Method{
	Name: "lzw",
	Wrapper: func(rw io.ReadWriter) (io.ReadWriter, error) {
		rc := lzw.NewReader(rw, lzw.LSB, 8)
		wc := lzw.NewWriter(rw, lzw.LSB, 8)
		return struct {
			io.Reader
			io.Writer
			io.Closer
		}{
			Reader: rc,
			Writer: wc,
			Closer: &multiCloser{rc, wc},
		}, nil
	},
}

// Method is a stream compression method.
// Custom methods may be defined, but generally speaking the only supported
// methods will be those with names defined in the "Stream Compression Methods
// Registry" maintained by the XSF Editor:
// https://xmpp.org/registrar/compress.html
// Since ZLIB is always supported, a Method is not defined for it.
type Method struct {
	Name    string
	Wrapper func(io.ReadWriter) (io.ReadWriter, error)


@@ 21,9 47,10 @@ type Method struct {

type multiCloser []io.Closer

// Close attempts to call every close method in the multiCloser. It always
// attempts all of them (unless one of them panics), but it only returns the
// last error if multiple of them error. There's probably a better way.
// Close attempts to call every close method in the multiCloser.
// It always attempts all of them (unless one of them panics), but it only
// returns the last error if multiple of them error.
// There's probably a better way.
func (mc multiCloser) Close() (err error) {
	var e error
	for _, c := range mc {