Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- defmodule MHolder do
- defmacro packet {name, fields_defs} do
- fields_dec = Enum.map fields_defs, fn({:{}, _, [:case, var_name, val_map]}) ->
- var = Macro.var(var_name, __MODULE__)
- new_var = Macro.var(String.to_atom("#{var_name}_decoded"), __MODULE__)
- rest = Macro.var(:rest, __MODULE__)
- cases = Enum.map val_map, fn({val, struct_name})->
- val = if val == :_ do {:_, [], __MODULE__} else val end
- quote do unquote(val) -> decode(unquote(struct_name), unquote(rest)) end
- end
- quote do
- {:ok, unquote(new_var), unquote(rest)} = case unquote(var) do
- unquote(Enum.concat(cases))
- end
- end
- ({type, name}) ->
- var = Macro.var(name, __MODULE__)
- rest = Macro.var(:rest, __MODULE__)
- cond do
- type in [:sbyte, :byte, :int, :sint, :long, :sfloat, :float, :sshort, :short] -> #simple types
- dec_name = String.to_atom("decode_#{type}")
- quote do
- {:ok, unquote(var), unquote(rest)} = unquote(dec_name)(unquote(rest))
- end
- true -> #custom types
- quote do
- {:ok, unquote(var), unquote(rest)} = decode(unquote(type), unquote(rest))
- end
- end
- end
- IO.puts "building results"
- results = Enum.map fields_defs, fn({:{}, _, [:case, var_name, val_map]}) ->
- new_var_name = String.to_atom("#{var_name}_decoded")
- new_var = Macro.var(new_var_name, __MODULE__)
- {new_var_name, new_var}
- ({_, name}) ->
- var = Macro.var(name, __MODULE__)
- {name, var}
- end
- composed_result = {:%{}, [], results}
- # fields_enc = Enum.map fields_defs, fn({type, name}) ->
- # var = Macro.var(name, __MODULE__)
- # rest = Macro.var(:rest, __MODULE__)
- # data = Macro.var(:data, __MODULE__)
- # cond do
- # type in [:sbyte, :byte, :int, :sint, :long, :sfloat, :float, :sshort, :short] -> #simple types
- # enc_name = String.to_atom("encode_#{type}")
- # quote do
- # unquote(rest) = unquote(rest) <> unquote(enc_name)(unquote(data).unquote(var))
- # end
- # true ->
- # quote do
- # nil
- # end
- # end
- # end
- quote do
- def decode(unquote(name), rest) do
- unquote_splicing(fields_dec)
- {:ok, unquote(composed_result), rest}
- end
- # def encode(unquote(name), data) do
- # rest = ""
- # unquote_splicing(fields_enc)
- # rest
- # end
- end
- end
- end
- defmodule K do
- require MHolder
- packets =
- [
- {:ks_request_version,
- [
- {:int, :unk_int1},
- {:int, :client_seq},
- {:int, :server_seq},
- {:int, :crypter},
- {:byte, :unk_byte1}
- ]
- }
- ]
- MHolder.packet {:ks_request_version,
- [
- {:int, :unk_int1},
- {:int, :client_seq},
- {:int, :server_seq},
- {:int, :crypter},
- {:byte, :unk_byte1},
- {:case, :unk_byte1,
- [
- {1, :struct1},
- {:_, :struct2}
- ]
- }
- ]
- }
- MHolder.packet {:struct1, [{:byte, :field0}]}
- MHolder.packet {:struct2, [{:byte, :field0}]}
- def decode_byte(<<b::8, rest::binary>>) do
- {:ok, b, rest}
- end
- def decode_int(<<b::32-little, rest::binary>>) do
- {:ok, b, rest}
- end
- def decode(x,y) do
- IO.inspect {:unknown_decode,x,y}
- :error
- end
- def encode_byte(val) do
- <<val::8>>
- end
- def encode_int(val) do
- <<val::32-little>>
- end
- end
- {:ok, s, rest} = K.decode(:ks_request_version, "somethingebcdfgh"<> <<9>><>"jklaaaaaaaaaaaaaaa")
- K.encode :ks_request_version, s
Add Comment
Please, Sign In to add comment