File: alternate

package info (click to toggle)
golang-github-digitalocean-go-qemu 0.0~git20200529.1b453d0-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,264 kB
  • sloc: sh: 34; makefile: 7
file content (96 lines) | stat: -rw-r--r-- 3,236 bytes parent folder | download | duplicates (3)
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))
}