Monster

--[[ MyGame.Example.Monster

  Automatically generated by the FlatBuffers compiler, do not modify.
  Or modify. I'm a message, not a cop.

  flatc version: 23.5.9

  Declared by  : //monster_test.fbs
  Rooting type : MyGame.Example.Monster (//monster_test.fbs)

--]]

local __MyGame_Example_Ability = require('MyGame.Example.Ability')
local __MyGame_Example_Referrable = require('MyGame.Example.Referrable')
local __MyGame_Example_Stat = require('MyGame.Example.Stat')
local __MyGame_Example_Test = require('MyGame.Example.Test')
local __MyGame_Example_Vec3 = require('MyGame.Example.Vec3')
local __MyGame_InParentNamespace = require('MyGame.InParentNamespace')
local flatbuffers = require('flatbuffers')

-- an example documentation comment: "monster object"
local Monster = {}
local mt = {}

function Monster.New()
  local o = {}
  setmetatable(o, {__index = mt})
  return o
end

function Monster.GetRootAsMonster(buf, offset)
  if type(buf) == "string" then
    buf = flatbuffers.binaryArray.New(buf)
  end

  local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)
  local o = Monster.New()
  o:Init(buf, n + offset)
  return o
end

function mt:Init(buf, pos)
  self.view = flatbuffers.view.New(buf, pos)
end

function mt:Pos()
  local o = self.view:Offset(4)
  if o ~= 0 then
    local x = self.view.pos + o
    local obj = __MyGame_Example_Vec3.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:Mana()
  local o = self.view:Offset(6)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Int16, self.view.pos + o)
  end
  return 150
end

function mt:Hp()
  local o = self.view:Offset(8)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Int16, self.view.pos + o)
  end
  return 100
end

function mt:Name()
  local o = self.view:Offset(10)
  if o ~= 0 then
    return self.view:String(self.view.pos + o)
  end
end

function mt:Inventory(j)
  local o = self.view:Offset(14)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Uint8, a + ((j-1) * 1))
  end
  return 0
end

function mt:InventoryAsString(start, stop)
  return self.view:VectorAsString(14, start, stop)
end

function mt:InventoryLength()
  local o = self.view:Offset(14)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:Color()
  local o = self.view:Offset(16)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint8, self.view.pos + o)
  end
  return 8
end

function mt:TestType()
  local o = self.view:Offset(18)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint8, self.view.pos + o)
  end
  return 0
end

function mt:Test()
  local o = self.view:Offset(20)
  if o ~= 0 then
   local obj = flatbuffers.view.New(flatbuffers.binaryArray.New(0), 0)
    self.view:Union(obj, o)
    return obj
  end
end

function mt:Test4(j)
  local o = self.view:Offset(22)
  if o ~= 0 then
    local x = self.view:Vector(o)
    x = x + ((j-1) * 4)
    local obj = __MyGame_Example_Test.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:Test4Length()
  local o = self.view:Offset(22)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:Testarrayofstring(j)
  local o = self.view:Offset(24)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:String(a + ((j-1) * 4))
  end
  return ''
end

function mt:TestarrayofstringLength()
  local o = self.view:Offset(24)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

-- an example documentation comment: this will end up in the generated code
-- multiline too
function mt:Testarrayoftables(j)
  local o = self.view:Offset(26)
  if o ~= 0 then
    local x = self.view:Vector(o)
    x = x + ((j-1) * 4)
    x = self.view:Indirect(x)
    local obj = Monster.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:TestarrayoftablesLength()
  local o = self.view:Offset(26)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:Enemy()
  local o = self.view:Offset(28)
  if o ~= 0 then
    local x = self.view:Indirect(self.view.pos + o)
    local obj = Monster.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:Testnestedflatbuffer(j)
  local o = self.view:Offset(30)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Uint8, a + ((j-1) * 1))
  end
  return 0
end

function mt:TestnestedflatbufferAsString(start, stop)
  return self.view:VectorAsString(30, start, stop)
end

function mt:TestnestedflatbufferLength()
  local o = self.view:Offset(30)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:Testempty()
  local o = self.view:Offset(32)
  if o ~= 0 then
    local x = self.view:Indirect(self.view.pos + o)
    local obj = __MyGame_Example_Stat.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:Testbool()
  local o = self.view:Offset(34)
  if o ~= 0 then
    return (self.view:Get(flatbuffers.N.Bool, self.view.pos + o) ~=0)
  end
  return false
end

function mt:Testhashs32Fnv1()
  local o = self.view:Offset(36)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Int32, self.view.pos + o)
  end
  return 0
end

function mt:Testhashu32Fnv1()
  local o = self.view:Offset(38)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint32, self.view.pos + o)
  end
  return 0
end

function mt:Testhashs64Fnv1()
  local o = self.view:Offset(40)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Int64, self.view.pos + o)
  end
  return 0
end

function mt:Testhashu64Fnv1()
  local o = self.view:Offset(42)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint64, self.view.pos + o)
  end
  return 0
end

function mt:Testhashs32Fnv1a()
  local o = self.view:Offset(44)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Int32, self.view.pos + o)
  end
  return 0
end

function mt:Testhashu32Fnv1a()
  local o = self.view:Offset(46)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint32, self.view.pos + o)
  end
  return 0
end

function mt:Testhashs64Fnv1a()
  local o = self.view:Offset(48)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Int64, self.view.pos + o)
  end
  return 0
end

function mt:Testhashu64Fnv1a()
  local o = self.view:Offset(50)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint64, self.view.pos + o)
  end
  return 0
end

function mt:Testarrayofbools(j)
  local o = self.view:Offset(52)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Bool, a + ((j-1) * 1))
  end
  return 0
end

function mt:TestarrayofboolsAsString(start, stop)
  return self.view:VectorAsString(52, start, stop)
end

function mt:TestarrayofboolsLength()
  local o = self.view:Offset(52)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:Testf()
  local o = self.view:Offset(54)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float32, self.view.pos + o)
  end
  return 3.14159
end

function mt:Testf2()
  local o = self.view:Offset(56)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float32, self.view.pos + o)
  end
  return 3.0
end

function mt:Testf3()
  local o = self.view:Offset(58)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float32, self.view.pos + o)
  end
  return 0.0
end

function mt:Testarrayofstring2(j)
  local o = self.view:Offset(60)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:String(a + ((j-1) * 4))
  end
  return ''
end

function mt:Testarrayofstring2Length()
  local o = self.view:Offset(60)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:Testarrayofsortedstruct(j)
  local o = self.view:Offset(62)
  if o ~= 0 then
    local x = self.view:Vector(o)
    x = x + ((j-1) * 8)
    local obj = __MyGame_Example_Ability.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:TestarrayofsortedstructLength()
  local o = self.view:Offset(62)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:Flex(j)
  local o = self.view:Offset(64)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Uint8, a + ((j-1) * 1))
  end
  return 0
end

function mt:FlexAsString(start, stop)
  return self.view:VectorAsString(64, start, stop)
end

function mt:FlexLength()
  local o = self.view:Offset(64)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:Test5(j)
  local o = self.view:Offset(66)
  if o ~= 0 then
    local x = self.view:Vector(o)
    x = x + ((j-1) * 4)
    local obj = __MyGame_Example_Test.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:Test5Length()
  local o = self.view:Offset(66)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:VectorOfLongs(j)
  local o = self.view:Offset(68)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Int64, a + ((j-1) * 8))
  end
  return 0
end

function mt:VectorOfLongsLength()
  local o = self.view:Offset(68)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:VectorOfDoubles(j)
  local o = self.view:Offset(70)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Float64, a + ((j-1) * 8))
  end
  return 0
end

function mt:VectorOfDoublesLength()
  local o = self.view:Offset(70)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:ParentNamespaceTest()
  local o = self.view:Offset(72)
  if o ~= 0 then
    local x = self.view:Indirect(self.view.pos + o)
    local obj = __MyGame_InParentNamespace.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:VectorOfReferrables(j)
  local o = self.view:Offset(74)
  if o ~= 0 then
    local x = self.view:Vector(o)
    x = x + ((j-1) * 4)
    x = self.view:Indirect(x)
    local obj = __MyGame_Example_Referrable.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:VectorOfReferrablesLength()
  local o = self.view:Offset(74)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:SingleWeakReference()
  local o = self.view:Offset(76)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint64, self.view.pos + o)
  end
  return 0
end

function mt:VectorOfWeakReferences(j)
  local o = self.view:Offset(78)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Uint64, a + ((j-1) * 8))
  end
  return 0
end

function mt:VectorOfWeakReferencesLength()
  local o = self.view:Offset(78)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:VectorOfStrongReferrables(j)
  local o = self.view:Offset(80)
  if o ~= 0 then
    local x = self.view:Vector(o)
    x = x + ((j-1) * 4)
    x = self.view:Indirect(x)
    local obj = __MyGame_Example_Referrable.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:VectorOfStrongReferrablesLength()
  local o = self.view:Offset(80)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:CoOwningReference()
  local o = self.view:Offset(82)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint64, self.view.pos + o)
  end
  return 0
end

function mt:VectorOfCoOwningReferences(j)
  local o = self.view:Offset(84)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Uint64, a + ((j-1) * 8))
  end
  return 0
end

function mt:VectorOfCoOwningReferencesLength()
  local o = self.view:Offset(84)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:NonOwningReference()
  local o = self.view:Offset(86)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint64, self.view.pos + o)
  end
  return 0
end

function mt:VectorOfNonOwningReferences(j)
  local o = self.view:Offset(88)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Uint64, a + ((j-1) * 8))
  end
  return 0
end

function mt:VectorOfNonOwningReferencesLength()
  local o = self.view:Offset(88)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:AnyUniqueType()
  local o = self.view:Offset(90)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint8, self.view.pos + o)
  end
  return 0
end

function mt:AnyUnique()
  local o = self.view:Offset(92)
  if o ~= 0 then
   local obj = flatbuffers.view.New(flatbuffers.binaryArray.New(0), 0)
    self.view:Union(obj, o)
    return obj
  end
end

function mt:AnyAmbiguousType()
  local o = self.view:Offset(94)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint8, self.view.pos + o)
  end
  return 0
end

function mt:AnyAmbiguous()
  local o = self.view:Offset(96)
  if o ~= 0 then
   local obj = flatbuffers.view.New(flatbuffers.binaryArray.New(0), 0)
    self.view:Union(obj, o)
    return obj
  end
end

function mt:VectorOfEnums(j)
  local o = self.view:Offset(98)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Uint8, a + ((j-1) * 1))
  end
  return 0
end

function mt:VectorOfEnumsAsString(start, stop)
  return self.view:VectorAsString(98, start, stop)
end

function mt:VectorOfEnumsLength()
  local o = self.view:Offset(98)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:SignedEnum()
  local o = self.view:Offset(100)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Int8, self.view.pos + o)
  end
  return -1
end

function mt:Testrequirednestedflatbuffer(j)
  local o = self.view:Offset(102)
  if o ~= 0 then
    local a = self.view:Vector(o)
    return self.view:Get(flatbuffers.N.Uint8, a + ((j-1) * 1))
  end
  return 0
end

function mt:TestrequirednestedflatbufferAsString(start, stop)
  return self.view:VectorAsString(102, start, stop)
end

function mt:TestrequirednestedflatbufferLength()
  local o = self.view:Offset(102)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:ScalarKeySortedTables(j)
  local o = self.view:Offset(104)
  if o ~= 0 then
    local x = self.view:Vector(o)
    x = x + ((j-1) * 4)
    x = self.view:Indirect(x)
    local obj = __MyGame_Example_Stat.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:ScalarKeySortedTablesLength()
  local o = self.view:Offset(104)
  if o ~= 0 then
    return self.view:VectorLen(o)
  end
  return 0
