Skip to content

feat: lossless 64-bit integer mode — return cdata int64_t to LuaJIT #22

@membphis

Description

@membphis

Problem

LuaJIT's number type is a double (double). Integers larger than 2⁵³ lose precision when returned as a Lua number. JSON payloads with 64-bit IDs (e.g. Snowflake IDs, database row IDs) are silently truncated today.

Proposal

Add a qjd_get_int64 FFI function that returns the raw i64 value as a LuaJIT cdata int64_t, preserving full precision. The LuaJIT wrapper (lua/quickdecode.lua) should expose this as doc:get_int64(path) / cursor:get_int64(path).

Signed 64-bit covers all practical JSON integer IDs. Unsigned (uint64_t) can be added later if needed.

API sketch

// include/lua_quick_decode.h
int64_t qjd_get_int64(const qjd_doc *doc, const char *path, size_t path_len,
                       qjd_err *err_out);
-- lua/quickdecode.lua
function Doc:get_int64(path)
  local err = ffi.new("qjd_err[1]")
  local v   = lib.qjd_get_int64(self._doc, path, #path, err)
  if err[0] ~= QJD_OK then error(...) end
  return v   -- cdata int64_t; arithmetic and comparisons work natively in LuaJIT
end

Notes

  • Must parse as integer without going through f64; parse i64 directly in src/decode/number.rs.
  • Return QJD_TYPE_MISMATCH if the value is a float, bool, string, etc.
  • Return QJD_PARSE_ERROR if the integer overflows i64.
  • Add Rust unit tests covering i64::MAX, -i64::MIN, and overflow cases.
  • Add a Lua busted test asserting that a known > 2⁵³ integer round-trips losslessly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions