// Code generated by fidlgen; DO NOT EDIT.

package versions

import (
	_strings "strings"
	_bindings "syscall/zx/fidl"
)

const (
	AddedAtHead bool   = true
	Const       uint32 = 0
)

var _ _bindings.Enum = Enum(0)

type Enum uint32

const (
	EnumA Enum = 1

	// Enum_Unknown is the default unknown placeholder.
	Enum_Unknown Enum = 0xffffffff
)

func (_ Enum) I_EnumValues() []Enum {
	return []Enum{
		EnumA,
	}
}

func (_ Enum) I_EnumIsStrict() bool {
	return false
}

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

func (x Enum) String() string {
	switch x {
	case 1:
		return "A"
	}
	return "Unknown"
}

var _ _bindings.Bits = Bits(0)

type Bits uint32

const (
	BitsA     Bits = 1
	Bits_Mask Bits = 1
)

func (_ Bits) I_BitsMask() Bits {
	return Bits_Mask
}

func (_ Bits) I_BitsIsStrict() bool {
	return false
}

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

func (x Bits) GetUnknownBits() uint64 {
	return uint64(^Bits_Mask & x)
}

func (x Bits) InvertBits() Bits {
	return Bits_Mask & ^x
}

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

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

func (x Bits) String() string {
	var buf _strings.Builder
	if 1&x != 0 {
		if buf.Len() != 0 {
			buf.WriteRune('|')
		}
		buf.WriteString("A")
	}
	if buf.Len() == 0 {
		buf.WriteString("<empty bits>")
	}
	return buf.String()
}

type Struct struct {
	_ struct{} `fidl:"s" fidl_size_v2:"4" fidl_alignment_v2:"4"`
	X uint32   `fidl_offset_v2:"0"`
}

var _mStruct = _bindings.CreateLazyMarshaler(Struct{})

func (msg *Struct) Marshaler() _bindings.Marshaler {
	return _mStruct
}

type I_unionTag uint64

const (
	Union_unknownData = 0 // 0x00000000
	UnionX            = 1 // 0x00000001
)

type Union struct {
	I_unionTag    `fidl:"x" fidl_size_v2:"16" fidl_alignment_v2:"8" fidl_resource:"false"`
	I_unknownData interface{}
	X             uint32 `fidl_ordinal:"1"`
}

var _mUnion = _bindings.CreateLazyMarshaler(Union{})

func (msg *Union) Marshaler() _bindings.Marshaler {
	return _mUnion
}

func (_m *Union) reset() {
	switch _m.I_unionTag {
	case 1:
		var _zeroed uint32
		_m.X = _zeroed
	default:
		var _zeroed interface{}
		_m.I_unknownData = _zeroed
	}
}

func (_m *Union) Which() I_unionTag {
	switch _m.I_unionTag {
	case 1:
		return UnionX
	default:
		return Union_unknownData
	}
}

func (_m *Union) Ordinal() uint64 {
	return uint64(_m.I_unionTag)
}

func (_m *Union) SetX(x uint32) {
	_m.reset()
	_m.I_unionTag = UnionX
	_m.X = x
}

func UnionWithX(x uint32) Union {
	var _u Union
	_u.SetX(x)
	return _u
}
func (_m *Union) GetUnknownData() _bindings.UnknownData {
	return _m.I_unknownData.(_bindings.UnknownData)
}

type Table struct {
	_             struct{} `fidl:"t" fidl_size_v2:"16" fidl_alignment_v2:"8" fidl_resource:"false"`
	I_unknownData interface{}
	X             uint32 `fidl_ordinal:"1"`
	XPresent      bool
}

var _mTable = _bindings.CreateLazyMarshaler(Table{})

func (msg *Table) Marshaler() _bindings.Marshaler {
	return _mTable
}

func (u *Table) SetX(x uint32) {
	u.X = x
	u.XPresent = true
}

func (u *Table) GetX() uint32 {
	return u.X
}

func (u *Table) GetXWithDefault(_default uint32) uint32 {
	if !u.HasX() {
		return _default
	}
	return u.X
}

func (u *Table) HasX() bool {
	return u.XPresent
}

func (u *Table) ClearX() {
	u.XPresent = false
}

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

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

const ()

type OtherProtocolWithCtxInterface _bindings.ChannelProxy

type OtherProtocolWithCtx interface {
}

type OtherProtocolWithCtxTransitionalBase struct{}

type OtherProtocolWithCtxInterfaceRequest _bindings.InterfaceRequest

func NewOtherProtocolWithCtxInterfaceRequest() (OtherProtocolWithCtxInterfaceRequest, *OtherProtocolWithCtxInterface, error) {
	req, cli, err := _bindings.NewInterfaceRequest()
	return OtherProtocolWithCtxInterfaceRequest(req), (*OtherProtocolWithCtxInterface)(cli), err
}

type OtherProtocolWithCtxStub struct {
	Impl OtherProtocolWithCtx
}

func (s_ *OtherProtocolWithCtxStub) Dispatch(args_ _bindings.DispatchArgs) (_bindings.Message, bool, error) {
	switch args_.Ordinal {
	}
	return nil, false, _bindings.ErrUnknownOrdinal
}

type OtherProtocolEventProxy _bindings.ChannelProxy

const (
	ProtocolFooOrdinal uint64 = 0x567a8096af6e6139
)

type ProtocolWithCtxInterface _bindings.ChannelProxy

func (p *ProtocolWithCtxInterface) Foo(ctx_ _bindings.Context) error {
	var req_ _bindings.Message
	err_ := ((*_bindings.ChannelProxy)(p)).Send(ProtocolFooOrdinal, req_)
	return err_
}

type ProtocolWithCtx interface {
	Foo(ctx_ _bindings.Context) error
}

type ProtocolWithCtxTransitionalBase struct{}

type ProtocolWithCtxInterfaceRequest _bindings.InterfaceRequest

func NewProtocolWithCtxInterfaceRequest() (ProtocolWithCtxInterfaceRequest, *ProtocolWithCtxInterface, error) {
	req, cli, err := _bindings.NewInterfaceRequest()
	return ProtocolWithCtxInterfaceRequest(req), (*ProtocolWithCtxInterface)(cli), err
}

type ProtocolWithCtxStub struct {
	Impl ProtocolWithCtx
}

func (s_ *ProtocolWithCtxStub) Dispatch(args_ _bindings.DispatchArgs) (_bindings.Message, bool, error) {
	switch args_.Ordinal {
	case ProtocolFooOrdinal:
		err_ := s_.Impl.Foo(args_.Ctx)
		return nil, false, err_
	}
	return nil, false, _bindings.ErrUnknownOrdinal
}

type ProtocolEventProxy _bindings.ChannelProxy