end

function mt:NativeInline()
  local o = self.view:Offset(106)
  if o ~= 0 then
    local x = self.view.pos + o
    local obj = __MyGame_Example_Test.New()
    obj:Init(self.view.bytes, x)
    return obj
  end
end

function mt:LongEnumNonEnumDefault()
  local o = self.view:Offset(108)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint64, self.view.pos + o)
  end
  return 0
end

function mt:LongEnumNormalDefault()
  local o = self.view:Offset(110)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint64, self.view.pos + o)
  end
  return 2
end

function mt:NanDefault()
  local o = self.view:Offset(112)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float32, self.view.pos + o)
  end
  return nan
end

function mt:InfDefault()
  local o = self.view:Offset(114)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float32, self.view.pos + o)
  end
  return inf
end

function mt:PositiveInfDefault()
  local o = self.view:Offset(116)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float32, self.view.pos + o)
  end
  return inf
end

function mt:InfinityDefault()
  local o = self.view:Offset(118)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float32, self.view.pos + o)
  end
  return inf
end

function mt:PositiveInfinityDefault()
  local o = self.view:Offset(120)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float32, self.view.pos + o)
  end
  return inf
end

function mt:NegativeInfDefault()
  local o = self.view:Offset(122)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float32, self.view.pos + o)
  end
  return -inf
end

function mt:NegativeInfinityDefault()
  local o = self.view:Offset(124)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float32, self.view.pos + o)
  end
  return -inf
end

function mt:DoubleInfDefault()
  local o = self.view:Offset(126)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Float64, self.view.pos + o)
  end
  return inf
end

function Monster.Start(builder)
  builder:StartObject(62)
end

function Monster.AddPos(builder, pos)
  builder:PrependStructSlot(0, pos, 0)
end

function Monster.AddMana(builder, mana)
  builder:PrependInt16Slot(1, mana, 150)
end

function Monster.AddHp(builder, hp)
  builder:PrependInt16Slot(2, hp, 100)
end

function Monster.AddName(builder, name)
  builder:PrependUOffsetTRelativeSlot(3, name, 0)
end

function Monster.AddInventory(builder, inventory)
  builder:PrependUOffsetTRelativeSlot(5, inventory, 0)
end

function Monster.StartInventoryVector(builder, numElems)
  return builder:StartVector(1, numElems, 1)
end

function Monster.AddColor(builder, color)
  builder:PrependUint8Slot(6, color, 8)
end

function Monster.AddTestType(builder, testType)
  builder:PrependUint8Slot(7, testType, 0)
end

function Monster.AddTest(builder, test)
  builder:PrependUOffsetTRelativeSlot(8, test, 0)
end

function Monster.AddTest4(builder, test4)
  builder:PrependUOffsetTRelativeSlot(9, test4, 0)
end

function Monster.StartTest4Vector(builder, numElems)
  return builder:StartVector(4, numElems, 2)
end

function Monster.AddTestarrayofstring(builder, testarrayofstring)
  builder:PrependUOffsetTRelativeSlot(10, testarrayofstring, 0)
end

function Monster.StartTestarrayofstringVector(builder, numElems)
  return builder:StartVector(4, numElems, 4)
end

function Monster.AddTestarrayoftables(builder, testarrayoftables)
  builder:PrependUOffsetTRelativeSlot(11, testarrayoftables, 0)
end

function Monster.StartTestarrayoftablesVector(builder, numElems)
  return builder:StartVector(4, numElems, 4)
end

function Monster.AddEnemy(builder, enemy)
  builder:PrependStructSlot(12, enemy, 0)
end

function Monster.AddTestnestedflatbuffer(builder, testnestedflatbuffer)
  builder:PrependUOffsetTRelativeSlot(13, testnestedflatbuffer, 0)
end

function Monster.StartTestnestedflatbufferVector(builder, numElems)
  return builder:StartVector(1, numElems, 1)
end

function Monster.AddTestempty(builder, testempty)
  builder:PrependStructSlot(14, testempty, 0)
end

function Monster.AddTestbool(builder, testbool)
  builder:PrependBoolSlot(15, testbool, false)
end

function Monster.AddTesthashs32Fnv1(builder, testhashs32Fnv1)
  builder:PrependInt32Slot(16, testhashs32Fnv1, 0)
end

function Monster.AddTesthashu32Fnv1(builder, testhashu32Fnv1)
  builder:PrependUint32Slot(17, testhashu32Fnv1, 0)
end

function Monster.AddTesthashs64Fnv1(builder, testhashs64Fnv1)
  builder:PrependInt64Slot(18, testhashs64Fnv1, 0)
end

function Monster.AddTesthashu64Fnv1(builder, testhashu64Fnv1)
  builder:PrependUint64Slot(19, testhashu64Fnv1, 0)
end

function Monster.AddTesthashs32Fnv1a(builder, testhashs32Fnv1a)
  builder:PrependInt32Slot(20, testhashs32Fnv1a, 0)
end

function Monster.AddTesthashu32Fnv1a(builder, testhashu32Fnv1a)
  builder:PrependUint32Slot(21, testhashu32Fnv1a, 0)
end

function Monster.AddTesthashs64Fnv1a(builder, testhashs64Fnv1a)
  builder:PrependInt64Slot(22, testhashs64Fnv1a, 0)
end

function Monster.AddTesthashu64Fnv1a(builder, testhashu64Fnv1a)
  builder:PrependUint64Slot(23, testhashu64Fnv1a, 0)
end

function Monster.AddTestarrayofbools(builder, testarrayofbools)
  builder:PrependUOffsetTRelativeSlot(24, testarrayofbools, 0)
end

function Monster.StartTestarrayofboolsVector(builder, numElems)
  return builder:StartVector(1, numElems, 1)
end

function Monster.AddTestf(builder, testf)
  builder:PrependFloat32Slot(25, testf, 3.14159)
end

function Monster.AddTestf2(builder, testf2)
  builder:PrependFloat32Slot(26, testf2, 3.0)
end

function Monster.AddTestf3(builder, testf3)
  builder:PrependFloat32Slot(27, testf3, 0.0)
end

function Monster.AddTestarrayofstring2(builder, testarrayofstring2)
  builder:PrependUOffsetTRelativeSlot(28, testarrayofstring2, 0)
end

function Monster.StartTestarrayofstring2Vector(builder, numElems)
  return builder:StartVector(4, numElems, 4)
end

function Monster.AddTestarrayofsortedstruct(builder, testarrayofsortedstruct)
  builder:PrependUOffsetTRelativeSlot(29, testarrayofsortedstruct, 0)
end

function Monster.StartTestarrayofsortedstructVector(builder, numElems)
  return builder:StartVector(8, numElems, 4)
end

function Monster.AddFlex(builder, flex)
  builder:PrependUOffsetTRelativeSlot(30, flex, 0)
end

function Monster.StartFlexVector(builder, numElems)
  return builder:StartVector(1, numElems, 1)
end

function Monster.AddTest5(builder, test5)
  builder:PrependUOffsetTRelativeSlot(31, test5, 0)
end

function Monster.StartTest5Vector(builder, numElems)
  return builder:StartVector(4, numElems, 2)
end

function Monster.AddVectorOfLongs(builder, vectorOfLongs)
  builder:PrependUOffsetTRelativeSlot(32, vectorOfLongs, 0)
end

function Monster.StartVectorOfLongsVector(builder, numElems)
  return builder:StartVector(8, numElems, 8)
end

function Monster.AddVectorOfDoubles(builder, vectorOfDoubles)
  builder:PrependUOffsetTRelativeSlot(33, vectorOfDoubles, 0)
end

function Monster.StartVectorOfDoublesVector(builder, numElems)
  return builder:StartVector(8, numElems, 8)
end

function Monster.AddParentNamespaceTest(builder, parentNamespaceTest)
  builder:PrependStructSlot(34, parentNamespaceTest, 0)
end

function Monster.AddVectorOfReferrables(builder, vectorOfReferrables)
  builder:PrependUOffsetTRelativeSlot(35, vectorOfReferrables, 0)
end

function Monster.StartVectorOfReferrablesVector(builder, numElems)
  return builder:StartVector(4, numElems, 4)
end

function Monster.AddSingleWeakReference(builder, singleWeakReference)
  builder:PrependUint64Slot(36, singleWeakReference, 0)
end

function Monster.AddVectorOfWeakReferences(builder, vectorOfWeakReferences)
  builder:PrependUOffsetTRelativeSlot(37, vectorOfWeakReferences, 0)
end

function Monster.StartVectorOfWeakReferencesVector(builder, numElems)
  return builder:StartVector(8, numElems, 8)
end

function Monster.AddVectorOfStrongReferrables(builder, vectorOfStrongReferrables)
  builder:PrependUOffsetTRelativeSlot(38, vectorOfStrongReferrables, 0)
end

function Monster.StartVectorOfStrongReferrablesVector(builder, numElems)
  return builder:StartVector(4, numElems, 4)
end

function Monster.AddCoOwningReference(builder, coOwningReference)
  builder:PrependUint64Slot(39, coOwningReference, 0)
end

function Monster.AddVectorOfCoOwningReferences(builder, vectorOfCoOwningReferences)
  builder:PrependUOffsetTRelativeSlot(40, vectorOfCoOwningReferences, 0)
end

function Monster.StartVectorOfCoOwningReferencesVector(builder, numElems)
  return builder:StartVector(8, numElems, 8)
end

function Monster.AddNonOwningReference(builder, nonOwningReference)
  builder:PrependUint64Slot(41, nonOwningReference, 0)
end

function Monster.AddVectorOfNonOwningReferences(builder, vectorOfNonOwningReferences)
  builder:PrependUOffsetTRelativeSlot(42, vectorOfNonOwningReferences, 0)
end

function Monster.StartVectorOfNonOwningReferencesVector(builder, numElems)
  return builder:StartVector(8, numElems, 8)
end

function Monster.AddAnyUniqueType(builder, anyUniqueType)
  builder:PrependUint8Slot(43, anyUniqueType, 0)
end

function Monster.AddAnyUnique(builder, anyUnique)
  builder:PrependUOffsetTRelativeSlot(44, anyUnique, 0)
end

function Monster.AddAnyAmbiguousType(builder, anyAmbiguousType)
  builder:PrependUint8Slot(45, anyAmbiguousType, 0)
end

function Monster.AddAnyAmbiguous(builder, anyAmbiguous)
  builder:PrependUOffsetTRelativeSlot(46, anyAmbiguous, 0)
end

function Monster.AddVectorOfEnums(builder, vectorOfEnums)
  builder:PrependUOffsetTRelativeSlot(47, vectorOfEnums, 0)
end

function Monster.StartVectorOfEnumsVector(builder, numElems)
  return builder:StartVector(1, numElems, 1)
end

function Monster.AddSignedEnum(builder, signedEnum)
  builder:PrependInt8Slot(48, signedEnum, -1)
end

function Monster.AddTestrequirednestedflatbuffer(builder, testrequirednestedflatbuffer)
  builder:PrependUOffsetTRelativeSlot(49, testrequirednestedflatbuffer, 0)
end

function Monster.StartTestrequirednestedflatbufferVector(builder, numElems)
  return builder:StartVector(1, numElems, 1)
end

function Monster.AddScalarKeySortedTables(builder, scalarKeySortedTables)
  builder:PrependUOffsetTRelativeSlot(50, scalarKeySortedTables, 0)
