// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file is autogenerated by:
//     mojo/public/tools/bindings/mojom_bindings_generator.py
// For:
//     mojom/vanadium/discovery.mojom
//

package discovery

import (
	fmt "fmt"
	bindings "mojo/public/go/bindings"
	system "mojo/public/go/system"
	mojom_types "mojo/public/interfaces/bindings/mojom_types"
	service_describer "mojo/public/interfaces/bindings/service_describer"
	sort "sort"
)

// These IDs are the Mojom Identifiers / Type Keys.
// Mojom libraries importing this one will use these identifiers when building
// TypeReference objects.
var ID_discovery_Service__ string = "discovery_Service__"
var ID_discovery_Error__ string = "discovery_Error__"
var ID_discovery_Advertiser__ string = "discovery_Advertiser__"
var ID_discovery_Scanner__ string = "discovery_Scanner__"
var ID_discovery_ScanHandler__ string = "discovery_ScanHandler__"

var discoveryDesc__ = make(map[string]mojom_types.UserDefinedType)

func init() {
	discoveryDesc__["discovery_Service__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_Service__(),
	}
	discoveryDesc__["discovery_Error__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_Error__(),
	}
	discoveryDesc__["discovery_Advertiser__"] = &mojom_types.UserDefinedTypeInterfaceType{
		Value: discovery_Advertiser__(),
	}
	discoveryDesc__["discovery_Advertiser_Advertise_Params__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_Advertiser_Advertise_Params__(),
	}

	discoveryDesc__["discovery_Advertiser_Advertise_ResponseParams__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_Advertiser_Advertise_ResponseParams__(),
	}
	discoveryDesc__["discovery_Advertiser_Stop_Params__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_Advertiser_Stop_Params__(),
	}

	discoveryDesc__["discovery_Advertiser_Stop_ResponseParams__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_Advertiser_Stop_ResponseParams__(),
	}
	discoveryDesc__["discovery_Scanner__"] = &mojom_types.UserDefinedTypeInterfaceType{
		Value: discovery_Scanner__(),
	}
	discoveryDesc__["discovery_Scanner_Scan_Params__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_Scanner_Scan_Params__(),
	}

	discoveryDesc__["discovery_Scanner_Scan_ResponseParams__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_Scanner_Scan_ResponseParams__(),
	}
	discoveryDesc__["discovery_Scanner_Stop_Params__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_Scanner_Stop_Params__(),
	}

	discoveryDesc__["discovery_Scanner_Stop_ResponseParams__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_Scanner_Stop_ResponseParams__(),
	}
	discoveryDesc__["discovery_ScanHandler__"] = &mojom_types.UserDefinedTypeInterfaceType{
		Value: discovery_ScanHandler__(),
	}
	discoveryDesc__["discovery_ScanHandler_Found_Params__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_ScanHandler_Found_Params__(),
	}

	discoveryDesc__["discovery_ScanHandler_Lost_Params__"] = &mojom_types.UserDefinedTypeStructType{
		Value: discovery_ScanHandler_Lost_Params__(),
	}

}
func GetAllMojomTypeDefinitions() map[string]mojom_types.UserDefinedType {
	return discoveryDesc__
}

type Advertiser interface {
	Advertise(inService Service, inVisibility *[]string) (outHandle uint32, outInstanceId string, outErr *Error, err error)
	Stop(inH uint32) (outErr *Error, err error)
}

var advertiser_Name = "v23::discovery::Advertiser"

type Advertiser_Request bindings.InterfaceRequest

func (r *Advertiser_Request) Name() string {
	return advertiser_Name
}

type Advertiser_Pointer bindings.InterfacePointer

func (p *Advertiser_Pointer) Name() string {
	return advertiser_Name
}

type Advertiser_ServiceFactory struct {
	Delegate Advertiser_Factory
}

type Advertiser_Factory interface {
	Create(request Advertiser_Request)
}

func (f *Advertiser_ServiceFactory) Name() string {
	return advertiser_Name
}

func (f *Advertiser_ServiceFactory) ServiceDescription() service_describer.ServiceDescription {
	return &Advertiser_ServiceDescription{}
}

func (f *Advertiser_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
	request := Advertiser_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
	f.Delegate.Create(request)
}

// CreateMessagePipeForAdvertiser creates a message pipe for use with the
// Advertiser interface with a Advertiser_Request on one end and a Advertiser_Pointer on the other.
func CreateMessagePipeForAdvertiser() (Advertiser_Request, Advertiser_Pointer) {
	r, p := bindings.CreateMessagePipeForMojoInterface()
	return Advertiser_Request(r), Advertiser_Pointer(p)
}

const advertiser_Advertise_Name uint32 = 0
const advertiser_Stop_Name uint32 = 1

type Advertiser_Proxy struct {
	router *bindings.Router
	ids    bindings.Counter
}

func NewAdvertiserProxy(p Advertiser_Pointer, waiter bindings.AsyncWaiter) *Advertiser_Proxy {
	return &Advertiser_Proxy{
		bindings.NewRouter(p.PassMessagePipe(), waiter),
		bindings.NewCounter(),
	}
}

func (p *Advertiser_Proxy) Close_Proxy() {
	p.router.Close()
}

type advertiser_Advertise_Params struct {
	inService    Service
	inVisibility *[]string
}

func (s *advertiser_Advertise_Params) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(16, 0)
	if err := encoder.WritePointer(); err != nil {
		return err
	}
	if err := s.inService.Encode(encoder); err != nil {
		return err
	}
	if s.inVisibility == nil {
		encoder.WriteNullPointer()
	} else {
		if err := encoder.WritePointer(); err != nil {
			return err
		}
		encoder.StartArray(uint32(len((*s.inVisibility))), 64)
		for _, elem0 := range *s.inVisibility {
			if err := encoder.WritePointer(); err != nil {
				return err
			}
			if err := encoder.WriteString(elem0); err != nil {
				return err
			}
		}
		if err := encoder.Finish(); err != nil {
			return err
		}
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var advertiser_Advertise_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{24, 0},
}

