Giter Club home page Giter Club logo

microsoft / bond Goto Github PK

View Code? Open in Web Editor NEW
2.6K 196.0 322.0 17.12 MB

Bond is a cross-platform framework for working with schematized data. It supports cross-language de/serialization and powerful generic mechanisms for efficiently manipulating data. Bond is broadly used at Microsoft in high scale services.

License: MIT License

CMake 0.92% C++ 40.82% C 0.01% C# 20.20% Python 0.81% Haskell 5.48% Emacs Lisp 0.01% PowerShell 0.31% Java 31.18% Groovy 0.09% Shell 0.11% Dockerfile 0.05%

bond's Introduction

The Bond logo: a stylized glue gun


Build Status Bond.CSharp NuGet package

Bond

Bond is an open-source, cross-platform framework for working with schematized data. It supports cross-language serialization/deserialization and powerful generic mechanisms for efficiently manipulating data. Bond is broadly used at Microsoft in high scale services.

Bond is published on GitHub at https://github.com/microsoft/bond/.

For details, see the User's Manuals:

For a discussion about how Bond compares to similar frameworks see Why Bond.

Dependencies

Bond C++ library requires some C++11 features (currently limited to those supported by Visual C++ 2015); a C++11 compiler is required. Additionally, to build Bond you will need CMake (3.1+), Haskell Stack (1.5.1+) and Boost (1.61+).

Additionally, Bond requires RapidJSON. The Bond repository has a Git submodules for RapidJSON. It should be cloned with the --recursive flag:

git clone --recursive https://github.com/microsoft/bond.git

If you already have RapidJSON and would like to build against it, add argument -DBOND_FIND_RAPIDJSON=TRUE to the CMake invocation. It will use find_package(RapidJSON). If you do not provide a RapidJSON library, Bond will also install RapidJSON.

Following are specific instructions for building on various platforms.

Linux

Bond must be built with C++11 compiler. We test with Clang (3.8) and GNU C++ (5.4). We recommend Clang as it's faster with template-heavy code like Bond.

Run the following commands to install the minimal set of packages needed to build the core Bond library on Ubuntu 14.04:

sudo apt-get install \
    clang \
    cmake \
    zlib1g-dev \
    libboost-dev \
    libboost-thread-dev

Additionally, you need the Haskell Tool Stack. If your distro isn't shipping a new enough version of it, you may encounter some non-obvious build failures, so we recommend installing the latest Stack outside of package management:

curl -sSL https://get.haskellstack.org/ | sh

In the root bond directory run:

mkdir build
cd build
cmake ..
make
sudo make install

The build directory is just an example. Any directory can be used as the build destination.

To build the Bond Python module and all the C++/Python tests and examples, a few more packages are needed.

sudo apt-get install \
    autoconf \
    build-essential \
    libboost-date-time-dev \
    libboost-python-dev \
    libboost-test-dev \
    libtool \
    python2.7-dev

CMake needs to be re-run with different options. This can be done after building just the core libraries: the build tree will simply be updated with the new options.

cd build # or wherever you ran CMake before

Running the following command in the build directory will build and execute all the tests and examples:

make --jobs 8 check
sudo make install # To install the other libraries just built

(The unit tests are large so you may want to run 4-8 build jobs in parallel, assuming you have enough memory.)

macOS

