{"id":4322,"date":"2016-10-19T15:03:47","date_gmt":"2016-10-19T15:03:47","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=4322"},"modified":"2016-10-21T20:40:34","modified_gmt":"2016-10-21T20:40:34","slug":"__trashed","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/__trashed\/","title":{"rendered":"Getting started with Bond"},"content":{"rendered":"<p><strong>What&#8217;s Bond?<\/strong><\/p>\n<p>The Microsoft github repos. for <a href=\"https:\/\/github.com\/Microsoft\/bond\/\" target=\"_blank\">Bond<\/a> states that &#8220;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.&#8221;<\/p>\n<p>To put it another way, Bond appears to be similar to Google&#8217;s protocol buffers. See <a href=\"https:\/\/microsoft.github.io\/bond\/why_bond.html\" target=\"_blank\">Why Bond?<\/a> for more on what Bond is.<\/p>\n<p><em>At the time of writing, out of the box, Bond is supported with C++. C# and Python language bindings.<\/em><\/p>\n<p><strong>Jumping straight in<\/strong><\/p>\n<p>Let&#8217;s jump straight in an write some code. Here&#8217;s the steps to create our project<\/p>\n<ul>\n<li>For this example, let&#8217;s create a Console project in Visual Studio<\/li>\n<li>Using NuGet add the Bond.CSharp package<\/li>\n<\/ul>\n<p>Now we&#8217;ll define our schema using Bond&#8217;s IDL. This should be saved with the .bond extension, so in my case, this code is in Person.bond<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\nnamespace Sample\r\n\r\nstruct Person\r\n{\r\n    0: string FirstName;\r\n    1: string LastName;\r\n    2: int32 Age;\r\n}\r\n<\/pre>\n<p>Notice that we create a namespace and then use a Bond struct to define our data. Within the struct, each item of data is preceded with an numeric id (see <a href=\"https:\/\/microsoft.github.io\/bond\/manual\/compiler.html#idl-syntax\" target=\"_blank\">IDL Syntax<\/a> for more information).<\/p>\n<p>Now, we could obviously write the code to represent this IDL, but it&#8217;s be better still if we can generate the source code from the IDL. When we added the NuGet Bond.CSharp package we also got a copy of gbc, which is the command line tool for this purpose.<\/p>\n<p>Open up a cmd prompt and locate gbc (mine was installed into <Project>\\packages\\Bond.CSharp.5.0.0\\tools). From here we run the following<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\ngbc c# &lt;Project&gt;\\Person.bond -o=&lt;Project&gt;\r\n<\/pre>\n<p><em>Replace &lt;Project&gt; with the file path of your application and where your .bond file is located.<\/em>. <\/p>\n<p>This command will generate the source files from the Person.bond IDL and output (the -o switch) to the root of the project location.<\/p>\n<p>Now we need to include the generated files in our project &#8211; mine now includes Person_interfaces.cs, Person_proxies.cs, Person_services.cs and Person_types.cs. In fact we only need the Person_types.cs for this example. This includes the C# representation of our IDL and looks (basically) like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic partial class Person\r\n{\r\n   &#x5B;global::Bond.Id(0)]\r\n   public string FirstName { get; set; }\r\n\r\n   &#x5B;global::Bond.Id(1)]\r\n   public string LastName { get; set; }\r\n\r\n   &#x5B;global::Bond.Id(2)]\r\n   public int Age { get; set; }\r\n\r\n   public Person()\r\n      : this(&quot;Sample.Person&quot;, &quot;Person&quot;)\r\n   {}\r\n\r\n   protected Person(string fullName, string name)\r\n   {\r\n      FirstName = &quot;&quot;;\r\n      LastName = &quot;&quot;;\r\n   }\r\n}\r\n<\/pre>\n<p>Let&#8217;s now look at some code for writing a Person to the Bond serializer. <\/p>\n<p><em>Note: There is an example of serialization code in the <a href=\"https:\/\/microsoft.github.io\/bond\/manual\/bond_cs.html#input-and-output-streams\" target=\"_blank\">guide to Bond<\/a>. This shows the helper static methods, Serializer.To and Deserializer.From, however these are not the most optimal for non-trivial code, so I&#8217;ll ignore those for my example.<\/em><\/p>\n<p><strong>Using clause<\/strong><\/p>\n<p>Bond includes a Bond.IO.Safe namespace and a Bond.IO.Unsafe, according to the documentation the Unsafe namespace includes the fastest code. So For this example I&#8217;m using Bond.IO.Unsafe.<\/p>\n<p><strong>How to write an object to Bond<\/strong><\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar src = new Person\r\n{\r\n   FirstName = &quot;Scooby&quot;,\r\n   LastName = &quot;Doo&quot;,\r\n   Age = 7\r\n};\r\n\r\nvar output = new OutputBuffer();\r\nvar writer = new CompactBinaryWriter&lt;OutputBuffer&gt;(output);\r\nvar serializer = new Serializer&lt;CompactBinaryWriter&lt;OutputBuffer&gt;&gt;(typeof(Person));\r\n\r\nserializer.Serialize(src, writer);\r\n<\/pre>\n<p>The <em>Serialize.To<\/em> code allows us to dispense with the serializer, but the initial call to this creates the serializer which can take a performance hit if used inside a loop or the likes, hence creating the serializer upfront and using this instance in any loops would provide better overall performance.<\/p>\n<p><strong>How to read an object from Bond<\/strong><\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar input = new InputBuffer(output.Data);\r\nvar reader = new CompactBinaryReader&lt;InputBuffer&gt;(input);\r\nvar deserializer = new Deserializer&lt;CompactBinaryReader&lt;InputBuffer&gt;&gt;(typeof(Person));\r\n\r\nvar dst = deserializer.Deserialize(reader);\r\n<\/pre>\n<p>In the above code we&#8217;re getting the input from the OutputBuffer we created from writing data, although this is just to demonstrate usage. The InputBuffer can take a byte[] representing the data to be deserialized.<\/p>\n<p><em>Where possible InputBuffer&#8217;s and OutputBuffer&#8217;s should also be reused, simply set the buffer.Position = 0 to reset them after use.<\/em><\/p>\n<p><strong>Serialization Protocols<\/strong><\/p>\n<p>In the previous code we&#8217;ve used the CompactBinary classes which implements binary serialization (optimized for compactness, as the name suggests), but there are several other serialization protocols.<\/p>\n<p>FastBinaryReader\/FastBinaryWriter, classes are optimized for speed, and easily plug into our sample code like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar writer = new FastBinaryWriter&lt;OutputBuffer&gt;(output);\r\nvar serializer = new Serializer&lt;FastBinaryWriter&lt;OutputBuffer&gt;&gt;(typeof(Person));\r\n<\/pre>\n<p>and<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar reader = new FastBinaryReader&lt;InputBuffer&gt;(input);\r\nvar deserializer = new Deserializer&lt;FastBinaryReader&lt;InputBuffer&gt;&gt;(typeof(Person));\r\n<\/pre>\n<p>SimpleBinaryReader\/SimpleBinaryWriter, classes offer potential for a saving on the payload size.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar writer = new SimpleBinaryWriter&lt;OutputBuffer&gt;(output);\r\nvar serializer = new Serializer&lt;SimpleBinaryWriter&lt;OutputBuffer&gt;&gt;(typeof(Person));\r\n<\/pre>\n<p>and<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar reader = new SimpleBinaryReader&lt;InputBuffer&gt;(input);\r\nvar deserializer = new Deserializer&lt;SimpleBinaryReader&lt;InputBuffer&gt;&gt;(typeof(Person));\r\n<\/pre>\n<p><strong>Human readable serialization protocols<\/strong><\/p>\n<p>At the time of writing, Bond supports the two &#8220;human-readable&#8221; based protocols, which are XML and JSON.<\/p>\n<p>Let&#8217;s look at the changes required to read\/write JSON.<\/p>\n<p>The JSON protocol can be used with the .bond file as previously defined, or we can add JsonName attribute to the fields to produce <\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nnamespace Sample\r\n\r\nstruct Person\r\n{\r\n    &#x5B;JsonName(&quot;First&quot;)]\r\n    0: string FirstName;\r\n    &#x5B;JsonName(&quot;Last&quot;)]\r\n    1: string LastName;\r\n    &#x5B;JsonName(&quot;Age&quot;)]\r\n    2: int32 Age;\r\n}\r\n<\/pre>\n<p>if we are supporting Json with named attributes. The easiest way to use the SimpleJsonReade\/SimpleJsonWriter is using a string buffer (or StringBuilder in C# terms), so here&#8217;s the code to write our Person object to a Json string<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar sb = new StringBuilder();\r\nvar writer = new SimpleJsonWriter(new StringWriter(sb));\r\nvar serializer = new Serializer&lt;SimpleJsonWriter&gt;(typeof(Person));\r\n\r\nserializer.Serialize(src, writer);\r\n<\/pre>\n<p>to deserialize the string back to an object we can use<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar reader = new SimpleJsonReader(new StringReader(sb.ToString()));\r\nvar deserializer = new Deserializer&lt;SimpleJsonReader&gt;(typeof(Person));\r\n\r\nvar dst = deserializer.Deserialize(reader);\r\n<\/pre>\n<p>The XML protocol can be used with the original .bond file (or the Json one as the JsonName attributes are ignored) so nothing to change there. Here&#8217;s the code to write our object to XML (again we&#8217;re using a string as a buffer)<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar sb = new StringBuilder();\r\nvar writer = new SimpleXmlWriter(XmlWriter.Create(sb));\r\nvar serializer = new Serializer&lt;SimpleXmlWriter&gt;(typeof(Person));\r\n\r\nserializer.Serialize(src, writer);\r\n\r\nwriter.Flush();\r\n<\/pre>\n<p>and to deserialize the XML we simply use<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar reader = new SimpleXmlReader(\r\n     XmlReader.Create(\r\n         new StringReader(sb.ToString())));\r\nvar deserializer = new Deserializer&lt;SimpleXmlReader&gt;(typeof(Person));\r\n\r\nvar dst = deserializer.Deserialize(reader);\r\n<\/pre>\n<p><strong>Transcoding<\/strong><\/p>\n<p>The Transcoder allows us to convert &#8220;payloads&#8221; from one protocol to another. For example, let&#8217;s assume we&#8217;ve got a SimpleXmlReader representing some XML data and we want to transcode it to a CompactBinaryWriter format, we can do the following<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar reader = new SimpleXmlReader(XmlReader.Create(new StringReader(xml)));\r\n\r\nvar output = new OutputBuffer();\r\nvar writer = new CompactBinaryWriter&lt;OutputBuffer&gt;(output);\r\n\r\nvar transcode = new Transcoder&lt;\r\n   SimpleXmlReader, \r\n   CompactBinaryWriter&lt;OutputBuffer&gt;&gt;(\r\n      typeof(Person));\r\n\r\ntranscode.Transcode(reader, writer);\r\n<\/pre>\n<p>Now our payload is represented as a CompactBinaryWriter. Obviously this is more useful in scenarios where you have readers and writers as opposed to this crude example where we could convert to and from the Person object ourselves.<\/p>\n<p><strong>References<\/strong><\/p>\n<p><a href=\"https:\/\/microsoft.github.io\/bond\/manual\/bond_cs.html#deserializer\" target=\"_blank\">A Young Person\u2019s Guide to C# Bond<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>What&#8217;s Bond? The Microsoft github repos. for Bond states that &#8220;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.&#8221; To put it another way, Bond appears to be similar to Google&#8217;s protocol buffers. See Why Bond? for more on what [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[136],"tags":[],"class_list":["post-4322","post","type-post","status-publish","format-standard","hentry","category-bond"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/4322","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=4322"}],"version-history":[{"count":15,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/4322\/revisions"}],"predecessor-version":[{"id":4355,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/4322\/revisions\/4355"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=4322"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=4322"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=4322"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}