func (s *advertiser_Advertise_Params) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(advertiser_Advertise_Params_Versions), func(i int) bool {
		return advertiser_Advertise_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(advertiser_Advertise_Params_Versions) {
		if advertiser_Advertise_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := advertiser_Advertise_Params_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
		} else {
			if err := s.inService.Decode(decoder); err != nil {
				return err
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			s.inVisibility = nil
		} else {
			s.inVisibility = new([]string)
			len0, err := decoder.StartArray(64)
			if err != nil {
				return err
			}
			(*s.inVisibility) = make([]string, len0)
			for i0 := uint32(0); i0 < len0; i0++ {
				pointer1, err := decoder.ReadPointer()
				if err != nil {
					return err
				}
				if pointer1 == 0 {
					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
				} else {
					value1, err := decoder.ReadString()
					if err != nil {
						return err
					}
					(*s.inVisibility)[i0] = value1
				}
			}
			if err := decoder.Finish(); err != nil {
				return err
			}
		}
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_AdvertiserAdvertiseParams                   = "AdvertiserAdvertiseParams"
	structFullIdentifier_AdvertiserAdvertiseParams         = "discovery.AdvertiserAdvertiseParams"
	structFieldName_AdvertiserAdvertiseParams_InService    = "InService"
	structFieldName_AdvertiserAdvertiseParams_InVisibility = "InVisibility"
)

func discovery_Advertiser_Advertise_Params__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_AdvertiserAdvertiseParams,
			FullIdentifier: &structFullIdentifier_AdvertiserAdvertiseParams,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_AdvertiserAdvertiseParams_InService,
			},
			Type: &mojom_types.TypeTypeReference{
				Value: mojom_types.TypeReference{Identifier: &ID_discovery_Service__,
					TypeKey: &ID_discovery_Service__},
			},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_AdvertiserAdvertiseParams_InVisibility,
			},
			Type: &mojom_types.TypeArrayType{
				Value: mojom_types.ArrayType{Nullable: true, ElementType: &mojom_types.TypeStringType{mojom_types.StringType{false}}},
			},
		}},
	}
}

type advertiser_Advertise_ResponseParams struct {
	outHandle     uint32
	outInstanceId string
	outErr        *Error
}

func (s *advertiser_Advertise_ResponseParams) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(24, 0)
	if err := encoder.WriteUint32(s.outHandle); err != nil {
		return err
	}
	if err := encoder.WritePointer(); err != nil {
		return err
	}
	if err := encoder.WriteString(s.outInstanceId); err != nil {
		return err
	}
	if s.outErr == nil {
		encoder.WriteNullPointer()
	} else {
		if err := encoder.WritePointer(); err != nil {
			return err
		}
		if err := (*s.outErr).Encode(encoder); err != nil {
			return err
		}
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var advertiser_Advertise_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{32, 0},
}

func (s *advertiser_Advertise_ResponseParams) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(advertiser_Advertise_ResponseParams_Versions), func(i int) bool {
		return advertiser_Advertise_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(advertiser_Advertise_ResponseParams_Versions) {
		if advertiser_Advertise_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := advertiser_Advertise_ResponseParams_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		value0, err := decoder.ReadUint32()
		if err != nil {
			return err
		}
		s.outHandle = value0
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
		} else {
			value0, err := decoder.ReadString()
			if err != nil {
				return err
			}
			s.outInstanceId = value0
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			s.outErr = nil
		} else {
			s.outErr = new(Error)
			if err := (*s.outErr).Decode(decoder); err != nil {
				return err
			}
		}
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_AdvertiserAdvertiseResponseParams                    = "AdvertiserAdvertiseResponseParams"
	structFullIdentifier_AdvertiserAdvertiseResponseParams          = "discovery.AdvertiserAdvertiseResponseParams"
	structFieldName_AdvertiserAdvertiseResponseParams_OutHandle     = "OutHandle"
	structFieldName_AdvertiserAdvertiseResponseParams_OutInstanceId = "OutInstanceId"
	structFieldName_AdvertiserAdvertiseResponseParams_OutErr        = "OutErr"
)

func discovery_Advertiser_Advertise_ResponseParams__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_AdvertiserAdvertiseResponseParams,
			FullIdentifier: &structFullIdentifier_AdvertiserAdvertiseResponseParams,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_AdvertiserAdvertiseResponseParams_OutHandle,
			},
			Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_UinT32},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_AdvertiserAdvertiseResponseParams_OutInstanceId,
			},
			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_AdvertiserAdvertiseResponseParams_OutErr,
			},
			Type: &mojom_types.TypeTypeReference{
				Value: mojom_types.TypeReference{Nullable: true, Identifier: &ID_discovery_Error__,
					TypeKey: &ID_discovery_Error__},
			},
		}},
	}
}

func (p *Advertiser_Proxy) Advertise(inService Service, inVisibility *[]string) (outHandle uint32, outInstanceId string, outErr *Error, err error) {
	payload := &advertiser_Advertise_Params{
		inService,
		inVisibility,
	}
	header := bindings.MessageHeader{
		Type:      advertiser_Advertise_Name,
		Flags:     bindings.MessageExpectsResponseFlag,
		RequestId: p.ids.Count(),
	}
	var message *bindings.Message
	if message, err = bindings.EncodeMessage(header, payload); err != nil {
		err = fmt.Errorf("can't encode request: %v", err.Error())
		p.Close_Proxy()
		return
	}
	readResult := <-p.router.AcceptWithResponse(message)
	if err = readResult.Error; err != nil {
		p.Close_Proxy()
		return
	}
	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
		}
		return
	}
	if got, want := readResult.Message.Header.Type, advertiser_Advertise_Name; got != want {
		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
		}
		return
	}
	var response advertiser_Advertise_ResponseParams
	if err = readResult.Message.DecodePayload(&response); err != nil {
		p.Close_Proxy()
		return
	}
	outHandle = response.outHandle
	outInstanceId = response.outInstanceId
	outErr = response.outErr
	return
}

type advertiser_Stop_Params struct {
	inH uint32
}

func (s *advertiser_Stop_Params) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(8, 0)
	if err := encoder.WriteUint32(s.inH); err != nil {
		return err
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var advertiser_Stop_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{16, 0},
}

func (s *advertiser_Stop_Params) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(advertiser_Stop_Params_Versions), func(i int) bool {
		return advertiser_Stop_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(advertiser_Stop_Params_Versions) {
		if advertiser_Stop_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := advertiser_Stop_Params_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		value0, err := decoder.ReadUint32()
		if err != nil {
			return err
		}
		s.inH = value0
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_AdvertiserStopParams           = "AdvertiserStopParams"
	structFullIdentifier_AdvertiserStopParams = "discovery.AdvertiserStopParams"
	structFieldName_AdvertiserStopParams_InH  = "InH"
)

func discovery_Advertiser_Stop_Params__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_AdvertiserStopParams,
			FullIdentifier: &structFullIdentifier_AdvertiserStopParams,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_AdvertiserStopParams_InH,
			},
			Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_UinT32},
		}},
	}
}

type advertiser_Stop_ResponseParams struct {
	outErr *Error
}

func (s *advertiser_Stop_ResponseParams) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(8, 0)
	if s.outErr == nil {
		encoder.WriteNullPointer()
	} else {
		if err := encoder.WritePointer(); err != nil {
			return err
		}
		if err := (*s.outErr).Encode(encoder); err != nil {
			return err
		}
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var advertiser_Stop_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{16, 0},
}

