/echubby/deps/protobuffs/ebin/enum_pb.erl
http://erlang-lab.googlecode.com/ · Erlang · 148 lines · 127 code · 21 blank · 0 comment · 0 complexity · b02d4b429425dd9904eeb46fe635c263 MD5 · raw file
- -file("src/enum_pb.erl", 1).
- -module(enum_pb).
- -export([encode_enummsg/1, decode_enummsg/1]).
- -export([encode/1, decode/2, iolist/2]).
- -record(enummsg, {value}).
- encode(Record) -> encode(element(1, Record), Record).
- encode_enummsg(Record)
- when is_record(Record, enummsg) ->
- encode(enummsg, Record).
- encode(enummsg, Record) ->
- iolist_to_binary(iolist(enummsg, Record)).
- iolist(enummsg, Record) ->
- [pack(1, optional,
- with_default(Record#enummsg.value, none),
- enummsg_values, [])].
- with_default(undefined, none) -> undefined;
- with_default(undefined, Default) -> Default;
- with_default(Val, _) -> Val.
- pack(_, optional, undefined, _, _) -> [];
- pack(_, repeated, undefined, _, _) -> [];
- pack(_, repeated_packed, undefined, _, _) -> [];
- pack(_, repeated_packed, [], _, _) -> [];
- pack(FNum, required, undefined, Type, _) ->
- exit({error,
- {required_field_is_undefined, FNum, Type}});
- pack(_, repeated, [], _, Acc) -> lists:reverse(Acc);
- pack(FNum, repeated, [Head | Tail], Type, Acc) ->
- pack(FNum, repeated, Tail, Type,
- [pack(FNum, optional, Head, Type, []) | Acc]);
- pack(FNum, repeated_packed, Data, Type, _) ->
- protobuffs:encode_packed(FNum, Data, Type);
- pack(FNum, _, Data, _, _) when is_tuple(Data) ->
- [RecName | _] = tuple_to_list(Data),
- protobuffs:encode(FNum, encode(RecName, Data), bytes);
- pack(FNum, _, Data, Type, _)
- when Type =:= bool;
- Type =:= int32;
- Type =:= uint32;
- Type =:= int64;
- Type =:= uint64;
- Type =:= sint32;
- Type =:= sint64;
- Type =:= fixed32;
- Type =:= sfixed32;
- Type =:= fixed64;
- Type =:= sfixed64;
- Type =:= string;
- Type =:= bytes;
- Type =:= float;
- Type =:= double ->
- protobuffs:encode(FNum, Data, Type);
- pack(FNum, _, Data, Type, _) when is_atom(Data) ->
- protobuffs:encode(FNum, enum_to_int(Type, Data), enum).
- enum_to_int(enummsg_values, value2) -> 2;
- enum_to_int(enummsg_values, value1) -> 1.
- int_to_enum(enummsg_values, 2) -> value2;
- int_to_enum(enummsg_values, 1) -> value1;
- int_to_enum(_, Val) -> Val.
- decode_enummsg(Bytes) when is_binary(Bytes) ->
- decode(enummsg, Bytes).
- decode(enummsg_values, 1) -> value1;
- decode(enummsg, Bytes) when is_binary(Bytes) ->
- Types = [{1, value, enummsg_values, []}],
- Decoded = decode(Bytes, Types, []),
- to_record(enummsg, Decoded).
- decode(<<>>, _, Acc) -> Acc;
- decode(Bytes, Types, Acc) ->
- {ok, FNum} = protobuffs:next_field_num(Bytes),
- case lists:keysearch(FNum, 1, Types) of
- {value, {FNum, Name, Type, Opts}} ->
- {Value1, Rest1} = case lists:member(is_record, Opts) of
- true ->
- {{FNum, V}, R} = protobuffs:decode(Bytes,
- bytes),
- RecVal =
- decode(list_to_atom(string:to_lower(atom_to_list(Type))),
- V),
- {RecVal, R};
- false ->
- case lists:member(repeated_packed, Opts) of
- true ->
- {{FNum, V}, R} =
- protobuffs:decode_packed(Bytes,
- Type),
- {V, R};
- false ->
- {{FNum, V}, R} =
- protobuffs:decode(Bytes, Type),
- {unpack_value(V, Type), R}
- end
- end,
- case lists:member(repeated, Opts) of
- true ->
- case lists:keytake(FNum, 1, Acc) of
- {value, {FNum, Name, List}, Acc1} ->
- decode(Rest1, Types,
- [{FNum, Name,
- lists:reverse([int_to_enum(Type, Value1)
- | lists:reverse(List)])}
- | Acc1]);
- false ->
- decode(Rest1, Types,
- [{FNum, Name, [int_to_enum(Type, Value1)]} | Acc])
- end;
- false ->
- decode(Rest1, Types,
- [{FNum, Name, int_to_enum(Type, Value1)} | Acc])
- end;
- false -> exit({error, {unexpected_field_index, FNum}})
- end.
- unpack_value(Binary, string) when is_binary(Binary) ->
- binary_to_list(Binary);
- unpack_value(Value, _) -> Value.
- to_record(enummsg, DecodedTuples) ->
- lists:foldl(fun ({_FNum, Name, Val}, Record) ->
- set_record_field(record_info(fields, enummsg), Record,
- Name, Val)
- end,
- #enummsg{}, DecodedTuples).
- set_record_field(Fields, Record, Field, Value) ->
- Index = list_index(Field, Fields),
- erlang:setelement(Index + 1, Record, Value).
- list_index(Target, List) -> list_index(Target, List, 1).
- list_index(Target, [Target | _], Index) -> Index;
- list_index(Target, [_ | Tail], Index) ->
- list_index(Target, Tail, Index + 1);
- list_index(_, [], _) -> 0.