PageRenderTime 784ms CodeModel.GetById 34ms RepoModel.GetById 12ms app.codeStats 0ms

/protobuf.erl

https://code.google.com/p/protoc-gen-erl/
Erlang | 344 lines | 274 code | 22 blank | 48 comment | 2 complexity | 536498320062ca47863d6c5c57e22874 MD5 | raw file
  1. %% This file comes from http://github.com/ngerakines/erlang_protobuffs
  2. %% created by Nick Gerakines.
  3. %% I made some changes for this project
  4. %% NetSnail@gmail.com 2010
  5. %% Copyright (c) 2009
  6. %% Nick Gerakines <nick@gerakines.net>
  7. %% Jacob Vorreuter <jacob.vorreuter@gmail.com>
  8. %%
  9. %% Permission is hereby granted, free of charge, to any person
  10. %% obtaining a copy of this software and associated documentation
  11. %% files (the "Software"), to deal in the Software without
  12. %% restriction, including without limitation the rights to use,
  13. %% copy, modify, merge, publish, distribute, sublicense, and/or sell
  14. %% copies of the Software, and to permit persons to whom the
  15. %% Software is furnished to do so, subject to the following
  16. %% conditions:
  17. %%
  18. %% The above copyright notice and this permission notice shall be
  19. %% included in all copies or substantial portions of the Software.
  20. %%
  21. %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  23. %% OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  25. %% HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  26. %% WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  27. %% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  28. %% OTHER DEALINGS IN THE SOFTWARE.
  29. %%
  30. %% @doc A protcol buffers encoding and decoding module.
  31. -module(protobuf).
  32. -export([encode/3, read_field_num_and_wire_type/1, decode/2, decode_value/3]).
  33. -export([decode_loop/3, decode_loop/4, nop/2]).
  34. -export([build_extensions/1, build_extensions/2]).
  35. -export([encode_extensions/3]).
  36. -define(TYPE_VARINT, 0).
  37. -define(TYPE_64BIT, 1).
  38. -define(TYPE_STRING, 2).
  39. -define(TYPE_START_GROUP, 3).
  40. -define(TYPE_END_GROUP, 4).
  41. -define(TYPE_32BIT, 5).
  42. %% @spec encode(FieldID, Value, Type) -> Result
  43. %% FieldID = integer()
  44. %% Value = any()
  45. %% Type = bool | enum | int32 | uint32 | int64 | unit64 | sint32 | sint64 | fixed32 | sfixed32 | fixed64 | sfixed64 | string | bytes | float | double
  46. %% Result = list()
  47. %% @doc Encode an Erlang data structure into a Protocol Buffers value.
  48. encode(_FieldID, <<>>, _Type) ->
  49. <<>>;
  50. encode(_FieldID, undefined, _Type) ->
  51. <<>>;
  52. encode(FieldID, Value, Type) ->
  53. iolist_to_binary(encode_internal(FieldID, Value, Type)).
  54. build_extensions(ExtensionDesc) ->
  55. build_extensions(ExtensionDesc, []).
  56. build_extensions(ExtensionDesc, Extensions) ->
  57. [ExtensionDesc | Extensions].
  58. encode_extensions(_, undefined, _)->
  59. [];
  60. encode_extensions(_, [], _)->
  61. [];
  62. encode_extensions(MessageType, ExtensionMessages, Extensions)->
  63. ExtensionsForThis = lists:filter(fun(I)
  64. when element(1, I) =:= MessageType ->
  65. true;
  66. (_I) ->
  67. false
  68. end, Extensions),
  69. lists:map(fun({FieldID, Message})->
  70. case lists:keyfind(FieldID, 2, ExtensionsForThis) of
  71. {MessageType, FieldID, true, Type, true, _} ->
  72. [encode_internal(FieldID, M, Type) || M <- Message];
  73. {MessageType, FieldID, true, Type, false, _} ->
  74. encode_internal(FieldID, Message, Type);
  75. {MessageType, FieldID, Func, _, true, _} ->
  76. [encode_internal(FieldID, Func(M, Extensions), bytes) || M <- Message];
  77. {MessageType, FieldID, Func, _, false, _} ->
  78. encode_internal(FieldID, Func(Message, Extensions), bytes);
  79. false ->
  80. []
  81. end
  82. end, ExtensionMessages).
  83. %% @hidden
  84. encode_internal(FieldID, false, bool) ->
  85. encode_internal(FieldID, 0, int32);
  86. encode_internal(FieldID, true, bool) ->
  87. encode_internal(FieldID, 1, int32);
  88. encode_internal(FieldID, Integer, enum) ->
  89. encode_internal(FieldID, Integer, uint32);
  90. encode_internal(FieldID, Integer, int32) when Integer >= -16#80000000, Integer < 0 ->
  91. encode_internal(FieldID, Integer, int64);
  92. encode_internal(FieldID, Integer, int64) when Integer >= -16#8000000000000000, Integer < 0 ->
  93. encode_internal(FieldID, Integer + (1 bsl 64), uint64);
  94. encode_internal(FieldID, Integer, int32) when Integer >= -16#80000000, Integer =< 16#7fffffff ->
  95. encode_varint_field(FieldID, Integer);
  96. encode_internal(FieldID, Integer, uint32) when Integer band 16#ffffffff =:= Integer ->
  97. encode_varint_field(FieldID, Integer);
  98. encode_internal(FieldID, Integer, int64) when Integer >= -16#8000000000000000, Integer =< 16#7fffffffffffffff ->
  99. encode_varint_field(FieldID, Integer);
  100. encode_internal(FieldID, Integer, uint64) when Integer band 16#ffffffffffffffff =:= Integer ->
  101. encode_varint_field(FieldID, Integer);
  102. encode_internal(FieldID, Integer, bool) when Integer band 1 =:= 1 ->
  103. encode_varint_field(FieldID, Integer);
  104. encode_internal(FieldID, Integer, sint32) when Integer >= -16#80000000, Integer < 0 ->
  105. encode_varint_field(FieldID, bnot (Integer bsl 1));
  106. encode_internal(FieldID, Integer, sint64) when Integer >= -16#8000000000000000, Integer < 0 ->
  107. encode_varint_field(FieldID, bnot (Integer bsl 1));
  108. encode_internal(FieldID, Integer, sint32) when Integer >= 0, Integer =< 16#7fffffff ->
  109. encode_varint_field(FieldID, Integer bsl 1);
  110. encode_internal(FieldID, Integer, sint64) when Integer >= 0, Integer =< 16#7fffffffffffffff ->
  111. encode_varint_field(FieldID, Integer bsl 1);
  112. encode_internal(FieldID, Integer, fixed32) when Integer band 16#ffffffff =:= Integer ->
  113. [encode_field_tag(FieldID, ?TYPE_32BIT), <<Integer:32/little-integer>>];
  114. encode_internal(FieldID, Integer, sfixed32) when Integer >= -16#80000000, Integer =< 16#7fffffff ->
  115. [encode_field_tag(FieldID, ?TYPE_32BIT), <<Integer:32/little-integer>>];
  116. encode_internal(FieldID, Integer, fixed64) when Integer band 16#ffffffffffffffff =:= Integer ->
  117. [encode_field_tag(FieldID, ?TYPE_64BIT), <<Integer:64/little-integer>>];
  118. encode_internal(FieldID, Integer, sfixed64) when Integer >= -16#8000000000000000, Integer =< 16#7fffffffffffffff ->
  119. [encode_field_tag(FieldID, ?TYPE_64BIT), <<Integer:64/little-integer>>];
  120. encode_internal(FieldID, String, string) when is_list(String) ->
  121. encode_internal(FieldID, list_to_binary(String), string);
  122. encode_internal(FieldID, String, string) when is_binary(String) ->
  123. encode_internal(FieldID, String, bytes);
  124. encode_internal(FieldID, String, bytes) when is_list(String) ->
  125. encode_internal(FieldID, list_to_binary(String), bytes);
  126. encode_internal(FieldID, Bytes, bytes) when is_binary(Bytes) ->
  127. [encode_field_tag(FieldID, ?TYPE_STRING), encode_varint(size(Bytes)), Bytes];
  128. encode_internal(FieldID, String, bytes) when is_list(String) ->
  129. encode_internal(FieldID, list_to_binary(String), bytes);
  130. encode_internal(FieldID, Float, float) when is_integer(Float) ->
  131. encode_internal(FieldID, Float + 0.0, float);
  132. encode_internal(FieldID, Float, float) when is_float(Float) ->
  133. [encode_field_tag(FieldID, ?TYPE_32BIT), <<Float:32/little-float>>];
  134. encode_internal(FieldID, Float, double) when is_integer(Float) ->
  135. encode_internal(FieldID, Float + 0.0, double);
  136. encode_internal(FieldID, Float, double) when is_float(Float) ->
  137. [encode_field_tag(FieldID, ?TYPE_64BIT), <<Float:64/little-float>>].
  138. read_field_num_and_wire_type(Bytes) ->
  139. {Tag, Rest} = decode_varint(Bytes),
  140. FieldID = Tag bsr 3,
  141. WireType = Tag band 7,
  142. {{FieldID, WireType}, Rest}.
  143. %% @spec decode(Bytes, ExpectedType) -> Result
  144. %% Bytes = binary()
  145. %% ExpectedType = bool | enum | int32 | uint32 | int64 | unit64 | sint32 | sint64 | fixed32 | sfixed32 | fixed64 | sfixed64 | string | bytes | float | double
  146. %% Result = {{integer(), any()}, binary()}
  147. decode(Bytes, ExpectedType) ->
  148. {{FieldID, WireType}, Rest} = read_field_num_and_wire_type(Bytes),
  149. {Value, Rest1} = decode_value(Rest, WireType, ExpectedType),
  150. {{FieldID, Value}, Rest1}.
  151. decode_loop(Data, Record, Types) ->
  152. decode_loop(Data, Record, Types, []).
  153. decode_loop(Data, Record, Types, Extensions) ->
  154. ExtensionsForThis = lists:filter(fun(I)
  155. when element(1, I) =:= element(1, Record) ->
  156. true;
  157. (_I) ->
  158. false
  159. end, Extensions),
  160. decode_loop_message(Data, Record, Types, ExtensionsForThis, Extensions).
  161. decode_loop_message(<<>>, Record, Types, ExtensionsForThis, _Extensions) ->
  162. NewRecord = lists:foldl(fun ({_, _, FieldIndex, _, true}, R) ->
  163. case erlang:element(FieldIndex, R) of
  164. undefined ->
  165. R;
  166. L ->
  167. erlang:setelement(FieldIndex, R, lists:reverse(L))
  168. end;
  169. (_, R) ->
  170. R
  171. end, Record, Types),
  172. lists:foldl(fun({_, FieldID, _, FieldIndex, _, true}, R) ->
  173. case erlang:element(FieldIndex, R) of
  174. undefined ->
  175. R;
  176. Ext ->
  177. erlang:setelement(
  178. FieldIndex,
  179. R,
  180. lists:map(fun({ID, L}) when ID =:= FieldID -> {FieldID, lists:reverse(L)};
  181. (E) -> E
  182. end,
  183. Ext
  184. )
  185. )
  186. end;
  187. (_, R) ->
  188. R
  189. end, NewRecord, ExtensionsForThis);
  190. decode_loop_message(Data, Record, Types, ExtensionsForThis, Extensions) ->
  191. {{FieldID, WireType}, Rest1} = read_field_num_and_wire_type(Data),
  192. case lists:keyfind(FieldID, 1, Types) of
  193. {FieldID, Type, FieldIndex, Func, Repeated, _, _Default} ->
  194. {Value, Rest2} = decode_value(Rest1, WireType, Type),
  195. RealValue = Func(Value, Extensions),
  196. decode_loop_message(Rest2,
  197. erlang:setelement(FieldIndex, Record,
  198. case Repeated of
  199. true ->
  200. [RealValue | get_element_with_default(FieldIndex, Record,[])];
  201. false ->
  202. RealValue
  203. end),
  204. Types, ExtensionsForThis, Extensions);
  205. false ->
  206. case lists:keyfind(FieldID, 2, ExtensionsForThis) of
  207. {_, FieldID, Type, FieldIndex, Func, Repeated, _, _Default} ->
  208. {Value, Rest2} = decode_value(Rest1, WireType, Type),
  209. Ext = case erlang:element(FieldIndex, Record) of
  210. undefined ->
  211. [];
  212. V ->
  213. V
  214. end,
  215. RealValue = Func(Value, Extensions),
  216. decode_loop_message(Rest2, erlang:setelement(FieldIndex, Record,
  217. case lists:keyfind(FieldID, 1, Ext) of
  218. {FieldID, OldValue} ->
  219. lists:keyreplace(FieldID, 1, Ext, {FieldID,
  220. case Repeated of
  221. true ->
  222. [RealValue|OldValue];
  223. false ->
  224. RealValue
  225. end}
  226. );
  227. false ->
  228. [{FieldID,
  229. case Repeated of
  230. true ->
  231. [RealValue];
  232. false ->
  233. RealValue
  234. end}| Ext]
  235. end), Types, ExtensionsForThis, Extensions);
  236. false ->
  237. {_, Rest2} = decode_value(Rest1, WireType, bytes),
  238. decode_loop_message(Rest2, Record, Types, ExtensionsForThis, Extensions)
  239. end
  240. end.
  241. nop(Value, _) ->
  242. Value.
  243. get_element_with_default(Index, Record, Default) ->
  244. case erlang:element(Index, Record) of
  245. undefined ->
  246. Default;
  247. Value ->
  248. Value
  249. end.
  250. %% @hidden
  251. decode_value(Bytes, ?TYPE_VARINT, ExpectedType) ->
  252. {Value, Rest} = decode_varint(Bytes),
  253. {typecast(Value, ExpectedType), Rest};
  254. decode_value(Bytes, ?TYPE_STRING, string) ->
  255. {Value, Rest} = decode_value(Bytes, ?TYPE_STRING, bytes),
  256. {binary_to_list(Value), Rest};
  257. decode_value(Bytes, ?TYPE_STRING, bytes)->
  258. {Length, Rest} = decode_varint(Bytes),
  259. split_binary(Rest, Length);
  260. decode_value(<<Value:64/little-unsigned-integer, Rest/binary>>, ?TYPE_64BIT, fixed64) ->
  261. {Value, Rest};
  262. decode_value(<<Value:32/little-unsigned-integer, _:32, Rest/binary>>, ?TYPE_64BIT, fixed32) ->
  263. {Value, Rest};
  264. decode_value(<<Value:64/little-signed-integer, Rest/binary>>, ?TYPE_64BIT, sfixed64) ->
  265. {Value, Rest};
  266. decode_value(<<Value:32/little-signed-integer, _:32, Rest/binary>>, ?TYPE_64BIT, sfixed32) ->
  267. {Value, Rest};
  268. decode_value(<<Value:32/little-unsigned-integer, Rest/binary>>, ?TYPE_32BIT, Type) when Type =:= fixed32; Type =:= fixed64 ->
  269. {Value, Rest};
  270. decode_value(<<Value:32/little-signed-integer, Rest/binary>>, ?TYPE_32BIT, Type) when Type =:= sfixed32; Type =:= sfixed64 ->
  271. {Value, Rest};
  272. decode_value(<<Value:32/little-float, Rest/binary>>, ?TYPE_32BIT, float) ->
  273. {Value + 0.0, Rest};
  274. decode_value(<<Value:64/little-float, Rest/binary>>, ?TYPE_64BIT, double) ->
  275. {Value + 0.0, Rest};
  276. decode_value(_, WireType, ExpectedType) ->
  277. exit({error, {unexpected_value, WireType, ExpectedType}}).
  278. %% @hidden
  279. typecast(Value, SignedType) when SignedType =:= int32; SignedType =:= int64 ->
  280. if
  281. Value band 16#8000000000000000 =/= 0 -> Value - 16#10000000000000000;
  282. true -> Value
  283. end;
  284. typecast(Value, SignedType) when SignedType =:= sint32; SignedType =:= sint64 ->
  285. (Value bsr 1) bxor (-(Value band 1));
  286. typecast(Value, Type) when Type =:= bool ->
  287. case Value of
  288. 1 -> true;
  289. _ -> false
  290. end;
  291. typecast(Value, _) ->
  292. Value.
  293. %% @hidden
  294. encode_field_tag(FieldID, FieldType) when FieldID band 16#3fffffff =:= FieldID ->
  295. encode_varint((FieldID bsl 3) bor FieldType).
  296. %% @hidden
  297. encode_varint_field(FieldID, Integer) ->
  298. [encode_field_tag(FieldID, ?TYPE_VARINT), encode_varint(Integer)].
  299. %% @hidden
  300. encode_varint(I) ->
  301. encode_varint(I, []).
  302. %% @hidden
  303. encode_varint(I, Acc) when I =< 16#7f ->
  304. iolist_to_binary(lists:reverse([I | Acc]));
  305. encode_varint(I, Acc) ->
  306. Last_Seven_Bits = (I - ((I bsr 7) bsl 7)),
  307. First_X_Bits = (I bsr 7),
  308. With_Leading_Bit = Last_Seven_Bits bor 16#80,
  309. encode_varint(First_X_Bits, [With_Leading_Bit|Acc]).
  310. %% @hidden
  311. decode_varint(Bytes) ->
  312. decode_varint(Bytes, []).
  313. decode_varint(<<0:1, I:7, Rest/binary>>, Acc) ->
  314. Acc1 = [I|Acc],
  315. Result =
  316. lists:foldl(
  317. fun(X, Acc0) ->
  318. (Acc0 bsl 7 bor X)
  319. end, 0, Acc1),
  320. {Result, Rest};
  321. decode_varint(<<1:1, I:7, Rest/binary>>, Acc) ->
  322. decode_varint(Rest, [I | Acc]).