local bit_converter = { } local MAX_UINT16 = 65535 local MIN_UINT16 = 0 local MAX_UINT32 = 4294967295 local MIN_UINT32 = 0 local MAX_INT16 = 32767 local MIN_INT16 = -32768 local MAX_INT32 = 2147483647 local MIN_INT32 = -2147483648 local MAX_INT64 = 9223372036854775807 local MIN_INT64 = -9223372036854775808 local function maskHighBytes(num) return bit.band(num, 0xFF) end local function reverse(tbl) for i=1, math.floor(#tbl / 2) do local tmp = tbl[i] tbl[i] = tbl[#tbl - i + 1] tbl[#tbl - i + 1] = tmp end return tbl end local orders = { "LE", "BE" } local fromLEConvertors = { LE = function(bytes) return bytes end, BE = function(bytes) return reverse(bytes) end } local toLEConvertors = { LE = function(bytes) return bytes end, BE = function(bytes) return reverse(bytes) end } bit_converter.default_order = "BE" local function fromLE(bytes, orderTo) if orderTo then bit_converter.validate_order(orderTo) return fromLEConvertors[orderTo](bytes) else return bytes end end local function toLE(bytes, orderFrom) if orderFrom then bit_converter.validate_order(orderFrom) return toLEConvertors[orderFrom](bytes) else return bytes end end function bit_converter.validate_order(order) if not bit_converter.is_valid_order(order) then error("invalid order: "..order) end end function bit_converter.is_valid_order(order) return table.has(orders, order) end function bit_converter.string_to_bytes(str) local bytes = { } local len = string.len(str) local lenBytes = bit_converter.uint16_to_bytes(len) for i = 1, #lenBytes do bytes[i] = lenBytes[i] end for i = 1, len do bytes[#bytes + 1] = string.byte(string.sub(str, i, i)) end return bytes end function bit_converter.bool_to_byte(bool) return bool and 1 or 0 end -- Credits to Iryont local function floatOrDoubleToBytes(val, opt) local sign = 0 if val < 0 then sign = 1 val = -val end local mantissa, exponent = math.frexp(val) if val == 0 then mantissa = 0 exponent = 0 else mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, (opt == 'd') and 53 or 24) exponent = exponent + ((opt == 'd') and 1022 or 126) end local bytes = {} if opt == 'd' then val = mantissa for i = 1, 6 do bytes[#bytes + 1] = math.floor(val) % (2 ^ 8) val = math.floor(val / (2 ^ 8)) end else bytes[#bytes + 1] = math.floor(mantissa) % (2 ^ 8) val = math.floor(mantissa / (2 ^ 8)) bytes[#bytes + 1] = math.floor(val) % (2 ^ 8) val = math.floor(val / (2 ^ 8)) end bytes[#bytes + 1] = math.floor(exponent * ((opt == 'd') and 16 or 128) + val) % (2 ^ 8) val = math.floor((exponent * ((opt == 'd') and 16 or 128) + val) / (2 ^ 8)) bytes[#bytes + 1] = math.floor(sign * 128 + val) % (2 ^ 8) val = math.floor((sign * 128 + val) / (2 ^ 8)) return bytes end local function bytesToFloatOrDouble(bytes, opt) local n = (opt == 'd') and 8 or 4 local sign = 1 local mantissa = bytes[n - 1] % ((opt == 'd') and 16 or 128) for i = n - 2, 1, -1 do mantissa = mantissa * (2 ^ 8) + bytes[i] end if bytes[n] > 127 then sign = -1 end local exponent = (bytes[n] % 128) * ((opt == 'd') and 16 or 2) + math.floor(bytes[n - 1] / ((opt == 'd') and 16 or 128)) if exponent == 0 then return 0.0 else mantissa = (math.ldexp(mantissa, (opt == 'd') and -52 or -23) + 1) * sign return math.ldexp(mantissa, exponent - ((opt == 'd') and 1023 or 127)) end end -- function bit_converter.float32_to_bytes(float, order) return fromLE(floatOrDoubleToBytes(float, 'f'), order) end function bit_converter.float64_to_bytes(float, order) return fromLE(floatOrDoubleToBytes(float, 'd'), order) end function bit_converter.single_to_bytes(float, order) on_deprecated_call("bit_converter.float_to_bytes", "bit_converter.float32_to_bytes") return bit_converter.float32_to_bytes(bytes, order) end function bit_converter.double_to_bytes(double, order) on_deprecated_call("bit_converter.double_to_bytes", "bit_converter.float64_to_bytes") return bit_converter.float64_to_bytes(bytes, order) end local function uint32ToBytes(int, order) return fromLE({ maskHighBytes(int), maskHighBytes(bit.rshift(int, 8)), maskHighBytes(bit.rshift(int, 16)), maskHighBytes(bit.rshift(int, 24)) }, order) end local function uint16ToBytes(int, order) return fromLE({ maskHighBytes(int), maskHighBytes(bit.rshift(int, 8)) }, order) end function bit_converter.uint32_to_bytes(int, order) if int > MAX_UINT32 or int < MIN_UINT32 then error("invalid uint32") end return uint32ToBytes(int, order) end function bit_converter.uint16_to_bytes(int, order) if int > MAX_UINT16 or int < MIN_UINT16 then error("invalid uint16") end return uint16ToBytes(int, order) end function bit_converter.int64_to_bytes(int, order) if int > MAX_INT64 or int < MIN_INT64 then error("invalid int64") end return fromLE({ maskHighBytes(int), maskHighBytes(bit.rshift(int, 8)), maskHighBytes(bit.rshift(int, 16)), maskHighBytes(bit.rshift(int, 24)), maskHighBytes(bit.rshift(int, 32)), maskHighBytes(bit.rshift(int, 40)), maskHighBytes(bit.rshift(int, 48)), maskHighBytes(bit.rshift(int, 56)) }, order) end function bit_converter.int32_to_bytes(int, order) on_deprecated_call("bit_converter.int32_to_bytes", "bit_converter.sint32_to_bytes") if int > MAX_INT32 or int < MIN_INT32 then error("invalid int32") end return uint32ToBytes(int + MAX_INT32, order) end function bit_converter.int16_to_bytes(int, order) on_deprecated_call("bit_converter.int32_to_bytes", "bit_converter.sint16_to_bytes") if int > MAX_INT16 or int < MIN_INT16 then error("invalid int16") end return uint16ToBytes(int + MAX_INT16, order) end function bit_converter.sint32_to_bytes(int, order) if int > MAX_INT32 or int < MIN_INT32 then error("invalid sint32") end return uint32ToBytes(int + MAX_UINT32 + 1, order) end function bit_converter.sint16_to_bytes(int, order) if int > MAX_INT16 or int < MIN_INT16 then error("invalid sint16") end return uint16ToBytes(int + MAX_UINT16 + 1, order) end function bit_converter.bytes_to_float32(bytes, order) return bytesToFloatOrDouble(toLE(bytes, order), 'f') end function bit_converter.bytes_to_float64(bytes, order) return bytesToFloatOrDouble(toLE(bytes, order), 'd') end function bit_converter.bytes_to_single(bytes, order) on_deprecated_call("bit_converter.bytes_to_single", "bit_converter.bytes_to_float32") return bit_converter.bytes_to_float32(bytes, order) end function bit_converter.bytes_to_double(bytes, order) on_deprecated_call("bit_converter.bytes_to_double", "bit_converter.bytes_to_float64") return bit_converter.bytes_to_float64(bytes, order) end function bit_converter.bytes_to_string(bytes, order) local len = bit_converter.bytes_to_uint16({ bytes[1], bytes[2] }) local str = "" for i = 1, len do str = str..string.char(bytes[i + 2]) end return str end function bit_converter.byte_to_bool(byte) return byte ~= 0 end function bit_converter.bytes_to_uint32(bytes, order) if #bytes < 4 then error("eof") end bytes = toLE(bytes, order) return bit.bor( bit.bor( bit.bor( bytes[1], bit.lshift(bytes[2], 8)), bit.lshift(bytes[3], 16)), bit.lshift(bytes[4], 24)) end function bit_converter.bytes_to_uint16(bytes, order) if #bytes < 2 then error("eof") end bytes = toLE(bytes, order) return bit.bor( bit.lshift(bytes[2], 8), bytes[1], 0) end function bit_converter.bytes_to_int64(bytes, order) if #bytes < 8 then error("eof") end bytes = toLE(bytes, order) return bit.bor( bit.bor( bit.bor( bit.bor( bit.bor( bit.bor( bit.bor( bit.lshift(bytes[8], 56), bit.lshift(bytes[7], 48)), bit.lshift(bytes[6], 40)), bit.lshift(bytes[5], 32)), bit.lshift(bytes[4], 24)), bit.lshift(bit.band(bytes[3], 0xFF), 16)), bit.lshift(bit.band(bytes[2], 0xFF), 8)),bit.band(bytes[1], 0xFF)) end function bit_converter.bytes_to_int32(bytes, order) on_deprecated_call("bit_converter.bytes_to_int32", "bit_converter.bytes_to_sint32") return bit_converter.bytes_to_uint32(bytes, order) - MAX_INT32 end function bit_converter.bytes_to_int16(bytes, order) on_deprecated_call("bit_converter.bytes_to_int16", "bit_converter.bytes_to_sint16") return bit_converter.bytes_to_uint16(bytes, order) - MAX_INT16 end function bit_converter.bytes_to_sint32(bytes, order) local num = bit_converter.bytes_to_uint32(bytes, order) return MIN_INT32 * (bit.band(MAX_INT32 + 1, num) ~= 0 and 1 or 0) + bit.band(MAX_INT32, num) end function bit_converter.bytes_to_sint16(bytes, order) local num = bit_converter.bytes_to_uint16(bytes, order) return MIN_INT16 * (bit.band(MAX_INT16 + 1, num) ~= 0 and 1 or 0) + bit.band(MAX_INT16, num) end return bit_converter