zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/pkg/extensions/search/pagination/repo_pagination.go (about) 1 package pagination 2 3 import ( 4 "fmt" 5 "sort" 6 7 zerr "zotregistry.dev/zot/errors" 8 zcommon "zotregistry.dev/zot/pkg/common" 9 gql_gen "zotregistry.dev/zot/pkg/extensions/search/gql_generated" 10 ) 11 12 type RepoSummariesPageFinder struct { 13 limit int 14 offset int 15 sortBy SortCriteria 16 pageBuffer []*gql_gen.RepoSummary 17 } 18 19 func NewRepoSumPageFinder(limit, offset int, sortBy SortCriteria) (*RepoSummariesPageFinder, error) { 20 if sortBy == "" { 21 sortBy = AlphabeticAsc 22 } 23 24 if limit < 0 { 25 return nil, zerr.ErrLimitIsNegative 26 } 27 28 if offset < 0 { 29 return nil, zerr.ErrOffsetIsNegative 30 } 31 32 if _, found := RepoSumSortFuncs()[sortBy]; !found { 33 return nil, fmt.Errorf("sorting repos by '%s' is not supported %w", 34 sortBy, zerr.ErrSortCriteriaNotSupported) 35 } 36 37 return &RepoSummariesPageFinder{ 38 limit: limit, 39 offset: offset, 40 sortBy: sortBy, 41 pageBuffer: []*gql_gen.RepoSummary{}, 42 }, nil 43 } 44 45 func (pf *RepoSummariesPageFinder) Add(imgSum *gql_gen.RepoSummary) { 46 pf.pageBuffer = append(pf.pageBuffer, imgSum) 47 } 48 49 func (pf *RepoSummariesPageFinder) Page() ([]*gql_gen.RepoSummary, zcommon.PageInfo) { 50 if len(pf.pageBuffer) == 0 { 51 return []*gql_gen.RepoSummary{}, zcommon.PageInfo{} 52 } 53 54 pageInfo := zcommon.PageInfo{} 55 56 sort.Slice(pf.pageBuffer, RepoSumSortFuncs()[pf.sortBy](pf.pageBuffer)) 57 58 // the offset and limit are calculated in terms of repos counted 59 start := pf.offset 60 end := pf.offset + pf.limit 61 62 // we'll return an empty array when the offset is greater than the number of elements 63 if start >= len(pf.pageBuffer) { 64 start = len(pf.pageBuffer) 65 end = start 66 } 67 68 if end >= len(pf.pageBuffer) { 69 end = len(pf.pageBuffer) 70 } 71 72 page := pf.pageBuffer[start:end] 73 74 pageInfo.ItemCount = len(page) 75 76 if start == 0 && end == 0 { 77 page = pf.pageBuffer 78 pageInfo.ItemCount = len(page) 79 } 80 81 pageInfo.TotalCount = len(pf.pageBuffer) 82 83 return page, pageInfo 84 } 85 86 func RepoSumSortFuncs() map[SortCriteria]func(pageBuffer []*gql_gen.RepoSummary) func(i, j int) bool { 87 return map[SortCriteria]func(pageBuffer []*gql_gen.RepoSummary) func(i, j int) bool{ 88 AlphabeticAsc: RepoSortByAlphabeticAsc, 89 AlphabeticDsc: RepoSortByAlphabeticDsc, 90 Relevance: RepoSortByRelevance, 91 UpdateTime: RepoSortByUpdateTime, 92 Downloads: RepoSortByDownloads, 93 } 94 } 95 96 func RepoSortByAlphabeticAsc(pageBuffer []*gql_gen.RepoSummary) func(i, j int) bool { 97 return func(i, j int) bool { 98 return *pageBuffer[i].Name < *pageBuffer[j].Name 99 } 100 } 101 102 func RepoSortByAlphabeticDsc(pageBuffer []*gql_gen.RepoSummary) func(i, j int) bool { 103 return func(i, j int) bool { 104 return *pageBuffer[i].Name > *pageBuffer[j].Name 105 } 106 } 107 108 func RepoSortByRelevance(pageBuffer []*gql_gen.RepoSummary) func(i, j int) bool { 109 return func(i, j int) bool { 110 return *pageBuffer[i].Rank < *pageBuffer[j].Rank 111 } 112 } 113 114 // SortByUpdateTime sorting descending by time. 115 func RepoSortByUpdateTime(pageBuffer []*gql_gen.RepoSummary) func(i, j int) bool { 116 return func(i, j int) bool { 117 return pageBuffer[i].LastUpdated.After(*pageBuffer[j].LastUpdated) 118 } 119 } 120 121 // SortByDownloads returns a comparison function for descendant sorting by downloads. 122 func RepoSortByDownloads(pageBuffer []*gql_gen.RepoSummary) func(i, j int) bool { 123 return func(i, j int) bool { 124 return *pageBuffer[i].DownloadCount > *pageBuffer[j].DownloadCount 125 } 126 }