// Code generated by fidlgen; DO NOT EDIT.

package placementofattributes

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

const (
	ExampleConst uint32 = 0
)

var _ _bindings.Enum = ExampleEnum(0)

type ExampleEnum uint32

const (
	ExampleEnumMember ExampleEnum = 1
)

func (_ ExampleEnum) I_EnumValues() []ExampleEnum {
	return []ExampleEnum{
		ExampleEnumMember,
	}
}

func (_ ExampleEnum) I_EnumIsStrict() bool {
	return true
}

func (x ExampleEnum) IsUnknown() bool {
	switch x {
	case 1:
		return true
	default:
		return false
	}
}

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

var _ _bindings.Bits = ExampleBits(0)

type ExampleBits uint32

const (
	ExampleBitsMember ExampleBits = 1
	ExampleBits_Mask  ExampleBits = 1
)

func (_ ExampleBits) I_BitsMask() ExampleBits {
	return ExampleBits_Mask
}

func (_ ExampleBits) I_BitsIsStrict() bool {
	return true
}

func (x ExampleBits) HasUnknownBits() bool {
	return x.GetUnknownBits() != 0
}

func (x ExampleBits) GetUnknownBits() uint64 {
	return uint64(^ExampleBits_Mask & x)
}

func (x ExampleBits) InvertBits() ExampleBits {
	return ExampleBits_Mask & ^x
}

// HasBits validates that all flipped bits in the mask are set.
func (x ExampleBits) HasBits(mask ExampleBits) bool {
	return mask|x == x
}

// ClearBits ensures all flipped bits in the mask are unset.
func (x ExampleBits) ClearBits(mask ExampleBits) ExampleBits {
	return ^mask & x
}

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" fidl_resource:"false"`
	Variant           uint32 `fidl_ordinal:"1"`
}

func (_m *ExampleUnion) reset() {
	switch _m.I_exampleUnionTag {
	case 1:
		var _zeroed uint32
		_m.Variant = _zeroed
	}
}

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.reset()
	_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" fidl_resource:"false"`
	I_unknownData      interface{}
	Variant            uint32 `fidl_ordinal:"1"`
}

func (_m *ExampleXUnion) reset() {
	switch _m.I_exampleXUnionTag {
	case 1:
		var _zeroed uint32
		_m.Variant = _zeroed
	default:
		var _zeroed interface{}
		_m.I_unknownData = _zeroed
	}
}

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.reset()
	_m.I_exampleXUnionTag = ExampleXUnionVariant
	_m.Variant = variant
}

func ExampleXUnionWithVariant(variant uint32) ExampleXUnion {
	var _u ExampleXUnion
	_u.SetVariant(variant)
	return _u
}
func (_m *ExampleXUnion) GetUnknownData() _bindings.UnknownData {
	return _m.I_unknownData.(_bindings.UnknownData)
}

type ExampleTable struct {
	_             struct{} `fidl:"t" fidl_size_v1:"16" fidl_alignment_v1:"8" fidl_resource:"false"`
	I_unknownData interface{}
	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
}

func (u *ExampleTable) HasUnknownData() bool {
	return u.I_unknownData != nil
}

func (u *ExampleTable) GetUnknownData() map[uint64]_bindings.UnknownData {
	return u.I_unknownData.(map[uint64]_bindings.UnknownData)
}

const (
	ExampleProtocolMethodOrdinal uint64 = 0x207d2f81c0ddb184
)

type ExampleProtocolWithCtxInterface _bindings.ChannelProxy

func (p *ExampleProtocolWithCtxInterface) Method(ctx_ _bindings.Context, arg exampleusing.Empty) error {
	req_ := &exampleProtocolWithCtxMethodRequest{
		Arg: arg,
	}
	err_ := ((*_bindings.ChannelProxy)(p)).Send(ExampleProtocolMethodOrdinal, 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:
		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 ExampleProtocolEventProxy _bindings.ChannelProxy