Install Xcode and then run the following command to install the required packages using Homebrew (http://brew.sh/):

brew install \
    cmake \
    haskell-stack \
    boost \
    boost-python

(boost-python is optional and only needed for Python support.)

Bond can be built on macOS using either standard *nix makefiles or Xcode. In order to generate and build from makefiles, in the root bond directory run:

mkdir build
cd build
cmake ..
make
sudo make install

Alternatively, you can generate Xcode projects by passing the -G Xcode option to cmake:

cmake -G Xcode ..

You can build and run unit tests by building the check target in Xcode or by running make in the build directory:

make --jobs 8 check

Note that if you are using Homebrew's Python, you'll need to build boost-python from source:

brew install --build-from-source boost-python

and tell cmake the location of Homebrew's libpython by setting the PYTHON_LIBRARY variable, e.g.:

cmake .. \
    -DPYTHON_LIBRARY=/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib

Windows

Build Status

Install the following tools:

If you are building on a network behind a proxy, set the environment variable HTTP_PROXY, e.g.:

set HTTP_PROXY=http://your-proxy-name:80

Now you are ready to build the C# version of Bond. Open the solution file cs\cs.sln in Visual Studio and build as usual. The C# unit tests can also be run from within the solution.

To build using the .NET Core SDK:

dotnet restore cs\cs.sln
dotnet msbuild cs\cs.sln

The C++ and Python versions of Bond additionally require:

You may need to set the environment variables BOOST_ROOT and BOOST_LIBRARYDIR to specify where Boost and its pre-built libraries for your environment (MSVC 12 or MSVC 14) can be found, e.g.:

set BOOST_ROOT=D:\boost_1_61_0
set BOOST_LIBRARYDIR=D:\boost_1_61_0\lib64-msvc-14.0

The core Bond library and most examples only require Boost headers. The pre-built libraries are only needed for unit tests, and Python. If Boost or Python libraries are not found on the system, then some tests and examples will not be built.

To generate a solution to build the Bond Core C++ and Python with Visual Studio 2015 run the following commands from the root bond directory:

mkdir build
cd build
set PreferredToolArchitecture=x64
cmake -G "Visual Studio 14 2015 Win64" ..

Setting PreferredToolArchitecture=x64 selects the 64-bit toolchain which dramatically improves build speed. (The Bond unit tests are too big to build with 32-bit tools.)

Instead of cmake you can also use cmake-gui and specify configuration settings in the UI. This configuration step has to be performed only once. From then on you can use the generated solution build\bond.sln from Visual Studio or build from the command line using cmake:

cmake --build . --target
cmake --build . --target INSTALL

To build and execute the unit tests and examples run:

cmake --build . --target check -- /maxcpucount:8

Alternatively, you can build and install Bond using the vcpkg dependency manager:

git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.bat
./vcpkg integrate install
./vcpkg install bond

The Bond port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request in the vcpkg repository.

Contributing

Interested in contributing to Bond? Take a look at our contribution guidelines to get started.

bond's People

Contributors

alexsatch avatar alfpark avatar ara-ayvazyan avatar bertusgreeff avatar bhardwajs avatar biocomp avatar chwarr avatar csdahlberg avatar dnmiller avatar glenfe avatar hcoona avatar jdubrule avatar jviotti avatar lalo avatar microsoft-github-policy-service[bot] avatar mikemsft avatar musiddi avatar rambho avatar ranrav avatar rblaze avatar redknightlois avatar sapek avatar sigansky avatar smichtch avatar soyyorafa avatar tstein avatar veselinp avatar volka avatar xplicit avatar yanlongli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bond's Issues

Can't compile the sources

Linux platform:

At first I tried to compile on Ubuntu 12.04, cmake 3.10 says -- Could NOT find Boost. I tried to install boost 1.46 and boost 1.48 from the ubuntu packages. Could you please add to the cmake output minimal required version of the Boost?

Then I ordered 1GB RAM Ubuntu 14.04 VPS and tried to compile it again. cabal install update-install drops with out of memory exception. Please add minimum RAM requirements to the documentation.

Also, what is a required mono version for building cs.sln? Will it be built with mono 3.10?

Windows platform:

I followed the steps in documentation (install cmake, haskell, update cabal, open cs.sln in Visual Studio 2013) and run the build. The build has failed on the step:

Generating C:/Projects/bond/compiler/cabal.sandbox.config
Could not find target path 

The path C:\Projects\bond\compiler exists on the machine.

CompactBinary Protocol V2 doesn't work in C#

I updated the Serialization sample to use CBV2 and now it throws a runtime exception. I've seen similar errors with other IDL, but it appears there's some amount of corruption going on with V2.

Code (program.cs):

var writer = new CompactBinaryWriter<OutputBuffer>(output, 2 /* used to be 1 */);

// The first calls to Serialize.To and Deserialize<T>.From can take
// a relatively long time because they generate the de/serializer 
// for a given type and protocol.
Serialize.To(writer, src);

var input = new InputBuffer(output.Data);
var reader = new CompactBinaryReader<InputBuffer>(input, 2 /* used to be 1 */);

Exception:

System.IO.InvalidDataException was unhandled
HResult=-2146233087
Message=Invalid type BT_UINT64, expected BT_STRING
Source=Bond
StackTrace:
at Bond.Expressions.ThrowExpression.ThrowInvalidTypeException(BondDataType expectedType, BondDataType actualType)
at lambda_method(Closure , CompactBinaryReader1 ) at Bond.Deserializer1.Deserialize[T](R reader)
at Bond.Deserialize`1.From[R](R reader)
at Examples.Program.Main() in c:\Users\kylemc\Documents\Visual Studio 2013\Projects\serialization\program.cs:line 29
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:

Support a mode without runtime IL generation

.Net Native doesn't support runtime code generation, which means Bond won't work for WSA projects using .Net native. This could be avoided by generating the serializer/deserializer for each type in the codegen phase instead of using fancy runtime logic.

Need better errors/diagnostics when a type that can't be de/serialized is encountered

This is a re-raising of issue #68 with a better repro. When I update the guid example with the following IDL, I get a TypeInitializationException.

schema.bond

import "bond/core/bond.bond"

namespace Examples

using guid = bond.GUID;

struct Example
{
    0: guid id;
}

program.cs

public static class BondTypeAliasConverter
{
    public static Guid Convert(GUID value, Guid unused)
    {
        return default(Guid);
    }

    public static GUID Convert(Guid value, GUID unused)
    {
        return default(GUID);
    }
}
System.TypeInitializationException was unhandled
  HResult=-2146233036
  Message=The type initializer for 'Cache`2' threw an exception.
  Source=Bond
  TypeName=Cache`2
  StackTrace:
       at Bond.Serialize.To[W,T](W writer, T obj)
       at Examples.Program.Main() in C:\Users\kylemc\Desktop\ToSave\ToSave\guid\program.cs:line 34
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 
       HResult=-2147467261
       Message=Value cannot be null.
Parameter name: field
       ParamName=field
       Source=System.Core
       StackTrace:
            at System.Linq.Expressions.Expression.Field(Expression expression, FieldInfo field)
            at Bond.Expressions.DataExpression.PropertyOrField(Expression expression, String name)
            at Bond.Expressions.ObjectParser.Field(ITransform transform, Expression structVar, UInt16 id, ISchemaField schemaField, IField field)
            at Bond.Expressions.ObjectParser.<>c__DisplayClassc.<Apply>b__7(<>f__AnonymousType0`2 <>h__TransparentIdentifier0, IField knownField)
            at System.Linq.Enumerable.<SelectManyIterator>d__4`3.MoveNext()
            at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
            at Bond.Expressions.ObjectParser.Apply(ITransform transform)
            at Bond.Expressions.SerializerTransform`2.Struct(IParser parser, RuntimeSchema schema, Boolean isBase)
            at Bond.Expressions.SerializerTransform`2.Struct(IParser parser, RuntimeSchema schema)
            at Bond.Expressions.SerializerTransform`2.<>c__DisplayClass2.<GenerateSerialize>b__0(IParser p)
            at Bond.Expressions.SerializerGenerator`2.GenerateSerialize(Serialize serialize, IParser parser, ParameterExpression writer, Boolean inline)
            at Bond.Expressions.SerializerTransform`2.GenerateSerialize(SerializeWithSchema serializeWithSchema, IParser parser, RuntimeSchema schema)
            at Bond.Expressions.SerializerTransform`2.Value(IParser parser, Expression valueType, RuntimeSchema schema)
            at Bond.Expressions.SerializerTransform`2.<>c__DisplayClassc.<>c__DisplayClasse.<Struct>b__7(IParser fieldParser, Expression fieldType)
            at Bond.Expressions.Field.Bond.Expressions.IField.Value(IParser parser, Expression valueType)
            at Bond.Expressions.ObjectParser.Field(ITransform transform, Expression structVar, UInt16 id, ISchemaField schemaField, IField field)
            at Bond.Expressions.ObjectParser.<>c__DisplayClassc.<Apply>b__7(<>f__AnonymousType0`2 <>h__TransparentIdentifier0, IField knownField)
            at System.Linq.Enumerable.<SelectManyIterator>d__4`3.MoveNext()
            at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
            at Bond.Expressions.ObjectParser.Apply(ITransform transform)
            at Bond.Expressions.SerializerTransform`2.Struct(IParser parser, RuntimeSchema schema, Boolean isBase)
            at Bond.Expressions.SerializerTransform`2.Struct(IParser parser, RuntimeSchema schema)
            at Bond.Expressions.SerializerTransform`2.<>c__DisplayClass2.<GenerateSerialize>b__0(IParser p)
            at Bond.Expressions.SerializerGenerator`2.GenerateSerialize(Serialize serialize, IParser parser, ParameterExpression writer, Boolean inline)
            at Bond.Expressions.SerializerTransform`2.GenerateSerialize(SerializeWithSchema serializeWithSchema, IParser parser, RuntimeSchema schema)
            at Bond.Expressions.SerializerTransform`2.Generate(IParser parser)
            at Bond.Serializer`1..ctor(Type type)
            at Bond.Serialize.Cache`2..cctor()
       InnerException: 

Serialization fails is some cases when there are multiple type aliases

[Update]
I got codegen and samples working with two --using="type-alias=generated-code-type" statements in the options. Unfortunately, serialization still fails with the exception below.

I'm trying to author an IDL with multiple aliases. The IDL parses fine, but the compiler doesn't seem to account for more than one kvp in the --using parameter.

Expected:
--using="datetime=System.DateTime;guid=System.Guid" works

[global::Bond.Id(2), global::Bond.Type(typeof(ulong)), global::Bond.Required]
public System.DateTime timestampUtc { get; set; }

Actual:
--using="datetime=System.DateTime;guid=System.Guid"

results in generated code like the following:

[global::Bond.Id(2), global::Bond.Type(typeof(ulong)), global::Bond.Required]
public System.DateTime,guid=System.Guid timestampUtc { get; set; }

Benchmarks

Hi guys,

do you have any reference benchmarks? I was unable to find any ;(
I tried Bond for C# and fast binary was not really fast (usually 2-3 times slower than JSON - which I would assume is really the speed of Newtonsoft).

Also is there a better API than Bond.Deserialize<T>.From(reader)
something like Bond.Deserialize.From(reader, type) ?

NuGet package for .NET

I did not find nuget package for bond serializer. If it exists, please add couple of string into docs about its name and how to install it into .NET app. If it does not exist it would be great to upload it to nuget.org.

Add the ability to serialize byte array into blob field

Currently, Bond library requires to use ArraySegment<byte> in objects to serialize bytes into blobs. If I use byte array byte [] serializer/desirializer uses algorithm for Lists to serialize/desirialize the array. This is significally slower than using Buffer.BlockCopy, which is used for ArraySegment.

if I add an explicity declaration to use a blob for byte array

    [global::Bond.Id(0), global::Bond.Type(typeof(global::Bond.Tag.blob))]
    public byte[] Arr { get; set; }

Then I'll get an exception, System.ArgumentException : Instance property 'Array' is not defined for type 'System.Byte[]'

It would be nice if byte arrays serializes into blobs by default.

Tagged text protocol for debugging/diagnostics

There should be a tagged text protocol. This would be useful for debugging/diagnostics when dealing with tagged protocols. I'm really slow at reading compact binary, but I'm pretty fast at reading text.

A motivating example from some work I did a few days ago: I need to compare two compact binary payloads. With a text protocol, I could transcod them to this tagged text protocol and then diff tools would work on them.

This might also be useful for things like the Fiddler inspector mentioned in #74.

Given a struct like the following:

struct CoolStuff
{
    0: string StringField;
    1: int32 IntWithDefault = 1;
    2: vector<bool> SequenceContainer;
    3: map<string, string> MapContainer;
}

and an instance of this:

myCoolStuff = make CoolStuff
    with
        StringField = "once upon a time"
        SequenceContainer = make array:bool t,f,f
        MapContainer = make dict:string_string "there" : "was", "a" : "kingdom"

This would be represented in some tagged text protocol as:

((#:id 0 #:type string #:value "once upon a time")
 (#:id 2 #:type vector #:valueType bool #:size 3 #:value (true false false))
 (#:id 3 #:type map #:keyType string #:valueType string #:size 2 #:value (("there" "was") ("a" "kingdom"))))

Circular references

Is it possible to serialize object graphs with circular references? For example,

struct Example
{
    0: string Name;
    1: nullable<Example> Previous;
    2: nullable<Example> Next;
}

The code below results in StackOverflowException during serialization:

// c# code
var first = new Example { Name = "First" };
var second = new Example { Name = "Second" };
first.Next = second;
second.Previous = first;

var output = new OutputBuffer();
var writer = new SimpleBinaryWriter<OutputBuffer>(output);
Serialize.To(writer, first);

Generator does not suppress or propagate doc comments

When I use IDL codegen in a project that's building XML docs, I get the following error.

My_types.cs(201,16,201,26): error CS1591: Warning as Error: Missing XML comment for publicly visible type or member 'My()'

I'd prefer one of the following options

  1. Comments in the IDL get propagated to the generated output
  2. "#pragma warning disable 1591" gets added to the generated files

I'd prefer not to resort to the "project-global" suppression. If there's another option I don't know about, I'm happy to use that instead.

bonded<> recursive usage question

Hello, I am trying to get a combination of the generic_tree and polymorphic_container samples to obtain a polymorphic tree. But I cannot figure out how to serialize nested bonded<> fields, and I was wondering if that is supported?

C++ generated code: mark user-defined swap (conditionally) noexcept

Bond generates both user-defined 1/ member function swap and 2/ free-standing swap.

This allows for the well-known ADL trick à la

using std::swap;
swap(x, y);

Which is for example used by many stdlib algorithms.

Now, what Bond does not generate is the noexcept specifier when it is possible; consider:

static_assert( noexcept(swap(x, y)), "not noexcept swappabl" );

This will trigger for x, y that are of Bond-generated type.

I guess this can be solved along the lines of:

void swap(/*omitted*/) noexcept(noexcept(swap(x, y)))

which should help the stdlib in picking more efficient algorithm implementations when possible.

Thanks,
Daniel

Code generation does not detect out-of-range values for field defaults

This .bond file does not cause any code generation errors, though one would be expected, as the default value cannot be stored in the field.

namespace type_range;

struct HasInt32Field
{
    // default value here is 2 larger than an int64 can hold
    0: int32 i32_field = 9223372036854775809;
}

Here's the generated _types.cpp when running .\gbc.exe c++ .\type_range.bond

...
namespace type_range
{

    const bond::Metadata HasInt32Field::Schema::metadata
        = HasInt32Field::Schema::GetMetadata();

    const bond::Metadata HasInt32Field::Schema::s_i32_field_metadata
        = bond::reflection::MetadataInit(static_cast<int32_t>(9223372036854775809), "i32_field");


} // namespace type_range

Version details:

> .\gbc.exe -V
Bond Compiler 3.05, (C) Microsoft

Request for custom map implementation example (c++)

It must be possible to define a custom non-stl map container. For custom list and custom string there is an examples and it was easy to write some code based on them. But for map it seems more complex to do this.

Syntax highlighting for Notepad++

Now that there is syntax highlighting for Sublime, maybe someone could contribute highlighting for Notepad++ based on it.
If nobody picks this task up, I'll try to submit a PR myself at some point if I can, but can't promise anything... just thought it's an easy task that someone might want to pick up before I can get to it.

Bonded-nested Polymorphic types get lost during deserialization in C#

The primary problem this bug is trying to address is that the generic type parameter gets lost on a Clone action and so IBonded<T>.Deserialize() behaves differently depending on an object's level of nesting within the tree. For example, even though src.Shapes[0] = new Bonded<Circle>(circle), the following returns false (and ideally it would return true).

// false; "typeof(ShapeProps) != typeof(CircleProps)"
Debug.Assert(
    src.Shapes[0].Deserialize().Props.Deserialize().GetType() ==
    circle.Props.Deserialize().GetType());

To illustrate this, I took the polymorphic_container.csproj sample and updated it to included polymorphic types nested within a bonded struct.

Expected:
Polymorphic Bonded types Deserialize as the derived type they were created with where possible

Actual:
Polymorphic Bonded types Deserialize only as the base type when nested inside another Bonded struct

IDL:

namespace Examples

enum Type
{
    Unknown,
    Circle,
    Rectange
}

struct ShapeProps
{
}

struct Shape
{
    0: Type Type = Unknown;
    1: bonded<ShapeProps> Props;
}

struct Circle : Shape
{
    0: double Radius;
}

struct CircleProps : ShapeProps
{
    0: string CircleString;
}

struct Rectangle : Shape
{
    0: double Width;
    1: double Height;
}

struct RectangleProps : ShapeProps
{
    0: string RectangleString;
}

Program.cs:

static class Program
{
    static void Main()
    {
        var circle = new Circle
        {
            Type = Type.Circle,
            Radius = 3.14,
            Props = new Bonded<CircleProps>(new CircleProps
            {
                CircleString = "I'm a circle",
            }),
        };

        var rectangle = new Bonded<RectangleProps>(new Rectangle
        {
            Type = Type.Rectange,
            Width = 10,
            Height = 5.5,
            Props = new RectangleProps
            {
                RectangleString = "I'm a rectangle",
            },
        });

        var src = new Polymorphic
        {
            Shapes = 
            {
                new Bonded<Circle>(circle),
                new Bonded<Rectangle>(rectangle)
            }
        };

        // ===
        // false; "typeof(ShapeProps) != typeof(CircleProps)"
        Debug.Assert(
            src.Shapes[0].Deserialize().Props.Deserialize().GetType() ==
            circle.Props.Deserialize().GetType());
        // ===

        // ... remainder omitted
    }
}

<stdint.h> is C++11 specific

I ran into this with an older compiler. I don't believe C++03 actually provides sized int types. <boost/cstdint.hpp> could be included if the compiler is not C++11.

Failed to build on Win8.1 + VS2013

I'm trying to build it myself, but met following error.

2>------ Build started: Project: compiler, Configuration: Debug Win32 ------
3>------ Build started: Project: bond_unit_test_main, Configuration: Debug Win32 ------
3> Building Custom Rule D:/repos/bond/cpp/test/core/CMakeLists.txt
3> CMake does not need to re-run because D:\repos\bond.build\cpp\test\core\CMakeFiles\generate.stamp is up-to-date.
3> main.cpp
2> Building Custom Rule D:/repos/bond/compiler/CMakeLists.txt
2> CMake does not need to re-run because D:\repos\bond.build\compiler\CMakeFiles\generate.stamp is up-to-date.
2> Generating D:/repos/bond/compiler/cabal.sandbox.config
2> Writing a default package environment file to
2>
2> D:\repos\bond\compiler\cabal.sandbox.config
2>
2> Using an existing sandbox located at D:\repos\bond\compiler.cabal-sandbox
2>
2> Generating build/gbc/gbc.exe
2> Resolving dependencies...
2>
2> Notice: installing into a sandbox located at
2>
2> D:\repos\bond\compiler.cabal-sandbox
2>
2> Downloading aeson-0.7.0.6...
2>
2> cabal.exe: mallocPlainForeignPtrBytes: size must be >= 0
2> Resolving dependencies...
2>
2> Configuring gbc-3.0.2.0...
2>
2> cabal.exe: At least the following dependencies are missing:
2>
2> shakespeare >=2.0
2>
2> Package has never been configured. Configuring with default flags. If this
2>
2> fails, please run configure manually.
2>
2> Resolving dependencies...
2>
2> Configuring gbc-3.0.2.0...
2>
2> cabal.exe: At least the following dependencies are missing:
2>
2> shakespeare >=2.0
2>
2> Generating gbc.comp
2> 'build\gbc\gbc.exe' is not recognized as an internal or external command,

It seems to be cabal failed to install shakespear. So I tried to install shakespeare manually. However, it failed again.

D:\repos\bond.build>cabal install shakespeare
Resolving dependencies...
Downloading text-1.2.0.4...
Configuring exceptions-0.6.1...
Configuring dlist-0.7.1...
Configuring text-1.2.0.4...
Building exceptions-0.6.1...
Building dlist-0.7.1...
Building text-1.2.0.4...
Installed dlist-0.7.1
Installed exceptions-0.6.1
Installed text-1.2.0.4
Downloading hashable-1.2.3.1...
Downloading parsec-3.1.8...
Configuring system-filepath-0.4.13.1...
Configuring blaze-builder-0.3.3.4...
Configuring hashable-1.2.3.1...
Configuring parsec-3.1.8...
Building blaze-builder-0.3.3.4...
Building hashable-1.2.3.1...
Building parsec-3.1.8...
Building system-filepath-0.4.13.1...
Installed hashable-1.2.3.1
Downloading unordered-containers-0.2.5.1...
Configuring scientific-0.3.3.5...
Building scientific-0.3.3.5...
Installed blaze-builder-0.3.3.4
Configuring blaze-markup-0.6.2.0...
Building blaze-markup-0.6.2.0...
cabal: mallocPlainForeignPtrBytes: size must be >= 0

Env:
Win8.1
VS 2013
Boost 1.57
Python 2.7.6
Haskell 2014.2.0.0-x86_64
Cabal-install 1.18.0.5

Anyone has same issues?

Generate runtime schema from .bond file

The compiler command line utility and compiler library should allow generating marshaled runtime schema(s) from a .bond file. This would be useful for building tools that consume .bond file schema descriptions and use runtime schema to obtain schema metadata, e.g. to perform transcoding from binary to JSON.

Why are all protocol writers not implemented as classes?

Looking at the Bond code I see all implementations of IProtocolWriter as struct implementations. Is there a reasoning for this?

And then in the ProtocolWriter.cs there is a comment stating something about inlining .. are you stating that if the implementation of an IProtocolWriter is made a class this optimization goes away?

https://github.com/Microsoft/bond/blob/556ce21603a10759a6f2678b2ea14e4d0f659ef2/cs/src/core/expressions/ProtocolWriter.cs#L59

C++ generated code: provide option for not generating apply function overloads

Suppose I have a schema definition file M.bond.

gbc c++ M.bond

in addition to

M_reflection.h
M_types.h
M_types.cpp

bond automatically generates

M_apply.h
M_apply.cpp

Those two files are optional and not required. The "--apply" flag only let's me specify more protocols to create apply function overloads for. But there is currently no way to disable the generation of apply function overloads (except for removing them after each gbc invocation).

Thanks,
Daniel

rapidjson_helper no return statement in function compiler error

Hey,

I get the following compiler error when compiling bond using the android NDK.
bond/protocol/detail/rapidjson_helper.h:123:5:error: no return statement in function returning non-void

Looks like the issue is

120 size_t PutEnd(char* begin)
121 {
122 BOOST_ASSERT(begin == 0);
123 }

I'm not sure what the expected return value here is otherwise I'd submit a pull request, so can someone advise on this?

Thanks,
John

Code generation does not detect default value type mismatches when generating C#

Given the following .bond file

namespace type_mismatch;

struct HasUint64Field
{
    0: uint64 ui64_field = "this is a string value";
}

The following command runs without error and writes a .cs file.

> .\gbc.exe c# .\default_type_mismatch.bond

The .cs file is not valid however. Notice the ui64_field initialization.

...
namespace type_mismatch
{
    using System.Collections.Generic;

    [global::Bond.Schema]
    [System.CodeDom.Compiler.GeneratedCode("gbc", "3.05")]
    public partial class HasUint64Field
    {
        [global::Bond.Id(0)]
        public ulong ui64_field { get; set; }

        public HasUint64Field()
            : this("type_mismatch.HasUint64Field", "HasUint64Field")
        {}

        protected HasUint64Field(string fullName, string name)
        {
            ui64_field = "this is a string value";
        }
    }
} // type_mismatch

On the other hand, C++ code generation fails with the following error, though it does write _reflection.h and creates _types.h

> .\gbc.exe c++ .\default_type_mismatch.bond
gbc.exe: defaultValue: impossible happened.

Version details:

> .\gbc.exe -V
Bond Compiler 3.05, (C) Microsoft

This gbc is from Bond.CSharp 3.0.6.

Anonymous Objects

In Json.Net it is very simple to deserialize a Json stream into an anonymous object.
Is there a simple (native) way to do this in Bond (using eg tagged binary), or do I need to roll my own?

Thanks

Add support for C# "char" type.

Currently to serialize deserialize .NET primitive type char, I have to write

[global::Bond.Id(5), global::Bond.Type(typeof(UInt16))]
public char CharVar { get; set; }

It would be good if the char type has the native support from bond library, without explicitly mapping to UInt16

So the code becomes

[global::Bond.Id(5)]
public char CharVar { get; set; }

and CharVar will be seriliazed into uint16 bond protocol field.

Example use cases

Could you add some concrete example use cases for this to the README or the docs? It would be helpful to know what problems it is being used to solve.

JSON doesn't support lazy deserialization

I want to deserialize complex bond. Exception got thrown when I'm using SimpleJsonWriter. Is there some examples on json deserialization of complex types? Here is a schema I'm trying:

struct InnerStruct
{
    10: optional string baseType;
}
struct Record
{
    0: string Name;
    1: vector<double> Constants;
    2: optional bonded<InnerStruct> data;
}

Code:

var src = new Record
{
    Name = "FooBar",
    Constants = { 3.14, 6.28 },
    data = new Bonded<InnerStruct>(new InnerStruct() { baseType = "a" })
};

var jsonString = new StringBuilder();
var jsonWriter = new SimpleJsonWriter(new StringWriter(jsonString));

Serialize.To(jsonWriter, src);
jsonWriter.Flush();

var reader = new SimpleJsonReader(new StringReader(jsonString.ToString()));
src = Deserialize<Record>.From(reader);

Output:

{"Name":"FooBar","Constants":[3.14,6.28],"data":{"baseType":"a"}}

Unhandled Exception: System.TypeInitializationException: The type initializer for 'Cache`1' threw an exception. ---> System.NotImplementedException: The method or operation is not implemented.
   at Bond.Expressions.Pull.PullParser`1.Bonded(ValueHandler handler)
   at Bond.Expressions.DeserializerTransform`1.Value(IParser parser, Expression var, Expression valueType, Type schemaType, Boolean initialize)
   at Bond.Expressions.DeserializerTransform`1.CheckedValue(IParser parser, Expression var, Expression valueType, Type schemaType, Boolean initialize)
   at Bond.Expressions.DeserializerTransform`1.<>c__DisplayClass11.<>c__DisplayClass15.<Struct>b__c(IParser fieldParser, Expression fieldType)
   at Bond.Expressions.Field.Bond.Expressions.IField.Value(IParser parser, Expression valueType)
   at Bond.Expressions.Json.SimpleJsonParser`1.ProcessField(ParameterExpressionrequiredFields, IEnumerable`1 transforms)
   at Bond.Expressions.Json.SimpleJsonParser`1.<>c__DisplayClass9.<CreateStateMachine>b__8(Expression state)
   at Bond.Expressions.Pull.StateTransition.<>c__DisplayClass2.<.ctor>b__0(Expression s)
   at Bond.Expressions.Pull.StateTransition.Bond.Expressions.Pull.IStateTransition.Body(Expression state)
   at Bond.Expressions.Pull.PullParser`1.<>c__DisplayClassc.<CaseForToken>b__a(IStateTransition transition)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Bond.Expressions.Pull.PullParser`1.CaseForToken(ITokenTransition`1 tokenTransition, Expression state)
   at Bond.Expressions.Pull.PullParser`1.<>c__DisplayClass8.<SwitchToken>b__5(ITokenTransition`1 transition)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Bond.Expressions.Pull.PullParser`1.SwitchToken(IStateMachine`1 machine, Expression state)
   at Bond.Expressions.Pull.PullParser`1.Apply(ITransform transform)
   at Bond.Expressions.DeserializerTransform`1.Struct(IParser parser, Expression var, Type schemaType, Boolean initialize)
   at Bond.Expressions.DeserializerTransform`1.Deserialize(IParser parser, Expression var, Type objectType, Type schemaType, Boolean initialize)
   at Bond.Expressions.DeserializerTransform`1.Generate(IParser parser, Type type)
   at Bond.Deserializer`1..ctor(Type type, IParser parser, IFactory factory, Boolean inlineNested)
   at Bond.Deserializer`1..ctor(Type type)
   at Bond.Deserialize`1.Cache`1..cctor()
   --- End of inner exception stack trace ---
   at Bond.Deserialize`1.From[R](R reader)
   at TryBond.Program.Main() in c:\temp\TryBond\TryBond\Program.cs:line 35

nullable<alias-name> in C# tries to convert to generated-type-name instead of nullable<generated-type-name>

When I try to use nullable in my IDL, I get a runtime serialization error about a missing converter.

Expected:

When I've already specified "alias-name=generated-type-name", nullable=nullable should be implied. For example,

using datetime = uint64;

should be all I need to specify (including corresponding BondTypeAliasConverter methods) to define

5: nullable<datetime> otherTimestampUtc;

Actual:

Unfortunately, I get this error at runtime.

System.TypeInitializationException: The type initializer for 'Cache2' threw an exception. ---> System.InvalidOperationException: No coercion operator is defined between types 'System.Nullable1[System.DateTime]' and 'System.UInt64'.

at System.Linq.Expressions.Expression.GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType)
at System.Linq.Expressions.Expression.Convert(Expression expression, Type type, MethodInfo method)
at Bond.Expressions.ProtocolWriter1.Write(Expression value, BondDataType type) at Bond.Expressions.SerializerTransform2.<>c__DisplayClass22.b__21(Expression value)
at Bond.Expressions.ObjectParser.Scalar(Expression valueType, BondDataType expectedType, ValueHandler handler)
at Bond.Expressions.SerializerTransform2.Value(IParser parser, Expression valueType, RuntimeSchema schema) at Bond.Expressions.SerializerTransform2.<>c__DisplayClass11.b__10(IParser valueParser, Expression elementType, Expression next, Expression count)
at Bond.Expressions.ObjectParser.Nullable(ContainerHandler handler)
at Bond.Expressions.ObjectParser.Container(Nullable1 expectedType, ContainerHandler handler) at Bond.Expressions.SerializerTransform2.Container(IParser parser, RuntimeSchema schema)
at Bond.Expressions.SerializerTransform2.<>c__DisplayClass2.<GenerateSerialize>b__0(IParser p) at Bond.Expressions.SerializerGenerator2.GenerateSerialize(Serialize serialize, IParser parser, ParameterExpression writer, Boolean inline)
at Bond.Expressions.SerializerTransform2.GenerateSerialize(SerializeWithSchema serializeWithSchema, IParser parser, RuntimeSchema schema) at Bond.Expressions.SerializerTransform2.Value(IParser parser, Expression valueType, RuntimeSchema schema)
at Bond.Expressions.SerializerTransform2.<>c__DisplayClassc.<>c__DisplayClasse.<Struct>b__7(IParser fieldParser, Expression fieldType) at Bond.Expressions.Field.Bond.Expressions.IField.Value(IParser parser, Expression valueType) at Bond.Expressions.ObjectParser.Field(ITransform transform, Expression structVar, UInt16 id, ISchemaField schemaField, IField field) at Bond.Expressions.ObjectParser.<>c__DisplayClassc.<Apply>b__7(<>f__AnonymousType02 <>h__TransparentIdentifier0, IField knownField)
at System.Linq.Enumerable.d__43.MoveNext() at System.Collections.Generic.List1.InsertRange(Int32 index, IEnumerable1 collection) at Bond.Expressions.ObjectParser.Apply(ITransform transform) at Bond.Expressions.SerializerTransform2.Struct(IParser parser, RuntimeSchema schema, Boolean isBase)
at Bond.Expressions.SerializerTransform2.Struct(IParser parser, RuntimeSchema schema) at Bond.Expressions.SerializerTransform2.<>c__DisplayClass2.b__0(IParser p)
at Bond.Expressions.SerializerGenerator2.GenerateSerialize(Serialize serialize, IParser parser, ParameterExpression writer, Boolean inline) at Bond.Expressions.SerializerTransform2.GenerateSerialize(SerializeWithSchema serializeWithSchema, IParser parser, RuntimeSchema schema)
at Bond.Expressions.SerializerTransform2.Generate(IParser parser) at Bond.Serializer1..ctor(Type type)
at Bond.Serialize.Cache`2..cctor()
--- End of inner exception stack trace ---
at Bond.Serialize.To(W writer, T obj)

Include RapidJSON headers only if BOND_SIMPLE_JSON_PROTOCOL defined

Correct me if I'm wrong but RapidJSON headers needed only for simple JSON protocol. But this headers are included in any case. This forces a user to has a dependency on RapidJSON even if he/she is not going to use JSON at all.
I propose to include simple_json_xxx headers (along with RapidJSON headers) only if BOND_SIMPLE_JSON_PROTOCOL is defined.

How does bond deal with schema field name changes?

Hi. Thank you for open sourcing this library.

Suppose we had:

struct Record
{
    0: string Name;
}

which later was changed to:

struct Record2
{
    0: string FirstName;
}

How do you define a transform in bond of the data stored in Record to Record2 ? Or is this beyond the scope of bond?

SimpleJsonParser should check the FloatHandling setting

In SimpleJsonParser::

            else if (scalarTokenType == JsonToken.Float)
            {
                convertedValue = Expression.Convert(Reader.Value, typeof(double));
            }

If a user changes floathandling to decimal this will throw an invalid cast exception as you tried to unbox a decimal to a double. You are not safe by not taking a JsonSettings option as a user may simply override the default settings for Json.net.

Json.net does offer on the JsonReader some (very very few unfortunately) helpers which can be used as an optimization as they will avoid boxing. They will produce a Nullable<T> but that's still cheaper than boxing and unboxing.

Fiddler inspector

It would be nice to create a fiddler inspector, where you could point to a path with bond declaration files, and deserialize a request or response to a particular bond type that you specify, similar to how JSON is displayed.

Stretch goal: given the same configuration, allow fiddler to build a new request by serializing some JSON to a bond type.

Array Collection

Is it possible to get a true array Foo[] collection in generated C#, as opposed to List<Foo>?

cannot compile on macos

my machine

$ brew search boost
boost (installed) boost-bcp boost-build boost-python (installed)
homebrew/science/boost-compute homebrew/versions/boost150 Caskroom/cask/iboostup Caskroom/cask/turbo-boost-switcher
homebrew/versions/boost149 homebrew/versions/boost155 Caskroom/cask/pivotalbooster

$ cmake --version
cmake version 3.3.2

CMake suite maintained and supported by Kitware (kitware.com/cmake).
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.0 (clang-700.0.72)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

error message

In file included from /Users/xinqian/work/bond.github/cpp/inc/bond/core/protocol.h:15:
In file included from /Users/xinqian/work/bond.github/cpp/inc/bond/protocol/simple_binary.h:6:
/Users/xinqian/work/bond.github/cpp/inc/bond/protocol/encoding.h:30:5: error: unused typedef 'boost_static_assert_typedef_30'
[-Werror,-Wunused-local-typedef]
BOOST_STATIC_ASSERT(is_unsigned::value);
^
/usr/local/include/boost/static_assert.hpp:170:16: note: expanded from macro 'BOOST_STATIC_ASSERT'
BOOST_JOIN(boost_static_assert_typedef_, LINE) BOOST_STATIC_ASSERT_UNUSED_ATTRIBUTE
^
/usr/local/include/boost/config/suffix.hpp:544:28: note: expanded from macro 'BOOST_JOIN'

define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y )

                       ^

/usr/local/include/boost/config/suffix.hpp:545:31: note: expanded from macro 'BOOST_DO_JOIN'

define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y)

                          ^

