Start repo, claude & kimi still vibing tho

This commit is contained in:
ra
2026-02-14 17:04:21 -07:00
commit f5b8aeb39d
54 changed files with 9466 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
defmodule Odinsea.Util.BitTools do
@moduledoc """
Utility functions for bit and byte manipulation.
Provides helper functions for working with binary data, similar to Java's BitTools.
Ported from: src/tools/BitTools.java
"""
use Bitwise
@doc """
Reads a 16-bit short integer (little-endian) from a byte array at the given index.
## Parameters
- array: Binary array
- index: Starting position (0-based)
## Returns
- 16-bit integer value (0-65535)
"""
@spec get_short(binary(), non_neg_integer()) :: non_neg_integer()
def get_short(array, index) when is_binary(array) do
<<_skip::binary-size(index), value::little-unsigned-16, _rest::binary>> = array
value
end
@doc """
Reads a string from a byte array at the given index with specified length.
## Parameters
- array: Binary array
- index: Starting position
- length: Number of bytes to read
## Returns
- String extracted from the byte array
"""
@spec get_string(binary(), non_neg_integer(), non_neg_integer()) :: String.t()
def get_string(array, index, length) when is_binary(array) do
<<_skip::binary-size(index), string_data::binary-size(length), _rest::binary>> = array
to_string(string_data)
end
@doc """
Reads a MapleStory-convention string from a byte array.
Format: 2-byte little-endian length prefix + string data
## Parameters
- array: Binary array
- index: Starting position
## Returns
- String extracted from the byte array
"""
@spec get_maple_string(binary(), non_neg_integer()) :: String.t()
def get_maple_string(array, index) when is_binary(array) do
length = get_short(array, index)
get_string(array, index + 2, length)
end
@doc """
Rotates bits of a byte left by count positions.
## Parameters
- byte_val: Byte value (0-255)
- count: Number of positions to rotate
## Returns
- Rotated byte value
"""
@spec roll_left(byte(), non_neg_integer()) :: byte()
def roll_left(byte_val, count) when is_integer(byte_val) and byte_val >= 0 and byte_val <= 255 do
tmp = byte_val &&& 0xFF
rotated = tmp <<< rem(count, 8)
((rotated &&& 0xFF) ||| (rotated >>> 8)) &&& 0xFF
end
@doc """
Rotates bits of a byte right by count positions.
## Parameters
- byte_val: Byte value (0-255)
- count: Number of positions to rotate
## Returns
- Rotated byte value
"""
@spec roll_right(byte(), non_neg_integer()) :: byte()
def roll_right(byte_val, count) when is_integer(byte_val) and byte_val >= 0 and byte_val <= 255 do
tmp = byte_val &&& 0xFF
rotated = (tmp <<< 8) >>> rem(count, 8)
((rotated &&& 0xFF) ||| (rotated >>> 8)) &&& 0xFF
end
@doc """
Repeats the first `count` bytes of `input` `mul` times.
## Parameters
- input: Binary input
- count: Number of bytes to repeat from the input
- mul: Number of times to repeat
## Returns
- Binary with repeated bytes
"""
@spec multiply_bytes(binary(), non_neg_integer(), non_neg_integer()) :: binary()
def multiply_bytes(input, count, mul) when is_binary(input) do
# Take first `count` bytes
chunk = binary_part(input, 0, min(count, byte_size(input)))
# Repeat `mul` times
1..mul
|> Enum.map(fn _ -> chunk end)
|> IO.iodata_to_binary()
end
@doc """
Converts a double-precision float to a short by extracting high bits.
## Parameters
- d: Double-precision float
## Returns
- 16-bit integer extracted from the high bits
"""
@spec double_to_short_bits(float()) :: integer()
def double_to_short_bits(d) when is_float(d) do
# Convert double to 64-bit integer representation
<<long_bits::signed-64>> = <<d::float>>
# Extract high 16 bits (shift right by 48)
(long_bits >>> 48) &&& 0xFFFF
end
end