feat: added chunk and slice operations
parent
d39c7860c3
commit
ae59cd6088
@ -0,0 +1,55 @@
|
|||||||
|
package operation
|
||||||
|
|
||||||
|
import "github.com/aziis98/cabret"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registerType("chunk", &Chunk{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chunk is a list operation that will group incoming items in groups of the given size
|
||||||
|
type Chunk struct {
|
||||||
|
Count int
|
||||||
|
SkipRemaining bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (op *Chunk) Configure(options map[string]any) error {
|
||||||
|
var err error
|
||||||
|
op.Count, err = getKey[int](options, "size")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
op.SkipRemaining, err = getKey(options, "skip_remaining", false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (op *Chunk) ProcessList(items []cabret.Content) ([]cabret.Content, error) {
|
||||||
|
totalPages := len(items) / op.Count
|
||||||
|
|
||||||
|
chunks := make([][]cabret.Content, totalPages, totalPages+1)
|
||||||
|
|
||||||
|
for i := 0; i < totalPages; i++ {
|
||||||
|
chunks = append(chunks, items[i*op.Count:(i+1)*op.Count])
|
||||||
|
}
|
||||||
|
|
||||||
|
if !op.SkipRemaining {
|
||||||
|
chunks = append(chunks, items[totalPages*op.Count:])
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]cabret.Content, len(chunks))
|
||||||
|
for i, chunk := range chunks {
|
||||||
|
result[i] = cabret.Content{
|
||||||
|
Type: cabret.MetadataOnly,
|
||||||
|
Metadata: cabret.Map{
|
||||||
|
"Page": i + 1,
|
||||||
|
"TotalPages": totalPages,
|
||||||
|
"Items": chunk,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package operation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aziis98/cabret"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registerType("slice", &Slice{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slice is a [cabret.ListOperation] will return a slice of the incoming items.
|
||||||
|
// Both indices can be negative and will wrap around the items list.
|
||||||
|
// For example "&Slice{From: -1, To: 0}" will reverse the incoming items list.
|
||||||
|
type Slice struct {
|
||||||
|
From, To int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure will configure this operation
|
||||||
|
//
|
||||||
|
// from: <start index> # inclusive, optional and defaults to the start
|
||||||
|
// to: <end index> # exclusive, optional and defaults to the end
|
||||||
|
func (op *Slice) Configure(options map[string]any) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
op.From, err = getKey(options, "from", 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
op.To, err = getKey(options, "to", -1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (op *Slice) ProcessList(items []cabret.Content) ([]cabret.Content, error) {
|
||||||
|
from := op.From
|
||||||
|
to := op.To
|
||||||
|
|
||||||
|
if to < 0 {
|
||||||
|
to = to + len(items) + 1
|
||||||
|
}
|
||||||
|
if from < 0 {
|
||||||
|
reverse(items)
|
||||||
|
from = from + len(items) + 1
|
||||||
|
from, to = to, from
|
||||||
|
}
|
||||||
|
|
||||||
|
return items[from:to], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// utilities
|
||||||
|
//
|
||||||
|
|
||||||
|
// reverse taken from this answer https://stackoverflow.com/questions/28058278/how-do-i-reverse-a-slice-in-go
|
||||||
|
func reverse[S ~[]E, E any](s S) {
|
||||||
|
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
s[i], s[j] = s[j], s[i]
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue