Skip to content

Commit

Permalink
Merge pull request #12 from bucko909/list-list
Browse files Browse the repository at this point in the history
Decode List(Text) encoded by other tools
  • Loading branch information
bucko909 authored Apr 12, 2021
2 parents e0043e4 + a82dfd9 commit 923cb5f
Show file tree
Hide file tree
Showing 3 changed files with 296 additions and 218 deletions.
50 changes: 38 additions & 12 deletions src/capnp_compile.erl
Original file line number Diff line number Diff line change
Expand Up @@ -531,23 +531,49 @@ generate_follow_struct_list_pointer() ->
{ [], ast_follow_struct_list_pointer(), [generate_decode_far_pointer] }.

-ast_forms_function(#{name => ast_follow_struct_list_pointer}).
follow_tagged_struct_list_pointer(_DecodeFun, 0, _MessageRef) ->
follow_struct_list_pointer(_DecodeFun, 0, _MessageRef) ->
undefined;
follow_tagged_struct_list_pointer(DecodeFun, PointerInt, MessageRef) when PointerInt band 3 == 1 ->
follow_struct_list_pointer(DecodeFun, PointerInt, MessageRef)
when PointerInt band 3 == 1 andalso (PointerInt bsr 32) band 7 >= 5 ->
PointerOffset = case PointerInt band (1 bsl 31) of
0 -> ((PointerInt bsr 2) band (1 bsl 30 - 1)) + 1;
_ -> ((PointerInt bsr 2) band (1 bsl 30 - 1)) - (1 bsl 30) + 1
end,
LengthFromPointer = (PointerInt bsr 35) band (1 bsl 29 - 1),
NewOffset = MessageRef#message_ref.current_offset + PointerOffset,
SkipBits = NewOffset bsl 6,
<<_:SkipBits, Tag:64/little-unsigned-integer, _/binary>> = MessageRef#message_ref.current_segment,
Length = ((Tag bsr 2) band (1 bsl 30 - 1)),
DWords = (Tag bsr 32) band (1 bsl 16 - 1),
PWords = (Tag bsr 48) band (1 bsl 16 - 1),
decode_struct_list(DecodeFun, Length, DWords, PWords, MessageRef#message_ref{current_offset=NewOffset+1});
follow_tagged_struct_list_pointer(DecodeFun, PointerInt, MessageRef=#message_ref{}) when PointerInt band 3 == 2 ->
case (PointerInt bsr 32) band 7 of
5 ->
% Pointer to a list of primitive words. Treat like a list of
% structs with a single data word.
Length = LengthFromPointer,
DWords = 1,
PWords = 0,
ListStartOffset = NewOffset;
6 ->
% Pointer to a list of pointers. Treat like a list of structs
% with a single pointer word.
Length = LengthFromPointer,
DWords = 0,
PWords = 1,
ListStartOffset = NewOffset;
7 ->
% Tagged struct list. Decode the tag.
SkipBits = NewOffset bsl 6,
<<_:SkipBits, Tag:64/little-unsigned-integer, _/binary>> = MessageRef#message_ref.current_segment,
0 = (Tag band 3), % Sanity check.
Length = ((Tag bsr 2) band (1 bsl 30 - 1)),
DWords = (Tag bsr 32) band (1 bsl 16 - 1),
PWords = (Tag bsr 48) band (1 bsl 16 - 1),
LengthFromPointer = Length * (DWords + PWords), % Sanity check
ListStartOffset = NewOffset + 1
end,
decode_struct_list(DecodeFun, Length, DWords, PWords, MessageRef#message_ref{current_offset=ListStartOffset});
follow_struct_list_pointer(_DecodeFun, PointerInt, _MessageRef)
when PointerInt band 3 == 1 andalso (PointerInt bsr 32) band 7 < 5 ->
erlang:error({not_supported, "cannot currently decode List(struct {}) which is stored as a list of subword values"});
follow_struct_list_pointer(DecodeFun, PointerInt, MessageRef=#message_ref{}) when PointerInt band 3 == 2 ->
{NewPointerInt, NewMessageRef} = decode_far_pointer(PointerInt, MessageRef),
follow_tagged_struct_list_pointer(DecodeFun, NewPointerInt, NewMessageRef).
follow_struct_list_pointer(DecodeFun, NewPointerInt, NewMessageRef).

decode_struct_list(DecodeFun, Length, DWords, PWords, MessageRef) ->
Offset = MessageRef#message_ref.current_offset,
Expand Down Expand Up @@ -1266,14 +1292,14 @@ decoder(#ptr_type{type=struct, extra={TypeName, _, _}}, undefined, Var, Line, Me
ast(follow_struct_pointer(quote(Decoder), quote(Var), quote(MessageRef)));
decoder(#ptr_type{type=list, extra=#ptr_type{type=struct, extra={TypeName, _, _}}}, undefined, Var, Line, MessageRef, _Schema) ->
Decoder = {'fun', Line, {function, to_atom(append("internal_decode_", TypeName)), 3}},
ast(follow_tagged_struct_list_pointer(quote(Decoder), quote(Var), quote(MessageRef)));
ast(follow_struct_list_pointer(quote(Decoder), quote(Var), quote(MessageRef)));
decoder(#ptr_type{type=list, extra=#native_type{name=Name}}, undefined, Var, Line, MessageRef, _Schema) ->
Decoder = make_atom(Line, append("follow_", append(Name, "_list_pointer"))),
ast((quote(Decoder))(quote(Var), quote(MessageRef)));
decoder(#ptr_type{type=list, extra=#ptr_type{type=text_or_data, extra=TextType}}, undefined, Var, Line, MessageRef, _Schema) ->
DecoderName = to_atom(append("internal_decode_", TextType)),
Decoder = {'fun', Line, {function, DecoderName, 3}},
ast(follow_tagged_struct_list_pointer(quote(Decoder), quote(Var), quote(MessageRef)));
ast(follow_struct_list_pointer(quote(Decoder), quote(Var), quote(MessageRef)));
decoder(#ptr_type{type=text_or_data, extra=text}, undefined, Var, _Line, MessageRef, _Schema) ->
ast(follow_text_pointer(quote(Var), quote(MessageRef)));
decoder(#ptr_type{type=text_or_data, extra=data}, undefined, Var, _Line, MessageRef, _Schema) ->
Expand Down
Loading

0 comments on commit 923cb5f

Please sign in to comment.