erlang自定义二进制协议
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

285 行
10 KiB

  1. -module(protoMsg).
  2. -export([encode/1, decode/1, encodeRec/1, decodeRec/2]).
  3. -define(bool(V), (case V of true -> <<1:8>>; _ -> <<0:8>> end)).
  4. -define(int8(V), <<V:8>>).
  5. -define(uint8(V), <<V:8>>).
  6. -define(int16(V), <<V:16/big>>).
  7. -define(uint16(V), <<V:16/big>>).
  8. -define(int32(V), <<V:32/big>>).
  9. -define(uint32(V), <<V:32/big>>).
  10. -define(int64(V), <<V:64/big>>).
  11. -define(uint64(V), <<V:64/big>>).
  12. -define(float(V), <<V:32/big-float>>).
  13. -define(double(V), <<V:64/big-float>>).
  14. -define(string(V), (string(V))).
  15. -define(record(V), (case V of undefined -> [<<0:8>>]; V -> [<<1:8>>, encodeRec(V)] end)).
  16. -define(list_bool(List), [<<(length(List)):16/big>>, [?bool(V) || V <- List]]).
  17. -define(list_int8(List), [<<(length(List)):16/big>>, [?int8(V) || V <- List]]).
  18. -define(list_uint8(List), [<<(length(List)):16/big>>, [?uint8(V) || V <- List]]).
  19. -define(list_int16(List), [<<(length(List)):16/big>>, [?int16(V) || V <- List]]).
  20. -define(list_uint16(List), [<<(length(List)):16/big>>, [?uint16(V) || V <- List]]).
  21. -define(list_int32(List), [<<(length(List)):16/big>>, [?int32(V) || V <- List]]).
  22. -define(list_uint32(List), [<<(length(List)):16/big>>, [?uint32(V) || V <- List]]).
  23. -define(list_int64(List), [<<(length(List)):16/big>>, [?int64(V) || V <- List]]).
  24. -define(list_uint64(List), [<<(length(List)):16/big>>, [?uint64(V) || V <- List]]).
  25. -define(list_float(List), [<<(length(List)):16/big>>, [?float(V) || V <- List]]).
  26. -define(list_double(List), [<<(length(List)):16/big>>, [?double(V) || V <- List]]).
  27. -define(list_string(List), [<<(length(List)):16/big>>, [string(V) || V <- List]]).
  28. -define(list_record(List), [<<(length(List)):16/big>>, [encodeRec(V) || V <- List]]).
  29. string(Str) when is_binary(Str) ->
  30. [<<(byte_size(Str)):16/big>>, Str];
  31. string(Str) ->
  32. Str2 = unicode:characters_to_binary(Str, utf8),
  33. [<<(byte_size(Str2)):16/big>>, Str2].
  34. encode(Record) ->
  35. MsgBin = encodeRec(Record),
  36. MsgId = getMsgId(element(1, Record)),
  37. [<<MsgId:16/big>>, MsgBin].
  38. decode(Bin) ->
  39. <<MsgId:16/big, MsgBin/binary>> = Bin,
  40. SchList = getMsgSchema(MsgId),
  41. {<<>>, ResultList} = decodeField(SchList, MsgBin, [getMsgType(MsgId)]),
  42. list_to_tuple(ResultList).
  43. decodeRec(RecordName, Bin) ->
  44. SchList = getMsgSchema(RecordName),
  45. {LeftBin, Result} = decodeField(SchList, Bin, [RecordName]),
  46. {LeftBin, list_to_tuple(Result)}.
  47. decodeField([], LeftBin, Result) ->
  48. {LeftBin, lists:reverse(Result)};
  49. decodeField([Type | SchList], MsgBin, Result) ->
  50. case Type of
  51. int32 ->
  52. <<Int:32/big-signed, LeftBin/binary>> = MsgBin,
  53. decodeField(SchList, LeftBin, [Int | Result]);
  54. uint32 ->
  55. <<Int:32/big-unsigned, LeftBin/binary>> = MsgBin,
  56. decodeField(SchList, LeftBin, [Int | Result]);
  57. string ->
  58. <<Len:16/big, StrBin:Len/binary, LeftBin/binary>> = MsgBin,
  59. decodeField(SchList, LeftBin, [StrBin | Result]);
  60. int16 ->
  61. <<Int:16/big-signed, LeftBin/binary>> = MsgBin,
  62. decodeField(SchList, LeftBin, [Int | Result]);
  63. uint16 ->
  64. <<Int:16/big-unsigned, LeftBin/binary>> = MsgBin,
  65. decodeField(SchList, LeftBin, [Int | Result]);
  66. int8 ->
  67. <<Int:8/big-signed, LeftBin/binary>> = MsgBin,
  68. decodeField(SchList, LeftBin, [Int | Result]);
  69. uint8 ->
  70. <<Int:8/big-unsigned, LeftBin/binary>> = MsgBin,
  71. decodeField(SchList, LeftBin, [Int | Result]);
  72. int64 ->
  73. <<Int:64/big-signed, LeftBin/binary>> = MsgBin,
  74. decodeField(SchList, LeftBin, [Int | Result]);
  75. uint64 ->
  76. <<Int:64/big-unsigned, LeftBin/binary>> = MsgBin,
  77. decodeField(SchList, LeftBin, [Int | Result]);
  78. bool ->
  79. <<Bool:8/big-unsigned, LeftBin/binary>> = MsgBin,
  80. case Bool =:= 1 of
  81. true ->
  82. decodeField(SchList, LeftBin, [true | Result]);
  83. _ ->
  84. decodeField(SchList, LeftBin, [false | Result])
  85. end;
  86. falat ->
  87. <<Float:32/big-float, LeftBin/binary>> = MsgBin,
  88. decodeField(SchList, LeftBin, [Float | Result]);
  89. double ->
  90. <<Float:64/big-float, LeftBin/binary>> = MsgBin,
  91. decodeField(SchList, LeftBin, [Float | Result]);
  92. {list, int32} ->
  93. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  94. {LeftBin, RetList} = deInt32List(Len, LeftListBin, []),
  95. decodeField(SchList, LeftBin, [RetList | Result]);
  96. {list, uint32} ->
  97. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  98. {LeftBin, RetList} = deUint32List(Len, LeftListBin, []),
  99. decodeField(SchList, LeftBin, [RetList | Result]);
  100. {list, int16} ->
  101. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  102. {LeftBin, RetList} = deInt16List(Len, LeftListBin, []),
  103. decodeField(SchList, LeftBin, [RetList | Result]);
  104. {list, uint16} ->
  105. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  106. {LeftBin, RetList} = deUint16List(Len, LeftListBin, []),
  107. decodeField(SchList, LeftBin, [RetList | Result]);
  108. {list, int8} ->
  109. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  110. {LeftBin, RetList} = deInt8List(Len, LeftListBin, []),
  111. decodeField(SchList, LeftBin, [RetList | Result]);
  112. {list, uint8} ->
  113. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  114. {LeftBin, RetList} = deUint8List(Len, LeftListBin, []),
  115. decodeField(SchList, LeftBin, [RetList | Result]);
  116. {list, string} ->
  117. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  118. {LeftBin, RetList} = deStringList(Len, LeftListBin, []),
  119. decodeField(SchList, LeftBin, [RetList | Result]);
  120. {list, int64} ->
  121. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  122. {LeftBin, RetList} = deInt64List(Len, LeftListBin, []),
  123. decodeField(SchList, LeftBin, [RetList | Result]);
  124. {list, uint64} ->
  125. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  126. {LeftBin, RetList} = deUint64List(Len, LeftListBin, []),
  127. decodeField(SchList, LeftBin, [RetList | Result]);
  128. {list, bool} ->
  129. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  130. {LeftBin, RetList} = deBoolList(Len, LeftListBin, []),
  131. decodeField(SchList, LeftBin, [RetList | Result]);
  132. {list, flat} ->
  133. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  134. {LeftBin, RetList} = deFloatList(Len, LeftListBin, []),
  135. decodeField(SchList, LeftBin, [RetList | Result]);
  136. {list, double} ->
  137. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  138. {LeftBin, RetList} = deDoubleList(Len, LeftListBin, []),
  139. decodeField(SchList, LeftBin, [RetList | Result]);
  140. {list, RecordName} ->
  141. <<Len:16/big, LeftListBin/binary>> = MsgBin,
  142. {LeftBin, RetList} = deRecordList(Len, RecordName, LeftListBin, []),
  143. decodeField(SchList, LeftBin, [RetList | Result]);
  144. RecordName ->
  145. <<IsUndef:8, LeftBin/binary>> = MsgBin,
  146. case IsUndef of
  147. 0 ->
  148. decodeField(SchList, LeftBin, [undefined | Result]);
  149. _ ->
  150. SubSchList = getMsgSchema(RecordName),
  151. {SubLeftBin, SubResultList} = decodeField(SubSchList, LeftBin, [RecordName]),
  152. decodeField(SchList, SubLeftBin, [list_to_tuple(SubResultList) | Result])
  153. end
  154. end.
  155. deBoolList(0, MsgBin, RetList) ->
  156. {MsgBin, lists:reverse(RetList)};
  157. deBoolList(N, <<Bool:8, LeftBin/binary>>, RetList) ->
  158. case Bool =:= 1 of
  159. true ->
  160. deBoolList(N - 1, LeftBin, [true | RetList]);
  161. _ ->
  162. deBoolList(N - 1, LeftBin, [false | RetList])
  163. end.
  164. deInt8List(0, MsgBin, RetList) ->
  165. {MsgBin, RetList};
  166. deInt8List(N, <<Int:8/big-signed, LeftBin/binary>>, RetList) ->
  167. deInt8List(N - 1, LeftBin, [Int | RetList]).
  168. deUint8List(0, MsgBin, RetList) ->
  169. {MsgBin, lists:reverse(RetList)};
  170. deUint8List(N, <<Int:8/big-unsigned, LeftBin/binary>>, RetList) ->
  171. deUint8List(N - 1, LeftBin, [Int | RetList]).
  172. deInt16List(0, MsgBin, RetList) ->
  173. {MsgBin, lists:reverse(RetList)};
  174. deInt16List(N, <<Int:16/big-signed, LeftBin/binary>>, RetList) ->
  175. deInt16List(N - 1, LeftBin, [Int | RetList]).
  176. deUint16List(0, MsgBin, RetList) ->
  177. {MsgBin, lists:reverse(RetList)};
  178. deUint16List(N, <<Int:16/big-unsigned, LeftBin/binary>>, RetList) ->
  179. deUint16List(N - 1, LeftBin, [Int | RetList]).
  180. deInt32List(0, MsgBin, RetList) ->
  181. {MsgBin, lists:reverse(RetList)};
  182. deInt32List(N, <<Int:32/big-signed, LeftBin/binary>>, RetList) ->
  183. deInt32List(N - 1, LeftBin, [Int | RetList]).
  184. deUint32List(0, MsgBin, RetList) ->
  185. {MsgBin, lists:reverse(RetList)};
  186. deUint32List(N, <<Int:32/big-unsigned, LeftBin/binary>>, RetList) ->
  187. deUint32List(N - 1, LeftBin, [Int | RetList]).
  188. deInt64List(0, MsgBin, RetList) ->
  189. {MsgBin, lists:reverse(RetList)};
  190. deInt64List(N, <<Int:64/big-signed, LeftBin/binary>>, RetList) ->
  191. deInt64List(N - 1, LeftBin, [Int | RetList]).
  192. deUint64List(0, MsgBin, RetList) ->
  193. {MsgBin, lists:reverse(RetList)};
  194. deUint64List(N, <<Int:64/big-unsigned, LeftBin/binary>>, RetList) ->
  195. deUint64List(N - 1, LeftBin, [Int | RetList]).
  196. deFloatList(0, MsgBin, RetList) ->
  197. {MsgBin, lists:reverse(RetList)};
  198. deFloatList(N, <<Float:32/big-float, LeftBin/binary>>, RetList) ->
  199. deFloatList(N - 1, LeftBin, [Float | RetList]).
  200. deDoubleList(0, MsgBin, RetList) ->
  201. {MsgBin, lists:reverse(RetList)};
  202. deDoubleList(N, <<Float:64/big-float, LeftBin/binary>>, RetList) ->
  203. deDoubleList(N - 1, LeftBin, [Float | RetList]).
  204. deStringList(0, MsgBin, RetList) ->
  205. {MsgBin, lists:reverse(RetList)};
  206. deStringList(N, <<Len:16/big, StrBin:Len/binary-unit:8, LeftBin/binary>>, RetList) ->
  207. deStringList(N - 1, LeftBin, [StrBin | RetList]).
  208. deRecordList(0, _RecordName, MsgBin, RetList) ->
  209. {MsgBin, lists:reverse(RetList)};
  210. deRecordList(N, RecordName, MsgBin, RetList) ->
  211. {LeftBin, Tuple} = decodeRec(RecordName, MsgBin),
  212. deRecordList(N - 1, RecordName, LeftBin, [Tuple | RetList]).
  213. getMsgType(1)->
  214. test;
  215. getMsgType(2)->
  216. phoneNumber;
  217. getMsgType(3)->
  218. person;
  219. getMsgType(4)->
  220. addressBook;
  221. getMsgType(_) ->
  222. undefined.
  223. getMsgId(test)->
  224. 1;
  225. getMsgId(phoneNumber)->
  226. 2;
  227. getMsgId(person)->
  228. 3;
  229. getMsgId(addressBook)->
  230. 4;
  231. getMsgId(_) ->
  232. 0.
  233. encodeRec({test, V1}) ->
  234. [?string(V1)];
  235. encodeRec({phoneNumber, V1, V2}) ->
  236. [?record(V1), ?int32(V2)];
  237. encodeRec({person, V1, V2, V3, V4}) ->
  238. [?string(V1), ?int32(V2), ?string(V3), ?list_record(V4)];
  239. encodeRec({addressBook, V1, V2}) ->
  240. [?list_record(V1), ?list_record(V2)];
  241. encodeRec(_) ->
  242. [].
  243. getMsgSchema(test)->
  244. getMsgSchema(1);
  245. getMsgSchema(1)->
  246. [string];
  247. getMsgSchema(phoneNumber)->
  248. getMsgSchema(2);
  249. getMsgSchema(2)->
  250. [test,int32];
  251. getMsgSchema(person)->
  252. getMsgSchema(3);
  253. getMsgSchema(3)->
  254. [string,int32,string,{list,phoneNumber}];
  255. getMsgSchema(addressBook)->
  256. getMsgSchema(4);
  257. getMsgSchema(4)->
  258. [{list,person},{list,person}];
  259. getMsgSchema(_) ->
  260. [].