func (f *DirEntry) Info() (fs.FileInfo, error) {
	return f.TagSlice, nil
}
Info returns the FileInfo for the file or subdirectory described by the entry.
package wpk
import (
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"io/fs"
	"math"
	"path/filepath"
	"strings"
	"time"
)
const (
	Signature = "Whirlwind 3.3 Package   "  
	Prebuild  = "Whirlwind 3.3 Prebuild  "  
)
type (
	TID uint16
	FID uint32
	OFFSET uint64
	SIZE uint64
)
const (
	TIDfid        TID = 0  
	TIDoffset     TID = 1  
	TIDsize       TID = 2  
	TIDpath       TID = 3  
	TIDcreated    TID = 4  
	TIDlastwrite  TID = 5  
	TIDlastaccess TID = 6  
	TIDchange     TID = 7  
	TIDfileattr   TID = 8  
	TIDsys TID = 10  
	TIDcrc32ieee TID = 10  
	TIDcrc32c    TID = 11  
	TIDcrc32k    TID = 12  
	TIDcrc64iso  TID = 14  
	TIDmd5    TID = 20  
	TIDsha1   TID = 21  
	TIDsha224 TID = 22  
	TIDsha256 TID = 23  
	TIDsha384 TID = 24  
	TIDsha512 TID = 25  
	TIDmime     TID = 100  
	TIDlink     TID = 101  
	TIDkeywords TID = 102  
	TIDcategory TID = 103  
	TIDversion  TID = 104  
	TIDauthor   TID = 105  
	TIDcomment  TID = 106  
)
type ErrTag struct {
	What error   
	Key  string  
	TID  TID     
}
func (e *ErrTag) Error() string {
	return fmt.Sprintf("key '%s', tag ID %d: %s", e.Key, e.TID, e.What)
}
func (e *ErrTag) Unwrap() error {
	return e.What
}
var (
	ErrSignPre = errors.New("package is not ready")
	ErrSignBad = errors.New("signature does not pass")
	ErrNoTag    = errors.New("tag with given ID not found")
	ErrNoPath   = errors.New("file name is absent")
	ErrNoFID    = errors.New("file ID is absent")
	ErrNoOffset = errors.New("file offset is absent")
	ErrOutOff   = errors.New("file offset is out of bounds")
	ErrNoSize   = errors.New("file size is absent")
	ErrOutSize  = errors.New("file size is out of bounds")
)
type FileReader interface {
	io.Reader
	io.ReaderAt
	io.Seeker
	Size() int64
}
type NestedFile interface {
	fs.File
	FileReader
}
type NFTOMap map[string]OFFSET
type Tagger interface {
	NFTO() NFTOMap
	NamedTags(string) (TagSlice, bool)
}
type Packager interface {
	DataSize() int64
	Tagger
	OpenTags(TagSlice) (NestedFile, error)
	io.Closer
	fs.SubFS
	fs.StatFS
	fs.GlobFS
	fs.ReadFileFS
	fs.ReadDirFS
}
const (
	HeaderSize = 64
	SignSize = 0x18
	LabelSize = 0x18
)
type Header struct {
	signature [SignSize]byte
	disklabel [LabelSize]byte
	fttoffset OFFSET  
	fttsize   SIZE    
}
func (pack *Header) Label() string {
	var i int
	for ; i < LabelSize && pack.disklabel[i] > 0; i++ {
	}
	return string(pack.disklabel[:i])
}
func (pack *Header) SetLabel(label string) {
	for i := copy(pack.disklabel[:], []byte(label)); i < LabelSize; i++ {
		pack.disklabel[i] = 0  
	}
}
func (pack *Header) FTTOffset() int64 {
	return int64(pack.fttoffset)
}
func (pack *Header) FTTSize() int64 {
	return int64(pack.fttsize)
}
func (pack *Header) DataSize() int64 {
	if pack.fttoffset > HeaderSize {
		return int64(pack.fttoffset - HeaderSize)
	}
	return 0
}
func (pack *Header) ReadFrom(r io.Reader) (n int64, err error) {
	if err = binary.Read(r, binary.LittleEndian, pack.signature[:]); err != nil {
		return
	}
	n += SignSize
	if err = binary.Read(r, binary.LittleEndian, pack.disklabel[:]); err != nil {
		return
	}
	n += LabelSize
	if err = binary.Read(r, binary.LittleEndian, &pack.fttoffset); err != nil {
		return
	}
	n += 8
	if err = binary.Read(r, binary.LittleEndian, &pack.fttsize); err != nil {
		return
	}
	n += 8
	return
}
func (pack *Header) WriteTo(w io.Writer) (n int64, err error) {
	if err = binary.Write(w, binary.LittleEndian, pack.signature[:]); err != nil {
		return
	}
	n += SignSize
	if err = binary.Write(w, binary.LittleEndian, pack.disklabel[:]); err != nil {
		return
	}
	n += LabelSize
	if err = binary.Write(w, binary.LittleEndian, &pack.fttoffset); err != nil {
		return
	}
	n += 8
	if err = binary.Write(w, binary.LittleEndian, &pack.fttsize); err != nil {
		return
	}
	n += 8
	return
}
type Tag []byte
func (t Tag) String() (string, bool) {
	return string(t), true
}
func TagString(val string) Tag {
	return Tag(val)
}
func (t Tag) Bool() (bool, bool) {
	if len(t) == 1 {
		return t[0] > 0, true
	}
	return false, false
}
func TagBool(val bool) Tag {
	var buf [1]byte
	if val {
		buf[0] = 1
	}
	return buf[:]
}
func (t Tag) Byte() (byte, bool) {
	if len(t) == 1 {
		return t[0], true
	}
	return 0, false
}
func TagByte(val byte) Tag {
	var buf = [1]byte{val}
	return buf[:]
}
func (t Tag) Uint16() (TID, bool) {
	if len(t) == 2 {
		return TID(binary.LittleEndian.Uint16(t)), true
	}
	return 0, false
}
func TagUint16(val TID) Tag {
	var buf [2]byte
	binary.LittleEndian.PutUint16(buf[:], uint16(val))
	return buf[:]
}
func (t Tag) Uint32() (uint32, bool) {
	if len(t) == 4 {
		return binary.LittleEndian.Uint32(t), true
	}
	return 0, false
}
func TagUint32(val uint32) Tag {
	var buf [4]byte
	binary.LittleEndian.PutUint32(buf[:], val)
	return buf[:]
}
func (t Tag) Uint64() (uint64, bool) {
	if len(t) == 8 {
		return binary.LittleEndian.Uint64(t), true
	}
	return 0, false
}
func TagUint64(val uint64) Tag {
	var buf [8]byte
	binary.LittleEndian.PutUint64(buf[:], val)
	return buf[:]
}
func (t Tag) Uint() (uint, bool) {
	switch len(t) {
	case 1:
		return uint(t[0]), true
	case 2:
		return uint(binary.LittleEndian.Uint16(t)), true
	case 4:
		return uint(binary.LittleEndian.Uint32(t)), true
	case 8:
		return uint(binary.LittleEndian.Uint64(t)), true
	}
	return 0, false
}
func (t Tag) Number() (float64, bool) {
	if len(t) == 8 {
		return math.Float64frombits(binary.LittleEndian.Uint64(t)), true
	}
	return 0, false
}
func TagNumber(val float64) Tag {
	var buf [8]byte
	binary.LittleEndian.PutUint64(buf[:], math.Float64bits(val))
	return buf[:]
}
type Tagset map[TID]Tag
func (ts Tagset) FID() FID {
	if data, ok := ts[TIDfid]; ok {
		var fid, _ = data.Uint32()
		return FID(fid)
	}
	return 0
}
func (ts Tagset) Path() string {
	if data, ok := ts[TIDpath]; ok {
		return string(data)
	}
	return ""
}
func (ts Tagset) Name() string {
	if data, ok := ts[TIDpath]; ok {
		return filepath.Base(string(data))
	}
	return ""
}
func (ts Tagset) Size() int64 {
	if data, ok := ts[TIDsize]; ok {
		var size, _ = data.Uint64()
		return int64(size)
	}
	return 0
}
func (ts Tagset) Offset() int64 {
	if data, ok := ts[TIDoffset]; ok {
		var offset, _ = data.Uint64()
		return int64(offset)
	}
	return 0
}
func (ts Tagset) ReadFrom(r io.Reader) (n int64, err error) {
	var num, id, l TID
	if err = binary.Read(r, binary.LittleEndian, &num); err != nil {
		return
	}
	n += 2
	for i := TID(0); i < num; i++ {
		if err = binary.Read(r, binary.LittleEndian, &id); err != nil {
			return
		}
		n += 2
		if err = binary.Read(r, binary.LittleEndian, &l); err != nil {
			return
		}
		n += 2
		var data = make([]byte, l)
		if err = binary.Read(r, binary.LittleEndian, &data); err != nil {
			return
		}
		n += int64(l)
		ts[id] = data
	}
	return
}
func (ts Tagset) WriteTo(w io.Writer) (n int64, err error) {
	if err = binary.Write(w, binary.LittleEndian, TID(len(ts))); err != nil {
		return
	}
	n += 2
	for id, data := range ts {
		if err = binary.Write(w, binary.LittleEndian, id); err != nil {
			return
		}
		n += 2
		if err = binary.Write(w, binary.LittleEndian, TID(len(data))); err != nil {
			return
		}
		n += 2
		if err = binary.Write(w, binary.LittleEndian, data); err != nil {
			return
		}
		n += int64(len(data))
	}
	return
}
type TagSlice []byte
func (ts TagSlice) Num() int {
	if 2 > len(ts) {
		return 0
	}
	return int(binary.LittleEndian.Uint16(ts))
}
func (ts TagSlice) GetTag(tid TID) (Tag, error) {
	var n, tsl = 0, len(ts)
	if n+2 > tsl {
		return nil, io.EOF
	}
	var num = TID(binary.LittleEndian.Uint16(ts[n:]))
	n += 2
	for i := TID(0); i < num; i++ {
		if n+2 > tsl {
			return nil, io.EOF
		}
		var id = TID(binary.LittleEndian.Uint16(ts[n:]))
		n += 2
		if n+2 > tsl {
			return nil, io.EOF
		}
		var l = int(binary.LittleEndian.Uint16(ts[n:]))
		n += 2
		if n+l > tsl {
			return nil, io.EOF
		}
		if id == tid {
			return Tag(ts[n : n+l]), nil
		}
		n += l
	}
	return nil, ErrNoTag
}
func (ts TagSlice) String(tid TID) (string, bool) {
	if data, err := ts.GetTag(tid); err == nil {
		return data.String()
	}
	return "", false
}
func (ts TagSlice) Bool(tid TID) (bool, bool) {
	if data, err := ts.GetTag(tid); err == nil {
		return data.Bool()
	}
	return false, false
}
func (ts TagSlice) Byte(tid TID) (byte, bool) {
	if data, err := ts.GetTag(tid); err == nil {
		return data.Byte()
	}
	return 0, false
}
func (ts TagSlice) Uint16(tid TID) (TID, bool) {
	if data, err := ts.GetTag(tid); err == nil {
		return data.Uint16()
	}
	return 0, false
}
func (ts TagSlice) Uint32(tid TID) (uint32, bool) {
	if data, err := ts.GetTag(tid); err == nil {
		return data.Uint32()
	}
	return 0, false
}
func (ts TagSlice) Uint64(tid TID) (uint64, bool) {
	if data, err := ts.GetTag(tid); err == nil {
		return data.Uint64()
	}
	return 0, false
}
func (ts TagSlice) Uint(tid TID) (uint, bool) {
	if data, err := ts.GetTag(tid); err == nil {
		return data.Uint()
	}
	return 0, false
}
func (ts TagSlice) Number(tid TID) (float64, bool) {
	if data, err := ts.GetTag(tid); err == nil {
		return data.Number()
	}
	return 0, false
}
func (ts TagSlice) FID() FID {
	var fid, _ = ts.Uint32(TIDfid)
	return FID(fid)
}
func (ts TagSlice) Path() string {
	var kpath, _ = ts.String(TIDpath)
	return kpath
}
func (ts TagSlice) Name() string {
	var kpath, _ = ts.String(TIDpath)
	return filepath.Base(kpath)
}
func (ts TagSlice) Size() int64 {
	var size, _ = ts.Uint64(TIDsize)
	return int64(size)
}
func (ts TagSlice) Offset() int64 {
	var offset, _ = ts.Uint64(TIDoffset)
	return int64(offset)
}
func (ts TagSlice) Mode() fs.FileMode {
	if _, ok := ts.Uint32(TIDfid); ok {  
		return 0444
	}
	return fs.ModeDir
}
func (ts TagSlice) ModTime() time.Time {
	var crt, _ = ts.Uint64(TIDcreated)
	return time.Unix(int64(crt), 0)
}
func (ts TagSlice) IsDir() bool {
	var _, ok = ts.Uint32(TIDfid)  
	return !ok
}
func (ts TagSlice) Sys() interface{} {
	return nil
}
type DirEntry struct {
	TagSlice  
}
func (f *DirEntry) Type() fs.FileMode {
	if _, ok := f.Uint32(TIDfid); ok {  
		return 0444
	}
	return fs.ModeDir
}