@ -0,0 +1,9 @@ | |||
genProto | |||
===== | |||
An OTP library | |||
Build | |||
----- | |||
$ rebar3 compile |
@ -0,0 +1,9 @@ | |||
{application,genProto, | |||
[{description,"An OTP library"}, | |||
{vsn,"0.1.0"}, | |||
{registered,[]}, | |||
{applications,[kernel,stdlib]}, | |||
{env,[]}, | |||
{modules,[protoCode,protoField,protoGen,protoParse]}, | |||
{licenses,["Apache 2.0"]}, | |||
{links,[]}]}. |
@ -0,0 +1,24 @@ | |||
%% 测试协议 注释可以用 % 也可以用 // | |||
test { | |||
string aa; | |||
} | |||
// phoneNumber info | |||
phoneNumber{ | |||
test number; //电话号码 | |||
int32 type; //类型 | |||
} | |||
%% person info | |||
person{ | |||
string name; %% 名字 | |||
int32 id; %% id | |||
string email; //邮箱 | |||
list[phoneNumber] phone; // list of phoneNumber | |||
} | |||
%% addressBook info | |||
addressBook { | |||
list[person] person; | |||
list[person] other; | |||
} |
@ -0,0 +1,2 @@ | |||
{erl_opts, [debug_info]}. | |||
{deps, []}. |
@ -0,0 +1,13 @@ | |||
{application, genProto, | |||
[{description, "An OTP library"}, | |||
{vsn, "0.1.0"}, | |||
{registered, []}, | |||
{applications, | |||
[kernel, | |||
stdlib | |||
]}, | |||
{env, []}, | |||
{modules, []}, | |||
{licenses, ["Apache 2.0"]}, | |||
{links, []} | |||
]}. |
@ -0,0 +1,247 @@ | |||
-module(protoCode). | |||
-compile(nowarn_unused_function). | |||
-export([encode/1, decode/1, encodeRec/1, decodeRec/2]). | |||
-define(bool(V), (case V of true -> <<1:8>>; _ -> <<0:8>> end)). | |||
-define(int8(V), <<V:8>>). | |||
-define(uint8(V), <<V:8>>). | |||
-define(int16(V), <<V:16/big>>). | |||
-define(uint16(V), <<V:16/big>>). | |||
-define(int32(V), <<V:32/big>>). | |||
-define(uint32(V), <<V:32/big>>). | |||
-define(int64(V), <<V:64/big>>). | |||
-define(uint64(V), <<V:64/big>>). | |||
-define(float(V), <<V:32/big-float>>). | |||
-define(double(V), <<V:64/big-float>>). | |||
-define(string(V), (string(V))). | |||
-define(record(V), (case V of undefined -> [<<0:8>>]; V -> [<<1:8>>, encodeRec(V)] end)). | |||
-define(list_bool(List), [<<(length(List)):16/big>>, [?bool(V) || V <- List]]). | |||
-define(list_int8(List), [<<(length(List)):16/big>>, [?int8(V) || V <- List]]). | |||
-define(list_uint8(List), [<<(length(List)):16/big>>, [?uint8(V) || V <- List]]). | |||
-define(list_int16(List), [<<(length(List)):16/big>>, [?int16(V) || V <- List]]). | |||
-define(list_uint16(List), [<<(length(List)):16/big>>, [?uint16(V) || V <- List]]). | |||
-define(list_int32(List), [<<(length(List)):16/big>>, [?int32(V) || V <- List]]). | |||
-define(list_uint32(List), [<<(length(List)):16/big>>, [?uint32(V) || V <- List]]). | |||
-define(list_int64(List), [<<(length(List)):16/big>>, [?int64(V) || V <- List]]). | |||
-define(list_uint64(List), [<<(length(List)):16/big>>, [?uint64(V) || V <- List]]). | |||
-define(list_float(List), [<<(length(List)):16/big>>, [?float(V) || V <- List]]). | |||
-define(list_double(List), [<<(length(List)):16/big>>, [?double(V) || V <- List]]). | |||
-define(list_string(List), [<<(length(List)):16/big>>, [string(V) || V <- List]]). | |||
-define(list_record(List), [<<(length(List)):16/big>>, [encodeRec(V) || V <- List]]). | |||
string(Str) when is_binary(Str) -> | |||
[<<(byte_size(Str)):16/big>>, Str]; | |||
string(Str) -> | |||
Str2 = unicode:characters_to_binary(Str, utf8), | |||
[<<(byte_size(Str2)):16/big>>, Str2]. | |||
encode(Record) -> | |||
MsgBin = encodeRec(Record), | |||
MsgId = getMsgId(element(1, Record)), | |||
[<<MsgId:16/big>>, MsgBin]. | |||
decode(Bin) -> | |||
<<MsgId:16/big, MsgBin/binary>> = Bin, | |||
SchList = getMsgSchema(MsgId), | |||
{<<>>, ResultList} = decodeField(SchList, MsgBin, [getMsgType(MsgId)]), | |||
list_to_tuple(ResultList). | |||
decodeRec(RecordName, Bin) -> | |||
SchList = getMsgSchema(RecordName), | |||
{LeftBin, Result} = decodeField(SchList, Bin, [RecordName]), | |||
{LeftBin, list_to_tuple(Result)}. | |||
decodeField([], LeftBin, Result) -> | |||
{LeftBin, lists:reverse(Result)}; | |||
decodeField([Type | SchList], MsgBin, Result) -> | |||
case Type of | |||
int32 -> | |||
<<Int:32/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint32 -> | |||
<<Int:32/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
string -> | |||
<<Len:16/big, StrBin:Len/binary, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [StrBin | Result]); | |||
int16 -> | |||
<<Int:16/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint16 -> | |||
<<Int:16/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
int8 -> | |||
<<Int:8/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint8 -> | |||
<<Int:8/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
int64 -> | |||
<<Int:64/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint64 -> | |||
<<Int:64/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
bool -> | |||
<<Bool:8/big-unsigned, LeftBin/binary>> = MsgBin, | |||
case Bool =:= 1 of | |||
true -> | |||
decodeField(SchList, LeftBin, [true | Result]); | |||
_ -> | |||
decodeField(SchList, LeftBin, [false | Result]) | |||
end; | |||
falat -> | |||
<<Float:32/big-float, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Float | Result]); | |||
double -> | |||
<<Float:64/big-float, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Float | Result]); | |||
{list, int32} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt32List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint32} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint32List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, int16} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt16List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint16} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint16List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, int8} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt8List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint8} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint8List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, string} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deStringList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, int64} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt64List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint64} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint64List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, bool} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deBoolList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, flat} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deFloatList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, double} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deDoubleList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, RecordName} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deRecordList(Len, RecordName, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
RecordName -> | |||
<<IsUndef:8, LeftBin/binary>> = MsgBin, | |||
case IsUndef of | |||
0 -> | |||
decodeField(SchList, LeftBin, [undefined | Result]); | |||
_ -> | |||
SubSchList = getMsgSchema(RecordName), | |||
{SubLeftBin, SubResultList} = decodeField(SubSchList, LeftBin, [RecordName]), | |||
decodeField(SchList, SubLeftBin, [list_to_tuple(SubResultList) | Result]) | |||
end | |||
end. | |||
deBoolList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deBoolList(N, <<Bool:8, LeftBin/binary>>, RetList) -> | |||
case Bool =:= 1 of | |||
true -> | |||
deBoolList(N - 1, LeftBin, [true | RetList]); | |||
_ -> | |||
deBoolList(N - 1, LeftBin, [false | RetList]) | |||
end. | |||
deInt8List(0, MsgBin, RetList) -> | |||
{MsgBin, RetList}; | |||
deInt8List(N, <<Int:8/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt8List(N - 1, LeftBin, [Int | RetList]). | |||
deUint8List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint8List(N, <<Int:8/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint8List(N - 1, LeftBin, [Int | RetList]). | |||
deInt16List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deInt16List(N, <<Int:16/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt16List(N - 1, LeftBin, [Int | RetList]). | |||
deUint16List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint16List(N, <<Int:16/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint16List(N - 1, LeftBin, [Int | RetList]). | |||
deInt32List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deInt32List(N, <<Int:32/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt32List(N - 1, LeftBin, [Int | RetList]). | |||
deUint32List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint32List(N, <<Int:32/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint32List(N - 1, LeftBin, [Int | RetList]). | |||
deInt64List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deInt64List(N, <<Int:64/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt64List(N - 1, LeftBin, [Int | RetList]). | |||
deUint64List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint64List(N, <<Int:64/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint64List(N - 1, LeftBin, [Int | RetList]). | |||
deFloatList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deFloatList(N, <<Float:32/big-float, LeftBin/binary>>, RetList) -> | |||
deFloatList(N - 1, LeftBin, [Float | RetList]). | |||
deDoubleList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deDoubleList(N, <<Float:64/big-float, LeftBin/binary>>, RetList) -> | |||
deDoubleList(N - 1, LeftBin, [Float | RetList]). | |||
deStringList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deStringList(N, <<Len:16/big, StrBin:Len/binary-unit:8, LeftBin/binary>>, RetList) -> | |||
deStringList(N - 1, LeftBin, [StrBin | RetList]). | |||
deRecordList(0, _RecordName, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deRecordList(N, RecordName, MsgBin, RetList) -> | |||
{LeftBin, Tuple} = decodeRec(RecordName, MsgBin), | |||
deRecordList(N - 1, RecordName, LeftBin, [Tuple | RetList]). | |||
%%%%%%%%%%%%%%%%%%%%%%%%%% 防止编译报错占位 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |||
encodeRec(_) -> | |||
ok. | |||
getMsgId(_) -> | |||
ok. | |||
getMsgType(_) -> | |||
ok. | |||
getMsgSchema(_) -> | |||
ok. | |||
@ -0,0 +1,91 @@ | |||
-module(protoField). | |||
-compile([export_all, nowarn_export_all]). | |||
-define(TypeList, [ | |||
"bool", | |||
"int8", | |||
"uint8", | |||
"int16", | |||
"uint16", | |||
"int32", | |||
"uint32", | |||
"int64", | |||
"uint64", | |||
"float", | |||
"double", | |||
"string" | |||
]). | |||
-define(TypeValue, [ | |||
{"bool", "false", "boolean"}, | |||
{"int8", "0", "int8()"}, | |||
{"uint8", "0", "uint8()"}, | |||
{"int16", "0", "int16()"}, | |||
{"uint16", "0", "uint16()"}, | |||
{"int32", "0", "int32()"}, | |||
{"uint32", "0", "uint32()"}, | |||
{"int64", "0", "int64()"}, | |||
{"uint64", "0", "uint64()"}, | |||
{"float", "0.0", "float()"}, | |||
{"double", "0.0", "flaot"}, | |||
{"string", "\"\"", "string()"} | |||
]). | |||
getSchemaInfo(TypeStr) -> | |||
case lists:member(TypeStr, ?TypeList) of | |||
true -> | |||
erlang:list_to_atom(TypeStr); | |||
_ -> | |||
case TypeStr of | |||
"list[" ++ LeftStr -> | |||
[SubTypeStr | _] = re:split(LeftStr, "\\]", [{return, list}]), | |||
{list, erlang:list_to_atom(SubTypeStr)}; | |||
_ -> | |||
erlang:list_to_atom(TypeStr) | |||
end | |||
end. | |||
builtRecStr({TypeStr, NameStr}) -> | |||
case lists:keyfind(TypeStr, 1, ?TypeValue) of | |||
{TypeStr, DefValueStr, DefTypeStr} -> | |||
NameStr ++ " = " ++ DefValueStr ++ " :: " ++ DefTypeStr ++ "\n\t"; | |||
_ -> | |||
case TypeStr of | |||
"list[" ++ LeftStr -> | |||
[SubTypeStr | _] = re:split(LeftStr, "\\]", [{return, list}]), | |||
case lists:keyfind(SubTypeStr, 1, ?TypeValue) of | |||
{SubTypeStr, _DefSubValueStr, DefSubTypeStr} -> | |||
NameStr ++ " = [] " ++ " :: [" ++ DefSubTypeStr ++ "]\n\t"; | |||
_ -> | |||
NameStr ++ " = [] " ++ " :: [#" ++ SubTypeStr ++ "{}]\n\t" | |||
end; | |||
_ -> | |||
NameStr ++ " = undefined " ++ " :: #" ++ TypeStr ++ "{}\n\t" | |||
end | |||
end. | |||
builtPackStr(TypeStr) -> | |||
case lists:member(TypeStr, ?TypeList) of | |||
true -> | |||
"?" ++ TypeStr ++ "("; | |||
_ -> | |||
case TypeStr of | |||
"list[" ++ LeftStr -> | |||
[SubTypeStr | _] = re:split(LeftStr, "\\]", [{return, list}]), | |||
SubStr = | |||
case lists:member(SubTypeStr, ?TypeList) of | |||
true -> | |||
SubTypeStr; | |||
_ -> | |||
"record" | |||
end, | |||
"?list_" ++ SubStr ++ "("; | |||
_ -> | |||
"?record(" | |||
end | |||
end. | |||
@ -0,0 +1,365 @@ | |||
-module(protoGen). | |||
-export([ | |||
convertFile/1 | |||
, convert/1 | |||
, convertDir/0 | |||
, convertDir/1 | |||
, convertDir/3 | |||
]). | |||
protoHrlHeader() -> | |||
"-opaque int8() :: -128..127. | |||
-opaque int16() :: -32768..32767. | |||
-opaque int32() :: -2147483648..2147483647. | |||
-opaque int64() :: -9223372036854775808..9223372036854775807. | |||
-opaque uint8() :: 0..255. | |||
-opaque uint16() :: 0..65536. | |||
-opaque uint32() :: 0..4294967295. | |||
-opaque uint64() :: 0..18446744073709551615. | |||
-opaque single() :: float(). | |||
-opaque double() :: float().\n\n". | |||
protoErlHeader() -> | |||
"-module(protoMsg).\n\n | |||
-export([encode/1, decode/1, encodeRec/1, decodeRec/2]). | |||
-define(bool(V), (case V of true -> <<1:8>>; _ -> <<0:8>> end)). | |||
-define(int8(V), <<V:8>>). | |||
-define(uint8(V), <<V:8>>). | |||
-define(int16(V), <<V:16/big>>). | |||
-define(uint16(V), <<V:16/big>>). | |||
-define(int32(V), <<V:32/big>>). | |||
-define(uint32(V), <<V:32/big>>). | |||
-define(int64(V), <<V:64/big>>). | |||
-define(uint64(V), <<V:64/big>>). | |||
-define(float(V), <<V:32/big-float>>). | |||
-define(double(V), <<V:64/big-float>>). | |||
-define(string(V), (string(V))). | |||
-define(record(V), (case V of undefined -> [<<0:8>>]; V -> [<<1:8>>, encodeRec(V)] end)). | |||
-define(list_bool(List), [<<(length(List)):16/big>>, [?bool(V) || V <- List]]). | |||
-define(list_int8(List), [<<(length(List)):16/big>>, [?int8(V) || V <- List]]). | |||
-define(list_uint8(List), [<<(length(List)):16/big>>, [?uint8(V) || V <- List]]). | |||
-define(list_int16(List), [<<(length(List)):16/big>>, [?int16(V) || V <- List]]). | |||
-define(list_uint16(List), [<<(length(List)):16/big>>, [?uint16(V) || V <- List]]). | |||
-define(list_int32(List), [<<(length(List)):16/big>>, [?int32(V) || V <- List]]). | |||
-define(list_uint32(List), [<<(length(List)):16/big>>, [?uint32(V) || V <- List]]). | |||
-define(list_int64(List), [<<(length(List)):16/big>>, [?int64(V) || V <- List]]). | |||
-define(list_uint64(List), [<<(length(List)):16/big>>, [?uint64(V) || V <- List]]). | |||
-define(list_float(List), [<<(length(List)):16/big>>, [?float(V) || V <- List]]). | |||
-define(list_double(List), [<<(length(List)):16/big>>, [?double(V) || V <- List]]). | |||
-define(list_string(List), [<<(length(List)):16/big>>, [string(V) || V <- List]]). | |||
-define(list_record(List), [<<(length(List)):16/big>>, [encodeRec(V) || V <- List]]). | |||
string(Str) when is_binary(Str) -> | |||
[<<(byte_size(Str)):16/big>>, Str]; | |||
string(Str) -> | |||
Str2 = unicode:characters_to_binary(Str, utf8), | |||
[<<(byte_size(Str2)):16/big>>, Str2]. | |||
encode(Record) -> | |||
MsgBin = encodeRec(Record), | |||
MsgId = getMsgId(element(1, Record)), | |||
[<<MsgId:16/big>>, MsgBin]. | |||
decode(Bin) -> | |||
<<MsgId:16/big, MsgBin/binary>> = Bin, | |||
SchList = getMsgSchema(MsgId), | |||
{<<>>, ResultList} = decodeField(SchList, MsgBin, [getMsgType(MsgId)]), | |||
list_to_tuple(ResultList). | |||
decodeRec(RecordName, Bin) -> | |||
SchList = getMsgSchema(RecordName), | |||
{LeftBin, Result} = decodeField(SchList, Bin, [RecordName]), | |||
{LeftBin, list_to_tuple(Result)}. | |||
decodeField([], LeftBin, Result) -> | |||
{LeftBin, lists:reverse(Result)}; | |||
decodeField([Type | SchList], MsgBin, Result) -> | |||
case Type of | |||
int32 -> | |||
<<Int:32/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint32 -> | |||
<<Int:32/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
string -> | |||
<<Len:16/big, StrBin:Len/binary, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [StrBin | Result]); | |||
int16 -> | |||
<<Int:16/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint16 -> | |||
<<Int:16/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
int8 -> | |||
<<Int:8/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint8 -> | |||
<<Int:8/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
int64 -> | |||
<<Int:64/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint64 -> | |||
<<Int:64/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
bool -> | |||
<<Bool:8/big-unsigned, LeftBin/binary>> = MsgBin, | |||
case Bool =:= 1 of | |||
true -> | |||
decodeField(SchList, LeftBin, [true | Result]); | |||
_ -> | |||
decodeField(SchList, LeftBin, [false | Result]) | |||
end; | |||
falat -> | |||
<<Float:32/big-float, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Float | Result]); | |||
double -> | |||
<<Float:64/big-float, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Float | Result]); | |||
{list, int32} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt32List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint32} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint32List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, int16} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt16List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint16} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint16List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, int8} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt8List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint8} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint8List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, string} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deStringList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, int64} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt64List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint64} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint64List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, bool} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deBoolList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, flat} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deFloatList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, double} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deDoubleList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, RecordName} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deRecordList(Len, RecordName, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
RecordName -> | |||
<<IsUndef:8, LeftBin/binary>> = MsgBin, | |||
case IsUndef of | |||
0 -> | |||
decodeField(SchList, LeftBin, [undefined | Result]); | |||
_ -> | |||
SubSchList = getMsgSchema(RecordName), | |||
{SubLeftBin, SubResultList} = decodeField(SubSchList, LeftBin, [RecordName]), | |||
decodeField(SchList, SubLeftBin, [list_to_tuple(SubResultList) | Result]) | |||
end | |||
end. | |||
deBoolList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deBoolList(N, <<Bool:8, LeftBin/binary>>, RetList) -> | |||
case Bool =:= 1 of | |||
true -> | |||
deBoolList(N - 1, LeftBin, [true | RetList]); | |||
_ -> | |||
deBoolList(N - 1, LeftBin, [false | RetList]) | |||
end. | |||
deInt8List(0, MsgBin, RetList) -> | |||
{MsgBin, RetList}; | |||
deInt8List(N, <<Int:8/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt8List(N - 1, LeftBin, [Int | RetList]). | |||
deUint8List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint8List(N, <<Int:8/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint8List(N - 1, LeftBin, [Int | RetList]). | |||
deInt16List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deInt16List(N, <<Int:16/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt16List(N - 1, LeftBin, [Int | RetList]). | |||
deUint16List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint16List(N, <<Int:16/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint16List(N - 1, LeftBin, [Int | RetList]). | |||
deInt32List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deInt32List(N, <<Int:32/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt32List(N - 1, LeftBin, [Int | RetList]). | |||
deUint32List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint32List(N, <<Int:32/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint32List(N - 1, LeftBin, [Int | RetList]). | |||
deInt64List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deInt64List(N, <<Int:64/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt64List(N - 1, LeftBin, [Int | RetList]). | |||
deUint64List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint64List(N, <<Int:64/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint64List(N - 1, LeftBin, [Int | RetList]). | |||
deFloatList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deFloatList(N, <<Float:32/big-float, LeftBin/binary>>, RetList) -> | |||
deFloatList(N - 1, LeftBin, [Float | RetList]). | |||
deDoubleList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deDoubleList(N, <<Float:64/big-float, LeftBin/binary>>, RetList) -> | |||
deDoubleList(N - 1, LeftBin, [Float | RetList]). | |||
deStringList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deStringList(N, <<Len:16/big, StrBin:Len/binary-unit:8, LeftBin/binary>>, RetList) -> | |||
deStringList(N - 1, LeftBin, [StrBin | RetList]). | |||
deRecordList(0, _RecordName, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deRecordList(N, RecordName, MsgBin, RetList) -> | |||
{LeftBin, Tuple} = decodeRec(RecordName, MsgBin), | |||
deRecordList(N - 1, RecordName, LeftBin, [Tuple | RetList]).\n\n". | |||
genSchema({FieldType, _FieldName}, AccList) -> | |||
SchemaStr = protoField:getSchemaInfo(FieldType), | |||
[SchemaStr | AccList]. | |||
genMsgHrl(FieldInfo, {Index, AccList}) -> | |||
TemStr = | |||
case Index of | |||
1 -> | |||
""; | |||
_ -> | |||
"," | |||
end, | |||
RecStr = TemStr ++ protoField:builtRecStr(FieldInfo), | |||
{Index - 1, [RecStr | AccList]}. | |||
genEncodeRec({MsgName, _MsgId, FieldList}) -> | |||
FieldLen = length(FieldList), | |||
FunHead = | |||
fun(_, {Index, StrAcc}) -> | |||
{Index - 1, ", V" ++ integer_to_list(Index) ++ StrAcc} | |||
end, | |||
{_, TemStr} = lists:foldr(FunHead, {FieldLen, "}) ->\n\t"}, FieldList), | |||
HeadStr = "encodeRec({" ++ MsgName ++ TemStr, | |||
FunBody = | |||
fun({FieldType, _FieldName}, {Index, PStrAcc}) -> | |||
TemV = "V" ++ integer_to_list(Index), | |||
PackStr = protoField:builtPackStr(FieldType) ++ TemV ++ ")", | |||
case Index == 1 of | |||
true -> | |||
{Index - 1, PackStr ++ PStrAcc}; | |||
_ -> | |||
{Index - 1, ", " ++ PackStr ++ PStrAcc} | |||
end | |||
end, | |||
{_, LastStr} = lists:foldr(FunBody, {FieldLen, ""}, FieldList), | |||
case FieldLen > 0 of | |||
true -> | |||
HeadStr ++ "[" ++ LastStr ++ "];\n"; | |||
_ -> | |||
HeadStr ++ "[];\n" | |||
end. | |||
convertFile(File) -> | |||
protoParse:parseFile(File). | |||
convert([ProtoDir, HrlDir, ErlDir]) -> | |||
convertDir(atom_to_list(ProtoDir), atom_to_list(HrlDir), atom_to_list(ErlDir)). | |||
convertDir() -> | |||
convertDir("./", "./", "./"). | |||
convertDir(ProtoDir) -> | |||
convertDir(ProtoDir, "./", "./"). | |||
convertDir(ProtoDir, HrlDir, ErlDir) -> | |||
FunRead = | |||
fun(File, Acc) -> | |||
case filename:extension(File) == ".msg" of | |||
true -> | |||
io:format("Convert proto msg file: ~s ~n", [File]), | |||
BaseName = filename:basename(File, ".msg"), | |||
[ModIndex | _ModName] = re:split(BaseName, "_"), | |||
Index = binary_to_integer(ModIndex), | |||
put(messageid, Index * 1000 + 1), | |||
SProto = protoParse:parseFile(File), | |||
[SProto | Acc]; | |||
_ -> | |||
Acc | |||
end | |||
end, | |||
%% 下面文件帅选并不能准确的帅选出文件名为.msg结尾的文件 在FunRead函数中纠正处理一下 | |||
SProtoListOfList = filelib:fold_files(ProtoDir, "\\.msg", true, FunRead, []), | |||
SProtoList = lists:append(SProtoListOfList), | |||
SortedSProtoList = lists:sort(fun({_Name1, MessageId1, _FieldList1}, {_Name2, MessageId2, _FieldList2}) -> | |||
MessageId1 > MessageId2 end, SProtoList), | |||
FunSpell = | |||
fun({MsgName, MsgId, FieldList} = MsgInfo, {MsgHrlAcc, MsgTypeAcc, MsgIdAcc, MsgEndStr, MsgSchemaAcc}) -> | |||
TypeStr = "getMsgType(" ++ integer_to_list(MsgId) ++ ")->\n\t" ++ MsgName ++ ";\n", | |||
IdStr = "getMsgId(" ++ MsgName ++ ")->\n\t" ++ integer_to_list(MsgId) ++ ";\n", | |||
EncodeStr = genEncodeRec(MsgInfo), | |||
Len = erlang:length(FieldList), | |||
SchemaList = lists:foldr(fun genSchema/2, [], FieldList), | |||
SchemaStr = "getMsgSchema(" ++ MsgName ++ ")->\n\t" ++ "getMsgSchema(" ++ integer_to_list(MsgId) ++ ");\n" ++ | |||
"getMsgSchema(" ++ integer_to_list(MsgId) ++ ")->\n\t" ++ io_lib:format("~p", [SchemaList]) ++ ";\n", | |||
{_, LastFieldStr} = lists:foldr(fun genMsgHrl/2, {Len, ""}, FieldList), | |||
HrlStr = "-record(" ++ MsgName ++ " ,{\n\t" ++ LastFieldStr ++ "}).\n", | |||
{[HrlStr | MsgHrlAcc], [TypeStr | MsgTypeAcc], [IdStr | MsgIdAcc], [EncodeStr | MsgEndStr], [SchemaStr | MsgSchemaAcc]} | |||
end, | |||
{MsgHrlStr, MsgTypeStr, MsgIdStr, MsgEndStr, MsgSchemaStr} = lists:foldl(FunSpell, {[], ["getMsgType(_) ->\n\tundefined.\n\n"], ["getMsgId(_) ->\n\t0.\n\n"], ["encodeRec(_) ->\n\t[].\n\n"], ["getMsgSchema(_) ->\n\t[].\n\n"]}, SortedSProtoList), | |||
ModStr = protoErlHeader(), | |||
OutputStr = ModStr ++ MsgTypeStr ++ MsgIdStr ++ MsgEndStr ++ MsgSchemaStr, | |||
HrlFilename = do_write_hrl(HrlDir, protoMsg, protoHrlHeader() ++ MsgHrlStr), | |||
ErlFilename = do_write_erl(ErlDir, protoMsg, OutputStr), | |||
io:format("protoConvert hrl dir : ~s ~n", [HrlDir]), | |||
io:format("protoConvert erl dir : ~s ~n", [ErlDir]), | |||
io:format("protoConvert to hrl file ~s succ.~n", [HrlFilename]), | |||
io:format("protoConvert to erl file ~s succ.~n", [ErlFilename]), | |||
ok. | |||
do_write_hrl(OutDir, Mod, Str) when is_list(OutDir) -> | |||
Filename = filename:join([OutDir, atom_to_list(Mod) ++ ".hrl"]), | |||
ok = file:write_file(Filename, Str), | |||
Filename. | |||
do_write_erl(OutDir, Mod, Str) when is_list(OutDir) -> | |||
Filename = filename:join([OutDir, atom_to_list(Mod) ++ ".erl"]), | |||
ok = file:write_file(Filename, Str), | |||
Filename. |
@ -0,0 +1,475 @@ | |||
-module(protoParse). | |||
-compile(nowarn_unused_function). | |||
-export([ | |||
parseParse/1 | |||
, parseFile/1 | |||
]). | |||
-define(p_anything, true). | |||
-define(p_charclass, true). | |||
-define(p_choose, true). | |||
-define(p_label, true). | |||
-define(p_not, true). | |||
-define(p_one_or_more, true). | |||
-define(p_optional, true). | |||
-define(p_scan, true). | |||
-define(p_seq, true). | |||
-define(p_string, true). | |||
-define(p_zero_or_more, true). | |||
-spec parseFile(file:name()) -> any(). | |||
parseFile(Filename) -> | |||
case file:read_file(Filename) of | |||
{ok, Bin} -> | |||
parseParse(Bin); | |||
Err -> Err | |||
end. | |||
-spec parseParse(binary() | list()) -> any(). | |||
parseParse(List) when is_list(List) -> | |||
parseParse(unicode:characters_to_binary(List)); | |||
parseParse(Input) when is_binary(Input) -> | |||
Result = | |||
case 'all'(Input, {{line, 1}, {column, 1}}) of | |||
{AST, <<>>, _Index} -> | |||
AST; | |||
Any -> | |||
Any | |||
end, | |||
release_memo(), | |||
Result. | |||
-spec 'all'(input(), index()) -> parse_result(). | |||
'all'(Input, Index) -> | |||
p(Input, Index, 'all', | |||
fun(I, D) -> | |||
(p_seq([fun 'blank0'/2, p_zero_or_more(p_seq([fun 'protocol'/2, fun 'blank0'/2]))]))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
[_ | [T]] = Node, DataList = [H || [H | _] <- T], DataList | |||
end). | |||
-spec 'protocol'(input(), index()) -> parse_result(). | |||
'protocol'(Input, Index) -> | |||
p(Input, Index, 'protocol', | |||
fun(I, D) -> | |||
(p_seq([p_label('name', fun 'name'/2), fun 'blank0'/2, p_label('structural', fun 'structural'/2)]))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Name = binary_to_list(iolist_to_binary(proplists:get_value(name, Node))), | |||
Structural = proplists:get_value(structural, Node), | |||
MsgId = get(messageid), | |||
put(messageid, MsgId + 1), | |||
{Name, MsgId, Structural} | |||
end). | |||
-spec 'structural'(input(), index()) -> parse_result(). | |||
'structural'(Input, Index) -> | |||
p(Input, Index, 'structural', | |||
fun(I, D) -> | |||
(p_seq([p_string(<<"{">>), fun 'blank0'/2, p_zero_or_more(p_seq([fun 'field'/2, fun 'blank0'/2])), p_string(<<"}">>)]))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
[_, _, List, _] = Node, [H || [H | _] <- List] | |||
end). | |||
-spec 'field'(input(), index()) -> parse_result(). | |||
'field'(Input, Index) -> | |||
p(Input, Index, 'field', | |||
fun(I, D) -> | |||
(p_seq([p_label('datatype', fun 'typename'/2), fun 'blanks'/2, p_label('name', fun 'name'/2), fun 'blank0'/2, p_string(<<";">>)]))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
DataType = binary_to_list(iolist_to_binary(proplists:get_value(datatype, Node))), | |||
Name = binary_to_list(iolist_to_binary(proplists:get_value(name, Node))), | |||
{DataType, Name} | |||
end). | |||
-spec 'eof'(input(), index()) -> parse_result(). | |||
'eof'(Input, Index) -> | |||
p(Input, Index, 'eof', | |||
fun(I, D) -> | |||
(p_not(p_string(<<".">>)))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-spec 'newline'(input(), index()) -> parse_result(). | |||
'newline'(Input, Index) -> | |||
p(Input, Index, 'newline', | |||
fun(I, D) -> | |||
(p_seq([p_optional(p_charclass(<<"[\r]">>)), p_charclass(<<"[\n]">>)]))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-spec 'line_comment'(input(), index()) -> parse_result(). | |||
'line_comment'(Input, Index) -> | |||
p(Input, Index, 'line_comment', | |||
fun(I, D) -> | |||
(p_seq([p_choose([p_string(<<"//">>), p_string(<<"%">>)]), p_zero_or_more(p_seq([p_not(fun 'newline'/2), p_anything()])), p_choose([fun 'newline'/2, fun 'eof'/2])]))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-spec 'blank'(input(), index()) -> parse_result(). | |||
'blank'(Input, Index) -> | |||
p(Input, Index, 'blank', | |||
fun(I, D) -> | |||
(p_choose([p_charclass(<<"[\s\t]">>), fun 'newline'/2, fun 'line_comment'/2]))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-spec 'blank0'(input(), index()) -> parse_result(). | |||
'blank0'(Input, Index) -> | |||
p(Input, Index, 'blank0', | |||
fun(I, D) -> | |||
(p_zero_or_more(fun 'blank'/2))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-spec 'blanks'(input(), index()) -> parse_result(). | |||
'blanks'(Input, Index) -> | |||
p(Input, Index, 'blanks', | |||
fun(I, D) -> (p_one_or_more(fun 'blank'/2))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-spec 'alpha'(input(), index()) -> parse_result(). | |||
'alpha'(Input, Index) -> | |||
p(Input, Index, 'alpha', | |||
fun(I, D) -> | |||
(p_choose([p_charclass(<<"[a-z]">>), p_charclass(<<"[A-Z]">>), p_string(<<"_">>), p_string(<<"[">>), p_string(<<"]">>)]))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-spec 'alnum'(input(), index()) -> parse_result(). | |||
'alnum'(Input, Index) -> | |||
p(Input, Index, 'alnum', | |||
fun(I, D) -> | |||
(p_choose([fun 'alpha'/2, p_charclass(<<"[0-9]">>)]))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-spec 'word'(input(), index()) -> parse_result(). | |||
'word'(Input, Index) -> | |||
p(Input, Index, 'word', | |||
fun(I, D) -> | |||
(p_seq([fun 'alpha'/2, p_zero_or_more(fun 'alnum'/2)]))(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-spec 'name'(input(), index()) -> parse_result(). | |||
'name'(Input, Index) -> | |||
p(Input, Index, 'name', | |||
fun(I, D) -> | |||
(fun 'word'/2)(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-spec 'typename'(input(), index()) -> parse_result(). | |||
'typename'(Input, Index) -> | |||
p(Input, Index, 'typename', | |||
fun(I, D) -> | |||
(fun 'word'/2)(I, D) | |||
end, | |||
fun(Node, _Idx) -> | |||
Node | |||
end). | |||
-file("peg_includes.hrl", 1). | |||
-type index() :: {{line, pos_integer()}, {column, pos_integer()}}. | |||
-type input() :: binary(). | |||
-type parse_failure() :: {fail, term()}. | |||
-type parse_success() :: {term(), input(), index()}. | |||
-type parse_result() :: parse_failure() | parse_success(). | |||
-type parse_fun() :: fun((input(), index()) -> parse_result()). | |||
-type xform_fun() :: fun((input(), index()) -> term()). | |||
-spec p(input(), index(), atom(), parse_fun(), xform_fun()) -> parse_result(). | |||
p(Inp, StartIndex, Name, ParseFun, TransformFun) -> | |||
case get_memo(StartIndex, Name) of % See if the current reduction is memoized | |||
{ok, Memo} -> % If it is, return the stored result | |||
Memo; | |||
_ -> % If not, attempt to parse | |||
Result = | |||
case ParseFun(Inp, StartIndex) of | |||
{fail, _} = Failure -> % If it fails, memoize the failure | |||
Failure; | |||
{Match, InpRem, NewIndex} -> % If it passes, transform and memoize the result. | |||
Transformed = TransformFun(Match, StartIndex), | |||
{Transformed, InpRem, NewIndex} | |||
end, | |||
memoize(StartIndex, Name, Result), | |||
Result | |||
end. | |||
-spec setup_memo() -> list(). | |||
setup_memo() -> | |||
erase(). | |||
-spec release_memo() -> list(). | |||
release_memo() -> | |||
erase(). | |||
-spec memoize(index(), atom(), parse_result()) -> any(). | |||
memoize(Index, Name, Result) -> | |||
case get(Index) of | |||
undefined -> | |||
put(Index, [{Name, Result}]); | |||
[] -> | |||
put(Index, [{Name, Result}]); | |||
Plist -> | |||
put(Index, [{Name, Result} | Plist]) | |||
end. | |||
-spec get_memo(index(), atom()) -> {ok, term()} | {error, not_found}. | |||
get_memo(Index, Name) -> | |||
case get(Index) of | |||
undefined -> | |||
{error, not_found}; | |||
[] -> | |||
{error, not_found}; | |||
Plist -> | |||
case proplists:lookup(Name, Plist) of | |||
{Name, Result} -> | |||
{ok, Result}; | |||
_ -> | |||
{error, not_found} | |||
end | |||
end. | |||
-ifdef(p_eof). | |||
-spec p_eof() -> parse_fun(). | |||
p_eof() -> | |||
fun(<<>>, Index) -> | |||
{eof, [], Index}; | |||
(_, Index) -> | |||
{fail, {expected, eof, Index}} end. | |||
-endif. | |||
-ifdef(p_optional). | |||
-spec p_optional(parse_fun()) -> parse_fun(). | |||
p_optional(P) -> | |||
fun(Input, Index) -> | |||
case P(Input, Index) of | |||
{fail, _} -> | |||
{[], Input, Index}; | |||
{_, _, _} = Success -> | |||
Success | |||
end | |||
end. | |||
-endif. | |||
-ifdef(p_not). | |||
-spec p_not(parse_fun()) -> parse_fun(). | |||
p_not(P) -> | |||
fun(Input, Index) -> | |||
case P(Input, Index) of | |||
{fail, _} -> | |||
{[], Input, Index}; | |||
{Result, _, _} -> | |||
{fail, {expected, {no_match, Result}, Index}} | |||
end | |||
end. | |||
-endif. | |||
-ifdef(p_assert). | |||
-spec p_assert(parse_fun()) -> parse_fun(). | |||
p_assert(P) -> | |||
fun(Input, Index) -> | |||
case P(Input, Index) of | |||
{fail, _} = Failure -> | |||
Failure; | |||
_ -> | |||
{[], Input, Index} | |||
end | |||
end. | |||
-endif. | |||
-ifdef(p_seq). | |||
-spec p_seq([parse_fun()]) -> parse_fun(). | |||
p_seq(P) -> | |||
fun(Input, Index) -> | |||
p_all(P, Input, Index, []) | |||
end. | |||
-spec p_all([parse_fun()], input(), index(), [term()]) -> parse_result(). | |||
p_all([], Inp, Index, Accum) -> | |||
{lists:reverse(Accum), Inp, Index}; | |||
p_all([P | Parsers], Inp, Index, Accum) -> | |||
case P(Inp, Index) of | |||
{fail, _} = Failure -> | |||
Failure; | |||
{Result, InpRem, NewIndex} -> | |||
p_all(Parsers, InpRem, NewIndex, [Result | Accum]) | |||
end. | |||
-endif. | |||
-ifdef(p_choose). | |||
-spec p_choose([parse_fun()]) -> parse_fun(). | |||
p_choose(Parsers) -> | |||
fun(Input, Index) -> | |||
p_attempt(Parsers, Input, Index, none) | |||
end. | |||
-spec p_attempt([parse_fun()], input(), index(), none | parse_failure()) -> parse_result(). | |||
p_attempt([], _Input, _Index, Failure) -> Failure; | |||
p_attempt([P | Parsers], Input, Index, FirstFailure) -> | |||
case P(Input, Index) of | |||
{fail, _} = Failure -> | |||
case FirstFailure of | |||
none -> | |||
p_attempt(Parsers, Input, Index, Failure); | |||
_ -> | |||
p_attempt(Parsers, Input, Index, FirstFailure) | |||
end; | |||
Result -> | |||
Result | |||
end. | |||
-endif. | |||
-ifdef(p_zero_or_more). | |||
-spec p_zero_or_more(parse_fun()) -> parse_fun(). | |||
p_zero_or_more(P) -> | |||
fun(Input, Index) -> | |||
p_scan(P, Input, Index, []) | |||
end. | |||
-endif. | |||
-ifdef(p_one_or_more). | |||
-spec p_one_or_more(parse_fun()) -> parse_fun(). | |||
p_one_or_more(P) -> | |||
fun(Input, Index) -> | |||
Result = p_scan(P, Input, Index, []), | |||
case Result of | |||
{[_ | _], _, _} -> | |||
Result; | |||
_ -> | |||
{fail, {expected, Failure, _}} = P(Input, Index), | |||
{fail, {expected, {at_least_one, Failure}, Index}} | |||
end | |||
end. | |||
-endif. | |||
-ifdef(p_label). | |||
-spec p_label(atom(), parse_fun()) -> parse_fun(). | |||
p_label(Tag, P) -> | |||
fun(Input, Index) -> | |||
case P(Input, Index) of | |||
{fail, _} = Failure -> | |||
Failure; | |||
{Result, InpRem, NewIndex} -> | |||
{{Tag, Result}, InpRem, NewIndex} | |||
end | |||
end. | |||
-endif. | |||
-ifdef(p_scan). | |||
-spec p_scan(parse_fun(), input(), index(), [term()]) -> {[term()], input(), index()}. | |||
p_scan(_, <<>>, Index, Accum) -> | |||
{lists:reverse(Accum), <<>>, Index}; | |||
p_scan(P, Inp, Index, Accum) -> | |||
case P(Inp, Index) of | |||
{fail, _} -> | |||
{lists:reverse(Accum), Inp, Index}; | |||
{Result, InpRem, NewIndex} -> | |||
p_scan(P, InpRem, NewIndex, [Result | Accum]) | |||
end. | |||
-endif. | |||
-ifdef(p_string). | |||
-spec p_string(binary()) -> parse_fun(). | |||
p_string(S) -> | |||
Length = erlang:byte_size(S), | |||
fun(Input, Index) -> | |||
try | |||
<<S:Length/binary, Rest/binary>> = Input, | |||
{S, Rest, p_advance_index(S, Index)} | |||
catch | |||
error:{badmatch, _} -> | |||
{fail, {expected, {string, S}, Index}} | |||
end | |||
end. | |||
-endif. | |||
-ifdef(p_anything). | |||
-spec p_anything() -> parse_fun(). | |||
p_anything() -> | |||
fun(<<>>, Index) -> | |||
{fail, {expected, any_character, Index}}; | |||
(Input, Index) when is_binary(Input) -> | |||
<<C/utf8, Rest/binary>> = Input, | |||
{<<C/utf8>>, Rest, p_advance_index(<<C/utf8>>, Index)} | |||
end. | |||
-endif. | |||
-ifdef(p_charclass). | |||
-spec p_charclass(string() | binary()) -> parse_fun(). | |||
p_charclass(Class) -> | |||
{ok, RE} = re:compile(Class, [unicode, dotall]), | |||
fun(Inp, Index) -> | |||
case re:run(Inp, RE, [anchored]) of | |||
{match, [{0, Length} | _]} -> | |||
{Head, Tail} = erlang:split_binary(Inp, Length), | |||
{Head, Tail, p_advance_index(Head, Index)}; | |||
_ -> | |||
{fail, {expected, {character_class, binary_to_list(Class)}, Index}} | |||
end | |||
end. | |||
-endif. | |||
-ifdef(p_regexp). | |||
-spec p_regexp(binary()) -> parse_fun(). | |||
p_regexp(Regexp) -> | |||
{ok, RE} = re:compile(Regexp, [unicode, dotall, anchored]), | |||
fun(Inp, Index) -> | |||
case re:run(Inp, RE) of | |||
{match, [{0, Length} | _]} -> | |||
{Head, Tail} = erlang:split_binary(Inp, Length), | |||
{Head, Tail, p_advance_index(Head, Index)}; | |||
_ -> | |||
{fail, {expected, {regexp, binary_to_list(Regexp)}, Index}} | |||
end | |||
end. | |||
-endif. | |||
-ifdef(line). | |||
-spec line(index() | term()) -> pos_integer() | undefined. | |||
line({{line, L}, _}) -> L; | |||
line(_) -> undefined. | |||
-endif. | |||
-ifdef(column). | |||
-spec column(index() | term()) -> pos_integer() | undefined. | |||
column({_, {column, C}}) -> C; | |||
column(_) -> undefined. | |||
-endif. | |||
-spec p_advance_index(input() | unicode:charlist() | pos_integer(), index()) -> index(). | |||
p_advance_index(MatchedInput, Index) when is_list(MatchedInput) orelse is_binary(MatchedInput) -> % strings | |||
lists:foldl(fun p_advance_index/2, Index, unicode:characters_to_list(MatchedInput)); | |||
p_advance_index(MatchedInput, Index) when is_integer(MatchedInput) -> % single characters | |||
{{line, Line}, {column, Col}} = Index, | |||
case MatchedInput of | |||
$\n -> {{line, Line + 1}, {column, 1}}; | |||
_ -> {{line, Line}, {column, Col + 1}} | |||
end. |
@ -0,0 +1 @@ | |||
erl -pa ../ebin -s protoGen convertDir ../proto ./ ./ |
@ -0,0 +1,285 @@ | |||
-module(protoMsg). | |||
-export([encode/1, decode/1, encodeRec/1, decodeRec/2]). | |||
-define(bool(V), (case V of true -> <<1:8>>; _ -> <<0:8>> end)). | |||
-define(int8(V), <<V:8>>). | |||
-define(uint8(V), <<V:8>>). | |||
-define(int16(V), <<V:16/big>>). | |||
-define(uint16(V), <<V:16/big>>). | |||
-define(int32(V), <<V:32/big>>). | |||
-define(uint32(V), <<V:32/big>>). | |||
-define(int64(V), <<V:64/big>>). | |||
-define(uint64(V), <<V:64/big>>). | |||
-define(float(V), <<V:32/big-float>>). | |||
-define(double(V), <<V:64/big-float>>). | |||
-define(string(V), (string(V))). | |||
-define(record(V), (case V of undefined -> [<<0:8>>]; V -> [<<1:8>>, encodeRec(V)] end)). | |||
-define(list_bool(List), [<<(length(List)):16/big>>, [?bool(V) || V <- List]]). | |||
-define(list_int8(List), [<<(length(List)):16/big>>, [?int8(V) || V <- List]]). | |||
-define(list_uint8(List), [<<(length(List)):16/big>>, [?uint8(V) || V <- List]]). | |||
-define(list_int16(List), [<<(length(List)):16/big>>, [?int16(V) || V <- List]]). | |||
-define(list_uint16(List), [<<(length(List)):16/big>>, [?uint16(V) || V <- List]]). | |||
-define(list_int32(List), [<<(length(List)):16/big>>, [?int32(V) || V <- List]]). | |||
-define(list_uint32(List), [<<(length(List)):16/big>>, [?uint32(V) || V <- List]]). | |||
-define(list_int64(List), [<<(length(List)):16/big>>, [?int64(V) || V <- List]]). | |||
-define(list_uint64(List), [<<(length(List)):16/big>>, [?uint64(V) || V <- List]]). | |||
-define(list_float(List), [<<(length(List)):16/big>>, [?float(V) || V <- List]]). | |||
-define(list_double(List), [<<(length(List)):16/big>>, [?double(V) || V <- List]]). | |||
-define(list_string(List), [<<(length(List)):16/big>>, [string(V) || V <- List]]). | |||
-define(list_record(List), [<<(length(List)):16/big>>, [encodeRec(V) || V <- List]]). | |||
string(Str) when is_binary(Str) -> | |||
[<<(byte_size(Str)):16/big>>, Str]; | |||
string(Str) -> | |||
Str2 = unicode:characters_to_binary(Str, utf8), | |||
[<<(byte_size(Str2)):16/big>>, Str2]. | |||
encode(Record) -> | |||
MsgBin = encodeRec(Record), | |||
MsgId = getMsgId(element(1, Record)), | |||
[<<MsgId:16/big>>, MsgBin]. | |||
decode(Bin) -> | |||
<<MsgId:16/big, MsgBin/binary>> = Bin, | |||
SchList = getMsgSchema(MsgId), | |||
{<<>>, ResultList} = decodeField(SchList, MsgBin, [getMsgType(MsgId)]), | |||
list_to_tuple(ResultList). | |||
decodeRec(RecordName, Bin) -> | |||
SchList = getMsgSchema(RecordName), | |||
{LeftBin, Result} = decodeField(SchList, Bin, [RecordName]), | |||
{LeftBin, list_to_tuple(Result)}. | |||
decodeField([], LeftBin, Result) -> | |||
{LeftBin, lists:reverse(Result)}; | |||
decodeField([Type | SchList], MsgBin, Result) -> | |||
case Type of | |||
int32 -> | |||
<<Int:32/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint32 -> | |||
<<Int:32/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
string -> | |||
<<Len:16/big, StrBin:Len/binary, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [StrBin | Result]); | |||
int16 -> | |||
<<Int:16/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint16 -> | |||
<<Int:16/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
int8 -> | |||
<<Int:8/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint8 -> | |||
<<Int:8/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
int64 -> | |||
<<Int:64/big-signed, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
uint64 -> | |||
<<Int:64/big-unsigned, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Int | Result]); | |||
bool -> | |||
<<Bool:8/big-unsigned, LeftBin/binary>> = MsgBin, | |||
case Bool =:= 1 of | |||
true -> | |||
decodeField(SchList, LeftBin, [true | Result]); | |||
_ -> | |||
decodeField(SchList, LeftBin, [false | Result]) | |||
end; | |||
falat -> | |||
<<Float:32/big-float, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Float | Result]); | |||
double -> | |||
<<Float:64/big-float, LeftBin/binary>> = MsgBin, | |||
decodeField(SchList, LeftBin, [Float | Result]); | |||
{list, int32} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt32List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint32} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint32List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, int16} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt16List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint16} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint16List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, int8} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt8List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint8} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint8List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, string} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deStringList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, int64} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deInt64List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, uint64} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deUint64List(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, bool} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deBoolList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, flat} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deFloatList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, double} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deDoubleList(Len, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
{list, RecordName} -> | |||
<<Len:16/big, LeftListBin/binary>> = MsgBin, | |||
{LeftBin, RetList} = deRecordList(Len, RecordName, LeftListBin, []), | |||
decodeField(SchList, LeftBin, [RetList | Result]); | |||
RecordName -> | |||
<<IsUndef:8, LeftBin/binary>> = MsgBin, | |||
case IsUndef of | |||
0 -> | |||
decodeField(SchList, LeftBin, [undefined | Result]); | |||
_ -> | |||
SubSchList = getMsgSchema(RecordName), | |||
{SubLeftBin, SubResultList} = decodeField(SubSchList, LeftBin, [RecordName]), | |||
decodeField(SchList, SubLeftBin, [list_to_tuple(SubResultList) | Result]) | |||
end | |||
end. | |||
deBoolList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deBoolList(N, <<Bool:8, LeftBin/binary>>, RetList) -> | |||
case Bool =:= 1 of | |||
true -> | |||
deBoolList(N - 1, LeftBin, [true | RetList]); | |||
_ -> | |||
deBoolList(N - 1, LeftBin, [false | RetList]) | |||
end. | |||
deInt8List(0, MsgBin, RetList) -> | |||
{MsgBin, RetList}; | |||
deInt8List(N, <<Int:8/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt8List(N - 1, LeftBin, [Int | RetList]). | |||
deUint8List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint8List(N, <<Int:8/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint8List(N - 1, LeftBin, [Int | RetList]). | |||
deInt16List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deInt16List(N, <<Int:16/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt16List(N - 1, LeftBin, [Int | RetList]). | |||
deUint16List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint16List(N, <<Int:16/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint16List(N - 1, LeftBin, [Int | RetList]). | |||
deInt32List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deInt32List(N, <<Int:32/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt32List(N - 1, LeftBin, [Int | RetList]). | |||
deUint32List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint32List(N, <<Int:32/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint32List(N - 1, LeftBin, [Int | RetList]). | |||
deInt64List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deInt64List(N, <<Int:64/big-signed, LeftBin/binary>>, RetList) -> | |||
deInt64List(N - 1, LeftBin, [Int | RetList]). | |||
deUint64List(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deUint64List(N, <<Int:64/big-unsigned, LeftBin/binary>>, RetList) -> | |||
deUint64List(N - 1, LeftBin, [Int | RetList]). | |||
deFloatList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deFloatList(N, <<Float:32/big-float, LeftBin/binary>>, RetList) -> | |||
deFloatList(N - 1, LeftBin, [Float | RetList]). | |||
deDoubleList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deDoubleList(N, <<Float:64/big-float, LeftBin/binary>>, RetList) -> | |||
deDoubleList(N - 1, LeftBin, [Float | RetList]). | |||
deStringList(0, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deStringList(N, <<Len:16/big, StrBin:Len/binary-unit:8, LeftBin/binary>>, RetList) -> | |||
deStringList(N - 1, LeftBin, [StrBin | RetList]). | |||
deRecordList(0, _RecordName, MsgBin, RetList) -> | |||
{MsgBin, lists:reverse(RetList)}; | |||
deRecordList(N, RecordName, MsgBin, RetList) -> | |||
{LeftBin, Tuple} = decodeRec(RecordName, MsgBin), | |||
deRecordList(N - 1, RecordName, LeftBin, [Tuple | RetList]). | |||
getMsgType(1)-> | |||
test; | |||
getMsgType(2)-> | |||
phoneNumber; | |||
getMsgType(3)-> | |||
person; | |||
getMsgType(4)-> | |||
addressBook; | |||
getMsgType(_) -> | |||
undefined. | |||
getMsgId(test)-> | |||
1; | |||
getMsgId(phoneNumber)-> | |||
2; | |||
getMsgId(person)-> | |||
3; | |||
getMsgId(addressBook)-> | |||
4; | |||
getMsgId(_) -> | |||
0. | |||
encodeRec({test, V1}) -> | |||
[?string(V1)]; | |||
encodeRec({phoneNumber, V1, V2}) -> | |||
[?record(V1), ?int32(V2)]; | |||
encodeRec({person, V1, V2, V3, V4}) -> | |||
[?string(V1), ?int32(V2), ?string(V3), ?list_record(V4)]; | |||
encodeRec({addressBook, V1, V2}) -> | |||
[?list_record(V1), ?list_record(V2)]; | |||
encodeRec(_) -> | |||
[]. | |||
getMsgSchema(test)-> | |||
getMsgSchema(1); | |||
getMsgSchema(1)-> | |||
[string]; | |||
getMsgSchema(phoneNumber)-> | |||
getMsgSchema(2); | |||
getMsgSchema(2)-> | |||
[test,int32]; | |||
getMsgSchema(person)-> | |||
getMsgSchema(3); | |||
getMsgSchema(3)-> | |||
[string,int32,string,{list,phoneNumber}]; | |||
getMsgSchema(addressBook)-> | |||
getMsgSchema(4); | |||
getMsgSchema(4)-> | |||
[{list,person},{list,person}]; | |||
getMsgSchema(_) -> | |||
[]. | |||
@ -0,0 +1,28 @@ | |||
-opaque int8() :: -128..127. | |||
-opaque int16() :: -32768..32767. | |||
-opaque int32() :: -2147483648..2147483647. | |||
-opaque int64() :: -9223372036854775808..9223372036854775807. | |||
-opaque uint8() :: 0..255. | |||
-opaque uint16() :: 0..65536. | |||
-opaque uint32() :: 0..4294967295. | |||
-opaque uint64() :: 0..18446744073709551615. | |||
-opaque single() :: float(). | |||
-opaque double() :: float(). | |||
-record(test ,{ | |||
aa = "" :: string() | |||
}). | |||
-record(phoneNumber ,{ | |||
number = undefined :: #test{} | |||
,type = 0 :: int32() | |||
}). | |||
-record(person ,{ | |||
name = "" :: string() | |||
,id = 0 :: int32() | |||
,email = "" :: string() | |||
,phone = [] :: [#phoneNumber{}] | |||
}). | |||
-record(addressBook ,{ | |||
person = [] :: [#person{}] | |||
,other = [] :: [#person{}] | |||
}). |
@ -0,0 +1,3 @@ | |||
#if not exist ebin md ebin | |||
FOR %%f in (*.erl) DO erlc -W0 -o . %%f | |||
pause |
@ -0,0 +1,319 @@ | |||
-module(test). | |||
-include("protoMsg.hrl"). | |||
-compile(export_all). | |||
hh1(0) -> | |||
ok; | |||
hh1(N) -> | |||
A = [tt1,tt2,tt3,tt4,{tet,tt1},{tet, tt2},{tet,tt3}, yyy], | |||
test(A), | |||
hh1(N -1). | |||
hh2(0) -> | |||
ok; | |||
hh2(N) -> | |||
A = [tt1,tt2,tt3,tt4,{tet,tt1},{tet, tt2},{tet,tt3}, yyy], | |||
tet(A), | |||
hh2(N -1). | |||
test([]) -> | |||
ok; | |||
test([A | T]) -> | |||
case A of | |||
tt1 -> | |||
ok; | |||
tt2 -> | |||
ok; | |||
tt3 -> | |||
ok; | |||
tt4 -> | |||
ok; | |||
{tet, tt1} -> | |||
ok; | |||
{tet, tt2} -> | |||
ok; | |||
{tet, tt3} -> | |||
ok; | |||
_ -> | |||
ok | |||
end, | |||
test(T). | |||
tet([]) -> | |||
ok; | |||
tet([tt1 | T]) -> | |||
ok, | |||
tet(T); | |||
tet([tt2 | T]) -> | |||
ok, | |||
tet(T); | |||
tet([tt3 | T]) -> | |||
ok, | |||
tet(T); | |||
tet([tt4 | T]) -> | |||
ok, | |||
tet(T); | |||
tet([{tet, tt1} | T]) -> | |||
ok, | |||
tet(T); | |||
tet([{tet, tt2} | T]) -> | |||
ok, | |||
tet(T); | |||
tet([{tet, tt3} | T]) -> | |||
ok, | |||
tet(T); | |||
tet([YY | T]) -> | |||
ok, | |||
tet(T). | |||
tt1(0)-> | |||
AddressBook = #addressBook{ | |||
person = [ | |||
#person{ | |||
name = "Alice", | |||
id = 10000, | |||
phone = [ | |||
#phoneNumber{ number = #test{aa = "123456789"} , type = 1 }, | |||
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 } | |||
] | |||
}, | |||
#person{ | |||
name = "Bob", | |||
id = 20000, | |||
phone = [ | |||
#phoneNumber{number = #test{aa = "01234567890"} , type = 3 } | |||
] | |||
} | |||
] | |||
}, | |||
Bin = protoMsg:encode(AddressBook); | |||
tt1(N) -> | |||
tt1(), | |||
tt1(N- 1). | |||
tt1() -> | |||
AddressBook = #addressBook{ | |||
person = [ | |||
#person{ | |||
name = "Alice", | |||
id = 10000, | |||
phone = [ | |||
#phoneNumber{ number = #test{aa = "123456789"} , type = 1 }, | |||
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 } | |||
] | |||
}, | |||
#person{ | |||
name = "Bob", | |||
id = 20000, | |||
phone = [ | |||
#phoneNumber{number = #test{aa = "01234567890"} , type = 3 } | |||
] | |||
} | |||
] | |||
}, | |||
%"others" => [ | |||
% #{ | |||
% "name" => "Carol", | |||
% "id" => 30000, | |||
% "phone" => [ | |||
% #{ "number" => #{"aa" => "9876543210"} } | |||
% ] | |||
% } | |||
%] | |||
%AddressBook = #person{name = "1232134", id = 11111,email = "aaa" ,phone = [#phoneNumber{}] }, | |||
%AddressBook = #phoneNumber{number =#test{aa = "dffsaf"},type = 12 }, | |||
Bin = protoMsg:encode(AddressBook). | |||
%ok = file:write_file("fff.bin", Bin), | |||
%print_bin(Bin), | |||
%Bin = protoCode:encode(AddressBook), | |||
%ok = file:write_file("fff.bin", Bin), | |||
%print_bin(Bin), | |||
%MsgId = protoMsg:getMsgId(element(1, AddressBook)), | |||
%<<MsgId:16/little, Bin/binary>>. | |||
tt(N) -> | |||
AddressBook = #addressBook{ | |||
person = [ | |||
#person{ | |||
name = "Alice", | |||
id = 10000, | |||
phone = [ | |||
#phoneNumber{ number = #test{aa = "123456789"} , type = 1 }, | |||
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 } | |||
] | |||
}, | |||
#person{ | |||
name = "Bob", | |||
id = 20000, | |||
phone = [ | |||
#phoneNumber{number = #test{aa = "01234567890"} , type = 3 } | |||
] | |||
} | |||
] | |||
}, | |||
%"others" => [ | |||
% #{ | |||
% "name" => "Carol", | |||
% "id" => 30000, | |||
% "phone" => [ | |||
% #{ "number" => #{"aa" => "9876543210"} } | |||
% ] | |||
% } | |||
%] | |||
%AddressBook = #person{name = "1232134", id = 11111,email = "aaa" ,phone = [#phoneNumber{}] }, | |||
%AddressBook = #phoneNumber{number =#test{aa = "dffsaf"},type = 12 }, | |||
Bin = protoMsg:encode(AddressBook), | |||
%ok = file:write_file("fff.bin", Bin), | |||
%print_bin(Bin), | |||
tt(N, iolist_to_binary(Bin)). | |||
tt(0, Bin) -> | |||
protoMsg:decode(Bin); | |||
tt(N, Bin) -> | |||
protoMsg:decode(Bin), | |||
tt(N-1, Bin). | |||
%{Len, List, RestBin} = protoMsg("AddressBook", Bin), | |||
%io:format("Len:~p, RestBin:~p~n", [Len, RestBin]), | |||
%io:format("List:~p~n", [List]), | |||
%{Map, _, _} = sproto:decode2("AddressBook", Bin), | |||
%Map. | |||
ttt1(0)-> | |||
AddressBook = #addressBook{ | |||
person = [ | |||
#person{ | |||
name = "Alice", | |||
id = 10000, | |||
phone = [ | |||
#phoneNumber{ number = #test{aa = "你好啊 嘿嘿"} , type = 1 }, | |||
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 } | |||
] | |||
}, | |||
#person{ | |||
name = "Bob", | |||
id = 20000, | |||
phone = [ | |||
#phoneNumber{number = #test{aa = "范德萨地方范德萨发"} , type = 3 } | |||
] | |||
} | |||
] | |||
}, | |||
term_to_binary(AddressBook); | |||
ttt1(N) -> | |||
ttt1(), | |||
ttt1(N- 1). | |||
ttt1() -> | |||
AddressBook = #addressBook{ | |||
person = [ | |||
#person{ | |||
name = "Alice", | |||
id = 10000, | |||
phone = [ | |||
#phoneNumber{ number = #test{aa = "你好啊 嘿嘿"} , type = 1 }, | |||
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 } | |||
] | |||
}, | |||
#person{ | |||
name = "Bob", | |||
id = 20000, | |||
phone = [ | |||
#phoneNumber{number = #test{aa = "范德萨地方范德萨发"} , type = 3 } | |||
] | |||
} | |||
] | |||
}, | |||
%"others" => [ | |||
% #{ | |||
% "name" => "Carol", | |||
% "id" => 30000, | |||
% "phone" => [ | |||
% #{ "number" => #{"aa" => "9876543210"} } | |||
% ] | |||
% } | |||
%] | |||
%AddressBook = #person{name = "1232134", id = 11111,email = "aaa" ,phone = [#phoneNumber{}] }, | |||
%AddressBook = #phoneNumber{number =#test{aa = "dffsaf"},type = 12 }, | |||
Bin = term_to_binary(AddressBook). | |||
%ok = file:write_file("fff.bin", Bin), | |||
%print_bin(Bin), | |||
%Bin = protoCode:encode(AddressBook), | |||
%ok = file:write_file("fff.bin", Bin), | |||
%print_bin(Bin), | |||
%MsgId = protoMsg:getMsgId(element(1, AddressBook)), | |||
%<<MsgId:16/little, Bin/binary>>. | |||
ttt(N) -> | |||
AddressBook = #addressBook{ | |||
person = [ | |||
#person{ | |||
name = "Alice", | |||
id = 10000, | |||
phone = [ | |||
#phoneNumber{ number = #test{aa = "123456789"} , type = 1 }, | |||
#phoneNumber{ number = #test{aa = "87654321"} , type = 2 } | |||
] | |||
}, | |||
#person{ | |||
name = "Bob", | |||
id = 20000, | |||
phone = [ | |||
#phoneNumber{number = #test{aa = "01234567890"} , type = 3 } | |||
] | |||
} | |||
] | |||
}, | |||
%"others" => [ | |||
% #{ | |||
% "name" => "Carol", | |||
% "id" => 30000, | |||
% "phone" => [ | |||
% #{ "number" => #{"aa" => "9876543210"} } | |||
% ] | |||
% } | |||
%] | |||
%AddressBook = #person{name = "1232134", id = 11111,email = "aaa" ,phone = [#phoneNumber{}] }, | |||
%AddressBook = #phoneNumber{number =#test{aa = "dffsaf"},type = 12 }, | |||
%ok = file:write_file("fff.bin", Bin), | |||
%print_bin(Bin), | |||
ttt(N, term_to_binary(AddressBook)). | |||
ttt(0, Bin) -> | |||
binary_to_term(Bin); | |||
ttt(N, Bin) -> | |||
binary_to_term(Bin), | |||
ttt(N-1, Bin). | |||
print_bin(Bin) -> | |||
ByteList = lists:reverse(bin_to_hex(Bin, [])), | |||
Fun = fun(Byte, Acc) -> | |||
io:format("~2.16.0b ", [Byte]), | |||
case Acc rem 8 =:= 0 of | |||
true -> io:format("~n", []); | |||
false -> ok | |||
end, | |||
Acc + 1 | |||
end, | |||
lists:foldl(Fun, 1, ByteList), | |||
io:format("bytes:~p~n", [byte_size(Bin)]). | |||
bin_to_hex(<<>>, Acc) -> | |||
Acc; | |||
bin_to_hex(Bin, Acc) -> | |||
<<A:8, Bin2/binary>> = Bin, | |||
bin_to_hex(Bin2, [A|Acc]). |