diff --git a/modules/caddyhttp/fileserver/browsetplcontext.go b/modules/caddyhttp/fileserver/browsetplcontext.go index b9489c6a6dc..eb4828e3af4 100644 --- a/modules/caddyhttp/fileserver/browsetplcontext.go +++ b/modules/caddyhttp/fileserver/browsetplcontext.go @@ -15,6 +15,7 @@ package fileserver import ( + "cmp" "context" "io/fs" "net/url" @@ -22,7 +23,6 @@ import ( "path" "path/filepath" "slices" - "sort" "strconv" "strings" "time" @@ -221,28 +221,19 @@ func (l *browseTemplateContext) applySortAndLimit(sortParam, orderParam, limitPa l.Sort = sortParam l.Order = orderParam + switch l.Sort { + case sortByName: + slices.SortFunc(l.Items, compareByName) + case sortByNameDirFirst: + slices.SortFunc(l.Items, compareByNameDirFirst) + case sortBySize: + slices.SortFunc(l.Items, compareBySize) + case sortByTime: + slices.SortFunc(l.Items, compareByTime) + } + if l.Order == "desc" { - switch l.Sort { - case sortByName: - sort.Sort(sort.Reverse(byName(*l))) - case sortByNameDirFirst: - sort.Sort(sort.Reverse(byNameDirFirst(*l))) - case sortBySize: - sort.Sort(sort.Reverse(bySize(*l))) - case sortByTime: - sort.Sort(sort.Reverse(byTime(*l))) - } - } else { - switch l.Sort { - case sortByName: - sort.Sort(byName(*l)) - case sortByNameDirFirst: - sort.Sort(byNameDirFirst(*l)) - case sortBySize: - sort.Sort(bySize(*l)) - case sortByTime: - sort.Sort(byTime(*l)) - } + slices.Reverse(l.Items) } if offsetParam != "" { @@ -318,59 +309,44 @@ func (fi fileInfo) HumanModTime(format string) string { return fi.ModTime.Format(format) } -type ( - byName browseTemplateContext - byNameDirFirst browseTemplateContext - bySize browseTemplateContext - byTime browseTemplateContext -) - -func (l byName) Len() int { return len(l.Items) } -func (l byName) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i] } - -func (l byName) Less(i, j int) bool { - return strings.ToLower(l.Items[i].Name) < strings.ToLower(l.Items[j].Name) +func compareByName(a, b fileInfo) int { + return cmp.Compare(strings.ToLower(a.Name), strings.ToLower(b.Name)) } -func (l byNameDirFirst) Len() int { return len(l.Items) } -func (l byNameDirFirst) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i] } - -func (l byNameDirFirst) Less(i, j int) bool { - // sort by name if both are dir or file - if l.Items[i].IsDir == l.Items[j].IsDir { - return strings.ToLower(l.Items[i].Name) < strings.ToLower(l.Items[j].Name) +func compareByNameDirFirst(a, b fileInfo) int { + if a.IsDir != b.IsDir { + if a.IsDir { + return -1 + } + return 1 } - // sort dir ahead of file - return l.Items[i].IsDir + return cmp.Compare(strings.ToLower(a.Name), strings.ToLower(b.Name)) } -func (l bySize) Len() int { return len(l.Items) } -func (l bySize) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i] } - -func (l bySize) Less(i, j int) bool { +func compareBySize(a, b fileInfo) int { const directoryOffset = -1 << 31 // = -math.MinInt32 - iSize, jSize := l.Items[i].Size, l.Items[j].Size + aSize, bSize := a.Size, b.Size // directory sizes depend on the file system; to // provide a consistent experience, put them up front // and sort them by name - if l.Items[i].IsDir { - iSize = directoryOffset + if a.IsDir { + aSize = directoryOffset } - if l.Items[j].IsDir { - jSize = directoryOffset + if b.IsDir { + bSize = directoryOffset } - if l.Items[i].IsDir && l.Items[j].IsDir { - return strings.ToLower(l.Items[i].Name) < strings.ToLower(l.Items[j].Name) + if a.IsDir && b.IsDir { + return cmp.Compare(strings.ToLower(a.Name), strings.ToLower(b.Name)) } - return iSize < jSize + return cmp.Compare(aSize, bSize) } -func (l byTime) Len() int { return len(l.Items) } -func (l byTime) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i] } -func (l byTime) Less(i, j int) bool { return l.Items[i].ModTime.Before(l.Items[j].ModTime) } +func compareByTime(a, b fileInfo) int { + return a.ModTime.Compare(b.ModTime) +} const ( sortByName = "name"