feat: added chunk and slice operations

main
Antonio De Lucreziis 2 years ago
parent d39c7860c3
commit ae59cd6088

@ -22,6 +22,9 @@ type File struct {
Content
}
// MetadataOnly is a mime type representing an item that only holds metadata
const MetadataOnly = "metadata-only"
type Content struct {
// Type for known content formats is just the mime-type
Type string
@ -34,15 +37,15 @@ type Content struct {
}
type Operation interface {
Configure(config map[string]any) error
Configure(options map[string]any) error
}
type ListOperation interface {
Operation
ProcessList(contents []Content) ([]Content, error)
ProcessList(items []Content) ([]Content, error)
}
type ItemOperation interface {
Operation
ProcessItem(content Content) (*Content, error)
ProcessItem(item Content) (*Content, error)
}

@ -18,8 +18,10 @@ require (
github.com/yuin/goldmark v1.5.3 // indirect
github.com/yuin/goldmark-meta v1.1.0 // indirect
golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
golang.org/x/tools v0.4.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools v2.2.0+incompatible // indirect

@ -35,6 +35,8 @@ github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUei
github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0=
golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15 h1:5oN1Pz/eDhCpbMbLstvIPa0b/BEQo6g6nwV3pLjfM6w=
golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -45,6 +47,8 @@ golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

@ -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…
Cancel
Save