package lib import ( "errors" "farga/db/types" "fmt" "reflect" "unicode/utf8" ) // prepends item to slice func Prepend[T any](slice []T, item T) []T { return append([]T{item}, slice...) } // returns the size in a nice format. e.g "428KiB" func Size(data []byte) string { var sizes = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB"} // i don't think we need more than this var size = float32(len(data)) var level = 1 for size > 1024 { size = (size / 1024) level++ } return fmt.Sprint(size, sizes[level-1]) } // returns the time. feed it seconds. e.g "12 mins.", "14 hours". func FormatTime(seconds int) string { const ( minute = 60 hour = 60 * minute ) switch { case seconds >= hour: n := seconds / hour return fmt.Sprintf("%d hour%s.", n, Plural(n)) case seconds >= minute: n := seconds / minute return fmt.Sprintf("%d min%s.", n, Plural(n)) default: return fmt.Sprintf("%d sec%s.", seconds, Plural(seconds)) } } // returns an "s" if n > 1. func Plural(n int) string { if n == 1 { return "" } return "s" } // is it rangeable? can you run {{range .}} or foreach? func IsRangeable(v interface{}) bool { if v == nil { return false } rv := reflect.ValueOf(v) switch rv.Kind() { case reflect.Slice, reflect.Array, reflect.Map, reflect.Chan: return true default: return false } } // shortens a string to n characters. func TruncateString(s string, n int) (string, error) { // if it tries to truncate strings shorter than n, return the entire string. if utf8.RuneCountInString(s) < n { return "", errors.New("Invalid truncate index: larger than string.") } if n < 0 { return "", errors.New("Invalid truncate index: lower than zero.") } return s[:n], nil } // gets the root of a repo as it would be accessed from an URL. func RepoRoot(meta types.Repo) string { user := meta.User.Handle name := meta.Name return "/~" + user + "/" + name }