func (s *advertiser_Stop_ResponseParams) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(advertiser_Stop_ResponseParams_Versions), func(i int) bool {
		return advertiser_Stop_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(advertiser_Stop_ResponseParams_Versions) {
		if advertiser_Stop_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := advertiser_Stop_ResponseParams_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			s.outErr = nil
		} else {
			s.outErr = new(Error)
			if err := (*s.outErr).Decode(decoder); err != nil {
				return err
			}
		}
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_AdvertiserStopResponseParams             = "AdvertiserStopResponseParams"
	structFullIdentifier_AdvertiserStopResponseParams   = "discovery.AdvertiserStopResponseParams"
	structFieldName_AdvertiserStopResponseParams_OutErr = "OutErr"
)

func discovery_Advertiser_Stop_ResponseParams__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_AdvertiserStopResponseParams,
			FullIdentifier: &structFullIdentifier_AdvertiserStopResponseParams,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_AdvertiserStopResponseParams_OutErr,
			},
			Type: &mojom_types.TypeTypeReference{
				Value: mojom_types.TypeReference{Nullable: true, Identifier: &ID_discovery_Error__,
					TypeKey: &ID_discovery_Error__},
			},
		}},
	}
}

func (p *Advertiser_Proxy) Stop(inH uint32) (outErr *Error, err error) {
	payload := &advertiser_Stop_Params{
		inH,
	}
	header := bindings.MessageHeader{
		Type:      advertiser_Stop_Name,
		Flags:     bindings.MessageExpectsResponseFlag,
		RequestId: p.ids.Count(),
	}
	var message *bindings.Message
	if message, err = bindings.EncodeMessage(header, payload); err != nil {
		err = fmt.Errorf("can't encode request: %v", err.Error())
		p.Close_Proxy()
		return
	}
	readResult := <-p.router.AcceptWithResponse(message)
	if err = readResult.Error; err != nil {
		p.Close_Proxy()
		return
	}
	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
		}
		return
	}
	if got, want := readResult.Message.Header.Type, advertiser_Stop_Name; got != want {
		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
		}
		return
	}
	var response advertiser_Stop_ResponseParams
	if err = readResult.Message.DecodePayload(&response); err != nil {
		p.Close_Proxy()
		return
	}
	outErr = response.outErr
	return
}

type advertiser_Stub struct {
	connector *bindings.Connector
	impl      Advertiser
}

func NewAdvertiserStub(r Advertiser_Request, impl Advertiser, waiter bindings.AsyncWaiter) *bindings.Stub {
	connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
	return bindings.NewStub(connector, &advertiser_Stub{connector, impl})
}

var (
	interfaceName_Advertiser                 = "Advertiser"
	interfaceFullIdentifier_Advertiser       = "discovery.Advertiser"
	interfaceMethodName_Advertiser_Advertise = "Advertise"
	interfaceMethodName_Advertiser_Stop      = "Stop"
)

func discovery_Advertiser__() mojom_types.MojomInterface {
	responseParamsMap := make(map[string]*mojom_types.MojomStruct)
	_ = responseParamsMap // To avoid the declared but unused compiler error
	mstruct_Advertise := discovery_Advertiser_Advertise_ResponseParams__()
	responseParamsMap[interfaceMethodName_Advertiser_Advertise] = &mstruct_Advertise
	mstruct_Stop := discovery_Advertiser_Stop_ResponseParams__()
	responseParamsMap[interfaceMethodName_Advertiser_Stop] = &mstruct_Stop
	return mojom_types.MojomInterface{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &interfaceName_Advertiser,
			FullIdentifier: &interfaceFullIdentifier_Advertiser,
		},
		Methods: map[uint32]mojom_types.MojomMethod{advertiser_Advertise_Name: mojom_types.MojomMethod{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &interfaceMethodName_Advertiser_Advertise,
			},
			Parameters:     discovery_Advertiser_Advertise_Params__(),
			ResponseParams: responseParamsMap[interfaceMethodName_Advertiser_Advertise],
		}, advertiser_Stop_Name: mojom_types.MojomMethod{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &interfaceMethodName_Advertiser_Stop,
			},
			Parameters:     discovery_Advertiser_Stop_Params__(),
			ResponseParams: responseParamsMap[interfaceMethodName_Advertiser_Stop],
		}},
	}
}

func (f *Advertiser_Request) ServiceDescription() service_describer.ServiceDescription {
	return &Advertiser_ServiceDescription{}
}

type Advertiser_ServiceDescription struct{}

func (sd *Advertiser_ServiceDescription) GetTopLevelInterface() (outMojomInterface mojom_types.MojomInterface, err error) {
	return discovery_Advertiser__(), nil
}

func (sd *Advertiser_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
	if udt, ok := GetAllMojomTypeDefinitions()[inTypeKey]; ok {
		return udt, nil
	}
	return nil, fmt.Errorf("%s_ServiceDescription does not recognize %s", "Advertiser", inTypeKey)
}

func (sd *Advertiser_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
	o := GetAllMojomTypeDefinitions()
	return &o, nil
}

var _ service_describer.ServiceDescription = (*Advertiser_ServiceDescription)(nil)

func (s *advertiser_Stub) Accept(message *bindings.Message) (err error) {
	switch message.Header.Type {
	case advertiser_Advertise_Name:
		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
			}
		}
		var request advertiser_Advertise_Params
		if err := message.DecodePayload(&request); err != nil {
			return err
		}
		var response advertiser_Advertise_ResponseParams
		response.outHandle, response.outInstanceId, response.outErr, err = s.impl.Advertise(request.inService, request.inVisibility)
		if err != nil {
			return
		}
		header := bindings.MessageHeader{
			Type:      advertiser_Advertise_Name,
			Flags:     bindings.MessageIsResponseFlag,
			RequestId: message.Header.RequestId,
		}
		message, err = bindings.EncodeMessage(header, &response)
		if err != nil {
			return err
		}
		return s.connector.WriteMessage(message)
	case advertiser_Stop_Name:
		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
			}
		}
		var request advertiser_Stop_Params
		if err := message.DecodePayload(&request); err != nil {
			return err
		}
		var response advertiser_Stop_ResponseParams
		response.outErr, err = s.impl.Stop(request.inH)
		if err != nil {
			return
		}
		header := bindings.MessageHeader{
			Type:      advertiser_Stop_Name,
			Flags:     bindings.MessageIsResponseFlag,
			RequestId: message.Header.RequestId,
		}
		message, err = bindings.EncodeMessage(header, &response)
		if err != nil {
			return err
		}
		return s.connector.WriteMessage(message)
	default:
		return &bindings.ValidationError{
			bindings.MessageHeaderUnknownMethod,
			fmt.Sprintf("unknown method %v", message.Header.Type),
		}
	}
	return
}

