* limitations under the License.
*/
-// There are 2 #defines that have an impact on performance of this ByteBuffer implementation
+// There are 3 #defines that have an impact on performance / features of this ByteBuffer implementation
//
// UNSAFE_BYTEBUFFER
// This will use unsafe code to manipulate the underlying byte array. This
// This will disable the bounds check asserts to the byte array. This can
// yield a small performance gain in normal code..
//
+// ENABLE_SPAN_T
+// This will enable reading and writing blocks of memory with a Span<T> instead if just
+// T[]. You can also enable writing directly to shared memory or other types of memory
+// by providing a custom implementation of ByteBufferAllocator.
+// ENABLE_SPAN_T also requires UNSAFE_BYTEBUFFER to be defined
+//
// Using UNSAFE_BYTEBUFFER and BYTEBUFFER_NO_BOUNDS_CHECK together can yield a
// performance gain of ~15% for some operations, however doing so is potentially
// dangerous. Do so at your own risk!
using System;
using System.Collections.Generic;
using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Text;
+#if ENABLE_SPAN_T && !UNSAFE_BYTEBUFFER
+#error ENABLE_SPAN_T requires UNSAFE_BYTEBUFFER to also be defined
+#endif
+
namespace FlatBuffers
{
+ public abstract class ByteBufferAllocator : IDisposable
+ {
+#if UNSAFE_BYTEBUFFER
+ public unsafe byte* Buffer
+ {
+ get;
+ protected set;
+ }
+#else
+ public byte[] Buffer
+ {
+ get;
+ protected set;
+ }
+#endif
+
+ public int Length
+ {
+ get;
+ protected set;
+ }
+
+ public abstract void Dispose();
+
+ public abstract void GrowFront(int newSize);
+
+#if !ENABLE_SPAN_T
+ public abstract byte[] ByteArray { get; }
+#endif
+ }
+
+ public class ByteArrayAllocator : ByteBufferAllocator
+ {
+ private byte[] _buffer;
+
+ public ByteArrayAllocator(byte[] buffer)
+ {
+ _buffer = buffer;
+ InitPointer();
+ }
+
+ public override 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];
+ System.Buffer.BlockCopy(_buffer, 0, newBuffer, newSize - Length, Length);
+ _buffer = newBuffer;
+ InitPointer();
+ }
+
+ public override void Dispose()
+ {
+ GC.SuppressFinalize(this);
+#if UNSAFE_BYTEBUFFER
+ if (_handle.IsAllocated)
+ {
+ _handle.Free();
+ }
+#endif
+ }
+
+#if !ENABLE_SPAN_T
+ public override byte[] ByteArray => _buffer;
+#endif
+
+#if UNSAFE_BYTEBUFFER
+ private GCHandle _handle;
+
+ ~ByteArrayAllocator()
+ {
+ if (_handle.IsAllocated)
+ {
+ _handle.Free();
+ }
+ }
+#endif
+
+ private void InitPointer()
+ {
+ Length = _buffer.Length;
+#if UNSAFE_BYTEBUFFER
+ if (_handle.IsAllocated)
+ {
+ _handle.Free();
+ }
+ _handle = GCHandle.Alloc(_buffer, GCHandleType.Pinned);
+ unsafe
+ {
+ Buffer = (byte*)_handle.AddrOfPinnedObject().ToPointer();
+ }
+#else
+ Buffer = _buffer;
+#endif
+ }
+ }
+
+
/// <summary>
/// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers.
/// </summary>
- public class ByteBuffer
+ public class ByteBuffer : IDisposable
{
- protected byte[] _buffer;
+ private ByteBufferAllocator _buffer;
private int _pos; // Must track start of the buffer.
- public int Length { get { return _buffer.Length; } }
+ public ByteBuffer(ByteBufferAllocator allocator, int position)
+ {
+ _buffer = allocator;
+ _pos = position;
+ }
public ByteBuffer(int size) : this(new byte[size]) { }
public ByteBuffer(byte[] buffer, int pos)
{
- _buffer = buffer;
+ _buffer = new ByteArrayAllocator(buffer);
_pos = pos;
}
+ public void Dispose()
+ {
+ if (_buffer != null)
+ {
+ _buffer.Dispose();
+ }
+ }
+
public int Position {
get { return _pos; }
set { _pos = value; }
}
+ public int Length { get { return _buffer.Length; } }
+
public void Reset()
{
_pos = 0;
// 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;
+ _buffer.GrowFront(newSize);
}
public byte[] ToArray(int pos, int len)
return SizeOf<T>() * x.Length;
}
+#if ENABLE_SPAN_T
+ public static int ArraySize<T>(Span<T> x)
+ {
+ return SizeOf<T>() * x.Length;
+ }
+#endif
+
// Get a portion of the buffer casted into an array of type T, given
// the buffer position and length.
+#if ENABLE_SPAN_T
public T[] ToArray<T>(int pos, int len)
where T: struct
{
+ unsafe
+ {
+ AssertOffsetAndLength(pos, len);
+ T[] arr = new T[len];
+ var typed = MemoryMarshal.Cast<byte, T>(new Span<byte>(_buffer.Buffer + pos, _buffer.Length));
+ typed.Slice(0, arr.Length).CopyTo(arr);
+ return arr;
+ }
+ }
+#else
+ public T[] ToArray<T>(int pos, int len)
+ where T : struct
+ {
AssertOffsetAndLength(pos, len);
T[] arr = new T[len];
- Buffer.BlockCopy(_buffer, pos, arr, 0, ArraySize(arr));
+ Buffer.BlockCopy(_buffer.ByteArray, pos, arr, 0, ArraySize(arr));
return arr;
}
+#endif
public byte[] ToSizedArray()
{
return ToArray<byte>(0, Length);
}
+
+#if ENABLE_SPAN_T
+ public unsafe Span<byte> ToSpan(int pos, int len)
+ {
+ return new Span<byte>(_buffer.Buffer, _buffer.Length).Slice(pos, len);
+ }
+#else
public ArraySegment<byte> ToArraySegment(int pos, int len)
{
- return new ArraySegment<byte>(_buffer, pos, len);
+ return new ArraySegment<byte>(_buffer.ByteArray, pos, len);
}
+#endif
+#if !ENABLE_SPAN_T
public MemoryStream ToMemoryStream(int pos, int len)
{
- return new MemoryStream(_buffer, pos, len);
+ return new MemoryStream(_buffer.ByteArray, pos, len);
}
+#endif
#if !UNSAFE_BYTEBUFFER
// Pre-allocated helper arrays for convertion.
{
for (int i = 0; i < count; i++)
{
- _buffer[offset + i] = (byte)(data >> i * 8);
+ _buffer.Buffer[offset + i] = (byte)(data >> i * 8);
}
}
else
{
for (int i = 0; i < count; i++)
{
- _buffer[offset + count - 1 - i] = (byte)(data >> i * 8);
+ _buffer.Buffer[offset + count - 1 - i] = (byte)(data >> i * 8);
}
}
}
{
for (int i = 0; i < count; i++)
{
- r |= (ulong)_buffer[offset + i] << i * 8;
+ r |= (ulong)_buffer.Buffer[offset + i] << i * 8;
}
}
else
{
for (int i = 0; i < count; i++)
{
- r |= (ulong)_buffer[offset + count - 1 - i] << i * 8;
+ r |= (ulong)_buffer.Buffer[offset + count - 1 - i] << i * 8;
}
}
return r;
private void AssertOffsetAndLength(int offset, int length)
{
- #if !BYTEBUFFER_NO_BOUNDS_CHECK
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
if (offset < 0 ||
offset > _buffer.Length - length)
throw new ArgumentOutOfRangeException();
- #endif
+#endif
+ }
+
+#if UNSAFE_BYTEBUFFER
+
+ public unsafe void PutSbyte(int offset, sbyte value)
+ {
+ AssertOffsetAndLength(offset, sizeof(sbyte));
+ _buffer.Buffer[offset] = (byte)value;
+ }
+
+ public unsafe void PutByte(int offset, byte value)
+ {
+ AssertOffsetAndLength(offset, sizeof(byte));
+ _buffer.Buffer[offset] = value;
+ }
+
+ public unsafe void PutByte(int offset, byte value, int count)
+ {
+ AssertOffsetAndLength(offset, sizeof(byte) * count);
+ for (var i = 0; i < count; ++i)
+ _buffer.Buffer[offset + i] = value;
}
+ // this method exists in order to conform with Java ByteBuffer standards
+ public void Put(int offset, byte value)
+ {
+ PutByte(offset, value);
+ }
+#else
public void PutSbyte(int offset, sbyte value)
{
AssertOffsetAndLength(offset, sizeof(sbyte));
- _buffer[offset] = (byte)value;
+ _buffer.Buffer[offset] = (byte)value;
}
public void PutByte(int offset, byte value)
{
AssertOffsetAndLength(offset, sizeof(byte));
- _buffer[offset] = value;
+ _buffer.Buffer[offset] = value;
}
public void PutByte(int offset, byte value, int count)
{
AssertOffsetAndLength(offset, sizeof(byte) * count);
for (var i = 0; i < count; ++i)
- _buffer[offset + i] = value;
+ _buffer.Buffer[offset + i] = value;
}
// this method exists in order to conform with Java ByteBuffer standards
{
PutByte(offset, value);
}
+#endif
+#if ENABLE_SPAN_T
+ public unsafe void PutStringUTF8(int offset, string value)
+ {
+ AssertOffsetAndLength(offset, value.Length);
+ fixed (char* s = value)
+ {
+ Encoding.UTF8.GetBytes(s, value.Length, _buffer.Buffer + offset, Length - offset);
+ }
+ }
+#else
public void PutStringUTF8(int offset, string value)
{
AssertOffsetAndLength(offset, value.Length);
Encoding.UTF8.GetBytes(value, 0, value.Length,
- _buffer, offset);
+ _buffer.ByteArray, offset);
}
+#endif
#if UNSAFE_BYTEBUFFER
// Unsafe but more efficient versions of Put*.
public unsafe void PutUshort(int offset, ushort value)
{
AssertOffsetAndLength(offset, sizeof(ushort));
- fixed (byte* ptr = _buffer)
- {
- *(ushort*)(ptr + offset) = BitConverter.IsLittleEndian
- ? value
- : ReverseBytes(value);
- }
+ byte* ptr = _buffer.Buffer;
+ *(ushort*)(ptr + offset) = BitConverter.IsLittleEndian
+ ? value
+ : ReverseBytes(value);
}
public void PutInt(int offset, int value)
public unsafe void PutUint(int offset, uint value)
{
AssertOffsetAndLength(offset, sizeof(uint));
- fixed (byte* ptr = _buffer)
- {
- *(uint*)(ptr + offset) = BitConverter.IsLittleEndian
- ? value
- : ReverseBytes(value);
- }
+ byte* ptr = _buffer.Buffer;
+ *(uint*)(ptr + offset) = BitConverter.IsLittleEndian
+ ? value
+ : ReverseBytes(value);
}
public unsafe void PutLong(int offset, long value)
public unsafe void PutUlong(int offset, ulong value)
{
AssertOffsetAndLength(offset, sizeof(ulong));
- fixed (byte* ptr = _buffer)
- {
- *(ulong*)(ptr + offset) = BitConverter.IsLittleEndian
- ? value
- : ReverseBytes(value);
- }
+ byte* ptr = _buffer.Buffer;
+ *(ulong*)(ptr + offset) = BitConverter.IsLittleEndian
+ ? value
+ : ReverseBytes(value);
}
public unsafe void PutFloat(int offset, float value)
{
AssertOffsetAndLength(offset, sizeof(float));
- fixed (byte* ptr = _buffer)
+ byte* ptr = _buffer.Buffer;
+ if (BitConverter.IsLittleEndian)
{
- if (BitConverter.IsLittleEndian)
- {
- *(float*)(ptr + offset) = value;
- }
- else
- {
- *(uint*)(ptr + offset) = ReverseBytes(*(uint*)(&value));
- }
+ *(float*)(ptr + offset) = value;
+ }
+ else
+ {
+ *(uint*)(ptr + offset) = ReverseBytes(*(uint*)(&value));
}
}
public unsafe void PutDouble(int offset, double value)
{
AssertOffsetAndLength(offset, sizeof(double));
- fixed (byte* ptr = _buffer)
+ byte* ptr = _buffer.Buffer;
+ if (BitConverter.IsLittleEndian)
{
- if (BitConverter.IsLittleEndian)
- {
- *(double*)(ptr + offset) = value;
+ *(double*)(ptr + offset) = value;
- }
- else
- {
- *(ulong*)(ptr + offset) = ReverseBytes(*(ulong*)(ptr + offset));
- }
+ }
+ else
+ {
+ *(ulong*)(ptr + offset) = ReverseBytes(*(ulong*)(ptr + offset));
}
}
#else // !UNSAFE_BYTEBUFFER
#endif // UNSAFE_BYTEBUFFER
- /// <summary>
- /// Copies an array of type T into this buffer, ending at the given
- /// offset into this buffer. The starting offset is calculated based on the length
- /// of the array and is the value returned.
- /// </summary>
- /// <typeparam name="T">The type of the input data (must be a struct)</typeparam>
- /// <param name="offset">The offset into this buffer where the copy will end</param>
- /// <param name="x">The array to copy data from</param>
- /// <returns>The 'start' location of this buffer now, after the copy completed</returns>
- public int Put<T>(int offset, T[] x)
- where T : struct
+#if UNSAFE_BYTEBUFFER
+ public unsafe sbyte GetSbyte(int index)
{
- if(x == null)
- {
- throw new ArgumentNullException("Cannot put a null array");
- }
-
- if(x.Length == 0)
- {
- throw new ArgumentException("Cannot put an empty array");
- }
-
- if(!IsSupportedType<T>())
- {
- throw new ArgumentException("Cannot put an array of type "
- + typeof(T) + " into this buffer");
- }
-
- if (BitConverter.IsLittleEndian)
- {
- int numBytes = ByteBuffer.ArraySize(x);
- offset -= numBytes;
- AssertOffsetAndLength(offset, numBytes);
- // if we are LE, just do a block copy
- Buffer.BlockCopy(x, 0, _buffer, offset, numBytes);
- }
- else
- {
- throw new NotImplementedException("Big Endian Support not implemented yet " +
- "for putting typed arrays");
- // if we are BE, we have to swap each element by itself
- //for(int i = x.Length - 1; i >= 0; i--)
- //{
- // todo: low priority, but need to genericize the Put<T>() functions
- //}
- }
- return offset;
+ AssertOffsetAndLength(index, sizeof(sbyte));
+ return (sbyte)_buffer.Buffer[index];
}
-
-
-
+ public unsafe byte Get(int index)
+ {
+ AssertOffsetAndLength(index, sizeof(byte));
+ return _buffer.Buffer[index];
+ }
+#else
public sbyte GetSbyte(int index)
{
AssertOffsetAndLength(index, sizeof(sbyte));
- return (sbyte)_buffer[index];
+ return (sbyte)_buffer.Buffer[index];
}
public byte Get(int index)
{
AssertOffsetAndLength(index, sizeof(byte));
- return _buffer[index];
+ return _buffer.Buffer[index];
}
+#endif
+#if ENABLE_SPAN_T
+ public unsafe string GetStringUTF8(int startPos, int len)
+ {
+ return Encoding.UTF8.GetString(_buffer.Buffer + startPos, len);
+ }
+#else
public string GetStringUTF8(int startPos, int len)
{
- return Encoding.UTF8.GetString(_buffer, startPos, len);
+ return Encoding.UTF8.GetString(_buffer.ByteArray, startPos, len);
}
+#endif
#if UNSAFE_BYTEBUFFER
// Unsafe but more efficient versions of Get*.
public unsafe ushort GetUshort(int offset)
{
AssertOffsetAndLength(offset, sizeof(ushort));
- fixed (byte* ptr = _buffer)
+ byte* ptr = _buffer.Buffer;
{
return BitConverter.IsLittleEndian
? *(ushort*)(ptr + offset)
public unsafe uint GetUint(int offset)
{
AssertOffsetAndLength(offset, sizeof(uint));
- fixed (byte* ptr = _buffer)
+ byte* ptr = _buffer.Buffer;
{
return BitConverter.IsLittleEndian
? *(uint*)(ptr + offset)
public unsafe ulong GetUlong(int offset)
{
AssertOffsetAndLength(offset, sizeof(ulong));
- fixed (byte* ptr = _buffer)
+ byte* ptr = _buffer.Buffer;
{
return BitConverter.IsLittleEndian
? *(ulong*)(ptr + offset)
public unsafe float GetFloat(int offset)
{
AssertOffsetAndLength(offset, sizeof(float));
- fixed (byte* ptr = _buffer)
+ byte* ptr = _buffer.Buffer;
{
if (BitConverter.IsLittleEndian)
{
public unsafe double GetDouble(int offset)
{
AssertOffsetAndLength(offset, sizeof(double));
- fixed (byte* ptr = _buffer)
+ byte* ptr = _buffer.Buffer;
{
if (BitConverter.IsLittleEndian)
{
return doublehelper[0];
}
#endif // UNSAFE_BYTEBUFFER
+
+ /// <summary>
+ /// Copies an array of type T into this buffer, ending at the given
+ /// offset into this buffer. The starting offset is calculated based on the length
+ /// of the array and is the value returned.
+ /// </summary>
+ /// <typeparam name="T">The type of the input data (must be a struct)</typeparam>
+ /// <param name="offset">The offset into this buffer where the copy will end</param>
+ /// <param name="x">The array to copy data from</param>
+ /// <returns>The 'start' location of this buffer now, after the copy completed</returns>
+ public int Put<T>(int offset, T[] x)
+ where T : struct
+ {
+ if (x == null)
+ {
+ throw new ArgumentNullException("Cannot put a null array");
+ }
+
+ if (x.Length == 0)
+ {
+ throw new ArgumentException("Cannot put an empty array");
+ }
+
+ if (!IsSupportedType<T>())
+ {
+ throw new ArgumentException("Cannot put an array of type "
+ + typeof(T) + " into this buffer");
+ }
+
+ if (BitConverter.IsLittleEndian)
+ {
+ int numBytes = ByteBuffer.ArraySize(x);
+ offset -= numBytes;
+ AssertOffsetAndLength(offset, numBytes);
+ // if we are LE, just do a block copy
+#if ENABLE_SPAN_T
+ unsafe
+ {
+ MemoryMarshal.Cast<T, byte>(x).CopyTo(new Span<byte>(_buffer.Buffer, _buffer.Length).Slice(offset, numBytes));
+ }
+#else
+ Buffer.BlockCopy(x, 0, _buffer.ByteArray, offset, numBytes);
+#endif
+ }
+ else
+ {
+ throw new NotImplementedException("Big Endian Support not implemented yet " +
+ "for putting typed arrays");
+ // if we are BE, we have to swap each element by itself
+ //for(int i = x.Length - 1; i >= 0; i--)
+ //{
+ // todo: low priority, but need to genericize the Put<T>() functions
+ //}
+ }
+ return offset;
+ }
+
+#if ENABLE_SPAN_T
+ public unsafe int Put<T>(int offset, Span<T> x)
+ where T : struct
+ {
+ if (x.Length == 0)
+ {
+ throw new ArgumentException("Cannot put an empty array");
+ }
+
+ if (!IsSupportedType<T>())
+ {
+ throw new ArgumentException("Cannot put an array of type "
+ + typeof(T) + " into this buffer");
+ }
+
+ if (BitConverter.IsLittleEndian)
+ {
+ int numBytes = ByteBuffer.ArraySize(x);
+ offset -= numBytes;
+ AssertOffsetAndLength(offset, numBytes);
+ // if we are LE, just do a block copy
+ MemoryMarshal.Cast<T, byte>(x).CopyTo(new Span<byte>(_buffer.Buffer, _buffer.Length).Slice(offset, numBytes));
+ }
+ else
+ {
+ throw new NotImplementedException("Big Endian Support not implemented yet " +
+ "for putting typed arrays");
+ // if we are BE, we have to swap each element by itself
+ //for(int i = x.Length - 1; i >= 0; i--)
+ //{
+ // todo: low priority, but need to genericize the Put<T>() functions
+ //}
+ }
+ return offset;
+ }
+#endif
}
}
public short Hp { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetShort(o + __p.bb_pos) : (short)100; } }
public bool MutateHp(short hp) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutShort(o + __p.bb_pos, hp); return true; } else { return false; } }
public string Name { get { int o = __p.__offset(10); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
+#if ENABLE_SPAN_T
+ public Span<byte> GetNameBytes() { return __p.__vector_as_span(10); }
+#else
public ArraySegment<byte>? GetNameBytes() { return __p.__vector_as_arraysegment(10); }
+#endif
public byte[] GetNameArray() { return __p.__vector_as_array<byte>(10); }
public byte Inventory(int j) { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
public int InventoryLength { get { int o = __p.__offset(14); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span<byte> GetInventoryBytes() { return __p.__vector_as_span(14); }
+#else
public ArraySegment<byte>? GetInventoryBytes() { return __p.__vector_as_arraysegment(14); }
+#endif
public byte[] GetInventoryArray() { return __p.__vector_as_array<byte>(14); }
public bool MutateInventory(int j, byte inventory) { int o = __p.__offset(14); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, inventory); return true; } else { return false; } }
public Color Color { get { int o = __p.__offset(16); return o != 0 ? (Color)__p.bb.GetSbyte(o + __p.bb_pos) : Color.Blue; } }
public Monster? Enemy { get { int o = __p.__offset(28); return o != 0 ? (Monster?)(new Monster()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public byte Testnestedflatbuffer(int j) { int o = __p.__offset(30); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
public int TestnestedflatbufferLength { get { int o = __p.__offset(30); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span<byte> GetTestnestedflatbufferBytes() { return __p.__vector_as_span(30); }
+#else
public ArraySegment<byte>? GetTestnestedflatbufferBytes() { return __p.__vector_as_arraysegment(30); }
+#endif
public byte[] GetTestnestedflatbufferArray() { return __p.__vector_as_array<byte>(30); }
public Monster? GetTestnestedflatbufferAsMonster() { int o = __p.__offset(30); return o != 0 ? (Monster?)(new Monster()).__assign(__p.__indirect(__p.__vector(o)), __p.bb) : null; }
public bool MutateTestnestedflatbuffer(int j, byte testnestedflatbuffer) { int o = __p.__offset(30); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, testnestedflatbuffer); return true; } else { return false; } }
public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __p.__offset(50); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, testhashu64_fnv1a); return true; } else { return false; } }
public bool Testarrayofbools(int j) { int o = __p.__offset(52); return o != 0 ? 0!=__p.bb.Get(__p.__vector(o) + j * 1) : false; }
public int TestarrayofboolsLength { get { int o = __p.__offset(52); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span<byte> GetTestarrayofboolsBytes() { return __p.__vector_as_span(52); }
+#else
public ArraySegment<byte>? GetTestarrayofboolsBytes() { return __p.__vector_as_arraysegment(52); }
+#endif
public bool[] GetTestarrayofboolsArray() { return __p.__vector_as_array<bool>(52); }
public bool MutateTestarrayofbools(int j, bool testarrayofbools) { int o = __p.__offset(52); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, (byte)(testarrayofbools ? 1 : 0)); return true; } else { return false; } }
public float Testf { get { int o = __p.__offset(54); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)3.14159f; } }
public int TestarrayofsortedstructLength { get { int o = __p.__offset(62); return o != 0 ? __p.__vector_len(o) : 0; } }
public byte Flex(int j) { int o = __p.__offset(64); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
public int FlexLength { get { int o = __p.__offset(64); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span<byte> GetFlexBytes() { return __p.__vector_as_span(64); }
+#else
public ArraySegment<byte>? GetFlexBytes() { return __p.__vector_as_arraysegment(64); }
+#endif
public byte[] GetFlexArray() { return __p.__vector_as_array<byte>(64); }
public bool MutateFlex(int j, byte flex) { int o = __p.__offset(64); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, flex); return true; } else { return false; } }
public Test? Test5(int j) { int o = __p.__offset(66); return o != 0 ? (Test?)(new Test()).__assign(__p.__vector(o) + j * 4, __p.bb) : null; }
public int Test5Length { get { int o = __p.__offset(66); return o != 0 ? __p.__vector_len(o) : 0; } }
public long VectorOfLongs(int j) { int o = __p.__offset(68); return o != 0 ? __p.bb.GetLong(__p.__vector(o) + j * 8) : (long)0; }
public int VectorOfLongsLength { get { int o = __p.__offset(68); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span<byte> GetVectorOfLongsBytes() { return __p.__vector_as_span(68); }
+#else
public ArraySegment<byte>? GetVectorOfLongsBytes() { return __p.__vector_as_arraysegment(68); }
+#endif
public long[] GetVectorOfLongsArray() { return __p.__vector_as_array<long>(68); }
public bool MutateVectorOfLongs(int j, long vector_of_longs) { int o = __p.__offset(68); if (o != 0) { __p.bb.PutLong(__p.__vector(o) + j * 8, vector_of_longs); return true; } else { return false; } }
public double VectorOfDoubles(int j) { int o = __p.__offset(70); return o != 0 ? __p.bb.GetDouble(__p.__vector(o) + j * 8) : (double)0; }
public int VectorOfDoublesLength { get { int o = __p.__offset(70); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span<byte> GetVectorOfDoublesBytes() { return __p.__vector_as_span(70); }
+#else
public ArraySegment<byte>? GetVectorOfDoublesBytes() { return __p.__vector_as_arraysegment(70); }
+#endif
public double[] GetVectorOfDoublesArray() { return __p.__vector_as_array<double>(70); }
public bool MutateVectorOfDoubles(int j, double vector_of_doubles) { int o = __p.__offset(70); if (o != 0) { __p.bb.PutDouble(__p.__vector(o) + j * 8, vector_of_doubles); return true; } else { return false; } }
public MyGame.InParentNamespace? ParentNamespaceTest { get { int o = __p.__offset(72); return o != 0 ? (MyGame.InParentNamespace?)(new MyGame.InParentNamespace()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public bool MutateSingleWeakReference(ulong single_weak_reference) { int o = __p.__offset(76); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, single_weak_reference); return true; } else { return false; } }
public ulong VectorOfWeakReferences(int j) { int o = __p.__offset(78); return o != 0 ? __p.bb.GetUlong(__p.__vector(o) + j * 8) : (ulong)0; }
public int VectorOfWeakReferencesLength { get { int o = __p.__offset(78); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span<byte> GetVectorOfWeakReferencesBytes() { return __p.__vector_as_span(78); }
+#else
public ArraySegment<byte>? GetVectorOfWeakReferencesBytes() { return __p.__vector_as_arraysegment(78); }
+#endif
public ulong[] GetVectorOfWeakReferencesArray() { return __p.__vector_as_array<ulong>(78); }
public bool MutateVectorOfWeakReferences(int j, ulong vector_of_weak_references) { int o = __p.__offset(78); if (o != 0) { __p.bb.PutUlong(__p.__vector(o) + j * 8, vector_of_weak_references); return true; } else { return false; } }
public Referrable? VectorOfStrongReferrables(int j) { int o = __p.__offset(80); return o != 0 ? (Referrable?)(new Referrable()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
public bool MutateCoOwningReference(ulong co_owning_reference) { int o = __p.__offset(82); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, co_owning_reference); return true; } else { return false; } }
public ulong VectorOfCoOwningReferences(int j) { int o = __p.__offset(84); return o != 0 ? __p.bb.GetUlong(__p.__vector(o) + j * 8) : (ulong)0; }
public int VectorOfCoOwningReferencesLength { get { int o = __p.__offset(84); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span<byte> GetVectorOfCoOwningReferencesBytes() { return __p.__vector_as_span(84); }
+#else
public ArraySegment<byte>? GetVectorOfCoOwningReferencesBytes() { return __p.__vector_as_arraysegment(84); }
+#endif
public ulong[] GetVectorOfCoOwningReferencesArray() { return __p.__vector_as_array<ulong>(84); }
public bool MutateVectorOfCoOwningReferences(int j, ulong vector_of_co_owning_references) { int o = __p.__offset(84); if (o != 0) { __p.bb.PutUlong(__p.__vector(o) + j * 8, vector_of_co_owning_references); return true; } else { return false; } }
public ulong NonOwningReference { get { int o = __p.__offset(86); return o != 0 ? __p.bb.GetUlong(o + __p.bb_pos) : (ulong)0; } }
public bool MutateNonOwningReference(ulong non_owning_reference) { int o = __p.__offset(86); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, non_owning_reference); return true; } else { return false; } }
public ulong VectorOfNonOwningReferences(int j) { int o = __p.__offset(88); return o != 0 ? __p.bb.GetUlong(__p.__vector(o) + j * 8) : (ulong)0; }
public int VectorOfNonOwningReferencesLength { get { int o = __p.__offset(88); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span<byte> GetVectorOfNonOwningReferencesBytes() { return __p.__vector_as_span(88); }
+#else
public ArraySegment<byte>? GetVectorOfNonOwningReferencesBytes() { return __p.__vector_as_arraysegment(88); }
+#endif
public ulong[] GetVectorOfNonOwningReferencesArray() { return __p.__vector_as_array<ulong>(88); }
public bool MutateVectorOfNonOwningReferences(int j, ulong vector_of_non_owning_references) { int o = __p.__offset(88); if (o != 0) { __p.bb.PutUlong(__p.__vector(o) + j * 8, vector_of_non_owning_references); return true; } else { return false; } }