itd/infinitime/fstypes.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
}