type Scanner interface {
	Scan(inQuery string, inScanHandler ScanHandler_Pointer) (outHandle uint32, outErr *Error, err error)
	Stop(inH uint32) (outErr *Error, err error)
}

var scanner_Name = "v23::discovery::Scanner"

type Scanner_Request bindings.InterfaceRequest

func (r *Scanner_Request) Name() string {
	return scanner_Name
}

type Scanner_Pointer bindings.InterfacePointer

func (p *Scanner_Pointer) Name() string {
	return scanner_Name
}

type Scanner_ServiceFactory struct {
	Delegate Scanner_Factory
}

type Scanner_Factory interface {
	Create(request Scanner_Request)
}

func (f *Scanner_ServiceFactory) Name() string {
	return scanner_Name
}

func (f *Scanner_ServiceFactory) ServiceDescription() service_describer.ServiceDescription {
	return &Scanner_ServiceDescription{}
}

func (f *Scanner_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
	request := Scanner_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
	f.Delegate.Create(request)
}

// CreateMessagePipeForScanner creates a message pipe for use with the
// Scanner interface with a Scanner_Request on one end and a Scanner_Pointer on the other.
func CreateMessagePipeForScanner() (Scanner_Request, Scanner_Pointer) {
	r, p := bindings.CreateMessagePipeForMojoInterface()
	return Scanner_Request(r), Scanner_Pointer(p)
}

const scanner_Scan_Name uint32 = 0
const scanner_Stop_Name uint32 = 1

type Scanner_Proxy struct {
	router *bindings.Router
	ids    bindings.Counter
}

func NewScannerProxy(p Scanner_Pointer, waiter bindings.AsyncWaiter) *Scanner_Proxy {
	return &Scanner_Proxy{
		bindings.NewRouter(p.PassMessagePipe(), waiter),
		bindings.NewCounter(),
	}
}

func (p *Scanner_Proxy) Close_Proxy() {
	p.router.Close()
}

type scanner_Scan_Params struct {
	inQuery       string
	inScanHandler ScanHandler_Pointer
}

func (s *scanner_Scan_Params) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(16, 0)
	if err := encoder.WritePointer(); err != nil {
		return err
	}
	if err := encoder.WriteString(s.inQuery); err != nil {
		return err
	}
	if err := encoder.WriteInterface(s.inScanHandler.PassMessagePipe()); err != nil {
		return err
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var scanner_Scan_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{24, 0},
}

func (s *scanner_Scan_Params) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(scanner_Scan_Params_Versions), func(i int) bool {
		return scanner_Scan_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(scanner_Scan_Params_Versions) {
		if scanner_Scan_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := scanner_Scan_Params_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
		} else {
			value0, err := decoder.ReadString()
			if err != nil {
				return err
			}
			s.inQuery = value0
		}
	}
	if header.ElementsOrVersion >= 0 {
		handle0, err := decoder.ReadInterface()
		if err != nil {
			return err
		}
		if handle0.IsValid() {
			handleOwner := bindings.NewMessagePipeHandleOwner(handle0)
			s.inScanHandler = ScanHandler_Pointer{handleOwner}
		} else {
			return &bindings.ValidationError{bindings.UnexpectedInvalidHandle, "unexpected invalid handle"}
		}
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_ScannerScanParams                    = "ScannerScanParams"
	structFullIdentifier_ScannerScanParams          = "discovery.ScannerScanParams"
	structFieldName_ScannerScanParams_InQuery       = "InQuery"
	structFieldName_ScannerScanParams_InScanHandler = "InScanHandler"
)

func discovery_Scanner_Scan_Params__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_ScannerScanParams,
			FullIdentifier: &structFullIdentifier_ScannerScanParams,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_ScannerScanParams_InQuery,
			},
			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_ScannerScanParams_InScanHandler,
			},
			Type: &mojom_types.TypeTypeReference{
				Value: mojom_types.TypeReference{Identifier: &ID_discovery_ScanHandler__,
					TypeKey: &ID_discovery_ScanHandler__},
			},
		}},
	}
}

type scanner_Scan_ResponseParams struct {
	outHandle uint32
	outErr    *Error
}

func (s *scanner_Scan_ResponseParams) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(16, 0)
	if err := encoder.WriteUint32(s.outHandle); err != nil {
		return err
	}
	if s.outErr == nil {
		encoder.WriteNullPointer()
	} else {
		if err := encoder.WritePointer(); err != nil {
			return err
		}
		if err := (*s.outErr).Encode(encoder); err != nil {
			return err
		}
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var scanner_Scan_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{24, 0},
}

func (s *scanner_Scan_ResponseParams) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(scanner_Scan_ResponseParams_Versions), func(i int) bool {
		return scanner_Scan_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(scanner_Scan_ResponseParams_Versions) {
		if scanner_Scan_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := scanner_Scan_ResponseParams_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		value0, err := decoder.ReadUint32()
		if err != nil {
			return err
		}
		s.outHandle = value0
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			s.outErr = nil
		} else {
			s.outErr = new(Error)
			if err := (*s.outErr).Decode(decoder); err != nil {
				return err
			}
		}
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_ScannerScanResponseParams                = "ScannerScanResponseParams"
	structFullIdentifier_ScannerScanResponseParams      = "discovery.ScannerScanResponseParams"
	structFieldName_ScannerScanResponseParams_OutHandle = "OutHandle"
	structFieldName_ScannerScanResponseParams_OutErr    = "OutErr"
)

func discovery_Scanner_Scan_ResponseParams__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_ScannerScanResponseParams,
			FullIdentifier: &structFullIdentifier_ScannerScanResponseParams,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_ScannerScanResponseParams_OutHandle,
			},
			Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_UinT32},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_ScannerScanResponseParams_OutErr,
			},
			Type: &mojom_types.TypeTypeReference{
				Value: mojom_types.TypeReference{Nullable: true, Identifier: &ID_discovery_Error__,
					TypeKey: &ID_discovery_Error__},
			},
		}},
	}
}

func (p *Scanner_Proxy) Scan(inQuery string, inScanHandler ScanHandler_Pointer) (outHandle uint32, outErr *Error, err error) {
	payload := &scanner_Scan_Params{
		inQuery,
		inScanHandler,
	}
	header := bindings.MessageHeader{
		Type:      scanner_Scan_Name,
		Flags:     bindings.MessageExpectsResponseFlag,
		RequestId: p.ids.Count(),
	}
	var message *bindings.Message
	if message, err = bindings.EncodeMessage(header, payload); err != nil {
		err = fmt.Errorf("can't encode request: %v", err.Error())
		p.Close_Proxy()
		return
	}
	readResult := <-p.router.AcceptWithResponse(message)
	if err = readResult.Error; err != nil {
		p.Close_Proxy()
		return
	}
	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
		}
		return
	}
	if got, want := readResult.Message.Header.Type, scanner_Scan_Name; got != want {
		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
		}
		return
	}
	var response scanner_Scan_ResponseParams
	if err = readResult.Message.DecodePayload(&response); err != nil {
		p.Close_Proxy()
		return
	}
	outHandle = response.outHandle
	outErr = response.outErr
	return
}