end

function Monster.StartScalarKeySortedTablesVector(builder, numElems)
  return builder:StartVector(4, numElems, 4)
end

function Monster.AddNativeInline(builder, nativeInline)
  builder:PrependStructSlot(51, nativeInline, 0)
end

function Monster.AddLongEnumNonEnumDefault(builder, longEnumNonEnumDefault)
  builder:PrependUint64Slot(52, longEnumNonEnumDefault, 0)
end

function Monster.AddLongEnumNormalDefault(builder, longEnumNormalDefault)
  builder:PrependUint64Slot(53, longEnumNormalDefault, 2)
end

function Monster.AddNanDefault(builder, nanDefault)
  builder:PrependFloat32Slot(54, nanDefault, nan)
end

function Monster.AddInfDefault(builder, infDefault)
  builder:PrependFloat32Slot(55, infDefault, inf)
end

function Monster.AddPositiveInfDefault(builder, positiveInfDefault)
  builder:PrependFloat32Slot(56, positiveInfDefault, inf)
end

function Monster.AddInfinityDefault(builder, infinityDefault)
  builder:PrependFloat32Slot(57, infinityDefault, inf)
end

function Monster.AddPositiveInfinityDefault(builder, positiveInfinityDefault)
  builder:PrependFloat32Slot(58, positiveInfinityDefault, inf)
end

function Monster.AddNegativeInfDefault(builder, negativeInfDefault)
  builder:PrependFloat32Slot(59, negativeInfDefault, -inf)
end

function Monster.AddNegativeInfinityDefault(builder, negativeInfinityDefault)
  builder:PrependFloat32Slot(60, negativeInfinityDefault, -inf)
end

function Monster.AddDoubleInfDefault(builder, doubleInfDefault)
  builder:PrependFloat64Slot(61, doubleInfDefault, inf)
end

function Monster.End(builder)
  return builder:EndObject()
end

return Monster


Ability

