-- Code generated by luapp. DO NOT EDIT.



local PB = (function(...)
local PB = {}

local next = next
local type = type

PB.E = {
  ["go.chromium.org.luci.server.quota.quotapb.Op.Options"] = {
    ["NO_OPTIONS"] = 0,
    [0] = "NO_OPTIONS",
    ["IGNORE_POLICY_BOUNDS"] = 1,
    [1] = "IGNORE_POLICY_BOUNDS",
    ["DO_NOT_CAP_PROPOSED"] = 2,
    [2] = "DO_NOT_CAP_PROPOSED",
    ["WITH_POLICY_LIMIT_DELTA"] = 4,
    [4] = "WITH_POLICY_LIMIT_DELTA",
  },

  ["go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo"] = {
    ["CURRENT_BALANCE"] = 0,
    [0] = "CURRENT_BALANCE",
    ["ZERO"] = 1,
    [1] = "ZERO",
    ["DEFAULT"] = 2,
    [2] = "DEFAULT",
    ["LIMIT"] = 3,
    [3] = "LIMIT",
  },

  ["go.chromium.org.luci.server.quota.quotapb.OpResult.AccountStatus"] = {
    ["ALREADY_EXISTS"] = 0,
    [0] = "ALREADY_EXISTS",
    ["CREATED"] = 1,
    [1] = "CREATED",
    ["RECREATED"] = 2,
    [2] = "RECREATED",
  },

  ["go.chromium.org.luci.server.quota.quotapb.OpResult.OpStatus"] = {
    ["SUCCESS"] = 0,
    [0] = "SUCCESS",
    ["ERR_UNKNOWN"] = 1,
    [1] = "ERR_UNKNOWN",
    ["ERR_OVERFLOW"] = 2,
    [2] = "ERR_OVERFLOW",
    ["ERR_UNDERFLOW"] = 3,
    [3] = "ERR_UNDERFLOW",
    ["ERR_UNKNOWN_POLICY"] = 4,
    [4] = "ERR_UNKNOWN_POLICY",
    ["ERR_MISSING_ACCOUNT"] = 5,
    [5] = "ERR_MISSING_ACCOUNT",
    ["ERR_POLICY_REQUIRED"] = 6,
    [6] = "ERR_POLICY_REQUIRED",
  },
}

PB.M = {
  ["go.chromium.org.luci.server.quota.quotapb.Account"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["balance"] -- 1: int64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field balance: expected number, but got "..T)
        end
        if val > 9007199254740991 then
          error("field balance: overflows lua max integer")
        end
        if val < -9007199254740991 then
          error("field balance: underflows lua min integer")
        end
        acc[1] = val
      end

      val = obj["updated_ts"] -- 2: google.protobuf.Timestamp
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field updated_ts: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field updated_ts: missing type")
        end
        if val["$type"] ~= "google.protobuf.Timestamp" then
          error("field updated_ts: expected message type 'google.protobuf.Timestamp', but got "..val["$type"])
        end
        val = PB.M["google.protobuf.Timestamp"].marshal(val)
        acc[2] = val
      end

      val = obj["policy_change_ts"] -- 3: google.protobuf.Timestamp
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field policy_change_ts: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field policy_change_ts: missing type")
        end
        if val["$type"] ~= "google.protobuf.Timestamp" then
          error("field policy_change_ts: expected message type 'google.protobuf.Timestamp', but got "..val["$type"])
        end
        val = PB.M["google.protobuf.Timestamp"].marshal(val)
        acc[3] = val
      end

      val = obj["policy_ref"] -- 4: go.chromium.org.luci.server.quota.quotapb.PolicyRef
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field policy_ref: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field policy_ref: missing type")
        end
        if val["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.PolicyRef" then
          error("field policy_ref: expected message type 'go.chromium.org.luci.server.quota.quotapb.PolicyRef', but got "..val["$type"])
        end
        val = PB.M["go.chromium.org.luci.server.quota.quotapb.PolicyRef"].marshal(val)
        acc[4] = val
      end

      val = obj["policy"] -- 5: go.chromium.org.luci.server.quota.quotapb.Policy
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field policy: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field policy: missing type")
        end
        if val["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.Policy" then
          error("field policy: expected message type 'go.chromium.org.luci.server.quota.quotapb.Policy', but got "..val["$type"])
        end
        val = PB.M["go.chromium.org.luci.server.quota.quotapb.Policy"].marshal(val)
        acc[5] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.Account",
        ["balance"] = 0,
        ["updated_ts"] = nil,
        ["policy_change_ts"] = nil,
        ["policy_ref"] = nil,
        ["policy"] = nil,
      }
      local dec = {
        [1] = function(val) -- balance: int64
          local T = type(val)
          if T ~= "number" then
            error("field balance: expected number, but got "..T)
          end
          ret["balance"] = val
        end,
        [2] = function(val) -- updated_ts: google.protobuf.Timestamp
          local T = type(val)
          if T ~= "table" then
            error("field updated_ts: expected table, but got "..T)
          end
          ret["updated_ts"] = PB.M["google.protobuf.Timestamp"].unmarshal(val)
        end,
        [3] = function(val) -- policy_change_ts: google.protobuf.Timestamp
          local T = type(val)
          if T ~= "table" then
            error("field policy_change_ts: expected table, but got "..T)
          end
          ret["policy_change_ts"] = PB.M["google.protobuf.Timestamp"].unmarshal(val)
        end,
        [4] = function(val) -- policy_ref: go.chromium.org.luci.server.quota.quotapb.PolicyRef
          local T = type(val)
          if T ~= "table" then
            error("field policy_ref: expected table, but got "..T)
          end
          ret["policy_ref"] = PB.M["go.chromium.org.luci.server.quota.quotapb.PolicyRef"].unmarshal(val)
        end,
        [5] = function(val) -- policy: go.chromium.org.luci.server.quota.quotapb.Policy
          local T = type(val)
          if T ~= "table" then
            error("field policy: expected table, but got "..T)
          end
          ret["policy"] = PB.M["go.chromium.org.luci.server.quota.quotapb.Policy"].unmarshal(val)
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["balance"] = true,
      ["updated_ts"] = true,
      ["policy_change_ts"] = true,
      ["policy_ref"] = true,
      ["policy"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.AccountID"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["app_id"] -- 1: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field app_id: expected string, but got "..T)
        end
        acc[1] = val
      end

      val = obj["realm"] -- 2: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field realm: expected string, but got "..T)
        end
        acc[2] = val
      end

      val = obj["identity"] -- 3: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field identity: expected string, but got "..T)
        end
        acc[3] = val
      end

      val = obj["namespace"] -- 4: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field namespace: expected string, but got "..T)
        end
        acc[4] = val
      end

      val = obj["name"] -- 5: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field name: expected string, but got "..T)
        end
        acc[5] = val
      end

      val = obj["resource_type"] -- 6: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field resource_type: expected string, but got "..T)
        end
        acc[6] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.AccountID",
        ["app_id"] = "",
        ["realm"] = "",
        ["identity"] = "",
        ["namespace"] = "",
        ["name"] = "",
        ["resource_type"] = "",
      }
      local dec = {
        [1] = function(val) -- app_id: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field app_id: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field app_id: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field app_id: expected string, but got "..T)
          end
          ret["app_id"] = val
        end,
        [2] = function(val) -- realm: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field realm: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field realm: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field realm: expected string, but got "..T)
          end
          ret["realm"] = val
        end,
        [3] = function(val) -- identity: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field identity: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field identity: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field identity: expected string, but got "..T)
          end
          ret["identity"] = val
        end,
        [4] = function(val) -- namespace: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field namespace: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field namespace: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field namespace: expected string, but got "..T)
          end
          ret["namespace"] = val
        end,
        [5] = function(val) -- name: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field name: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field name: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field name: expected string, but got "..T)
          end
          ret["name"] = val
        end,
        [6] = function(val) -- resource_type: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field resource_type: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field resource_type: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field resource_type: expected string, but got "..T)
          end
          ret["resource_type"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["app_id"] = true,
      ["realm"] = true,
      ["identity"] = true,
      ["namespace"] = true,
      ["name"] = true,
      ["resource_type"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.ApplyOpsRequest"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["request_id"] -- 1: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field request_id: expected string, but got "..T)
        end
        acc[1] = val
      end

      val = obj["request_id_ttl"] -- 2: google.protobuf.Duration
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field request_id_ttl: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field request_id_ttl: missing type")
        end
        if val["$type"] ~= "google.protobuf.Duration" then
          error("field request_id_ttl: expected message type 'google.protobuf.Duration', but got "..val["$type"])
        end
        val = PB.M["google.protobuf.Duration"].marshal(val)
        acc[2] = val
      end

      val = obj["ops"] -- 3: repeated go.chromium.org.luci.server.quota.quotapb.Op
      if next(val) ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field ops: expected list[message], but got "..T)
        end
        local maxIdx = 0
        local length = 0
        for i, v in next, val do
          if type(i) ~= "number" then
            error("field ops: expected list[message], but got table")
          end
          local T = type(v)
          if T ~= "table" then
            error("field ops["..(i-1).."]: expected table, but got "..T)
          end
          if not v["$type"] then
            error("field ops["..(i-1).."]: missing type")
          end
          if v["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.Op" then
            error("field ops["..(i-1).."]: expected message type 'go.chromium.org.luci.server.quota.quotapb.Op', but got "..v["$type"])
          end
          val[i] = PB.M["go.chromium.org.luci.server.quota.quotapb.Op"].marshal(v)
          if i > maxIdx then
            maxIdx = i
          end
          length = length + 1
        end
        if length ~= maxIdx then
          error("field ops: expected list[message], but got table")
        end
        acc[3] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.ApplyOpsRequest",
        ["request_id"] = "",
        ["request_id_ttl"] = nil,
        ["ops"] = {},
      }
      local dec = {
        [1] = function(val) -- request_id: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field request_id: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field request_id: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field request_id: expected string, but got "..T)
          end
          ret["request_id"] = val
        end,
        [2] = function(val) -- request_id_ttl: google.protobuf.Duration
          local T = type(val)
          if T ~= "table" then
            error("field request_id_ttl: expected table, but got "..T)
          end
          ret["request_id_ttl"] = PB.M["google.protobuf.Duration"].unmarshal(val)
        end,
        [3] = function(val) -- ops: repeated go.chromium.org.luci.server.quota.quotapb.Op
          local T = type(val)
          if T ~= "table" then
            error("field ops: expected list[message], but got "..T)
          end
          local max = 0
          local count = 0
          for i, v in next, val do
            if type(i) ~= "number" then
              error("field ops: expected list[message], but got table")
            end
            if i > max then
              max = i
            end
            count = count + 1
            local T = type(v)
            if T ~= "table" then
              error("field ops["..(i-1).."]: expected table, but got "..T)
            end
            val[i] = PB.M["go.chromium.org.luci.server.quota.quotapb.Op"].unmarshal(v)
          end
          if max ~= count then
            error("field ops: expected list[message], but got table")
          end
          ret["ops"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["request_id"] = true,
      ["request_id_ttl"] = true,
      ["ops"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.ApplyOpsResponse"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["results"] -- 1: repeated go.chromium.org.luci.server.quota.quotapb.OpResult
      if next(val) ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field results: expected list[message], but got "..T)
        end
        local maxIdx = 0
        local length = 0
        for i, v in next, val do
          if type(i) ~= "number" then
            error("field results: expected list[message], but got table")
          end
          local T = type(v)
          if T ~= "table" then
            error("field results["..(i-1).."]: expected table, but got "..T)
          end
          if not v["$type"] then
            error("field results["..(i-1).."]: missing type")
          end
          if v["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.OpResult" then
            error("field results["..(i-1).."]: expected message type 'go.chromium.org.luci.server.quota.quotapb.OpResult', but got "..v["$type"])
          end
          val[i] = PB.M["go.chromium.org.luci.server.quota.quotapb.OpResult"].marshal(v)
          if i > maxIdx then
            maxIdx = i
          end
          length = length + 1
        end
        if length ~= maxIdx then
          error("field results: expected list[message], but got table")
        end
        acc[1] = val
      end

      val = obj["originally_set"] -- 2: google.protobuf.Timestamp
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field originally_set: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field originally_set: missing type")
        end
        if val["$type"] ~= "google.protobuf.Timestamp" then
          error("field originally_set: expected message type 'google.protobuf.Timestamp', but got "..val["$type"])
        end
        val = PB.M["google.protobuf.Timestamp"].marshal(val)
        acc[2] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.ApplyOpsResponse",
        ["results"] = {},
        ["originally_set"] = nil,
      }
      local dec = {
        [1] = function(val) -- results: repeated go.chromium.org.luci.server.quota.quotapb.OpResult
          local T = type(val)
          if T ~= "table" then
            error("field results: expected list[message], but got "..T)
          end
          local max = 0
          local count = 0
          for i, v in next, val do
            if type(i) ~= "number" then
              error("field results: expected list[message], but got table")
            end
            if i > max then
              max = i
            end
            count = count + 1
            local T = type(v)
            if T ~= "table" then
              error("field results["..(i-1).."]: expected table, but got "..T)
            end
            val[i] = PB.M["go.chromium.org.luci.server.quota.quotapb.OpResult"].unmarshal(v)
          end
          if max ~= count then
            error("field results: expected list[message], but got table")
          end
          ret["results"] = val
        end,
        [2] = function(val) -- originally_set: google.protobuf.Timestamp
          local T = type(val)
          if T ~= "table" then
            error("field originally_set: expected table, but got "..T)
          end
          ret["originally_set"] = PB.M["google.protobuf.Timestamp"].unmarshal(val)
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["results"] = true,
      ["originally_set"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.Op"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["account_id"] -- 1: go.chromium.org.luci.server.quota.quotapb.AccountID
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field account_id: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field account_id: missing type")
        end
        if val["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.AccountID" then
          error("field account_id: expected message type 'go.chromium.org.luci.server.quota.quotapb.AccountID', but got "..val["$type"])
        end
        val = PB.M["go.chromium.org.luci.server.quota.quotapb.AccountID"].marshal(val)
        acc[1] = val
      end

      val = obj["policy_id"] -- 2: go.chromium.org.luci.server.quota.quotapb.PolicyID
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field policy_id: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field policy_id: missing type")
        end
        if val["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.PolicyID" then
          error("field policy_id: expected message type 'go.chromium.org.luci.server.quota.quotapb.PolicyID', but got "..val["$type"])
        end
        val = PB.M["go.chromium.org.luci.server.quota.quotapb.PolicyID"].marshal(val)
        acc[2] = val
      end

      val = obj["relative_to"] -- 3: enum go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo
      if val ~= 0 and val ~= "CURRENT_BALANCE" then
        local T = type(val)
        local origval = val
        if T == "string" then
          val = PB.E["go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo"][val]
          if val == nil then
            error("field relative_to: bad string enum value "..origval)
          end
        elseif T == "number" then
          if PB.E["go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo"][val] == nil then
            error("field relative_to: bad numeric enum value "..origval)
          end
        else
          error("field relative_to: expected number or string, but got "..T)
        end
        acc[3] = val
      end

      val = obj["delta"] -- 4: int64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field delta: expected number, but got "..T)
        end
        if val > 9007199254740991 then
          error("field delta: overflows lua max integer")
        end
        if val < -9007199254740991 then
          error("field delta: underflows lua min integer")
        end
        acc[4] = val
      end

      val = obj["options"] -- 5: uint32
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field options: expected number, but got "..T)
        end
        if val < 0 then
          error("field options: negative")
        end
        if val > 4294967295 then
          error("field options: overflows max uint32")
        end
        acc[5] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.Op",
        ["account_id"] = nil,
        ["policy_id"] = nil,
        ["relative_to"] = "CURRENT_BALANCE",
        ["delta"] = 0,
        ["options"] = 0,
      }
      local dec = {
        [1] = function(val) -- account_id: go.chromium.org.luci.server.quota.quotapb.AccountID
          local T = type(val)
          if T ~= "table" then
            error("field account_id: expected table, but got "..T)
          end
          ret["account_id"] = PB.M["go.chromium.org.luci.server.quota.quotapb.AccountID"].unmarshal(val)
        end,
        [2] = function(val) -- policy_id: go.chromium.org.luci.server.quota.quotapb.PolicyID
          local T = type(val)
          if T ~= "table" then
            error("field policy_id: expected table, but got "..T)
          end
          ret["policy_id"] = PB.M["go.chromium.org.luci.server.quota.quotapb.PolicyID"].unmarshal(val)
        end,
        [3] = function(val) -- relative_to: enum go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo
          local T = type(val)
          if T ~= "number" then
            error("field relative_to: expected numeric enum, but got "..T)
          end
          local origval = val
          local newval = PB.E["go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo"][val]
          if newval == nil then
            error("field relative_to: bad enum value "..origval)
          end
          ret["relative_to"] = newval
        end,
        [4] = function(val) -- delta: int64
          local T = type(val)
          if T ~= "number" then
            error("field delta: expected number, but got "..T)
          end
          ret["delta"] = val
        end,
        [5] = function(val) -- options: uint32
          local T = type(val)
          if T ~= "number" then
            error("field options: expected number, but got "..T)
          end
          ret["options"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["account_id"] = true,
      ["policy_id"] = true,
      ["relative_to"] = true,
      ["delta"] = true,
      ["options"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.OpResult"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["new_balance"] -- 1: int64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field new_balance: expected number, but got "..T)
        end
        if val > 9007199254740991 then
          error("field new_balance: overflows lua max integer")
        end
        if val < -9007199254740991 then
          error("field new_balance: underflows lua min integer")
        end
        acc[1] = val
      end

      val = obj["previous_balance"] -- 2: int64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field previous_balance: expected number, but got "..T)
        end
        if val > 9007199254740991 then
          error("field previous_balance: overflows lua max integer")
        end
        if val < -9007199254740991 then
          error("field previous_balance: underflows lua min integer")
        end
        acc[2] = val
      end

      val = obj["account_status"] -- 3: enum go.chromium.org.luci.server.quota.quotapb.OpResult.AccountStatus
      if val ~= 0 and val ~= "ALREADY_EXISTS" then
        local T = type(val)
        local origval = val
        if T == "string" then
          val = PB.E["go.chromium.org.luci.server.quota.quotapb.OpResult.AccountStatus"][val]
          if val == nil then
            error("field account_status: bad string enum value "..origval)
          end
        elseif T == "number" then
          if PB.E["go.chromium.org.luci.server.quota.quotapb.OpResult.AccountStatus"][val] == nil then
            error("field account_status: bad numeric enum value "..origval)
          end
        else
          error("field account_status: expected number or string, but got "..T)
        end
        acc[3] = val
      end

      val = obj["status"] -- 4: enum go.chromium.org.luci.server.quota.quotapb.OpResult.OpStatus
      if val ~= 0 and val ~= "SUCCESS" then
        local T = type(val)
        local origval = val
        if T == "string" then
          val = PB.E["go.chromium.org.luci.server.quota.quotapb.OpResult.OpStatus"][val]
          if val == nil then
            error("field status: bad string enum value "..origval)
          end
        elseif T == "number" then
          if PB.E["go.chromium.org.luci.server.quota.quotapb.OpResult.OpStatus"][val] == nil then
            error("field status: bad numeric enum value "..origval)
          end
        else
          error("field status: expected number or string, but got "..T)
        end
        acc[4] = val
      end

      val = obj["status_msg"] -- 5: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field status_msg: expected string, but got "..T)
        end
        acc[5] = val
      end

      val = obj["previous_balance_adjusted"] -- 6: int64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field previous_balance_adjusted: expected number, but got "..T)
        end
        if val > 9007199254740991 then
          error("field previous_balance_adjusted: overflows lua max integer")
        end
        if val < -9007199254740991 then
          error("field previous_balance_adjusted: underflows lua min integer")
        end
        acc[6] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.OpResult",
        ["new_balance"] = 0,
        ["previous_balance"] = 0,
        ["account_status"] = "ALREADY_EXISTS",
        ["status"] = "SUCCESS",
        ["status_msg"] = "",
        ["previous_balance_adjusted"] = 0,
      }
      local dec = {
        [1] = function(val) -- new_balance: int64
          local T = type(val)
          if T ~= "number" then
            error("field new_balance: expected number, but got "..T)
          end
          ret["new_balance"] = val
        end,
        [2] = function(val) -- previous_balance: int64
          local T = type(val)
          if T ~= "number" then
            error("field previous_balance: expected number, but got "..T)
          end
          ret["previous_balance"] = val
        end,
        [3] = function(val) -- account_status: enum go.chromium.org.luci.server.quota.quotapb.OpResult.AccountStatus
          local T = type(val)
          if T ~= "number" then
            error("field account_status: expected numeric enum, but got "..T)
          end
          local origval = val
          local newval = PB.E["go.chromium.org.luci.server.quota.quotapb.OpResult.AccountStatus"][val]
          if newval == nil then
            error("field account_status: bad enum value "..origval)
          end
          ret["account_status"] = newval
        end,
        [4] = function(val) -- status: enum go.chromium.org.luci.server.quota.quotapb.OpResult.OpStatus
          local T = type(val)
          if T ~= "number" then
            error("field status: expected numeric enum, but got "..T)
          end
          local origval = val
          local newval = PB.E["go.chromium.org.luci.server.quota.quotapb.OpResult.OpStatus"][val]
          if newval == nil then
            error("field status: bad enum value "..origval)
          end
          ret["status"] = newval
        end,
        [5] = function(val) -- status_msg: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field status_msg: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field status_msg: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field status_msg: expected string, but got "..T)
          end
          ret["status_msg"] = val
        end,
        [6] = function(val) -- previous_balance_adjusted: int64
          local T = type(val)
          if T ~= "number" then
            error("field previous_balance_adjusted: expected number, but got "..T)
          end
          ret["previous_balance_adjusted"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["new_balance"] = true,
      ["previous_balance"] = true,
      ["account_status"] = true,
      ["status"] = true,
      ["status_msg"] = true,
      ["previous_balance_adjusted"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.Policy"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["default"] -- 1: uint64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field default: expected number, but got "..T)
        end
        if val < 0 then
          error("field default: negative")
        end
        if val > 9007199254740991 then
          error("field default: overflows lua max integer")
        end
        acc[1] = val
      end

      val = obj["limit"] -- 2: uint64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field limit: expected number, but got "..T)
        end
        if val < 0 then
          error("field limit: negative")
        end
        if val > 9007199254740991 then
          error("field limit: overflows lua max integer")
        end
        acc[2] = val
      end

      val = obj["refill"] -- 3: go.chromium.org.luci.server.quota.quotapb.Policy.Refill
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field refill: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field refill: missing type")
        end
        if val["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.Policy.Refill" then
          error("field refill: expected message type 'go.chromium.org.luci.server.quota.quotapb.Policy.Refill', but got "..val["$type"])
        end
        val = PB.M["go.chromium.org.luci.server.quota.quotapb.Policy.Refill"].marshal(val)
        acc[3] = val
      end

      val = obj["options"] -- 4: int32
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field options: expected number, but got "..T)
        end
        if val > 2147483647 then
          error("field options: overflows int32")
        end
        if val < -2147483648 then
          error("field options: underflows int32")
        end
        acc[4] = val
      end

      val = obj["lifetime"] -- 5: google.protobuf.Duration
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field lifetime: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field lifetime: missing type")
        end
        if val["$type"] ~= "google.protobuf.Duration" then
          error("field lifetime: expected message type 'google.protobuf.Duration', but got "..val["$type"])
        end
        val = PB.M["google.protobuf.Duration"].marshal(val)
        acc[5] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.Policy",
        ["default"] = 0,
        ["limit"] = 0,
        ["refill"] = nil,
        ["options"] = 0,
        ["lifetime"] = nil,
      }
      local dec = {
        [1] = function(val) -- default: uint64
          local T = type(val)
          if T ~= "number" then
            error("field default: expected number, but got "..T)
          end
          ret["default"] = val
        end,
        [2] = function(val) -- limit: uint64
          local T = type(val)
          if T ~= "number" then
            error("field limit: expected number, but got "..T)
          end
          ret["limit"] = val
        end,
        [3] = function(val) -- refill: go.chromium.org.luci.server.quota.quotapb.Policy.Refill
          local T = type(val)
          if T ~= "table" then
            error("field refill: expected table, but got "..T)
          end
          ret["refill"] = PB.M["go.chromium.org.luci.server.quota.quotapb.Policy.Refill"].unmarshal(val)
        end,
        [4] = function(val) -- options: int32
          local T = type(val)
          if T ~= "number" then
            error("field options: expected number, but got "..T)
          end
          ret["options"] = val
        end,
        [5] = function(val) -- lifetime: google.protobuf.Duration
          local T = type(val)
          if T ~= "table" then
            error("field lifetime: expected table, but got "..T)
          end
          ret["lifetime"] = PB.M["google.protobuf.Duration"].unmarshal(val)
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["default"] = true,
      ["limit"] = true,
      ["refill"] = true,
      ["options"] = true,
      ["lifetime"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.Policy.Refill"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["units"] -- 1: int64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field units: expected number, but got "..T)
        end
        if val > 9007199254740991 then
          error("field units: overflows lua max integer")
        end
        if val < -9007199254740991 then
          error("field units: underflows lua min integer")
        end
        acc[1] = val
      end

      val = obj["interval"] -- 2: uint32
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field interval: expected number, but got "..T)
        end
        if val < 0 then
          error("field interval: negative")
        end
        if val > 4294967295 then
          error("field interval: overflows max uint32")
        end
        acc[2] = val
      end

      val = obj["offset"] -- 3: uint32
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field offset: expected number, but got "..T)
        end
        if val < 0 then
          error("field offset: negative")
        end
        if val > 4294967295 then
          error("field offset: overflows max uint32")
        end
        acc[3] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.Policy.Refill",
        ["units"] = 0,
        ["interval"] = 0,
        ["offset"] = 0,
      }
      local dec = {
        [1] = function(val) -- units: int64
          local T = type(val)
          if T ~= "number" then
            error("field units: expected number, but got "..T)
          end
          ret["units"] = val
        end,
        [2] = function(val) -- interval: uint32
          local T = type(val)
          if T ~= "number" then
            error("field interval: expected number, but got "..T)
          end
          ret["interval"] = val
        end,
        [3] = function(val) -- offset: uint32
          local T = type(val)
          if T ~= "number" then
            error("field offset: expected number, but got "..T)
          end
          ret["offset"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["units"] = true,
      ["interval"] = true,
      ["offset"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.PolicyConfigID"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["app_id"] -- 1: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field app_id: expected string, but got "..T)
        end
        acc[1] = val
      end

      val = obj["realm"] -- 2: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field realm: expected string, but got "..T)
        end
        acc[2] = val
      end

      val = obj["version_scheme"] -- 3: uint32
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field version_scheme: expected number, but got "..T)
        end
        if val < 0 then
          error("field version_scheme: negative")
        end
        if val > 4294967295 then
          error("field version_scheme: overflows max uint32")
        end
        acc[3] = val
      end

      val = obj["version"] -- 4: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field version: expected string, but got "..T)
        end
        acc[4] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.PolicyConfigID",
        ["app_id"] = "",
        ["realm"] = "",
        ["version_scheme"] = 0,
        ["version"] = "",
      }
      local dec = {
        [1] = function(val) -- app_id: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field app_id: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field app_id: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field app_id: expected string, but got "..T)
          end
          ret["app_id"] = val
        end,
        [2] = function(val) -- realm: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field realm: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field realm: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field realm: expected string, but got "..T)
          end
          ret["realm"] = val
        end,
        [3] = function(val) -- version_scheme: uint32
          local T = type(val)
          if T ~= "number" then
            error("field version_scheme: expected number, but got "..T)
          end
          ret["version_scheme"] = val
        end,
        [4] = function(val) -- version: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field version: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field version: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field version: expected string, but got "..T)
          end
          ret["version"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["app_id"] = true,
      ["realm"] = true,
      ["version_scheme"] = true,
      ["version"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.PolicyID"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["config"] -- 1: go.chromium.org.luci.server.quota.quotapb.PolicyConfigID
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field config: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field config: missing type")
        end
        if val["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.PolicyConfigID" then
          error("field config: expected message type 'go.chromium.org.luci.server.quota.quotapb.PolicyConfigID', but got "..val["$type"])
        end
        val = PB.M["go.chromium.org.luci.server.quota.quotapb.PolicyConfigID"].marshal(val)
        acc[1] = val
      end

      val = obj["key"] -- 2: go.chromium.org.luci.server.quota.quotapb.PolicyKey
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field key: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field key: missing type")
        end
        if val["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.PolicyKey" then
          error("field key: expected message type 'go.chromium.org.luci.server.quota.quotapb.PolicyKey', but got "..val["$type"])
        end
        val = PB.M["go.chromium.org.luci.server.quota.quotapb.PolicyKey"].marshal(val)
        acc[2] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.PolicyID",
        ["config"] = nil,
        ["key"] = nil,
      }
      local dec = {
        [1] = function(val) -- config: go.chromium.org.luci.server.quota.quotapb.PolicyConfigID
          local T = type(val)
          if T ~= "table" then
            error("field config: expected table, but got "..T)
          end
          ret["config"] = PB.M["go.chromium.org.luci.server.quota.quotapb.PolicyConfigID"].unmarshal(val)
        end,
        [2] = function(val) -- key: go.chromium.org.luci.server.quota.quotapb.PolicyKey
          local T = type(val)
          if T ~= "table" then
            error("field key: expected table, but got "..T)
          end
          ret["key"] = PB.M["go.chromium.org.luci.server.quota.quotapb.PolicyKey"].unmarshal(val)
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["config"] = true,
      ["key"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.PolicyKey"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["namespace"] -- 1: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field namespace: expected string, but got "..T)
        end
        acc[1] = val
      end

      val = obj["name"] -- 2: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field name: expected string, but got "..T)
        end
        acc[2] = val
      end

      val = obj["resource_type"] -- 3: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field resource_type: expected string, but got "..T)
        end
        acc[3] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.PolicyKey",
        ["namespace"] = "",
        ["name"] = "",
        ["resource_type"] = "",
      }
      local dec = {
        [1] = function(val) -- namespace: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field namespace: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field namespace: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field namespace: expected string, but got "..T)
          end
          ret["namespace"] = val
        end,
        [2] = function(val) -- name: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field name: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field name: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field name: expected string, but got "..T)
          end
          ret["name"] = val
        end,
        [3] = function(val) -- resource_type: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field resource_type: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field resource_type: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field resource_type: expected string, but got "..T)
          end
          ret["resource_type"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["namespace"] = true,
      ["name"] = true,
      ["resource_type"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.PolicyRef"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["config"] -- 1: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field config: expected string, but got "..T)
        end
        acc[1] = val
      end

      val = obj["key"] -- 2: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field key: expected string, but got "..T)
        end
        acc[2] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.PolicyRef",
        ["config"] = "",
        ["key"] = "",
      }
      local dec = {
        [1] = function(val) -- config: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field config: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field config: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field config: expected string, but got "..T)
          end
          ret["config"] = val
        end,
        [2] = function(val) -- key: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field key: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field key: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field key: expected string, but got "..T)
          end
          ret["key"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["config"] = true,
      ["key"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.RawOp"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["account_ref"] -- 1: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field account_ref: expected string, but got "..T)
        end
        acc[1] = val
      end

      val = obj["policy_ref"] -- 2: go.chromium.org.luci.server.quota.quotapb.PolicyRef
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field policy_ref: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field policy_ref: missing type")
        end
        if val["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.PolicyRef" then
          error("field policy_ref: expected message type 'go.chromium.org.luci.server.quota.quotapb.PolicyRef', but got "..val["$type"])
        end
        val = PB.M["go.chromium.org.luci.server.quota.quotapb.PolicyRef"].marshal(val)
        acc[2] = val
      end

      val = obj["relative_to"] -- 3: enum go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo
      if val ~= 0 and val ~= "CURRENT_BALANCE" then
        local T = type(val)
        local origval = val
        if T == "string" then
          val = PB.E["go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo"][val]
          if val == nil then
            error("field relative_to: bad string enum value "..origval)
          end
        elseif T == "number" then
          if PB.E["go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo"][val] == nil then
            error("field relative_to: bad numeric enum value "..origval)
          end
        else
          error("field relative_to: expected number or string, but got "..T)
        end
        acc[3] = val
      end

      val = obj["delta"] -- 4: int64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field delta: expected number, but got "..T)
        end
        if val > 9007199254740991 then
          error("field delta: overflows lua max integer")
        end
        if val < -9007199254740991 then
          error("field delta: underflows lua min integer")
        end
        acc[4] = val
      end

      val = obj["options"] -- 5: uint32
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field options: expected number, but got "..T)
        end
        if val < 0 then
          error("field options: negative")
        end
        if val > 4294967295 then
          error("field options: overflows max uint32")
        end
        acc[5] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.RawOp",
        ["account_ref"] = "",
        ["policy_ref"] = nil,
        ["relative_to"] = "CURRENT_BALANCE",
        ["delta"] = 0,
        ["options"] = 0,
      }
      local dec = {
        [1] = function(val) -- account_ref: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field account_ref: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field account_ref: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field account_ref: expected string, but got "..T)
          end
          ret["account_ref"] = val
        end,
        [2] = function(val) -- policy_ref: go.chromium.org.luci.server.quota.quotapb.PolicyRef
          local T = type(val)
          if T ~= "table" then
            error("field policy_ref: expected table, but got "..T)
          end
          ret["policy_ref"] = PB.M["go.chromium.org.luci.server.quota.quotapb.PolicyRef"].unmarshal(val)
        end,
        [3] = function(val) -- relative_to: enum go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo
          local T = type(val)
          if T ~= "number" then
            error("field relative_to: expected numeric enum, but got "..T)
          end
          local origval = val
          local newval = PB.E["go.chromium.org.luci.server.quota.quotapb.Op.RelativeTo"][val]
          if newval == nil then
            error("field relative_to: bad enum value "..origval)
          end
          ret["relative_to"] = newval
        end,
        [4] = function(val) -- delta: int64
          local T = type(val)
          if T ~= "number" then
            error("field delta: expected number, but got "..T)
          end
          ret["delta"] = val
        end,
        [5] = function(val) -- options: uint32
          local T = type(val)
          if T ~= "number" then
            error("field options: expected number, but got "..T)
          end
          ret["options"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["account_ref"] = true,
      ["policy_ref"] = true,
      ["relative_to"] = true,
      ["delta"] = true,
      ["options"] = true,
    },
  },

  ["go.chromium.org.luci.server.quota.quotapb.UpdateAccountsInput"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["request_key"] -- 1: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field request_key: expected string, but got "..T)
        end
        acc[1] = val
      end

      val = obj["request_key_ttl"] -- 2: google.protobuf.Duration
      if val ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field request_key_ttl: expected table, but got "..T)
        end
        if not val["$type"] then
          error("field request_key_ttl: missing type")
        end
        if val["$type"] ~= "google.protobuf.Duration" then
          error("field request_key_ttl: expected message type 'google.protobuf.Duration', but got "..val["$type"])
        end
        val = PB.M["google.protobuf.Duration"].marshal(val)
        acc[2] = val
      end

      val = obj["hash_scheme"] -- 3: uint32
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field hash_scheme: expected number, but got "..T)
        end
        if val < 0 then
          error("field hash_scheme: negative")
        end
        if val > 4294967295 then
          error("field hash_scheme: overflows max uint32")
        end
        acc[3] = val
      end

      val = obj["hash"] -- 4: string
      if val ~= "" then
        local T = type(val)
        if T ~= "string" then
          error("field hash: expected string, but got "..T)
        end
        acc[4] = val
      end

      val = obj["ops"] -- 5: repeated go.chromium.org.luci.server.quota.quotapb.RawOp
      if next(val) ~= nil then
        local T = type(val)
        if T ~= "table" then
          error("field ops: expected list[message], but got "..T)
        end
        local maxIdx = 0
        local length = 0
        for i, v in next, val do
          if type(i) ~= "number" then
            error("field ops: expected list[message], but got table")
          end
          local T = type(v)
          if T ~= "table" then
            error("field ops["..(i-1).."]: expected table, but got "..T)
          end
          if not v["$type"] then
            error("field ops["..(i-1).."]: missing type")
          end
          if v["$type"] ~= "go.chromium.org.luci.server.quota.quotapb.RawOp" then
            error("field ops["..(i-1).."]: expected message type 'go.chromium.org.luci.server.quota.quotapb.RawOp', but got "..v["$type"])
          end
          val[i] = PB.M["go.chromium.org.luci.server.quota.quotapb.RawOp"].marshal(v)
          if i > maxIdx then
            maxIdx = i
          end
          length = length + 1
        end
        if length ~= maxIdx then
          error("field ops: expected list[message], but got table")
        end
        acc[5] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "go.chromium.org.luci.server.quota.quotapb.UpdateAccountsInput",
        ["request_key"] = "",
        ["request_key_ttl"] = nil,
        ["hash_scheme"] = 0,
        ["hash"] = "",
        ["ops"] = {},
      }
      local dec = {
        [1] = function(val) -- request_key: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field request_key: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field request_key: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field request_key: expected string, but got "..T)
          end
          ret["request_key"] = val
        end,
        [2] = function(val) -- request_key_ttl: google.protobuf.Duration
          local T = type(val)
          if T ~= "table" then
            error("field request_key_ttl: expected table, but got "..T)
          end
          ret["request_key_ttl"] = PB.M["google.protobuf.Duration"].unmarshal(val)
        end,
        [3] = function(val) -- hash_scheme: uint32
          local T = type(val)
          if T ~= "number" then
            error("field hash_scheme: expected number, but got "..T)
          end
          ret["hash_scheme"] = val
        end,
        [4] = function(val) -- hash: string
          local T = type(val)
          if T == "number" then
            if not PB.internUnmarshalTable then
              error("field hash: failed to look up interned string: intern table not set")
            end
            local origval = val
            local newval = PB.internUnmarshalTable[val]
            if newval == nil then
              error("field hash: failed to look up interned string: "..origval)
            end
            val = newval
            T = type(val)
          end
          if T ~= "string" then
            error("field hash: expected string, but got "..T)
          end
          ret["hash"] = val
        end,
        [5] = function(val) -- ops: repeated go.chromium.org.luci.server.quota.quotapb.RawOp
          local T = type(val)
          if T ~= "table" then
            error("field ops: expected list[message], but got "..T)
          end
          local max = 0
          local count = 0
          for i, v in next, val do
            if type(i) ~= "number" then
              error("field ops: expected list[message], but got table")
            end
            if i > max then
              max = i
            end
            count = count + 1
            local T = type(v)
            if T ~= "table" then
              error("field ops["..(i-1).."]: expected table, but got "..T)
            end
            val[i] = PB.M["go.chromium.org.luci.server.quota.quotapb.RawOp"].unmarshal(v)
          end
          if max ~= count then
            error("field ops: expected list[message], but got table")
          end
          ret["ops"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["request_key"] = true,
      ["request_key_ttl"] = true,
      ["hash_scheme"] = true,
      ["hash"] = true,
      ["ops"] = true,
    },
  },

  ["google.protobuf.Duration"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["seconds"] -- 1: int64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field seconds: expected number, but got "..T)
        end
        if val > 9007199254740991 then
          error("field seconds: overflows lua max integer")
        end
        if val < -9007199254740991 then
          error("field seconds: underflows lua min integer")
        end
        acc[1] = val
      end

      val = obj["nanos"] -- 2: int32
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field nanos: expected number, but got "..T)
        end
        if val > 2147483647 then
          error("field nanos: overflows int32")
        end
        if val < -2147483648 then
          error("field nanos: underflows int32")
        end
        acc[2] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "google.protobuf.Duration",
        ["seconds"] = 0,
        ["nanos"] = 0,
      }
      local dec = {
        [1] = function(val) -- seconds: int64
          local T = type(val)
          if T ~= "number" then
            error("field seconds: expected number, but got "..T)
          end
          ret["seconds"] = val
        end,
        [2] = function(val) -- nanos: int32
          local T = type(val)
          if T ~= "number" then
            error("field nanos: expected number, but got "..T)
          end
          ret["nanos"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["seconds"] = true,
      ["nanos"] = true,
    },
  },

  ["google.protobuf.Timestamp"] = {
    marshal = function(obj)
      local acc, val, T = {}, nil, nil, nil

      val = obj["seconds"] -- 1: int64
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field seconds: expected number, but got "..T)
        end
        if val > 9007199254740991 then
          error("field seconds: overflows lua max integer")
        end
        if val < -9007199254740991 then
          error("field seconds: underflows lua min integer")
        end
        acc[1] = val
      end

      val = obj["nanos"] -- 2: int32
      if val ~= 0 then
        local T = type(val)
        if T ~= "number" then
          error("field nanos: expected number, but got "..T)
        end
        if val > 2147483647 then
          error("field nanos: overflows int32")
        end
        if val < -2147483648 then
          error("field nanos: underflows int32")
        end
        acc[2] = val
      end

      local unknown = obj["$unknown"]
      if unknown ~= nil then
        for k, v in next, unknown do acc[k] = v end
      end
      return acc
    end,

    unmarshal = function(raw)
      local defaults = {}
      local ret =  {
        ["$unknown"] = {},
        ["$type"] = "google.protobuf.Timestamp",
        ["seconds"] = 0,
        ["nanos"] = 0,
      }
      local dec = {
        [1] = function(val) -- seconds: int64
          local T = type(val)
          if T ~= "number" then
            error("field seconds: expected number, but got "..T)
          end
          ret["seconds"] = val
        end,
        [2] = function(val) -- nanos: int32
          local T = type(val)
          if T ~= "number" then
            error("field nanos: expected number, but got "..T)
          end
          ret["nanos"] = val
        end,
      }
      for k, v in next, raw do
        local fn = dec[k]
        if fn ~= nil then
          fn(v)
        else
          ret["$unknown"][k] = v
        end
      end
      return ret
    end,
    keys = {
      ["seconds"] = true,
      ["nanos"] = true,
    },
  },
}

if cmsgpack == nil then
  local cmsgpack = ...
  assert(cmsgpack)
end
local cmsgpack_pack = cmsgpack.pack
local cmsgpack_unpack = cmsgpack.unpack
function PB.setInternTable(t)
  if PB.internUnmarshalTable then
    error("cannot set intern table twice")
  end
  if type(t) ~= "table" then
    error("must call PB.setInternTable with a table (got "..type(t)..")")
  end
  PB.internUnmarshalTable = {}
  for i, v in ipairs(t) do
    PB.internUnmarshalTable[i-1] = v
  end
end
function PB.marshal(obj)
  local T = obj["$type"]
  if T == nil then
    error("obj is missing '$type' field")
  end
  local codec = PB.M[T]
  if codec == nil then
    error("unknown proto message type: "..T)
  end
  return cmsgpack_pack(codec.marshal(obj))
end
function PB.unmarshal(messageName, msgpackpb)
  local codec = PB.M[messageName]
  if codec == nil then
    error("unknown proto message type: "..messageName)
  end
  return codec.unmarshal(cmsgpack_unpack(msgpackpb))
end
function PB.new(messageName, defaults)
  local codec = PB.M[messageName]
  if codec == nil then
    error("unknown proto message type: "..messageName)
  end
  local ret = codec.unmarshal({})
  if defaults ~= nil then
    for k, v in next, defaults do
      if k[0] ~= "$" then
        if not codec.keys[k] then
          error("invalid property name '"..k.."' for "..messageName)
        end
        ret[k] = v
      end
    end
  end
  return ret
end
return PB
end)(cmsgpack)
PB.setInternTable(KEYS)

local Utils = (function(...)

local PB = ...
assert(PB)

local redis = redis

local Utils = {}

local nowRaw = redis.call('TIME')
Utils.NOW = PB.new('google.protobuf.Timestamp', {
  seconds = tonumber(nowRaw[1]),
  nanos = tonumber(nowRaw[2]) * 1000,
})

local math_floor = math.floor

function Utils.Millis(duration)
  if duration == nil then
    return nil
  end
  return math_floor(duration.seconds * 1000 + duration.nanos / 1000000)
end

function Utils.WithRequestID(req, callback)
  local req_id_key = req.request_key

  if req_id_key ~= "" then
    local hash_scheme, hash, response = unpack(redis.call(
       "HMGET", req_id_key, "hash_scheme", "hash", "response"))
    if hash_scheme ~= nil then
      local my_scheme = tonumber(hash_scheme)
      if response then
        if req.hash_scheme ~= my_scheme then
          return response
        elseif req.hash_scheme == my_scheme and req.hash == hash then
          return response
        else
          return redis.error_reply('REQUEST_HASH')
        end
      end
    end
  end

  local ret, allOK = callback()

  local response = PB.marshal(ret)

  if allOK and req_id_key ~= "" then
    redis.call(
      "HSET", req_id_key,
      "hash_scheme", tostring(req.hash_scheme),
      "hash", req.hash,
      "response", response
    )
    local ttl = Utils.Millis(req.request_key_ttl)
    if ttl == nil then
      ttl = 2 * 60 * 60 * 1000
    end
    if ttl > 0 then
      redis.call("PEXPIRE", req_id_key, ttl)
    end
  end

  return response
end

return Utils
end)(PB)

local req = PB.unmarshal("go.chromium.org.luci.server.quota.quotapb.UpdateAccountsInput", ARGV[1])

return Utils.WithRequestID(req, function()
  local Policy = (function(...)

local PB, Utils = ...
assert(PB)
assert(Utils)

local Policy = {
  CACHE = {},
}

local PolicyPB = "go.chromium.org.luci.server.quota.quotapb.Policy"
local PolicyRefPB = "go.chromium.org.luci.server.quota.quotapb.PolicyRef"

function Policy.get(policy_ref)
  assert(policy_ref ~= nil, "Policy:get called with <nil>")

  local configkey = policy_ref.config
  local policykey = policy_ref.key

  if configkey == "" and policykey == "" then
    return nil
  end

  local configTable = Policy.CACHE[configkey]
  if not configTable then
    configTable = {}
    Policy.CACHE[configkey] = configTable
  end

  local entry = configTable[policykey]
  if not entry then
    local raw = redis.call("HGET", configkey, policykey)
    if not raw then
      return nil -- will result in "ERR_UNKNOWN_POLICY"
    end
    entry = {
      policy_ref = policy_ref,
      pb = PB.unmarshal(PolicyPB, raw),
    }
    configTable[policykey] = entry
  end
  return entry
end

return Policy
end)(PB, Utils)
  local Account = (function(...)

local PB, Utils, Policy = ...
assert(PB)
assert(Utils)
assert(Policy)

local Account = {
  CACHE = {},
}

local math_floor = math.floor
local math_min = math.min
local math_max = math.max

local NOW = Utils.NOW
local redis_call = redis.call

local AccountPB = "go.chromium.org.luci.server.quota.quotapb.Account"

function Account:get(key)
  assert(key, "Account:get called with <nil>")
  assert(key ~= "", "Account:get called with ''")
  local entry = Account.CACHE[key]
  if not entry then
    local raw = redis_call("GET", key)
    entry = {
      key = key,
    }
    if raw then
      local ok, pb = pcall(PB.unmarshal, AccountPB, raw)
      if ok then
        entry.pb = pb
        entry.account_status = "ALREADY_EXISTS"
      else
        entry.account_status = "RECREATED"
      end
    else
      entry.account_status = "CREATED"
    end
    if not entry.pb then
      entry.pb = PB.new(AccountPB, {
        updated_ts = NOW,
      })
    end
    setmetatable(entry, self)
    self.__index = self
    self.CACHE[key] = entry

    if entry.account_status == "ALREADY_EXISTS" then
      entry:applyRefill()
      entry.pb.updated_ts = NOW
    end
  end
  return entry
end

local RELATIVE_TO_CURRENT_BALANCE = "CURRENT_BALANCE"
local RELATIVE_TO_DEFAULT = "DEFAULT"
local RELATIVE_TO_LIMIT = "LIMIT"
local RELATIVE_TO_ZERO = "ZERO"

local isInfiniteRefill = function(policy)
  if not policy then
    return false
  end

  if not policy.refill then
    return false
  end

  if policy.refill.interval ~= 0 then
    return false
  end

  if policy.refill.units <= 0 then
    error("invalid zero-interval refill policy")
  end

  return true
end

local opts = PB.E["go.chromium.org.luci.server.quota.quotapb.Op.Options"]
local IGNORE_POLICY_BOUNDS = opts.IGNORE_POLICY_BOUNDS
local DO_NOT_CAP_PROPOSED = opts.DO_NOT_CAP_PROPOSED
local WITH_POLICY_LIMIT_DELTA = opts.WITH_POLICY_LIMIT_DELTA

local computeProposed = function(op, new_account, current, policy)
  local relative_to = op.relative_to
  if relative_to == RELATIVE_TO_ZERO then
    return op.delta
  end

  if policy == nil and new_account then
    return 0, "ERR_POLICY_REQUIRED"
  end

  if relative_to == RELATIVE_TO_CURRENT_BALANCE then
    return current + op.delta
  end

  if policy == nil then
    return 0, "ERR_POLICY_REQUIRED"
  end

  if relative_to == RELATIVE_TO_LIMIT then
    return policy.limit + op.delta
  end

  if relative_to == RELATIVE_TO_DEFAULT then
    return policy.default + op.delta
  end

  error("invalid `relative_to` value: "..op.relative_to)
end

function Account:applyOp(op, result)
  local options = op.options
  local ignore_bounds = (options/IGNORE_POLICY_BOUNDS)%2 >= 1
  local no_cap = (options/DO_NOT_CAP_PROPOSED)%2 >= 1
  local with_policy_limit_delta = (options/WITH_POLICY_LIMIT_DELTA)%2 >= 1

  if op.policy_ref ~= nil then
    local policy_raw = Policy.get(op.policy_ref)
    if not policy_raw then
      result.status = "ERR_UNKNOWN_POLICY"
      return
    end
    self:setPolicy(policy_raw, result, with_policy_limit_delta)
  end
  local pb = self.pb
  local policy = pb.policy

  if ignore_bounds and no_cap then
    error("IGNORE_POLICY_BOUNDS and DO_NOT_CAP_PROPOSED both set")
  end

  local current = pb.balance

  local proposed, status = computeProposed(op, self.account_status ~= "ALREADY_EXISTS", current, policy)
  if status ~= nil then
    result.status = status
    return
  end

  local limit = nil
  if policy then
    limit = policy.limit
  end
  if not (no_cap or ignore_bounds) then
    proposed = math_min(proposed, limit)
  end

  if ignore_bounds then
    pb.balance = proposed
  elseif policy == nil then
    result.status = "ERR_POLICY_REQUIRED"
    return
  elseif proposed >= 0 and proposed <= limit then
    if isInfiniteRefill(policy) then
      pb.balance = limit
    else
      pb.balance = proposed
    end
  else
    if proposed < 0 and proposed < current then
      result.status = "ERR_UNDERFLOW"
      return
    end
    if proposed > limit and proposed > current then
      result.status = "ERR_OVERFLOW"
      return
    end
    pb.balance = proposed
  end

  self.account_status = "ALREADY_EXISTS"
end

function Account:applyRefill()
  local policy = self.pb.policy
  if policy == nil then
    return
  end
  local limit = policy.limit

  local refill = policy.refill
  if refill == nil then
    return
  end

  local curBalance = self.pb.balance

  if isInfiniteRefill(policy) then
    self.pb.balance = math_max(curBalance, limit)
    return
  end

  local units = refill.units
  local interval = refill.interval

  local offset = refill.offset
  local updated_unix = self.pb.updated_ts.seconds - offset
  local now_unix = NOW.seconds - offset


  local first_event_unix = (updated_unix - (updated_unix % interval)) + interval
  local last_event_unix = (now_unix - (now_unix % interval))

  if last_event_unix < first_event_unix then
    return
  end

  local num_events = ((last_event_unix - first_event_unix) / interval) + 1
  assert(math_floor(num_events) == num_events)

  local delta = num_events * units
  if delta > 0 and curBalance < limit then
    self.pb.balance = math_min(curBalance+delta, limit)
  elseif delta < 0 and curBalance > 0 then
    self.pb.balance = math_max(curBalance+delta, 0)
  end
end

local policyRefEq = function(a, b)
  if a == nil and b == nil then
    return true
  end
  if a == nil and b ~= nil then
    return false
  end
  if a ~= nil and b == nil then
    return false
  end
  return a.config == b.config and a.key == b.key
end

function Account:setPolicy(policy, result, with_policy_limit_delta)
  if policy then
    if not policyRefEq(self.pb.policy_ref, policy.policy_ref) then
      if with_policy_limit_delta and self.pb.policy_ref ~= nil then
        local delta = policy.pb.limit - self.pb.policy.limit
        self.pb.balance = self.pb.balance + delta

        result.previous_balance_adjusted = self.pb.balance
      end

      self.pb.policy = policy.pb
      self.pb.policy_ref = policy.policy_ref
      self.pb.policy_change_ts = NOW
    end

    if self.account_status ~= "ALREADY_EXISTS" then
      self.pb.balance = policy.pb.default
    end

    self:applyRefill() -- in case this policy is infinite, this will set the balance to limit.
  else
    self.pb.policy = nil
    self.pb.policy_ref = nil
    self.pb.policy_change_ts = NOW
  end
end

function Account:write()
  local lifetime_ms = nil
  if self.pb.policy then
    lifetime_ms = Utils.Millis(self.pb.policy.lifetime)
  end

  local raw = PB.marshal(self.pb)
  if lifetime_ms then
    redis_call('SET', self.key, raw, 'PX', lifetime_ms)
  else
    redis_call('SET', self.key, raw)
  end
end

function Account.ApplyOps(oplist)
  local ret = PB.new("go.chromium.org.luci.server.quota.quotapb.ApplyOpsResponse")
  local allOK = true
  for i, op in ipairs(oplist) do
    local account = Account:get(op.account_ref)

    local result = PB.new("go.chromium.org.luci.server.quota.quotapb.OpResult", {
      status = "SUCCESS",  -- by default; applyOp can overwrite this.
      account_status = account.account_status,
      previous_balance = account.pb.balance,
      previous_balance_adjusted = account.pb.balance,
    })
    ret.results[i] = result

    local ok, err = pcall(account.applyOp, account, op, result)
    if not ok then
      result.status = "ERR_UNKNOWN"
      result.status_msg = tostring(err)
    end

    if result.status == "SUCCESS" then
      result.new_balance = account.pb.balance
    else
      allOK = false
    end
  end

  if allOK then
    for key, account in pairs(Account.CACHE) do
      account:write()
    end
    ret.originally_set = NOW
  end

  return ret, allOK
end

return Account
end)(PB, Utils, Policy)
  return Account.ApplyOps(req.ops)
end)
