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 }