a59d3fb044 | ||
---|---|---|
.. | ||
external | ||
generated | ||
include/bond_lite | ||
schema | ||
tests | ||
README.md |
README.md
Bond Lite
A simple C++ implementation of Bond compact binary protocol.
Why?
The original Bond library has many great features which make it easy to use, but at the same time, make it dependent on various libraries from Boost like Variant or MPL. This means that in order to use Bond even in the simplest case, just to encode some data and send them away, Boost has to be added to the target application build, together with a lot of unnecessary features, C++ exceptions support etc.
Because our use case is exactly a very simple one-way encoding of data and we don't need the advanced features provided by the full Bond library, a simple light-weight implementation of Bond serializer was created instead, based on the simplistic approach used in the TypeScript Bond implementation. It works with the same Bond schema descriptions as a source, but does not require anything else than a compliant C++11 compiler and STL to be used.
Compatibility
This serializer is limited in many ways, targeted primarily to be able to encode Aria telemetry packets in Skype applications. The schema used by Aria does not use all Bond features.
Furthermore, the deserializer is supposed to be used only by unit and functional tests written as part of the C++ Aria client library, so there are even less requirements for its performance and robustness.
These limitations are in place:
- Only the Bond compact binary protocol v1 is supported
- Floating-point values work correctly on little-endian architectures only
- Wide-char strings are not supported
- Inheritance (structures with ancestors) is not supported
- All fields are deemed optional, regardless of actual schema modifier
maybe<T>
,nothing
and maybe other Bond features are not supported
However, where possible, the schema processor and the (de)serializer try to detect any unsupported options and features right away, so that any errors would be detected early.
How to use from an application?
Requirements: C++11 compiler
-
Add
bondlite/include
and the directory with generated header files to compiler's include path. -
Add these to the program:
(YourBondSchemaName
depends on the source file name,DataPackage
in Aria case)#include <bond_lite/All.hpp> #include <YourBondSchemaName_types.hpp> #include <YourBondSchemaName_writers.hpp> // for serializing #include <YourBondSchemaName_readers.hpp> // for deserializing
-
Use the types defined by your Bond schema as any other C++ structure or enumeration. All structures have their default constructor, copy constructor, move constructor, assignment operator, move-assignment operator and
==
and!=
operators provided. -
Serialize any defined structure
record
into a binary bloboutput
like this:std::vector<uint8_t> output; bond_lite::CompactBinaryProtocolWriter writer(output); bond_lite::Serialize(writer, record);
-
Deserialize a binary blob
input
to any defined structurerecord
like this:const std::vector<uint8_t> input; bond_lite::CompactBinaryProtocolReader reader(input); if (!bond_lite::Deserialize(reader, record)) { // handle error }
How to (re)generate C++ files from Bond schema?
Requirements: Bond compiler gbc
, Python
-
Convert .bond files to .json schema (
bond_const.bond
is always needed):gbc schema bond_const.bond YourBondSchemaName.bond
-
Convert .json files to .cpp files:
python bondjson2cpp.py YourBondSchemaName.json
-
A common generated file
BondDataTypes.hpp
as well as three header filesYourBondSchemaName_types.hpp
,YourBondSchemaName_writers.hpp
andYourBondSchemaName_readers.hpp
per each user schema will be created for use in the target application.
The .json files (generated by gbc
) and the .hpp files (generated by
bondjson2cpp.py
) are commonly checked-in with the final project to
avoid adding extra dependencies for the most common build case.
How to run unit tests?
If a full Bond library is available (see below), the unit tests compare the results of the Bond Lite serializer with the output from the original Bond implementation.
If not, the results are compared with a hard-coded reference data only (stored previously by someone who had the full Bond library available). This is still useful as a regression test.
The binary blob is then decoded using Bond Lite deserializer again and compared with the original structure. This partially validates also the comparison operator implementation.
Requirements: C++11 compiler, Google Test
Optional: Boost, Bond, RapidJSON
-
Run CMake to prepare project files for the target platform.
-
Build the unit tests project.
-
Run the unit tests binary.
How to prepare full Bond?
If one needs to use the Bond compiler gbc
in order to rebuild a
schema, work on improving the Bond Lite (de)serializer or run the unit
tests in their entirety, the full Bond package must be built beforehand.
Requirements: C++ compiler, Boost, Haskell compiler, RapidJSON, CMake
The following steps describe the process on Windows.
-
Download and install the required tools and libraries if not already available:
https://www.haskell.org/
http://www.boost.org/
http://cmake.org/ -
Perform Haskell Cabal update, e.g.:
"C:\Program Files (x86)\Haskell Platform\7.10.3\lib\extralibs\bin\cabal.exe" update
-
Clone the Bond repository in some workspace:
git clone https://github.com/Microsoft/bond
RapidJSON is bundled as a submodule:
git submodule update --init
-
Create a separate build directory next to it to keep things clean:
mkdir build cd build
-
Set necessary environment variables (update the paths as required):
set CABAL_PATH=C:\Program Files (x86)\Haskell Platform\7.10.3\lib\extralibs set GHC_PATH=C:\Program Files (x86)\Haskell Platform\7.10.3 set BOOST_ROOT=C:\Code\ext\boost_1_60_0
-
Prepare project files:
cmake ..\bond
-
Load the solution into Visual Studio:
start bond.sln
-
Build projects compiler\gbc, bond and bond_apply.
(Project "sandbox" can fail, but it is not a problem.) -
The Bond compiler is built as
compiler\build\gbc\gbc.exe
.
It can be useful to copy it to somewhere where it can be found/reused more easier. -
Copy or symlink the Bond C++ files to the Bond Lite project.
- The whole directory bond\cpp\inc\bond to bondlite\external.
- The whole directory bond\cpp\generated\bond to bondlite\generated.
- The whole directory bond\thirdparty\rapidjson\include\rapidjson to bondlite\external.
-
Generate the Aria Bond C++ files in directory bond-aria:
cd bondlite\generated mkdir bond-aria cd bond-aria gbc c++ ..\..\schema\DataPackage.bond
-
Rebuild the CMake project. It will detect the full Bond is present and use it.
CMake variableBOOST_ROOT_PATH
has to be set correctly -- in dev_buildtools case:ant ... -Dmodule.clienttelemetry.shared=-DBOOST_INCLUDE_PATH=C:\...\boost_1_60_0
Or use cmake-gui in the build directory.