package util import ( "bufio" "crypto/sha256" "errors" "fmt" "io" "os" "strings" "net/url" "path/filepath" "golang.org/x/term" ) func Assert(condition bool) { if !condition { panic("assertion failed!") } } func Dirents(dir string) (entries []string, err error) { d, err := os.Open(dir) if err != nil { return nil, errors.New(err.Error()) } names, err := d.Readdirnames(0) if err != nil { return nil, errors.New(err.Error()) } for _, e := range names { entries = append(entries, e) } return } func DoChunks(f io.Reader, fun func (buf []byte)) (err error) { err = nil bytes, chunks := int64(0), int64(0) r := bufio.NewReader(f) buf := make([]byte, 0, 4*1024) for { var n int n, err = r.Read(buf[:cap(buf)]) buf = buf[:n] if n == 0 { if err == nil { continue } if err == io.EOF { break } return } chunks++ bytes += int64(len(buf)) Assert(n == len(buf)) fun(buf) if err != nil && err != io.EOF { return } } return } func EscapePath(path string) string { return strings.ReplaceAll(url.QueryEscape(path), "%2F", "/") } func HashOf(s string) string { h := sha256.New() h.Write([]byte(s)) return fmt.Sprintf("%x", h.Sum(nil)) } // print only if interactive func Iprint(format string, args ...any) { if term.IsTerminal(int(os.Stderr.Fd())) { fmt.Fprintf(os.Stderr, format, args...) } } func MapToValues[Map ~map[K]V, K comparable, V any](m Map) (values []V) { for _, v := range m { values = append(values, v) } return } func OptionalString(cond bool, s string) string { if cond { return s } return "" } func Warn(format string, args ...any) { fmt.Fprintf(os.Stderr, "%s: %s\n", filepath.Base(os.Args[0]), fmt.Sprintf(format, args...)) } func Die(format string, args ...any) { Warn(format, args...) os.Exit(1) }