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
|
{{/*
There are very few alternates in the API, but one of them
(BlockDevRef) is quite tricky, because it references a flat union as
one of its implementations. So, a lot of this logic is specific to
supporting flat unions as implementations of an alternate.
*/}}
{{ $basename := .Name.Go }}
// {{ .Name }} -> {{ $basename }} (alternate)
// {{ $basename }} implements the "{{ .Name }}" QMP API type.
//
// Can be one of:
{{- range $suffix, $type := .Options }}
// - {{ $basename }}{{ $suffix.Go }}
{{- end }}
type {{ $basename }} interface {
is{{ $basename }}()
}
{{- range $suffix, $type := .Options }}
{{ $subname := printf "%s%s" $basename $suffix.Go }}
{{- if $type.NullType }}
// {{ $subname }} is a JSON null type, so it must
// also implement the isNullable interface.
type {{ $subname }} struct {}
func ({{ $subname }}) isNull() bool { return true }
{{- else }}
// {{ $subname }} is an implementation of {{ $basename }}
type {{ $subname }} {{ $type.Go }}
{{- end }}
{{- if eq (typeOf (index API $type)) "flatunion" }}
{{ $u := index API $type }}
{{- range $suffix, $type := $u.Options }}
func ({{ $u.Name.Go }}{{ $suffix.Go }}) is{{ $basename }}() {}
{{- end }}
{{- else }}
func ({{ $subname }}) is{{ $basename }}() {}
{{- end }}
{{- end }}
func decode{{ $basename }}(bs json.RawMessage) ({{ $basename }}, error) {
{{/*
Unfortunately, we have to range through the types three times in order
for us to do the type discovery via unmarshalling in the correct order
*/}}
{{- range $suffix, $type := .Options }}
{{- if $type.NullType }}
// Always try unmarshalling for nil first if it's an option
// because other types could unmarshal successfully in the case
// where a Null json type was provided.
var {{ $suffix }} *int
if err := json.Unmarshal([]byte(bs), &{{ $suffix }}); err == nil {
if {{ $suffix }} == nil {
return {{ printf "%s%s" $basename $suffix.Go }}{}, nil
}
}
{{- end }}
{{- end }}
{{- range $suffix, $type := .Options }}
{{- if $type.SimpleType }}
var {{ $suffix }} {{ printf "%s%s" $basename $suffix.Go }}
if err := json.Unmarshal([]byte(bs), &{{ $suffix }}); err == nil {
return {{ $suffix }}, nil
}
{{- end }}
{{- end }}
{{- range $suffix, $type := .Options }}
{{- if not $type.NullType }}
{{- if not $type.SimpleType }}
{{ $subtype := index API $type }}
{{- if eq (typeOf $subtype) "flatunion" }}
if {{ $suffix }}, err := decode{{ $type.Go }}([]byte(bs)); err == nil {
switch impl := {{ $suffix }}.(type) {
{{- range $suffix, $type := $subtype.Options }}
case {{ $subtype.Name.Go }}{{ $suffix.Go }}:
return impl, nil
{{- end }}
}
}
{{- else }}
var {{ $suffix }} {{ printf "%s%s" $basename $suffix.Go }}
if err := json.Unmarshal([]byte(bs), &{{ $suffix }}); err == nil {
return {{ $suffix }}, nil
}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
return nil, fmt.Errorf("unable to decode %q as a {{ $basename }}", string(bs))
}
|