From 08cf50c54a704bd76a30602a5efc65ccb7985695 Mon Sep 17 00:00:00 2001
From: Robert Schmidtke <robert-schmidtke@users.noreply.github.com>
Date: Mon, 12 Mar 2018 19:30:46 +0100
Subject: [PATCH] Java/C#/Python prefixed size support (#4445)

* initial changes to support size prefixed buffers in Java

* add slice equivalent to CSharp ByteBuffer

* resolve TODO for slicing in CSharp code generation

* add newly generated Java and CSharp test sources

* fix typo in comment

* add FinishSizePrefixed methods to CSharp FlatBufferBuilder as well

* add option to allow writing the prefix as well

* generate size-prefixed monster binary as well

* extend JavaTest to test the size prefixed binary as well

* use constants for size prefix length

* fuse common code for getRootAs and getSizePrefixedRootAs

* pulled file identifier out of if

* add FinishSizePrefixed, GetSizePrefixedRootAs support for Python

* Revert "extend JavaTest to test the size prefixed binary as well"

This reverts commit 68be4420dda47e8d0600bb19691f03be71503a68.

* Revert "generate size-prefixed monster binary as well"

This reverts commit 2939516fdf78df4f061c627221e232b312301417.

* fix ByteBuffer.cs Slice() method; add proper CSharp and Java tests

* fix unused parameter

* increment version number

* pulled out generated methods into separate utility class

* pulled out generated methods into separate utility class for Python

* fix indentation

* remove unnecessary comment

* fix newline and copyright

* add ByteBufferUtil to csproj compilation

* hide ByteBuffer's internal data; track offset into parent's array

* test unsafe versions as well; compile and run in debug mode

* clarify help text for size prefix

* move ByteBuffer slicing behavior to subclass

* fix protection levels

* add size prefix support for text generation

* add ByteBufferSlice to csproj compilation

* revert size prefix handling for nested buffers

* use duplicate instead of slice for removing size prefix

* remove slice subclass and use duplicate for removing size prefix

* remove slice specific tests

* remove superfluous command line option
---
 .gitignore                                    |   1 +
 .../google/flatbuffers/ByteBufferUtil.java    |  58 +++++++
 java/com/google/flatbuffers/Constants.java    |   2 +
 .../google/flatbuffers/FlatBufferBuilder.java |  55 +++++-
 net/FlatBuffers/ByteBuffer.cs                 |  72 +++++++-
 net/FlatBuffers/ByteBuffer.exe                | Bin 0 -> 71168 bytes
 net/FlatBuffers/ByteBufferUtil.cs             |  39 +++++
 net/FlatBuffers/FlatBufferBuilder.cs          | 141 ++++++++++-----
 net/FlatBuffers/FlatBufferConstants.cs        |   1 +
 net/FlatBuffers/Table.cs                      |  17 +-
 python/flatbuffers/builder.py                 |  22 ++-
 python/flatbuffers/util.py                    |  28 +++
 src/idl_gen_general.cpp                       |  27 +--
 tests/FlatBuffers.Test/ByteBufferTests.cs     |  95 ++++++----
 .../FlatBuffers.Test/FlatBuffers.Test.csproj  |   3 +
 .../FlatBuffersExampleTests.cs                |  38 +++-
 .../FlatBuffers.Test/FlatBuffersFuzzTests.cs  | 164 ++++++++++++------
 tests/FlatBuffers.Test/NetTest.sh             |  18 +-
 tests/JavaTest.java                           |  32 +++-
 tests/MyGame/Example/Monster.cs               |   1 +
 tests/MyGame/Example/Monster.java             |   1 +
 tests/monster_test.bfbs                       | Bin 6184 -> 6112 bytes
 .../namespace_test2_generated.ts              |  20 +--
 tests/py_test.py                              |  23 ++-
 24 files changed, 660 insertions(+), 198 deletions(-)
 create mode 100644 java/com/google/flatbuffers/ByteBufferUtil.java
 create mode 100755 net/FlatBuffers/ByteBuffer.exe
 create mode 100644 net/FlatBuffers/ByteBufferUtil.cs
 create mode 100644 python/flatbuffers/util.py

diff --git a/.gitignore b/.gitignore
index 9a3b07e3..c1011c38 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,6 +47,7 @@ snapshot.sh
 tags
 tests/go_gen
 tests/monsterdata_java_wire.mon
+tests/monsterdata_java_wire_sp.mon
 tests/monsterdata_go_wire.mon
 tests/monsterdata_javascript_wire.mon
 tests/unicode_test.mon
diff --git a/java/com/google/flatbuffers/ByteBufferUtil.java b/java/com/google/flatbuffers/ByteBufferUtil.java
new file mode 100644
index 00000000..624dc4e2
--- /dev/null
+++ b/java/com/google/flatbuffers/ByteBufferUtil.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.flatbuffers;
+
+import static com.google.flatbuffers.Constants.*;
+
+import java.nio.ByteBuffer;
+
+/// @file
+/// @addtogroup flatbuffers_java_api
+/// @{
+
+/**
+ * Class that collects utility functions around `ByteBuffer`.
+ */
+public class ByteBufferUtil {
+
+	/**
+     * Extract the size prefix from a `ByteBuffer`.
+     * 
+     * @param bb a size-prefixed buffer
+     * @return the size prefix
+     */
+    public static int getSizePrefix(ByteBuffer bb) {
+        return bb.getInt(bb.position());
+    }
+
+	/**
+     * Create a duplicate of a size-prefixed `ByteBuffer` that has its position
+     * advanced just past the size prefix.
+     * 
+     * @param bb a size-prefixed buffer
+     * @return a new buffer on the same underlying data that has skipped the
+     *         size prefix
+     */
+    public static ByteBuffer removeSizePrefix(ByteBuffer bb) {
+        ByteBuffer s = bb.duplicate();
+        s.position(s.position() + SIZE_PREFIX_LENGTH);
+        return s;
+    }
+
+}
+
+/// @}
diff --git a/java/com/google/flatbuffers/Constants.java b/java/com/google/flatbuffers/Constants.java
index f5906314..751f4a65 100644
--- a/java/com/google/flatbuffers/Constants.java
+++ b/java/com/google/flatbuffers/Constants.java
@@ -37,6 +37,8 @@ public class Constants {
     static final int SIZEOF_DOUBLE = 8;
     /** The number of bytes in a file identifier. */
     static final int FILE_IDENTIFIER_LENGTH = 4;
+    /** The number of bytes in a size prefix. */
+    public static final int SIZE_PREFIX_LENGTH = 4;
 }
 
 /// @endcond
diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java
index f98fbedc..44f107ae 100644
--- a/java/com/google/flatbuffers/FlatBufferBuilder.java
+++ b/java/com/google/flatbuffers/FlatBufferBuilder.java
@@ -816,30 +816,75 @@ public class FlatBufferBuilder {
      * Finalize a buffer, pointing to the given `root_table`.
      *
      * @param root_table An offset to be added to the buffer.
+     * @param size_prefix Whether to prefix the size to the buffer.
      */
-    public void finish(int root_table) {
-        prep(minalign, SIZEOF_INT);
+    protected void finish(int root_table, boolean size_prefix) {
+        prep(minalign, SIZEOF_INT + (size_prefix ? SIZEOF_INT : 0));
         addOffset(root_table);
+        if (size_prefix) {
+            addInt(bb.capacity() - space);
+        }
         bb.position(space);
         finished = true;
     }
 
+    /**
+     * Finalize a buffer, pointing to the given `root_table`.
+     *
+     * @param root_table An offset to be added to the buffer.
+     */
+    public void finish(int root_table) {
+        finish(root_table, false);
+    }
+
+    /**
+     * Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
+     *
+     * @param root_table An offset to be added to the buffer.
+     */
+    public void finishSizePrefixed(int root_table) {
+        finish(root_table, true);
+    }
+
     /**
      * Finalize a buffer, pointing to the given `root_table`.
      *
      * @param root_table An offset to be added to the buffer.
      * @param file_identifier A FlatBuffer file identifier to be added to the buffer before
      * `root_table`.
+     * @param size_prefix Whether to prefix the size to the buffer.
      */
-    public void finish(int root_table, String file_identifier) {
-        prep(minalign, SIZEOF_INT + FILE_IDENTIFIER_LENGTH);
+    protected void finish(int root_table, String file_identifier, boolean size_prefix) {
+        prep(minalign, SIZEOF_INT + FILE_IDENTIFIER_LENGTH + (size_prefix ? SIZEOF_INT : 0));
         if (file_identifier.length() != FILE_IDENTIFIER_LENGTH)
             throw new AssertionError("FlatBuffers: file identifier must be length " +
                                      FILE_IDENTIFIER_LENGTH);
         for (int i = FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) {
             addByte((byte)file_identifier.charAt(i));
         }
-        finish(root_table);
+        finish(root_table, size_prefix);
+    }
+
+    /**
+     * Finalize a buffer, pointing to the given `root_table`.
+     *
+     * @param root_table An offset to be added to the buffer.
+     * @param file_identifier A FlatBuffer file identifier to be added to the buffer before
+     * `root_table`.
+     */
+    public void finish(int root_table, String file_identifier) {
+        finish(root_table, file_identifier, false);
+    }
+
+    /**
+     * Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
+     *
+     * @param root_table An offset to be added to the buffer.
+     * @param file_identifier A FlatBuffer file identifier to be added to the buffer before
+     * `root_table`.
+     */
+    public void finishSizePrefixed(int root_table, String file_identifier) {
+        finish(root_table, file_identifier, true);
     }
 
     /**
diff --git a/net/FlatBuffers/ByteBuffer.cs b/net/FlatBuffers/ByteBuffer.cs
index 37a2c7e6..878e740b 100644
--- a/net/FlatBuffers/ByteBuffer.cs
+++ b/net/FlatBuffers/ByteBuffer.cs
@@ -30,6 +30,8 @@
 //
 
 using System;
+using System.IO;
+using System.Text;
 
 namespace FlatBuffers
 {
@@ -38,12 +40,12 @@ namespace FlatBuffers
     /// </summary>
     public class ByteBuffer
     {
-        private readonly byte[] _buffer;
+        protected byte[] _buffer;
         private int _pos;  // Must track start of the buffer.
 
         public int Length { get { return _buffer.Length; } }
 
-        public byte[] Data { get { return _buffer; } }
+        public ByteBuffer(int size) : this(new byte[size]) { }
 
         public ByteBuffer(byte[] buffer) : this(buffer, 0) { }
 
@@ -63,11 +65,64 @@ namespace FlatBuffers
             _pos = 0;
         }
 
+        // Create a new ByteBuffer on the same underlying data.
+        // The new ByteBuffer's position will be same as this buffer's.
+        public ByteBuffer Duplicate()
+        {
+            return new ByteBuffer(_buffer, Position);
+        }
+
+        // Increases the size of the ByteBuffer, and copies the old data towards
+        // the end of the new buffer.
+        public void GrowFront(int newSize)
+        {
+            if ((Length & 0xC0000000) != 0)
+                throw new Exception(
+                    "ByteBuffer: cannot grow buffer beyond 2 gigabytes.");
+
+            if (newSize < Length)
+                throw new Exception("ByteBuffer: cannot truncate buffer.");
+
+            byte[] newBuffer = new byte[newSize];
+            Buffer.BlockCopy(_buffer, 0, newBuffer, newSize - Length,
+                             Length);
+            _buffer = newBuffer;
+        }
+
+        public byte[] ToArray(int pos, int len)
+        {
+            byte[] arr = new byte[len];
+            Buffer.BlockCopy(_buffer, pos, arr, 0, len);
+            return arr;
+        }
+
+        public byte[] ToSizedArray()
+        {
+            return ToArray(Position, Length - Position);
+        }
+
+        public byte[] ToFullArray()
+        {
+            return ToArray(0, Length);
+        }
+
+        public ArraySegment<byte> ToArraySegment(int pos, int len)
+        {
+            return new ArraySegment<byte>(_buffer, pos, len);
+        }
+
+        public MemoryStream ToMemoryStream(int pos, int len)
+        {
+            return new MemoryStream(_buffer, pos, len);
+        }
+
+#if !UNSAFE_BYTEBUFFER
         // Pre-allocated helper arrays for convertion.
         private float[] floathelper = new[] { 0.0f };
         private int[] inthelper = new[] { 0 };
         private double[] doublehelper = new[] { 0.0 };
         private ulong[] ulonghelper = new[] { 0UL };
+#endif // !UNSAFE_BYTEBUFFER
 
         // Helper functions for the unsafe version.
         static public ushort ReverseBytes(ushort input)
@@ -136,7 +191,6 @@ namespace FlatBuffers
         }
 #endif // !UNSAFE_BYTEBUFFER
 
-
         private void AssertOffsetAndLength(int offset, int length)
         {
             #if !BYTEBUFFER_NO_BOUNDS_CHECK
@@ -171,6 +225,13 @@ namespace FlatBuffers
             PutByte(offset, value);
         }
 
+        public void PutStringUTF8(int offset, string value)
+        {
+            AssertOffsetAndLength(offset, value.Length);
+            Encoding.UTF8.GetBytes(value, 0, value.Length,
+                _buffer, offset);
+        }
+
 #if UNSAFE_BYTEBUFFER
         // Unsafe but more efficient versions of Put*.
         public void PutShort(int offset, short value)
@@ -321,6 +382,11 @@ namespace FlatBuffers
             return _buffer[index];
         }
 
+        public string GetStringUTF8(int startPos, int len)
+        {
+            return Encoding.UTF8.GetString(_buffer, startPos, len);
+        }
+
 #if UNSAFE_BYTEBUFFER
         // Unsafe but more efficient versions of Get*.
         public short GetShort(int offset)
diff --git a/net/FlatBuffers/ByteBuffer.exe b/net/FlatBuffers/ByteBuffer.exe
new file mode 100755
index 0000000000000000000000000000000000000000..4361c00f2a116cc1336d27077e71c7f11c21e063
GIT binary patch
literal 71168
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
YO}Kp$q%=^=$U0*dQ`k=uKO!3VA1ycl(*OVf

literal 0
HcmV?d00001

diff --git a/net/FlatBuffers/ByteBufferUtil.cs b/net/FlatBuffers/ByteBufferUtil.cs
new file mode 100644
index 00000000..66e82668
--- /dev/null
+++ b/net/FlatBuffers/ByteBufferUtil.cs
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace FlatBuffers
+{
+	/// <summary>
+	/// Class that collects utility functions around `ByteBuffer`.
+	/// </summary>
+	public class ByteBufferUtil
+	{
+		// Extract the size prefix from a `ByteBuffer`.
+		public static int GetSizePrefix(ByteBuffer bb) {
+			return bb.GetInt(bb.Position);
+		}
+
+		// Create a duplicate of a size-prefixed `ByteBuffer` that has its position
+		// advanced just past the size prefix.
+		public static ByteBuffer RemoveSizePrefix(ByteBuffer bb) {
+			ByteBuffer s = bb.Duplicate();
+			s.Position += FlatBufferConstants.SizePrefixLength;
+			return s;
+		}
+	}
+}
diff --git a/net/FlatBuffers/FlatBufferBuilder.cs b/net/FlatBuffers/FlatBufferBuilder.cs
index 90627fdf..a2224498 100644
--- a/net/FlatBuffers/FlatBufferBuilder.cs
+++ b/net/FlatBuffers/FlatBufferBuilder.cs
@@ -59,7 +59,7 @@ namespace FlatBuffers
                 throw new ArgumentOutOfRangeException("initialSize",
                     initialSize, "Must be greater than zero");
             _space = initialSize;
-            _bb = new ByteBuffer(new byte[initialSize]);
+            _bb = new ByteBuffer(initialSize);
         }
 
         /// <summary>
@@ -99,18 +99,7 @@ namespace FlatBuffers
         // the end of the new buffer (since we build the buffer backwards).
         void GrowBuffer()
         {
-            var oldBuf = _bb.Data;
-            var oldBufSize = oldBuf.Length;
-            if ((oldBufSize & 0xC0000000) != 0)
-                throw new Exception(
-                    "FlatBuffers: cannot grow buffer beyond 2 gigabytes.");
-
-            var newBufSize = oldBufSize << 1;
-            var newBuf = new byte[newBufSize];
-
-            Buffer.BlockCopy(oldBuf, 0, newBuf, newBufSize - oldBufSize,
-                             oldBufSize);
-            _bb = new ByteBuffer(newBuf, newBufSize);
+            _bb.GrowFront(_bb.Length << 1);
         }
 
         // Prepare to write an element of `size` after `additional_bytes`
@@ -475,7 +464,7 @@ namespace FlatBuffers
             AddByte(0);
             var utf8StringLen = Encoding.UTF8.GetByteCount(s);
             StartVector(1, utf8StringLen, 1);
-            Encoding.UTF8.GetBytes(s, 0, s.Length, _bb.Data, _space -= utf8StringLen);
+            _bb.PutStringUTF8(_space -= utf8StringLen, s);
             return new StringOffset(EndVector().Value);
         }
 
@@ -586,13 +575,41 @@ namespace FlatBuffers
         /// <param name="rootTable">
         /// An offset to be added to the buffer.
         /// </param>
-        public void Finish(int rootTable)
+        /// <param name="sizePrefix">
+        /// Whether to prefix the size to the buffer.
+        /// </param>
+        protected void Finish(int rootTable, bool sizePrefix)
         {
-            Prep(_minAlign, sizeof(int));
+            Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0));
             AddOffset(rootTable);
+            if (sizePrefix) {
+                AddInt(_bb.Length - _space);
+            }
             _bb.Position = _space;
         }
 
+        /// <summary>
+        /// Finalize a buffer, pointing to the given `root_table`.
+        /// </summary>
+        /// <param name="rootTable">
+        /// An offset to be added to the buffer.
+        /// </param>
+        public void Finish(int rootTable)
+        {
+            Finish(rootTable, false);
+        }
+
+        /// <summary>
+        /// Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
+        /// </summary>
+        /// <param name="rootTable">
+        /// An offset to be added to the buffer.
+        /// </param>
+        public void FinishSizePrefixed(int rootTable)
+        {
+            Finish(rootTable, true);
+        }
+
         /// <summary>
         /// Get the ByteBuffer representing the FlatBuffer.
         /// </summary>
@@ -615,41 +632,69 @@ namespace FlatBuffers
         /// </returns>
         public byte[] SizedByteArray()
         {
-            var newArray = new byte[_bb.Data.Length - _bb.Position];
-            Buffer.BlockCopy(_bb.Data, _bb.Position, newArray, 0,
-                             _bb.Data.Length - _bb.Position);
-            return newArray;
-        }
-
-         /// <summary>
-         /// Finalize a buffer, pointing to the given `rootTable`.
-         /// </summary>
-         /// <param name="rootTable">
-         /// An offset to be added to the buffer.
-         /// </param>
-         /// <param name="fileIdentifier">
-         /// A FlatBuffer file identifier to be added to the buffer before
-         /// `root_table`.
-         /// </param>
-         public void Finish(int rootTable, string fileIdentifier)
-         {
-             Prep(_minAlign, sizeof(int) +
-                             FlatBufferConstants.FileIdentifierLength);
-             if (fileIdentifier.Length !=
-                 FlatBufferConstants.FileIdentifierLength)
-                 throw new ArgumentException(
-                     "FlatBuffers: file identifier must be length " +
-                     FlatBufferConstants.FileIdentifierLength,
-                     "fileIdentifier");
-             for (int i = FlatBufferConstants.FileIdentifierLength - 1; i >= 0;
-                  i--)
-             {
-                AddByte((byte)fileIdentifier[i]);
-             }
-             Finish(rootTable);
+            return _bb.ToSizedArray();
+        }
+
+        /// <summary>
+        /// Finalize a buffer, pointing to the given `rootTable`.
+        /// </summary>
+        /// <param name="rootTable">
+        /// An offset to be added to the buffer.
+        /// </param>
+        /// <param name="fileIdentifier">
+        /// A FlatBuffer file identifier to be added to the buffer before
+        /// `root_table`.
+        /// </param>
+        /// <param name="sizePrefix">
+        /// Whether to prefix the size to the buffer.
+        /// </param>
+        protected void Finish(int rootTable, string fileIdentifier, bool sizePrefix)
+        {
+            Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0) +
+                            FlatBufferConstants.FileIdentifierLength);
+            if (fileIdentifier.Length !=
+                FlatBufferConstants.FileIdentifierLength)
+                throw new ArgumentException(
+                    "FlatBuffers: file identifier must be length " +
+                    FlatBufferConstants.FileIdentifierLength,
+                    "fileIdentifier");
+            for (int i = FlatBufferConstants.FileIdentifierLength - 1; i >= 0;
+                 i--)
+            {
+               AddByte((byte)fileIdentifier[i]);
+            }
+            Finish(rootTable, sizePrefix);
         }
 
+        /// <summary>
+        /// Finalize a buffer, pointing to the given `rootTable`.
+        /// </summary>
+        /// <param name="rootTable">
+        /// An offset to be added to the buffer.
+        /// </param>
+        /// <param name="fileIdentifier">
+        /// A FlatBuffer file identifier to be added to the buffer before
+        /// `root_table`.
+        /// </param>
+        public void Finish(int rootTable, string fileIdentifier)
+        {
+            Finish(rootTable, fileIdentifier, false);
+        }
 
+        /// <summary>
+        /// Finalize a buffer, pointing to the given `rootTable`, with the size prefixed.
+        /// </summary>
+        /// <param name="rootTable">
+        /// An offset to be added to the buffer.
+        /// </param>
+        /// <param name="fileIdentifier">
+        /// A FlatBuffer file identifier to be added to the buffer before
+        /// `root_table`.
+        /// </param>
+        public void FinishSizePrefixed(int rootTable, string fileIdentifier)
+        {
+            Finish(rootTable, fileIdentifier, true);
+        }
     }
 }
 
diff --git a/net/FlatBuffers/FlatBufferConstants.cs b/net/FlatBuffers/FlatBufferConstants.cs
index ab3092c4..e30f3f39 100644
--- a/net/FlatBuffers/FlatBufferConstants.cs
+++ b/net/FlatBuffers/FlatBufferConstants.cs
@@ -24,5 +24,6 @@ namespace FlatBuffers
     public static class FlatBufferConstants
     {
         public const int FileIdentifierLength = 4;
+        public const int SizePrefixLength = 4;
     }
 }
diff --git a/net/FlatBuffers/Table.cs b/net/FlatBuffers/Table.cs
index 55182b38..4a188ff8 100644
--- a/net/FlatBuffers/Table.cs
+++ b/net/FlatBuffers/Table.cs
@@ -60,7 +60,7 @@ namespace FlatBuffers
             offset += bb.GetInt(offset);
             var len = bb.GetInt(offset);
             var startPos = offset + sizeof(int);
-            return Encoding.UTF8.GetString(bb.Data, startPos , len);
+            return bb.GetStringUTF8(startPos, len);
         }
 
         // Get the length of a vector whose offset is stored at "offset" in this object.
@@ -91,7 +91,7 @@ namespace FlatBuffers
 
             var pos = this.__vector(o);
             var len = this.__vector_len(o);
-            return new ArraySegment<byte>(this.bb.Data, pos, len);
+            return bb.ToArraySegment(pos, len);
         }
 
         // Initialize any Table-derived type to point to the union at the given offset.
@@ -126,10 +126,11 @@ namespace FlatBuffers
             var startPos_1 = offset_1 + sizeof(int);
             var startPos_2 = offset_2 + sizeof(int);
             var len = Math.Min(len_1, len_2);
-            byte[] bbArray = bb.Data;
             for(int i = 0; i < len; i++) {
-                if (bbArray[i + startPos_1] != bbArray[i + startPos_2])
-                    return bbArray[i + startPos_1] - bbArray[i + startPos_2];
+                byte b1 = bb.Get(i + startPos_1);
+                byte b2 = bb.Get(i + startPos_2);
+                if (b1 != b2)
+                    return b1 - b2;
             }
             return len_1 - len_2;
         }
@@ -142,10 +143,10 @@ namespace FlatBuffers
             var len_2 = key.Length;
             var startPos_1 = offset_1 + sizeof(int);
             var len = Math.Min(len_1, len_2);
-            byte[] bbArray = bb.Data;
             for (int i = 0; i < len; i++) {
-                if (bbArray[i + startPos_1] != key[i])
-                    return bbArray[i + startPos_1] - key[i];
+                byte b = bb.Get(i + startPos_1);
+                if (b != key[i])
+                    return b - key[i];
             }
             return len_1 - len_2;
         }
diff --git a/python/flatbuffers/builder.py b/python/flatbuffers/builder.py
index a21f3616..dea77ebf 100644
--- a/python/flatbuffers/builder.py
+++ b/python/flatbuffers/builder.py
@@ -483,14 +483,32 @@ class Builder(object):
         self.current_vtable[slotnum] = self.Offset()
     ## @endcond
 
-    def Finish(self, rootTable):
+    def __Finish(self, rootTable, sizePrefix):
         """Finish finalizes a buffer, pointing to the given `rootTable`."""
         N.enforce_number(rootTable, N.UOffsetTFlags)
-        self.Prep(self.minalign, N.UOffsetTFlags.bytewidth)
+        prepSize = N.UOffsetTFlags.bytewidth
+        if sizePrefix:
+            prepSize += N.Int32Flags.bytewidth
+        self.Prep(self.minalign, prepSize)
         self.PrependUOffsetTRelative(rootTable)
+        if sizePrefix:
+            size = len(self.Bytes) - self.Head()
+            N.enforce_number(size, N.Int32Flags)
+            self.PrependInt32(size)
         self.finished = True
         return self.Head()
 
+    def Finish(self, rootTable):
+        """Finish finalizes a buffer, pointing to the given `rootTable`."""
+        return self.__Finish(rootTable, False)
+
+    def FinishSizePrefixed(self, rootTable):
+        """
+        Finish finalizes a buffer, pointing to the given `rootTable`,
+        with the size prefixed.
+        """
+        return self.__Finish(rootTable, True)
+
     ## @cond FLATBUFFERS_INTERNAL
     def Prepend(self, flags, off):
         self.Prep(flags.bytewidth, 0)
diff --git a/python/flatbuffers/util.py b/python/flatbuffers/util.py
new file mode 100644
index 00000000..abcb9c75
--- /dev/null
+++ b/python/flatbuffers/util.py
@@ -0,0 +1,28 @@
+# Copyright 2017 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from . import encode
+from . import number_types
+from . import packer
+
+def GetSizePrefix(buf, offset):
+	"""Extract the size prefix from a buffer."""
+	return encode.Get(packer.int32, buf, offset)
+
+def RemoveSizePrefix(buf, offset):
+	"""
+	Create a slice of a size-prefixed buffer that has
+	its position advanced just past the size prefix.
+	"""
+	return buf, offset + number_types.Int32Flags.bytewidth
diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp
index 9c23c5dd..970f08cc 100644
--- a/src/idl_gen_general.cpp
+++ b/src/idl_gen_general.cpp
@@ -1331,17 +1331,22 @@ class GeneralGenerator : public BaseGenerator {
       }
       code += "    return " + GenOffsetConstruct(struct_def, "o") + ";\n  }\n";
       if (parser_.root_struct_def_ == &struct_def) {
-        code += "  public static void ";
-        code += FunctionStart('F') + "inish" + struct_def.name;
-        code +=
-            "Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def);
-        code += " offset) {";
-        code += " builder." + FunctionStart('F') + "inish(offset";
-        if (lang_.language == IDLOptions::kCSharp) { code += ".Value"; }
-
-        if (parser_.file_identifier_.length())
-          code += ", \"" + parser_.file_identifier_ + "\"";
-        code += "); }\n";
+        std::string size_prefix[] = { "", "SizePrefixed" };
+        for (int i = 0; i < 2; ++i) {
+          code += "  public static void ";
+          code += FunctionStart('F') + "inish" + size_prefix[i] +
+                  struct_def.name;
+          code += "Buffer(FlatBufferBuilder builder, " +
+                  GenOffsetType(struct_def);
+          code += " offset) {";
+          code += " builder." + FunctionStart('F') + "inish" + size_prefix[i] +
+                  "(offset";
+          if (lang_.language == IDLOptions::kCSharp) { code += ".Value"; }
+
+          if (parser_.file_identifier_.length())
+            code += ", \"" + parser_.file_identifier_ + "\"";
+          code += "); }\n";
+        }
       }
     }
     // Only generate key compare function for table,
diff --git a/tests/FlatBuffers.Test/ByteBufferTests.cs b/tests/FlatBuffers.Test/ByteBufferTests.cs
index 3324f12a..58bd71e5 100644
--- a/tests/FlatBuffers.Test/ByteBufferTests.cs
+++ b/tests/FlatBuffers.Test/ByteBufferTests.cs
@@ -44,8 +44,7 @@ namespace FlatBuffers.Test
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutByteCannotPutAtOffsetPastLength()
         {
-            var buffer = new byte[1];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(1);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutByte(1, 99));
         }
 #endif
@@ -66,8 +65,7 @@ namespace FlatBuffers.Test
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutShortCannotPutAtOffsetPastLength()
         {
-            var buffer = new byte[2];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(2);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(2, 99));
         }
 #endif
@@ -76,16 +74,14 @@ namespace FlatBuffers.Test
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutShortChecksLength()
         {
-            var buffer = new byte[1];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(1);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(0, 99));
         }
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutShortChecksLengthAndOffset()
         {
-            var buffer = new byte[2];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(2);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(1, 99));
         }
 #endif
@@ -108,24 +104,21 @@ namespace FlatBuffers.Test
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutIntCannotPutAtOffsetPastLength()
         {
-            var buffer = new byte[4];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(4);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(2, 0x0A0B0C0D));
         }
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutIntChecksLength()
         {
-            var buffer = new byte[1];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(1);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(0, 0x0A0B0C0D));
         }
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutIntChecksLengthAndOffset()
         {
-            var buffer = new byte[4];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(4);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(2, 0x0A0B0C0D));
         }
 #endif
@@ -152,24 +145,21 @@ namespace FlatBuffers.Test
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutLongCannotPutAtOffsetPastLength()
         {
-            var buffer = new byte[8];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(8);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(2, 0x010203040A0B0C0D));
         }
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutLongChecksLength()
         {
-            var buffer = new byte[1];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(1);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(0, 0x010203040A0B0C0D));
         }
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutLongChecksLengthAndOffset()
         {
-            var buffer = new byte[8];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(8);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(2, 0x010203040A0B0C0D));
         }
 #endif
@@ -187,8 +177,7 @@ namespace FlatBuffers.Test
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetByteChecksOffset()
         {
-            var buffer = new byte[1];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(1);
             Assert.Throws<ArgumentOutOfRangeException>(()=>uut.Get(1));
         }
 #endif
@@ -207,16 +196,14 @@ namespace FlatBuffers.Test
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetShortChecksOffset()
         {
-            var buffer = new byte[2];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(2);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetShort(2));
         }
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetShortChecksLength()
         {
-            var buffer = new byte[2];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(2);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetShort(1));
         }
 #endif
@@ -237,16 +224,14 @@ namespace FlatBuffers.Test
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetIntChecksOffset()
         {
-            var buffer = new byte[4];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(4);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetInt(4));
         }
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetIntChecksLength()
         {
-            var buffer = new byte[2];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(2);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetInt(0));
         }
 #endif
@@ -271,16 +256,14 @@ namespace FlatBuffers.Test
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetLongChecksOffset()
         {
-            var buffer = new byte[8];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(8);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetLong(8));
         }
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetLongChecksLength()
         {
-            var buffer = new byte[7];
-            var uut = new ByteBuffer(buffer);
+            var uut = new ByteBuffer(7);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetLong(0));
         }
 #endif
@@ -317,5 +300,49 @@ namespace FlatBuffers.Test
             var rereverse = ByteBuffer.ReverseBytes(reverse);
             Assert.AreEqual(original, rereverse);
         }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_ToFullArray_MatchesBuffer()
+        {
+            var buffer = new byte[4];
+            buffer[0] = 0x0D;
+            buffer[1] = 0x0C;
+            buffer[2] = 0x0B;
+            buffer[3] = 0x0A;
+            var uut = new ByteBuffer(buffer);
+            Assert.ArrayEqual(buffer, uut.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_ToSizedArray_MatchesBuffer()
+        {
+            var buffer = new byte[4];
+            buffer[0] = 0x0D;
+            buffer[1] = 0x0C;
+            buffer[2] = 0x0B;
+            buffer[3] = 0x0A;
+            var uut = new ByteBuffer(buffer);
+            Assert.ArrayEqual(buffer, uut.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Duplicate_MatchesBuffer()
+        {
+            var buffer = new byte[4];
+            buffer[0] = 0x0D;
+            buffer[1] = 0x0C;
+            buffer[2] = 0x0B;
+            buffer[3] = 0x0A;
+            var uut = new ByteBuffer(buffer);
+            Assert.AreEqual(0x0A0B0C0D, uut.GetInt(0));
+
+            // Advance by two bytes
+            uut.Position = 2; uut = uut.Duplicate();
+            Assert.AreEqual(0x0A0B, uut.GetShort(2));
+
+            // Advance by one more byte
+            uut.Position = 1; uut = uut.Duplicate();
+            Assert.AreEqual(0x0A, uut.Get(3));
+        }
     }
 }
diff --git a/tests/FlatBuffers.Test/FlatBuffers.Test.csproj b/tests/FlatBuffers.Test/FlatBuffers.Test.csproj
index 38d62d61..7c67274a 100644
--- a/tests/FlatBuffers.Test/FlatBuffers.Test.csproj
+++ b/tests/FlatBuffers.Test/FlatBuffers.Test.csproj
@@ -41,6 +41,9 @@
     <Compile Include="..\..\net\FlatBuffers\ByteBuffer.cs">
       <Link>FlatBuffers\ByteBuffer.cs</Link>
     </Compile>
+    <Compile Include="..\..\net\FlatBuffers\ByteBufferUtil.cs">
+      <Link>FlatBuffers\ByteBufferUtil.cs</Link>
+    </Compile>
     <Compile Include="..\..\net\FlatBuffers\IFlatbufferObject.cs">
       <Link>FlatBuffers\IFlatbufferObject.cs</Link>
     </Compile>
diff --git a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
index ccd5b05d..82d4fdf2 100644
--- a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
+++ b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
@@ -32,6 +32,12 @@ namespace FlatBuffers.Test
 
         [FlatBuffersTestMethod]
         public void CanCreateNewFlatBufferFromScratch()
+        {
+            CanCreateNewFlatBufferFromScratch(true);
+            CanCreateNewFlatBufferFromScratch(false);
+        }
+
+        private void CanCreateNewFlatBufferFromScratch(bool sizePrefix)
         {
             // Second, let's create a FlatBuffer from scratch in C#, and test it also.
             // We use an initial size of 1 to exercise the reallocation algorithm,
@@ -95,22 +101,40 @@ namespace FlatBuffers.Test
             Monster.AddTestarrayoftables(fbb, sortMons);
             var mon = Monster.EndMonster(fbb);
 
-            Monster.FinishMonsterBuffer(fbb, mon);
+            if (sizePrefix)
+            {
+                Monster.FinishSizePrefixedMonsterBuffer(fbb, mon);
+            }
+            else
+            {
+                Monster.FinishMonsterBuffer(fbb, mon);
+            }
 
 
             // Dump to output directory so we can inspect later, if needed
-            using (var ms = new MemoryStream(fbb.DataBuffer.Data, fbb.DataBuffer.Position, fbb.Offset))
+            using (var ms = fbb.DataBuffer.ToMemoryStream(fbb.DataBuffer.Position, fbb.Offset))
             {
                 var data = ms.ToArray();
-                File.WriteAllBytes(@"Resources/monsterdata_cstest.mon",data);
+                string filename = @"Resources/monsterdata_cstest" + (sizePrefix ? "_sp" : "") + ".mon";
+                File.WriteAllBytes(filename, data);
+            }
+
+            // Remove the size prefix if necessary for further testing
+            ByteBuffer dataBuffer = fbb.DataBuffer;
+            if (sizePrefix)
+            {
+                Assert.AreEqual(ByteBufferUtil.GetSizePrefix(dataBuffer) + FlatBufferConstants.SizePrefixLength,
+                                dataBuffer.Length - dataBuffer.Position);
+                dataBuffer = ByteBufferUtil.RemoveSizePrefix(dataBuffer);
             }
 
             // Now assert the buffer
-            TestBuffer(fbb.DataBuffer);
+            TestBuffer(dataBuffer);
 
             //Attempt to mutate Monster fields and check whether the buffer has been mutated properly
             // revert to original values after testing
-            Monster monster = Monster.GetRootAsMonster(fbb.DataBuffer);
+            Monster monster = Monster.GetRootAsMonster(dataBuffer);
+            
 
             // mana is optional and does not exist in the buffer so the mutation should fail
             // the mana field should retain its default value
@@ -161,12 +185,12 @@ namespace FlatBuffers.Test
             pos.MutateX(1.0f);
             Assert.AreEqual(pos.X, 1.0f);
 
-            TestBuffer(fbb.DataBuffer);
+            TestBuffer(dataBuffer);
         }
 
         private void TestBuffer(ByteBuffer bb)
         {
-            var monster = Monster.GetRootAsMonster(bb);
+            Monster monster = Monster.GetRootAsMonster(bb);
 
             Assert.AreEqual(80, monster.Hp);
             Assert.AreEqual(150, monster.Mana);
diff --git a/tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs b/tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs
index d9332465..2d411a2b 100644
--- a/tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs
+++ b/tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs
@@ -33,21 +33,21 @@ namespace FlatBuffers.Test
         public void TestNumbers()
         {
             var builder = new FlatBufferBuilder(1);
-            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
             builder.AddBool(true);
-            Assert.ArrayEqual(new byte[] { 1 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 1 }, builder.DataBuffer.ToFullArray());
             builder.AddSbyte(-127);
-            Assert.ArrayEqual(new byte[] { 129, 1 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 129, 1 }, builder.DataBuffer.ToFullArray());
             builder.AddByte(255);
-            Assert.ArrayEqual(new byte[] { 0, 255, 129, 1 }, builder.DataBuffer.Data); // First pad
+            Assert.ArrayEqual(new byte[] { 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // First pad
             builder.AddShort(-32222);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.Data); // Second pad
+            Assert.ArrayEqual(new byte[] { 0, 0, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // Second pad
             builder.AddUshort(0xFEEE);
-            Assert.ArrayEqual(new byte[] { 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.Data); // no pad
+            Assert.ArrayEqual(new byte[] { 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // no pad
             builder.AddInt(-53687092);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.Data); // third pad
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // third pad
             builder.AddUint(0x98765432);
-            Assert.ArrayEqual(new byte[] { 0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.Data); // no pad
+            Assert.ArrayEqual(new byte[] { 0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // no pad
         }
 
         [FlatBuffersTestMethod]
@@ -55,11 +55,11 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.AddUlong(0x1122334455667788);
-            Assert.ArrayEqual(new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, builder.DataBuffer.ToFullArray());
 
             builder = new FlatBufferBuilder(1);
             builder.AddLong(0x1122334455667788);
-            Assert.ArrayEqual(new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -67,11 +67,11 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.StartVector(sizeof(byte), 1, 1);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
             builder.AddByte(1);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
             builder.EndVector();
-            Assert.ArrayEqual(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -79,13 +79,13 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.StartVector(sizeof(byte), 2, 1);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
             builder.AddByte(1);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, builder.DataBuffer.ToFullArray());
             builder.AddByte(2);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 2, 1, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 2, 1, 0, 0 }, builder.DataBuffer.ToFullArray());
             builder.EndVector();
-            Assert.ArrayEqual(new byte[] { 2, 0, 0, 0, 2, 1, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 2, 0, 0, 0, 2, 1, 0, 0 }, builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -93,11 +93,11 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.StartVector(sizeof(ushort), 1, 1);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
             builder.AddUshort(1);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
             builder.EndVector();
-            Assert.ArrayEqual(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -105,13 +105,13 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.StartVector(sizeof(ushort), 2, 1);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
             builder.AddUshort(0xABCD);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0xCD, 0xAB }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0xCD, 0xAB }, builder.DataBuffer.ToFullArray());
             builder.AddUshort(0xDCBA);
-            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB }, builder.DataBuffer.ToFullArray());
             builder.EndVector();
-            Assert.ArrayEqual(new byte[] { 2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB }, builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -119,7 +119,7 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.CreateString("foo");
-            Assert.ArrayEqual(new byte[] { 3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0 }, builder.DataBuffer.ToFullArray());
 
             builder.CreateString("moop");
             Assert.ArrayEqual(new byte[]
@@ -132,7 +132,7 @@ namespace FlatBuffers.Test
                 0, 0, 0, 0, // zero terminator with 3 byte pad
                 3, 0, 0, 0,
                 (byte)'f', (byte)'o', (byte)'o', 0
-            }, builder.DataBuffer.Data);
+            }, builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -144,7 +144,7 @@ namespace FlatBuffers.Test
             {
                 3, 0, 0, 0,
                 0x01, 0x02, 0x03, 0
-            }, builder.DataBuffer.Data); // No padding
+            }, builder.DataBuffer.ToFullArray()); // No padding
             builder.CreateString("\x04\x05\x06\x07");
             Assert.ArrayEqual(new byte[]
             {
@@ -156,7 +156,7 @@ namespace FlatBuffers.Test
                 0, 0, 0, 0, // zero terminator with 3 byte pad
                 3, 0, 0, 0,
                 0x01, 0x02, 0x03, 0
-            }, builder.DataBuffer.Data); // No padding
+            }, builder.DataBuffer.ToFullArray()); // No padding
         }
 
         [FlatBuffersTestMethod]
@@ -164,14 +164,14 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.StartObject(0);
-            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
             builder.EndObject();
             Assert.ArrayEqual(new byte[]
             {
                 4, 0, 4, 0,
                 4, 0, 0, 0
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -179,7 +179,7 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.StartObject(1);
-            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
             builder.AddBool(0, true, false);
             builder.EndObject();
             Assert.ArrayEqual(new byte[]
@@ -192,7 +192,7 @@ namespace FlatBuffers.Test
                 0, 0, 0, // padding
                 1, // value 0
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -200,7 +200,7 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.StartObject(1);
-            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
             builder.AddBool(0, false, false);
             builder.EndObject();
             Assert.ArrayEqual(new byte[]
@@ -211,7 +211,7 @@ namespace FlatBuffers.Test
                 // entry 0 is not stored (trimmed end of vtable)
                 4, 0, 0, 0, // int32 offset for start of vtable
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -219,7 +219,7 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.StartObject(1);
-            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
             builder.AddShort(0, 0x789A, 0);
             builder.EndObject();
             Assert.ArrayEqual(new byte[]
@@ -232,7 +232,7 @@ namespace FlatBuffers.Test
                 0, 0, // padding
                 0x9A, 0x78, //value 0
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -240,7 +240,7 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.StartObject(2);
-            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
             builder.AddShort(0, 0x3456, 0);
             builder.AddShort(1, 0x789A, 0);
             builder.EndObject();
@@ -254,7 +254,7 @@ namespace FlatBuffers.Test
                 0x9A, 0x78, // value 1
                 0x56, 0x34, // value 0
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -262,7 +262,7 @@ namespace FlatBuffers.Test
         {
             var builder = new FlatBufferBuilder(1);
             builder.StartObject(2);
-            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
             builder.AddShort(0, 0x3456, 0);
             builder.AddBool(1, true, false);
             builder.EndObject();
@@ -276,7 +276,7 @@ namespace FlatBuffers.Test
                 0, 1, // padding + value 1
                 0x56, 0x34, // value 0
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -303,7 +303,7 @@ namespace FlatBuffers.Test
                 4, 0, 0, 0,
                 0, 0, 0, 0,
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -330,7 +330,7 @@ namespace FlatBuffers.Test
                 0, 0, 55, 0, // value 0
                 0, 0, 0, 0, // length of vector (not in sctruc)
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
 
@@ -361,7 +361,7 @@ namespace FlatBuffers.Test
                 0x78, 0x56,       // vector value 0
                 0x34, 0x12,       // vector value 1
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -391,7 +391,7 @@ namespace FlatBuffers.Test
                 0x00, 0x00, 0x34, 0x12, // struct value 1
                 0x00, 0x00, 0x00, 55, // struct value 0
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -425,7 +425,7 @@ namespace FlatBuffers.Test
                 44, // vector 0, 1
                 33, // vector 0, 0
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -438,7 +438,7 @@ namespace FlatBuffers.Test
             var off = builder.EndObject();
             builder.Finish(off);
 
-            Assert.ArrayEqual(new byte[]
+            byte[] padded = new byte[]
             {
                 0, 0, 0, 0,
                 0, 0, 0, 0,
@@ -452,8 +452,13 @@ namespace FlatBuffers.Test
                 66, 0, // value 1
                 0, 33, // value 0
 
-            },
-                builder.DataBuffer.Data);
+            };
+            Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray());
+
+            // no padding in sized array
+            byte[] unpadded = new byte[padded.Length - 12];
+            Buffer.BlockCopy(padded, 12, unpadded, 0, unpadded.Length);
+            Assert.ArrayEqual(unpadded, builder.DataBuffer.ToSizedArray());
         }
 
         [FlatBuffersTestMethod]
@@ -504,7 +509,7 @@ namespace FlatBuffers.Test
                 44, // value 1, 0
                 33,
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         [FlatBuffersTestMethod]
@@ -519,7 +524,7 @@ namespace FlatBuffers.Test
             var off = builder.EndObject();
             builder.Finish(off);
 
-            Assert.ArrayEqual(new byte[]
+            byte[] padded = new byte[]
             {
                 0, 0, 0, 0,
                 0, 0, 0, 0,
@@ -546,8 +551,61 @@ namespace FlatBuffers.Test
                 1, 1, 1, 1,  // values
                 1, 1, 1, 1,
 
-            },
-                builder.DataBuffer.Data);
+            };
+            Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray());
+
+            // no padding in sized array
+            byte[] unpadded = new byte[padded.Length - 28];
+            Buffer.BlockCopy(padded, 28, unpadded, 0, unpadded.Length);
+            Assert.ArrayEqual(unpadded, builder.DataBuffer.ToSizedArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestBunchOfBoolsSizePrefixed()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartObject(8);
+            for (var i = 0; i < 8; i++)
+            {
+                builder.AddBool(i, true, false);
+            }
+            var off = builder.EndObject();
+            builder.FinishSizePrefixed(off);
+
+            byte[] padded = new byte[]
+            {
+                0, 0, 0, 0,
+                0, 0, 0, 0,
+                0, 0, 0, 0,
+                0, 0, 0, 0,
+                0, 0, 0, 0,
+                0, 0, 0, 0,      // padding to 64 bytes
+
+                36, 0, 0, 0,     // size prefix
+                24, 0, 0, 0,     // root of table, pointing to vtable offset (obj0)
+                20, 0, // vtable bytes
+                12, 0, // object length
+                11, 0, // start of value 0
+                10, 0, // start of value 1
+                9, 0, // start of value 2
+                8, 0, // start of value 3
+                7, 0, // start of value 4
+                6, 0, // start of value 5
+                5, 0, // start of value 6
+                4, 0, // start of value 7
+
+                20, 0, 0, 0, // int32 offset for start of vtable
+
+                1, 1, 1, 1,  // values
+                1, 1, 1, 1,
+
+            };
+            Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray());
+
+            // no padding in sized array
+            byte[] unpadded = new byte[padded.Length - 24];
+            Buffer.BlockCopy(padded, 24, unpadded, 0, unpadded.Length);
+            Assert.ArrayEqual(unpadded, builder.DataBuffer.ToSizedArray());
         }
 
         [FlatBuffersTestMethod]
@@ -569,7 +627,7 @@ namespace FlatBuffers.Test
                 0, 0, 128, 63,  // value
 
             },
-                builder.DataBuffer.Data);
+                builder.DataBuffer.ToFullArray());
         }
 
         private void CheckObjects(int fieldCount, int objectCount)
diff --git a/tests/FlatBuffers.Test/NetTest.sh b/tests/FlatBuffers.Test/NetTest.sh
index ea16e472..6201549c 100644
--- a/tests/FlatBuffers.Test/NetTest.sh
+++ b/tests/FlatBuffers.Test/NetTest.sh
@@ -2,8 +2,22 @@
 
 # Testing C# on Linux using Mono.
 
-mcs -out:fbnettest.exe ../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs FlatBuffersTestClassAttribute.cs FlatBuffersTestMethodAttribute.cs Assert.cs FlatBuffersExampleTests.cs Program.cs ByteBufferTests.cs FlatBufferBuilderTests.cs FlatBuffersFuzzTests.cs FuzzTestData.cs Lcg.cs TestTable.cs
-./fbnettest.exe
+mcs -debug -out:./fbnettest.exe \
+  ../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs ../MyGame/*.cs \
+  FlatBuffersTestClassAttribute.cs FlatBuffersTestMethodAttribute.cs Assert.cs FlatBuffersExampleTests.cs Program.cs ByteBufferTests.cs FlatBufferBuilderTests.cs FlatBuffersFuzzTests.cs FuzzTestData.cs Lcg.cs TestTable.cs
+mono --debug ./fbnettest.exe
 rm fbnettest.exe
 rm Resources/monsterdata_cstest.mon
+rm Resources/monsterdata_cstest_sp.mon
+
+# Repeat with unsafe versions
+
+mcs -debug -out:./fbnettest.exe \
+  -unsafe -d:UNSAFE_BYTEBUFFER \
+  ../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs ../MyGame/*.cs \
+  FlatBuffersTestClassAttribute.cs FlatBuffersTestMethodAttribute.cs Assert.cs FlatBuffersExampleTests.cs Program.cs ByteBufferTests.cs FlatBufferBuilderTests.cs FlatBuffersFuzzTests.cs FuzzTestData.cs Lcg.cs TestTable.cs
+mono --debug ./fbnettest.exe
+rm fbnettest.exe
+rm Resources/monsterdata_cstest.mon
+rm Resources/monsterdata_cstest_sp.mon
 
diff --git a/tests/JavaTest.java b/tests/JavaTest.java
index 9a5b6763..a9dedf97 100644
--- a/tests/JavaTest.java
+++ b/tests/JavaTest.java
@@ -21,6 +21,8 @@ import java.nio.channels.FileChannel;
 import MyGame.Example.*;
 import NamespaceA.*;
 import NamespaceA.NamespaceB.*;
+import com.google.flatbuffers.ByteBufferUtil;
+import static com.google.flatbuffers.Constants.*;
 import com.google.flatbuffers.FlatBufferBuilder;
 
 class JavaTest {
@@ -53,7 +55,8 @@ class JavaTest {
         // better for performance.
         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
 
-        TestBuilderBasics(fbb);
+        TestBuilderBasics(fbb, true);
+        TestBuilderBasics(fbb, false);
 
         TestExtendedBuffer(fbb.dataBuffer().asReadOnlyBuffer());
 
@@ -244,14 +247,14 @@ class JavaTest {
 
         FlatBufferBuilder fbb = new FlatBufferBuilder(1, new MappedByteBufferFactory());
 
-        TestBuilderBasics(fbb);
+        TestBuilderBasics(fbb, false);
     }
 
     static void TestSizedInputStream() {
         // Test on default FlatBufferBuilder that uses HeapByteBuffer
         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
 
-        TestBuilderBasics(fbb);
+        TestBuilderBasics(fbb, false);
 
         InputStream in = fbb.sizedInputStream();
         byte[] array = fbb.sizedByteArray();
@@ -271,7 +274,7 @@ class JavaTest {
         TestEq(count, array.length);
     }
 
-    static void TestBuilderBasics(FlatBufferBuilder fbb) {
+    static void TestBuilderBasics(FlatBufferBuilder fbb, boolean sizePrefix) {
         int[] names = {fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma")};
         int[] off = new int[3];
         Monster.startMonster(fbb);
@@ -321,7 +324,11 @@ class JavaTest {
         Monster.addTestarrayoftables(fbb, sortMons);
         int mon = Monster.endMonster(fbb);
 
-        Monster.finishMonsterBuffer(fbb, mon);
+        if (sizePrefix) {
+            Monster.finishSizePrefixedMonsterBuffer(fbb, mon);
+        } else {
+            Monster.finishMonsterBuffer(fbb, mon);
+        }
 
         // Write the result to a file for debugging purposes:
         // Note that the binaries are not necessarily identical, since the JSON
@@ -329,7 +336,8 @@ class JavaTest {
         // Java code. They are functionally equivalent though.
 
         try {
-            FileChannel fc = new FileOutputStream("monsterdata_java_wire.mon").getChannel();
+            String filename = "monsterdata_java_wire" + (sizePrefix ? "_sp" : "") + ".mon";
+            FileChannel fc = new FileOutputStream(filename).getChannel();
             fc.write(fbb.dataBuffer().duplicate());
             fc.close();
         } catch(java.io.IOException e) {
@@ -338,18 +346,24 @@ class JavaTest {
         }
 
         // Test it:
-        TestExtendedBuffer(fbb.dataBuffer());
+        ByteBuffer dataBuffer = fbb.dataBuffer();
+        if (sizePrefix) {
+            TestEq(ByteBufferUtil.getSizePrefix(dataBuffer) + SIZE_PREFIX_LENGTH,
+                   dataBuffer.remaining());
+            dataBuffer = ByteBufferUtil.removeSizePrefix(dataBuffer);
+        }
+        TestExtendedBuffer(dataBuffer);
 
         // Make sure it also works with read only ByteBuffers. This is slower,
         // since creating strings incurs an additional copy
         // (see Table.__string).
-        TestExtendedBuffer(fbb.dataBuffer().asReadOnlyBuffer());
+        TestExtendedBuffer(dataBuffer.asReadOnlyBuffer());
 
         TestEnums();
 
         //Attempt to mutate Monster fields and check whether the buffer has been mutated properly
         // revert to original values after testing
-        Monster monster = Monster.getRootAsMonster(fbb.dataBuffer());
+        Monster monster = Monster.getRootAsMonster(dataBuffer);
 
         // mana is optional and does not exist in the buffer so the mutation should fail
         // the mana field should retain its default value
diff --git a/tests/MyGame/Example/Monster.cs b/tests/MyGame/Example/Monster.cs
index c554c3cd..b7844fb3 100644
--- a/tests/MyGame/Example/Monster.cs
+++ b/tests/MyGame/Example/Monster.cs
@@ -203,6 +203,7 @@ public struct Monster : IFlatbufferObject
     return new Offset<Monster>(o);
   }
   public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset<Monster> offset) { builder.Finish(offset.Value, "MONS"); }
+  public static void FinishSizePrefixedMonsterBuffer(FlatBufferBuilder builder, Offset<Monster> offset) { builder.FinishSizePrefixed(offset.Value, "MONS"); }
 
   public static VectorOffset CreateSortedVectorOfMonster(FlatBufferBuilder builder, Offset<Monster>[] offsets) {
     Array.Sort(offsets, (Offset<Monster> o1, Offset<Monster> o2) => Table.CompareStrings(Table.__offset(10, o1.Value, builder.DataBuffer), Table.__offset(10, o2.Value, builder.DataBuffer), builder.DataBuffer));
diff --git a/tests/MyGame/Example/Monster.java b/tests/MyGame/Example/Monster.java
index 6048dc7b..8a5bb0e7 100644
--- a/tests/MyGame/Example/Monster.java
+++ b/tests/MyGame/Example/Monster.java
@@ -228,6 +228,7 @@ public final class Monster extends Table {
     return o;
   }
   public static void finishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "MONS"); }
+  public static void finishSizePrefixedMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finishSizePrefixed(offset, "MONS"); }
 
   @Override
   protected int keysCompare(Integer o1, Integer o2, ByteBuffer _bb) { return compareStrings(__offset(10, o1, _bb), __offset(10, o2, _bb), _bb); }
diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs
index 0093defa39236196ec7a5b46b46b6c25ac81c770..76057281704be584128772e75e929d6ede2867cb 100644
GIT binary patch
literal 6112
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
VbLl~AAp4u!_`R@N=EqXn{{a6@Xv+Wq

literal 6184
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

diff --git a/tests/namespace_test/namespace_test2_generated.ts b/tests/namespace_test/namespace_test2_generated.ts
index 61cf6312..aa623a87 100644
--- a/tests/namespace_test/namespace_test2_generated.ts
+++ b/tests/namespace_test/namespace_test2_generated.ts
@@ -1,6 +1,6 @@
 // automatically generated by the FlatBuffers compiler, do not modify
 
-import * as NS39599748 from "./namespace_test1_generated";
+import * as NS4989953370203581498 from "./namespace_test1_generated";
 /**
  * @constructor
  */
@@ -39,24 +39,24 @@ static getRootAsTableInFirstNS(bb:flatbuffers.ByteBuffer, obj?:TableInFirstNS):T
  * @param {NamespaceA.NamespaceB.TableInNestedNS=} obj
  * @returns {NamespaceA.NamespaceB.TableInNestedNS|null}
  */
-fooTable(obj?:NS39599748.NamespaceA.NamespaceB.TableInNestedNS):NS39599748.NamespaceA.NamespaceB.TableInNestedNS|null {
+fooTable(obj?:NS4989953370203581498.NamespaceA.NamespaceB.TableInNestedNS):NS4989953370203581498.NamespaceA.NamespaceB.TableInNestedNS|null {
   var offset = this.bb!.__offset(this.bb_pos, 4);
-  return offset ? (obj || new NS39599748.NamespaceA.NamespaceB.TableInNestedNS).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
+  return offset ? (obj || new NS4989953370203581498.NamespaceA.NamespaceB.TableInNestedNS).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
 };
 
 /**
  * @returns {NamespaceA.NamespaceB.EnumInNestedNS}
  */
-fooEnum():NS39599748.NamespaceA.NamespaceB.EnumInNestedNS {
+fooEnum():NS4989953370203581498.NamespaceA.NamespaceB.EnumInNestedNS {
   var offset = this.bb!.__offset(this.bb_pos, 6);
-  return offset ? /** @type {NamespaceA.NamespaceB.EnumInNestedNS} */ (this.bb!.readInt8(this.bb_pos + offset)) : NS39599748.NamespaceA.NamespaceB.EnumInNestedNS.A;
+  return offset ? /** @type {NamespaceA.NamespaceB.EnumInNestedNS} */ (this.bb!.readInt8(this.bb_pos + offset)) : NS4989953370203581498.NamespaceA.NamespaceB.EnumInNestedNS.A;
 };
 
 /**
  * @param {NamespaceA.NamespaceB.EnumInNestedNS} value
  * @returns {boolean}
  */
-mutate_foo_enum(value:NS39599748.NamespaceA.NamespaceB.EnumInNestedNS):boolean {
+mutate_foo_enum(value:NS4989953370203581498.NamespaceA.NamespaceB.EnumInNestedNS):boolean {
   var offset = this.bb!.__offset(this.bb_pos, 6);
 
   if (offset === 0) {
@@ -71,9 +71,9 @@ mutate_foo_enum(value:NS39599748.NamespaceA.NamespaceB.EnumInNestedNS):boolean {
  * @param {NamespaceA.NamespaceB.StructInNestedNS=} obj
  * @returns {NamespaceA.NamespaceB.StructInNestedNS|null}
  */
-fooStruct(obj?:NS39599748.NamespaceA.NamespaceB.StructInNestedNS):NS39599748.NamespaceA.NamespaceB.StructInNestedNS|null {
+fooStruct(obj?:NS4989953370203581498.NamespaceA.NamespaceB.StructInNestedNS):NS4989953370203581498.NamespaceA.NamespaceB.StructInNestedNS|null {
   var offset = this.bb!.__offset(this.bb_pos, 8);
-  return offset ? (obj || new NS39599748.NamespaceA.NamespaceB.StructInNestedNS).__init(this.bb_pos + offset, this.bb!) : null;
+  return offset ? (obj || new NS4989953370203581498.NamespaceA.NamespaceB.StructInNestedNS).__init(this.bb_pos + offset, this.bb!) : null;
 };
 
 /**
@@ -95,8 +95,8 @@ static addFooTable(builder:flatbuffers.Builder, fooTableOffset:flatbuffers.Offse
  * @param {flatbuffers.Builder} builder
  * @param {NamespaceA.NamespaceB.EnumInNestedNS} fooEnum
  */
-static addFooEnum(builder:flatbuffers.Builder, fooEnum:NS39599748.NamespaceA.NamespaceB.EnumInNestedNS) {
-  builder.addFieldInt8(1, fooEnum, NS39599748.NamespaceA.NamespaceB.EnumInNestedNS.A);
+static addFooEnum(builder:flatbuffers.Builder, fooEnum:NS4989953370203581498.NamespaceA.NamespaceB.EnumInNestedNS) {
+  builder.addFieldInt8(1, fooEnum, NS4989953370203581498.NamespaceA.NamespaceB.EnumInNestedNS.A);
 };
 
 /**
diff --git a/tests/py_test.py b/tests/py_test.py
index aeef729a..1b76b61a 100644
--- a/tests/py_test.py
+++ b/tests/py_test.py
@@ -25,6 +25,7 @@ import unittest
 
 
 from flatbuffers import compat
+from flatbuffers import util
 from flatbuffers.compat import range_func as compat_range
 from flatbuffers.compat import NumpyRequiredForThisFeature
 
@@ -56,9 +57,11 @@ def assertRaises(test_case, fn, exception_class):
 class TestWireFormat(unittest.TestCase):
     def test_wire_format(self):
         # Verify that using the generated Python code builds a buffer without
-        # returning errors, and is interpreted correctly:
-        gen_buf, gen_off = make_monster_from_generated_code()
-        CheckReadBuffer(gen_buf, gen_off)
+        # returning errors, and is interpreted correctly, for size prefixed
+        # representation and regular:
+        for sizePrefix in [True, False]:
+            gen_buf, gen_off = make_monster_from_generated_code(sizePrefix = sizePrefix)
+            CheckReadBuffer(gen_buf, gen_off, sizePrefix = sizePrefix)
 
         # Verify that the canonical flatbuffer file is readable by the
         # generated Python code. Note that context managers are not part of
@@ -74,7 +77,7 @@ class TestWireFormat(unittest.TestCase):
         f.close()
 
 
-def CheckReadBuffer(buf, offset):
+def CheckReadBuffer(buf, offset, sizePrefix = False):
     ''' CheckReadBuffer checks that the given buffer is evaluated correctly
         as the example Monster. '''
 
@@ -83,6 +86,11 @@ def CheckReadBuffer(buf, offset):
         if not stmt:
             raise AssertionError('CheckReadBuffer case failed')
 
+    if sizePrefix:
+        size = util.GetSizePrefix(buf, offset)
+        # taken from the size of monsterdata_python_wire.mon, minus 4
+        asserter(size == 348)
+        buf, offset = util.RemoveSizePrefix(buf, offset)
     monster = MyGame.Example.Monster.Monster.GetRootAsMonster(buf, offset)
 
     asserter(monster.Hp() == 80)
@@ -810,7 +818,7 @@ class TestByteLayout(unittest.TestCase):
         ])
 
 
-def make_monster_from_generated_code():
+def make_monster_from_generated_code(sizePrefix = False):
     ''' Use generated code to build the example Monster. '''
 
     b = flatbuffers.Builder(0)
@@ -871,7 +879,10 @@ def make_monster_from_generated_code():
     MyGame.Example.Monster.MonsterAddVectorOfDoubles(b, VectorOfDoubles)
     mon = MyGame.Example.Monster.MonsterEnd(b)
 
-    b.Finish(mon)
+    if sizePrefix:
+        b.FinishSizePrefixed(mon)
+    else:
+        b.Finish(mon)
 
     return b.Bytes, b.Head()
 
-- 
GitLab