# automatically generated by the FlatBuffers compiler, do not modify

# namespace: reflection

import flatbuffers
from flatbuffers.compat import import_numpy
np = import_numpy()

class Schema(object):
    __slots__ = ['_tab']

    @classmethod
    def GetRootAs(cls, buf, offset=0):
        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
        x = Schema()
        x.Init(buf, n + offset)
        return x

    @classmethod
    def GetRootAsSchema(cls, buf, offset=0):
        """This method is deprecated. Please switch to GetRootAs."""
        return cls.GetRootAs(buf, offset)
    @classmethod
    def SchemaBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
        return flatbuffers.util.BufferHasIdentifier(buf, offset, b"\x42\x46\x42\x53", size_prefixed=size_prefixed)

    # Schema
    def Init(self, buf, pos):
        self._tab = flatbuffers.table.Table(buf, pos)

    # Schema
    def Objects(self, j):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
        if o != 0:
            x = self._tab.Vector(o)
            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
            x = self._tab.Indirect(x)
            from reflection.Object import Object
            obj = Object()
            obj.Init(self._tab.Bytes, x)
            return obj
        return None

    # Schema
    def ObjectsLength(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
        if o != 0:
            return self._tab.VectorLen(o)
        return 0

    # Schema
    def ObjectsIsNone(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
        return o == 0

    # Schema
    def Enums(self, j):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            x = self._tab.Vector(o)
            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
            x = self._tab.Indirect(x)
            from reflection.Enum import Enum
            obj = Enum()
            obj.Init(self._tab.Bytes, x)
            return obj
        return None

    # Schema
    def EnumsLength(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            return self._tab.VectorLen(o)
        return 0

    # Schema
    def EnumsIsNone(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        return o == 0

    # Schema
    def FileIdent(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        if o != 0:
            return self._tab.String(o + self._tab.Pos)
        return None

    # Schema
    def FileExt(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
        if o != 0:
            return self._tab.String(o + self._tab.Pos)
        return None

    # Schema
    def RootTable(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
        if o != 0:
            x = self._tab.Indirect(o + self._tab.Pos)
            from reflection.Object import Object
            obj = Object()
            obj.Init(self._tab.Bytes, x)
            return obj
        return None

    # Schema
    def Services(self, j):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
        if o != 0:
            x = self._tab.Vector(o)
            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
            x = self._tab.Indirect(x)
            from reflection.Service import Service
            obj = Service()
            obj.Init(self._tab.Bytes, x)
            return obj
        return None

    # Schema
    def ServicesLength(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
        if o != 0:
            return self._tab.VectorLen(o)
        return 0

    # Schema
    def ServicesIsNone(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
        return o == 0

    # Schema
    def AdvancedFeatures(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos)
        return 0

    # All the files used in this compilation. Files are relative to where
    # flatc was invoked.
    # Schema
    def FbsFiles(self, j):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
        if o != 0:
            x = self._tab.Vector(o)
            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
            x = self._tab.Indirect(x)
            from reflection.SchemaFile import SchemaFile
            obj = SchemaFile()
            obj.Init(self._tab.Bytes, x)
            return obj
        return None

    # Schema
    def FbsFilesLength(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
        if o != 0:
            return self._tab.VectorLen(o)
        return 0

    # Schema
    def FbsFilesIsNone(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
        return o == 0

def SchemaStart(builder): builder.StartObject(8)
def Start(builder):
    return SchemaStart(builder)
def SchemaAddObjects(builder, objects): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(objects), 0)
def AddObjects(builder, objects):
    return SchemaAddObjects(builder, objects)
def SchemaStartObjectsVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def StartObjectsVector(builder, numElems):
    return SchemaStartObjectsVector(builder, numElems)
def SchemaAddEnums(builder, enums): builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(enums), 0)
def AddEnums(builder, enums):
    return SchemaAddEnums(builder, enums)
def SchemaStartEnumsVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def StartEnumsVector(builder, numElems):
    return SchemaStartEnumsVector(builder, numElems)
def SchemaAddFileIdent(builder, fileIdent): builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(fileIdent), 0)
def AddFileIdent(builder, fileIdent):
    return SchemaAddFileIdent(builder, fileIdent)
def SchemaAddFileExt(builder, fileExt): builder.PrependUOffsetTRelativeSlot(3, flatbuffers.number_types.UOffsetTFlags.py_type(fileExt), 0)
def AddFileExt(builder, fileExt):
    return SchemaAddFileExt(builder, fileExt)
def SchemaAddRootTable(builder, rootTable): builder.PrependUOffsetTRelativeSlot(4, flatbuffers.number_types.UOffsetTFlags.py_type(rootTable), 0)
def AddRootTable(builder, rootTable):
    return SchemaAddRootTable(builder, rootTable)
def SchemaAddServices(builder, services): builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(services), 0)
def AddServices(builder, services):
    return SchemaAddServices(builder, services)
def SchemaStartServicesVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def StartServicesVector(builder, numElems):
    return SchemaStartServicesVector(builder, numElems)
def SchemaAddAdvancedFeatures(builder, advancedFeatures): builder.PrependUint64Slot(6, advancedFeatures, 0)
def AddAdvancedFeatures(builder, advancedFeatures):
    return SchemaAddAdvancedFeatures(builder, advancedFeatures)
def SchemaAddFbsFiles(builder, fbsFiles): builder.PrependUOffsetTRelativeSlot(7, flatbuffers.number_types.UOffsetTFlags.py_type(fbsFiles), 0)
def AddFbsFiles(builder, fbsFiles):
    return SchemaAddFbsFiles(builder, fbsFiles)
def SchemaStartFbsFilesVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def StartFbsFilesVector(builder, numElems):
    return SchemaStartFbsFilesVector(builder, numElems)
def SchemaEnd(builder): return builder.EndObject()
def End(builder):
    return SchemaEnd(builder)