defmodule WaParser.LEB128 do def encode_unsigned(0) do <<0x00>> end def encode_unsigned(int) when int > 0 do int |> to_bitstring |> seven_bits_encoding end def decode_unsigned(binary) do decode_unsigned(binary, <<>>) end defp decode_unsigned(<<0::1, byte::7>>, acc) do bitstring = <<byte::7, acc::bitstring>> size = :erlang.bit_size(bitstring) <<int::unsigned-integer-size(size)>> = bitstring int end defp decode_unsigned(<<1::1, byte::7, rest::bytes>>, acc) do decode_unsigned(rest, <<byte::7, acc::bitstring>>) end def encode_signed(0) do <<0x00>> end def encode_signed(int) do int |> to_bitstring |> seven_bits_encoding end defp to_bitstring(int) do abs = if int < 0 do int * -1 else int end bytes_needed = ceil(:math.log2(abs)) bytes_needed = ceil(bytes_needed / 7) * 7 <<int::size(bytes_needed)>> end defp seven_bits_encoding(binary) do seven_bits_encoding(binary, []) end defp seven_bits_encoding(<<>>, acc) do acc |> Enum.into(<<>>) end defp seven_bits_encoding(<<sb::size(7), rest::bitstring>>, acc) do byte = case acc do [] -> <<sb>> _ -> <<1::1, sb::7>> end seven_bits_encoding(rest, [byte | acc]) end def decode_signed(binary) do decode_signed(binary, <<>>) end defp decode_signed(<<0::1, byte::7>>, acc) do bitstring = <<byte::7, acc::bitstring>> size = :erlang.bit_size(bitstring) <<int::signed-integer-size(size)>> = bitstring int end defp decode_signed(<<1::1, byte::7, rest::bytes>>, acc) do decode_signed(rest, <<byte::7, acc::bitstring>>) end end