143 lines
2.8 KiB
Go
143 lines
2.8 KiB
Go
package infinitime
|
|
|
|
import (
|
|
"fmt"
|
|
"io/fs"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// DirEntry represents an entry from a directory listing
|
|
type DirEntry struct {
|
|
flags uint32
|
|
modtime uint64
|
|
size uint32
|
|
path string
|
|
}
|
|
|
|
// Name returns the name of the file described by the entry
|
|
func (de DirEntry) Name() string {
|
|
return de.path
|
|
}
|
|
|
|
// IsDir reports whether the entry describes a directory.
|
|
func (de DirEntry) IsDir() bool {
|
|
return de.flags&0b1 == 1
|
|
}
|
|
|
|
// Type returns the type bits for the entry.
|
|
func (de DirEntry) Type() fs.FileMode {
|
|
if de.IsDir() {
|
|
return fs.ModeDir
|
|
} else {
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// Info returns the FileInfo for the file or subdirectory described by the entry.
|
|
func (de DirEntry) Info() (fs.FileInfo, error) {
|
|
return FileInfo{
|
|
name: de.path,
|
|
size: de.size,
|
|
modtime: de.modtime,
|
|
mode: de.Type(),
|
|
isDir: de.IsDir(),
|
|
}, nil
|
|
}
|
|
|
|
func (de DirEntry) String() string {
|
|
var isDirChar rune
|
|
if de.IsDir() {
|
|
isDirChar = 'd'
|
|
} else {
|
|
isDirChar = '-'
|
|
}
|
|
|
|
// Get human-readable value for file size
|
|
val, unit := bytesHuman(de.size)
|
|
prec := 0
|
|
// If value is less than 10, set precision to 1
|
|
if val < 10 {
|
|
prec = 1
|
|
}
|
|
// Convert float to string
|
|
valStr := strconv.FormatFloat(val, 'f', prec, 64)
|
|
|
|
// Return string formatted like so:
|
|
// - 10 kB file
|
|
// or:
|
|
// d 0 B .
|
|
return fmt.Sprintf(
|
|
"%c %3s %-2s %s",
|
|
isDirChar,
|
|
valStr,
|
|
unit,
|
|
de.path,
|
|
)
|
|
}
|
|
|
|
func bytesHuman(b uint32) (float64, string) {
|
|
const unit = 1000
|
|
// Set possible unit prefixes (PineTime flash is 4MB)
|
|
units := [2]rune{'k', 'M'}
|
|
// If amount of bytes is less than smallest unit
|
|
if b < unit {
|
|
// Return unchanged with unit "B"
|
|
return float64(b), "B"
|
|
}
|
|
|
|
div, exp := uint32(unit), 0
|
|
// Get decimal values and unit prefix index
|
|
for n := b / unit; n >= unit; n /= unit {
|
|
div *= unit
|
|
exp++
|
|
}
|
|
|
|
// Create string for full unit
|
|
unitStr := string([]rune{units[exp], 'B'})
|
|
|
|
// Return decimal with unit string
|
|
return float64(b) / float64(div), unitStr
|
|
}
|
|
|
|
// FileInfo implements fs.FileInfo
|
|
type FileInfo struct {
|
|
name string
|
|
size uint32
|
|
modtime uint64
|
|
mode fs.FileMode
|
|
isDir bool
|
|
}
|
|
|
|
// Name returns the base name of the file
|
|
func (fi FileInfo) Name() string {
|
|
return fi.name
|
|
}
|
|
|
|
// Size returns the total size of the file
|
|
func (fi FileInfo) Size() int64 {
|
|
return int64(fi.size)
|
|
}
|
|
|
|
// Mode returns the mode of the file
|
|
func (fi FileInfo) Mode() fs.FileMode {
|
|
return fi.mode
|
|
}
|
|
|
|
// ModTime returns the modification time of the file
|
|
// As of now, this is unimplemented in InfiniTime, and
|
|
// will always return 0.
|
|
func (fi FileInfo) ModTime() time.Time {
|
|
return time.Unix(0, int64(fi.modtime))
|
|
}
|
|
|
|
// IsDir returns whether the file is a directory
|
|
func (fi FileInfo) IsDir() bool {
|
|
return fi.isDir
|
|
}
|
|
|
|
// Sys is unimplemented and returns nil
|
|
func (fi FileInfo) Sys() any {
|
|
return nil
|
|
}
|