package scanner // protocolTemplate is the template for generating WLTurbo-backed Go bindings. // // Generated objects embed wl.BaseProxy, send every request through // wl.Context.RequestArgs (typed arguments, no interface boxing; it owns // version checks, child registration and FD cleanup), and dispatch typed // events to registered handlers. Nothing in the generated code opens a // socket or frames messages itself: that is the transport's job. const protocolTemplate = `// Code generated by wlturbo-scanner. DO NOT EDIT. // Protocol: {{.Protocol}} // Source: {{.Source}} {{if .Copyright}} // Upstream protocol copyright and license: {{.Copyright}}{{end}} package {{.Package}} {{.ImportBlock}} {{range .Constants}} // {{.Name}} is the {{.Enum}} {{.Entry}} value. const {{.Name}}{{if .Type}} {{.Type}}{{end}} = {{.Value}} {{- end}} {{range .Interfaces}} {{- $iface := .}} // {{$iface.GoName}}Interface is the protocol interface name. const {{$iface.GoName}}Interface = "{{$iface.Name}}" // {{$iface.GoName}} is the generated binding for {{$iface.Name}} version {{$iface.Version}}. type {{$iface.GoName}} struct { wl.BaseProxy {{- if $iface.HasEvents}} // handlersMu guards the handler slices: a client may register or replace // handlers while another goroutine dispatches events. handlersMu sync.Mutex {{- end}} {{- range $iface.Events}} {{.HandlerField}} []func({{.HandlerParams}}) {{- end}} } // New{{$iface.GoName}} returns an unbound {{$iface.GoName}}. func New{{$iface.GoName}}(ctx *wl.Context) *{{$iface.GoName}} { obj := &{{$iface.GoName}}{} obj.SetContext(ctx) ctx.Register(obj) return obj } {{- range $iface.Requests}} {{- if .Doc}} // {{.Doc}} {{- end}} func (o *{{$iface.GoName}}) {{.GoName}}({{.Params}}) {{.Results}} { {{- range .ArgPreparations}} {{.}} {{- end}} {{- if .CreatesChild}} {{- if .ChildFactory}} {{.ChildVar}} := {{.ChildFactory}}(o.Context()) {{- else}} {{.ChildVar}} := &{{.ChildType}}{} {{.ChildVar}}.SetContext(o.Context()) {{- end}} {{- end}} if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: {{.Opcode}}, Name: "{{$iface.Name}}.{{.Name}}" {{- if gt .Since 1}}, Since: {{.Since}}{{end}} {{- if .Destructor}}, Destructor: true{{end}} {{- if .CreatesChild}}, Child: {{.ChildVar}}{{end}} {{- if .HasFDs}}, FDs: []int{ {{- .FDList -}} }{{end}}}{{.ArgList}}); err != nil { return {{.ErrorReturn}} } {{- if .CreatesChild}} return {{.ChildVar}}, nil {{- else}} return nil {{- end}} } {{- end}} {{- range $iface.Events}} // On{{.GoName}} registers a handler for the {{.Name}} event. // // Handlers are appended, so a second call adds another handler rather than // replacing the first. Registration is safe while another goroutine dispatches. func (o *{{$iface.GoName}}) On{{.GoName}}(handler func({{.HandlerParams}})) { if handler == nil { return } o.handlersMu.Lock() defer o.handlersMu.Unlock() o.{{.HandlerField}} = append(o.{{.HandlerField}}, handler) } // {{.HandlerAccessor}} returns the handlers registered for {{.Name}}, taken // under the lock so a handler may register another handler while events are // being dispatched. func (o *{{$iface.GoName}}) {{.HandlerAccessor}}() []func({{.HandlerParams}}) { o.handlersMu.Lock() defer o.handlersMu.Unlock() return o.{{.HandlerField}} } {{- end}} // EventSignature returns the declared event argument types in wire order. func (o *{{$iface.GoName}}) EventSignature(opcode uint16) (string, bool) { switch opcode { {{- range $iface.SignatureCases}} case {{.Opcode}}: return "{{.Signature}}", true {{- end}} default: return "", false } } // Dispatch decodes one event on {{$iface.Name}} and calls the registered handlers. func (o *{{$iface.GoName}}) Dispatch(event *wl.Event) { switch event.Opcode { {{- range $iface.Events}} case {{.Opcode}}: // {{.Name}} {{- range .DecodeLines}} {{.}} {{- end}} {{if .HasFD}}{{range .FDNames}}owned{{.}} := {{.}}; defer owned{{.}}.Close() {{end}}{{end}} for i, handler := range o.{{.HandlerAccessor}}() { {{- if .HasFD}} if i > 0 { {{range .FDNames}}{{.}} = nil; {{end}} } {{- else}} _ = i {{- end}} handler({{.HandlerArgs}}) } {{- if .ServerDestroy}} o.Context().Unregister(o) {{- end}} {{- end}} default: } } {{end}} `