--[[ MyGame.Example.Ability

  Automatically generated by the FlatBuffers compiler, do not modify.
  Or modify. I'm a message, not a cop.

  flatc version: 23.5.9

  Declared by  : //monster_test.fbs
  Rooting type : MyGame.Example.Monster (//monster_test.fbs)

--]]

local flatbuffers = require('flatbuffers')

local Ability = {}
local mt = {}

function Ability.New()
  local o = {}
  setmetatable(o, {__index = mt})
  return o
end

function mt:Init(buf, pos)
  self.view = flatbuffers.view.New(buf, pos)
end

function mt:Id()
  return self.view:Get(flatbuffers.N.Uint32, self.view.pos + 0)
end

function mt:Distance()
  return self.view:Get(flatbuffers.N.Uint32, self.view.pos + 4)
end

function Ability.CreateAbility(builder, id, distance)
  builder:Prep(4, 8)
  builder:PrependUint32(distance)
  builder:PrependUint32(id)
  return builder:Offset()
end

return Ability


Race

--[[ MyGame.Example.Race

  Automatically generated by the FlatBuffers compiler, do not modify.
  Or modify. I'm a message, not a cop.

  flatc version: 23.5.9

  Declared by  : //monster_test.fbs
  Rooting type : MyGame.Example.Monster (//monster_test.fbs)

--]]

local Race = {
  None = -1,
  Human = 0,
  Dwarf = 1,
  Elf = 2,
}

return Race


Any

--[[ MyGame.Example.Any

  Automatically generated by the FlatBuffers compiler, do not modify.
  Or modify. I'm a message, not a cop.

  flatc version: 23.5.9

  Declared by  : //monster_test.fbs
  Rooting type : MyGame.Example.Monster (//monster_test.fbs)

--]]

local Any = {
  NONE = 0,
  Monster = 1,
  TestSimpleTableWithEnum = 2,
  MyGame_Example2_Monster = 3,
}

return Any


Referrable

--[[ MyGame.Example.Referrable

  Automatically generated by the FlatBuffers compiler, do not modify.
  Or modify. I'm a message, not a cop.

  flatc version: 23.5.9

  Declared by  : //monster_test.fbs
  Rooting type : MyGame.Example.Monster (//monster_test.fbs)

--]]

local flatbuffers = require('flatbuffers')

local Referrable = {}
local mt = {}

function Referrable.New()
  local o = {}
  setmetatable(o, {__index = mt})
  return o
end

function mt:Init(buf, pos)
  self.view = flatbuffers.view.New(buf, pos)
end

function mt:Id()
  local o = self.view:Offset(4)
  if o ~= 0 then
    return self.view:Get(flatbuffers.N.Uint64, self.view.pos + o)
  end
  return 0
end

function Referrable.Start(builder)
  builder:StartObject(1)
end

function Referrable.AddId(builder, id)
  builder:PrependUint64Slot(0, id, 0)
end

function Referrable.End(builder)
  return builder:EndObject()
end

return Referrable


--[[ MyGame.Example.Vec3

  Automatically generated by the FlatBuffers compiler, do not modify.
  Or modify. I'm a message, not a cop.

  flatc version: 23.5.9

  Declared by  : //monster_test.fbs
  Rooting type : MyGame.Example.Monster (//monster_test.fbs)

--]]

local flatbuffers = require('flatbuffers')

local Vec3 = {}
local mt = {}

function Vec3.New()
  local o = {}
  setmetatable(o, {__index = mt})
  return o
end

function mt:Init(buf, pos)
  self.view = flatbuffers.view.New(buf, pos)
end

function mt:X()
  return self.view:Get(flatbuffers.N.Float32, self.view.pos + 0)
end

function mt:Y()
  return self.view:Get(flatbuffers.N.Float32, self.view.pos + 4)
end

function mt:Z()
  return self.view:Get(flatbuffers.N.Float32, self.view.pos + 8)
end

function mt:Test1()
  return self.view:Get(flatbuffers.N.Float64, self.view.pos + 16)
end

function mt:Test2()
  return self.view:Get(flatbuffers.N.Uint8, self.view.pos + 24)
end

function mt:Test3(obj)
  obj:Init(self.view.bytes, self.view.pos + 26)
  return obj
end

function Vec3.CreateVec3(builder, x, y, z, test1, test2, test3_a, test3_b)
  builder:Prep(8, 32)
  builder:Pad(2)
  builder:Prep(2, 4)
  builder:Pad(1)
  builder:PrependInt8(test3_b)
  builder:PrependInt16(test3_a)
  builder:Pad(1)
  builder:PrependUint8(test2)
  builder:PrependFloat64(test1)
  builder:Pad(4)
  builder:PrependFloat32(z)
  builder:PrependFloat32(y)
  builder:PrependFloat32(x)
  return builder:Offset()
end

return Vec3


Color

--[[ MyGame.Example.Color

  Automatically generated by the FlatBuffers compiler, do not modify.
  Or modify. I'm a message, not a cop.

  flatc version: 23.5.9

  Declared by  : //monster_test.fbs
  Rooting type : MyGame.Example.Monster (//monster_test.fbs)

--]]

-- Composite components of Monster color.
local Color = {
  Red = 1,
  -- \brief color Green
  -- Green is bit_flag with value (1u << 1)
  Green = 2,
  -- \brief color Blue (1u << 3)
  Blue = 8,
}

return Color


StructOfStructsOfStructs

--[[ MyGame.Example.StructOfStructsOfStructs

  Automatically generated by the FlatBuffers compiler, do not modify.
  Or modify. I'm a message, not a cop.

  flatc version: 23.5.9

  Declared by  : //monster_test.fbs
  Rooting type : MyGame.Example.Monster (//monster_test.fbs)

--]]

local flatbuffers = require('flatbuffers')

local StructOfStructsOfStructs = {}
local mt = {}

function StructOfStructsOfStructs.New()
  local o = {}
  setmetatable(o, {__index = mt})
  return o
end

function mt:Init(buf, pos)
  self.view = flatbuffers.view.New(buf, pos)
end

function mt:A(obj)
  obj:Init(self.view.bytes, self.view.pos + 0)
  return obj
end

function StructOfStructsOfStructs.CreateStructOfStructsOfStructs(builder, a_a_id, a_a_distance, a_b_a, a_b_b, a_c_id, a_c_distance)
  builder:Prep(4, 20)
  builder:Prep(4, 20)
  builder:Prep(4, 8)
  builder:PrependUint32(a_c_distance)
  builder:PrependUint32(a_c_id)
  builder:Prep(2, 4)
  builder:Pad(1)
  builder:PrependInt8(a_b_b)
  builder:PrependInt16(a_b_a)
  builder:Prep(4, 8)
  builder:PrependUint32(a_a_distance)
  builder:PrependUint32(a_a_id)
  return builder:Offset()
end

return StructOfStructsOfStructs


AnyUniqueAliases

--[[ MyGame.Example.AnyUniqueAliases

  Automatically generated by the FlatBuffers compiler, do not modify.
  Or modify. I'm a message, not a cop.

  flatc version: 23.5.9

  Declared by  : //monster_test.fbs
  Rooting type : MyGame.Example.Monster (//monster_test.fbs)

--]]

local AnyUniqueAliases = {
  NONE = 0,
  M = 1,
  TS = 2,
  M2 = 3,
}

return AnyUniqueAliases


AnyAmbiguousAliases

--[[ MyGame.Example.AnyAmbiguousAliases

  Automatically generated by the FlatBuffers compiler, do not modify.
  Or modify. I'm a message, not a cop.

  flatc version: 23.5.9

  Declared by  : //monster_test.fbs
  Rooting type : MyGame.Example.Monster (//monster_test.fbs)

--]]

local AnyAmbiguousAliases = {
  NONE = 0,
  M1 = 1,
  M2 = 2,
  M3 = 3,
}

return AnyAmbiguousAliases


spirv

-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-- FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
-- IN THE MATERIALS.
-- This header is automatically generated by the same tool that creates
-- the Binary Section of the SPIR-V specification.
-- Enumeration tokens for SPIR-V, in various styles:
--   C, C++, C++11, JSON, Lua, Python
--
-- - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
-- - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
-- - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
-- - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
-- - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
--
-- Some tokens act like mask values, which can be OR'd together,
-- while others are mutually exclusive.  The mask-like ones have
-- "Mask" in their name, and a parallel enum that has the shift
-- amount (1 << x) for each corresponding enumerant.
spv = {
    MagicNumber = 0x07230203,
    Version = 0x00010100,
    Revision = 6,
    OpCodeMask = 0xffff,
    WordCountShift = 16,
    SourceLanguage = {
        Unknown = 0,
        ESSL = 1,
        GLSL = 2,
        OpenCL_C = 3,
        OpenCL_CPP = 4,
        HLSL = 5,
    },
    ExecutionModel = {
        Vertex = 0,
        TessellationControl = 1,
        TessellationEvaluation = 2,
        Geometry = 3,
        Fragment = 4,
        GLCompute = 5,
        Kernel = 6,
    },
    AddressingModel = {
        Logical = 0,
        Physical32 = 1,
        Physical64 = 2,
    },
    MemoryModel = {
        Simple = 0,
        GLSL450 = 1,
        OpenCL = 2,
    },
    ExecutionMode = {
        Invocations = 0,
        SpacingEqual = 1,
        SpacingFractionalEven = 2,
        SpacingFractionalOdd = 3,
        VertexOrderCw = 4,
        VertexOrderCcw = 5,
        PixelCenterInteger = 6,
        OriginUpperLeft = 7,
        OriginLowerLeft = 8,
        EarlyFragmentTests = 9,
        PointMode = 10,
        Xfb = 11,
        DepthReplacing = 12,
        DepthGreater = 14,
        DepthLess = 15,
        DepthUnchanged = 16,
        LocalSize = 17,
        LocalSizeHint = 18,
        InputPoints = 19,
        InputLines = 20,
        InputLinesAdjacency = 21,
        Triangles = 22,
        InputTrianglesAdjacency = 23,
        Quads = 24,
        Isolines = 25,
        OutputVertices = 26,
        OutputPoints = 27,
        OutputLineStrip = 28,
        OutputTriangleStrip = 29,
        VecTypeHint = 30,
        ContractionOff = 31,
        Initializer = 33,
        Finalizer = 34,
        SubgroupSize = 35,
        SubgroupsPerWorkgroup = 36,
    },
    StorageClass = {
        UniformConstant = 0,
        Input = 1,
        Uniform = 2,
        Output = 3,
        Workgroup = 4,
        CrossWorkgroup = 5,
        Private = 6,
        Function = 7,
        Generic = 8,
        PushConstant = 9,
        AtomicCounter = 10,
        Image = 11,
        StorageBuffer = 12,
    },
    Dim = {
        Dim1D = 0,
        Dim2D = 1,
        Dim3D = 2,
        Cube = 3,
        Rect = 4,
        Buffer = 5,
        SubpassData = 6,
    },
    SamplerAddressingMode = {
        None = 0,
        ClampToEdge = 1,
        Clamp = 2,
        Repeat = 3,
        RepeatMirrored = 4,
    },
    SamplerFilterMode = {
        Nearest = 0,
        Linear = 1,
    },
    ImageFormat = {
        Unknown = 0,
        Rgba32f = 1,
        Rgba16f = 2,
        R32f = 3,
        Rgba8 = 4,
        Rgba8Snorm = 5,
        Rg32f = 6,
        Rg16f = 7,
        R11fG11fB10f = 8,
        R16f = 9,
        Rgba16 = 10,
        Rgb10A2 = 11,
        Rg16 = 12,
        Rg8 = 13,
        R16 = 14,
        R8 = 15,
        Rgba16Snorm = 16,
        Rg16Snorm = 17,
        Rg8Snorm = 18,
        R16Snorm = 19,
        R8Snorm = 20,
        Rgba32i = 21,
        Rgba16i = 22,
        Rgba8i = 23,
        R32i = 24,
        Rg32i = 25,
        Rg16i = 26,
        Rg8i = 27,
        R16i = 28,
        R8i = 29,
        Rgba32ui = 30,
        Rgba16ui = 31,
        Rgba8ui = 32,
        R32ui = 33,
        Rgb10a2ui = 34,
        Rg32ui = 35,
        Rg16ui = 36,
        Rg8ui = 37,
        R16ui = 38,
        R8ui = 39,
    },
    ImageChannelOrder = {
        R = 0,
        A = 1,
        RG = 2,
        RA = 3,
        RGB = 4,
        RGBA = 5,
        BGRA = 6,
        ARGB = 7,
        Intensity = 8,
        Luminance = 9,
        Rx = 10,
        RGx = 11,
        RGBx = 12,
        Depth = 13,
        DepthStencil = 14,
        sRGB = 15,
        sRGBx = 16,
        sRGBA = 17,
        sBGRA = 18,
        ABGR = 19,
    },
    ImageChannelDataType = {
        SnormInt8 = 0,
        SnormInt16 = 1,
        UnormInt8 = 2,
        UnormInt16 = 3,
        UnormShort565 = 4,
        UnormShort555 = 5,
        UnormInt101010 = 6,
        SignedInt8 = 7,
        SignedInt16 = 8,
        SignedInt32 = 9,
        UnsignedInt8 = 10,
        UnsignedInt16 = 11,
        UnsignedInt32 = 12,
        HalfFloat = 13,
        Float = 14,
        UnormInt24 = 15,
        UnormInt101010_2 = 16,
    },
    ImageOperandsShift = {
        Bias = 0,
        Lod = 1,
        Grad = 2,
        ConstOffset = 3,
        Offset = 4,
        ConstOffsets = 5,
        Sample = 6,
        MinLod = 7,
    },
    ImageOperandsMask = {
        MaskNone = 0,
        Bias = 0x00000001,
        Lod = 0x00000002,
        Grad = 0x00000004,
        ConstOffset = 0x00000008,
        Offset = 0x00000010,
        ConstOffsets = 0x00000020,
        Sample = 0x00000040,
        MinLod = 0x00000080,
    },
    FPFastMathModeShift = {
        NotNaN = 0,
        NotInf = 1,
        NSZ = 2,
        AllowRecip = 3,
        Fast = 4,
    },
    FPFastMathModeMask = {
        MaskNone = 0,
        NotNaN = 0x00000001,
        NotInf = 0x00000002,
        NSZ = 0x00000004,
        AllowRecip = 0x00000008,
        Fast = 0x00000010,
    },
    FPRoundingMode = {
        RTE = 0,
        RTZ = 1,
        RTP = 2,
        RTN = 3,
    },
    LinkageType = {
        Export = 0,
        Import = 1,
    },
    AccessQualifier = {
        ReadOnly = 0,
        WriteOnly = 1,
        ReadWrite = 2,
    },
    FunctionParameterAttribute = {
        Zext = 0,
        Sext = 1,
        ByVal = 2,
        Sret = 3,
        NoAlias = 4,
        NoCapture = 5,
        NoWrite = 6,
        NoReadWrite = 7,
    },
    Decoration = {
        RelaxedPrecision = 0,
        SpecId = 1,
        Block = 2,
        BufferBlock = 3,
        RowMajor = 4,
        ColMajor = 5,
        ArrayStride = 6,
        MatrixStride = 7,
        GLSLShared = 8,
        GLSLPacked = 9,
        CPacked = 10,
        BuiltIn = 11,
        NoPerspective = 13,
        Flat = 14,
        Patch = 15,
        Centroid = 16,
        Sample = 17,
        Invariant = 18,
        Restrict = 19,
        Aliased = 20,
        Volatile = 21,
        Constant = 22,
        Coherent = 23,
        NonWritable = 24,
        NonReadable = 25,
        Uniform = 26,
        SaturatedConversion = 28,
        Stream = 29,
        Location = 30,
        Component = 31,
        Index = 32,
        Binding = 33,
        DescriptorSet = 34,
        Offset = 35,
        XfbBuffer = 36,
        XfbStride = 37,
        FuncParamAttr = 38,
        FPRoundingMode = 39,
        FPFastMathMode = 40,
        LinkageAttributes = 41,
        NoContraction = 42,
        InputAttachmentIndex = 43,
        Alignment = 44,
        MaxByteOffset = 45,
        OverrideCoverageNV = 5248,
        PassthroughNV = 5250,
        ViewportRelativeNV = 5252,
        SecondaryViewportRelativeNV = 5256,
    },
    BuiltIn = {
        Position = 0,
        PointSize = 1,
        ClipDistance = 3,
        CullDistance = 4,
        VertexId = 5,
        InstanceId = 6,
        PrimitiveId = 7,
        InvocationId = 8,
        Layer = 9,
        ViewportIndex = 10,
        TessLevelOuter = 11,
        TessLevelInner = 12,
        TessCoord = 13,
        PatchVertices = 14,
        FragCoord = 15,
        PointCoord = 16,
        FrontFacing = 17,
        SampleId = 18,
        SamplePosition = 19,
        SampleMask = 20,
        FragDepth = 22,
        HelperInvocation = 23,
        NumWorkgroups = 24,
        WorkgroupSize = 25,
        WorkgroupId = 26,
        LocalInvocationId = 27,
        GlobalInvocationId = 28,
        LocalInvocationIndex = 29,
        WorkDim = 30,
        GlobalSize = 31,
        EnqueuedWorkgroupSize = 32,
        GlobalOffset = 33,
        GlobalLinearId = 34,
        SubgroupSize = 36,
        SubgroupMaxSize = 37,
        NumSubgroups = 38,
        NumEnqueuedSubgroups = 39,
        SubgroupId = 40,
        SubgroupLocalInvocationId = 41,
        VertexIndex = 42,
        InstanceIndex = 43,
        SubgroupEqMaskKHR = 4416,
        SubgroupGeMaskKHR = 4417,
        SubgroupGtMaskKHR = 4418,
        SubgroupLeMaskKHR = 4419,
        SubgroupLtMaskKHR = 4420,
        BaseVertex = 4424,
        BaseInstance = 4425,
        DrawIndex = 4426,
        DeviceIndex = 4438,
        ViewIndex = 4440,
        ViewportMaskNV = 5253,
        SecondaryPositionNV = 5257,
        SecondaryViewportMaskNV = 5258,
        PositionPerViewNV = 5261,
        ViewportMaskPerViewNV = 5262,
    },
    SelectionControlShift = {
        Flatten = 0,
        DontFlatten = 1,
    },
    SelectionControlMask = {
        MaskNone = 0,
        Flatten = 0x00000001,
        DontFlatten = 0x00000002,
    },
    LoopControlShift = {
        Unroll = 0,
        DontUnroll = 1,
        DependencyInfinite = 2,
        DependencyLength = 3,
    },
    LoopControlMask = {
        MaskNone = 0,
        Unroll = 0x00000001,
        DontUnroll = 0x00000002,
        DependencyInfinite = 0x00000004,
        DependencyLength = 0x00000008,
    },
    FunctionControlShift = {
        Inline = 0,
        DontInline = 1,
        Pure = 2,
        Const = 3,
    },
    FunctionControlMask = {
        MaskNone = 0,
        Inline = 0x00000001,
        DontInline = 0x00000002,
        Pure = 0x00000004,
        Const = 0x00000008,
    },
    MemorySemanticsShift = {
        Acquire = 1,
        Release = 2,
        AcquireRelease = 3,
        SequentiallyConsistent = 4,
        UniformMemory = 6,
        SubgroupMemory = 7,
        WorkgroupMemory = 8,
        CrossWorkgroupMemory = 9,
        AtomicCounterMemory = 10,
        ImageMemory = 11,
    },
    MemorySemanticsMask = {
        MaskNone = 0,
        Acquire = 0x00000002,
        Release = 0x00000004,
        AcquireRelease = 0x00000008,
        SequentiallyConsistent = 0x00000010,
        UniformMemory = 0x00000040,
        SubgroupMemory = 0x00000080,
        WorkgroupMemory = 0x00000100,
        CrossWorkgroupMemory = 0x00000200,
        AtomicCounterMemory = 0x00000400,
        ImageMemory = 0x00000800,
    },
    MemoryAccessShift = {
        Volatile = 0,
        Aligned = 1,
        Nontemporal = 2,
    },
    MemoryAccessMask = {
        MaskNone = 0,
        Volatile = 0x00000001,
        Aligned = 0x00000002,
        Nontemporal = 0x00000004,
    },
    Scope = {
        CrossDevice = 0,
        Device = 1,
        Workgroup = 2,
        Subgroup = 3,
        Invocation = 4,
    },
    GroupOperation = {
        Reduce = 0,
        InclusiveScan = 1,
        ExclusiveScan = 2,
    },
    KernelEnqueueFlags = {
        NoWait = 0,
        WaitKernel = 1,
        WaitWorkGroup = 2,
    },
    KernelProfilingInfoShift = {
        CmdExecTime = 0,
    },
    KernelProfilingInfoMask = {
        MaskNone = 0,
        CmdExecTime = 0x00000001,
    },
    Capability = {
        Matrix = 0,
        Shader = 1,
        Geometry = 2,
        Tessellation = 3,
        Addresses = 4,
        Linkage = 5,
        Kernel = 6,
        Vector16 = 7,
        Float16Buffer = 8,
        Float16 = 9,
        Float64 = 10,
        Int64 = 11,
        Int64Atomics = 12,
        ImageBasic = 13,
        ImageReadWrite = 14,
        ImageMipmap = 15,
        Pipes = 17,
        Groups = 18,
        DeviceEnqueue = 19,
        LiteralSampler = 20,
        AtomicStorage = 21,
        Int16 = 22,
        TessellationPointSize = 23,
        GeometryPointSize = 24,
        ImageGatherExtended = 25,
        StorageImageMultisample = 27,
        UniformBufferArrayDynamicIndexing = 28,
        SampledImageArrayDynamicIndexing = 29,
        StorageBufferArrayDynamicIndexing = 30,
        StorageImageArrayDynamicIndexing = 31,
        ClipDistance = 32,
        CullDistance = 33,
        ImageCubeArray = 34,
        SampleRateShading = 35,
        ImageRect = 36,
        SampledRect = 37,
        GenericPointer = 38,
        Int8 = 39,
        InputAttachment = 40,
        SparseResidency = 41,
        MinLod = 42,
        Sampled1D = 43,
        Image1D = 44,
        SampledCubeArray = 45,
        SampledBuffer = 46,
        ImageBuffer = 47,
        ImageMSArray = 48,
        StorageImageExtendedFormats = 49,
        ImageQuery = 50,
        DerivativeControl = 51,
        InterpolationFunction = 52,
        TransformFeedback = 53,
        GeometryStreams = 54,
        StorageImageReadWithoutFormat = 55,
        StorageImageWriteWithoutFormat = 56,
        MultiViewport = 57,
        SubgroupDispatch = 58,
        NamedBarrier = 59,
        PipeStorage = 60,
        SubgroupBallotKHR = 4423,
        DrawParameters = 4427,
        SubgroupVoteKHR = 4431,
        StorageBuffer16BitAccess = 4433,
        StorageUniformBufferBlock16 = 4433,
        StorageUniform16 = 4434,
        UniformAndStorageBuffer16BitAccess = 4434,
        StoragePushConstant16 = 4435,
        StorageInputOutput16 = 4436,
        DeviceGroup = 4437,
        MultiView = 4439,
        VariablePointersStorageBuffer = 4441,
        VariablePointers = 4442,
        SampleMaskOverrideCoverageNV = 5249,
        GeometryShaderPassthroughNV = 5251,
        ShaderViewportIndexLayerNV = 5254,
        ShaderViewportMaskNV = 5255,
        ShaderStereoViewNV = 5259,
        PerViewAttributesNV = 5260,
    },
    Op = {
        OpNop = 0,
        OpUndef = 1,
        OpSourceContinued = 2,
        OpSource = 3,
        OpSourceExtension = 4,
        OpName = 5,
        OpMemberName = 6,
        OpString = 7,
        OpLine = 8,
        OpExtension = 10,
        OpExtInstImport = 11,
        OpExtInst = 12,
        OpMemoryModel = 14,
        OpEntryPoint = 15,
        OpExecutionMode = 16,
        OpCapability = 17,
        OpTypeVoid = 19,
        OpTypeBool = 20,
        OpTypeInt = 21,
        OpTypeFloat = 22,
        OpTypeVector = 23,
        OpTypeMatrix = 24,
        OpTypeImage = 25,
        OpTypeSampler = 26,
        OpTypeSampledImage = 27,
        OpTypeArray = 28,
        OpTypeRuntimeArray = 29,
        OpTypeStruct = 30,
        OpTypeOpaque = 31,
        OpTypePointer = 32,
        OpTypeFunction = 33,
        OpTypeEvent = 34,
        OpTypeDeviceEvent = 35,
        OpTypeReserveId = 36,
        OpTypeQueue = 37,
        OpTypePipe = 38,
        OpTypeForwardPointer = 39,
        OpConstantTrue = 41,
        OpConstantFalse = 42,
        OpConstant = 43,
        OpConstantComposite = 44,
        OpConstantSampler = 45,
        OpConstantNull = 46,
        OpSpecConstantTrue = 48,
        OpSpecConstantFalse = 49,
        OpSpecConstant = 50,
        OpSpecConstantComposite = 51,
        OpSpecConstantOp = 52,
        OpFunction = 54,
        OpFunctionParameter = 55,
        OpFunctionEnd = 56,
        OpFunctionCall = 57,
        OpVariable = 59,
        OpImageTexelPointer = 60,
        OpLoad = 61,
        OpStore = 62,
        OpCopyMemory = 63,
        OpCopyMemorySized = 64,
        OpAccessChain = 65,
        OpInBoundsAccessChain = 66,
        OpPtrAccessChain = 67,
        OpArrayLength = 68,
        OpGenericPtrMemSemantics = 69,
        OpInBoundsPtrAccessChain = 70,
        OpDecorate = 71,
        OpMemberDecorate = 72,
        OpDecorationGroup = 73,
        OpGroupDecorate = 74,
        OpGroupMemberDecorate = 75,
        OpVectorExtractDynamic = 77,
        OpVectorInsertDynamic = 78,
        OpVectorShuffle = 79,
        OpCompositeConstruct = 80,
        OpCompositeExtract = 81,
        OpCompositeInsert = 82,
        OpCopyObject = 83,
        OpTranspose = 84,
        OpSampledImage = 86,
        OpImageSampleImplicitLod = 87,
        OpImageSampleExplicitLod = 88,
        OpImageSampleDrefImplicitLod = 89,
        OpImageSampleDrefExplicitLod = 90,
        OpImageSampleProjImplicitLod = 91,
        OpImageSampleProjExplicitLod = 92,
        OpImageSampleProjDrefImplicitLod = 93,
        OpImageSampleProjDrefExplicitLod = 94,
        OpImageFetch = 95,
        OpImageGather = 96,
        OpImageDrefGather = 97,
        OpImageRead = 98,
        OpImageWrite = 99,
        OpImage = 100,
        OpImageQueryFormat = 101,
        OpImageQueryOrder = 102,
        OpImageQuerySizeLod = 103,
        OpImageQuerySize = 104,
        OpImageQueryLod = 105,
        OpImageQueryLevels = 106,
        OpImageQuerySamples = 107,
        OpConvertFToU = 109,
        OpConvertFToS = 110,
        OpConvertSToF = 111,
        OpConvertUToF = 112,
        OpUConvert = 113,
        OpSConvert = 114,
        OpFConvert = 115,
        OpQuantizeToF16 = 116,
        OpConvertPtrToU = 117,
        OpSatConvertSToU = 118,
        OpSatConvertUToS = 119,
        OpConvertUToPtr = 120,
        OpPtrCastToGeneric = 121,
        OpGenericCastToPtr = 122,
        OpGenericCastToPtrExplicit = 123,
        OpBitcast = 124,
        OpSNegate = 126,
        OpFNegate = 127,
        OpIAdd = 128,
        OpFAdd = 129,
        OpISub = 130,
        OpFSub = 131,
        OpIMul = 132,
        OpFMul = 133,
        OpUDiv = 134,
        OpSDiv = 135,
        OpFDiv = 136,
        OpUMod = 137,
        OpSRem = 138,
        OpSMod = 139,
        OpFRem = 140,
        OpFMod = 141,
        OpVectorTimesScalar = 142,
        OpMatrixTimesScalar = 143,
        OpVectorTimesMatrix = 144,
        OpMatrixTimesVector = 145,
        OpMatrixTimesMatrix = 146,
        OpOuterProduct = 147,
        OpDot = 148,
        OpIAddCarry = 149,
        OpISubBorrow = 150,
        OpUMulExtended = 151,
        OpSMulExtended = 152,
        OpAny = 154,
        OpAll = 155,
        OpIsNan = 156,
        OpIsInf = 157,
        OpIsFinite = 158,
        OpIsNormal = 159,
        OpSignBitSet = 160,
        OpLessOrGreater = 161,
        OpOrdered = 162,
        OpUnordered = 163,
        OpLogicalEqual = 164,
        OpLogicalNotEqual = 165,
        OpLogicalOr = 166,
        OpLogicalAnd = 167,
        OpLogicalNot = 168,
        OpSelect = 169,
        OpIEqual = 170,
        OpINotEqual = 171,
        OpUGreaterThan = 172,
        OpSGreaterThan = 173,
        OpUGreaterThanEqual = 174,
        OpSGreaterThanEqual = 175,
        OpULessThan = 176,
        OpSLessThan = 177,
        OpULessThanEqual = 178,
        OpSLessThanEqual = 179,
        OpFOrdEqual = 180,
        OpFUnordEqual = 181,
        OpFOrdNotEqual = 182,
        OpFUnordNotEqual = 183,
        OpFOrdLessThan = 184,
        OpFUnordLessThan = 185,
        OpFOrdGreaterThan = 186,
        OpFUnordGreaterThan = 187,
        OpFOrdLessThanEqual = 188,
        OpFUnordLessThanEqual = 189,
        OpFOrdGreaterThanEqual = 190,
        OpFUnordGreaterThanEqual = 191,
        OpShiftRightLogical = 194,
        OpShiftRightArithmetic = 195,
        OpShiftLeftLogical = 196,
        OpBitwiseOr = 197,
        OpBitwiseXor = 198,
        OpBitwiseAnd = 199,
        OpNot = 200,
        OpBitFieldInsert = 201,
        OpBitFieldSExtract = 202,
        OpBitFieldUExtract = 203,
        OpBitReverse = 204,
        OpBitCount = 205,
        OpDPdx = 207,
        OpDPdy = 208,
        OpFwidth = 209,
        OpDPdxFine = 210,
        OpDPdyFine = 211,
        OpFwidthFine = 212,
        OpDPdxCoarse = 213,
        OpDPdyCoarse = 214,
        OpFwidthCoarse = 215,
        OpEmitVertex = 218,
        OpEndPrimitive = 219,
        OpEmitStreamVertex = 220,
        OpEndStreamPrimitive = 221,
        OpControlBarrier = 224,
        OpMemoryBarrier = 225,
        OpAtomicLoad = 227,
        OpAtomicStore = 228,
        OpAtomicExchange = 229,
        OpAtomicCompareExchange = 230,
        OpAtomicCompareExchangeWeak = 231,
        OpAtomicIIncrement = 232,
        OpAtomicIDecrement = 233,
        OpAtomicIAdd = 234,
        OpAtomicISub = 235,
        OpAtomicSMin = 236,
        OpAtomicUMin = 237,
        OpAtomicSMax = 238,
        OpAtomicUMax = 239,
        OpAtomicAnd = 240,
        OpAtomicOr = 241,
        OpAtomicXor = 242,
        OpPhi = 245,
        OpLoopMerge = 246,
        OpSelectionMerge = 247,
        OpLabel = 248,
        OpBranch = 249,
        OpBranchConditional = 250,
        OpSwitch = 251,
        OpKill = 252,
        OpReturn = 253,
        OpReturnValue = 254,
        OpUnreachable = 255,
        OpLifetimeStart = 256,
        OpLifetimeStop = 257,
        OpGroupAsyncCopy = 259,
        OpGroupWaitEvents = 260,
        OpGroupAll = 261,
        OpGroupAny = 262,
        OpGroupBroadcast = 263,
        OpGroupIAdd = 264,
        OpGroupFAdd = 265,
        OpGroupFMin = 266,
        OpGroupUMin = 267,
        OpGroupSMin = 268,
        OpGroupFMax = 269,
        OpGroupUMax = 270,
        OpGroupSMax = 271,
        OpReadPipe = 274,
        OpWritePipe = 275,
        OpReservedReadPipe = 276,
        OpReservedWritePipe = 277,
        OpReserveReadPipePackets = 278,
        OpReserveWritePipePackets = 279,
        OpCommitReadPipe = 280,
        OpCommitWritePipe = 281,
        OpIsValidReserveId = 282,
        OpGetNumPipePackets = 283,
        OpGetMaxPipePackets = 284,
        OpGroupReserveReadPipePackets = 285,
        OpGroupReserveWritePipePackets = 286,
        OpGroupCommitReadPipe = 287,
        OpGroupCommitWritePipe = 288,
        OpEnqueueMarker = 291,
        OpEnqueueKernel = 292,
        OpGetKernelNDrangeSubGroupCount = 293,
        OpGetKernelNDrangeMaxSubGroupSize = 294,
        OpGetKernelWorkGroupSize = 295,
        OpGetKernelPreferredWorkGroupSizeMultiple = 296,
        OpRetainEvent = 297,
        OpReleaseEvent = 298,
        OpCreateUserEvent = 299,
        OpIsValidEvent = 300,
        OpSetUserEventStatus = 301,
        OpCaptureEventProfilingInfo = 302,
        OpGetDefaultQueue = 303,
        OpBuildNDRange = 304,
        OpImageSparseSampleImplicitLod = 305,
        OpImageSparseSampleExplicitLod = 306,
        OpImageSparseSampleDrefImplicitLod = 307,
        OpImageSparseSampleDrefExplicitLod = 308,
        OpImageSparseSampleProjImplicitLod = 309,
        OpImageSparseSampleProjExplicitLod = 310,
        OpImageSparseSampleProjDrefImplicitLod = 311,
        OpImageSparseSampleProjDrefExplicitLod = 312,
        OpImageSparseFetch = 313,
        OpImageSparseGather = 314,
        OpImageSparseDrefGather = 315,
        OpImageSparseTexelsResident = 316,
        OpNoLine = 317,
        OpAtomicFlagTestAndSet = 318,
        OpAtomicFlagClear = 319,
        OpImageSparseRead = 320,
        OpSizeOf = 321,
        OpTypePipeStorage = 322,
        OpConstantPipeStorage = 323,
        OpCreatePipeFromPipeStorage = 324,
        OpGetKernelLocalSizeForSubgroupCount = 325,
        OpGetKernelMaxNumSubgroups = 326,
        OpTypeNamedBarrier = 327,
        OpNamedBarrierInitialize = 328,
        OpMemoryNamedBarrier = 329,
        OpModuleProcessed = 330,
        OpSubgroupBallotKHR = 4421,
        OpSubgroupFirstInvocationKHR = 4422,
        OpSubgroupAllKHR = 4428,
        OpSubgroupAnyKHR = 4429,
        OpSubgroupAllEqualKHR = 4430,
        OpSubgroupReadInvocationKHR = 4432,
    },
}


test.gen

-- Code generated by luapp. DO NOT EDIT.

local other = (function(...)
return {
  value = 100
}
end)()

print(other.value)


test

local other = loadfile("other_test.lua")()

print(other.value)


return {
  value = 100
}


require 'test_fixtures'
Account = G.Account
Policy = G.Policy
Utils = G.Utils
function testPolicyGetMissing()
  local ref = PB.new("go.chromium.org.luci.server.quota.quotapb.PolicyRef", {
    config = "policy_config",
    key = "policy_name",
  })
  lu.assertNil(Policy.get(ref))
end
function testPolicyGet()
  local ref = PB.new("go.chromium.org.luci.server.quota.quotapb.PolicyRef", {
    config = "policy_config",
    key = "policy_name",
  })
  local policy = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy", {
    default = 20,
    limit = 100,
    refill = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy.Refill",  {
      units = 1,
      interval = 100,
    }),
    lifetime = PB.new("google.protobuf.Duration", {
      seconds = 3600,
    }),
  })
  redis.call("HSET", ref.config, ref.key, PB.marshal(policy))
  local expectedPolicy = "\132\001\020\002d\003\146\001d\005\145\205\014\016"
  lu.assertEquals(redis.DATA[ref.config][ref.key], expectedPolicy)
  local policy = Policy.get(ref)
  lu.assertEquals(policy.pb.default, 20)
  lu.assertEquals(policy.pb.limit, 100)
  lu.assertEquals(policy.pb.refill.units, 1)
  lu.assertEquals(policy.pb.refill.interval, 100)
  lu.assertEquals(policy.pb.lifetime.seconds, 3600)
end
return lu.LuaUnit.run("-v")


require 'test_fixtures'
Account = G.Account
Policy = G.Policy
Utils = G.Utils
local DO_NOT_CAP_PROPOSED = PB.E["go.chromium.org.luci.server.quota.quotapb.Op.Options"].DO_NOT_CAP_PROPOSED
local IGNORE_POLICY_BOUNDS = PB.E["go.chromium.org.luci.server.quota.quotapb.Op.Options"].IGNORE_POLICY_BOUNDS
function enumMap(e)
  local ret = {}
  for k, v in pairs(PB.E[e]) do
    if type(k) == "string" then
      ret[k] = k
    end
  end
  return ret
end
local AccountStatus = enumMap("go.chromium.org.luci.server.quota.quotapb.OpResult.AccountStatus")
local OpStatus = enumMap("go.chromium.org.luci.server.quota.quotapb.OpResult.OpStatus")
function mkOp(fields)
  return PB.new("go.chromium.org.luci.server.quota.quotapb.RawOp", fields)
end
function setPolicy(policy_config, policy_key, policy_params)
  local ref = PB.new("go.chromium.org.luci.server.quota.quotapb.PolicyRef", {
    config = policy_config,
    key = policy_key,
  })
  local policy = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy", policy_params)
  redis.call("HSET", ref.config, ref.key, PB.marshal(policy))
  return ref
end
function testAccountGetEmpty()
  local account = Account:get(KEYS[1])
  lu.assertEquals(account.account_status, AccountStatus.CREATED)
  lu.assertEquals(account.key, KEYS[1], "account key is saved")
end
function testSaveEmptyAccount()
  local account = Account:get(KEYS[1])
  account:write()
  lu.assertEquals(#redis.DATA, 0, "save is a NOOP until we set a value.")
end
-- Use `./datatool -type Account -out msgpackpb+lua`
--
-- {
--  "balance": 100,
--  "updated_ts": "2022-12-12T08:41:26+00:00"
-- }
--
-- The msgpackpb+pretty of this is:
-- [
--   8i100,
--   [
--     32u1670834486,
--   ],
-- ]
local packedAccount = "\146d\145\206c\150\2336"
function testAccountSetValue()
  local account = Account:get(KEYS[1])
  account.pb.balance = 100
  account:write()
  lu.assertEquals(redis.DATA[KEYS[1]], packedAccount, "data is saved in packed form")
end
function testAccountLoad()
  redis.call("SET", KEYS[1], packedAccount)
  local account = Account:get(KEYS[1])
  lu.assertEquals(account.pb.balance, 100)
  lu.assertEquals(account.pb.updated_ts.seconds, 1670834486)
end
function testNilAccountSetPolicy()
  local account = Account:get(KEYS[1])
  local policy = {
    policy_ref = PB.new("go.chromium.org.luci.server.quota.quotapb.PolicyRef", {
      config = "policy_key",
      key = "policy_name",
    }),
    pb = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy", {
      default = 100,
      limit = 1000,
      refill = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy.Refill", {
        units = 1,
        interval = 1,
      }),
      lifetime = PB.new("google.protobuf.Duration", {
        seconds = 123,
      })
    }),
  }
  account:setPolicy(policy)
  lu.assertEquals(account.pb.balance, policy.pb.default)
  account:write()
  lu.assertEquals(account.pb.updated_ts, Utils.NOW)
  lu.assertEquals(redis.DATA[KEYS[1]], "\149d\145\206c\150\2336\145\206c\150\2336\146\170policy_key\171policy_name\132\001d\002\205\003\232\003\146\001\001\005\145{")
  lu.assertEquals(redis.TTL[KEYS[1]], 123000)
end
function testNilAccountSetPolicyNoRefill()
  local account = Account:get(KEYS[1])
  local policy = {
    policy_ref = PB.new("go.chromium.org.luci.server.quota.quotapb.PolicyRef", {
      config = "policy_key",
      key = "policy_name",
    }),
    pb = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy", {
      default = 100,
      limit = 1000,
      lifetime = PB.new("google.protobuf.Duration", {
        seconds = 123,
      })
    }),
  }
  account:setPolicy(policy)
  lu.assertEquals(account.pb.balance, policy.pb.default)
  lu.assertEquals(account.pb.updated_ts, Utils.NOW)
  account:write()
  lu.assertEquals(redis.DATA[KEYS[1]], "\149d\145\206c\150\2336\145\206c\150\2336\146\170policy_key\171policy_name\131\001d\002\205\003\232\005\145{")
  lu.assertEquals(redis.TTL[KEYS[1]], 123000)
