func EmptyDirNode() *dag.ProtoNode {
	return dag.NodeWithData(FolderPBData())
}
EmptyDirNode creates an empty folder Protonode.
package unixfs
import (
	"errors"
	"fmt"
	proto "github.com/gogo/protobuf/proto"
	dag "github.com/ipfs/go-merkledag"
	ipld "github.com/ipfs/go-ipld-format"
	pb "github.com/ipfs/go-unixfs/pb"
)
type LinkResult struct {
	Link *ipld.Link
	Err  error
}
const (
	TRaw       = pb.Data_Raw
	TFile      = pb.Data_File
	TDirectory = pb.Data_Directory
	TMetadata  = pb.Data_Metadata
	TSymlink   = pb.Data_Symlink
	THAMTShard = pb.Data_HAMTShard
)
var (
	ErrMalformedFileFormat = errors.New("malformed data in file format")
	ErrUnrecognizedType    = errors.New("unrecognized node type")
)
func FromBytes(data []byte) (*pb.Data, error) {
	pbdata := new(pb.Data)
	err := proto.Unmarshal(data, pbdata)
	if err != nil {
		return nil, err
	}
	return pbdata, nil
}
func FilePBData(data []byte, totalsize uint64) []byte {
	pbfile := new(pb.Data)
	typ := pb.Data_File
	pbfile.Type = &typ
	pbfile.Data = data
	pbfile.Filesize = proto.Uint64(totalsize)
	data, err := proto.Marshal(pbfile)
	if err != nil {
		panic(err)
	}
	return data
}
func FolderPBData() []byte {
	pbfile := new(pb.Data)
	typ := pb.Data_Directory
	pbfile.Type = &typ
	data, err := proto.Marshal(pbfile)
	if err != nil {
		panic(err)
	}
	return data
}
func WrapData(b []byte) []byte {
	pbdata := new(pb.Data)
	typ := pb.Data_Raw
	pbdata.Data = b
	pbdata.Type = &typ
	pbdata.Filesize = proto.Uint64(uint64(len(b)))
	out, err := proto.Marshal(pbdata)
	if err != nil {
		panic(err)
	}
	return out
}
func SymlinkData(path string) ([]byte, error) {
	pbdata := new(pb.Data)
	typ := pb.Data_Symlink
	pbdata.Data = []byte(path)
	pbdata.Type = &typ
	out, err := proto.Marshal(pbdata)
	if err != nil {
		return nil, err
	}
	return out, nil
}
func HAMTShardData(data []byte, fanout uint64, hashType uint64) ([]byte, error) {
	pbdata := new(pb.Data)
	typ := pb.Data_HAMTShard
	pbdata.Type = &typ
	pbdata.HashType = proto.Uint64(hashType)
	pbdata.Data = data
	pbdata.Fanout = proto.Uint64(fanout)
	out, err := proto.Marshal(pbdata)
	if err != nil {
		return nil, err
	}
	return out, nil
}
func UnwrapData(data []byte) ([]byte, error) {
	pbdata := new(pb.Data)
	err := proto.Unmarshal(data, pbdata)
	if err != nil {
		return nil, err
	}
	return pbdata.GetData(), nil
}
func DataSize(data []byte) (uint64, error) {
	pbdata := new(pb.Data)
	err := proto.Unmarshal(data, pbdata)
	if err != nil {
		return 0, err
	}
	return size(pbdata)
}
func size(pbdata *pb.Data) (uint64, error) {
	switch pbdata.GetType() {
	case pb.Data_Directory, pb.Data_HAMTShard:
		return 0, errors.New("can't get data size of directory")
	case pb.Data_File, pb.Data_Raw:
		return pbdata.GetFilesize(), nil
	case pb.Data_Symlink:
		return uint64(len(pbdata.GetData())), nil
	default:
		return 0, errors.New("unrecognized node data type")
	}
}
type FSNode struct {
	format pb.Data
}
func FSNodeFromBytes(b []byte) (*FSNode, error) {
	n := new(FSNode)
	err := proto.Unmarshal(b, &n.format)
	if err != nil {
		return nil, err
	}
	return n, nil
}
func NewFSNode(dataType pb.Data_DataType) *FSNode {
	n := new(FSNode)
	n.format.Type = &dataType
	n.UpdateFilesize(0)
	return n
}
func (n *FSNode) HashType() uint64 {
	return n.format.GetHashType()
}
func (n *FSNode) Fanout() uint64 {
	return n.format.GetFanout()
}
func (n *FSNode) AddBlockSize(s uint64) {
	n.UpdateFilesize(int64(s))
	n.format.Blocksizes = append(n.format.Blocksizes, s)
}
func (n *FSNode) RemoveBlockSize(i int) {
	n.UpdateFilesize(-int64(n.format.Blocksizes[i]))
	n.format.Blocksizes = append(n.format.Blocksizes[:i], n.format.Blocksizes[i+1:]...)
}
func (n *FSNode) BlockSize(i int) uint64 {
	return n.format.Blocksizes[i]
}
func (n *FSNode) BlockSizes() []uint64 {
	return n.format.GetBlocksizes()
}
func (n *FSNode) RemoveAllBlockSizes() {
	n.format.Blocksizes = []uint64{}
	n.format.Filesize = proto.Uint64(uint64(len(n.Data())))
}
func (n *FSNode) GetBytes() ([]byte, error) {
	return proto.Marshal(&n.format)
}
func (n *FSNode) FileSize() uint64 {
	size, _ := size(&n.format)
	return size
}
func (n *FSNode) NumChildren() int {
	return len(n.format.Blocksizes)
}
func (n *FSNode) Data() []byte {
	return n.format.GetData()
}
func (n *FSNode) SetData(newData []byte) {
	n.UpdateFilesize(int64(len(newData) - len(n.Data())))
	n.format.Data = newData
}
func (n *FSNode) UpdateFilesize(filesizeDiff int64) {
	n.format.Filesize = proto.Uint64(uint64(
		int64(n.format.GetFilesize()) + filesizeDiff))
}
func (n *FSNode) Type() pb.Data_DataType {
	return n.format.GetType()
}
func (n *FSNode) IsDir() bool {
	switch n.Type() {
	case pb.Data_Directory, pb.Data_HAMTShard:
		return true
	default:
		return false
	}
}
type Metadata struct {
	MimeType string
	Size     uint64
}
func MetadataFromBytes(b []byte) (*Metadata, error) {
	pbd := new(pb.Data)
	err := proto.Unmarshal(b, pbd)
	if err != nil {
		return nil, err
	}
	if pbd.GetType() != pb.Data_Metadata {
		return nil, errors.New("incorrect node type")
	}
	pbm := new(pb.Metadata)
	err = proto.Unmarshal(pbd.Data, pbm)
	if err != nil {
		return nil, err
	}
	md := new(Metadata)
	md.MimeType = pbm.GetMimeType()
	return md, nil
}
func (m *Metadata) Bytes() ([]byte, error) {
	pbm := new(pb.Metadata)
	pbm.MimeType = &m.MimeType
	return proto.Marshal(pbm)
}
func BytesForMetadata(m *Metadata) ([]byte, error) {
	pbd := new(pb.Data)
	pbd.Filesize = proto.Uint64(m.Size)
	typ := pb.Data_Metadata
	pbd.Type = &typ
	mdd, err := m.Bytes()
	if err != nil {
		return nil, err
	}
	pbd.Data = mdd
	return proto.Marshal(pbd)
}