Skip to content

Commit

Permalink
Merge branch 'oneof'
Browse files Browse the repository at this point in the history
  • Loading branch information
tomas-abrahamsson committed Oct 24, 2014
2 parents 6600093 + 48f866c commit 217d3a5
Show file tree
Hide file tree
Showing 11 changed files with 1,252 additions and 311 deletions.
3 changes: 3 additions & 0 deletions README.md
Expand Up @@ -21,6 +21,7 @@ Features of gpb
- the 'packed' and 'default' options
- generating metadata information
- package namespacing (optional)
- oneof

gpb reads but ignores or throws away:
- options other than 'packed' or 'default'
Expand Down Expand Up @@ -188,6 +189,8 @@ Mapping of protocol buffer datatypes to erlang
string unicode string, thus list of integers
----------------------------------------------------------------
bytes binary
----------------------------------------------------------------
oneof {ChosenFieldName, Value}


Interaction with rebar
Expand Down
46 changes: 37 additions & 9 deletions descr_src/gpb_compile_descr.erl
Expand Up @@ -52,6 +52,10 @@ defs_to_descr_2(Name, Defs) ->
source_code_info = undefined %% #'SourceCodeInfo'{} | undefined
}.

get_all_oneofs(Defs) ->
lists:flatten([[Name || #gpb_oneof{name=Name} <- Fields]
|| {{msg,_}, Fields} <- Defs]).

defs_to_package(Defs) ->
%% There can be at most 1 package definition
%% The parser will reject any multiple package definitions
Expand All @@ -61,6 +65,7 @@ defs_to_package(Defs) ->
end.

defs_to_msgtype(Defs) ->
AllOneofs = get_all_oneofs(Defs),
%% There is a slight bit of mismatch here: the DescriptorProto
%% contains fields for `nested_type' and `enum_type', and defines
%% a name resolution scheme, but the gpb parser already un-nests,
Expand All @@ -71,29 +76,49 @@ defs_to_msgtype(Defs) ->
%% save also the unprocessed parse results.
[#'DescriptorProto'{
name = atom_to_ustring(MsgName),
field = field_defs_to_mgstype_fields(Fields),
field = field_defs_to_mgstype_fields(Fields, AllOneofs),
extension = [],
nested_type = [],
enum_type = [],
extension_range = [],
options = undefined
options = undefined,
oneof_decl = oneof_decl(AllOneofs)
}
|| {{msg,MsgName}, Fields} <- Defs].

field_defs_to_mgstype_fields(Fields) ->
field_defs_to_mgstype_fields(Fields, AllOneofs) ->
lists:append([field_def_to_msgtype_field(Field, AllOneofs)
|| Field <- Fields]).

field_def_to_msgtype_field(#?gpb_field{name=FName,
fnum=FNum,
type=Type,
occurrence=Occurrence,
opts=Opts}=Field,
_AllOneofs) ->
[#'FieldDescriptorProto'{
name = atom_to_ustring(FName),
number = FNum,
label = occurrence_def_to_descr_label(Occurrence),
type = type_to_descr_type(Type),
type_name = type_to_descr_type_name(Type),
default_value = field_default_value(Field),
options = field_options(Opts)}
|| #?gpb_field{name=FName,
fnum=FNum,
type=Type,
occurrence=Occurrence,
opts=Opts}=Field <- Fields].
options = field_options(Opts)}];
field_def_to_msgtype_field(#gpb_oneof{name=FName,
fields=OFields},
AllOneofs) ->
OneofIndex = find_oneof_index(FName, AllOneofs),
[begin
[F] = field_def_to_msgtype_field(OField, AllOneofs),
F#'FieldDescriptorProto'{oneof_index = OneofIndex}
end
|| OField <- OFields].

find_oneof_index(Name, Names) ->
find_pos(Name, Names, 0).

find_pos(Name, [Name | _], Pos) -> Pos;
find_pos(Name, [_ | Rest], Pos) -> find_pos(Name, Rest, Pos+1).

occurrence_def_to_descr_label(optional) -> 'LABEL_OPTIONAL';
occurrence_def_to_descr_label(required) -> 'LABEL_REQUIRED';
Expand Down Expand Up @@ -178,6 +203,9 @@ defs_to_service(Defs) ->
output=Output} <- Rpcs]}
|| {{service, ServiceName}, Rpcs} <- Defs].

oneof_decl(AllOneofs) ->
[#'OneofDescriptorProto'{name=atom_to_ustring(Name)} || Name <- AllOneofs].

atom_to_ustring(A) ->
Utf8Str = atom_to_list(A),
unicode:characters_to_list(list_to_binary(Utf8Str), utf8).
Expand Down

0 comments on commit 217d3a5

Please sign in to comment.