end
function testNilAccountSetPolicyInfinite()
  local account = Account:get(KEYS[1])
  local policy = {
    policy_ref = PB.new("go.chromium.org.luci.server.quota.quotapb.PolicyRef", {
      config = "policy_key",
      key = "policy_name",
    }),
    pb = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy", {
      default = 100,
      limit = 1000,
      refill = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy.Refill", {
        units = 1,
        interval = 0, -- infinity
      }),
      lifetime = PB.new("google.protobuf.Duration", {
        seconds = 123,
      })
    }),
  }
  account:setPolicy(policy)
  lu.assertEquals(account.pb.balance, policy.pb.limit)
  -- note; this is not quite real, ApplyOps would be the only way to do this,
  -- and it will explicitly avoid decreasing the balance. However applyRefill
  -- on get should restore this.
  account.pb.balance = 2
  lu.assertEquals(account.pb.balance, 2)
  account:write()
  Account.CACHE = {}
  account = Account:get(KEYS[1])
  lu.assertEquals(account.pb.balance, policy.pb.limit)
  lu.assertEquals(redis.DATA[KEYS[1]], "\149\002\145\206c\150\2336\145\206c\150\2336\146\170policy_key\171policy_name\132\001d\002\205\003\232\003\145\001\005\145{")
  lu.assertEquals(redis.TTL[KEYS[1]], 123000)
end
function testAccountSetPolicyRefill()
  local account = Account:get(KEYS[1])
  account.pb.balance = 100
  account:write()
  lu.assertEquals(account.pb.balance, 100)
  lu.assertEquals(account.pb.updated_ts, Utils.NOW)
  Utils.NOW.seconds = Utils.NOW.seconds + 3
  local policy = {
    policy_ref = PB.new("go.chromium.org.luci.server.quota.quotapb.PolicyRef", {
      config = "policy_key",
      key = "policy_name",
    }),
    pb = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy", {
      default = 100,
      limit = 1000,
      refill = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy.Refill", {
        units = 1,
        interval = 2,
      }),
      lifetime = PB.new("google.protobuf.Duration", {
        seconds = 123,
      })
    }),
  }
  account:setPolicy(policy)
  lu.assertEquals(account.pb.balance, 100)
  lu.assertEquals(account.pb.policy_ref.config, "policy_key")
  lu.assertEquals(account.pb.policy_ref.key, "policy_name")
  lu.assertEquals(account.pb.policy.limit, 1000)
  lu.assertEquals(account.pb.policy.refill.interval, 2)
  lu.assertEquals(account.pb.policy_change_ts, Utils.NOW)
  account:write()
  Utils.NOW.seconds = Utils.NOW.seconds + 3
  Account.CACHE = {}
  account = Account:get(KEYS[1])
  lu.assertEquals(account.pb.balance, 102)
  Utils.NOW.seconds = Utils.NOW.seconds + 1
  Account.CACHE = {}
  account = Account:get(KEYS[1])
  lu.assertEquals(account.pb.balance, 102)
  Utils.NOW.seconds = Utils.NOW.seconds + 1
  Account.CACHE = {}
  account = Account:get(KEYS[1])
  lu.assertEquals(account.pb.balance, 103)
  account:write()
  lu.assertEquals(redis.DATA[KEYS[1]], "\149g\145\206c\150\233>\145\206c\150\2339\146\170policy_key\171policy_name\132\001d\002\205\003\232\003\146\001\002\005\145{")
  lu.assertEquals(redis.TTL[KEYS[1]], 123000)
