rclone/backend/s3/gen_setfrom.go

102 lines
2.7 KiB
Go

// Generate boilerplate code for setting similar structs from each other
//go:build ignore
package main
import (
"flag"
"fmt"
"io"
"log"
"os"
"reflect"
"strings"
"github.com/aws/aws-sdk-go/service/s3"
)
// flags
var (
outputFile = flag.String("o", "", "Output file name, stdout if unset")
)
// globals
var (
out io.Writer = os.Stdout
)
// genSetFrom generates code to set the public members of a from b
//
// a and b should be pointers to structs
//
// a can be a different type from b
//
// Only the Fields which have the same name and assignable type on a
// and b will be set.
//
// This is useful for copying between almost identical structures that
// are frequently present in auto-generated code for cloud storage
// interfaces.
func genSetFrom(a, b interface{}) {
name := fmt.Sprintf("setFrom_%T_%T", a, b)
name = strings.Replace(name, ".", "", -1)
name = strings.Replace(name, "*", "", -1)
fmt.Fprintf(out, "\n// %s copies matching elements from a to b\n", name)
fmt.Fprintf(out, "func %s(a %T, b %T) {\n", name, a, b)
ta := reflect.TypeOf(a).Elem()
tb := reflect.TypeOf(b).Elem()
va := reflect.ValueOf(a).Elem()
vb := reflect.ValueOf(b).Elem()
for i := 0; i < tb.NumField(); i++ {
bField := vb.Field(i)
tbField := tb.Field(i)
name := tbField.Name
aField := va.FieldByName(name)
taField, found := ta.FieldByName(name)
if found && aField.IsValid() && bField.IsValid() && aField.CanSet() && tbField.Type.AssignableTo(taField.Type) {
fmt.Fprintf(out, "\ta.%s = b.%s\n", name, name)
}
}
fmt.Fprintf(out, "}\n")
}
func main() {
flag.Parse()
if *outputFile != "" {
fd, err := os.Create(*outputFile)
if err != nil {
log.Fatal(err)
}
defer func() {
err := fd.Close()
if err != nil {
log.Fatal(err)
}
}()
out = fd
}
fmt.Fprintf(out, `// Code generated by "go run gen_setfrom.go"; DO NOT EDIT.
package s3
import "github.com/aws/aws-sdk-go/service/s3"
`)
genSetFrom(new(s3.ListObjectsInput), new(s3.ListObjectsV2Input))
genSetFrom(new(s3.ListObjectsV2Output), new(s3.ListObjectsOutput))
genSetFrom(new(s3.ListObjectVersionsInput), new(s3.ListObjectsV2Input))
genSetFrom(new(s3.ObjectVersion), new(s3.DeleteMarkerEntry))
genSetFrom(new(s3.ListObjectsV2Output), new(s3.ListObjectVersionsOutput))
genSetFrom(new(s3.Object), new(s3.ObjectVersion))
genSetFrom(new(s3.CreateMultipartUploadInput), new(s3.HeadObjectOutput))
genSetFrom(new(s3.CreateMultipartUploadInput), new(s3.CopyObjectInput))
genSetFrom(new(s3.UploadPartCopyInput), new(s3.CopyObjectInput))
genSetFrom(new(s3.HeadObjectOutput), new(s3.GetObjectOutput))
genSetFrom(new(s3.CreateMultipartUploadInput), new(s3.PutObjectInput))
genSetFrom(new(s3.HeadObjectOutput), new(s3.PutObjectInput))
genSetFrom(new(s3.CopyObjectInput), new(s3.PutObjectInput))
}