/usr/local/include/boost/config/suffix.hpp:546:32: note: expanded from macro 'BOOST_DO_JOIN2'

define BOOST_DO_JOIN2( X, Y ) X##Y

                           ^

:42:1: note: expanded from here
boost_static_assert_typedef_30
^
In file included from /Users/xinqian/work/bond.github/cpp/generated/bond/core/bond_types.cpp:13:
In file included from /Users/xinqian/work/bond.github/cpp/generated/bond/core/bond_reflection.h:16:
In file included from /Users/xinqian/work/bond.github/cpp/inc/bond/core/reflection.h:17:
In file included from /Users/xinqian/work/bond.github/cpp/inc/bond/core/bonded.h:7:
In file included from /Users/xinqian/work/bond.github/cpp/inc/bond/core/protocol.h:15:
In file included from /Users/xinqian/work/bond.github/cpp/inc/bond/protocol/simple_binary.h:6:
/Users/xinqian/work/bond.github/cpp/inc/bond/protocol/encoding.h:42:5: error: unused typedef 'boost_static_assert_typedef_42'

Union type in C#

If I use an explict struct (see below) and manually decorate it with the [bond] attributes, will Bond do the right things in terms of de/serialization. In other words, in the snippet below will the populated field (both at offset 0) maintain fidelity across the wire?