end
function testAccountBalanceExtreme()
  local account = Account:get(KEYS[1])
  account.pb.balance = 9007199254740991
  account:write() -- ok
  account.pb.balance = 9007199254740991 + 1
  lu.assertErrorMsgContains("overflow", account.write, account)
  account.pb.balance = -9007199254740991
  account:write() -- ok
  account.pb.balance = -9007199254740991 - 1
  lu.assertErrorMsgContains("underflows", account.write, account)
end
function testAccountApplyOpFinitePolicy()
  local account = Account:get(KEYS[1])
  local p = {
    pb = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy", {
      limit = 1000,
    }),
    policy_ref = PB.new("go.chromium.org.luci.server.quota.quotapb.PolicyRef", {
      config = "policy_key",
      key = "policy_name",
    }),
  }
  account:setPolicy(p)
  local setOp = function(cur, amt, options)
    account.pb.balance = cur
    return mkOp({
      delta = amt,
      relative_to = "ZERO",
      options = options or 0,
    })
  end
  lu.assertEquals(account:applyOp(setOp(20, 300)), nil)  -- increase < limit
  lu.assertEquals(account.pb.balance, 300)
  lu.assertEquals(account:applyOp(setOp(20, 5)), nil)    -- decrease > 0
  lu.assertEquals(account.pb.balance, 5)
  lu.assertEquals(account:applyOp(setOp(20, 1000)), nil) -- increase == limit
  lu.assertEquals(account.pb.balance, 1000)
  lu.assertEquals(account:applyOp(setOp(20, 0)), nil)    -- decrease == 0
  lu.assertEquals(account.pb.balance, 0)
  lu.assertEquals(account:applyOp(setOp(-100, 300)), nil)  -- increase < limit
  lu.assertEquals(account.pb.balance, 300)
  lu.assertEquals(account:applyOp(setOp(-100, -50)), nil)  -- increase < limit
  lu.assertEquals(account.pb.balance, -50)
  lu.assertEquals(account:applyOp(setOp(-100, 0)), nil)    -- increase == 0
  lu.assertEquals(account.pb.balance, 0)
  lu.assertEquals(account:applyOp(setOp(-100, 1000)), nil) -- increase == limit
  lu.assertEquals(account.pb.balance, 1000)
  lu.assertEquals(account:applyOp(setOp(2000, 300)), nil)  -- decrease < limit
  lu.assertEquals(account.pb.balance, 300)
  lu.assertEquals(account:applyOp(setOp(2000, 1000)), nil) -- decrease == limit
  lu.assertEquals(account.pb.balance, 1000)
  lu.assertEquals(account:applyOp(setOp(2000, 0)), nil)    -- decrease == 0
  lu.assertEquals(account.pb.balance, 0)
  -- soft cap
  lu.assertEquals(account:applyOp(setOp(2000, 1500)), nil) -- decrease < limit
  lu.assertEquals(account.pb.balance, 1000)
  -- hard cap
  lu.assertEquals(account:applyOp(setOp(2000, 1500, DO_NOT_CAP_PROPOSED)), nil) -- decrease < limit
  lu.assertEquals(account.pb.balance, 1500)
  local rslt = {}
  Account.applyOp(account, setOp(20, -1), rslt)
  lu.assertEquals(rslt.status, "ERR_UNDERFLOW")
  lu.assertEquals(account.pb.balance, 20)
  local rslt = {}
  Account.applyOp(account, setOp(-100, -200), rslt)
  lu.assertEquals(rslt.status, "ERR_UNDERFLOW")
  lu.assertEquals(account.pb.balance, -100)
  local rslt = {}
  Account.applyOp(account, setOp(20, 1001, DO_NOT_CAP_PROPOSED), rslt)
  lu.assertEquals(rslt.status, "ERR_OVERFLOW")
  lu.assertEquals(account.pb.balance, 20)
  local rslt = {}
  Account.applyOp(account, setOp(1500, 2000, DO_NOT_CAP_PROPOSED), rslt)
  lu.assertEquals(rslt.status, "ERR_OVERFLOW")
  lu.assertEquals(account.pb.balance, 1500)
end
function testAccountApplyOpInfinitePolicy()
  local account = Account:get(KEYS[1])
  local p = {
    pb = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy", {
      limit = 1000,
      refill = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy.Refill", {
        units = 1,
      })
    }),
    policy_ref = PB.new("go.chromium.org.luci.server.quota.quotapb.PolicyRef", {
      config = "policy_key",
      key = "policy_name",
    }),
  }
  account:setPolicy(p)
  -- note: we do not need to test cases where the current balance is something
  -- other than `pb.policy.limit`. We rely on Account construction and setPolicy
  -- to call applyRefill(), and for applyOp to always leave balance >= limit.
  local setOp = function(amt, options)
    account.pb.balance = p.pb.limit
    return mkOp({
      delta = amt,
      relative_to = "ZERO",
      options = options or 0,
    })
  end
  lu.assertEquals(account:applyOp(setOp(0)), nil)
  lu.assertEquals(account.pb.balance, 1000)
  lu.assertEquals(account:applyOp(setOp(1000)), nil)
  lu.assertEquals(account.pb.balance, 1000)
  lu.assertEquals(account:applyOp(setOp(500)), nil)
  lu.assertEquals(account.pb.balance, 1000)
  lu.assertEquals(account:applyOp(setOp(1234)), nil)
  lu.assertEquals(account.pb.balance, 1000)
  -- we can, however, start with a higher than limit balance.
  local op = setOp(1234, DO_NOT_CAP_PROPOSED)
  account.pb.balance = 2000
  lu.assertEquals(account:applyOp(op), nil)
  lu.assertEquals(account.pb.balance, 1234)
  local rslt = {}
  Account.applyOp(account, setOp(-1000), rslt)
  lu.assertEquals(rslt.status, "ERR_UNDERFLOW")
  lu.assertEquals(account.pb.balance, 1000)
  local rslt = {}
  Account.applyOp(account, setOp(1001, DO_NOT_CAP_PROPOSED), rslt)
  lu.assertEquals(rslt.status, "ERR_OVERFLOW")
  lu.assertEquals(account.pb.balance, 1000)
  local rslt = {}
  Account.applyOp(account, setOp(-1), rslt)
  lu.assertEquals(rslt.status, "ERR_UNDERFLOW")
  lu.assertEquals(account.pb.balance, 1000)
end
function testAccountApplyOpZeroPolicy()
  local account = Account:get(KEYS[1])
  local p = {
    pb = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy", {
      limit = 0,
    }),
    policy_ref = PB.new("go.chromium.org.luci.server.quota.quotapb.PolicyRef", {
      config = "policy_key",
      key = "policy_name",
    }),
  }
  account:setPolicy(p)
  local setOp = function(cur, amt, options)
    account.pb.balance = cur
    return mkOp({
      delta = amt,
      relative_to = "ZERO",
      options = options,
    })
  end
  lu.assertEquals(account:applyOp(setOp(0, 0)), nil)
  lu.assertEquals(account.pb.balance, 0)
  lu.assertEquals(account:applyOp(setOp(100, 1)), nil)
  lu.assertEquals(account.pb.balance, 0)
  lu.assertEquals(account:applyOp(setOp(100, 1, DO_NOT_CAP_PROPOSED)), nil)
  lu.assertEquals(account.pb.balance, 1)
  lu.assertEquals(account:applyOp(setOp(2000, 1000)), nil)
  lu.assertEquals(account.pb.balance, 0)
  lu.assertEquals(account:applyOp(setOp(2000, 1000, DO_NOT_CAP_PROPOSED)), nil)
  lu.assertEquals(account.pb.balance, 1000)
  lu.assertEquals(account:applyOp(setOp(-2000, -1000)), nil)
  lu.assertEquals(account.pb.balance, -1000)
  local rslt = {}
  Account.applyOp(account, setOp(0, 1000, DO_NOT_CAP_PROPOSED), rslt)
  lu.assertEquals(rslt.status, "ERR_OVERFLOW")
  lu.assertEquals(account.pb.balance, 0)
  local rslt = {}
  Account.applyOp(account, setOp(-100, 1, DO_NOT_CAP_PROPOSED), rslt)
  lu.assertEquals(rslt.status, "ERR_OVERFLOW")
  lu.assertEquals(account.pb.balance, -100)
  local rslt = {}
  Account.applyOp(account, setOp(0, 1, DO_NOT_CAP_PROPOSED), rslt)
  lu.assertEquals(rslt.status, "ERR_OVERFLOW")
  lu.assertEquals(account.pb.balance, 0)
  local rslt = {}
  Account.applyOp(account, setOp(0, -1), rslt)
  lu.assertEquals(rslt.status, "ERR_UNDERFLOW")
  lu.assertEquals(account.pb.balance, 0)
end
function testAccountApplyOpAddPolicy()
  local ref = setPolicy("policy_config", "policy_name", {
    default = 20,
    limit = 100,
    refill = PB.new("go.chromium.org.luci.server.quota.quotapb.Policy.Refill",  {
      units = 1,
      interval = 100,
    }),
    lifetime = PB.new("google.protobuf.Duration", {
      seconds = 3600,
    }),
  })
  local account = Account:get(KEYS[1])
  account:applyOp(mkOp({
    policy_ref = ref,
    relative_to = "CURRENT_BALANCE",
    delta = 13,
  }))
  lu.assertEquals(account.pb.balance, 33)
