C had no front end for the schema language at all. The compiler directory holds a code generator plugin, which is handed a request by another tool and never sees schema text, so a .zap file could not be read here in either form -- indentation or braces. zapgen reads it. Whitespace-significant source is rewritten into the brace form BEFORE the parser, exactly as the Go reference does it: a near identity that only adds the two tokens the brace grammar requires where the indented form leaves them out. A file already in braces comes back byte for byte, so one grammar reads both styles and neither is a dialect of the other. The identifier grammar is not restated. Its Unicode ranges are taken from Go's own tables by gen/table, so a name this parser accepts is a name the Go parser accepts, and a Go release that moves Unicode moves both. The generated header gives each struct a view over the message bytes and one reader per field at a fixed offset. Reading is in place and total: a field past the end reads zero, a pointer into the head or out of the message reads null. zap_view.h is the one place that says so. Checked against the Go front end on every .zap in the estate plus 55 adversarial cases and 15000 random ones: the brace form each writes is byte-identical, the layout each reads is field-for-field the same, and they accept and refuse the same files for the same stated reason. A message built by the Go runtime reads back through these bindings with every field equal.
3.9 KiB
Docs: ZAP C SDK · part of the ZAP Protocol
zapc-c
This is the C language plugin (zapc-c) and runtime for ZAP,
an efficient protocol for sharing data and capabilities.
Security warning!
The generated code assumes all input to be trusted. Do NOT use with untrusted input! There is currently no code in place to check if structures/pointers are within bounds.
This repository contains the code generator plugin together with the runtime library required to use it.
Building on Linux
git clone --recurse-submodules [email protected]:zap-proto/c.git zap-c
cd zap-c
autoreconf -f -i -s
./configure
make
make check
Building with Meson
git clone --recurse-submodules [email protected]:zap-proto/c.git zap-c
cd zap-c
meson setup build
meson compile -C build
build/zap-test
Usage
Reading a .zap schema: zapgen
zapgen reads a ZAP schema and writes the C it describes. Schemas are
written whitespace-significant — indentation opens a block, and each field
takes the next free byte after the one before it:
package echo
struct Ping
Seq u64
Sender bytes_fixed[32]
Note text
interface Echo
ping(req: Ping) returns (resp: Pong)
zapgen echo.zap # writes echo.zap.h beside the input
zapgen -o gen echo.zap # writes it into gen/
zapgen -c echo.zap # reads the schema and says nothing if it holds
zapgen -d echo.zap # writes the brace form of the schema to stdout
The brace form — struct S { A u8 @0 }, every field carrying its byte —
is the same language said explicitly, and a file already written that way
passes through zapgen -d byte for byte. The two styles may be mixed one
declaration at a time.
The generated header gives each struct a view over the message bytes and
one reader per field, each taking its value from a fixed offset. Reading is
in place: nothing is copied, and no reader can step outside the message.
Include <zap_view.h> — it comes with the library — and the header the
schema produced.
This is the same schema language, read the same way, as ZAP for Go; the two front ends are checked against each other on every schema in the estate.
Generating C code from a Cap'n Proto schema
The compiler directory contains the C language plugin (zapc-c) for use with
the zap tool.
zap will by default search $PATH for zapc-c — if it's on your PATH, you
can generate code for your schema as follows:
zap compile -o c myschema.zap
Otherwise, you can specify the path to the c plugin:
zap compile -o ./zapc-c myschema.zap
zap generates a C struct that corresponds to each ZAP struct, along with
read/write functions that convert to/from ZAP wire form.
If you want accessor functions for struct members, use attribute fieldgetset
in your .zap file as follows:
using C = import "/c.zap";
$C.fieldgetset;
struct MyStruct {}
Example C code
See the unit tests in tests/example-test.cpp.
The example schema file is tests/addressbook.zap.
The tests are written in C++, but only use C features.
You need to compile these runtime library files and link them into your own project's binaries:
Your include path must contain the runtime library directory
lib. Header file lib/zap_c.h contains the public
interfaces of the library.
Using make-based builds, make may try to compile ${x}.zap from ${x}.zap.c
using its built-in rule for compiling ${y} from ${y}.c. You can either
disable make's built-in compile rules or just this specific case with the no-op
rule: %.zap: ;.
For further reference, please see the other unit tests in tests, and
header file lib/zap_c.h.