// Code generated by fidlgen; DO NOT EDIT.

package example

import (
	exampleusing "fidl/exampleusing"
	_bindings "syscall/zx/fidl"
)

const (
	ExampleConst uint32 = 0
)

type ExampleEnum uint32

const (
	ExampleEnumMember ExampleEnum = 1
)

func (x ExampleEnum) String() string {
	switch x {
	case 1:
		return "Member"
	}
	return "Unknown"
}

type ExampleBits uint32

const (
	ExampleBitsMember ExampleBits = 1
)

func (x ExampleBits) String() string {
	switch x {
	case 1:
		return "Member"
	}
	return "Unknown"
}

type ExampleStruct struct {
	_      struct{} `fidl:"s" fidl_size_v1:"4" fidl_alignment_v1:"4"`
	Member uint32   `fidl_offset_v1:"0"`
}

var _mExampleStruct = _bindings.CreateLazyMarshaler(ExampleStruct{})

func (msg *ExampleStruct) Marshaler() _bindings.Marshaler {
	return _mExampleStruct
}

type exampleProtocolWithCtxMethodRequest struct {
	_   struct{}           `fidl:"s" fidl_size_v1:"8" fidl_alignment_v1:"8"`
	Arg exampleusing.Empty `fidl_offset_v1:"0"`
}

var _mexampleProtocolWithCtxMethodRequest = _bindings.CreateLazyMarshaler(exampleProtocolWithCtxMethodRequest{})

func (msg *exampleProtocolWithCtxMethodRequest) Marshaler() _bindings.Marshaler {
	return _mexampleProtocolWithCtxMethodRequest
}

type I_exampleUnionTag uint64

const (
	ExampleUnionVariant = 1 // 0x00000001
)

type ExampleUnion struct {
	I_exampleUnionTag `fidl:"x!" fidl_size_v1:"24" fidl_alignment_v1:"8"`
	Variant           uint32 `fidl_ordinal:"1"`
}

func (_m *ExampleUnion) Which() I_exampleUnionTag {
	return _m.I_exampleUnionTag
}

func (_m *ExampleUnion) Ordinal() uint64 {
	return uint64(_m.I_exampleUnionTag)
}

func (_m *ExampleUnion) SetVariant(variant uint32) {
	_m.I_exampleUnionTag = ExampleUnionVariant
	_m.Variant = variant
}

func ExampleUnionWithVariant(variant uint32) ExampleUnion {
	var _u ExampleUnion
	_u.SetVariant(variant)
	return _u
}

type I_exampleXUnionTag uint64

const (
	ExampleXUnion_unknownData = 0 // 0x00000000
	ExampleXUnionVariant      = 1 // 0x00000001
)

type ExampleXUnion struct {
	I_exampleXUnionTag `fidl:"x" fidl_size_v1:"24" fidl_alignment_v1:"8"`
	I_unknownData      []byte
	Variant            uint32 `fidl_ordinal:"1"`
}

func (_m *ExampleXUnion) Which() I_exampleXUnionTag {
	switch _m.I_exampleXUnionTag {
	case 1:
		return ExampleXUnionVariant
	default:
		return ExampleXUnion_unknownData
	}
}

func (_m *ExampleXUnion) Ordinal() uint64 {
	return uint64(_m.I_exampleXUnionTag)
}

func (_m *ExampleXUnion) SetVariant(variant uint32) {
	_m.I_exampleXUnionTag = ExampleXUnionVariant
	_m.Variant = variant
}

func ExampleXUnionWithVariant(variant uint32) ExampleXUnion {
	var _u ExampleXUnion
	_u.SetVariant(variant)
	return _u
}

type ExampleTable struct {
	_             struct{} `fidl:"t" fidl_size_v1:"16" fidl_alignment_v1:"8"`
	Member        uint32   `fidl_ordinal:"1"`
	MemberPresent bool
}

func (u *ExampleTable) SetMember(member uint32) {
	u.Member = member
	u.MemberPresent = true
}

func (u *ExampleTable) GetMember() uint32 {
	return u.Member
}

func (u *ExampleTable) GetMemberWithDefault(_default uint32) uint32 {
	if !u.HasMember() {
		return _default
	}
	return u.Member
}

func (u *ExampleTable) HasMember() bool {
	return u.MemberPresent
}

func (u *ExampleTable) ClearMember() {
	u.MemberPresent = false
}

const (
	ExampleProtocolMethodOrdinal    uint64 = 0x42fd6a1b00000000
	ExampleProtocolMethodGenOrdinal uint64 = 0x1b489f95492fd90e
)

type ExampleProtocolWithCtxInterface _bindings.ChannelProxy

func (p *ExampleProtocolWithCtxInterface) Method(ctx_ _bindings.Context, arg exampleusing.Empty) error {
	req_ := &exampleProtocolWithCtxMethodRequest{
		Arg: arg,
	}
	err_ := ((*_bindings.ChannelProxy)(p)).Send(ExampleProtocolMethodGenOrdinal, req_)
	return err_
}

type ExampleProtocolWithCtx interface {
	Method(ctx_ _bindings.Context, arg exampleusing.Empty) error
}

type ExampleProtocolWithCtxTransitionalBase struct{}

type ExampleProtocolWithCtxInterfaceRequest _bindings.InterfaceRequest

func NewExampleProtocolWithCtxInterfaceRequest() (ExampleProtocolWithCtxInterfaceRequest, *ExampleProtocolWithCtxInterface, error) {
	req, cli, err := _bindings.NewInterfaceRequest()
	return ExampleProtocolWithCtxInterfaceRequest(req), (*ExampleProtocolWithCtxInterface)(cli), err
}

type ExampleProtocolWithCtxStub struct {
	Impl ExampleProtocolWithCtx
}

func (s_ *ExampleProtocolWithCtxStub) Dispatch(args_ _bindings.DispatchArgs) (_bindings.Message, bool, error) {
	switch args_.Ordinal {
	case ExampleProtocolMethodOrdinal:
		fallthrough
	case ExampleProtocolMethodGenOrdinal:
		in_ := exampleProtocolWithCtxMethodRequest{}
		marshalerCtx, ok := _bindings.GetMarshalerContext(args_.Ctx)
		if !ok {
			return nil, false, _bindings.ErrMissingMarshalerContext
		}
		if _, _, err_ := _bindings.UnmarshalWithContext2(marshalerCtx, args_.Bytes, args_.HandleInfos, &in_); err_ != nil {
			return nil, false, err_
		}
		err_ := s_.Impl.Method(args_.Ctx, in_.Arg)
		return nil, false, err_
	}
	return nil, false, _bindings.ErrUnknownOrdinal
}

type ExampleProtocolService struct {
	_bindings.BindingSet
}

func (s *ExampleProtocolService) EventProxyFor(key _bindings.BindingKey) (*ExampleProtocolEventProxy, bool) {
	pxy, err := s.BindingSet.ProxyFor(key)
	return (*ExampleProtocolEventProxy)(pxy), err
}

type ExampleProtocolEventProxy _bindings.ChannelProxy