Background: I have an efficient in-memory representation of data (the struct below is just one part of that representation). I also need an efficient wire representation of the same data, but not sure whether I need a completely separate struct for Bond or whether I can just 're-use' the existing struct.

 [Bond.Schema(...)]
 [StructLayout(LayoutKind.Explicit, Pack=1)]
    internal struct Union
    {
        #region Blittable

        [Bond.Id(0)]
        [FieldOffset(0)]
        public Byte Byte;

        [Bond.Id(1)]
        [FieldOffset(0)]
        public Int16 Int16;

...etc...

Pypi package

Could you create a Python package (preferably wheel) for the bindings and publish it in pypi?

Json & Dependencies should be packed in a different package.

Json requires to use add as a dependency Json.Net. While it is a very standard library, there are some projects that can have potential issues.

For example, if you are using other Json version (previous or newer) which cannot be expected to work (they can but there is nothing that ensures it -- compatibility between major versions in semantic versioning is not guaranteed). In fact, issuing a different package with nuget versions introduced in Nuget 3.0 you can even release one for each compatible major json version. Other projects just doesnt need json at all, introduce such a dependency (and deal with it) when it is only used in Json Transcoders, Readers and Writers if you are not using them.

Support for unsafe pointer based InputBuffer and OutputBuffer

Currently Bond is missing a facility to deal with unmanaged memory as source and/or destination of the data. From what I see on the code implementing an InputPtrBuffer and OutputPtrBuffer would be straightforward. Is that the proper approach?

Would you accept such a contribution if possible? (I have a CoreCLR CLA already signed).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.