-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.go
127 lines (109 loc) · 3.75 KB
/
template.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package merge
const codeTemplate = `
// Code generated by go-merge-types. DO NOT EDIT.
package {{.Output.Package}}
import (
import_fmt "fmt"
import_sync "sync"
{{range $source := .Sources}}
{{$source.Package.Alias}} "{{$source.Package.ImportPath}}"
{{end}}
{{range $imp := .Output.Imports}}
{{$imp}}
{{end}}
)
// {{.Output.Type}} is a new type which can multiplex calls to different implementation types.
type {{.Output.Type}} struct {
{{range $index, $source := .Sources}}
typ{{$index}} *{{$source.Package.Alias}}.{{$source.Type}}
{{end}}
currTag string
mu import_sync.RWMutex
unsafe bool // default: false
}
// New{{.Output.Type}} creates a new merged type.
func New{{.Output.Type}}({{range $index, $arg := .Output.InitArgs}}{{if eq $index 0}}{{else}}, {{end}}{{$arg.Name}} {{$arg.Type}}{{end}}) (*{{.Output.Type}}, error) {
var (
mergedType {{.Output.Type}}
err error
)
mergedType.currTag = "{{.Output.DefaultTag}}"
{{range $sourceIndex, $source := .Sources}}
mergedType.typ{{$sourceIndex}}, err = {{$source.Package.Alias}}.New{{$source.Type}}({{range $argIndex, $arg := $source.InitArgs}}{{if eq $argIndex 0}}{{else}}, {{end}}{{$arg.Name}}{{end}})
if err != nil {
return nil, import_fmt.Errorf("failed to initialize {{$source.Package.Alias}}.{{$source.Type}}: %v", err)
}
{{end}}
return &mergedType, nil
}
// IsKnownTagFor{{.Output.Type}} tells if given tag is a known tag.
func IsKnownTagFor{{.Output.Type}}(tag string) bool {
{{range $tag := .Output.KnownTags}}
if tag == "{{$tag}}" {
return true
}
{{end}}
return false
}
// Use sets the used implementation to given tag.
func (merged *{{.Output.Type}}) Use(tag string) (changed bool) {
if !merged.unsafe {
merged.mu.Lock()
defer merged.mu.Unlock()
}
// use the default tag if the provided tag is unknown
if !IsKnownTagFor{{.Output.Type}}(tag) {
tag = "{{.Output.DefaultTag}}"
}
changed = merged.currTag != tag
merged.currTag = tag
return
}
// Unsafe disables the mutex.
func (merged *{{.Output.Type}}) Unsafe() {
merged.unsafe = true
}
// Safe enables the mutex.
func (merged *{{.Output.Type}}) Safe() {
merged.unsafe = false
}
{{range $method := .Output.Methods}}
{{if or $method.NoReturn $method.SingleReturn}}{{else}}
// {{$method.ReturnType.Name}} is a merged return type.
type {{$method.ReturnType.Name}} struct {
{{range $retField := $method.ReturnType.Fields}}
{{$retField.Name}} {{$retField.Type}}
{{end}}
}{{end}}
// {{$method.Name}} multiplexes to different implementations of the method.
func (merged *{{$.Output.Type}}) {{$method.Name}}({{range $index, $arg := $method.Args}}{{if eq $index 0}}{{else}}, {{end}}{{$arg.Name}} {{$arg.Type}}{{end}}) {{if $method.NoReturn}}(err error){{else}}(retVal {{if eq $method.SingleReturn false}}*{{end}}{{$method.ReturnType.Name}}, err error){{end}} {
if !merged.unsafe {
merged.mu.RLock()
defer merged.mu.RUnlock()
}
{{if eq $method.SingleReturn false}}{{if eq $method.NoReturn false}}
retVal = &{{$method.ReturnType.Name}}{}
{{end}}{{end}}
{{range $variation := $method.Variations}}
if merged.currTag == "{{$variation.Tag}}" {
{{if $variation.NoReturn}}{{else}}{{if $variation.OnlyError}}methodErr := {{else}}val, methodErr := {{end}}{{end}}merged.typ{{$variation.SourceIndex}}.{{$variation.Name}}({{range $index, $arg := $variation.Args}}{{if eq $index 0}}{{else}}, {{end}}{{$arg.Name}}{{end}})
{{if eq $variation.NoReturn false}}
if methodErr != nil {
err = methodErr
return
}{{end}}
{{if $method.SingleReturn}}
retVal = val
{{else}}
{{range $retField := $variation.ReturnedFields}}
retVal.{{$retField.Name}} = val{{if $variation.MergeReturnedStruct}}.{{$retField.Name}}{{else}}{{end}}
{{end}}
{{end}}
return
}
{{end}}
err = import_fmt.Errorf("{{$.Output.Type}}.{{$method.Name}} not implemented (tag=%s)", merged.currTag)
return
}
{{end}}
`