github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/backend/s3/gen_setfrom.go (about)

     1  // Generate boilerplate code for setting similar structs from each other
     2  
     3  //go:build ignore
     4  
     5  package main
     6  
     7  import (
     8  	"flag"
     9  	"fmt"
    10  	"io"
    11  	"log"
    12  	"os"
    13  	"reflect"
    14  	"strings"
    15  
    16  	"github.com/aws/aws-sdk-go/service/s3"
    17  )
    18  
    19  // flags
    20  var (
    21  	outputFile = flag.String("o", "", "Output file name, stdout if unset")
    22  )
    23  
    24  // globals
    25  var (
    26  	out io.Writer = os.Stdout
    27  )
    28  
    29  // genSetFrom generates code to set the public members of a from b
    30  //
    31  // a and b should be pointers to structs
    32  //
    33  // a can be a different type from b
    34  //
    35  // Only the Fields which have the same name and assignable type on a
    36  // and b will be set.
    37  //
    38  // This is useful for copying between almost identical structures that
    39  // are frequently present in auto-generated code for cloud storage
    40  // interfaces.
    41  func genSetFrom(a, b interface{}) {
    42  	name := fmt.Sprintf("setFrom_%T_%T", a, b)
    43  	name = strings.Replace(name, ".", "", -1)
    44  	name = strings.Replace(name, "*", "", -1)
    45  	fmt.Fprintf(out, "\n// %s copies matching elements from a to b\n", name)
    46  	fmt.Fprintf(out, "func %s(a %T, b %T) {\n", name, a, b)
    47  	ta := reflect.TypeOf(a).Elem()
    48  	tb := reflect.TypeOf(b).Elem()
    49  	va := reflect.ValueOf(a).Elem()
    50  	vb := reflect.ValueOf(b).Elem()
    51  	for i := 0; i < tb.NumField(); i++ {
    52  		bField := vb.Field(i)
    53  		tbField := tb.Field(i)
    54  		name := tbField.Name
    55  		aField := va.FieldByName(name)
    56  		taField, found := ta.FieldByName(name)
    57  		if found && aField.IsValid() && bField.IsValid() && aField.CanSet() && tbField.Type.AssignableTo(taField.Type) {
    58  			fmt.Fprintf(out, "\ta.%s = b.%s\n", name, name)
    59  		}
    60  	}
    61  	fmt.Fprintf(out, "}\n")
    62  }
    63  
    64  func main() {
    65  	flag.Parse()
    66  
    67  	if *outputFile != "" {
    68  		fd, err := os.Create(*outputFile)
    69  		if err != nil {
    70  			log.Fatal(err)
    71  		}
    72  		defer func() {
    73  			err := fd.Close()
    74  			if err != nil {
    75  				log.Fatal(err)
    76  			}
    77  		}()
    78  		out = fd
    79  	}
    80  
    81  	fmt.Fprintf(out, `// Code generated by "go run gen_setfrom.go"; DO NOT EDIT.
    82  
    83  package s3
    84  
    85  import "github.com/aws/aws-sdk-go/service/s3"
    86  `)
    87  
    88  	genSetFrom(new(s3.ListObjectsInput), new(s3.ListObjectsV2Input))
    89  	genSetFrom(new(s3.ListObjectsV2Output), new(s3.ListObjectsOutput))
    90  	genSetFrom(new(s3.ListObjectVersionsInput), new(s3.ListObjectsV2Input))
    91  	genSetFrom(new(s3.ObjectVersion), new(s3.DeleteMarkerEntry))
    92  	genSetFrom(new(s3.ListObjectsV2Output), new(s3.ListObjectVersionsOutput))
    93  	genSetFrom(new(s3.Object), new(s3.ObjectVersion))
    94  	genSetFrom(new(s3.CreateMultipartUploadInput), new(s3.HeadObjectOutput))
    95  	genSetFrom(new(s3.CreateMultipartUploadInput), new(s3.CopyObjectInput))
    96  	genSetFrom(new(s3.UploadPartCopyInput), new(s3.CopyObjectInput))
    97  	genSetFrom(new(s3.HeadObjectOutput), new(s3.GetObjectOutput))
    98  	genSetFrom(new(s3.CreateMultipartUploadInput), new(s3.PutObjectInput))
    99  	genSetFrom(new(s3.HeadObjectOutput), new(s3.PutObjectInput))
   100  	genSetFrom(new(s3.CopyObjectInput), new(s3.PutObjectInput))
   101  }