func (s SetAttrMask) Empty() bool {
	return !s.Permissions && !s.UID && !s.GID && !s.Size && !s.ATime && !s.MTime && !s.CTime && !s.ATimeNotSystemTime && !s.MTimeNotSystemTime
}
Empty returns true if no fields are masked.
package p9
import (
	"fmt"
	"math"
	"os"
	"strings"
	"sync/atomic"
	"github.com/hugelgupf/p9/internal"
)
var Debug = func(fmt string, v ...interface{}) {}
const (
	DefaultMessageSize uint32 = 64 << 10
)
type OpenFlags uint32
const (
	ReadOnly OpenFlags = 0
	WriteOnly OpenFlags = 1
	ReadWrite OpenFlags = 2
	OpenFlagsModeMask OpenFlags = 3
)
func (o OpenFlags) Mode() OpenFlags {
	return o & OpenFlagsModeMask
}
func (o OpenFlags) OSFlags() int {
	return int(o & OpenFlagsModeMask)
}
func (o OpenFlags) String() string {
	switch o {
	case ReadOnly:
		return "ReadOnly"
	case WriteOnly:
		return "WriteOnly"
	case ReadWrite:
		return "ReadWrite"
	case OpenFlagsModeMask:
		return "OpenFlagsModeMask"
	default:
		return fmt.Sprintf("unknown (%#x)", uint32(o))
	}
}
type tag uint16
type fid uint64
type FileMode uint32
const (
	FileModeMask FileMode = 0170000
	ModeSocket FileMode = 0140000
	ModeSymlink FileMode = 0120000
	ModeRegular FileMode = 0100000
	ModeBlockDevice FileMode = 060000
	ModeDirectory FileMode = 040000
	ModeCharacterDevice FileMode = 020000
	ModeNamedPipe FileMode = 010000
	Read FileMode = 04
	Write FileMode = 02
	Exec FileMode = 01
	AllPermissions FileMode = 0777
	Sticky FileMode = 01000
	permissionsMask FileMode = 01777
)
func (m FileMode) QIDType() QIDType {
	switch {
	case m.IsDir():
		return TypeDir
	case m.IsSocket(), m.IsNamedPipe(), m.IsCharacterDevice():
		return TypeAppendOnly
	case m.IsSymlink():
		return TypeSymlink
	default:
		return TypeRegular
	}
}
func (m FileMode) FileType() FileMode {
	return m & FileModeMask
}
func (m FileMode) Permissions() FileMode {
	return m & permissionsMask
}
func (m FileMode) Writable() FileMode {
	return m | 0222
}
func (m FileMode) IsReadable() bool {
	return m&0444 != 0
}
func (m FileMode) IsWritable() bool {
	return m&0222 != 0
}
func (m FileMode) IsExecutable() bool {
	return m&0111 != 0
}
func (m FileMode) IsRegular() bool {
	return m&FileModeMask == ModeRegular
}
func (m FileMode) IsDir() bool {
	return m&FileModeMask == ModeDirectory
}
func (m FileMode) IsNamedPipe() bool {
	return m&FileModeMask == ModeNamedPipe
}
func (m FileMode) IsCharacterDevice() bool {
	return m&FileModeMask == ModeCharacterDevice
}
func (m FileMode) IsBlockDevice() bool {
	return m&FileModeMask == ModeBlockDevice
}
func (m FileMode) IsSocket() bool {
	return m&FileModeMask == ModeSocket
}
func (m FileMode) IsSymlink() bool {
	return m&FileModeMask == ModeSymlink
}
func ModeFromOS(mode os.FileMode) FileMode {
	m := FileMode(mode.Perm())
	switch {
	case mode.IsDir():
		m |= ModeDirectory
	case mode&os.ModeSymlink != 0:
		m |= ModeSymlink
	case mode&os.ModeSocket != 0:
		m |= ModeSocket
	case mode&os.ModeNamedPipe != 0:
		m |= ModeNamedPipe
	case mode&os.ModeCharDevice != 0:
		m |= ModeCharacterDevice
	case mode&os.ModeDevice != 0:
		m |= ModeBlockDevice
	default:
		m |= ModeRegular
	}
	return m
}
func (m FileMode) OSMode() os.FileMode {
	var osMode os.FileMode
	osMode |= os.FileMode(m.Permissions())
	switch {
	case m.IsDir():
		osMode |= os.ModeDir
	case m.IsSymlink():
		osMode |= os.ModeSymlink
	case m.IsSocket():
		osMode |= os.ModeSocket
	case m.IsNamedPipe():
		osMode |= os.ModeNamedPipe
	case m.IsCharacterDevice():
		osMode |= os.ModeCharDevice | os.ModeDevice
	case m.IsBlockDevice():
		osMode |= os.ModeDevice
	}
	return osMode
}
type UID uint32
func (uid UID) Ok() bool {
	return uid != NoUID
}
type GID uint32
func (gid GID) Ok() bool {
	return gid != NoGID
}
const (
	noTag tag = math.MaxUint16
	noFID fid = math.MaxUint32
	NoUID UID = math.MaxUint32
	NoGID GID = math.MaxUint32
)
type msgType uint8
const (
	msgRlerror      msgType = 7
	msgTstatfs      msgType = 8
	msgRstatfs      msgType = 9
	msgTlopen       msgType = 12
	msgRlopen       msgType = 13
	msgTlcreate     msgType = 14
	msgRlcreate     msgType = 15
	msgTsymlink     msgType = 16
	msgRsymlink     msgType = 17
	msgTmknod       msgType = 18
	msgRmknod       msgType = 19
	msgTrename      msgType = 20
	msgRrename      msgType = 21
	msgTreadlink    msgType = 22
	msgRreadlink    msgType = 23
	msgTgetattr     msgType = 24
	msgRgetattr     msgType = 25
	msgTsetattr     msgType = 26
	msgRsetattr     msgType = 27
	msgTxattrwalk   msgType = 30
	msgRxattrwalk   msgType = 31
	msgTxattrcreate msgType = 32
	msgRxattrcreate msgType = 33
	msgTreaddir     msgType = 40
	msgRreaddir     msgType = 41
	msgTfsync       msgType = 50
	msgRfsync       msgType = 51
	msgTlink        msgType = 70
	msgRlink        msgType = 71
	msgTmkdir       msgType = 72
	msgRmkdir       msgType = 73
	msgTrenameat    msgType = 74
	msgRrenameat    msgType = 75
	msgTunlinkat    msgType = 76
	msgRunlinkat    msgType = 77
	msgTversion     msgType = 100
	msgRversion     msgType = 101
	msgTauth        msgType = 102
	msgRauth        msgType = 103
	msgTattach      msgType = 104
	msgRattach      msgType = 105
	msgTflush       msgType = 108
	msgRflush       msgType = 109
	msgTwalk        msgType = 110
	msgRwalk        msgType = 111
	msgTread        msgType = 116
	msgRread        msgType = 117
	msgTwrite       msgType = 118
	msgRwrite       msgType = 119
	msgTclunk       msgType = 120
	msgRclunk       msgType = 121
	msgTremove      msgType = 122
	msgRremove      msgType = 123
	msgTflushf      msgType = 124
	msgRflushf      msgType = 125
	msgTwalkgetattr msgType = 126
	msgRwalkgetattr msgType = 127
	msgTucreate     msgType = 128
	msgRucreate     msgType = 129
	msgTumkdir      msgType = 130
	msgRumkdir      msgType = 131
	msgTumknod      msgType = 132
	msgRumknod      msgType = 133
	msgTusymlink    msgType = 134
	msgRusymlink    msgType = 135
)
type QIDType uint8
const (
	TypeDir QIDType = 0x80
	TypeAppendOnly QIDType = 0x40
	TypeExclusive QIDType = 0x20
	TypeMount QIDType = 0x10
	TypeAuth QIDType = 0x08
	TypeTemporary QIDType = 0x04
	TypeSymlink QIDType = 0x02
	TypeLink QIDType = 0x01
	TypeRegular QIDType = 0x00
)
type QID struct {
	Type QIDType
	Version uint32
	Path uint64
}
func (q QID) String() string {
	return fmt.Sprintf("QID{Type: %d, Version: %d, Path: %d}", q.Type, q.Version, q.Path)
}
func (q *QID) decode(b *buffer) {
	q.Type = b.ReadQIDType()
	q.Version = b.Read32()
	q.Path = b.Read64()
}
func (q *QID) encode(b *buffer) {
	b.WriteQIDType(q.Type)
	b.Write32(q.Version)
	b.Write64(q.Path)
}
type QIDGenerator struct {
	uids uint64
}
func (q *QIDGenerator) Get(t QIDType) QID {
	return QID{
		Type:    t,
		Version: 0,
		Path:    atomic.AddUint64(&q.uids, 1),
	}
}
type FSStat struct {
	Type uint32
	BlockSize uint32
	Blocks uint64
	BlocksFree uint64
	BlocksAvailable uint64
	Files uint64
	FilesFree uint64
	FSID uint64
	NameLength uint32
}
func (f *FSStat) decode(b *buffer) {
	f.Type = b.Read32()
	f.BlockSize = b.Read32()
	f.Blocks = b.Read64()
	f.BlocksFree = b.Read64()
	f.BlocksAvailable = b.Read64()
	f.Files = b.Read64()
	f.FilesFree = b.Read64()
	f.FSID = b.Read64()
	f.NameLength = b.Read32()
}
func (f *FSStat) encode(b *buffer) {
	b.Write32(f.Type)
	b.Write32(f.BlockSize)
	b.Write64(f.Blocks)
	b.Write64(f.BlocksFree)
	b.Write64(f.BlocksAvailable)
	b.Write64(f.Files)
	b.Write64(f.FilesFree)
	b.Write64(f.FSID)
	b.Write32(f.NameLength)
}
type AttrMask struct {
	Mode        bool
	NLink       bool
	UID         bool
	GID         bool
	RDev        bool
	ATime       bool
	MTime       bool
	CTime       bool
	INo         bool
	Size        bool
	Blocks      bool
	BTime       bool
	Gen         bool
	DataVersion bool
}
func (a AttrMask) Contains(b AttrMask) bool {
	if b.Mode && !a.Mode {
		return false
	}
	if b.NLink && !a.NLink {
		return false
	}
	if b.UID && !a.UID {
		return false
	}
	if b.GID && !a.GID {
		return false
	}
	if b.RDev && !a.RDev {
		return false
	}
	if b.ATime && !a.ATime {
		return false
	}
	if b.MTime && !a.MTime {
		return false
	}
	if b.CTime && !a.CTime {
		return false
	}
	if b.INo && !a.INo {
		return false
	}
	if b.Size && !a.Size {
		return false
	}
	if b.Blocks && !a.Blocks {
		return false
	}
	if b.BTime && !a.BTime {
		return false
	}
	if b.Gen && !a.Gen {
		return false
	}
	if b.DataVersion && !a.DataVersion {
		return false
	}
	return true
}
func (a AttrMask) Empty() bool {
	return !a.Mode && !a.NLink && !a.UID && !a.GID && !a.RDev && !a.ATime && !a.MTime && !a.CTime && !a.INo && !a.Size && !a.Blocks && !a.BTime && !a.Gen && !a.DataVersion
}
var AttrMaskAll = AttrMask{
	Mode:        true,
	NLink:       true,
	UID:         true,
	GID:         true,
	RDev:        true,
	ATime:       true,
	MTime:       true,
	CTime:       true,
	INo:         true,
	Size:        true,
	Blocks:      true,
	BTime:       true,
	Gen:         true,
	DataVersion: true,
}
func (a AttrMask) String() string {
	var masks []string
	if a.Mode {
		masks = append(masks, "Mode")
	}
	if a.NLink {
		masks = append(masks, "NLink")
	}
	if a.UID {
		masks = append(masks, "UID")
	}
	if a.GID {
		masks = append(masks, "GID")
	}
	if a.RDev {
		masks = append(masks, "RDev")
	}
	if a.ATime {
		masks = append(masks, "ATime")
	}
	if a.MTime {
		masks = append(masks, "MTime")
	}
	if a.CTime {
		masks = append(masks, "CTime")
	}
	if a.INo {
		masks = append(masks, "INo")
	}
	if a.Size {
		masks = append(masks, "Size")
	}
	if a.Blocks {
		masks = append(masks, "Blocks")
	}
	if a.BTime {
		masks = append(masks, "BTime")
	}
	if a.Gen {
		masks = append(masks, "Gen")
	}
	if a.DataVersion {
		masks = append(masks, "DataVersion")
	}
	return fmt.Sprintf("AttrMask{with: %s}", strings.Join(masks, " "))
}
func (a *AttrMask) decode(b *buffer) {
	mask := b.Read64()
	a.Mode = mask&0x00000001 != 0
	a.NLink = mask&0x00000002 != 0
	a.UID = mask&0x00000004 != 0
	a.GID = mask&0x00000008 != 0
	a.RDev = mask&0x00000010 != 0
	a.ATime = mask&0x00000020 != 0
	a.MTime = mask&0x00000040 != 0
	a.CTime = mask&0x00000080 != 0
	a.INo = mask&0x00000100 != 0
	a.Size = mask&0x00000200 != 0
	a.Blocks = mask&0x00000400 != 0
	a.BTime = mask&0x00000800 != 0
	a.Gen = mask&0x00001000 != 0
	a.DataVersion = mask&0x00002000 != 0
}
func (a *AttrMask) encode(b *buffer) {
	var mask uint64
	if a.Mode {
		mask |= 0x00000001
	}
	if a.NLink {
		mask |= 0x00000002
	}
	if a.UID {
		mask |= 0x00000004
	}
	if a.GID {
		mask |= 0x00000008
	}
	if a.RDev {
		mask |= 0x00000010
	}
	if a.ATime {
		mask |= 0x00000020
	}
	if a.MTime {
		mask |= 0x00000040
	}
	if a.CTime {
		mask |= 0x00000080
	}
	if a.INo {
		mask |= 0x00000100
	}
	if a.Size {
		mask |= 0x00000200
	}
	if a.Blocks {
		mask |= 0x00000400
	}
	if a.BTime {
		mask |= 0x00000800
	}
	if a.Gen {
		mask |= 0x00001000
	}
	if a.DataVersion {
		mask |= 0x00002000
	}
	b.Write64(mask)
}
type NLink uint64
type Dev uint64
type Attr struct {
	Mode             FileMode
	UID              UID
	GID              GID
	NLink            NLink
	RDev             Dev
	Size             uint64
	BlockSize        uint64
	Blocks           uint64
	ATimeSeconds     uint64
	ATimeNanoSeconds uint64
	MTimeSeconds     uint64
	MTimeNanoSeconds uint64
	CTimeSeconds     uint64
	CTimeNanoSeconds uint64
	BTimeSeconds     uint64
	BTimeNanoSeconds uint64
	Gen              uint64
	DataVersion      uint64
}
func (a Attr) String() string {
	return fmt.Sprintf("Attr{Mode: 0o%o, UID: %d, GID: %d, NLink: %d, RDev: %d, Size: %d, BlockSize: %d, Blocks: %d, ATime: {Sec: %d, NanoSec: %d}, MTime: {Sec: %d, NanoSec: %d}, CTime: {Sec: %d, NanoSec: %d}, BTime: {Sec: %d, NanoSec: %d}, Gen: %d, DataVersion: %d}",
		a.Mode, a.UID, a.GID, a.NLink, a.RDev, a.Size, a.BlockSize, a.Blocks, a.ATimeSeconds, a.ATimeNanoSeconds, a.MTimeSeconds, a.MTimeNanoSeconds, a.CTimeSeconds, a.CTimeNanoSeconds, a.BTimeSeconds, a.BTimeNanoSeconds, a.Gen, a.DataVersion)
}
func (a *Attr) encode(b *buffer) {
	b.WriteFileMode(a.Mode)
	b.WriteUID(a.UID)
	b.WriteGID(a.GID)
	b.Write64(uint64(a.NLink))
	b.Write64(uint64(a.RDev))
	b.Write64(a.Size)
	b.Write64(a.BlockSize)
	b.Write64(a.Blocks)
	b.Write64(a.ATimeSeconds)
	b.Write64(a.ATimeNanoSeconds)
	b.Write64(a.MTimeSeconds)
	b.Write64(a.MTimeNanoSeconds)
	b.Write64(a.CTimeSeconds)
	b.Write64(a.CTimeNanoSeconds)
	b.Write64(a.BTimeSeconds)
	b.Write64(a.BTimeNanoSeconds)
	b.Write64(a.Gen)
	b.Write64(a.DataVersion)
}
func (a *Attr) decode(b *buffer) {
	a.Mode = b.ReadFileMode()
	a.UID = b.ReadUID()
	a.GID = b.ReadGID()
	a.NLink = NLink(b.Read64())
	a.RDev = Dev(b.Read64())
	a.Size = b.Read64()
	a.BlockSize = b.Read64()
	a.Blocks = b.Read64()
	a.ATimeSeconds = b.Read64()
	a.ATimeNanoSeconds = b.Read64()
	a.MTimeSeconds = b.Read64()
	a.MTimeNanoSeconds = b.Read64()
	a.CTimeSeconds = b.Read64()
	a.CTimeNanoSeconds = b.Read64()
	a.BTimeSeconds = b.Read64()
	a.BTimeNanoSeconds = b.Read64()
	a.Gen = b.Read64()
	a.DataVersion = b.Read64()
}
func StatToAttr(s *internal.Stat_t, req AttrMask) (Attr, AttrMask) {
	attr := Attr{
		UID: NoUID,
		GID: NoGID,
	}
	if req.Mode {
		attr.Mode = FileMode(s.Mode)
	}
	if req.NLink {
		attr.NLink = NLink(s.Nlink)
	}
	if req.UID {
		attr.UID = UID(s.Uid)
	}
	if req.GID {
		attr.GID = GID(s.Gid)
	}
	if req.RDev {
		attr.RDev = Dev(s.Dev)
	}
	if req.ATime {
		attr.ATimeSeconds = uint64(s.Atim.Sec)
		attr.ATimeNanoSeconds = uint64(s.Atim.Nsec)
	}
	if req.MTime {
		attr.MTimeSeconds = uint64(s.Mtim.Sec)
		attr.MTimeNanoSeconds = uint64(s.Mtim.Nsec)
	}
	if req.CTime {
		attr.CTimeSeconds = uint64(s.Ctim.Sec)
		attr.CTimeNanoSeconds = uint64(s.Ctim.Nsec)
	}
	if req.Size {
		attr.Size = uint64(s.Size)
	}
	if req.Blocks {
		attr.BlockSize = uint64(s.Blksize)
		attr.Blocks = uint64(s.Blocks)
	}
	req.BTime = false
	req.Gen = false
	req.DataVersion = false
	return attr, req
}
type SetAttrMask struct {
	Permissions        bool
	UID                bool
	GID                bool
	Size               bool
	ATime              bool
	MTime              bool
	CTime              bool
	ATimeNotSystemTime bool
	MTimeNotSystemTime bool
}
func (s SetAttrMask) IsSubsetOf(m SetAttrMask) bool {
	sb := s.bitmask()
	sm := m.bitmask()
	return sm|sb == sm
}
func (s SetAttrMask) String() string {
	var masks []string
	if s.Permissions {
		masks = append(masks, "Permissions")
	}
	if s.UID {
		masks = append(masks, "UID")
	}
	if s.GID {
		masks = append(masks, "GID")
	}
	if s.Size {
		masks = append(masks, "Size")
	}
	if s.ATime {
		masks = append(masks, "ATime")
	}
	if s.MTime {
		masks = append(masks, "MTime")
	}
	if s.CTime {
		masks = append(masks, "CTime")
	}
	if s.ATimeNotSystemTime {
		masks = append(masks, "ATimeNotSystemTime")
	}
	if s.MTimeNotSystemTime {
		masks = append(masks, "MTimeNotSystemTime")
	}
	return fmt.Sprintf("SetAttrMask{with: %s}", strings.Join(masks, " "))
}