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
4802eee2
Commit
4802eee2
authored
Apr 01, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Doc proof-read.
parent
db57d130
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
178 additions
and
87 deletions
+178
-87
page.html
doc/_layouts/page.html
+15
-6
cxx.md
doc/cxx.md
+22
-19
encoding.md
doc/encoding.md
+45
-21
install.md
doc/install.md
+62
-14
language.md
doc/language.md
+21
-18
stylesheet.css
doc/stylesheets/stylesheet.css
+13
-9
No files found.
doc/_layouts/page.html
View file @
4802eee2
...
...
@@ -59,15 +59,21 @@
var
menu
=
document
.
getElementById
(
"menu"
);
var
setMenuLayout
=
function
()
{
if
(
window
.
innerWidth
<
117
0
)
{
if
(
window
.
innerWidth
<
90
0
)
{
document
.
body
.
className
=
"narrow"
;
menu
.
className
=
""
;
}
else
if
(
window
.
scrollY
<
219
||
window
.
innerHeight
<
menu
.
clientHeight
+
20
)
{
document
.
body
.
className
=
"wide"
;
menu
.
className
=
""
;
}
else
{
document
.
body
.
className
=
"wide"
;
menu
.
className
=
"floating"
;
if
(
window
.
innerWidth
<
1170
)
{
document
.
body
.
className
=
"normal"
;
}
else
{
document
.
body
.
className
=
"wide"
;
}
if
(
window
.
scrollY
<
219
||
window
.
innerHeight
<
menu
.
clientHeight
+
20
)
{
menu
.
className
=
""
;
}
else
{
menu
.
className
=
"floating"
;
}
}
};
setMenuLayout
();
...
...
@@ -166,6 +172,9 @@
parent
.
appendChild
(
item
);
}
}
var
menu
=
document
.
getElementById
(
"menu"
);
document
.
getElementById
(
"main_content"
).
style
.
minHeight
=
menu
.
clientHeight
+
100
+
"px"
;
})()
</script>
...
...
doc/cxx.md
View file @
4802eee2
...
...
@@ -64,18 +64,17 @@ void printAddressBook(int fd) {
This implementation makes use of C++11 features. If you are using GCC, you will need at least
version 4.7 to compile Cap'n Proto, with
`--std=gnu++0x`
. Other compilers have not been tested at
this time. In general, you do not need to understand C++11 features to _use_ Cap'n Proto; it all
happens under the hood.
this time.
This implementation prefers to handle errors using exceptions. Exceptions are only used in
circumstances that should never occur in normal opertaion. For example, exceptions are thrown
on assertion failures (indicating bugs in the code), network failures
(indicating incorrect
configuration), and invalid input. Exceptions thrown by Cap'n Proto are never part of the
interface and never need to be caught in correct usage. The purpose of throwing exceptions is
to
allow higher-level code a chance to recover from unexpected circumstances without disrupting other
work happening in the same process. For example, a server that handles requests from multiple
clients should, on exception, return an error to the client that caused the exception and clos
e
that connection, but should continue
handling other connections normally.
on assertion failures (indicating bugs in the code), network failures
, and invalid input.
Exceptions thrown by Cap'n Proto are never part of the interface and never need to be caught in
correct usage. The purpose of throwing exceptions is to allow higher-level code a chance
to
recover from unexpected circumstances without disrupting other work happening in the same process.
For example, a server that handles requests from multiple clients should, on exception, return an
error to the client that caused the exception and close that connection, but should continu
e
handling other connections normally.
When Cap'n Proto code might throw an exception from a destructor, it first checks
`std::uncaught_exception()`
to ensure that this is safe. If another exception is already active,
...
...
@@ -86,7 +85,7 @@ In recognition of the fact that some teams prefer not to use exceptions, and tha
exceptions in the compiler introduces overhead, Cap'n Proto allows you to disable them entirely
by registering your own exception callback. The callback will be called in place of throwing an
exception. The callback may abort the process, and is required to do so in certain circumstances
(
e.g.
when a fatal bug is detected). If the callback returns normally, Cap'n Proto will attempt
(when a fatal bug is detected). If the callback returns normally, Cap'n Proto will attempt
to continue by inventing "safe" values. This will lead to garbage output, but at least the program
will not crash. Your exception callback should set some sort of a flag indicating that an error
occurred, and somewhere up the stack you should check for that flag and cancel the operation.
...
...
@@ -100,6 +99,7 @@ To generate C++ code from your `.capnp` [interface definition](language.html), r
capnpc myproto.capnp
This will create
`myproto.capnp.h`
and
`myproto.capnp.c++`
in the same directory as
`myproto.capnp`
.
(Currently, it also dumps some debug info to stdout, e.g. the offset of each field.)
_TODO: This will become more complicated later as we add support for more languages and such._
...
...
@@ -149,11 +149,11 @@ MyStruct::Reader getMyStructField();
`Foo::Builder`
, meanwhile, has two or three methods for each field
`bar`
:
*
`getBar()`
: For primitives, returns the value. For composites, returns a Builder for the
composite. If a composite field has not been initialized (i
ts pointer is null), it will be
initialized to a copy of the field's default value before returning.
composite. If a composite field has not been initialized (i
.e. this is the first time it has
been accessed), it will be
initialized to a copy of the field's default value before returning.
*
`setBar(x)`
: For primitives, sets the value to X. For composites, sets the value to a copy of
x, which must be a Reader for the type.
*
`initBar(n)`
: Only for lists
(including blobs). Sets the field to a newly-allocated list
*
`initBar(n)`
: Only for lists
and blobs. Sets the field to a newly-allocated list or blob
of size n and returns a Builder for it. The elements of the list are initialized to their empty
state (zero for numbers, default values for structs).
*
`initBar()`
: Only for structs. Sets the field to a newly-allocated struct and returns a
...
...
@@ -190,7 +190,8 @@ void setMyListField(::capnproto::List<double>::Reader value);
## Lists
Lists are represented by the type
`capnproto::List<T>`
, where
`T`
is any of the primitive types,
any Cap'n Proto user-defined type,
`capnproto::Text`
,
`capnproto::Data`
, or
`capnproto::List<T>`
.
any Cap'n Proto user-defined type,
`capnproto::Text`
,
`capnproto::Data`
, or
`capnproto::List<U>`
(to form a list of lists).
The type
`List<T>`
itself is not instantiatable, but has two inner classes:
`Reader`
and
`Builder`
.
As with structs, these types behave like pointers to read-only and read-write data, respectively.
...
...
@@ -213,16 +214,18 @@ values when the list is created.
## Enums
Cap'n Proto enums become C++11 "enum classes". That means
,
they behave like any other enum, but
Cap'n Proto enums become C++11 "enum classes". That means they behave like any other enum, but
the enum's values are scoped within the type. E.g. for an enum
`Foo`
with value
`bar`
, you must
refer to the value as
`Foo::BAR`
.
The enum class's base type is
`uint16_t`
.
refer to the value as
`Foo::BAR`
.
To match prevaling C++ style, an enum's value names are converted to UPPERCASE_WITH_UNDERSCORES
(whereas in the definition language you'd write them in camelCase).
Keep in mind when writing
`switch`
blocks that an enum read off the wire may have a numeric
value that is not listed in its definition. This may be the case if the sender is using a newer
version of the protocol, or if the message is corrupt or malicious.
version of the protocol, or if the message is corrupt or malicious. In C++11, enums are allowed
to have any value that is within the range of their base type, which for Cap'n Proto enums is
`uint16_t`
.
## Blobs (Text and Data)
...
...
@@ -252,11 +255,11 @@ Interfaces (RPC) are not yet implemented at this time.
To create a new message, you must start by creating a
`capnproto::MessageBuilder`
(
`capnproto/message.h`
). This is an abstract type which you can implement yourself, but most users
will want to use
`capnproto::MallocMessageBuilder`
. Once your message is constructed, write it to
a file descriptor
`capnproto::writeMessageToFd(fd, builder)`
(
`capnproto/serialize.h`
) or
a file descriptor
with
`capnproto::writeMessageToFd(fd, builder)`
(
`capnproto/serialize.h`
) or
`capnproto::writePackedMessageToFd(fd, builder)`
(
`capnproto/serialize-packed.h`
).
To read a message, you must create a
`capnproto::MessageReader`
, which is another abstract type.
Implementations are specific to the
import
source. You can use
`capnproto::StreamFdMessageReader`
Implementations are specific to the
data
source. You can use
`capnproto::StreamFdMessageReader`
(
`capnproto/serialize.h`
) or
`capnproto::PackedFdMessageReader`
(
`capnproto/serialize-packed.h`
)
to read from file descriptors; both take the file descriptor as a constructor argument.
...
...
doc/encoding.md
View file @
4802eee2
...
...
@@ -12,8 +12,8 @@ by this spec is newer than what is actually implemented.
## 64-bit Words
For the purpose of Cap'n Proto, a "word" is defined as 8 bytes, or 64 bits. Since alignment of
data is important, all objects
are aligned to word boundaries, and sizes are usually expressed in
terms of words.
data is important, all objects
(structs, lists, and blobs) are aligned to word boundaries, and
sizes are usually expressed in
terms of words.
## Messages
...
...
@@ -39,9 +39,6 @@ a message into multiple segments may be convenient:
The first word of the first segment of the message is always a pointer pointing to the message's
root struct.
Note that users of Cap'n Proto never need to understand segments; this is all taken care of
automatically by the runtime library.
## Built-in Types
The built-in primitive types are encoded as follows:
...
...
@@ -59,11 +56,13 @@ The built-in blob types are encoded as follows:
*
`Data`
: Encoded as a pointer, identical to
`List(UInt8)`
.
*
`Text`
: Like
`Data`
, but the content must be valid UTF-8, the last byte of the content must be
zero, and no other byte of the content can be zero.
zero, and no other byte of the content can be zero. Note that the NUL terminator is included in
the size sent on the wire, but the runtime library should not count it in any size reported to
the application.
## Enums
Enums are encoded the same as
16-bit integers
.
Enums are encoded the same as
`UInt16`
.
## Lists
...
...
@@ -74,9 +73,9 @@ A list value is encoded as a pointer to a flat array of values.
|A| B |C | D |
+-+-----------------------------+--+----------------------------+
A (2 bits) =
0
1, to indicate that this is a list pointer.
A (2 bits) = 1, to indicate that this is a list pointer.
B (30 bits) = Offset, in words, from the start of the pointer to the
start of the list. Signed.
start of the
first element of the
list. Signed.
C (3 bits) = Size of each element:
0 = 0 (e.g. List(Void))
1 = 1 bit
...
...
@@ -120,7 +119,7 @@ A struct pointer looks like this:
|A| B | C | D |
+-+-----------------------------+---------------+---------------+
A (2 bits) = 0
0
, to indicate that this is a struct pointer.
A (2 bits) = 0, to indicate that this is a struct pointer.
B (30 bits) = Offset, in words, from the start of the pointer to the
start of the struct's data section. Signed.
C (16 bits) = Size of the struct's data section, in words.
...
...
@@ -133,8 +132,8 @@ Ignoring unions, the layout of fields within the struct is determined by the fol
For each field of the struct, ordered by field number {
If the field is a pointer {
Add it to the end of the pointer section.
} else if the data section layout so far includes p
adding large
enough and properly-aligned
to hold this field {
} else if the data section layout so far includes p
roperly-aligned
padding large enough
to hold this field {
Replace the padding space with the new field, preferring to
put the field as close to the beginning of the section as
possible.
...
...
@@ -165,14 +164,15 @@ When unions are present, add the following logic:
member at all. (See no-union logic, above.)
}
} else {
Treat it as a regular field
. (See no-union logic, above.)
Assign an offset as normal
. (See no-union logic, above.)
}
}
Note that in the worst case, the members of a union could end up using 23 bytes plus one bit (one
pointer plus data section locations of 64, 32, 16, 8, and 1 bits). This is an unfortunate side
effect of the desire to pack fields in the smallest space where they will fit and the need to
maintain backwards-compatibility as fields are added. The worst case should be rare in practice.
maintain backwards-compatibility as fields are added. The worst case should be rare in practice,
and can be avoided entirely by always declaring a union's largest member first.
### Default Values
...
...
@@ -201,7 +201,7 @@ the pointer as a "far pointer", which looks like this:
|A| B | C |
+-+-----------------------------+-------------------------------+
A (2 bits) =
0
2, to indicate that this is a far pointer.
A (2 bits) = 2, to indicate that this is a far pointer.
B (30 bits) = Offset, in words, from the start of the target segment
to the location of the far-pointer landing-pad within that
segment.
...
...
@@ -221,14 +221,14 @@ The reason for the convoluted double-far convention is to make it possible to fo
to an object in a segment that is full. If you can't allocate even one word in the segment where
the target resides, then you will need to allocate a landing pad in some other segment, and use
this double-far approach. This should be exceedingly rare in practice since pointers are normally
set to point to
_new_ object
s.
set to point to
new objects, not existing one
s.
## Serialization Over a Stream
When transmitting a message, the segments must be framed in some way, i.e. to communicate the
number of segments and their sizes before communicating the actual data. The best framing approach
may differ depending on the medium -- for example, messages read via
`mmap`
or shared memory may
call for different approach than messages sent over a socket or a pipe. Cap'n Proto does not
call for
a
different approach than messages sent over a socket or a pipe. Cap'n Proto does not
attempt to specify a framing format for every situation. However, since byte streams are by far
the most common transmission medium, Cap'n Proto does define and implement a recommended framing
format for them.
...
...
@@ -238,7 +238,7 @@ little-endian.
*
(4 bytes) The number of segments, minus one (since there is always at least one segment).
*
(N
*
4 bytes) The size of each segment, in words.
*
(0 or 4 bytes) Padding up to
a multiple of words
.
*
(0 or 4 bytes) Padding up to
the next word boundary
.
*
The content of each segment, in order.
## Packing
...
...
@@ -271,9 +271,33 @@ In addition to the above, there are two tag values which are treated specially:
long text blobs. Because of this rule, the worst-case space overhead of packing is 2 bytes per
2 KiB of input (256 words = 2KiB).
Packing is normally applied on top of the standard stream framing described in the previous
section.
## Compression
When Cap'n Proto messages may contain repetitive data (especially, large text blobs), it makes sense
to apply a standard compression algorithm in addition to packing. When CPU time is also still
important, we recommend Google's
[
Snappy
](
https://code.google.com/p/snappy/
)
. Otherwise,
[
zlib
](
http://www.zlib.net
)
is probably a good choice.
to apply a standard compression algorithm in addition to packing. When CPU time is scarce, we
recommend Google's
[
Snappy
](
https://code.google.com/p/snappy/
)
. Otherwise,
[
zlib
](
http://www.zlib.net
)
is slower but will compress more.
## Security Notes
A naive implementation of a Cap'n Proto reader may be vulnerable to DoS attacks based on two types
of malicious input:
*
A message containing cyclic (or even just overlapping) pointers can cause the reader to go into
an infinite loop while traversing the content.
*
A message with deeply-nested objects can cause a stack overflow in typical code which processes
messages recursively.
To defend against these attacks, every Cap'n Proto implementation should implemented the following
restrictions by default:
*
As the application traverses the message, each time a pointer is dereferenced, a counter should
be incremented by the size of the data to which it points. If this counter goes over some limit,
an error should be raised, and/or default values should be returned. The C++ implementation
currently defaults to a limit of 64MiB, but allows the caller to set a different limit if desired.
*
As the application traverses the message, the pointer depth should be tracked. Again, if it goes
over some limit, an error should be raised. The C++ implementation currently defaults to a limit
of 64 pointers, but allows the caller to set a different limit.
doc/install.md
View file @
4802eee2
...
...
@@ -65,7 +65,7 @@ productivity, so I really like using Ekam.
Unfortunately it's very much unfinished. It works (for me), but it is quirky and rough around the
edges. It only works on Linux, and is best used together with Eclipse. If you find it
unacceptable, scroll down to the
Automake instructions, below
.
unacceptable, scroll down to the
[
Automake instructions
](
#building_with_automake
)
.
The Cap'n Proto repo includes a script which will attempt to set up Ekam for you.
...
...
@@ -79,18 +79,61 @@ symlinks under src. It also imports the [Google Test](https://googletest.google
Once Ekam is installed, you can do:
make -f Makefile.ekam
continuous
make -f Makefile.ekam
once
This will build everything it can and run tests. If successful, the benchmarks will be built
and saved in
`tmp/capnproto/benchmark`
. Try running
`tmp/capnproto/benchmark/runner`
.
This will build everything it can and run tests.
Note that Ekam will fail to build some things and output a bunch of error messages. You should
be able to ignore any errors that originate outside of the
`capnproto`
directory -- these are just
parts of other packages like Google Test that Ekam doesn't fully know how to build, but aren't
needed by Cap'n Proto anyway.
### Running the Benchmarks
Before getting into benchmarks, let me be frank: performance varies wildly by use case, and no
benchmark is going to properly reflect the big picture. If performance is critical to your use
case, you should write a benchmark specific to your case, and test multiple serialization
technologies. Don't assume anything. If you find Cap'n Proto performs sub-optimally, though,
[
tell us about it
](
https://groups.google.com/group/capnproto
)
.
That said, Cap'n Proto does have a small suite of silly benchmarks used to validate changes.
The Ekam build will put the benchmark binaries in
`tmp/capnproto/benchmark`
.
tmp/capnproto/benchmark
This runs the default test case, CatRank. CatRank simulates a search engine scoring algorithm
which promotes pages that discuss cats (and demotes ones discussing dogs). A list of up to 1000
random search results with URLs, scores, and snippets is sent to the server, which searches the
snippets for instances of "cat" and "dog", adjusts their scores accordingly, then returns the new
result list sorted by score.
This test case is very string-heavy. Cap'n Proto performs well due to its zero-copy strings, but
packing the message doesn't help much.
tmp/capnproto/benchmark eval
In this test case, the client generates a random, deeply-nested arithmetic expression for the
server to evaluate. This case is a pathologically bad case for Cap'n Proto as it involves lots of
pointers with relatively little actual data. When packing is enabled it actually loses to
Protobufs by a little bit on CPU time (as of this writing, at least; it'll probably get better with
optimization).
tmp/capnproto/benchmark carsales
This test case involves sending to the server a description of a bunch of cars, and asks the server
to decide how much the lot is worth. This case is very number-heavy, and because of this
Cap'n Proto's "packed" mode really shines.
### Developing with Ekam
If you intend to do some development, you should build
`continuous`
or
`continuous-opt`
instead
of
`once`
. These modes will build everything, then watch the source tree for changes and rebuild
as necessary.
`continuous`
does a debug build while
`continuous-opt`
optimizes; the former is best
while developing but don't run the benchmarks in debug mode!
If you use Eclipse, you should use the Ekam Eclipse plugin to get build results fed back into your
editor. Build the plugin like so:
editor
while building in continuous mode
. Build the plugin like so:
1.
Open the
`.ekam/eclipse`
directory as an Eclipse project.
2.
File -> Export -> Plug-in Development -> Deployable Plug-ins and Fragments.
...
...
@@ -102,10 +145,10 @@ editor. Build the plugin like so:
within this project.
6.
Window -> Show View -> Other -> Ekam -> Ekam Dashboard
The dashboard view lets you browse the whole tree
and also populates your editor with err
or
markers.
The dashboard view lets you browse the whole tree
of build actions and also populates your edit
or
with error
markers.
### Building
W
ith Automake
### Building
w
ith Automake
If setting up Ekam is too much work for you, you can also build with Automake.
...
...
@@ -117,17 +160,22 @@ If setting up Ekam is too much work for you, you can also build with Automake.
unzip gtest-1.6.0.zip
cd gtest-1.6.0
./configure
make
cp -r include/gtest $PREFIX/include/gtest
cp ./lib/.libs/*.a $PREFIX/lib
make -j4
mkdir -p ~/gtest-install/include
mkdir -p ~/gtest-install/lib
cp -r include/gtest ~/gtest-install/include/gtest
cp ./lib/.libs/*.a ~/gtest-install/lib
2.
Clone and build the Cap'n Proto code.
git clone https://github.com/kentonv/capnproto.git
cd capnproto/c++
autoreconf -i
./configure
make check
CXXFLAGS="-O2 -DNDEBUG -I$HOME/gtest-install/include" \
LDFLAGS="-L$HOME/gtest-install/lib" \
./configure
make -j4 check
sudo make install
This will install libcapnproto.a in /usr/local/lib and headers in /usr/local/include/capnproto.
This will install
`libcapnproto.a`
in
`/usr/local/lib`
and headers in
`/usr/local/include/capnproto`
.
doc/language.md
View file @
4802eee2
...
...
@@ -40,9 +40,8 @@ struct Date {
Some notes:
*
Types come after names. This makes sense because the name is usually the thing you are looking
for when you read the code, so it should be up front where it is easiest to see, not hidden later
on the line. Sorry, C got it wrong.
*
Types come after names. The name is by far the most important thing to see, especially when
quickly skimming, so we put it up front where it is most visible. Sorry, C got it wrong.
*
The
`@N`
annotations show how the protocol evolved over time, so that the system can make sure
to maintain compatibility with older versions. Fields (and enum values, and interface methods)
must be numbered consecutively starting from zero in the order in which they were added. In this
...
...
@@ -95,7 +94,7 @@ The following types are automatically defined:
Notes:
*
The
`Void`
type has exactly one possible value, and thus can be encoded in zero b
yte
s. It is
*
The
`Void`
type has exactly one possible value, and thus can be encoded in zero b
it
s. It is
rarely used, but can be useful as a union member.
*
`Text`
is always UTF-8 encoded and NUL-terminated.
*
`Data`
is a completely arbitrary sequence of bytes.
...
...
@@ -142,6 +141,7 @@ struct Person {
employer @6 in employment :Company;
school @7 in employment :School;
selfEmployed @8 in employment :Void;
# We assume that a person is only one of these.
}
{% endhighlight %}
...
...
@@ -149,12 +149,13 @@ Notes:
*
Unions are numbered in the same number space as other fields. Remember that the purpose of the
numbers is to indicate the evolution order of the struct. The system needs to know when the union
was declared relative to the fields in it. Also note that
at most
one element of the union is
allowed to have a number less than the union's number, as unionizing two or more
existing fields
would change their layout.
was declared relative to the fields in it. Also note that
no more than
one element of the union is
allowed to have a number less than the union's number, as unionizing two or more
pre-existing
fields
would change their layout.
*
Notice that we used the "useless"
`Void`
type here. We don't have any extra information to store
for the
`unemployed`
or
`selfEmployed`
cases, but we still want the union to have tags for them.
for the
`unemployed`
or
`selfEmployed`
cases, but we still want the union to distinguish these
states from others.
### Enums
...
...
@@ -204,7 +205,7 @@ interface File {
{% endhighlight %}
Notice something interesting here:
`FileInfo`
is a struct, but it contains a
`File`
, which is an
interface. Structs (and primitive types) are passed by value, but interfaces are passed by
interface. Structs (and primitive types) are passed
over RPC
by value, but interfaces are passed by
reference. So when
`Directory.open`
is called remotely, the content of a
`FileInfo`
(including
values for
`name`
and
`size`
) is transmitted back, but for the
`file`
field, only the address of
some remote
`File`
object is sent.
...
...
@@ -218,7 +219,8 @@ reference to an object inherently represents a "capability" to access it.
### Constants
You can define constants in Cap'n Proto. Constants can have any value.
You can define constants in Cap'n Proto. These don't affect what is sent on the wire, but they
will be included in the generated code.
{% highlight capnp %}
const pi :Float32 = 3.14159;
...
...
@@ -237,11 +239,11 @@ struct Foo {
struct Bar {
#...
}
bar@0 :Bar;
bar
@0 :Bar;
}
struct Baz {
bar@0 :Foo.Bar;
bar
@0 :Foo.Bar;
}
{% endhighlight %}
...
...
@@ -250,12 +252,12 @@ If typing long scopes becomes cumbersome, you can use `using` to declare an alia
{% highlight capnp %}
struct Qux {
using Foo.Bar;
bar@0 :Bar;
bar
@0 :Bar;
}
struct Corge {
using T = Foo.Bar;
bar@0 :T;
bar
@0 :T;
}
{% endhighlight %}
...
...
@@ -266,7 +268,7 @@ An `import` expression names the scope of some other file:
{% highlight capnp %}
struct Foo {
# Use type "Baz" defined in bar.capnp.
baz@0 :import "bar.capnp".Baz;
baz
@0 :import "bar.capnp".Baz;
}
{% endhighlight %}
...
...
@@ -277,7 +279,7 @@ using Bar = import "bar.capnp";
struct Foo {
# Use type "Baz" defined in bar.capnp.
baz@0 :Bar.Baz;
baz
@0 :Bar.Baz;
}
{% endhighlight %}
...
...
@@ -302,10 +304,11 @@ A protocol can be changed in the following ways without breaking backwards-compa
*
New parameters may be added to a method. The new parameters must be added to the end of the
parameter list and must have default values.
*
Any symbolic name can be changed, as long as the ordinal numbers stay the same.
*
Types definitions can be moved to different scopes.
*
A field of type
`List(T)`
, where
`T`
is NOT a struct type, may be changed to type
`List(U)`
,
where
`U`
is a struct type whose
field number 0
is of type
`T`
. This rule is useful when you
where
`U`
is a struct type whose
`@0`
field
is of type
`T`
. This rule is useful when you
realize too late that you need to attach some extra data to each element of your list. Without
this rule, you would be stuck defining parallel lists, which are ugly.
this rule, you would be stuck defining parallel lists, which are ugly
and error-prone
.
Any other change should be assumed NOT to be safe. Also, these rules only apply to the Cap'n Proto
native encoding. It is sometimes useful to transcode Cap'n Proto types to other formats, like
...
...
doc/stylesheets/stylesheet.css
View file @
4802eee2
...
...
@@ -279,6 +279,10 @@ Full-Width Styles
margin
:
0
auto
;
}
body
.normal
#main_content
.inner
{
margin
:
0
auto
0
250px
;
}
#discuss_banner
{
display
:
block
;
position
:
absolute
;
...
...
@@ -481,7 +485,7 @@ Small Device Styles
}
.wide
#corner_hack
{
body
.wide
#corner_hack
,
body
.normal
#corner_hack
{
position
:
absolute
;
left
:
0px
;
top
:
209px
;
...
...
@@ -490,7 +494,7 @@ Small Device Styles
background
:
#212121
;
}
.wide
#corner_hack
>
div
{
body
.wide
#corner_hack
>
div
,
body
.normal
#corner_hack
>
div
{
margin-left
:
249px
;
height
:
10px
;
border-radius
:
10px
0px
0px
0px
;
...
...
@@ -499,7 +503,7 @@ Small Device Styles
border-left
:
1px
solid
#111
;
}
.wide
#menu
{
body
.wide
#menu
,
body
.normal
#menu
{
position
:
absolute
;
left
:
0px
;
top
:
219px
;
...
...
@@ -507,12 +511,12 @@ Small Device Styles
z-index
:
10
;
}
.wide
#menu
.floating
{
body
.wide
#menu
.floating
,
body
.normal
#menu
.floating
{
position
:
fixed
;
top
:
0px
;
}
.narrow
#menu
{
body
.narrow
#menu
{
position
:
relative
;
max-width
:
640px
;
padding
:
50px
10px
0px
10px
;
...
...
@@ -520,7 +524,7 @@ Small Device Styles
}
@media
screen
and
(
max-width
:
480px
)
{
.narrow
#menu
{
body
.narrow
#menu
{
min-width
:
320px
;
max-width
:
480px
;
}
...
...
@@ -541,16 +545,16 @@ Small Device Styles
border-right
:
1px
solid
#111
;
}
.wide
#menu
>
ul
>
li
:last-child
{
body
.wide
#menu
>
ul
>
li
:last-child
,
body
.normal
#menu
>
ul
>
li
:last-child
{
border-radius
:
0px
0px
10px
0px
;
border-bottom
:
1px
solid
#111
;
}
.narrow
#menu
>
ul
>
li
:first-child
{
body
.narrow
#menu
>
ul
>
li
:first-child
{
border-radius
:
10px
10px
0px
0px
;
}
.narrow
#menu
>
ul
>
li
:last-child
{
body
.narrow
#menu
>
ul
>
li
:last-child
{
border-radius
:
0px
0px
10px
10px
;
}
...
...
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