type scanner_Stop_Params struct {
	inH uint32
}

func (s *scanner_Stop_Params) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(8, 0)
	if err := encoder.WriteUint32(s.inH); err != nil {
		return err
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var scanner_Stop_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{16, 0},
}

func (s *scanner_Stop_Params) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(scanner_Stop_Params_Versions), func(i int) bool {
		return scanner_Stop_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(scanner_Stop_Params_Versions) {
		if scanner_Stop_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := scanner_Stop_Params_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		value0, err := decoder.ReadUint32()
		if err != nil {
			return err
		}
		s.inH = value0
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_ScannerStopParams           = "ScannerStopParams"
	structFullIdentifier_ScannerStopParams = "discovery.ScannerStopParams"
	structFieldName_ScannerStopParams_InH  = "InH"
)

func discovery_Scanner_Stop_Params__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_ScannerStopParams,
			FullIdentifier: &structFullIdentifier_ScannerStopParams,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_ScannerStopParams_InH,
			},
			Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_UinT32},
		}},
	}
}

type scanner_Stop_ResponseParams struct {
	outErr *Error
}

func (s *scanner_Stop_ResponseParams) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(8, 0)
	if s.outErr == nil {
		encoder.WriteNullPointer()
	} else {
		if err := encoder.WritePointer(); err != nil {
			return err
		}
		if err := (*s.outErr).Encode(encoder); err != nil {
			return err
		}
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var scanner_Stop_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{16, 0},
}

func (s *scanner_Stop_ResponseParams) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(scanner_Stop_ResponseParams_Versions), func(i int) bool {
		return scanner_Stop_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(scanner_Stop_ResponseParams_Versions) {
		if scanner_Stop_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := scanner_Stop_ResponseParams_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			s.outErr = nil
		} else {
			s.outErr = new(Error)
			if err := (*s.outErr).Decode(decoder); err != nil {
				return err
			}
		}
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_ScannerStopResponseParams             = "ScannerStopResponseParams"
	structFullIdentifier_ScannerStopResponseParams   = "discovery.ScannerStopResponseParams"
	structFieldName_ScannerStopResponseParams_OutErr = "OutErr"
)

func discovery_Scanner_Stop_ResponseParams__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_ScannerStopResponseParams,
			FullIdentifier: &structFullIdentifier_ScannerStopResponseParams,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_ScannerStopResponseParams_OutErr,
			},
			Type: &mojom_types.TypeTypeReference{
				Value: mojom_types.TypeReference{Nullable: true, Identifier: &ID_discovery_Error__,
					TypeKey: &ID_discovery_Error__},
			},
		}},
	}
}

func (p *Scanner_Proxy) Stop(inH uint32) (outErr *Error, err error) {
	payload := &scanner_Stop_Params{
		inH,
	}
	header := bindings.MessageHeader{
		Type:      scanner_Stop_Name,
		Flags:     bindings.MessageExpectsResponseFlag,
		RequestId: p.ids.Count(),
	}
	var message *bindings.Message
	if message, err = bindings.EncodeMessage(header, payload); err != nil {
		err = fmt.Errorf("can't encode request: %v", err.Error())
		p.Close_Proxy()
		return
	}
	readResult := <-p.router.AcceptWithResponse(message)
	if err = readResult.Error; err != nil {
		p.Close_Proxy()
		return
	}
	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
		}
		return
	}
	if got, want := readResult.Message.Header.Type, scanner_Stop_Name; got != want {
		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
		}
		return
	}
	var response scanner_Stop_ResponseParams
	if err = readResult.Message.DecodePayload(&response); err != nil {
		p.Close_Proxy()
		return
	}
	outErr = response.outErr
	return
}

type scanner_Stub struct {
	connector *bindings.Connector
	impl      Scanner
}

func NewScannerStub(r Scanner_Request, impl Scanner, waiter bindings.AsyncWaiter) *bindings.Stub {
	connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
	return bindings.NewStub(connector, &scanner_Stub{connector, impl})
}

var (
	interfaceName_Scanner            = "Scanner"
	interfaceFullIdentifier_Scanner  = "discovery.Scanner"
	interfaceMethodName_Scanner_Scan = "Scan"
	interfaceMethodName_Scanner_Stop = "Stop"
)

func discovery_Scanner__() mojom_types.MojomInterface {
	responseParamsMap := make(map[string]*mojom_types.MojomStruct)
	_ = responseParamsMap // To avoid the declared but unused compiler error
	mstruct_Scan := discovery_Scanner_Scan_ResponseParams__()
	responseParamsMap[interfaceMethodName_Scanner_Scan] = &mstruct_Scan
	mstruct_Stop := discovery_Scanner_Stop_ResponseParams__()
	responseParamsMap[interfaceMethodName_Scanner_Stop] = &mstruct_Stop
	return mojom_types.MojomInterface{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &interfaceName_Scanner,
			FullIdentifier: &interfaceFullIdentifier_Scanner,
		},
		Methods: map[uint32]mojom_types.MojomMethod{scanner_Scan_Name: mojom_types.MojomMethod{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &interfaceMethodName_Scanner_Scan,
			},
			Parameters:     discovery_Scanner_Scan_Params__(),
			ResponseParams: responseParamsMap[interfaceMethodName_Scanner_Scan],
		}, scanner_Stop_Name: mojom_types.MojomMethod{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &interfaceMethodName_Scanner_Stop,
			},
			Parameters:     discovery_Scanner_Stop_Params__(),
			ResponseParams: responseParamsMap[interfaceMethodName_Scanner_Stop],
		}},
	}
}

func (f *Scanner_Request) ServiceDescription() service_describer.ServiceDescription {
	return &Scanner_ServiceDescription{}
}

type Scanner_ServiceDescription struct{}

func (sd *Scanner_ServiceDescription) GetTopLevelInterface() (outMojomInterface mojom_types.MojomInterface, err error) {
	return discovery_Scanner__(), nil
}

func (sd *Scanner_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
	if udt, ok := GetAllMojomTypeDefinitions()[inTypeKey]; ok {
		return udt, nil
	}
	return nil, fmt.Errorf("%s_ServiceDescription does not recognize %s", "Scanner", inTypeKey)
}

func (sd *Scanner_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
	o := GetAllMojomTypeDefinitions()
	return &o, nil
}

var _ service_describer.ServiceDescription = (*Scanner_ServiceDescription)(nil)

