func CompressFile(source, destination string) error {
	cIface, err := ByExtension(destination)
	if err != nil {
		return err
	}
	c, ok := cIface.(Compressor)
	if !ok {
		return fmt.Errorf("format specified by destination filename is not a recognized compression algorithm: %s", destination)
	}
	return FileCompressor{Compressor: c}.CompressFile(source, destination)
}
CompressFile is a convenience function to simply compress a file.
The compression algorithm is selected implicitly based on the
destination's extension.
package archiver
import (
	"fmt"
	"io"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
)
type Archiver interface {
	ExtensionChecker
	Archive(sources []string, destination string) error
}
type ExtensionChecker interface {
	CheckExt(name string) error
}
type Unarchiver interface {
	Unarchive(source, destination string) error
}
type Writer interface {
	Create(out io.Writer) error
	Write(f File) error
	Close() error
}
type Reader interface {
	Open(in io.Reader, size int64) error
	Read() (File, error)
	Close() error
}
type Extractor interface {
	Extract(source, target, destination string) error
}
type File struct {
	os.FileInfo
	Header interface{}
	io.ReadCloser
}
type FileInfo struct {
	os.FileInfo
	CustomName string
}
func (fi FileInfo) Name() string {
	if fi.CustomName != "" {
		return fi.CustomName
	}
	return fi.FileInfo.Name()
}
type ReadFakeCloser struct {
	io.Reader
}
func (rfc ReadFakeCloser) Close() error { return nil }
type Walker interface {
	Walk(archive string, walkFn WalkFunc) error
}
type WalkFunc func(f File) error
var ErrStopWalk = fmt.Errorf("walk stopped")
type Compressor interface {
	ExtensionChecker
	Compress(in io.Reader, out io.Writer) error
}
type Decompressor interface {
	Decompress(in io.Reader, out io.Writer) error
}
type Matcher interface {
	Match(io.ReadSeeker) (bool, error)
}
func Archive(sources []string, destination string) error {
	aIface, err := ByExtension(destination)
	if err != nil {
		return err
	}
	a, ok := aIface.(Archiver)
	if !ok {
		return fmt.Errorf("format specified by destination filename is not an archive format: %s (%T)", destination, aIface)
	}
	return a.Archive(sources, destination)
}
func Unarchive(source, destination string) error {
	uaIface, err := ByExtension(source)
	if err != nil {
		return err
	}
	u, ok := uaIface.(Unarchiver)
	if !ok {
		return fmt.Errorf("format specified by source filename is not an archive format: %s (%T)", source, uaIface)
	}
	return u.Unarchive(source, destination)
}
func Walk(archive string, walkFn WalkFunc) error {
	wIface, err := ByExtension(archive)
	if err != nil {
		return err
	}
	w, ok := wIface.(Walker)
	if !ok {
		return fmt.Errorf("format specified by archive filename is not a walker format: %s (%T)", archive, wIface)
	}
	return w.Walk(archive, walkFn)
}
func Extract(source, target, destination string) error {
	eIface, err := ByExtension(source)
	if err != nil {
		return err
	}
	e, ok := eIface.(Extractor)
	if !ok {
		return fmt.Errorf("format specified by source filename is not an extractor format: %s (%T)", source, eIface)
	}
	return e.Extract(source, target, destination)
}