// Code generated by fidlgen; DO NOT EDIT.

package error

import (
	_bindings "syscall/zx/fidl"
)

type ExampleFooResponse struct {
	_ struct{} `fidl:"s" fidl_size_v1:"8" fidl_alignment_v1:"8"`
	Y int64    `fidl_offset_v1:"0"`
}

var _mExampleFooResponse = _bindings.CreateLazyMarshaler(ExampleFooResponse{})

func (msg *ExampleFooResponse) Marshaler() _bindings.Marshaler {
	return _mExampleFooResponse
}

type exampleWithCtxFooRequest struct {
	_ struct{} `fidl:"s" fidl_size_v1:"16" fidl_alignment_v1:"8"`
	S string   `fidl_offset_v1:"0" fidl_bounds:""`
}

var _mexampleWithCtxFooRequest = _bindings.CreateLazyMarshaler(exampleWithCtxFooRequest{})

func (msg *exampleWithCtxFooRequest) Marshaler() _bindings.Marshaler {
	return _mexampleWithCtxFooRequest
}

type exampleWithCtxFooResponse struct {
	_      struct{}         `fidl:"s" fidl_size_v1:"24" fidl_alignment_v1:"8"`
	Result ExampleFooResult `fidl_offset_v1:"0"`
}

var _mexampleWithCtxFooResponse = _bindings.CreateLazyMarshaler(exampleWithCtxFooResponse{})

func (msg *exampleWithCtxFooResponse) Marshaler() _bindings.Marshaler {
	return _mexampleWithCtxFooResponse
}

type I_exampleFooResultTag uint64

const (
	ExampleFooResultResponse = 1 // 0x00000001
	ExampleFooResultErr      = 2 // 0x00000002
)

type ExampleFooResult struct {
	I_exampleFooResultTag `fidl:"x!" fidl_size_v1:"24" fidl_alignment_v1:"8" fidl_resource:"false"`
	Response              ExampleFooResponse `fidl_ordinal:"1"`
	Err                   uint32             `fidl_ordinal:"2"`
}

func (_m *ExampleFooResult) reset() {
	switch _m.I_exampleFooResultTag {
	case 1:
		var _zeroed ExampleFooResponse
		_m.Response = _zeroed
	case 2:
		var _zeroed uint32
		_m.Err = _zeroed
	}
}

func (_m *ExampleFooResult) Which() I_exampleFooResultTag {
	return _m.I_exampleFooResultTag
}

func (_m *ExampleFooResult) Ordinal() uint64 {
	return uint64(_m.I_exampleFooResultTag)
}

func (_m *ExampleFooResult) SetResponse(response ExampleFooResponse) {
	_m.reset()
	_m.I_exampleFooResultTag = ExampleFooResultResponse
	_m.Response = response
}

func ExampleFooResultWithResponse(response ExampleFooResponse) ExampleFooResult {
	var _u ExampleFooResult
	_u.SetResponse(response)
	return _u
}

func (_m *ExampleFooResult) SetErr(err uint32) {
	_m.reset()
	_m.I_exampleFooResultTag = ExampleFooResultErr
	_m.Err = err
}

func ExampleFooResultWithErr(err uint32) ExampleFooResult {
	var _u ExampleFooResult
	_u.SetErr(err)
	return _u
}

const (
	ExampleFooOrdinal uint64 = 0x57e41804562237ae
)

type ExampleWithCtxInterface _bindings.ChannelProxy

func (p *ExampleWithCtxInterface) Foo(ctx_ _bindings.Context, s string) (ExampleFooResult, error) {
	req_ := &exampleWithCtxFooRequest{
		S: s,
	}
	resp_ := &exampleWithCtxFooResponse{}
	err_ := ((*_bindings.ChannelProxy)(p)).Call(ExampleFooOrdinal, req_, resp_)
	return resp_.Result, err_
}

type ExampleWithCtx interface {
	Foo(ctx_ _bindings.Context, s string) (ExampleFooResult, error)
}

type ExampleWithCtxTransitionalBase struct{}

type ExampleWithCtxInterfaceRequest _bindings.InterfaceRequest

func NewExampleWithCtxInterfaceRequest() (ExampleWithCtxInterfaceRequest, *ExampleWithCtxInterface, error) {
	req, cli, err := _bindings.NewInterfaceRequest()
	return ExampleWithCtxInterfaceRequest(req), (*ExampleWithCtxInterface)(cli), err
}

type ExampleWithCtxStub struct {
	Impl ExampleWithCtx
}

func (s_ *ExampleWithCtxStub) Dispatch(args_ _bindings.DispatchArgs) (_bindings.Message, bool, error) {
	switch args_.Ordinal {
	case ExampleFooOrdinal:
		in_ := exampleWithCtxFooRequest{}
		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_
		}
		result, err_ := s_.Impl.Foo(args_.Ctx, in_.S)
		out_ := exampleWithCtxFooResponse{}
		out_.Result = result
		return &out_, true, err_
	}
	return nil, false, _bindings.ErrUnknownOrdinal
}

type ExampleEventProxy _bindings.ChannelProxy