end
function testApplyOpsOK()
  local pol_one = setPolicy("policy_config", "one", {
    default = 10,
    limit = 100,
  })
  local pol_two = setPolicy("policy_config", "two", {
    default = 20,
    limit = 200,
  })
  local rsp, allOK = Account.ApplyOps({
    mkOp({
      account_ref = "acct1",
      policy_ref = pol_one,
      relative_to = "CURRENT_BALANCE",
      delta = 100, -- should hit limit, stop at 100.
    }),
    mkOp({
      account_ref = "acct2",
      policy_ref = pol_two,
      relative_to = "CURRENT_BALANCE",
      delta = 100, -- stop at 120 under limit.
    }),
  })
  lu.assertTrue(allOK)
  lu.assertEquals(#rsp.results, 2)
  lu.assertEquals(rsp.results[1].account_status, AccountStatus.CREATED)
  lu.assertEquals(rsp.results[1].status_msg, "")
  lu.assertEquals(rsp.results[1].status, OpStatus.SUCCESS)
  lu.assertEquals(rsp.results[1].previous_balance, 0)
  lu.assertEquals(rsp.results[1].new_balance, 100)
  lu.assertEquals(rsp.results[2].account_status, AccountStatus.CREATED)
  lu.assertEquals(rsp.results[2].status_msg, "")
  lu.assertEquals(rsp.results[2].status, OpStatus.SUCCESS)
  lu.assertEquals(rsp.results[2].previous_balance, 0)
  lu.assertEquals(rsp.results[2].new_balance, 120)
end
function testApplyOpsFail()
  local pol_one = setPolicy("policy_config", "one", {
    default = 10,
    limit = 100,
  })
  local rsp, allOK = Account.ApplyOps({
    mkOp({
      account_ref = "acct1",
      relative_to = "CURRENT_BALANCE",
      options = DO_NOT_CAP_PROPOSED + IGNORE_POLICY_BOUNDS,
      delta = 1000,
    }),
    mkOp({
      account_ref = "acct2",
      policy_ref = pol_one,
      relative_to = "CURRENT_BALANCE",
      options = DO_NOT_CAP_PROPOSED,
      delta = 1000,
    }),
    mkOp({
      account_ref = "acct3",
      policy_ref = pol_one,
      relative_to = "CURRENT_BALANCE",
      delta = -1000,
    }),
    mkOp({
      account_ref = "acct4",
      policy_ref = {config = "nope", key = "missing"},
      relative_to = "CURRENT_BALANCE",
      delta = 100,
    }),
    mkOp({
      account_ref = "acct5",
      relative_to = "CURRENT_BALANCE",
      delta = 100,
    }),
    mkOp({
      account_ref = "acct6",
      relative_to = "ZERO",
      delta = 100,
    }),
  })
  lu.assertFalse(allOK)
  lu.assertEquals(#rsp.results, 6)
  lu.assertEquals(rsp.results[1].account_status, AccountStatus.CREATED)
  lu.assertStrContains(rsp.results[1].status_msg, "IGNORE_POLICY_BOUNDS and DO_NOT_CAP_PROPOSED both set")
  lu.assertEquals(rsp.results[1].status, OpStatus.ERR_UNKNOWN)
  lu.assertEquals(rsp.results[2].account_status, AccountStatus.CREATED)
  lu.assertEquals(rsp.results[2].status_msg, "")
  lu.assertEquals(rsp.results[2].status, OpStatus.ERR_OVERFLOW)
  lu.assertEquals(rsp.results[3].account_status, AccountStatus.CREATED)
  lu.assertEquals(rsp.results[3].status, OpStatus.ERR_UNDERFLOW)
  lu.assertEquals(rsp.results[3].status_msg, "")
  lu.assertEquals(rsp.results[4].account_status, AccountStatus.CREATED)
  lu.assertEquals(rsp.results[4].status, OpStatus.ERR_UNKNOWN_POLICY)
  lu.assertEquals(rsp.results[4].status_msg, "")
  lu.assertEquals(rsp.results[5].account_status, AccountStatus.CREATED)
  lu.assertEquals(rsp.results[5].status_msg, "")
  lu.assertEquals(rsp.results[5].status, OpStatus.ERR_POLICY_REQUIRED)
end
function testApplyOpsMultiSameAccount()
  local req = PB.new("go.chromium.org.luci.server.quota.quotapb.ApplyOpsRequest", {
  })
end
return lu.LuaUnit.run("-v")


lu = require 'luaunit/luaunit'
-- This makes tracebacks work correctly; otherwise they show the location inside
-- of the luaunit assertion function. Suspect something to do with Go lua impl.
lu.STRIP_EXTRA_ENTRIES_IN_STACK_TRACE = 1
function dumpTable(table, depth)
  if depth == nil then
    depth = 0
  end
  if (depth > 200) then
    print("Error: Depth > 200 in dumpTable()")
    return
  end
  for k,v in pairs(table) do
    if (type(v) == "table") then
      print(string.rep("  ", depth)..k..":")
      dumpTable(v, depth+1)
    else
      print(string.rep("  ", depth)..k..": ",v)
    end
  end
end
KEYS = {"account_key~account_name", "policy_key"}
cmsgpack = require 'luamsgpack/MessagePack'
PB = loadfile('../../../quotapb/quotapb.lua')()
T0_SEC = 1670834486
T0_MSEC = 0
function DUMP(...)
  local toprint = {}
  for i, v in next, arg do
    if type(v) == "table" then
      v = cjson.encode(v)
    end
    toprint[i] = v
  end
  print(unpack(toprint))
end
redis = {
  DATA = {},
  TTL = {}
}
function redis.call(method, ...)
  local function check(nameTypes)
    if #nameTypes ~= arg.n then
      error(string.format("TEST ERROR: redis:call: %s: wrong arg.n: %d != %d", method, #nameTypes, args.n))
    end
    for i, nameType in ipairs(nameTypes) do
      local t = type(arg[i])
      local name, want = unpack(nameType)
      if t ~= want then
        error(string.format("TEST ERROR: redis:call: %s: bad %s type: %s, wanted %s", method, name, t, want))
      end
    end
    return unpack(arg)
  end
  if method == "HGET" then
    local key, field = check({{"key", "string"}, {"field", "string"}})
    return (redis.DATA[key] or {})[field]
  end
  if method == "HMGET" then
    local key, field, field2, field3 = check({
      {"key", "string"},
      {"field", "string"},
      {"field2", "string"},
      {"field3", "string"},
    })
    local subCache = (redis.DATA[key] or {})
    return {subCache[field], subCache[field2], subCache[field3]}
  end
  if method == "HSET" and arg.n == 3 then
    local key, field, value = check({
      {"key", "string"},
      {"field", "string"}, {"value", "string"},
    })
    local subCache = redis.DATA[key]
    if subCache == nil then
      subCache = {}
      redis.DATA[key] = subCache
    end
    subCache[field] = tostring(value)
    return
  end
  if method == "HSET" and arg.n == 5 then
    local key, field, value, field2, value2 = check({
      {"key", "string"},
      {"field", "string"}, {"value", "string"},
      {"field2", "string"}, {"value2", "string"},
    })
    local subCache = redis.DATA[key]
    if subCache == nil then
      subCache = {}
      redis.DATA[key] = subCache
    end
    subCache[field] = tostring(value)
    subCache[field2] = tostring(value3)
    return
  end
  if method == "HSET" then
    local key, field, value, field2, value2, field3, value3 = check({
      {"key", "string"},
      {"field", "string"}, {"value", "string"},
      {"field2", "string"}, {"value2", "string"},
      {"field3", "string"}, {"value3", "string"},
    })
    local subCache = redis.DATA[key]
    if subCache == nil then
      subCache = {}
      redis.DATA[key] = subCache
    end
    subCache[field] = tostring(value)
    subCache[field2] = tostring(value2)
    subCache[field3] = tostring(value3)
    return
  end
  if method == "GET" then
    local key = check({{"key", "string"}})
    return redis.DATA[key]
  end
  if method == "SET" and arg.n == 4 then
    local key, value, PX, TTL = check({
      {"key", "string"}, {"value", "string"},
      {"PX", "string"}, {"TTL", "number"},
    })
    if PX ~= "PX" then
      error(string.format("TEST ERROR: unexpected option %s != PX", PX))
    end
    redis.DATA[key] = value
    redis.TTL[key] = TTL
    return
  end
  if method == "SET" then
    local key, value = check({{"key", "string"}, {"value", "string"}})
    redis.DATA[key] = value
    redis.TTL[key] = nil
    return
  end
  if method == "PEXPIRE" then
    local key, exp = check({{"key", "string"}, {"exp", "number"}})
    redis.TTL[key] = exp
    return
  end
  if method == "TIME" then
    check({})
    return {T0_SEC, T0_MSEC}
  end
  error(string.format("TEST ERROR: redis.call unsupported method %s", method))
end
function redis.error_reply(msg)
  return { error = "ERR "..msg }
end
function redis.status_reply(obj)
  return { ok = obj }
end
local Utils = loadfile('../../lua/utils.lua')(PB, policyNames)
local Policy = loadfile('../../lua/policy.lua')(PB, Utils)
local Account = loadfile('../../lua/account.lua')(PB, Utils, Policy)
G = {}
G.Utils = Utils
G.Policy = Policy
G.Account = Account
-- This is a hack; we hook the output to reset global state.
-- The alternative would be to add a layer of 'test classes', but for our
-- purposes, this should be OK.
local realStartTest = lu.LuaUnit.outputType.startTest
lu.LuaUnit.outputType.startTest = function( self, testName )
  redis.DATA = {}
  redis.TTL = {}
  Policy.CACHE = {}
  Account.CACHE = {}
  Utils.NOW.seconds = T0_SEC
  Utils.NOW.nanos = T0_MSEC * 1000000
  realStartTest(self, testName)
end


require 'test_fixtures'
Account = G.Account
Policy = G.Policy
Utils = G.Utils
function testMillis()
  lu.assertEquals(Utils.Millis(nil), nil)
  local dur = PB.new("google.protobuf.Duration", {
    seconds = 127,
    nanos = 19304658,
  })
  lu.assertEquals(Utils.Millis(dur), 127019)
end
function testWithRequestIDNoKey()
  local req = PB.new("go.chromium.org.luci.server.quota.quotapb.UpdateAccountsInput")
  local ret = Utils.WithRequestID(req, function()
    return PB.new("google.protobuf.Duration", {
      seconds = 100,
    }), true
  end)
  lu.assertEquals(ret, "\145d")
  lu.assertEquals(redis.DATA, {})
  lu.assertEquals(redis.TTL, {})
end
function testWithRequestIDWithKeyAndHash()
  local req = PB.new("go.chromium.org.luci.server.quota.quotapb.UpdateAccountsInput", {
    request_key = "thing",
    request_key_ttl = PB.new("google.protobuf.Duration", {
      seconds = 127,
      nanos = 19304658,
    }),
    hash_scheme = 1,
    hash = "i am a banana.",
  })
  local ret = Utils.WithRequestID(req, function()
    return PB.new("google.protobuf.Duration", {
      seconds = 100,
    }), true
  end)
  lu.assertEquals(ret, "\145d")
  lu.assertEquals(redis.DATA["thing"], {
    hash="i am a banana.",
    hash_scheme="1",
    response="\145d",
  })
  lu.assertEquals(redis.TTL["thing"], 127019)
  local ret = Utils.WithRequestID(req, function()
    error("no! this should be deduplicated!")
  end)
  lu.assertEquals(ret, "\145d")
  req.hash = "not banana"
  local ret = Utils.WithRequestID(req, function()
    error("no! this should be deduplicated!")
  end)
  lu.assertEquals(ret, {
    error = "ERR REQUEST_HASH",
  })
  req.hash_scheme = 2 -- allowed
  local ret = Utils.WithRequestID(req, function()
    error("no! this should be deduplicated!")
  end)
  lu.assertEquals(ret, "\145d")
end
function testWithRequestIDError()
  local req = PB.new("go.chromium.org.luci.server.quota.quotapb.UpdateAccountsInput", {
    request_key = "thing",
    request_key_ttl = PB.new("google.protobuf.Duration", {
      seconds = 127,
      nanos = 19304658,
    }),
    hash_scheme = 1,
    hash = "i am a banana.",
  })
  local ret = Utils.WithRequestID(req, function()
    return PB.new("google.protobuf.Duration", {
      seconds = 100,
    }), false
  end)
  lu.assertEquals(ret, "\145d")
  lu.assertEquals(redis.DATA, {})
  lu.assertEquals(redis.TTL, {})
end
return lu.LuaUnit.run("-v")