Skip to content

Commit 56c146a

Browse files
committed
fix some inconsistencies
support passing a schema node directly to ecapnp:{get|set}_root. treat named unions properly (being unnamed unions wrapped in a group).
1 parent 21eb203 commit 56c146a

File tree

6 files changed

+53
-16
lines changed

6 files changed

+53
-16
lines changed

priv/samples/addressbook.sh

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ read([]) ->
3636
dump_message(read_stdin()).
3737

3838
write([]) ->
39-
{ok, Root} = ecapnp:set_root('AddressBook', addressbook_capnp),
39+
{ok, Root} = ecapnp:set_root(addressbook_capnp:'AddressBook'()),
4040
[Alice, Bob, Steve] = ecapnp:set(people, 3, Root),
4141
[AlicePhone] = ecapnp:set(phones, 1, Alice),
4242
[BobPhone1, BobPhone2] = ecapnp:set(phones, 2, Bob),
@@ -91,7 +91,7 @@ dump_message(Data) ->
9191
{ok, Message, <<>>} = ecapnp_message:read(
9292
ecapnp_serialize:unpack(Data)),
9393
{ok, Root} = ecapnp:get_root(
94-
'AddressBook', addressbook_capnp, Message),
94+
addressbook_capnp:'AddressBook'(), Message),
9595
People = ecapnp:get(people, Root),
9696
[dump_person(Person) || Person <- People].
9797

@@ -103,8 +103,7 @@ dump_person(Person) ->
103103
[io:format(" ~s phone: ~s~n", [ecapnp:get(type, P),
104104
ecapnp:get(number, P)])
105105
|| P <- Phones],
106-
%% hmm... not the best looking api, this.. :/
107-
case ecapnp:get(ecapnp:get(employment, Person)) of
106+
case ecapnp:get(employment, Person) of
108107
unemployed -> io:format(" unemployed~n");
109108
{employer, Employer} ->
110109
io:format(" employer: ~s~n", [Employer]);

src/ecapnp.erl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
%% Public API
3030
%% ===================================================================
3131

32-
-export([get_root/3, get/1, get/2, set_root/2, set/2, set/3, init/2,
33-
init/3, const/2, request/2, send/1, wait/1, wait/2]).
32+
-export([get_root/2, get_root/3, get/1, get/2, set_root/1, set_root/2,
33+
set/2, set/3, init/2, init/3, const/2, request/2, send/1,
34+
wait/1, wait/2]).
3435

3536
%% ===================================================================
3637
%% Public Types
@@ -190,6 +191,9 @@
190191
get_root(Type, Schema, Segments) ->
191192
ecapnp_get:root(Type, Schema, Segments).
192193

194+
get_root(Schema, Segments) ->
195+
ecapnp_get:root(Schema, Segments).
196+
193197
-spec set_root(type_name(), schema()) -> {ok, Root::object()}.
194198
%% @doc Set the root object for a new message.
195199
%% This creates a new empty message, ready to be filled with data.
@@ -199,6 +203,9 @@ get_root(Type, Schema, Segments) ->
199203
set_root(Type, Schema) ->
200204
ecapnp_set:root(Type, Schema).
201205

206+
set_root(Schema) ->
207+
ecapnp_set:root(Schema).
208+
202209
-spec get(object()) -> {field_name(), field_value()} | field_name().
203210
%% @doc Read the unnamed union value of object.
204211
%% The result value is either a tuple, describing which union tag it

src/ecapnp_get.erl

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,21 @@ read_field(#ptr{ idx=Idx }=Ptr, #object{ ref = Ref }=Object) ->
120120
Object),
121121
read_ptr(Ptr, Obj);
122122
read_field(#group{ id=Type }, Object) ->
123-
ecapnp_obj:to_struct(Type, Object).
123+
case ecapnp_obj:to_struct(Type, Object) of
124+
#object{
125+
schema = #schema_node{
126+
kind = #struct{
127+
union_field = Union,
128+
fields = []
129+
}}}=Group
130+
when Union =/= none ->
131+
%% when we read a named union, we want to get the union
132+
%% value directly, but a named union is represented as a
133+
%% unnamed union wrapped in a group
134+
read_field(Union, Group);
135+
Group ->
136+
Group
137+
end.
124138