func (s *scanner_Stub) Accept(message *bindings.Message) (err error) {
	switch message.Header.Type {
	case scanner_Scan_Name:
		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
			}
		}
		var request scanner_Scan_Params
		if err := message.DecodePayload(&request); err != nil {
			return err
		}
		var response scanner_Scan_ResponseParams
		response.outHandle, response.outErr, err = s.impl.Scan(request.inQuery, request.inScanHandler)
		if err != nil {
			return
		}
		header := bindings.MessageHeader{
			Type:      scanner_Scan_Name,
			Flags:     bindings.MessageIsResponseFlag,
			RequestId: message.Header.RequestId,
		}
		message, err = bindings.EncodeMessage(header, &response)
		if err != nil {
			return err
		}
		return s.connector.WriteMessage(message)
	case scanner_Stop_Name:
		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
			}
		}
		var request scanner_Stop_Params
		if err := message.DecodePayload(&request); err != nil {
			return err
		}
		var response scanner_Stop_ResponseParams
		response.outErr, err = s.impl.Stop(request.inH)
		if err != nil {
			return
		}
		header := bindings.MessageHeader{
			Type:      scanner_Stop_Name,
			Flags:     bindings.MessageIsResponseFlag,
			RequestId: message.Header.RequestId,
		}
		message, err = bindings.EncodeMessage(header, &response)
		if err != nil {
			return err
		}
		return s.connector.WriteMessage(message)
	default:
		return &bindings.ValidationError{
			bindings.MessageHeaderUnknownMethod,
			fmt.Sprintf("unknown method %v", message.Header.Type),
		}
	}
	return
}

type ScanHandler interface {
	Found(inService Service) (err error)
	Lost(inInstanceId string) (err error)
}

var scanHandler_Name = "v23::discovery::ScanHandler"

type ScanHandler_Request bindings.InterfaceRequest

func (r *ScanHandler_Request) Name() string {
	return scanHandler_Name
}

type ScanHandler_Pointer bindings.InterfacePointer

func (p *ScanHandler_Pointer) Name() string {
	return scanHandler_Name
}

type ScanHandler_ServiceFactory struct {
	Delegate ScanHandler_Factory
}

type ScanHandler_Factory interface {
	Create(request ScanHandler_Request)
}

func (f *ScanHandler_ServiceFactory) Name() string {
	return scanHandler_Name
}

func (f *ScanHandler_ServiceFactory) ServiceDescription() service_describer.ServiceDescription {
	return &ScanHandler_ServiceDescription{}
}

func (f *ScanHandler_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
	request := ScanHandler_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
	f.Delegate.Create(request)
}

// CreateMessagePipeForScanHandler creates a message pipe for use with the
// ScanHandler interface with a ScanHandler_Request on one end and a ScanHandler_Pointer on the other.
func CreateMessagePipeForScanHandler() (ScanHandler_Request, ScanHandler_Pointer) {
	r, p := bindings.CreateMessagePipeForMojoInterface()
	return ScanHandler_Request(r), ScanHandler_Pointer(p)
}

const scanHandler_Found_Name uint32 = 0
const scanHandler_Lost_Name uint32 = 1

type ScanHandler_Proxy struct {
	router *bindings.Router
	ids    bindings.Counter
}

func NewScanHandlerProxy(p ScanHandler_Pointer, waiter bindings.AsyncWaiter) *ScanHandler_Proxy {
	return &ScanHandler_Proxy{
		bindings.NewRouter(p.PassMessagePipe(), waiter),
		bindings.NewCounter(),
	}
}

func (p *ScanHandler_Proxy) Close_Proxy() {
	p.router.Close()
}

type scanHandler_Found_Params struct {
	inService Service
}

func (s *scanHandler_Found_Params) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(8, 0)
	if err := encoder.WritePointer(); err != nil {
		return err
	}
	if err := s.inService.Encode(encoder); err != nil {
		return err
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var scanHandler_Found_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{16, 0},
}

func (s *scanHandler_Found_Params) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(scanHandler_Found_Params_Versions), func(i int) bool {
		return scanHandler_Found_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(scanHandler_Found_Params_Versions) {
		if scanHandler_Found_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := scanHandler_Found_Params_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
		} else {
			if err := s.inService.Decode(decoder); err != nil {
				return err
			}
		}
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_ScanHandlerFoundParams                = "ScanHandlerFoundParams"
	structFullIdentifier_ScanHandlerFoundParams      = "discovery.ScanHandlerFoundParams"
	structFieldName_ScanHandlerFoundParams_InService = "InService"
)

func discovery_ScanHandler_Found_Params__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_ScanHandlerFoundParams,
			FullIdentifier: &structFullIdentifier_ScanHandlerFoundParams,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_ScanHandlerFoundParams_InService,
			},
			Type: &mojom_types.TypeTypeReference{
				Value: mojom_types.TypeReference{Identifier: &ID_discovery_Service__,
					TypeKey: &ID_discovery_Service__},
			},
		}},
	}
}

func (p *ScanHandler_Proxy) Found(inService Service) (err error) {
	payload := &scanHandler_Found_Params{
		inService,
	}
	header := bindings.MessageHeader{
		Type:  scanHandler_Found_Name,
		Flags: bindings.MessageNoFlag,
	}
	var message *bindings.Message
	if message, err = bindings.EncodeMessage(header, payload); err != nil {
		err = fmt.Errorf("can't encode request: %v", err.Error())
		p.Close_Proxy()
		return
	}
	if err = p.router.Accept(message); err != nil {
		p.Close_Proxy()
		return
	}
	return
}

type scanHandler_Lost_Params struct {
	inInstanceId string
}

func (s *scanHandler_Lost_Params) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(8, 0)
	if err := encoder.WritePointer(); err != nil {
		return err
	}
	if err := encoder.WriteString(s.inInstanceId); err != nil {
		return err
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var scanHandler_Lost_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{16, 0},
}

func (s *scanHandler_Lost_Params) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(scanHandler_Lost_Params_Versions), func(i int) bool {
		return scanHandler_Lost_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(scanHandler_Lost_Params_Versions) {
		if scanHandler_Lost_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := scanHandler_Lost_Params_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
		} else {
			value0, err := decoder.ReadString()
			if err != nil {
				return err
			}
			s.inInstanceId = value0
		}
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_ScanHandlerLostParams                   = "ScanHandlerLostParams"
	structFullIdentifier_ScanHandlerLostParams         = "discovery.ScanHandlerLostParams"
	structFieldName_ScanHandlerLostParams_InInstanceId = "InInstanceId"
)

func discovery_ScanHandler_Lost_Params__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_ScanHandlerLostParams,
			FullIdentifier: &structFullIdentifier_ScanHandlerLostParams,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_ScanHandlerLostParams_InInstanceId,
			},
			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
		}},
	}
}

func (p *ScanHandler_Proxy) Lost(inInstanceId string) (err error) {
	payload := &scanHandler_Lost_Params{
		inInstanceId,
	}
	header := bindings.MessageHeader{
		Type:  scanHandler_Lost_Name,
		Flags: bindings.MessageNoFlag,
	}
	var message *bindings.Message
	if message, err = bindings.EncodeMessage(header, payload); err != nil {
		err = fmt.Errorf("can't encode request: %v", err.Error())
		p.Close_Proxy()
		return
	}
	if err = p.router.Accept(message); err != nil {
		p.Close_Proxy()
		return
	}
	return
}

type scanHandler_Stub struct {
	connector *bindings.Connector
	impl      ScanHandler
}

func NewScanHandlerStub(r ScanHandler_Request, impl ScanHandler, waiter bindings.AsyncWaiter) *bindings.Stub {
	connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
	return bindings.NewStub(connector, &scanHandler_Stub{connector, impl})
}

var (
	interfaceName_ScanHandler             = "ScanHandler"
	interfaceFullIdentifier_ScanHandler   = "discovery.ScanHandler"
	interfaceMethodName_ScanHandler_Found = "Found"
	interfaceMethodName_ScanHandler_Lost  = "Lost"
)

func discovery_ScanHandler__() mojom_types.MojomInterface {
	responseParamsMap := make(map[string]*mojom_types.MojomStruct)
	_ = responseParamsMap // To avoid the declared but unused compiler error
	return mojom_types.MojomInterface{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &interfaceName_ScanHandler,
			FullIdentifier: &interfaceFullIdentifier_ScanHandler,
		},
		Methods: map[uint32]mojom_types.MojomMethod{scanHandler_Found_Name: mojom_types.MojomMethod{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &interfaceMethodName_ScanHandler_Found,
			},
			Parameters:     discovery_ScanHandler_Found_Params__(),
			ResponseParams: responseParamsMap[interfaceMethodName_ScanHandler_Found],
		}, scanHandler_Lost_Name: mojom_types.MojomMethod{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &interfaceMethodName_ScanHandler_Lost,
			},
			Parameters:     discovery_ScanHandler_Lost_Params__(),
			ResponseParams: responseParamsMap[interfaceMethodName_ScanHandler_Lost],
		}},
	}
}

func (f *ScanHandler_Request) ServiceDescription() service_describer.ServiceDescription {
	return &ScanHandler_ServiceDescription{}
}

type ScanHandler_ServiceDescription struct{}

func (sd *ScanHandler_ServiceDescription) GetTopLevelInterface() (outMojomInterface mojom_types.MojomInterface, err error) {
	return discovery_ScanHandler__(), nil
}

func (sd *ScanHandler_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
	if udt, ok := GetAllMojomTypeDefinitions()[inTypeKey]; ok {
		return udt, nil
	}
	return nil, fmt.Errorf("%s_ServiceDescription does not recognize %s", "ScanHandler", inTypeKey)
}

func (sd *ScanHandler_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
	o := GetAllMojomTypeDefinitions()
	return &o, nil
}

var _ service_describer.ServiceDescription = (*ScanHandler_ServiceDescription)(nil)

func (s *scanHandler_Stub) Accept(message *bindings.Message) (err error) {
	switch message.Header.Type {
	case scanHandler_Found_Name:
		if message.Header.Flags != bindings.MessageNoFlag {
			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
			}
		}
		var request scanHandler_Found_Params
		if err := message.DecodePayload(&request); err != nil {
			return err
		}
		err = s.impl.Found(request.inService)
		if err != nil {
			return
		}
	case scanHandler_Lost_Name:
		if message.Header.Flags != bindings.MessageNoFlag {
			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
			}
		}
		var request scanHandler_Lost_Params
		if err := message.DecodePayload(&request); err != nil {
			return err
		}
		err = s.impl.Lost(request.inInstanceId)
		if err != nil {
			return
		}
	default:
		return &bindings.ValidationError{
			bindings.MessageHeaderUnknownMethod,
			fmt.Sprintf("unknown method %v", message.Header.Type),
		}
	}
	return
}

type Service struct {
	InstanceId    *string
	InstanceName  *string
	InterfaceName string
	Attrs         *map[string]string
	Addrs         []string
}

func (s *Service) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(40, 0)
	if s.InstanceId == nil {
		encoder.WriteNullPointer()
	} else {
		if err := encoder.WritePointer(); err != nil {
			return err
		}
		if err := encoder.WriteString((*s.InstanceId)); err != nil {
			return err
		}
	}
	if s.InstanceName == nil {
		encoder.WriteNullPointer()
	} else {
		if err := encoder.WritePointer(); err != nil {
			return err
		}
		if err := encoder.WriteString((*s.InstanceName)); err != nil {
			return err
		}
	}
	if err := encoder.WritePointer(); err != nil {
		return err
	}
	if err := encoder.WriteString(s.InterfaceName); err != nil {
		return err
	}
	if s.Attrs == nil {
		encoder.WriteNullPointer()
	} else {
		if err := encoder.WritePointer(); err != nil {
			return err
		}
		encoder.StartMap()
		{
			var keys0 []string
			var values0 []string
			for key0, value0 := range *s.Attrs {
				keys0 = append(keys0, key0)
				values0 = append(values0, value0)
			}
			if err := encoder.WritePointer(); err != nil {
				return err
			}
			encoder.StartArray(uint32(len(keys0)), 64)
			for _, elem1 := range keys0 {
				if err := encoder.WritePointer(); err != nil {
					return err
				}
				if err := encoder.WriteString(elem1); err != nil {
					return err
				}
			}
			if err := encoder.Finish(); err != nil {
				return err
			}
			if err := encoder.WritePointer(); err != nil {
				return err
			}
			encoder.StartArray(uint32(len(values0)), 64)
			for _, elem1 := range values0 {
				if err := encoder.WritePointer(); err != nil {
					return err
				}
				if err := encoder.WriteString(elem1); err != nil {
					return err
				}
			}
			if err := encoder.Finish(); err != nil {
				return err
			}
		}
		if err := encoder.Finish(); err != nil {
			return err
		}
	}
	if err := encoder.WritePointer(); err != nil {
		return err
	}
	encoder.StartArray(uint32(len(s.Addrs)), 64)
	for _, elem0 := range s.Addrs {
		if err := encoder.WritePointer(); err != nil {
			return err
		}
		if err := encoder.WriteString(elem0); err != nil {
			return err
		}
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var service_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{48, 0},
}

