github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/types/query/pagination.go (about) 1 package query 2 3 import ( 4 "fmt" 5 6 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 7 8 "google.golang.org/grpc/codes" 9 "google.golang.org/grpc/status" 10 ) 11 12 // DefaultLimit is the default `limit` for queries 13 // if the `limit` is not supplied, paginate will use `DefaultLimit` 14 const DefaultLimit = 100 15 16 // ParsePagination validate PageRequest and returns page number & limit. 17 func ParsePagination(pageReq *PageRequest) (page, limit int, err error) { 18 offset := 0 19 limit = DefaultLimit 20 21 if pageReq != nil { 22 offset = int(pageReq.Offset) 23 limit = int(pageReq.Limit) 24 } 25 if offset < 0 { 26 return 1, 0, status.Error(codes.InvalidArgument, "offset must greater than 0") 27 } 28 29 if limit < 0 { 30 return 1, 0, status.Error(codes.InvalidArgument, "limit must greater than 0") 31 } else if limit == 0 { 32 limit = DefaultLimit 33 } 34 35 page = offset/limit + 1 36 37 return page, limit, nil 38 } 39 40 // Paginate does pagination of all the results in the PrefixStore based on the 41 // provided PageRequest. onResult should be used to do actual unmarshaling. 42 func Paginate( 43 prefixStore types.KVStore, 44 pageRequest *PageRequest, 45 onResult func(key []byte, value []byte) error, 46 ) (*PageResponse, error) { 47 48 // if the PageRequest is nil, use default PageRequest 49 if pageRequest == nil { 50 pageRequest = &PageRequest{} 51 } 52 53 offset := pageRequest.Offset 54 key := pageRequest.Key 55 limit := pageRequest.Limit 56 countTotal := pageRequest.CountTotal 57 58 if offset > 0 && key != nil { 59 return nil, fmt.Errorf("invalid request, either offset or key is expected, got both") 60 } 61 62 if limit == 0 { 63 limit = DefaultLimit 64 65 // count total results when the limit is zero/not supplied 66 countTotal = true 67 } 68 69 if len(key) != 0 { 70 iterator := prefixStore.Iterator(key, nil) 71 defer iterator.Close() 72 73 var count uint64 74 var nextKey []byte 75 76 for ; iterator.Valid(); iterator.Next() { 77 if count == limit { 78 nextKey = iterator.Key() 79 break 80 } 81 if iterator.Error() != nil { 82 return nil, iterator.Error() 83 } 84 err := onResult(iterator.Key(), iterator.Value()) 85 if err != nil { 86 return nil, err 87 } 88 89 count++ 90 } 91 92 return &PageResponse{ 93 NextKey: nextKey, 94 }, nil 95 } 96 97 iterator := prefixStore.Iterator(nil, nil) 98 defer iterator.Close() 99 100 end := offset + limit 101 102 var count uint64 103 var nextKey []byte 104 105 for ; iterator.Valid(); iterator.Next() { 106 count++ 107 108 if count <= offset { 109 continue 110 } 111 if count <= end { 112 err := onResult(iterator.Key(), iterator.Value()) 113 if err != nil { 114 return nil, err 115 } 116 } else if count == end+1 { 117 nextKey = iterator.Key() 118 119 if !countTotal { 120 break 121 } 122 } 123 if iterator.Error() != nil { 124 return nil, iterator.Error() 125 } 126 } 127 128 res := &PageResponse{NextKey: nextKey} 129 if countTotal { 130 res.Total = count 131 } 132 133 return res, nil 134 } 135 136 func NewPaginateFromPageLimit(page, limit int) *PageRequest { 137 var offset uint64 138 if page > 1 { 139 offset = uint64((page - 1) * limit) 140 } 141 142 if limit <= 0 { 143 limit = DefaultLimit 144 } 145 146 return &PageRequest{ 147 Key: nil, 148 Offset: offset, 149 Limit: uint64(limit), 150 CountTotal: true, 151 } 152 }