125139
read_ptr(#ptr{ type=Type, default=Default }, #object{ ref = Ref }=Obj) ->
126140
case Type of

src/ecapnp_set.erl

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ set_field(#ptr{ idx=Idx, type=Type, default=Default }=Ptr,
138138
{object, Value};
139139
true ->
140140
throw({error, {invalid_object_value, Value}})
141-
end,
141+
end,
142142
write_obj(ObjType, ObjValue, ecapnp_ref:ptr(Idx, StructRef), Obj)
143143
end;
144144
{struct, StructType} ->
@@ -200,7 +200,26 @@ set_field(#ptr{ idx=Idx, type=Type, default=Default }=Ptr,
200200
set_field(#group{ id=Type }, {default}, #object{ ref=StructRef }=Obj) ->
201201
ecapnp_obj:from_ref(StructRef, Type, Obj);
202202
set_field(#group{ id=Type }, Value, #object{ ref=StructRef }=Obj) ->
203-
union(Value, ecapnp_obj:from_ref(StructRef, Type, Obj)).
203+
case ecapnp_obj:from_ref(StructRef, Type, Obj) of
204+
#object{
205+
schema = #schema_node{
206+
kind = #struct{
207+
union_field = Union,
208+
fields = []
209+
}}}=Group
210+
when Union =/= none ->
211+
%% set named union (which are represented as an unnamed
212+
%% union wrapped in a group)
213+
set_field(Union, Value, Group);
214+
Group ->
215+
%% set group field (or group unnamed union)
216+
case Value of
217+
{FieldName, FieldValue} ->
218+
field(FieldName, FieldValue, Group);
219+
_ ->
220+
field(Value, Group)
221+
end
222+
end.
204223

205224
write_obj(Type, Value, Ref, Obj) when is_binary(Value) ->
206225
ecapnp_obj:from_ref(

test/ecapnp_get_tests.erl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ check_default_values(Msg) ->
4646
?assertEqual(33, ecapnp:get(intField, Root)),
4747
?assertEqual(<<"test">>, ecapnp:get(textField, Root)),
4848
?assertEqual({boolField, false}, ecapnp:get(Root)),
49-
Grp = ecapnp:get(opts, Root),
50-
?assertEqual({bool, true}, ecapnp:get(Grp)),
49+
?assertEqual({bool, true}, ecapnp:get(opts, Root)),
5150
Meta = ecapnp:get(meta, Root),
5251
?assertEqual(0, ecapnp:get(id, Meta)),
5352
?assertEqual(<<>>, ecapnp:get(tag, Meta)),
@@ -105,8 +104,7 @@ field_values_test() ->
105104
?assertEqual(-44, ecapnp:get(a, Union)),
106105
?assertEqual(0, ecapnp:get(b, Union)),
107106
?assertEqual(22, ecapnp:get(c, Union)),
108-
Grp = ecapnp:get(opts, Root),
109-
{object, Obj} = ecapnp:get(Grp),
107+
{object, Obj} = ecapnp:get(opts, Root),
110108
Simple = ecapnp_obj:to_struct('Simple', Obj),
111109
?assertEqual(<<"Hello World!">>, ecapnp:get(simpleMessage, Simple)),
112110
?assertEqual(<<"default message">>, ecapnp:get(message, Simple)),

test/ecapnp_set_tests.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,10 +315,10 @@ group_field_test() ->
315315
"foo bar",0
316316
>>], Data).
317317

318-
group_union_test() ->
318+
named_union_test() ->
319+
%% please note that a named union is the same as a unnamed union wrapped in a group
319320
{ok, Root} = ecapnp:set_root('Test', test_capnp),
320-
Grp = ecapnp:get(opts, Root),
321-
ok = ecapnp:set({text, <<"testing">>}, Grp),
321+
ok = ecapnp:set(opts, {text, <<"testing">>}, Root),
322322
Data = ecapnp_data:get_segments((Root#object.ref)#ref.data#builder.pid),
323323
?assertEqual(
324324
[<<0:32/integer, 2,0, 6,0, %% Test struct, 16 bytes, 6 ptrs

0 commit comments

Comments
 (0)