func (s *Service) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(service_Versions), func(i int) bool {
		return service_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(service_Versions) {
		if service_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := service_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			s.InstanceId = nil
		} else {
			s.InstanceId = new(string)
			value0, err := decoder.ReadString()
			if err != nil {
				return err
			}
			(*s.InstanceId) = value0
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			s.InstanceName = nil
		} else {
			s.InstanceName = new(string)
			value0, err := decoder.ReadString()
			if err != nil {
				return err
			}
			(*s.InstanceName) = value0
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
		} else {
			value0, err := decoder.ReadString()
			if err != nil {
				return err
			}
			s.InterfaceName = value0
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			s.Attrs = nil
		} else {
			s.Attrs = new(map[string]string)
			if err := decoder.StartMap(); err != nil {
				return err
			}
			var keys0 []string
			{
				pointer1, err := decoder.ReadPointer()
				if err != nil {
					return err
				}
				if pointer1 == 0 {
					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
				} else {
					len1, err := decoder.StartArray(64)
					if err != nil {
						return err
					}
					keys0 = make([]string, len1)
					for i1 := uint32(0); i1 < len1; i1++ {
						pointer2, err := decoder.ReadPointer()
						if err != nil {
							return err
						}
						if pointer2 == 0 {
							return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
						} else {
							value2, err := decoder.ReadString()
							if err != nil {
								return err
							}
							keys0[i1] = value2
						}
					}
					if err := decoder.Finish(); err != nil {
						return err
					}
				}
			}
			var values0 []string
			{
				pointer1, err := decoder.ReadPointer()
				if err != nil {
					return err
				}
				if pointer1 == 0 {
					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
				} else {
					len1, err := decoder.StartArray(64)
					if err != nil {
						return err
					}
					values0 = make([]string, len1)
					for i1 := uint32(0); i1 < len1; i1++ {
						pointer2, err := decoder.ReadPointer()
						if err != nil {
							return err
						}
						if pointer2 == 0 {
							return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
						} else {
							value2, err := decoder.ReadString()
							if err != nil {
								return err
							}
							values0[i1] = value2
						}
					}
					if err := decoder.Finish(); err != nil {
						return err
					}
				}
			}
			if len(keys0) != len(values0) {
				return &bindings.ValidationError{bindings.DifferentSizedArraysInMap,
					fmt.Sprintf("Number of keys %d is different from number of values %d", len(keys0), len(values0)),
				}
			}
			if err := decoder.Finish(); err != nil {
				return err
			}
			len0 := len(keys0)
			map0 := make(map[string]string)
			for i0 := 0; i0 < len0; i0++ {
				map0[keys0[i0]] = values0[i0]
			}
			(*s.Attrs) = map0
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
		} else {
			len0, err := decoder.StartArray(64)
			if err != nil {
				return err
			}
			s.Addrs = make([]string, len0)
			for i0 := uint32(0); i0 < len0; i0++ {
				pointer1, err := decoder.ReadPointer()
				if err != nil {
					return err
				}
				if pointer1 == 0 {
					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
				} else {
					value1, err := decoder.ReadString()
					if err != nil {
						return err
					}
					s.Addrs[i0] = value1
				}
			}
			if err := decoder.Finish(); err != nil {
				return err
			}
		}
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_Service                    = "Service"
	structFullIdentifier_Service          = "discovery.Service"
	structFieldName_Service_InstanceId    = "InstanceId"
	structFieldName_Service_InstanceName  = "InstanceName"
	structFieldName_Service_InterfaceName = "InterfaceName"
	structFieldName_Service_Attrs         = "Attrs"
	structFieldName_Service_Addrs         = "Addrs"
)

func discovery_Service__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_Service,
			FullIdentifier: &structFullIdentifier_Service,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_Service_InstanceId,
			},
			Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_Service_InstanceName,
			},
			Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_Service_InterfaceName,
			},
			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_Service_Attrs,
			},
			Type: &mojom_types.TypeMapType{
				Value: mojom_types.MapType{Nullable: true, KeyType: &mojom_types.TypeStringType{mojom_types.StringType{false}},
					ValueType: &mojom_types.TypeStringType{mojom_types.StringType{false}},
				},
			},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_Service_Addrs,
			},
			Type: &mojom_types.TypeArrayType{
				Value: mojom_types.ArrayType{ElementType: &mojom_types.TypeStringType{mojom_types.StringType{false}}},
			},
		}},
	}
}

type Error struct {
	Id     string
	Action int32
	Msg    string
}

func (s *Error) Encode(encoder *bindings.Encoder) error {
	encoder.StartStruct(24, 0)
	if err := encoder.WritePointer(); err != nil {
		return err
	}
	if err := encoder.WriteString(s.Id); err != nil {
		return err
	}
	if err := encoder.WriteInt32(s.Action); err != nil {
		return err
	}
	if err := encoder.WritePointer(); err != nil {
		return err
	}
	if err := encoder.WriteString(s.Msg); err != nil {
		return err
	}
	if err := encoder.Finish(); err != nil {
		return err
	}
	return nil
}

var error_Versions []bindings.DataHeader = []bindings.DataHeader{
	bindings.DataHeader{32, 0},
}

func (s *Error) Decode(decoder *bindings.Decoder) error {
	header, err := decoder.StartStruct()
	if err != nil {
		return err
	}
	index := sort.Search(len(error_Versions), func(i int) bool {
		return error_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
	})
	if index < len(error_Versions) {
		if error_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
			index--
		}
		expectedSize := error_Versions[index].Size
		if expectedSize != header.Size {
			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
			}
		}
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
		} else {
			value0, err := decoder.ReadString()
			if err != nil {
				return err
			}
			s.Id = value0
		}
	}
	if header.ElementsOrVersion >= 0 {
		value0, err := decoder.ReadInt32()
		if err != nil {
			return err
		}
		s.Action = value0
	}
	if header.ElementsOrVersion >= 0 {
		pointer0, err := decoder.ReadPointer()
		if err != nil {
			return err
		}
		if pointer0 == 0 {
			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
		} else {
			value0, err := decoder.ReadString()
			if err != nil {
				return err
			}
			s.Msg = value0
		}
	}
	if err := decoder.Finish(); err != nil {
		return err
	}
	return nil
}

// String names and labels used by the MojomStruct types.
var (
	structName_Error             = "Error"
	structFullIdentifier_Error   = "discovery.Error"
	structFieldName_Error_Id     = "Id"
	structFieldName_Error_Action = "Action"
	structFieldName_Error_Msg    = "Msg"
)

func discovery_Error__() mojom_types.MojomStruct {
	return mojom_types.MojomStruct{
		DeclData: &mojom_types.DeclarationData{
			ShortName:      &structName_Error,
			FullIdentifier: &structFullIdentifier_Error,
		}, Fields: []mojom_types.StructField{mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_Error_Id,
			},
			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_Error_Action,
			},
			Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_InT32},
		}, mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{
				ShortName: &structFieldName_Error_Msg,
			},
			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
		}},
	}
}
