func (dei DirectoryEntryIndex) GetFile(i int) (filename string, fdf *ExfatFileDirectoryEntry) {
	ide := dei["File"][i]
	return ide.Extra["complete_filename"].(string), ide.PrimaryEntry.(*ExfatFileDirectoryEntry)
}
GetFile returns the file directory-entry with index `i`.
package exfat
import (
	"fmt"
	"reflect"
	"strings"
	"github.com/dsoprea/go-logging"
)
const (
	directoryEntryBytesCount = 32
)
type ExfatNavigator struct {
	er                 *ExfatReader
	firstClusterNumber uint32
}
func NewExfatNavigator(er *ExfatReader, firstClusterNumber uint32) (en *ExfatNavigator) {
	return &ExfatNavigator{
		er:                 er,
		firstClusterNumber: firstClusterNumber,
	}
}
type DirectoryEntryVisitorFunc func(primaryEntry DirectoryEntry, secondaryEntries []DirectoryEntry) (err error)
func (en *ExfatNavigator) EnumerateDirectoryEntries(cb DirectoryEntryVisitorFunc) (visitedClusters, visitedSectors []uint32, err error) {
	defer func() {
		if errRaw := recover(); errRaw != nil {
			err = log.Wrap(errRaw.(error))
		}
	}()
	entryNumber := 0
	isDone := false
	var primaryEntry DirectoryEntry
	var secondaryEntries []DirectoryEntry
	visitedClusters = make([]uint32, 0)
	visitedSectors = make([]uint32, 0)
	cvf := func(ec *ExfatCluster) (doContinue bool, err error) {
		defer func() {
			if errRaw := recover(); errRaw != nil {
				var ok bool
				if err, ok = errRaw.(error); ok == true {
					err = log.Wrap(err)
				} else {
					err = log.Errorf("Error not an error: [%s] [%v]", reflect.TypeOf(err).Name(), err)
				}
			}
		}()
		visitedClusters = append(visitedClusters, ec.ClusterNumber())
		svf := func(sectorNumber uint32, data []byte) (doContinue bool, err error) {
			defer func() {
				if errRaw := recover(); errRaw != nil {
					var ok bool
					if err, ok = errRaw.(error); ok == true {
						err = log.Wrap(err)
					} else {
						err = log.Errorf("Error not an error: [%s] [%v]", reflect.TypeOf(err).Name(), err)
					}
				}
			}()
			visitedSectors = append(visitedSectors, sectorNumber)
			sectorSize := en.er.SectorSize()
			i := 0
			for {
				directoryEntryData := data[i*directoryEntryBytesCount : (i+1)*directoryEntryBytesCount]
				entryType := EntryType(directoryEntryData[0])
				if entryType.IsEndOfDirectory() == true {
					isDone = true
					return false, nil
				}
				de, err := parseDirectoryEntry(entryType, directoryEntryData)
				log.PanicIf(err)
				if entryType.IsPrimary() == true {
					primaryEntry = de
					secondaryEntries = make([]DirectoryEntry, 0)
				} else {
					secondaryEntries = append(secondaryEntries, de)
				}
				if pde, ok := primaryEntry.(PrimaryDirectoryEntry); ok == true {
					if len(secondaryEntries) == int(pde.SecondaryCount()) {
						err := cb(primaryEntry, secondaryEntries)
						log.PanicIf(err)
					}
				} else if entryType.IsPrimary() == true {
					err := cb(primaryEntry, secondaryEntries)
					log.PanicIf(err)
				}
				entryNumber++
				i++
				if uint32(i*directoryEntryBytesCount) >= sectorSize {
					break
				}
			}
			return true, nil
		}
		err = ec.EnumerateSectors(svf)
		log.PanicIf(err)
		if isDone == true {
			return false, nil
		}
		return true, nil
	}
	useFat := false
	err = en.er.EnumerateClusters(en.firstClusterNumber, cvf, useFat)
	log.PanicIf(err)
	return visitedClusters, visitedSectors, nil
}
type IndexedDirectoryEntry struct {
	PrimaryEntry     DirectoryEntry
	SecondaryEntries []DirectoryEntry
	Extra            map[string]interface{}
}
type DirectoryEntryIndex map[string][]IndexedDirectoryEntry
func (dei DirectoryEntryIndex) Dump() {
	fmt.Printf("Directory Entry Index\n")
	fmt.Printf("=====================\n")
	fmt.Printf("\n")
	for typeName, ideList := range dei {
		fmt.Printf("%s\n", typeName)
		fmt.Println(strings.Repeat("-", len(typeName)))
		fmt.Printf("\n")
		for i, ide := range ideList {
			fmt.Printf("# %d\n", i)
			fmt.Printf("\n")
			fmt.Printf("  Primary: %s\n", ide.PrimaryEntry)
			for j, secondaryEntry := range ide.SecondaryEntries {
				fmt.Printf("  Secondary (%d): %s\n", j, secondaryEntry)
			}
			fmt.Printf("\n")
			if len(ide.Extra) > 0 {
				fmt.Printf("  Extra:\n")
				for k, v := range ide.Extra {
					fmt.Printf("    %s: %s\n", k, v)
				}
				fmt.Printf("\n")
			}
			if fdf, ok := ide.PrimaryEntry.(*ExfatFileDirectoryEntry); ok == true {
				fmt.Printf("  Attributes:\n")
				fdf.FileAttributes.DumpBareIndented("    ")
				fmt.Printf("\n")
			}
		}
	}
}
func (dei DirectoryEntryIndex) Filenames() (filenames map[string]bool) {
	fileIdeList, found := dei["File"]
	if found == true {
		filenames = make(map[string]bool, len(fileIdeList))
		for _, ide := range fileIdeList {
			filename := ide.Extra["complete_filename"].(string)
			filenames[filename] = ide.PrimaryEntry.(*ExfatFileDirectoryEntry).FileAttributes.IsDirectory()
		}
	} else {
		filenames = make(map[string]bool, 0)
	}
	return filenames
}
func (dei DirectoryEntryIndex) FileCount() (count int) {
	if fileIdeList, found := dei["File"]; found == true {
		count = len(fileIdeList)
	}
	return count
}