Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
07b979a3
Commit
07b979a3
authored
May 13, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Test Dynamic API.
parent
08d73bef
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1024 additions
and
221 deletions
+1024
-221
Makefile.am
c++/Makefile.am
+6
-0
dynamic-test.c++
c++/src/capnproto/dynamic-test.c++
+585
-26
dynamic.c++
c++/src/capnproto/dynamic.c++
+260
-118
dynamic.h
c++/src/capnproto/dynamic.h
+116
-67
layout.c++
c++/src/capnproto/layout.c++
+14
-7
layout.h
c++/src/capnproto/layout.h
+1
-1
schema.c++
c++/src/capnproto/schema.c++
+24
-0
schema.h
c++/src/capnproto/schema.h
+16
-0
CxxGenerator.hs
compiler/src/CxxGenerator.hs
+1
-1
WireFormat.hs
compiler/src/WireFormat.hs
+1
-1
No files found.
c++/Makefile.am
View file @
07b979a3
...
...
@@ -49,6 +49,8 @@ includecapnp_HEADERS = \
src/capnproto/layout.h
\
src/capnproto/list.h
\
src/capnproto/message.h
\
src/capnproto/schema.h
\
src/capnproto/dynamic.h
\
src/capnproto/io.h
\
src/capnproto/serialize.h
\
src/capnproto/serialize-packed.h
\
...
...
@@ -73,6 +75,8 @@ libcapnproto_a_SOURCES= \
src/capnproto/layout.c++
\
src/capnproto/list.c++
\
src/capnproto/message.c++
\
src/capnproto/schema.c++
\
src/capnproto/dynamic.c++
\
src/capnproto/io.c++
\
src/capnproto/serialize.c++
\
src/capnproto/serialize-packed.c++
...
...
@@ -117,6 +121,8 @@ capnproto_test_SOURCES = \
src/capnproto/logging-test.c++
\
src/capnproto/layout-test.c++
\
src/capnproto/message-test.c++
\
src/capnproto/schema-test.c++
\
src/capnproto/dynamic-test.c++
\
src/capnproto/encoding-test.c++
\
src/capnproto/serialize-test.c++
\
src/capnproto/serialize-packed-test.c++
\
...
...
c++/src/capnproto/dynamic-test.c++
View file @
07b979a3
...
...
@@ -55,7 +55,7 @@ namespace capnproto {
namespace
internal
{
namespace
{
void
dynamicInitTest
m
essage
(
DynamicStruct
::
Builder
builder
)
{
void
dynamicInitTest
M
essage
(
DynamicStruct
::
Builder
builder
)
{
builder
.
set
(
"voidField"
,
Void
::
VOID
);
builder
.
set
(
"boolField"
,
true
);
builder
.
set
(
"int8Field"
,
-
123
);
...
...
@@ -68,8 +68,8 @@ void dynamicInitTestmessage(DynamicStruct::Builder builder) {
builder
.
set
(
"uInt64Field"
,
12345678901234567890ull
);
builder
.
set
(
"float32Field"
,
1234.5
);
builder
.
set
(
"float64Field"
,
-
123e45
);
builder
.
set
(
"textField"
,
Text
::
Reader
(
"foo"
)
);
builder
.
set
(
"dataField"
,
Data
::
Reader
(
"bar"
)
);
builder
.
set
(
"textField"
,
"foo"
);
builder
.
set
(
"dataField"
,
"bar"
);
{
auto
subBuilder
=
builder
.
init
(
"structField"
).
as
<
DynamicStruct
>
();
subBuilder
.
set
(
"voidField"
,
Void
::
VOID
);
...
...
@@ -84,14 +84,14 @@ void dynamicInitTestmessage(DynamicStruct::Builder builder) {
subBuilder
.
set
(
"uInt64Field"
,
345678901234567890ull
);
subBuilder
.
set
(
"float32Field"
,
-
1.25e-10
);
subBuilder
.
set
(
"float64Field"
,
345
);
subBuilder
.
set
(
"textField"
,
Text
::
Reader
(
"baz"
)
);
subBuilder
.
set
(
"dataField"
,
Data
::
Reader
(
"qux"
)
);
subBuilder
.
set
(
"textField"
,
"baz"
);
subBuilder
.
set
(
"dataField"
,
"qux"
);
{
auto
subSubBuilder
=
subBuilder
.
init
(
"structField"
).
as
<
DynamicStruct
>
();
subSubBuilder
.
set
(
"textField"
,
Text
::
Reader
(
"nested"
)
);
subSubBuilder
.
init
(
"structField"
).
as
<
DynamicStruct
>
().
set
(
"textField"
,
Text
::
Reader
(
"really nested"
)
);
subSubBuilder
.
set
(
"textField"
,
"nested"
);
subSubBuilder
.
init
(
"structField"
).
as
<
DynamicStruct
>
().
set
(
"textField"
,
"really nested"
);
}
subBuilder
.
set
(
"enumField"
,
toDynamic
(
TestEnum
::
BAZ
)
);
subBuilder
.
set
(
"enumField"
,
TestEnum
::
BAZ
);
subBuilder
.
set
(
"voidList"
,
{
Void
::
VOID
,
Void
::
VOID
,
Void
::
VOID
});
subBuilder
.
set
(
"boolList"
,
{
false
,
true
,
false
,
true
,
true
});
...
...
@@ -106,19 +106,17 @@ void dynamicInitTestmessage(DynamicStruct::Builder builder) {
subBuilder
.
set
(
"uInt64List"
,
{
123456789012345ull
,
678901234567890ull
,
0ull
,
0xffffffffffffffffull
});
subBuilder
.
set
(
"float32List"
,
{
0
,
1234567
,
1e37
,
-
1e37
,
1e-37
,
-
1e-37
});
subBuilder
.
set
(
"float64List"
,
{
0
,
123456789012345
,
1e306
,
-
1e306
,
1e-306
,
-
1e-306
});
subBuilder
.
set
(
"textList"
,
{
Text
::
Reader
(
"quux"
),
Text
::
Reader
(
"corge"
),
Text
::
Reader
(
"grault"
)
});
subBuilder
.
set
(
"dataList"
,
{
Data
::
Reader
(
"garply"
),
Data
::
Reader
(
"waldo"
),
Data
::
Reader
(
"fred"
)
});
subBuilder
.
set
(
"textList"
,
{
"quux"
,
"corge"
,
"grault"
});
subBuilder
.
set
(
"dataList"
,
{
"garply"
,
"waldo"
,
"fred"
});
{
auto
listBuilder
=
subBuilder
.
init
(
"structList"
,
3
).
as
<
DynamicList
>
();
listBuilder
[
0
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
Text
::
Reader
(
"x structlist 1"
)
);
listBuilder
[
1
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
Text
::
Reader
(
"x structlist 2"
)
);
listBuilder
[
2
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
Text
::
Reader
(
"x structlist 3"
)
);
listBuilder
[
0
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
"x structlist 1"
);
listBuilder
[
1
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
"x structlist 2"
);
listBuilder
[
2
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
"x structlist 3"
);
}
subBuilder
.
set
(
"enumList"
,
{
toDynamic
(
TestEnum
::
QUX
),
toDynamic
(
TestEnum
::
BAR
),
toDynamic
(
TestEnum
::
GRAULT
)});
subBuilder
.
set
(
"enumList"
,
{
TestEnum
::
QUX
,
TestEnum
::
BAR
,
TestEnum
::
GRAULT
});
}
builder
.
set
(
"enumField"
,
toDynamic
(
TestEnum
::
CORGE
)
);
builder
.
set
(
"enumField"
,
TestEnum
::
CORGE
);
builder
.
init
(
"voidList"
,
6
);
builder
.
set
(
"boolList"
,
{
true
,
false
,
false
,
true
});
...
...
@@ -138,23 +136,584 @@ void dynamicInitTestmessage(DynamicStruct::Builder builder) {
std
::
numeric_limits
<
double
>::
infinity
(),
-
std
::
numeric_limits
<
double
>::
infinity
(),
std
::
numeric_limits
<
double
>::
quiet_NaN
()});
builder
.
set
(
"textList"
,
{
Text
::
Reader
(
"plugh"
),
Text
::
Reader
(
"xyzzy"
),
Text
::
Reader
(
"thud"
)
});
builder
.
set
(
"dataList"
,
{
Data
::
Reader
(
"oops"
),
Data
::
Reader
(
"exhausted"
),
Data
::
Reader
(
"rfc3092"
)
});
builder
.
set
(
"textList"
,
{
"plugh"
,
"xyzzy"
,
"thud"
});
builder
.
set
(
"dataList"
,
{
"oops"
,
"exhausted"
,
"rfc3092"
});
{
auto
listBuilder
=
builder
.
init
(
"structList"
,
3
).
as
<
DynamicList
>
();
listBuilder
[
0
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
Text
::
Reader
(
"structlist 1"
)
);
listBuilder
[
1
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
Text
::
Reader
(
"structlist 2"
)
);
listBuilder
[
2
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
Text
::
Reader
(
"structlist 3"
)
);
listBuilder
[
0
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
"structlist 1"
);
listBuilder
[
1
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
"structlist 2"
);
listBuilder
[
2
].
as
<
DynamicStruct
>
().
set
(
"textField"
,
"structlist 3"
);
}
builder
.
set
(
"enumList"
,
{
toDynamic
(
TestEnum
::
FOO
),
toDynamic
(
TestEnum
::
GARPLY
)
});
builder
.
set
(
"enumList"
,
{
TestEnum
::
FOO
,
TestEnum
::
GARPLY
});
}
TEST
(
DynamicApi
,
Struct
)
{
template
<
typename
T
>
void
expectPrimitiveEq
(
T
a
,
T
b
)
{
EXPECT_EQ
(
a
,
b
);
}
void
expectPrimitiveEq
(
float
a
,
float
b
)
{
EXPECT_FLOAT_EQ
(
a
,
b
);
}
void
expectPrimitiveEq
(
double
a
,
double
b
)
{
EXPECT_DOUBLE_EQ
(
a
,
b
);
}
void
expectPrimitiveEq
(
Text
::
Reader
a
,
Text
::
Builder
b
)
{
EXPECT_EQ
(
a
,
b
);
}
void
expectPrimitiveEq
(
Data
::
Reader
a
,
Data
::
Builder
b
)
{
EXPECT_EQ
(
a
,
b
);
}
// Hack because as<>() is a template-parameter-dependent lookup everywhere below...
#define as template as
template
<
typename
Element
,
typename
T
>
void
checkList
(
T
reader
,
std
::
initializer_list
<
ReaderFor
<
Element
>>
expected
)
{
auto
list
=
reader
.
as
<
DynamicList
>
();
ASSERT_EQ
(
expected
.
size
(),
list
.
size
());
for
(
uint
i
=
0
;
i
<
expected
.
size
();
i
++
)
{
expectPrimitiveEq
(
expected
.
begin
()[
i
],
list
[
i
].
as
<
Element
>
());
}
auto
typed
=
reader
.
as
<
List
<
Element
>>
();
ASSERT_EQ
(
expected
.
size
(),
typed
.
size
());
for
(
uint
i
=
0
;
i
<
expected
.
size
();
i
++
)
{
expectPrimitiveEq
(
expected
.
begin
()[
i
],
typed
[
i
]);
}
}
inline
bool
isNaN
(
float
f
)
{
return
f
!=
f
;
}
inline
bool
isNaN
(
double
f
)
{
return
f
!=
f
;
}
template
<
typename
Reader
>
void
dynamicCheckTestMessage
(
Reader
reader
)
{
EXPECT_EQ
(
Void
::
VOID
,
reader
.
get
(
"voidField"
).
as
<
Void
>
());
EXPECT_EQ
(
true
,
reader
.
get
(
"boolField"
).
as
<
bool
>
());
EXPECT_EQ
(
-
123
,
reader
.
get
(
"int8Field"
).
as
<
int8_t
>
());
EXPECT_EQ
(
-
12345
,
reader
.
get
(
"int16Field"
).
as
<
int16_t
>
());
EXPECT_EQ
(
-
12345678
,
reader
.
get
(
"int32Field"
).
as
<
int32_t
>
());
EXPECT_EQ
(
-
123456789012345ll
,
reader
.
get
(
"int64Field"
).
as
<
int64_t
>
());
EXPECT_EQ
(
234u
,
reader
.
get
(
"uInt8Field"
).
as
<
uint8_t
>
());
EXPECT_EQ
(
45678u
,
reader
.
get
(
"uInt16Field"
).
as
<
uint16_t
>
());
EXPECT_EQ
(
3456789012u
,
reader
.
get
(
"uInt32Field"
).
as
<
uint32_t
>
());
EXPECT_EQ
(
12345678901234567890ull
,
reader
.
get
(
"uInt64Field"
).
as
<
uint64_t
>
());
EXPECT_FLOAT_EQ
(
1234.5
f
,
reader
.
get
(
"float32Field"
).
as
<
float
>
());
EXPECT_DOUBLE_EQ
(
-
123e45
,
reader
.
get
(
"float64Field"
).
as
<
double
>
());
EXPECT_EQ
(
"foo"
,
reader
.
get
(
"textField"
).
as
<
Text
>
());
EXPECT_EQ
(
"bar"
,
reader
.
get
(
"dataField"
).
as
<
Data
>
());
{
auto
subReader
=
reader
.
get
(
"structField"
).
as
<
DynamicStruct
>
();
EXPECT_EQ
(
Void
::
VOID
,
subReader
.
get
(
"voidField"
).
as
<
Void
>
());
EXPECT_EQ
(
true
,
subReader
.
get
(
"boolField"
).
as
<
bool
>
());
EXPECT_EQ
(
-
12
,
subReader
.
get
(
"int8Field"
).
as
<
int8_t
>
());
EXPECT_EQ
(
3456
,
subReader
.
get
(
"int16Field"
).
as
<
int16_t
>
());
EXPECT_EQ
(
-
78901234
,
subReader
.
get
(
"int32Field"
).
as
<
int32_t
>
());
EXPECT_EQ
(
56789012345678ll
,
subReader
.
get
(
"int64Field"
).
as
<
int64_t
>
());
EXPECT_EQ
(
90u
,
subReader
.
get
(
"uInt8Field"
).
as
<
uint8_t
>
());
EXPECT_EQ
(
1234u
,
subReader
.
get
(
"uInt16Field"
).
as
<
uint16_t
>
());
EXPECT_EQ
(
56789012u
,
subReader
.
get
(
"uInt32Field"
).
as
<
uint32_t
>
());
EXPECT_EQ
(
345678901234567890ull
,
subReader
.
get
(
"uInt64Field"
).
as
<
uint64_t
>
());
EXPECT_FLOAT_EQ
(
-
1.25e-10
f
,
subReader
.
get
(
"float32Field"
).
as
<
float
>
());
EXPECT_DOUBLE_EQ
(
345
,
subReader
.
get
(
"float64Field"
).
as
<
double
>
());
EXPECT_EQ
(
"baz"
,
subReader
.
get
(
"textField"
).
as
<
Text
>
());
EXPECT_EQ
(
"qux"
,
subReader
.
get
(
"dataField"
).
as
<
Data
>
());
{
auto
subSubReader
=
subReader
.
get
(
"structField"
).
as
<
DynamicStruct
>
();
EXPECT_EQ
(
"nested"
,
subSubReader
.
get
(
"textField"
).
as
<
Text
>
());
EXPECT_EQ
(
"really nested"
,
subSubReader
.
get
(
"structField"
).
as
<
DynamicStruct
>
()
.
get
(
"textField"
).
as
<
Text
>
());
}
EXPECT_EQ
(
TestEnum
::
BAZ
,
subReader
.
get
(
"enumField"
).
as
<
TestEnum
>
());
checkList
<
Void
>
(
subReader
.
get
(
"voidList"
),
{
Void
::
VOID
,
Void
::
VOID
,
Void
::
VOID
});
checkList
<
bool
>
(
subReader
.
get
(
"boolList"
),
{
false
,
true
,
false
,
true
,
true
});
checkList
<
int8_t
>
(
subReader
.
get
(
"int8List"
),
{
12
,
-
34
,
-
0x80
,
0x7f
});
checkList
<
int16_t
>
(
subReader
.
get
(
"int16List"
),
{
1234
,
-
5678
,
-
0x8000
,
0x7fff
});
checkList
<
int32_t
>
(
subReader
.
get
(
"int32List"
),
{
12345678
,
-
90123456
,
-
0x8000000
,
0x7ffffff
});
// gcc warns on -0x800...ll and the only work-around I could find was to do -0x7ff...ll-1.
checkList
<
int64_t
>
(
subReader
.
get
(
"int64List"
),
{
123456789012345ll
,
-
678901234567890ll
,
-
0x7fffffffffffffffll
-
1
,
0x7fffffffffffffffll
});
checkList
<
uint8_t
>
(
subReader
.
get
(
"uInt8List"
),
{
12u
,
34u
,
0u
,
0xffu
});
checkList
<
uint16_t
>
(
subReader
.
get
(
"uInt16List"
),
{
1234u
,
5678u
,
0u
,
0xffffu
});
checkList
<
uint32_t
>
(
subReader
.
get
(
"uInt32List"
),
{
12345678u
,
90123456u
,
0u
,
0xffffffffu
});
checkList
<
uint64_t
>
(
subReader
.
get
(
"uInt64List"
),
{
123456789012345ull
,
678901234567890ull
,
0ull
,
0xffffffffffffffffull
});
checkList
<
float
>
(
subReader
.
get
(
"float32List"
),
{
0.0
f
,
1234567.0
f
,
1e37
f
,
-
1e37
f
,
1e-37
f
,
-
1e-37
f
});
checkList
<
double
>
(
subReader
.
get
(
"float64List"
),
{
0.0
,
123456789012345.0
,
1e306
,
-
1e306
,
1e-306
,
-
1e-306
});
checkList
<
Text
>
(
subReader
.
get
(
"textList"
),
{
"quux"
,
"corge"
,
"grault"
});
checkList
<
Data
>
(
subReader
.
get
(
"dataList"
),
{
"garply"
,
"waldo"
,
"fred"
});
{
auto
listReader
=
subReader
.
get
(
"structList"
).
as
<
DynamicList
>
();
ASSERT_EQ
(
3u
,
listReader
.
size
());
EXPECT_EQ
(
"x structlist 1"
,
listReader
[
0
].
as
<
DynamicStruct
>
().
get
(
"textField"
).
as
<
Text
>
());
EXPECT_EQ
(
"x structlist 2"
,
listReader
[
1
].
as
<
DynamicStruct
>
().
get
(
"textField"
).
as
<
Text
>
());
EXPECT_EQ
(
"x structlist 3"
,
listReader
[
2
].
as
<
DynamicStruct
>
().
get
(
"textField"
).
as
<
Text
>
());
}
checkList
<
TestEnum
>
(
subReader
.
get
(
"enumList"
),
{
TestEnum
::
QUX
,
TestEnum
::
BAR
,
TestEnum
::
GRAULT
});
}
EXPECT_EQ
(
TestEnum
::
CORGE
,
reader
.
get
(
"enumField"
).
as
<
TestEnum
>
());
EXPECT_EQ
(
6u
,
reader
.
get
(
"voidList"
).
as
<
DynamicList
>
().
size
());
checkList
<
bool
>
(
reader
.
get
(
"boolList"
),
{
true
,
false
,
false
,
true
});
checkList
<
int8_t
>
(
reader
.
get
(
"int8List"
),
{
111
,
-
111
});
checkList
<
int16_t
>
(
reader
.
get
(
"int16List"
),
{
11111
,
-
11111
});
checkList
<
int32_t
>
(
reader
.
get
(
"int32List"
),
{
111111111
,
-
111111111
});
checkList
<
int64_t
>
(
reader
.
get
(
"int64List"
),
{
1111111111111111111ll
,
-
1111111111111111111ll
});
checkList
<
uint8_t
>
(
reader
.
get
(
"uInt8List"
),
{
111u
,
222u
});
checkList
<
uint16_t
>
(
reader
.
get
(
"uInt16List"
),
{
33333u
,
44444u
});
checkList
<
uint32_t
>
(
reader
.
get
(
"uInt32List"
),
{
3333333333u
});
checkList
<
uint64_t
>
(
reader
.
get
(
"uInt64List"
),
{
11111111111111111111ull
});
{
auto
listReader
=
reader
.
get
(
"float32List"
).
as
<
DynamicList
>
();
ASSERT_EQ
(
4u
,
listReader
.
size
());
EXPECT_EQ
(
5555.5
f
,
listReader
[
0
].
as
<
float
>
());
EXPECT_EQ
(
std
::
numeric_limits
<
float
>::
infinity
(),
listReader
[
1
].
as
<
float
>
());
EXPECT_EQ
(
-
std
::
numeric_limits
<
float
>::
infinity
(),
listReader
[
2
].
as
<
float
>
());
EXPECT_TRUE
(
isNaN
(
listReader
[
3
].
as
<
float
>
()));
}
{
auto
listReader
=
reader
.
get
(
"float64List"
).
as
<
DynamicList
>
();
ASSERT_EQ
(
4u
,
listReader
.
size
());
EXPECT_EQ
(
7777.75
,
listReader
[
0
].
as
<
double
>
());
EXPECT_EQ
(
std
::
numeric_limits
<
double
>::
infinity
(),
listReader
[
1
].
as
<
double
>
());
EXPECT_EQ
(
-
std
::
numeric_limits
<
double
>::
infinity
(),
listReader
[
2
].
as
<
double
>
());
EXPECT_TRUE
(
isNaN
(
listReader
[
3
].
as
<
double
>
()));
}
checkList
<
Text
>
(
reader
.
get
(
"textList"
),
{
"plugh"
,
"xyzzy"
,
"thud"
});
checkList
<
Data
>
(
reader
.
get
(
"dataList"
),
{
"oops"
,
"exhausted"
,
"rfc3092"
});
{
auto
listReader
=
reader
.
get
(
"structList"
).
as
<
DynamicList
>
();
ASSERT_EQ
(
3u
,
listReader
.
size
());
EXPECT_EQ
(
"structlist 1"
,
listReader
[
0
].
as
<
DynamicStruct
>
().
get
(
"textField"
).
as
<
Text
>
());
EXPECT_EQ
(
"structlist 2"
,
listReader
[
1
].
as
<
DynamicStruct
>
().
get
(
"textField"
).
as
<
Text
>
());
EXPECT_EQ
(
"structlist 3"
,
listReader
[
2
].
as
<
DynamicStruct
>
().
get
(
"textField"
).
as
<
Text
>
());
}
checkList
<
TestEnum
>
(
reader
.
get
(
"enumList"
),
{
TestEnum
::
FOO
,
TestEnum
::
GARPLY
});
}
template
<
typename
Reader
>
void
dynamicCheckTestMessageAllZero
(
Reader
reader
)
{
EXPECT_EQ
(
Void
::
VOID
,
reader
.
get
(
"voidField"
).
as
<
Void
>
());
EXPECT_EQ
(
false
,
reader
.
get
(
"boolField"
).
as
<
bool
>
());
EXPECT_EQ
(
0
,
reader
.
get
(
"int8Field"
).
as
<
int8_t
>
());
EXPECT_EQ
(
0
,
reader
.
get
(
"int16Field"
).
as
<
int16_t
>
());
EXPECT_EQ
(
0
,
reader
.
get
(
"int32Field"
).
as
<
int32_t
>
());
EXPECT_EQ
(
0
,
reader
.
get
(
"int64Field"
).
as
<
int64_t
>
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"uInt8Field"
).
as
<
uint8_t
>
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"uInt16Field"
).
as
<
uint16_t
>
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"uInt32Field"
).
as
<
uint32_t
>
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"uInt64Field"
).
as
<
uint64_t
>
());
EXPECT_FLOAT_EQ
(
0
,
reader
.
get
(
"float32Field"
).
as
<
float
>
());
EXPECT_DOUBLE_EQ
(
0
,
reader
.
get
(
"float64Field"
).
as
<
double
>
());
EXPECT_EQ
(
""
,
reader
.
get
(
"textField"
).
as
<
Text
>
());
EXPECT_EQ
(
""
,
reader
.
get
(
"dataField"
).
as
<
Data
>
());
{
auto
subReader
=
reader
.
get
(
"structField"
).
as
<
DynamicStruct
>
();
EXPECT_EQ
(
Void
::
VOID
,
subReader
.
get
(
"voidField"
).
as
<
Void
>
());
EXPECT_EQ
(
false
,
subReader
.
get
(
"boolField"
).
as
<
bool
>
());
EXPECT_EQ
(
0
,
subReader
.
get
(
"int8Field"
).
as
<
int8_t
>
());
EXPECT_EQ
(
0
,
subReader
.
get
(
"int16Field"
).
as
<
int16_t
>
());
EXPECT_EQ
(
0
,
subReader
.
get
(
"int32Field"
).
as
<
int32_t
>
());
EXPECT_EQ
(
0
,
subReader
.
get
(
"int64Field"
).
as
<
int64_t
>
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"uInt8Field"
).
as
<
uint8_t
>
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"uInt16Field"
).
as
<
uint16_t
>
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"uInt32Field"
).
as
<
uint32_t
>
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"uInt64Field"
).
as
<
uint64_t
>
());
EXPECT_FLOAT_EQ
(
0
,
subReader
.
get
(
"float32Field"
).
as
<
float
>
());
EXPECT_DOUBLE_EQ
(
0
,
subReader
.
get
(
"float64Field"
).
as
<
double
>
());
EXPECT_EQ
(
""
,
subReader
.
get
(
"textField"
).
as
<
Text
>
());
EXPECT_EQ
(
""
,
subReader
.
get
(
"dataField"
).
as
<
Data
>
());
{
auto
subSubReader
=
subReader
.
get
(
"structField"
).
as
<
DynamicStruct
>
();
EXPECT_EQ
(
""
,
subSubReader
.
get
(
"textField"
).
as
<
Text
>
());
EXPECT_EQ
(
""
,
subSubReader
.
get
(
"structField"
).
as
<
DynamicStruct
>
()
.
get
(
"textField"
).
as
<
Text
>
());
}
EXPECT_EQ
(
0u
,
subReader
.
get
(
"voidList"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"boolList"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"int8List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"int16List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"int32List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"int64List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"uInt8List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"uInt16List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"uInt32List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"uInt64List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"float32List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"float64List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"textList"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"dataList"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
subReader
.
get
(
"structList"
).
as
<
DynamicList
>
().
size
());
}
EXPECT_EQ
(
0u
,
reader
.
get
(
"voidList"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"boolList"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"int8List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"int16List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"int32List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"int64List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"uInt8List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"uInt16List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"uInt32List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"uInt64List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"float32List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"float64List"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"textList"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"dataList"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
0u
,
reader
.
get
(
"structList"
).
as
<
DynamicList
>
().
size
());
}
#undef as
void
dynamicInitListDefaults
(
DynamicStruct
::
Builder
builder
)
{
auto
lists
=
builder
.
init
(
"lists"
).
as
<
DynamicStruct
>
();
lists
.
init
(
"list0"
,
2
);
lists
.
init
(
"list1"
,
4
);
lists
.
init
(
"list8"
,
2
);
lists
.
init
(
"list16"
,
2
);
lists
.
init
(
"list32"
,
2
);
lists
.
init
(
"list64"
,
2
);
lists
.
init
(
"listP"
,
2
);
lists
.
get
(
"list0"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
set
(
"f"
,
Void
::
VOID
);
lists
.
get
(
"list0"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
set
(
"f"
,
Void
::
VOID
);
lists
.
get
(
"list1"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
set
(
"f"
,
true
);
lists
.
get
(
"list1"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
set
(
"f"
,
false
);
lists
.
get
(
"list1"
).
as
<
DynamicList
>
()[
2
].
as
<
DynamicStruct
>
().
set
(
"f"
,
true
);
lists
.
get
(
"list1"
).
as
<
DynamicList
>
()[
3
].
as
<
DynamicStruct
>
().
set
(
"f"
,
true
);
lists
.
get
(
"list8"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
set
(
"f"
,
123u
);
lists
.
get
(
"list8"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
set
(
"f"
,
45u
);
lists
.
get
(
"list16"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
set
(
"f"
,
12345u
);
lists
.
get
(
"list16"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
set
(
"f"
,
6789u
);
lists
.
get
(
"list32"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
set
(
"f"
,
123456789u
);
lists
.
get
(
"list32"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
set
(
"f"
,
234567890u
);
lists
.
get
(
"list64"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
set
(
"f"
,
1234567890123456u
);
lists
.
get
(
"list64"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
set
(
"f"
,
2345678901234567u
);
lists
.
get
(
"listP"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
set
(
"f"
,
"foo"
);
lists
.
get
(
"listP"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
set
(
"f"
,
"bar"
);
{
auto
l
=
lists
.
init
(
"int32ListList"
,
3
).
as
<
DynamicList
>
();
l
.
init
(
0
,
3
).
as
<
DynamicList
>
().
copyFrom
({
1
,
2
,
3
});
l
.
init
(
1
,
2
).
as
<
DynamicList
>
().
copyFrom
({
4
,
5
});
l
.
init
(
2
,
1
).
as
<
DynamicList
>
().
copyFrom
({
12341234
});
}
{
auto
l
=
lists
.
init
(
"textListList"
,
3
).
as
<
DynamicList
>
();
l
.
init
(
0
,
2
).
as
<
DynamicList
>
().
copyFrom
({
"foo"
,
"bar"
});
l
.
init
(
1
,
1
).
as
<
DynamicList
>
().
copyFrom
({
"baz"
});
l
.
init
(
2
,
2
).
as
<
DynamicList
>
().
copyFrom
({
"qux"
,
"corge"
});
}
{
auto
l
=
lists
.
init
(
"structListList"
,
2
).
as
<
DynamicList
>
();
auto
e
=
l
.
init
(
0
,
2
).
as
<
DynamicList
>
();
e
[
0
].
as
<
TestAllTypes
>
().
setInt32Field
(
123
);
e
[
1
].
as
<
TestAllTypes
>
().
setInt32Field
(
456
);
e
=
l
.
init
(
1
,
1
).
as
<
DynamicList
>
();
e
[
0
].
as
<
TestAllTypes
>
().
setInt32Field
(
789
);
}
}
// Hack because as<>() is a template-parameter-dependent lookup everywhere below...
#define as template as
template
<
typename
Reader
>
void
dynamicCheckListDefaults
(
Reader
reader
)
{
auto
lists
=
reader
.
get
(
"lists"
).
as
<
DynamicStruct
>
();
ASSERT_EQ
(
2u
,
lists
.
get
(
"list0"
).
as
<
DynamicList
>
().
size
());
ASSERT_EQ
(
4u
,
lists
.
get
(
"list1"
).
as
<
DynamicList
>
().
size
());
ASSERT_EQ
(
2u
,
lists
.
get
(
"list8"
).
as
<
DynamicList
>
().
size
());
ASSERT_EQ
(
2u
,
lists
.
get
(
"list16"
).
as
<
DynamicList
>
().
size
());
ASSERT_EQ
(
2u
,
lists
.
get
(
"list32"
).
as
<
DynamicList
>
().
size
());
ASSERT_EQ
(
2u
,
lists
.
get
(
"list64"
).
as
<
DynamicList
>
().
size
());
ASSERT_EQ
(
2u
,
lists
.
get
(
"listP"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
Void
::
VOID
,
lists
.
get
(
"list0"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
Void
>
());
EXPECT_EQ
(
Void
::
VOID
,
lists
.
get
(
"list0"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
Void
>
());
EXPECT_TRUE
(
lists
.
get
(
"list1"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
bool
>
());
EXPECT_FALSE
(
lists
.
get
(
"list1"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
bool
>
());
EXPECT_TRUE
(
lists
.
get
(
"list1"
).
as
<
DynamicList
>
()[
2
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
bool
>
());
EXPECT_TRUE
(
lists
.
get
(
"list1"
).
as
<
DynamicList
>
()[
3
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
bool
>
());
EXPECT_EQ
(
123u
,
lists
.
get
(
"list8"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
uint8_t
>
());
EXPECT_EQ
(
45u
,
lists
.
get
(
"list8"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
uint8_t
>
());
EXPECT_EQ
(
12345u
,
lists
.
get
(
"list16"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
uint16_t
>
());
EXPECT_EQ
(
6789u
,
lists
.
get
(
"list16"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
uint16_t
>
());
EXPECT_EQ
(
123456789u
,
lists
.
get
(
"list32"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
uint32_t
>
());
EXPECT_EQ
(
234567890u
,
lists
.
get
(
"list32"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
uint32_t
>
());
EXPECT_EQ
(
1234567890123456u
,
lists
.
get
(
"list64"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
uint64_t
>
());
EXPECT_EQ
(
2345678901234567u
,
lists
.
get
(
"list64"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
uint64_t
>
());
EXPECT_EQ
(
"foo"
,
lists
.
get
(
"listP"
).
as
<
DynamicList
>
()[
0
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
Text
>
());
EXPECT_EQ
(
"bar"
,
lists
.
get
(
"listP"
).
as
<
DynamicList
>
()[
1
].
as
<
DynamicStruct
>
().
get
(
"f"
).
as
<
Text
>
());
{
auto
l
=
lists
.
get
(
"int32ListList"
).
as
<
DynamicList
>
();
ASSERT_EQ
(
3u
,
l
.
size
());
checkList
<
int32_t
>
(
l
[
0
],
{
1
,
2
,
3
});
checkList
<
int32_t
>
(
l
[
1
],
{
4
,
5
});
checkList
<
int32_t
>
(
l
[
2
],
{
12341234
});
}
{
auto
l
=
lists
.
get
(
"textListList"
).
as
<
DynamicList
>
();
ASSERT_EQ
(
3u
,
l
.
size
());
checkList
<
Text
>
(
l
[
0
],
{
"foo"
,
"bar"
});
checkList
<
Text
>
(
l
[
1
],
{
"baz"
});
checkList
<
Text
>
(
l
[
2
],
{
"qux"
,
"corge"
});
}
{
auto
l
=
lists
.
get
(
"structListList"
).
as
<
DynamicList
>
();
ASSERT_EQ
(
2u
,
l
.
size
());
auto
e
=
l
[
0
].
as
<
DynamicList
>
();
ASSERT_EQ
(
2u
,
e
.
size
());
EXPECT_EQ
(
123
,
e
[
0
].
as
<
TestAllTypes
>
().
getInt32Field
());
EXPECT_EQ
(
456
,
e
[
1
].
as
<
TestAllTypes
>
().
getInt32Field
());
e
=
l
[
1
].
as
<
DynamicList
>
();
ASSERT_EQ
(
1u
,
e
.
size
());
EXPECT_EQ
(
789
,
e
[
0
].
as
<
TestAllTypes
>
().
getInt32Field
());
}
}
#undef as
TEST
(
DynamicApi
,
Build
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
initRoot
<
DynamicStruct
>
(
Schema
::
from
<
TestAllTypes
>
());
dynamicInitTestMessage
(
root
);
checkTestMessage
(
root
.
asReader
().
as
<
TestAllTypes
>
());
dynamicCheckTestMessage
(
root
.
asReader
());
dynamicCheckTestMessage
(
root
);
}
TEST
(
DynamicApi
,
Read
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
initRoot
<
TestAllTypes
>
();
dynamicInitTestmessage
(
toDynamic
(
root
));
checkTestMessage
(
root
);
initTestMessage
(
root
);
dynamicCheckTestMessage
(
toDynamic
(
root
.
asReader
()));
dynamicCheckTestMessage
(
toDynamic
(
root
).
asReader
());
dynamicCheckTestMessage
(
toDynamic
(
root
));
}
TEST
(
DynamicApi
,
Defaults
)
{
AlignedData
<
1
>
nullRoot
=
{{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
}};
ArrayPtr
<
const
word
>
segments
[
1
]
=
{
arrayPtr
(
nullRoot
.
words
,
1
)};
SegmentArrayMessageReader
reader
(
arrayPtr
(
segments
,
1
));
auto
root
=
reader
.
getRoot
<
DynamicStruct
>
(
Schema
::
from
<
TestDefaults
>
());
dynamicCheckTestMessage
(
root
);
}
TEST
(
DynamicApi
,
DefaultsBuilder
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
initRoot
<
DynamicStruct
>
(
Schema
::
from
<
TestDefaults
>
());
checkTestMessage
(
root
.
asReader
().
as
<
TestDefaults
>
());
dynamicCheckTestMessage
(
root
.
asReader
());
// This will initialize the whole message, replacing null pointers with copies of defaults.
dynamicCheckTestMessage
(
root
);
// Check again now that the message is initialized.
checkTestMessage
(
root
.
asReader
().
as
<
TestDefaults
>
());
dynamicCheckTestMessage
(
root
.
asReader
());
dynamicCheckTestMessage
(
root
);
}
TEST
(
DynamicApi
,
Zero
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
initRoot
<
DynamicStruct
>
(
Schema
::
from
<
TestAllTypes
>
());
dynamicCheckTestMessageAllZero
(
root
.
asReader
());
checkTestMessageAllZero
(
root
.
asReader
().
as
<
TestAllTypes
>
());
dynamicCheckTestMessageAllZero
(
root
);
checkTestMessageAllZero
(
root
.
asReader
().
as
<
TestAllTypes
>
());
}
TEST
(
DynamicApi
,
ListListsBuild
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
initRoot
<
DynamicStruct
>
(
Schema
::
from
<
TestListDefaults
>
());
dynamicInitListDefaults
(
root
);
checkTestMessage
(
root
.
asReader
().
as
<
TestListDefaults
>
());
dynamicCheckListDefaults
(
root
.
asReader
());
dynamicCheckListDefaults
(
root
);
}
TEST
(
DynamicApi
,
ListListsRead
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
initRoot
<
TestListDefaults
>
();
initTestMessage
(
root
);
dynamicCheckListDefaults
(
toDynamic
(
root
.
asReader
()));
dynamicCheckListDefaults
(
toDynamic
(
root
).
asReader
());
dynamicCheckListDefaults
(
toDynamic
(
root
));
}
TEST
(
DynamicApi
,
GenericObjects
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
getRoot
<
test
::
TestObject
>
();
dynamicInitTestMessage
(
root
.
initObjectField
<
DynamicStruct
>
(
Schema
::
from
<
TestAllTypes
>
()));
checkTestMessage
(
root
.
asReader
().
getObjectField
<
TestAllTypes
>
());
dynamicCheckTestMessage
(
root
.
asReader
().
getObjectField
<
DynamicStruct
>
(
Schema
::
from
<
TestAllTypes
>
()));
dynamicCheckTestMessage
(
root
.
getObjectField
<
DynamicStruct
>
(
Schema
::
from
<
TestAllTypes
>
()));
{
{
auto
list
=
root
.
initObjectField
<
DynamicList
>
(
Schema
::
from
<
List
<
uint32_t
>>
(),
4
);
list
.
set
(
0
,
123
);
list
.
set
(
1
,
456
);
list
.
set
(
2
,
789
);
list
.
set
(
3
,
123456789
);
}
{
auto
list
=
root
.
asReader
().
getObjectField
<
List
<
uint32_t
>>
();
ASSERT_EQ
(
4u
,
list
.
size
());
EXPECT_EQ
(
123u
,
list
[
0
]);
EXPECT_EQ
(
456u
,
list
[
1
]);
EXPECT_EQ
(
789u
,
list
[
2
]);
EXPECT_EQ
(
123456789u
,
list
[
3
]);
}
checkList
<
uint32_t
>
(
root
.
asReader
().
getObjectField
<
DynamicList
>
(
Schema
::
from
<
List
<
uint32_t
>>
()),
{
123u
,
456u
,
789u
,
123456789u
});
checkList
<
uint32_t
>
(
root
.
getObjectField
<
DynamicList
>
(
Schema
::
from
<
List
<
uint32_t
>>
()),
{
123u
,
456u
,
789u
,
123456789u
});
}
}
TEST
(
DynamicApi
,
DynamicGenericObjects
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
getRoot
<
DynamicStruct
>
(
Schema
::
from
<
test
::
TestObject
>
());
dynamicInitTestMessage
(
root
.
initObject
(
"objectField"
,
Schema
::
from
<
TestAllTypes
>
()));
checkTestMessage
(
root
.
asReader
().
as
<
test
::
TestObject
>
().
getObjectField
<
TestAllTypes
>
());
dynamicCheckTestMessage
(
root
.
asReader
().
get
(
"objectField"
).
as
<
DynamicObject
>
().
as
(
Schema
::
from
<
TestAllTypes
>
()));
dynamicCheckTestMessage
(
root
.
get
(
"objectField"
).
as
<
DynamicObject
>
().
as
(
Schema
::
from
<
TestAllTypes
>
()));
dynamicCheckTestMessage
(
root
.
getObject
(
"objectField"
,
Schema
::
from
<
TestAllTypes
>
()));
{
{
auto
list
=
root
.
initObject
(
"objectField"
,
Schema
::
from
<
List
<
uint32_t
>>
(),
4
);
list
.
set
(
0
,
123
);
list
.
set
(
1
,
456
);
list
.
set
(
2
,
789
);
list
.
set
(
3
,
123456789
);
}
{
auto
list
=
root
.
asReader
().
as
<
test
::
TestObject
>
().
getObjectField
<
List
<
uint32_t
>>
();
ASSERT_EQ
(
4u
,
list
.
size
());
EXPECT_EQ
(
123u
,
list
[
0
]);
EXPECT_EQ
(
456u
,
list
[
1
]);
EXPECT_EQ
(
789u
,
list
[
2
]);
EXPECT_EQ
(
123456789u
,
list
[
3
]);
}
checkList
<
uint32_t
>
(
root
.
asReader
().
get
(
"objectField"
).
as
<
DynamicObject
>
().
as
(
Schema
::
from
<
List
<
uint32_t
>>
()),
{
123u
,
456u
,
789u
,
123456789u
});
checkList
<
uint32_t
>
(
root
.
get
(
"objectField"
).
as
<
DynamicObject
>
().
as
(
Schema
::
from
<
List
<
uint32_t
>>
()),
{
123u
,
456u
,
789u
,
123456789u
});
checkList
<
uint32_t
>
(
root
.
getObject
(
"objectField"
,
Schema
::
from
<
List
<
uint32_t
>>
()),
{
123u
,
456u
,
789u
,
123456789u
});
}
}
TEST
(
DynamicApi
,
UnionsRead
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
initRoot
<
TestUnion
>
();
root
.
getUnion0
().
setU0f1s32
(
1234567
);
root
.
getUnion1
().
setU1f1sp
(
"foo"
);
root
.
getUnion2
().
setU2f0s1
(
true
);
root
.
getUnion3
().
setU3f0s64
(
1234567890123456789ll
);
{
auto
dynamic
=
toDynamic
(
root
.
asReader
());
{
auto
u
=
dynamic
.
get
(
"union0"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_EQ
(
"u0f1s32"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
1234567
,
u
.
get
().
as
<
int32_t
>
());
}
{
auto
u
=
dynamic
.
get
(
"union1"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_EQ
(
"u1f1sp"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
"foo"
,
u
.
get
().
as
<
Text
>
());
}
{
auto
u
=
dynamic
.
get
(
"union2"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_EQ
(
"u2f0s1"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_TRUE
(
u
.
get
().
as
<
bool
>
());
}
{
auto
u
=
dynamic
.
get
(
"union3"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_EQ
(
"u3f0s64"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
1234567890123456789ll
,
u
.
get
().
as
<
int64_t
>
());
}
}
{
// Again as a builder.
auto
dynamic
=
toDynamic
(
root
);
{
auto
u
=
dynamic
.
get
(
"union0"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_EQ
(
"u0f1s32"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
1234567
,
u
.
get
().
as
<
int32_t
>
());
}
{
auto
u
=
dynamic
.
get
(
"union1"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_EQ
(
"u1f1sp"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
"foo"
,
u
.
get
().
as
<
Text
>
());
}
{
auto
u
=
dynamic
.
get
(
"union2"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_EQ
(
"u2f0s1"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_TRUE
(
u
.
get
().
as
<
bool
>
());
}
{
auto
u
=
dynamic
.
get
(
"union3"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_EQ
(
"u3f0s64"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
1234567890123456789ll
,
u
.
get
().
as
<
int64_t
>
());
}
}
}
TEST
(
DynamicApi
,
UnionsWrite
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
initRoot
<
DynamicStruct
>
(
Schema
::
from
<
TestUnion
>
());
root
.
get
(
"union0"
).
as
<
DynamicUnion
>
().
set
(
"u0f1s32"
,
1234567
);
root
.
get
(
"union1"
).
as
<
DynamicUnion
>
().
set
(
"u1f1sp"
,
"foo"
);
root
.
get
(
"union2"
).
as
<
DynamicUnion
>
().
set
(
"u2f0s1"
,
true
);
root
.
get
(
"union3"
).
as
<
DynamicUnion
>
().
set
(
"u3f0s64"
,
1234567890123456789ll
);
auto
reader
=
root
.
asReader
().
as
<
TestUnion
>
();
ASSERT_EQ
(
TestUnion
::
Union0
::
U0F1S32
,
reader
.
getUnion0
().
which
());
EXPECT_EQ
(
1234567
,
reader
.
getUnion0
().
getU0f1s32
());
ASSERT_EQ
(
TestUnion
::
Union1
::
U1F1SP
,
reader
.
getUnion1
().
which
());
EXPECT_EQ
(
"foo"
,
reader
.
getUnion1
().
getU1f1sp
());
ASSERT_EQ
(
TestUnion
::
Union2
::
U2F0S1
,
reader
.
getUnion2
().
which
());
EXPECT_TRUE
(
reader
.
getUnion2
().
getU2f0s1
());
ASSERT_EQ
(
TestUnion
::
Union3
::
U3F0S64
,
reader
.
getUnion3
().
which
());
EXPECT_EQ
(
1234567890123456789ll
,
reader
.
getUnion3
().
getU3f0s64
());
}
}
// namespace
...
...
c++/src/capnproto/dynamic.c++
View file @
07b979a3
...
...
@@ -24,8 +24,6 @@
#define CAPNPROTO_PRIVATE
#include "dynamic.h"
#include "logging.h"
#include <unordered_map>
#include <unordered_set>
namespace
capnproto
{
...
...
@@ -122,7 +120,7 @@ uint16_t DynamicEnum::asImpl(uint64_t requestedTypeId) {
// =======================================================================================
DynamicStruct
::
Reader
DynamicObject
::
Reader
::
as
(
StructSchema
schema
)
{
DynamicStruct
::
Reader
DynamicObject
::
as
(
StructSchema
schema
)
{
if
(
reader
.
kind
==
internal
::
ObjectKind
::
NULL_POINTER
)
{
return
DynamicStruct
::
Reader
(
schema
,
internal
::
StructReader
());
}
...
...
@@ -131,17 +129,8 @@ DynamicStruct::Reader DynamicObject::Reader::as(StructSchema schema) {
}
return
DynamicStruct
::
Reader
(
schema
,
reader
.
structReader
);
}
DynamicStruct
::
Builder
DynamicObject
::
Builder
::
as
(
StructSchema
schema
)
{
if
(
builder
.
kind
==
internal
::
ObjectKind
::
NULL_POINTER
)
{
return
DynamicStruct
::
Builder
(
schema
,
internal
::
StructBuilder
());
}
VALIDATE_INPUT
(
builder
.
kind
==
internal
::
ObjectKind
::
STRUCT
,
"Object is not a struct."
)
{
return
DynamicStruct
::
Builder
(
schema
,
internal
::
StructBuilder
());
}
return
DynamicStruct
::
Builder
(
schema
,
builder
.
structBuilder
);
}
DynamicList
::
Reader
DynamicObject
::
Reader
::
as
(
ListSchema
schema
)
{
DynamicList
::
Reader
DynamicObject
::
as
(
ListSchema
schema
)
{
if
(
reader
.
kind
==
internal
::
ObjectKind
::
NULL_POINTER
)
{
return
DynamicList
::
Reader
(
schema
,
internal
::
ListReader
());
}
...
...
@@ -150,21 +139,12 @@ DynamicList::Reader DynamicObject::Reader::as(ListSchema schema) {
}
return
DynamicList
::
Reader
(
schema
,
reader
.
listReader
);
}
DynamicList
::
Builder
DynamicObject
::
Builder
::
as
(
ListSchema
schema
)
{
if
(
builder
.
kind
==
internal
::
ObjectKind
::
NULL_POINTER
)
{
return
DynamicList
::
Builder
(
schema
,
internal
::
ListBuilder
());
}
VALIDATE_INPUT
(
builder
.
kind
==
internal
::
ObjectKind
::
LIST
,
"Object is not a list."
)
{
return
DynamicList
::
Builder
(
schema
,
internal
::
ListBuilder
());
}
return
DynamicList
::
Builder
(
schema
,
builder
.
listBuilder
);
}
// =======================================================================================
Maybe
<
StructSchema
::
Member
>
DynamicUnion
::
Reader
::
which
()
{
auto
members
=
schema
.
getMembers
();
uint16_t
discrim
=
reader
.
getDataField
<
uint
32
_t
>
(
uint16_t
discrim
=
reader
.
getDataField
<
uint
16
_t
>
(
schema
.
getProto
().
getBody
().
getUnionMember
().
getDiscriminantOffset
()
*
ELEMENTS
);
if
(
discrim
<
members
.
size
())
{
...
...
@@ -175,7 +155,7 @@ Maybe<StructSchema::Member> DynamicUnion::Reader::which() {
}
Maybe
<
StructSchema
::
Member
>
DynamicUnion
::
Builder
::
which
()
{
auto
members
=
schema
.
getMembers
();
uint16_t
discrim
=
builder
.
getDataField
<
uint
32
_t
>
(
uint16_t
discrim
=
builder
.
getDataField
<
uint
16
_t
>
(
schema
.
getProto
().
getBody
().
getUnionMember
().
getDiscriminantOffset
()
*
ELEMENTS
);
if
(
discrim
<
members
.
size
())
{
...
...
@@ -186,50 +166,117 @@ Maybe<StructSchema::Member> DynamicUnion::Builder::which() {
}
DynamicValue
::
Reader
DynamicUnion
::
Reader
::
get
()
{
auto
w
=
which
();
RECOVERABLE_PRECOND
(
w
!=
nullptr
,
"Can't get() unknown union value."
)
{
return
DynamicValue
::
Reader
();
}
CHECK
(
w
->
getProto
().
getBody
().
which
()
==
schema
::
StructNode
::
Member
::
Body
::
FIELD_MEMBER
,
"Unsupported union member type."
);
return
DynamicValue
::
Reader
(
DynamicStruct
::
Reader
::
getImpl
(
reader
,
*
w
));
return
DynamicValue
::
Reader
(
DynamicStruct
::
Reader
::
getImpl
(
reader
,
checkIsKnown
()));
}
DynamicValue
::
Builder
DynamicUnion
::
Builder
::
get
()
{
auto
w
=
which
();
RECOVERABLE_PRECOND
(
w
!=
nullptr
,
"Can't get() unknown union value."
)
{
return
DynamicValue
::
Builder
();
}
CHECK
(
w
->
getProto
().
getBody
().
which
()
==
schema
::
StructNode
::
Member
::
Body
::
FIELD_MEMBER
,
"Unsupported union member type."
);
return
DynamicValue
::
Builder
(
DynamicStruct
::
Builder
::
getImpl
(
builder
,
*
w
));
return
DynamicValue
::
Builder
(
DynamicStruct
::
Builder
::
getImpl
(
builder
,
checkIsKnown
()));
}
void
DynamicUnion
::
Builder
::
set
(
StructSchema
::
Member
member
,
DynamicValue
::
Reader
value
)
{
auto
containingUnion
=
member
.
getContainingUnion
();
RECOVERABLE_PRECOND
(
containingUnion
!=
nullptr
&&
*
containingUnion
==
schema
,
"`member` is not a member of this union."
)
{
return
;
}
builder
.
setDataField
<
uint16_t
>
(
schema
.
getProto
().
getBody
().
getUnionMember
().
getDiscriminantOffset
()
*
ELEMENTS
,
member
.
getIndex
());
setDiscriminant
(
member
);
DynamicStruct
::
Builder
::
setImpl
(
builder
,
member
,
value
);
}
DynamicValue
::
Builder
DynamicUnion
::
Builder
::
init
(
StructSchema
::
Member
member
)
{
builder
.
setDataField
<
uint16_t
>
(
schema
.
getProto
().
getBody
().
getUnionMember
().
getDiscriminantOffset
()
*
ELEMENTS
,
member
.
getIndex
());
setDiscriminant
(
member
);
return
DynamicStruct
::
Builder
::
initImpl
(
builder
,
member
);
}
DynamicValue
::
Builder
DynamicUnion
::
Builder
::
init
(
StructSchema
::
Member
member
,
uint
size
)
{
setDiscriminant
(
member
);
return
DynamicStruct
::
Builder
::
initImpl
(
builder
,
member
,
size
);
}
DynamicStruct
::
Builder
DynamicUnion
::
Builder
::
getObject
(
StructSchema
schema
)
{
return
DynamicStruct
::
Builder
::
getObjectImpl
(
builder
,
checkIsObject
(),
schema
);
}
DynamicList
::
Builder
DynamicUnion
::
Builder
::
getObject
(
ListSchema
schema
)
{
return
DynamicStruct
::
Builder
::
getObjectImpl
(
builder
,
checkIsObject
(),
schema
);
}
Text
::
Builder
DynamicUnion
::
Builder
::
getObjectAsText
()
{
return
DynamicStruct
::
Builder
::
getObjectAsTextImpl
(
builder
,
checkIsObject
());
}
Data
::
Builder
DynamicUnion
::
Builder
::
getObjectAsData
()
{
return
DynamicStruct
::
Builder
::
getObjectAsDataImpl
(
builder
,
checkIsObject
());
}
DynamicStruct
::
Builder
DynamicUnion
::
Builder
::
initObject
(
StructSchema
::
Member
member
,
StructSchema
type
)
{
setObjectDiscriminant
(
member
);
return
DynamicStruct
::
Builder
::
initFieldImpl
(
builder
,
member
,
type
);
}
DynamicList
::
Builder
DynamicUnion
::
Builder
::
initObject
(
StructSchema
::
Member
member
,
ListSchema
type
,
uint
size
)
{
setObjectDiscriminant
(
member
);
return
DynamicStruct
::
Builder
::
initFieldImpl
(
builder
,
member
,
type
,
size
);
}
Text
::
Builder
DynamicUnion
::
Builder
::
initObjectAsText
(
StructSchema
::
Member
member
,
uint
size
)
{
setObjectDiscriminant
(
member
);
return
DynamicStruct
::
Builder
::
initFieldAsTextImpl
(
builder
,
member
,
size
);
}
Data
::
Builder
DynamicUnion
::
Builder
::
initObjectAsData
(
StructSchema
::
Member
member
,
uint
size
)
{
setObjectDiscriminant
(
member
);
return
DynamicStruct
::
Builder
::
initFieldAsDataImpl
(
builder
,
member
,
size
);
}
void
DynamicUnion
::
Builder
::
set
(
Text
::
Reader
name
,
DynamicValue
::
Reader
value
)
{
set
(
schema
.
getMemberByName
(
name
),
value
);
}
DynamicValue
::
Builder
DynamicUnion
::
Builder
::
init
(
Text
::
Reader
name
)
{
return
init
(
schema
.
getMemberByName
(
name
));
}
DynamicValue
::
Builder
DynamicUnion
::
Builder
::
init
(
Text
::
Reader
name
,
uint
size
)
{
return
init
(
schema
.
getMemberByName
(
name
),
size
);
}
DynamicStruct
::
Builder
DynamicUnion
::
Builder
::
initObject
(
Text
::
Reader
name
,
StructSchema
type
)
{
return
initObject
(
schema
.
getMemberByName
(
name
),
type
);
}
DynamicList
::
Builder
DynamicUnion
::
Builder
::
initObject
(
Text
::
Reader
name
,
ListSchema
type
,
uint
size
)
{
return
initObject
(
schema
.
getMemberByName
(
name
),
type
,
size
);
}
Text
::
Builder
DynamicUnion
::
Builder
::
initObjectAsText
(
Text
::
Reader
name
,
uint
size
)
{
return
initObjectAsText
(
schema
.
getMemberByName
(
name
),
size
);
}
Data
::
Builder
DynamicUnion
::
Builder
::
initObjectAsData
(
Text
::
Reader
name
,
uint
size
)
{
return
initObjectAsData
(
schema
.
getMemberByName
(
name
),
size
);
}
StructSchema
::
Member
DynamicUnion
::
Reader
::
checkIsKnown
()
{
auto
w
=
which
();
PRECOND
(
w
!=
nullptr
,
"Can't get() unknown union value."
);
CHECK
(
w
->
getProto
().
getBody
().
which
()
==
schema
::
StructNode
::
Member
::
Body
::
FIELD_MEMBER
,
"Unsupported union member type."
);
return
*
w
;
}
StructSchema
::
Member
DynamicUnion
::
Builder
::
checkIsKnown
()
{
auto
w
=
which
();
PRECOND
(
w
!=
nullptr
,
"Can't get() unknown union value."
);
CHECK
(
w
->
getProto
().
getBody
().
which
()
==
schema
::
StructNode
::
Member
::
Body
::
FIELD_MEMBER
,
"Unsupported union member type."
);
return
*
w
;
}
StructSchema
::
Member
DynamicUnion
::
Builder
::
checkIsObject
()
{
auto
result
=
checkIsKnown
();
PRECOND
(
result
.
getProto
().
getBody
().
getFieldMember
().
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected Object."
);
return
result
;
}
void
DynamicUnion
::
Builder
::
setDiscriminant
(
StructSchema
::
Member
member
)
{
auto
containingUnion
=
member
.
getContainingUnion
();
PRECOND
(
containingUnion
!=
nullptr
&&
*
containingUnion
==
schema
,
"`member` is not a member of this union."
);
builder
.
setDataField
<
uint16_t
>
(
schema
.
getProto
().
getBody
().
getUnionMember
().
getDiscriminantOffset
()
*
ELEMENTS
,
member
.
getIndex
());
return
DynamicStruct
::
Builder
::
initImpl
(
builder
,
member
,
size
);
}
void
DynamicUnion
::
Builder
::
setObjectDiscriminant
(
StructSchema
::
Member
member
)
{
PRECOND
(
member
.
getProto
().
getBody
().
getFieldMember
().
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected Object."
);
setDiscriminant
(
member
);
}
// =======================================================================================
...
...
@@ -268,19 +315,94 @@ DynamicValue::Builder DynamicStruct::Builder::init(StructSchema::Member member,
"`member` is not a member of this struct."
);
return
initImpl
(
builder
,
member
,
size
);
}
DynamicStruct
::
Builder
DynamicStruct
::
Builder
::
getObject
(
StructSchema
::
Member
member
,
StructSchema
type
)
{
PRECOND
(
member
.
getContainingStruct
()
==
schema
,
"`member` is not a member of this struct."
);
switch
(
member
.
getProto
().
getBody
().
which
())
{
case
schema
:
:
StructNode
::
Member
::
Body
::
UNION_MEMBER
:
FAIL_PRECOND
(
"Expected an Object."
);
return
DynamicStruct
::
Builder
();
case
schema
:
:
StructNode
::
Member
::
Body
::
FIELD_MEMBER
:
{
auto
field
=
member
.
getProto
().
getBody
().
getFieldMember
();
PRECOND
(
field
.
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected an Object."
);
return
getObjectImpl
(
builder
,
member
,
type
);
}
}
FAIL_CHECK
(
"switch() missing case."
,
member
.
getProto
().
getBody
().
which
());
return
DynamicStruct
::
Builder
();
}
DynamicList
::
Builder
DynamicStruct
::
Builder
::
getObject
(
StructSchema
::
Member
member
,
ListSchema
type
)
{
PRECOND
(
member
.
getContainingStruct
()
==
schema
,
"`member` is not a member of this struct."
);
switch
(
member
.
getProto
().
getBody
().
which
())
{
case
schema
:
:
StructNode
::
Member
::
Body
::
UNION_MEMBER
:
FAIL_PRECOND
(
"Expected an Object."
);
return
DynamicList
::
Builder
();
case
schema
:
:
StructNode
::
Member
::
Body
::
FIELD_MEMBER
:
{
auto
field
=
member
.
getProto
().
getBody
().
getFieldMember
();
PRECOND
(
field
.
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected an Object."
);
return
getObjectImpl
(
builder
,
member
,
type
);
}
}
FAIL_CHECK
(
"switch() missing case."
,
member
.
getProto
().
getBody
().
which
());
return
DynamicList
::
Builder
();
}
Text
::
Builder
DynamicStruct
::
Builder
::
getObjectAsText
(
StructSchema
::
Member
member
)
{
PRECOND
(
member
.
getContainingStruct
()
==
schema
,
"`member` is not a member of this struct."
);
switch
(
member
.
getProto
().
getBody
().
which
())
{
case
schema
:
:
StructNode
::
Member
::
Body
::
UNION_MEMBER
:
FAIL_PRECOND
(
"Expected an Object."
);
return
Text
::
Builder
();
case
schema
:
:
StructNode
::
Member
::
Body
::
FIELD_MEMBER
:
{
auto
field
=
member
.
getProto
().
getBody
().
getFieldMember
();
PRECOND
(
field
.
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected an Object."
);
return
getObjectAsDataImpl
(
builder
,
member
);
}
}
FAIL_CHECK
(
"switch() missing case."
,
member
.
getProto
().
getBody
().
which
());
return
Text
::
Builder
();
}
Data
::
Builder
DynamicStruct
::
Builder
::
getObjectAsData
(
StructSchema
::
Member
member
)
{
PRECOND
(
member
.
getContainingStruct
()
==
schema
,
"`member` is not a member of this struct."
);
switch
(
member
.
getProto
().
getBody
().
which
())
{
case
schema
:
:
StructNode
::
Member
::
Body
::
UNION_MEMBER
:
FAIL_PRECOND
(
"Expected an Object."
);
return
Data
::
Builder
();
case
schema
:
:
StructNode
::
Member
::
Body
::
FIELD_MEMBER
:
{
auto
field
=
member
.
getProto
().
getBody
().
getFieldMember
();
PRECOND
(
field
.
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected an Object."
);
return
getObjectAsDataImpl
(
builder
,
member
);
}
}
FAIL_CHECK
(
"switch() missing case."
,
member
.
getProto
().
getBody
().
which
());
return
Data
::
Builder
();
}
DynamicStruct
::
Builder
DynamicStruct
::
Builder
::
initObject
(
StructSchema
::
Member
member
,
StructSchema
type
)
{
PRECOND
(
member
.
getContainingStruct
()
==
schema
,
"`member` is not a member of this struct."
);
switch
(
member
.
getProto
().
getBody
().
which
())
{
case
schema
:
:
StructNode
::
Member
::
Body
::
UNION_MEMBER
:
FAIL_PRECOND
(
"
Can't init() a union. get() it first and then init() one of its members
."
);
FAIL_PRECOND
(
"
Expected an Object
."
);
return
DynamicStruct
::
Builder
();
case
schema
:
:
StructNode
::
Member
::
Body
::
FIELD_MEMBER
:
{
auto
field
=
member
.
getProto
().
getBody
().
getFieldMember
();
PRECOND
(
field
.
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected an Object. (To dynamically initialize a non-Object field, do not "
"pass an element type to initObjectField().)"
);
"Expected an Object."
);
return
initFieldImpl
(
builder
,
member
,
type
);
}
}
...
...
@@ -293,14 +415,13 @@ DynamicList::Builder DynamicStruct::Builder::initObject(
PRECOND
(
member
.
getContainingStruct
()
==
schema
,
"`member` is not a member of this struct."
);
switch
(
member
.
getProto
().
getBody
().
which
())
{
case
schema
:
:
StructNode
::
Member
::
Body
::
UNION_MEMBER
:
FAIL_PRECOND
(
"
Can't init() a union. get() it first and then init() one of its members
."
);
FAIL_PRECOND
(
"
Expected an Object
."
);
return
DynamicList
::
Builder
();
case
schema
:
:
StructNode
::
Member
::
Body
::
FIELD_MEMBER
:
{
auto
field
=
member
.
getProto
().
getBody
().
getFieldMember
();
PRECOND
(
field
.
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected an Object. (To dynamically initialize a non-Object field, do not "
"pass a struct schema to initObjectField().)"
);
"Expected an Object."
);
return
initFieldImpl
(
builder
,
member
,
type
,
size
);
}
}
...
...
@@ -312,14 +433,13 @@ Text::Builder DynamicStruct::Builder::initObjectAsText(StructSchema::Member memb
PRECOND
(
member
.
getContainingStruct
()
==
schema
,
"`member` is not a member of this struct."
);
switch
(
member
.
getProto
().
getBody
().
which
())
{
case
schema
:
:
StructNode
::
Member
::
Body
::
UNION_MEMBER
:
FAIL_PRECOND
(
"
Can't init() a union. get() it first and then init() one of its members
."
);
FAIL_PRECOND
(
"
Expected an Object
."
);
return
Text
::
Builder
();
case
schema
:
:
StructNode
::
Member
::
Body
::
FIELD_MEMBER
:
{
auto
field
=
member
.
getProto
().
getBody
().
getFieldMember
();
PRECOND
(
field
.
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected an Object. (To dynamically initialize a non-Object field, do not "
"pass a struct schema to initObjectField().)"
);
"Expected an Object."
);
return
initFieldAsDataImpl
(
builder
,
member
,
size
);
}
}
...
...
@@ -331,14 +451,13 @@ Data::Builder DynamicStruct::Builder::initObjectAsData(StructSchema::Member memb
PRECOND
(
member
.
getContainingStruct
()
==
schema
,
"`member` is not a member of this struct."
);
switch
(
member
.
getProto
().
getBody
().
which
())
{
case
schema
:
:
StructNode
::
Member
::
Body
::
UNION_MEMBER
:
FAIL_PRECOND
(
"
Can't init() a union. get() it first and then init() one of its members
."
);
FAIL_PRECOND
(
"
Expected an Object
."
);
return
Data
::
Builder
();
case
schema
:
:
StructNode
::
Member
::
Body
::
FIELD_MEMBER
:
{
auto
field
=
member
.
getProto
().
getBody
().
getFieldMember
();
PRECOND
(
field
.
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected an Object. (To dynamically initialize a non-Object field, do not "
"pass a struct schema to initObjectField().)"
);
"Expected an Object."
);
return
initFieldAsDataImpl
(
builder
,
member
,
size
);
}
}
...
...
@@ -348,73 +467,50 @@ Data::Builder DynamicStruct::Builder::initObjectAsData(StructSchema::Member memb
}
DynamicValue
::
Reader
DynamicStruct
::
Reader
::
get
(
Text
::
Reader
name
)
{
auto
member
=
schema
.
findMemberByName
(
name
);
RECOVERABLE_PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
)
{
return
DynamicValue
::
Reader
();
}
return
getImpl
(
reader
,
*
member
);
return
getImpl
(
reader
,
schema
.
getMemberByName
(
name
));
}
DynamicValue
::
Builder
DynamicStruct
::
Builder
::
get
(
Text
::
Reader
name
)
{
auto
member
=
schema
.
findMemberByName
(
name
);
RECOVERABLE_PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
)
{
return
DynamicValue
::
Builder
();
}
return
getImpl
(
builder
,
*
member
);
return
getImpl
(
builder
,
schema
.
getMemberByName
(
name
));
}
void
DynamicStruct
::
Builder
::
set
(
Text
::
Reader
name
,
DynamicValue
::
Reader
value
)
{
auto
member
=
schema
.
findMemberByName
(
name
);
RECOVERABLE_PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
)
{
return
;
}
return
setImpl
(
builder
,
*
member
,
value
);
setImpl
(
builder
,
schema
.
getMemberByName
(
name
),
value
);
}
void
DynamicStruct
::
Builder
::
set
(
Text
::
Reader
name
,
std
::
initializer_list
<
DynamicValue
::
Reader
>
value
)
{
init
(
name
,
value
.
size
()).
as
<
DynamicList
>
().
copyFrom
(
value
);
}
DynamicValue
::
Builder
DynamicStruct
::
Builder
::
init
(
Text
::
Reader
name
)
{
auto
member
=
schema
.
findMemberByName
(
name
);
RECOVERABLE_PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
)
{
return
DynamicValue
::
Builder
();
}
return
initImpl
(
builder
,
*
member
);
return
initImpl
(
builder
,
schema
.
getMemberByName
(
name
));
}
DynamicValue
::
Builder
DynamicStruct
::
Builder
::
init
(
Text
::
Reader
name
,
uint
size
)
{
auto
member
=
schema
.
findMemberByName
(
name
);
RECOVERABLE_PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
)
{
return
DynamicValue
::
Builder
();
}
return
initImpl
(
builder
,
*
member
,
size
);
return
initImpl
(
builder
,
schema
.
getMemberByName
(
name
),
size
);
}
DynamicStruct
::
Builder
DynamicStruct
::
Builder
::
getObject
(
Text
::
Reader
name
,
StructSchema
type
)
{
return
getObject
(
schema
.
getMemberByName
(
name
),
type
);
}
DynamicList
::
Builder
DynamicStruct
::
Builder
::
getObject
(
Text
::
Reader
name
,
ListSchema
type
)
{
return
getObject
(
schema
.
getMemberByName
(
name
),
type
);
}
Text
::
Builder
DynamicStruct
::
Builder
::
getObjectAsText
(
Text
::
Reader
name
)
{
return
getObjectAsText
(
schema
.
getMemberByName
(
name
));
}
Data
::
Builder
DynamicStruct
::
Builder
::
getObjectAsData
(
Text
::
Reader
name
)
{
return
getObjectAsText
(
schema
.
getMemberByName
(
name
));
}
DynamicStruct
::
Builder
DynamicStruct
::
Builder
::
initObject
(
Text
::
Reader
name
,
StructSchema
type
)
{
auto
member
=
schema
.
findMemberByName
(
name
);
RECOVERABLE_PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
)
{
return
DynamicStruct
::
Builder
();
}
return
initObject
(
*
member
,
type
);
return
initObject
(
schema
.
getMemberByName
(
name
),
type
);
}
DynamicList
::
Builder
DynamicStruct
::
Builder
::
initObject
(
Text
::
Reader
name
,
ListSchema
type
,
uint
size
)
{
auto
member
=
schema
.
findMemberByName
(
name
);
RECOVERABLE_PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
)
{
return
DynamicList
::
Builder
();
}
return
initObject
(
*
member
,
type
,
size
);
return
initObject
(
schema
.
getMemberByName
(
name
),
type
,
size
);
}
Text
::
Builder
DynamicStruct
::
Builder
::
initObjectAsText
(
Text
::
Reader
name
,
uint
size
)
{
auto
member
=
schema
.
findMemberByName
(
name
);
RECOVERABLE_PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
)
{
return
Text
::
Builder
();
}
return
initObjectAsText
(
*
member
,
size
);
return
initObjectAsText
(
schema
.
getMemberByName
(
name
),
size
);
}
Data
::
Builder
DynamicStruct
::
Builder
::
initObjectAsData
(
Text
::
Reader
name
,
uint
size
)
{
auto
member
=
schema
.
findMemberByName
(
name
);
RECOVERABLE_PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
)
{
return
Data
::
Builder
();
}
return
initObjectAsText
(
*
member
,
size
);
return
initObjectAsText
(
schema
.
getMemberByName
(
name
),
size
);
}
void
DynamicStruct
::
Builder
::
copyFrom
(
Reader
other
)
{
...
...
@@ -497,7 +593,7 @@ DynamicValue::Reader DynamicStruct::Reader::getImpl(
}
case
schema
:
:
Type
::
Body
::
OBJECT_TYPE
:
{
return
DynamicValue
::
Reader
(
DynamicObject
::
Reader
(
return
DynamicValue
::
Reader
(
DynamicObject
(
reader
.
getObjectField
(
field
.
getOffset
()
*
REFERENCES
,
dval
.
getObjectValue
<
internal
::
TrustedMessage
>
())));
}
...
...
@@ -573,13 +669,11 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl(
typedDval
.
data
(),
typedDval
.
size
()
*
BYTES
));
}
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
{
auto
elementType
=
type
.
getListType
();
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
return
DynamicValue
::
Builder
(
DynamicList
::
Builder
(
ListSchema
::
of
(
elementType
,
member
.
getContainingStruct
()),
ListSchema
::
of
(
type
.
getListType
()
,
member
.
getContainingStruct
()),
builder
.
getListField
(
field
.
getOffset
()
*
REFERENCES
,
dval
.
getListValue
<
internal
::
TrustedMessage
>
())));
}
case
schema
:
:
Type
::
Body
::
STRUCT_TYPE
:
{
auto
structSchema
=
...
...
@@ -593,9 +687,10 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl(
}
case
schema
:
:
Type
::
Body
::
OBJECT_TYPE
:
{
return
DynamicValue
::
Builder
(
DynamicObject
::
Builder
(
builder
.
getObjectField
(
field
.
getOffset
()
*
REFERENCES
,
dval
.
getObjectValue
<
internal
::
TrustedMessage
>
())));
return
DynamicValue
::
Builder
(
DynamicObject
(
builder
.
asReader
().
getObjectField
(
field
.
getOffset
()
*
REFERENCES
,
dval
.
getObjectValue
<
internal
::
TrustedMessage
>
())));
}
case
schema
:
:
Type
::
Body
::
INTERFACE_TYPE
:
...
...
@@ -611,6 +706,30 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl(
FAIL_CHECK
(
"switch() missing case."
,
member
.
getProto
().
getBody
().
which
());
return
DynamicValue
::
Builder
();
}
DynamicStruct
::
Builder
DynamicStruct
::
Builder
::
getObjectImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
field
,
StructSchema
type
)
{
return
DynamicStruct
::
Builder
(
type
,
builder
.
getStructField
(
field
.
getProto
().
getBody
().
getFieldMember
().
getOffset
()
*
REFERENCES
,
structSizeFromSchema
(
type
),
nullptr
));
}
DynamicList
::
Builder
DynamicStruct
::
Builder
::
getObjectImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
field
,
ListSchema
type
)
{
return
DynamicList
::
Builder
(
type
,
builder
.
getListField
(
field
.
getProto
().
getBody
().
getFieldMember
().
getOffset
()
*
REFERENCES
,
nullptr
));
}
Text
::
Builder
DynamicStruct
::
Builder
::
getObjectAsTextImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
field
)
{
return
builder
.
getBlobField
<
Text
>
(
field
.
getProto
().
getBody
().
getFieldMember
().
getOffset
()
*
REFERENCES
,
nullptr
,
0
*
BYTES
);
}
Data
::
Builder
DynamicStruct
::
Builder
::
getObjectAsDataImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
field
)
{
return
builder
.
getBlobField
<
Data
>
(
field
.
getProto
().
getBody
().
getFieldMember
().
getOffset
()
*
REFERENCES
,
nullptr
,
0
*
BYTES
);
}
void
DynamicStruct
::
Builder
::
setImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
member
,
DynamicValue
::
Reader
value
)
{
...
...
@@ -841,7 +960,7 @@ DynamicValue::Reader DynamicList::Reader::operator[](uint index) {
schema
.
getEnumElementType
(),
reader
.
getDataElement
<
uint16_t
>
(
index
*
ELEMENTS
)));
case
schema
:
:
Type
::
Body
::
OBJECT_TYPE
:
return
DynamicValue
::
Reader
(
DynamicObject
::
Reader
(
return
DynamicValue
::
Reader
(
DynamicObject
(
reader
.
getObjectElement
(
index
*
ELEMENTS
)));
case
schema
:
:
Type
::
Body
::
INTERFACE_TYPE
:
...
...
@@ -1158,7 +1277,6 @@ BuilderFor<typeName> DynamicValue::Builder::AsImpl<typeName>::apply(Builder buil
HANDLE_TYPE
(
bool
,
BOOL
,
bool
)
HANDLE_TYPE
(
text
,
TEXT
,
Text
)
HANDLE_TYPE
(
data
,
DATA
,
Data
)
HANDLE_TYPE
(
list
,
LIST
,
DynamicList
)
HANDLE_TYPE
(
struct
,
STRUCT
,
DynamicStruct
)
HANDLE_TYPE
(
enum
,
ENUM
,
DynamicEnum
)
...
...
@@ -1167,6 +1285,30 @@ HANDLE_TYPE(union, UNION, DynamicUnion)
#undef HANDLE_TYPE
Data
::
Reader
DynamicValue
::
Reader
::
AsImpl
<
Data
>::
apply
(
Reader
reader
)
{
if
(
reader
.
type
==
TEXT
)
{
// Implicitly convert from text.
return
reader
.
textValue
;
}
VALIDATE_INPUT
(
reader
.
type
==
DATA
,
"Type mismatch when using DynamicValue::Reader::as()."
)
{
return
Data
::
Reader
();
}
return
reader
.
dataValue
;
}
Data
::
Builder
DynamicValue
::
Builder
::
AsImpl
<
Data
>::
apply
(
Builder
builder
)
{
if
(
builder
.
type
==
TEXT
)
{
// Implicitly convert from text.
return
builder
.
textValue
;
}
VALIDATE_INPUT
(
builder
.
type
==
DATA
,
"Type mismatch when using DynamicValue::Builder::as()."
)
{
return
Data
::
Builder
();
}
return
builder
.
dataValue
;
}
// As in the header, HANDLE_TYPE(void, VOID, Void) crashes GCC 4.7.
Void
DynamicValue
::
Reader
::
AsImpl
<
Void
>::
apply
(
Reader
reader
)
{
VALIDATE_INPUT
(
reader
.
type
==
VOID
,
...
...
c++/src/capnproto/dynamic.h
View file @
07b979a3
...
...
@@ -65,10 +65,7 @@ struct DynamicValue {
class
Builder
;
};
class
DynamicEnum
;
struct
DynamicObject
{
class
Reader
;
class
Builder
;
};
class
DynamicObject
;
struct
DynamicUnion
{
class
Reader
;
class
Builder
;
...
...
@@ -103,6 +100,9 @@ class DynamicEnum {
public
:
DynamicEnum
()
=
default
;
template
<
typename
T
,
typename
EnableIf
=
TypeIfEnum
<
T
>>
inline
DynamicEnum
(
T
&&
value
)
:
DynamicEnum
(
toDynamic
(
value
))
{}
template
<
typename
T
>
inline
T
as
()
{
return
static_cast
<
T
>
(
asImpl
(
typeId
<
T
>
()));
}
// Cast to a native enum type.
...
...
@@ -134,9 +134,13 @@ private:
// -------------------------------------------------------------------
class
DynamicObject
::
Reader
{
class
DynamicObject
{
// Represents an "Object" field of unknown type. This class behaves as a Reader. There is no
// equivalent Builder; you must use getObject() or initObject() on the containing struct and
// specify a type if you want to build an Object field.
public
:
Reader
()
=
default
;
DynamicObject
()
=
default
;
template
<
typename
T
>
inline
typename
T
::
Reader
as
()
{
return
AsImpl
<
T
>::
apply
(
*
this
);
}
...
...
@@ -148,31 +152,7 @@ public:
private
:
internal
::
ObjectReader
reader
;
inline
Reader
(
internal
::
ObjectReader
reader
)
:
reader
(
reader
)
{}
template
<
typename
T
,
Kind
kind
=
kind
<
T
>
()
>
struct
AsImpl
;
// Implementation backing the as() method. Needs to be a struct to allow partial
// specialization. Has a method apply() which does the work.
friend
struct
DynamicStruct
;
friend
struct
DynamicList
;
};
class
DynamicObject
::
Builder
{
public
:
Builder
()
=
default
;
template
<
typename
T
>
inline
typename
T
::
Builder
as
()
{
return
AsImpl
<
T
>::
apply
(
*
this
);
}
// Convert the object to the given struct, list, or blob type.
DynamicStruct
::
Builder
as
(
StructSchema
schema
);
DynamicList
::
Builder
as
(
ListSchema
schema
);
private
:
internal
::
ObjectBuilder
builder
;
inline
Builder
(
internal
::
ObjectBuilder
builder
)
:
builder
(
builder
)
{}
inline
DynamicObject
(
internal
::
ObjectReader
reader
)
:
reader
(
reader
)
{}
template
<
typename
T
,
Kind
kind
=
kind
<
T
>
()
>
struct
AsImpl
;
// Implementation backing the as() method. Needs to be a struct to allow partial
...
...
@@ -205,6 +185,8 @@ private:
inline
Reader
(
StructSchema
::
Union
schema
,
internal
::
StructReader
reader
)
:
schema
(
schema
),
reader
(
reader
)
{}
StructSchema
::
Member
checkIsKnown
();
friend
struct
DynamicStruct
;
};
...
...
@@ -223,6 +205,25 @@ public:
DynamicValue
::
Builder
init
(
StructSchema
::
Member
member
);
DynamicValue
::
Builder
init
(
StructSchema
::
Member
member
,
uint
size
);
DynamicStruct
::
Builder
getObject
(
StructSchema
schema
);
DynamicList
::
Builder
getObject
(
ListSchema
schema
);
Text
::
Builder
getObjectAsText
();
Data
::
Builder
getObjectAsData
();
DynamicStruct
::
Builder
initObject
(
StructSchema
::
Member
member
,
StructSchema
type
);
DynamicList
::
Builder
initObject
(
StructSchema
::
Member
member
,
ListSchema
type
,
uint
size
);
Text
::
Builder
initObjectAsText
(
StructSchema
::
Member
member
,
uint
size
);
Data
::
Builder
initObjectAsData
(
StructSchema
::
Member
member
,
uint
size
);
// Get/init an "Object" member. Must specify the type.
void
set
(
Text
::
Reader
name
,
DynamicValue
::
Reader
value
);
DynamicValue
::
Builder
init
(
Text
::
Reader
member
);
DynamicValue
::
Builder
init
(
Text
::
Reader
name
,
uint
size
);
DynamicStruct
::
Builder
initObject
(
Text
::
Reader
name
,
StructSchema
type
);
DynamicList
::
Builder
initObject
(
Text
::
Reader
name
,
ListSchema
type
,
uint
size
);
Text
::
Builder
initObjectAsText
(
Text
::
Reader
name
,
uint
size
);
Data
::
Builder
initObjectAsData
(
Text
::
Reader
name
,
uint
size
);
// Convenience methods that identify the member by text name.
private
:
StructSchema
::
Union
schema
;
internal
::
StructBuilder
builder
;
...
...
@@ -230,6 +231,11 @@ private:
inline
Builder
(
StructSchema
::
Union
schema
,
internal
::
StructBuilder
builder
)
:
schema
(
schema
),
builder
(
builder
)
{}
StructSchema
::
Member
checkIsKnown
();
StructSchema
::
Member
checkIsObject
();
void
setDiscriminant
(
StructSchema
::
Member
member
);
void
setObjectDiscriminant
(
StructSchema
::
Member
member
);
friend
struct
DynamicStruct
;
};
...
...
@@ -239,6 +245,9 @@ class DynamicStruct::Reader {
public
:
Reader
()
=
default
;
template
<
typename
T
,
typename
EnableIf
=
FromReader
<
T
>>
inline
Reader
(
T
&&
value
)
:
Reader
(
toDynamic
(
value
))
{}
template
<
typename
T
>
typename
T
::
Reader
as
();
// Convert the dynamic struct to its compiled-in type.
...
...
@@ -265,7 +274,7 @@ private:
template
<
typename
T
>
friend
struct
internal
::
PointerHelpers
;
friend
class
DynamicUnion
::
Reader
;
friend
struct
DynamicObject
;
friend
class
DynamicObject
;
friend
class
DynamicStruct
::
Builder
;
friend
struct
DynamicList
;
friend
class
MessageReader
;
...
...
@@ -278,6 +287,9 @@ class DynamicStruct::Builder {
public
:
Builder
()
=
default
;
template
<
typename
T
,
typename
EnableIf
=
FromBuilder
<
T
>>
inline
Builder
(
T
&&
value
)
:
Builder
(
toDynamic
(
value
))
{}
template
<
typename
T
>
typename
T
::
Builder
as
();
// Cast to a particular struct type.
...
...
@@ -294,6 +306,12 @@ public:
DynamicValue
::
Builder
init
(
StructSchema
::
Member
member
,
uint
size
);
// Init a struct, list, or blob field.
DynamicStruct
::
Builder
getObject
(
StructSchema
::
Member
member
,
StructSchema
type
);
DynamicList
::
Builder
getObject
(
StructSchema
::
Member
member
,
ListSchema
type
);
Text
::
Builder
getObjectAsText
(
StructSchema
::
Member
member
);
Data
::
Builder
getObjectAsData
(
StructSchema
::
Member
member
);
// Get an object field. You must specify the type.
DynamicStruct
::
Builder
initObject
(
StructSchema
::
Member
member
,
StructSchema
type
);
DynamicList
::
Builder
initObject
(
StructSchema
::
Member
member
,
ListSchema
type
,
uint
size
);
Text
::
Builder
initObjectAsText
(
StructSchema
::
Member
member
,
uint
size
);
...
...
@@ -305,6 +323,10 @@ public:
void
set
(
Text
::
Reader
name
,
std
::
initializer_list
<
DynamicValue
::
Reader
>
value
);
DynamicValue
::
Builder
init
(
Text
::
Reader
name
);
DynamicValue
::
Builder
init
(
Text
::
Reader
name
,
uint
size
);
DynamicStruct
::
Builder
getObject
(
Text
::
Reader
name
,
StructSchema
type
);
DynamicList
::
Builder
getObject
(
Text
::
Reader
name
,
ListSchema
type
);
Text
::
Builder
getObjectAsText
(
Text
::
Reader
name
);
Data
::
Builder
getObjectAsData
(
Text
::
Reader
name
);
DynamicStruct
::
Builder
initObject
(
Text
::
Reader
name
,
StructSchema
type
);
DynamicList
::
Builder
initObject
(
Text
::
Reader
name
,
ListSchema
type
,
uint
size
);
Text
::
Builder
initObjectAsText
(
Text
::
Reader
name
,
uint
size
);
...
...
@@ -326,8 +348,18 @@ private:
static
DynamicValue
::
Builder
getImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
member
);
static
DynamicStruct
::
Builder
getObjectImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
field
,
StructSchema
type
);
static
DynamicList
::
Builder
getObjectImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
field
,
ListSchema
type
);
static
Text
::
Builder
getObjectAsTextImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
field
);
static
Data
::
Builder
getObjectAsDataImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
field
);
static
void
setImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
member
,
DynamicValue
::
Reader
value
);
static
DynamicValue
::
Builder
initImpl
(
internal
::
StructBuilder
builder
,
StructSchema
::
Member
member
,
uint
size
);
static
DynamicValue
::
Builder
initImpl
(
...
...
@@ -344,7 +376,6 @@ private:
template
<
typename
T
>
friend
struct
internal
::
PointerHelpers
;
friend
class
DynamicUnion
::
Builder
;
friend
struct
DynamicObject
;
friend
struct
DynamicList
;
friend
class
MessageReader
;
friend
class
MessageBuilder
;
...
...
@@ -358,6 +389,9 @@ class DynamicList::Reader {
public
:
Reader
()
=
default
;
template
<
typename
T
,
typename
EnableIf
=
FromReader
<
T
>>
inline
Reader
(
T
&&
value
)
:
Reader
(
toDynamic
(
value
))
{}
template
<
typename
T
>
typename
T
::
Reader
as
();
// Try to convert to any List<T>, Data, or Text. Throws an exception if the underlying data
...
...
@@ -383,7 +417,7 @@ private:
template
<
typename
T
>
friend
struct
internal
::
PointerHelpers
;
friend
struct
DynamicStruct
;
friend
struct
DynamicObject
;
friend
class
DynamicObject
;
friend
class
DynamicList
::
Builder
;
template
<
typename
T
,
::
capnproto
::
Kind
k
>
friend
struct
::
capnproto
::
ToDynamic_
;
...
...
@@ -393,6 +427,9 @@ class DynamicList::Builder {
public
:
Builder
()
=
default
;
template
<
typename
T
,
typename
EnableIf
=
FromBuilder
<
T
>>
inline
Builder
(
T
&&
value
)
:
Builder
(
toDynamic
(
value
))
{}
template
<
typename
T
>
typename
T
::
Builder
as
();
// Try to convert to any List<T>, Data, or Text. Throws an exception if the underlying data
...
...
@@ -425,7 +462,6 @@ private:
template
<
typename
T
>
friend
struct
internal
::
PointerHelpers
;
friend
struct
DynamicStruct
;
friend
struct
DynamicObject
;
template
<
typename
T
,
::
capnproto
::
Kind
k
>
friend
struct
::
capnproto
::
ToDynamic_
;
};
...
...
@@ -445,8 +481,8 @@ struct MaybeReaderBuilder<DynamicEnum, Kind::UNKNOWN> {
template
<>
struct
MaybeReaderBuilder
<
DynamicObject
,
Kind
::
UNKNOWN
>
{
typedef
DynamicObject
::
Reader
Reader
;
typedef
DynamicObject
::
Builder
Builder
;
typedef
DynamicObject
Reader
;
typedef
DynamicObject
Builder
;
};
template
<>
...
...
@@ -480,13 +516,17 @@ public:
inline
Reader
(
unsigned
long
long
value
);
inline
Reader
(
float
value
);
inline
Reader
(
double
value
);
inline
Reader
(
const
char
*
value
);
// Text
inline
Reader
(
Text
::
Reader
value
);
inline
Reader
(
Data
::
Reader
value
);
inline
Reader
(
DynamicList
::
Reader
value
);
inline
Reader
(
DynamicEnum
value
);
inline
Reader
(
DynamicStruct
::
Reader
value
);
inline
Reader
(
DynamicUnion
::
Reader
value
);
inline
Reader
(
DynamicObject
::
Reader
value
);
inline
Reader
(
DynamicObject
value
);
template
<
typename
T
,
typename
EnableIf
=
decltype
(
toDynamic
(
instance
<
T
>
()))
>
inline
Reader
(
T
value
)
:
Reader
(
toDynamic
(
value
))
{}
template
<
typename
T
>
inline
ReaderFor
<
T
>
as
()
{
return
AsImpl
<
T
>::
apply
(
*
this
);
}
...
...
@@ -494,8 +534,8 @@ public:
// - Void, bool, [u]int{8,16,32,64}_t, float, double, any enum: Returns the raw value.
// - Text, Data, any struct type: Returns the corresponding Reader.
// - List<T> for any T listed above: Returns List<T>::Reader.
// - DynamicEnum
: Returns DynamicEnum
.
// - DynamicStruct, DynamicList, Dynamic
Object, Dynamic
Union: Returns the corresponding Reader.
// - DynamicEnum
, DynamicObject: Returns the corresponding type
.
// - DynamicStruct, DynamicList, DynamicUnion: Returns the corresponding Reader.
//
// DynamicValue allows various implicit conversions:
// - Any integer can be converted to any other integer type so long as the actual value is within
...
...
@@ -505,6 +545,7 @@ public:
// - Integers can be converted to floating points. This may lose information, but won't throw.
// - Float32/Float64 can be converted between each other. Converting Float64 -> Float32 may lose
// information, but won't throw.
// - Text can be converted to Data (but not vice-versa).
//
// Any other conversion attempt will throw an exception.
...
...
@@ -526,7 +567,7 @@ private:
DynamicEnum
enumValue
;
DynamicStruct
::
Reader
structValue
;
DynamicUnion
::
Reader
unionValue
;
DynamicObject
::
Reader
objectValue
;
DynamicObject
objectValue
;
};
template
<
typename
T
,
Kind
kind
=
kind
<
T
>
()
>
struct
AsImpl
;
...
...
@@ -557,7 +598,7 @@ public:
inline
Builder
(
DynamicEnum
value
);
inline
Builder
(
DynamicStruct
::
Builder
value
);
inline
Builder
(
DynamicUnion
::
Builder
value
);
inline
Builder
(
DynamicObject
::
Builder
value
);
inline
Builder
(
DynamicObject
value
);
template
<
typename
T
>
inline
BuilderFor
<
T
>
as
()
{
return
AsImpl
<
T
>::
apply
(
*
this
);
}
...
...
@@ -583,7 +624,7 @@ private:
DynamicEnum
enumValue
;
DynamicStruct
::
Builder
structValue
;
DynamicUnion
::
Builder
unionValue
;
DynamicObject
::
Builder
objectValue
;
DynamicObject
objectValue
;
};
template
<
typename
T
,
Kind
kind
=
kind
<
T
>
()
>
struct
AsImpl
;
...
...
@@ -669,7 +710,7 @@ BuilderFor<DynamicTypeFor<FromBuilder<T>>> toDynamic(T&& value) {
}
template
<
typename
T
>
DynamicTypeFor
<
TypeIfEnum
<
T
>>
toDynamic
(
T
&&
value
)
{
return
DynamicEnum
(
Schema
::
from
<
T
>
(),
static_cast
<
uint16_t
>
(
value
));
return
DynamicEnum
(
Schema
::
from
<
RemoveReference
<
T
>
>
(),
static_cast
<
uint16_t
>
(
value
));
}
#define CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \
...
...
@@ -694,6 +735,7 @@ CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned long long, UINT, uint);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
(
float
,
FLOAT
,
float
);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
(
double
,
FLOAT
,
float
);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
(
DynamicEnum
,
ENUM
,
enum
);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
(
DynamicObject
,
OBJECT
,
object
);
#undef CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
#define CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \
...
...
@@ -707,10 +749,11 @@ CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Data, DATA, data);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
(
DynamicList
,
LIST
,
list
);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
(
DynamicStruct
,
STRUCT
,
struct
);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
(
DynamicUnion
,
UNION
,
union
);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
(
DynamicObject
,
OBJECT
,
object
);
#undef CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
inline
DynamicValue
::
Reader
::
Reader
(
const
char
*
value
)
:
Reader
(
Text
::
Reader
(
value
))
{}
#define CAPNPROTO_DECLARE_TYPE(name, discrim, typeName) \
template <> \
struct DynamicValue::Reader::AsImpl<typeName> { \
...
...
@@ -769,26 +812,26 @@ struct DynamicValue::Builder::AsImpl<T, Kind::ENUM> {
template
<
typename
T
>
struct
DynamicValue
::
Reader
::
AsImpl
<
T
,
Kind
::
STRUCT
>
{
static
T
apply
(
Reader
reader
)
{
static
typename
T
::
Reader
apply
(
Reader
reader
)
{
return
reader
.
as
<
DynamicStruct
>
().
as
<
T
>
();
}
};
template
<
typename
T
>
struct
DynamicValue
::
Builder
::
AsImpl
<
T
,
Kind
::
STRUCT
>
{
static
T
apply
(
Builder
builder
)
{
static
typename
T
::
Builder
apply
(
Builder
builder
)
{
return
builder
.
as
<
DynamicStruct
>
().
as
<
T
>
();
}
};
template
<
typename
T
>
struct
DynamicValue
::
Reader
::
AsImpl
<
T
,
Kind
::
LIST
>
{
static
T
apply
(
Reader
reader
)
{
static
typename
T
::
Reader
apply
(
Reader
reader
)
{
return
reader
.
as
<
DynamicList
>
().
as
<
T
>
();
}
};
template
<
typename
T
>
struct
DynamicValue
::
Builder
::
AsImpl
<
T
,
Kind
::
LIST
>
{
static
T
apply
(
Builder
builder
)
{
static
typename
T
::
Builder
apply
(
Builder
builder
)
{
return
builder
.
as
<
DynamicList
>
().
as
<
T
>
();
}
};
...
...
@@ -796,28 +839,16 @@ struct DynamicValue::Builder::AsImpl<T, Kind::LIST> {
// -------------------------------------------------------------------
template
<
typename
T
>
struct
DynamicObject
::
Reader
::
AsImpl
<
T
,
Kind
::
STRUCT
>
{
static
T
apply
(
Reader
reader
)
{
return
reader
.
as
(
Schema
::
from
<
T
>
()).
as
<
T
>
();
}
};
template
<
typename
T
>
struct
DynamicObject
::
Builder
::
AsImpl
<
T
,
Kind
::
STRUCT
>
{
static
T
apply
(
Builder
builder
)
{
return
builder
.
as
(
Schema
::
from
<
T
>
()).
as
<
T
>
();
struct
DynamicObject
::
AsImpl
<
T
,
Kind
::
STRUCT
>
{
static
T
apply
(
DynamicObject
value
)
{
return
value
.
as
(
Schema
::
from
<
T
>
()).
as
<
T
>
();
}
};
template
<
typename
T
>
struct
DynamicObject
::
Reader
::
AsImpl
<
T
,
Kind
::
LIST
>
{
static
T
apply
(
Reader
reader
)
{
return
reader
.
as
(
Schema
::
from
<
T
>
()).
as
<
T
>
();
}
};
template
<
typename
T
>
struct
DynamicObject
::
Builder
::
AsImpl
<
T
,
Kind
::
LIST
>
{
static
T
apply
(
Builder
builder
)
{
return
builder
.
as
(
Schema
::
from
<
T
>
()).
as
<
T
>
();
struct
DynamicObject
::
AsImpl
<
T
,
Kind
::
LIST
>
{
static
T
apply
(
DynamicObject
value
)
{
return
value
.
as
(
Schema
::
from
<
T
>
()).
as
<
T
>
();
}
};
...
...
@@ -838,6 +869,15 @@ typename T::Builder DynamicStruct::Builder::as() {
return
typename
T
::
Builder
(
builder
);
}
template
<>
inline
DynamicStruct
::
Reader
DynamicStruct
::
Reader
::
as
<
DynamicStruct
>
()
{
return
*
this
;
}
template
<>
inline
DynamicStruct
::
Builder
DynamicStruct
::
Builder
::
as
<
DynamicStruct
>
()
{
return
*
this
;
}
inline
DynamicStruct
::
Reader
DynamicStruct
::
Builder
::
asReader
()
{
return
DynamicStruct
::
Reader
(
schema
,
builder
.
asReader
());
}
...
...
@@ -859,6 +899,15 @@ typename T::Builder DynamicList::Builder::as() {
return
typename
T
::
Builder
(
builder
);
}
template
<>
inline
DynamicList
::
Reader
DynamicList
::
Reader
::
as
<
DynamicList
>
()
{
return
*
this
;
}
template
<>
inline
DynamicList
::
Builder
DynamicList
::
Builder
::
as
<
DynamicList
>
()
{
return
*
this
;
}
}
// namespace capnproto
#endif // CAPNPROTO_DYNAMIC_H_
c++/src/capnproto/layout.c++
View file @
07b979a3
...
...
@@ -427,7 +427,8 @@ struct WireHelpers {
word
*
ptr
;
if
(
ref
->
isNull
())
{
if
(
defaultValue
==
nullptr
)
{
if
(
defaultValue
==
nullptr
||
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
)
->
isNull
())
{
ptr
=
allocate
(
ref
,
segment
,
size
.
total
(),
WireReference
::
STRUCT
);
ref
->
structRef
.
set
(
size
);
}
else
{
...
...
@@ -508,7 +509,8 @@ struct WireHelpers {
word
*
ptr
;
if
(
ref
->
isNull
())
{
if
(
defaultValue
==
nullptr
)
{
if
(
defaultValue
==
nullptr
||
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
)
->
isNull
())
{
return
ListBuilder
();
}
ptr
=
copyMessage
(
segment
,
ref
,
defaultRef
);
...
...
@@ -619,7 +621,8 @@ struct WireHelpers {
word
*
ptr
;
if
(
ref
->
isNull
())
{
if
(
defaultValue
==
nullptr
)
{
if
(
defaultValue
==
nullptr
||
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
)
->
isNull
())
{
return
ObjectBuilder
();
}
else
{
ptr
=
copyMessage
(
segment
,
ref
,
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
));
...
...
@@ -668,7 +671,8 @@ struct WireHelpers {
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
if
(
defaultValue
==
nullptr
)
{
if
(
defaultValue
==
nullptr
||
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
)
->
isNull
())
{
return
StructReader
(
nullptr
,
nullptr
,
nullptr
,
0
*
BITS
,
0
*
REFERENCES
,
0
*
BITS
,
std
::
numeric_limits
<
int
>::
max
());
}
...
...
@@ -714,7 +718,8 @@ struct WireHelpers {
const
word
*
ptr
;
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
if
(
defaultValue
==
nullptr
)
{
if
(
defaultValue
==
nullptr
||
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
)
->
isNull
())
{
return
ListReader
();
}
segment
=
nullptr
;
...
...
@@ -874,7 +879,8 @@ struct WireHelpers {
const
void
*
defaultValue
,
ByteCount
defaultSize
))
{
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
if
(
defaultValue
==
nullptr
)
{
if
(
defaultValue
==
nullptr
||
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
)
->
isNull
())
{
defaultValue
=
""
;
}
return
Text
::
Reader
(
reinterpret_cast
<
const
char
*>
(
defaultValue
),
defaultSize
/
BYTES
);
...
...
@@ -973,7 +979,8 @@ struct WireHelpers {
const
word
*
ptr
;
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
if
(
defaultValue
==
nullptr
)
{
if
(
defaultValue
==
nullptr
||
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
)
->
isNull
())
{
return
ObjectReader
();
}
segment
=
nullptr
;
...
...
c++/src/capnproto/layout.h
View file @
07b979a3
...
...
@@ -647,7 +647,7 @@ struct ObjectBuilder {
ObjectBuilder
()
:
kind
(
ObjectKind
::
NULL_POINTER
),
structBuilder
()
{}
ObjectBuilder
(
StructBuilder
structBuilder
)
:
kind
(
ObjectKind
::
STRUCT
),
structBuilder
(
structBuilder
)
{}
ObjectBuilder
(
ListBuilder
listBuilder
Builder
)
ObjectBuilder
(
ListBuilder
listBuilder
)
:
kind
(
ObjectKind
::
LIST
),
listBuilder
(
listBuilder
)
{}
};
...
...
c++/src/capnproto/schema.c++
View file @
07b979a3
...
...
@@ -122,6 +122,12 @@ Maybe<StructSchema::Member> StructSchema::findMemberByName(Text::Reader name) co
return
findSchemaMemberByName
(
raw
,
name
,
0
,
getMembers
());
}
StructSchema
::
Member
StructSchema
::
getMemberByName
(
Text
::
Reader
name
)
const
{
Maybe
<
StructSchema
::
Member
>
member
=
findMemberByName
(
name
);
PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
);
return
*
member
;
}
Maybe
<
StructSchema
::
Union
>
StructSchema
::
Member
::
getContainingUnion
()
const
{
if
(
unionIndex
==
0
)
return
nullptr
;
return
parent
.
getMembers
()[
unionIndex
-
1
].
asUnion
();
...
...
@@ -142,6 +148,12 @@ Maybe<StructSchema::Member> StructSchema::Union::findMemberByName(Text::Reader n
return
findSchemaMemberByName
(
parent
.
raw
,
name
,
index
+
1
,
getMembers
());
}
StructSchema
::
Member
StructSchema
::
Union
::
getMemberByName
(
Text
::
Reader
name
)
const
{
Maybe
<
StructSchema
::
Member
>
member
=
findMemberByName
(
name
);
PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
);
return
*
member
;
}
// -------------------------------------------------------------------
EnumSchema
::
EnumerantList
EnumSchema
::
getEnumerants
()
const
{
...
...
@@ -152,6 +164,12 @@ Maybe<EnumSchema::Enumerant> EnumSchema::findEnumerantByName(Text::Reader name)
return
findSchemaMemberByName
(
raw
,
name
,
0
,
getEnumerants
());
}
EnumSchema
::
Enumerant
EnumSchema
::
getEnumerantByName
(
Text
::
Reader
name
)
const
{
Maybe
<
EnumSchema
::
Enumerant
>
enumerant
=
findEnumerantByName
(
name
);
PRECOND
(
enumerant
!=
nullptr
,
"enum has no such enumerant"
,
name
);
return
*
enumerant
;
}
// -------------------------------------------------------------------
InterfaceSchema
::
MethodList
InterfaceSchema
::
getMethods
()
const
{
...
...
@@ -162,6 +180,12 @@ Maybe<InterfaceSchema::Method> InterfaceSchema::findMethodByName(Text::Reader na
return
findSchemaMemberByName
(
raw
,
name
,
0
,
getMethods
());
}
InterfaceSchema
::
Method
InterfaceSchema
::
getMethodByName
(
Text
::
Reader
name
)
const
{
Maybe
<
InterfaceSchema
::
Method
>
method
=
findMethodByName
(
name
);
PRECOND
(
method
!=
nullptr
,
"interface has no such method"
,
name
);
return
*
method
;
}
// =======================================================================================
ListSchema
ListSchema
::
of
(
schema
::
Type
::
Body
::
Which
primitiveType
)
{
...
...
c++/src/capnproto/schema.h
View file @
07b979a3
...
...
@@ -100,8 +100,12 @@ public:
class
MemberList
;
MemberList
getMembers
()
const
;
Maybe
<
Member
>
findMemberByName
(
Text
::
Reader
name
)
const
;
Member
getMemberByName
(
Text
::
Reader
name
)
const
;
// Like findMemberByName() but throws an exception on failure.
private
:
StructSchema
(
const
internal
::
RawSchema
*
raw
)
:
Schema
(
raw
)
{}
template
<
typename
T
>
static
inline
StructSchema
fromImpl
()
{
...
...
@@ -148,8 +152,12 @@ public:
Union
()
=
default
;
MemberList
getMembers
()
const
;
Maybe
<
Member
>
findMemberByName
(
Text
::
Reader
name
)
const
;
Member
getMemberByName
(
Text
::
Reader
name
)
const
;
// Like findMemberByName() but throws an exception on failure.
private
:
inline
Union
(
const
Member
&
base
)
:
Member
(
base
)
{}
...
...
@@ -187,8 +195,12 @@ public:
class
EnumerantList
;
EnumerantList
getEnumerants
()
const
;
Maybe
<
Enumerant
>
findEnumerantByName
(
Text
::
Reader
name
)
const
;
Enumerant
getEnumerantByName
(
Text
::
Reader
name
)
const
;
// Like findEnumerantByName() but throws an exception on failure.
private
:
EnumSchema
(
const
internal
::
RawSchema
*
raw
)
:
Schema
(
raw
)
{}
template
<
typename
T
>
static
inline
EnumSchema
fromImpl
()
{
...
...
@@ -250,8 +262,12 @@ public:
class
MethodList
;
MethodList
getMethods
()
const
;
Maybe
<
Method
>
findMethodByName
(
Text
::
Reader
name
)
const
;
Method
getMethodByName
(
Text
::
Reader
name
)
const
;
// Like findMethodByName() but throws an exception on failure.
private
:
InterfaceSchema
(
const
internal
::
RawSchema
*
raw
)
:
Schema
(
raw
)
{}
template
<
typename
T
>
static
inline
InterfaceSchema
fromImpl
()
{
...
...
compiler/src/CxxGenerator.hs
View file @
07b979a3
...
...
@@ -498,7 +498,7 @@ outerFileContext schemaNodes = fileContext where
DescEnum
d
->
muJust
$
enumContext
context
d
_
->
muNull
context
"typeSchema"
=
case
desc
of
DescUnion
u
->
muNull
DescUnion
_
->
muNull
_
->
muJust
$
schemaContext
context
desc
context
s
=
parent
s
...
...
compiler/src/WireFormat.hs
View file @
07b979a3
...
...
@@ -523,7 +523,7 @@ encodeSchema requestedFiles allFiles = (encRoot, nodesForEmbedding) where
BuiltinType
BuiltinFloat64
->
11
BuiltinType
BuiltinText
->
12
BuiltinType
BuiltinData
->
13
BuiltinType
BuiltinObject
->
1
9
BuiltinType
BuiltinObject
->
1
8
ListType
_
->
14
EnumType
_
->
15
StructType
_
->
16
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment