diff --git a/Hybrid Row Whitepaper.docx b/Hybrid Row Whitepaper.docx
new file mode 100644
index 0000000..9635cd4
Binary files /dev/null and b/Hybrid Row Whitepaper.docx differ
diff --git a/dotnet/src/HybridRow.Json/Microsoft.Azure.Cosmos.Serialization.HybridRow.Json.csproj b/dotnet/src/HybridRow.Json/Microsoft.Azure.Cosmos.Serialization.HybridRow.Json.csproj
new file mode 100644
index 0000000..d4b4d50
--- /dev/null
+++ b/dotnet/src/HybridRow.Json/Microsoft.Azure.Cosmos.Serialization.HybridRow.Json.csproj
@@ -0,0 +1,21 @@
+
+
+
+ true
+ {CE1C4987-FC19-4887-9EB6-13508F8DA644}
+ Library
+ Microsoft.Azure.Cosmos.Serialization.HybridRow.Json
+ Microsoft.Azure.Cosmos.Serialization.HybridRow.Json
+ netstandard2.0
+ AnyCPU
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/src/HybridRow.Json/Properties/AssemblyInfo.cs b/dotnet/src/HybridRow.Json/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..be43fcc
--- /dev/null
+++ b/dotnet/src/HybridRow.Json/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+//------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Microsoft.Azure.Cosmos.Serialization.HybridRow.Json")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("CE1C4987-FC19-4887-9EB6-13508F8DA644")]
diff --git a/dotnet/src/HybridRow.Json/RowReaderJsonExtensions.cs b/dotnet/src/HybridRow.Json/RowReaderJsonExtensions.cs
new file mode 100644
index 0000000..3341c9b
--- /dev/null
+++ b/dotnet/src/HybridRow.Json/RowReaderJsonExtensions.cs
@@ -0,0 +1,453 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ------------------------------------------------------------
+
+namespace Microsoft.Azure.Cosmos.Serialization.HybridRow.Json
+{
+ using System;
+ using System.Text;
+ using Microsoft.Azure.Cosmos.Core;
+ using Microsoft.Azure.Cosmos.Core.Utf8;
+ using Microsoft.Azure.Cosmos.Serialization.HybridRow.IO;
+ using Microsoft.Azure.Cosmos.Serialization.HybridRow.Layouts;
+
+ public static class RowReaderJsonExtensions
+ {
+ ///
+ /// Project a JSON document from a HybridRow .
+ ///
+ /// The reader to project to JSON.
+ /// If successful, the JSON document that corresponds to the .
+ /// The result.
+ public static Result ToJson(this ref RowReader reader, out string str)
+ {
+ return reader.ToJson(new RowReaderJsonSettings(" "), out str);
+ }
+
+ ///
+ /// Project a JSON document from a HybridRow .
+ ///
+ /// The reader to project to JSON.
+ /// Settings that control how the JSON document is formatted.
+ /// If successful, the JSON document that corresponds to the .
+ /// The result.
+ public static Result ToJson(this ref RowReader reader, RowReaderJsonSettings settings, out string str)
+ {
+ ReaderStringContext ctx = new ReaderStringContext(
+ new StringBuilder(),
+ new RowReaderJsonSettings(settings.IndentChars, settings.QuoteChar == '\'' ? '\'' : '"'),
+ 1);
+
+ ctx.Builder.Append("{");
+ Result result = RowReaderJsonExtensions.ToJson(ref reader, ctx);
+ if (result != Result.Success)
+ {
+ str = null;
+ return result;
+ }
+
+ ctx.Builder.Append(ctx.NewLine);
+ ctx.Builder.Append("}");
+ str = ctx.Builder.ToString();
+ return Result.Success;
+ }
+
+ private static Result ToJson(ref RowReader reader, ReaderStringContext ctx)
+ {
+ int index = 0;
+ while (reader.Read())
+ {
+ string path = !reader.Path.IsNull ? $"{ctx.Settings.QuoteChar}{reader.Path}{ctx.Settings.QuoteChar}:" : null;
+ if (index != 0)
+ {
+ ctx.Builder.Append(',');
+ }
+
+ index++;
+ ctx.Builder.Append(ctx.NewLine);
+ ctx.WriteIndent();
+ if (path != null)
+ {
+ ctx.Builder.Append(path);
+ ctx.Builder.Append(ctx.Separator);
+ }
+
+ Result r;
+ char scopeBracket = default;
+ char scopeCloseBracket = default;
+ switch (reader.Type.LayoutCode)
+ {
+ case LayoutCode.Null:
+ {
+ r = reader.ReadNull(out NullValue _);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append("null");
+ break;
+ }
+
+ case LayoutCode.Boolean:
+ {
+ r = reader.ReadBool(out bool value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.Int8:
+ {
+ r = reader.ReadInt8(out sbyte value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.Int16:
+ {
+ r = reader.ReadInt16(out short value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.Int32:
+ {
+ r = reader.ReadInt32(out int value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.Int64:
+ {
+ r = reader.ReadInt64(out long value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.UInt8:
+ {
+ r = reader.ReadUInt8(out byte value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.UInt16:
+ {
+ r = reader.ReadUInt16(out ushort value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.UInt32:
+ {
+ r = reader.ReadUInt32(out uint value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.UInt64:
+ {
+ r = reader.ReadUInt64(out ulong value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.VarInt:
+ {
+ r = reader.ReadVarInt(out long value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.VarUInt:
+ {
+ r = reader.ReadVarUInt(out ulong value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.Float32:
+ {
+ r = reader.ReadFloat32(out float value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.Float64:
+ {
+ r = reader.ReadFloat64(out double value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.Float128:
+ {
+ r = reader.ReadFloat128(out Float128 _);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ // ctx.Builder.AppendFormat("High: {0}, Low: {1}\n", value.High, value.Low);
+ Contract.Assert(false, "Float128 are not supported.");
+ break;
+ }
+
+ case LayoutCode.Decimal:
+ {
+ r = reader.ReadDecimal(out decimal value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value);
+ break;
+ }
+
+ case LayoutCode.DateTime:
+ {
+ r = reader.ReadDateTime(out DateTime value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(ctx.Settings.QuoteChar);
+ ctx.Builder.Append(value);
+ ctx.Builder.Append(ctx.Settings.QuoteChar);
+ break;
+ }
+
+ case LayoutCode.UnixDateTime:
+ {
+ r = reader.ReadUnixDateTime(out UnixDateTime value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(value.Milliseconds);
+ break;
+ }
+
+ case LayoutCode.Guid:
+ {
+ r = reader.ReadGuid(out Guid value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(ctx.Settings.QuoteChar);
+ ctx.Builder.Append(value.ToString());
+ ctx.Builder.Append(ctx.Settings.QuoteChar);
+ break;
+ }
+
+ case LayoutCode.MongoDbObjectId:
+ {
+ r = reader.ReadMongoDbObjectId(out MongoDbObjectId value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(ctx.Settings.QuoteChar);
+ ReadOnlyMemory bytes = value.ToByteArray();
+ ctx.Builder.Append(bytes.Span.ToHexString());
+ ctx.Builder.Append(ctx.Settings.QuoteChar);
+ break;
+ }
+
+ case LayoutCode.Utf8:
+ {
+ r = reader.ReadString(out Utf8Span value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(ctx.Settings.QuoteChar);
+ ctx.Builder.Append(value.ToString());
+ ctx.Builder.Append(ctx.Settings.QuoteChar);
+ break;
+ }
+
+ case LayoutCode.Binary:
+ {
+ r = reader.ReadBinary(out ReadOnlySpan value);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ ctx.Builder.Append(ctx.Settings.QuoteChar);
+ ctx.Builder.Append(value.ToHexString());
+ ctx.Builder.Append(ctx.Settings.QuoteChar);
+ break;
+ }
+
+ case LayoutCode.NullableScope:
+ case LayoutCode.ImmutableNullableScope:
+ {
+ if (!reader.HasValue)
+ {
+ ctx.Builder.Append("null");
+ break;
+ }
+
+ goto case LayoutCode.TypedTupleScope;
+ }
+
+ case LayoutCode.ArrayScope:
+ case LayoutCode.ImmutableArrayScope:
+ case LayoutCode.TypedArrayScope:
+ case LayoutCode.ImmutableTypedArrayScope:
+ case LayoutCode.TypedSetScope:
+ case LayoutCode.ImmutableTypedSetScope:
+ case LayoutCode.TypedMapScope:
+ case LayoutCode.ImmutableTypedMapScope:
+ case LayoutCode.TupleScope:
+ case LayoutCode.ImmutableTupleScope:
+ case LayoutCode.TypedTupleScope:
+ case LayoutCode.ImmutableTypedTupleScope:
+ case LayoutCode.TaggedScope:
+ case LayoutCode.ImmutableTaggedScope:
+ case LayoutCode.Tagged2Scope:
+ case LayoutCode.ImmutableTagged2Scope:
+ scopeBracket = '[';
+ scopeCloseBracket = ']';
+ goto case LayoutCode.EndScope;
+ case LayoutCode.ObjectScope:
+ case LayoutCode.ImmutableObjectScope:
+ case LayoutCode.Schema:
+ case LayoutCode.ImmutableSchema:
+ scopeBracket = '{';
+ scopeCloseBracket = '}';
+ goto case LayoutCode.EndScope;
+
+ case LayoutCode.EndScope:
+ {
+ ctx.Builder.Append(scopeBracket);
+ int snapshot = ctx.Builder.Length;
+ r = reader.ReadScope(new ReaderStringContext(ctx.Builder, ctx.Settings, ctx.Indent + 1), RowReaderJsonExtensions.ToJson);
+ if (r != Result.Success)
+ {
+ return r;
+ }
+
+ if (ctx.Builder.Length != snapshot)
+ {
+ ctx.Builder.Append(ctx.NewLine);
+ ctx.WriteIndent();
+ }
+
+ ctx.Builder.Append(scopeCloseBracket);
+ break;
+ }
+
+ default:
+ {
+ Contract.Assert(false, $"Unknown type will be ignored: {reader.Type.LayoutCode}");
+ break;
+ }
+ }
+ }
+
+ return Result.Success;
+ }
+
+ private readonly struct ReaderStringContext
+ {
+ public readonly int Indent;
+ public readonly StringBuilder Builder;
+ public readonly RowReaderJsonSettings Settings;
+ public readonly string Separator;
+ public readonly string NewLine;
+
+ public ReaderStringContext(StringBuilder builder, RowReaderJsonSettings settings, int indent)
+ {
+ this.Settings = settings;
+ this.Separator = settings.IndentChars == null ? "" : " ";
+ this.NewLine = settings.IndentChars == null ? "" : "\n";
+ this.Indent = indent;
+ this.Builder = builder;
+ }
+
+ public void WriteIndent()
+ {
+ string indentChars = this.Settings.IndentChars ?? "";
+ for (int i = 0; i < this.Indent; i++)
+ {
+ this.Builder.Append(indentChars);
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/src/HybridRow.Json/RowReaderJsonSettings.cs b/dotnet/src/HybridRow.Json/RowReaderJsonSettings.cs
new file mode 100644
index 0000000..4955da9
--- /dev/null
+++ b/dotnet/src/HybridRow.Json/RowReaderJsonSettings.cs
@@ -0,0 +1,24 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ------------------------------------------------------------
+
+#pragma warning disable CA1051 // Do not declare visible instance fields
+
+namespace Microsoft.Azure.Cosmos.Serialization.HybridRow.Json
+{
+ public readonly struct RowReaderJsonSettings
+ {
+ /// If non-null then child objects are indented by one copy of this string per level.
+ public readonly string IndentChars;
+
+ /// The quote character to use.
+ /// May be or .
+ public readonly char QuoteChar;
+
+ public RowReaderJsonSettings(string indentChars = " ", char quoteChar = '"')
+ {
+ this.IndentChars = indentChars;
+ this.QuoteChar = quoteChar;
+ }
+ }
+}
diff --git a/dotnet/src/HybridRow.Package/Microsoft.Azure.Cosmos.Serialization.HybridRow.Package.nuproj b/dotnet/src/HybridRow.Package/Microsoft.Azure.Cosmos.Serialization.HybridRow.Package.nuproj
new file mode 100644
index 0000000..91fda2c
--- /dev/null
+++ b/dotnet/src/HybridRow.Package/Microsoft.Azure.Cosmos.Serialization.HybridRow.Package.nuproj
@@ -0,0 +1,26 @@
+
+
+
+ {7047DD2A-14FA-445E-93B2-67EB98282C4D}
+ External
+ true
+
+
+
+ $(OutputRootDir)
+ $(NugetPackProperties);ProductSemanticVersion=$(ProductSemanticVersion);VersionPrereleaseExtension=$(VersionPrereleaseExtension)
+
+
+
+ false
+ {B7621117-AEF3-4E10-928D-533AE893F379}
+ Microsoft.Azure.Cosmos.Core
+
+
+ false
+ {490D42EE-1FEF-47CC-97E4-782A353B4D58}
+ Microsoft.Azure.Cosmos.Serialization.HybridRow
+
+
+
+
diff --git a/dotnet/src/HybridRow.Package/Microsoft.Azure.Cosmos.Serialization.HybridRow.Package.nuspec b/dotnet/src/HybridRow.Package/Microsoft.Azure.Cosmos.Serialization.HybridRow.Package.nuspec
new file mode 100644
index 0000000..b557e87
--- /dev/null
+++ b/dotnet/src/HybridRow.Package/Microsoft.Azure.Cosmos.Serialization.HybridRow.Package.nuspec
@@ -0,0 +1,29 @@
+
+
+
+ Microsoft.Azure.Cosmos.Serialization.HybridRow
+ 1.0.0-preview
+ Microsoft.Azure.Cosmos.Serialization.HybridRow
+ Microsoft
+ Microsoft
+ https://aka.ms/netcoregaeula
+ https://github.com/Azure/azure-cosmos-dotnet-v3
+ http://go.microsoft.com/fwlink/?LinkID=288890
+ false
+ Microsoft.Azure.Cosmos.Serialization.HybridRow
+ This package supports the Microsoft Azure Cosmos Client and is not intended to be used directly from your code.
+ Copyright © Microsoft Corporation
+ microsoft azure cosmos dotnetcore netcore netstandard
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/src/HybridRow.Tests.Perf/App.config b/dotnet/src/HybridRow.Tests.Perf/App.config
new file mode 100644
index 0000000..02249c3
--- /dev/null
+++ b/dotnet/src/HybridRow.Tests.Perf/App.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/src/HybridRow.Tests.Perf/BenchmarkSuiteBase.cs b/dotnet/src/HybridRow.Tests.Perf/BenchmarkSuiteBase.cs
new file mode 100644
index 0000000..ba2740d
--- /dev/null
+++ b/dotnet/src/HybridRow.Tests.Perf/BenchmarkSuiteBase.cs
@@ -0,0 +1,119 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ------------------------------------------------------------
+
+#pragma warning disable SA1401 // Fields should be private
+
+namespace Microsoft.Azure.Cosmos.Serialization.HybridRow.Tests.Perf
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Threading.Tasks;
+ using Microsoft.Azure.Cosmos.Core.Utf8;
+ using Microsoft.Azure.Cosmos.Serialization.HybridRow.IO;
+ using Microsoft.Azure.Cosmos.Serialization.HybridRow.Layouts;
+ using Microsoft.Azure.Cosmos.Serialization.HybridRow.RecordIO;
+ using Microsoft.Azure.Cosmos.Serialization.HybridRow.Schemas;
+ using Microsoft.Azure.Cosmos.Serialization.HybridRowGenerator;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ public class BenchmarkSuiteBase
+ {
+ private protected const int InitialCapacity = 2 * 1024 * 1024;
+ private protected LayoutResolverNamespace DefaultResolver = (LayoutResolverNamespace)SystemSchema.LayoutResolver;
+
+ private protected async Task<(List>, LayoutResolverNamespace)> LoadExpectedAsync(string expectedFile)
+ {
+ LayoutResolverNamespace resolver = this.DefaultResolver;
+ List> expected = new List>();
+ using (Stream stm = new FileStream(expectedFile, FileMode.Open))
+ {
+ // Read a RecordIO stream.
+ MemorySpanResizer resizer = new MemorySpanResizer(BenchmarkSuiteBase.InitialCapacity);
+ Result r = await stm.ReadRecordIOAsync(
+ record =>
+ {
+ r = BenchmarkSuiteBase.LoadOneRow(record, resolver, out Dictionary rowValue);
+ ResultAssert.IsSuccess(r);
+ expected.Add(rowValue);
+ return Result.Success;
+ },
+ segment =>
+ {
+ r = SegmentSerializer.Read(segment.Span, SystemSchema.LayoutResolver, out Segment s);
+ ResultAssert.IsSuccess(r);
+ Assert.IsNotNull(s.SDL);
+ resolver = new LayoutResolverNamespace(Namespace.Parse(s.SDL), resolver);
+ return Result.Success;
+ },
+ resizer);
+
+ ResultAssert.IsSuccess(r);
+ }
+
+ return (expected, resolver);
+ }
+
+ private protected static async Task WriteAllRowsAsync(
+ string file,
+ string sdl,
+ LayoutResolver resolver,
+ Layout layout,
+ List> rows)
+ {
+ using (Stream stm = new FileStream(file, FileMode.Truncate))
+ {
+ // Create a reusable, resizable buffer.
+ MemorySpanResizer resizer = new MemorySpanResizer(BenchmarkSuiteBase.InitialCapacity);
+
+ // Write a RecordIO stream.
+ Result r = await stm.WriteRecordIOAsync(
+ new Segment("HybridRow.Tests.Perf Expected Results", sdl),
+ (long index, out ReadOnlyMemory body) =>
+ {
+ body = default;
+ if (index >= rows.Count)
+ {
+ return Result.Success;
+ }
+
+ StreamingRowGenerator writer = new StreamingRowGenerator(
+ BenchmarkSuiteBase.InitialCapacity,
+ layout,
+ resolver,
+ resizer);
+
+ Result r2 = writer.WriteBuffer(rows[(int)index]);
+ if (r2 != Result.Success)
+ {
+ return r2;
+ }
+
+ body = resizer.Memory.Slice(0, writer.Length);
+ return Result.Success;
+ });
+
+ ResultAssert.IsSuccess(r);
+ }
+ }
+
+ private protected static Result LoadOneRow(Memory buffer, LayoutResolver resolver, out Dictionary rowValue)
+ {
+ RowBuffer row = new RowBuffer(buffer.Span, HybridRowVersion.V1, resolver);
+ RowReader reader = new RowReader(ref row);
+ return DiagnosticConverter.ReaderToDynamic(ref reader, out rowValue);
+ }
+
+ private protected static class ResultAssert
+ {
+ public static void IsSuccess(Result actual)
+ {
+ if (actual != Result.Success)
+ {
+ Assert.AreEqual(Result.Success, actual);
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/src/HybridRow.Tests.Perf/BsonJsonModelRowGenerator.cs b/dotnet/src/HybridRow.Tests.Perf/BsonJsonModelRowGenerator.cs
new file mode 100644
index 0000000..8342aa9
--- /dev/null
+++ b/dotnet/src/HybridRow.Tests.Perf/BsonJsonModelRowGenerator.cs
@@ -0,0 +1,110 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ------------------------------------------------------------
+
+namespace Microsoft.Azure.Cosmos.Serialization.HybridRow.Tests.Perf
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using Microsoft.Azure.Cosmos.Core;
+ using Microsoft.Azure.Cosmos.Core.Utf8;
+ using MongoDB.Bson.IO;
+
+ internal sealed class BsonJsonModelRowGenerator : IDisposable
+ {
+ private readonly MemoryStream stream;
+ private readonly BsonWriter writer;
+
+ public BsonJsonModelRowGenerator(int capacity)
+ {
+ this.stream = new MemoryStream(capacity);
+ this.writer = new BsonBinaryWriter(this.stream);
+ }
+
+ public int Length => (int)this.stream.Position;
+
+ public byte[] ToArray()
+ {
+ return this.stream.ToArray();
+ }
+
+ public void Reset()
+ {
+ this.stream.SetLength(0);
+ this.stream.Position = 0;
+ }
+
+ public void WriteBuffer(Dictionary dict)
+ {
+ this.writer.WriteStartDocument();
+ foreach ((Utf8String propPath, object propValue) in dict)
+ {
+ this.JsonModelSwitch(propPath, propValue);
+ }
+
+ this.writer.WriteEndDocument();
+ }
+
+ public void Dispose()
+ {
+ this.writer.Dispose();
+ this.stream.Dispose();
+ }
+
+ private void JsonModelSwitch(Utf8String path, object value)
+ {
+ if (path != null)
+ {
+ this.writer.WriteName(path.ToString());
+ }
+
+ switch (value)
+ {
+ case null:
+ this.writer.WriteNull();
+ return;
+ case bool x:
+ this.writer.WriteBoolean(x);
+ return;
+ case long x:
+ this.writer.WriteInt64(x);
+ return;
+ case double x:
+ this.writer.WriteDouble(x);
+ return;
+ case string x:
+ this.writer.WriteString(x);
+ return;
+ case Utf8String x:
+ this.writer.WriteString(x.ToString());
+ return;
+ case byte[] x:
+ this.writer.WriteBytes(x);
+ return;
+ case Dictionary x:
+ this.writer.WriteStartDocument();
+ foreach ((Utf8String propPath, object propValue) in x)
+ {
+ this.JsonModelSwitch(propPath, propValue);
+ }
+
+ this.writer.WriteEndDocument();
+ return;
+ case List