github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/cmd/serve/s3/pager.go (about)

     1  // Package s3 implements a fake s3 server for rclone
     2  package s3
     3  
     4  import (
     5  	"sort"
     6  
     7  	"github.com/rclone/gofakes3"
     8  )
     9  
    10  // pager splits the object list into smulitply pages.
    11  func (db *s3Backend) pager(list *gofakes3.ObjectList, page gofakes3.ListBucketPage) (*gofakes3.ObjectList, error) {
    12  	// sort by alphabet
    13  	sort.Slice(list.CommonPrefixes, func(i, j int) bool {
    14  		return list.CommonPrefixes[i].Prefix < list.CommonPrefixes[j].Prefix
    15  	})
    16  	// sort by modtime
    17  	sort.Slice(list.Contents, func(i, j int) bool {
    18  		return list.Contents[i].LastModified.Before(list.Contents[j].LastModified.Time)
    19  	})
    20  	tokens := page.MaxKeys
    21  	if tokens == 0 {
    22  		tokens = 1000
    23  	}
    24  	if page.HasMarker {
    25  		for i, obj := range list.Contents {
    26  			if obj.Key == page.Marker {
    27  				list.Contents = list.Contents[i+1:]
    28  				break
    29  			}
    30  		}
    31  		for i, obj := range list.CommonPrefixes {
    32  			if obj.Prefix == page.Marker {
    33  				list.CommonPrefixes = list.CommonPrefixes[i+1:]
    34  				break
    35  			}
    36  		}
    37  	}
    38  
    39  	response := gofakes3.NewObjectList()
    40  	for _, obj := range list.CommonPrefixes {
    41  		if tokens <= 0 {
    42  			break
    43  		}
    44  		response.AddPrefix(obj.Prefix)
    45  		tokens--
    46  	}
    47  
    48  	for _, obj := range list.Contents {
    49  		if tokens <= 0 {
    50  			break
    51  		}
    52  		response.Add(obj)
    53  		tokens--
    54  	}
    55  
    56  	if len(list.CommonPrefixes)+len(list.Contents) > int(page.MaxKeys) {
    57  		response.IsTruncated = true
    58  		if len(response.Contents) > 0 {
    59  			response.NextMarker = response.Contents[len(response.Contents)-1].Key
    60  		} else {
    61  			response.NextMarker = response.CommonPrefixes[len(response.CommonPrefixes)-1].Prefix
    62  		}
    63  	}
    64  
    65  	return response, nil
    66  }