# automatically generated by the FlatBuffers compiler, do not modify

# namespace: tosa

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

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

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

    @classmethod
    def GetRootAsResizeAttribute(cls, buf, offset=0):
        """This method is deprecated. Please switch to GetRootAs."""
        return cls.GetRootAs(buf, offset)
    @classmethod
    def ResizeAttributeBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
        return flatbuffers.util.BufferHasIdentifier(buf, offset, b"\x54\x4F\x53\x41", size_prefixed=size_prefixed)

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

    # ResizeAttribute
    def Scale(self, j):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
        if o != 0:
            a = self._tab.Vector(o)
            return self._tab.Get(flatbuffers.number_types.Int16Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 2))
        return 0

    # ResizeAttribute
    def ScaleAsNumpy(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
        if o != 0:
            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int16Flags, o)
        return 0

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

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

    # ResizeAttribute
    def Offset(self, j):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            a = self._tab.Vector(o)
            return self._tab.Get(flatbuffers.number_types.Int16Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 2))
        return 0

    # ResizeAttribute
    def OffsetAsNumpy(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int16Flags, o)
        return 0

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

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

    # ResizeAttribute
    def Border(self, j):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        if o != 0:
            a = self._tab.Vector(o)
            return self._tab.Get(flatbuffers.number_types.Int16Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 2))
        return 0

    # ResizeAttribute
    def BorderAsNumpy(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        if o != 0:
            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int16Flags, o)
        return 0

    # ResizeAttribute
    def BorderLength(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        if o != 0:
            return self._tab.VectorLen(o)
        return 0

    # ResizeAttribute
    def BorderIsNone(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        return o == 0

    # ResizeAttribute
    def Mode(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
        return 0

def ResizeAttributeStart(builder):
    builder.StartObject(4)

def Start(builder):
    ResizeAttributeStart(builder)

def ResizeAttributeAddScale(builder, scale):
    builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(scale), 0)

def AddScale(builder, scale):
    ResizeAttributeAddScale(builder, scale)

def ResizeAttributeStartScaleVector(builder, numElems):
    return builder.StartVector(2, numElems, 2)

def StartScaleVector(builder, numElems: int) -> int:
    return ResizeAttributeStartScaleVector(builder, numElems)

def ResizeAttributeAddOffset(builder, offset):
    builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(offset), 0)

def AddOffset(builder, offset):
    ResizeAttributeAddOffset(builder, offset)

def ResizeAttributeStartOffsetVector(builder, numElems):
    return builder.StartVector(2, numElems, 2)

def StartOffsetVector(builder, numElems: int) -> int:
    return ResizeAttributeStartOffsetVector(builder, numElems)

def ResizeAttributeAddBorder(builder, border):
    builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(border), 0)

def AddBorder(builder, border):
    ResizeAttributeAddBorder(builder, border)

def ResizeAttributeStartBorderVector(builder, numElems):
    return builder.StartVector(2, numElems, 2)

def StartBorderVector(builder, numElems: int) -> int:
    return ResizeAttributeStartBorderVector(builder, numElems)

def ResizeAttributeAddMode(builder, mode):
    builder.PrependUint32Slot(3, mode, 0)

def AddMode(builder, mode):
    ResizeAttributeAddMode(builder, mode)

def ResizeAttributeEnd(builder):
    return builder.EndObject()

def End(builder):
    return ResizeAttributeEnd(builder)
