// Code generated by the FlatBuffers compiler. DO NOT EDIT.

package order

import (
	flatbuffers "github.com/google/flatbuffers/go"

	Pizza "Pizza"
)

type FoodT struct {
	Pizza *Pizza.PizzaT `json:"pizza"`
	PizzaTest *Pizza.PizzaT `json:"pizza_test"`
}

func (t *FoodT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
	if t == nil { return 0 }
	pizzaOffset := t.Pizza.Pack(builder)
	pizzaTestOffset := t.PizzaTest.Pack(builder)
	FoodStart(builder)
	FoodAddPizza(builder, pizzaOffset)
	FoodAddPizzaTest(builder, pizzaTestOffset)
	return FoodEnd(builder)
}

func (rcv *Food) UnPackTo(t *FoodT) {
	t.Pizza = rcv.Pizza(nil).UnPack()
	t.PizzaTest = rcv.PizzaTest(nil).UnPack()
}

func (rcv *Food) UnPack() *FoodT {
	if rcv == nil { return nil }
	t := &FoodT{}
	rcv.UnPackTo(t)
	return t
}

type Food struct {
	_tab flatbuffers.Table
}

func GetRootAsFood(buf []byte, offset flatbuffers.UOffsetT) *Food {
	n := flatbuffers.GetUOffsetT(buf[offset:])
	x := &Food{}
	x.Init(buf, n+offset)
	return x
}

func GetSizePrefixedRootAsFood(buf []byte, offset flatbuffers.UOffsetT) *Food {
	n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
	x := &Food{}
	x.Init(buf, n+offset+flatbuffers.SizeUint32)
	return x
}

func (rcv *Food) Init(buf []byte, i flatbuffers.UOffsetT) {
	rcv._tab.Bytes = buf
	rcv._tab.Pos = i
}

func (rcv *Food) Table() flatbuffers.Table {
	return rcv._tab
}

func (rcv *Food) Pizza(obj *Pizza.Pizza) *Pizza.Pizza {
	o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
	if o != 0 {
		x := rcv._tab.Indirect(o + rcv._tab.Pos)
		if obj == nil {
			obj = new(Pizza.Pizza)
		}
		obj.Init(rcv._tab.Bytes, x)
		return obj
	}
	return nil
}

func (rcv *Food) PizzaTest(obj *Pizza.Pizza) *Pizza.Pizza {
	o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
	if o != 0 {
		x := rcv._tab.Indirect(o + rcv._tab.Pos)
		if obj == nil {
			obj = new(Pizza.Pizza)
		}
		obj.Init(rcv._tab.Bytes, x)
		return obj
	}
	return nil
}

func FoodStart(builder *flatbuffers.Builder) {
	builder.StartObject(2)
}
func FoodAddPizza(builder *flatbuffers.Builder, pizza flatbuffers.UOffsetT) {
	builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(pizza), 0)
}
func FoodAddPizzaTest(builder *flatbuffers.Builder, pizzaTest flatbuffers.UOffsetT) {
	builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(pizzaTest), 0)
}
func FoodEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
	return builder.EndObject()
}
