diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 30e0cecdf3d..e498c102ca3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -221,6 +221,28 @@ jobs: cd tests\FlatBuffers.Test\bin\Release\net8.0 .\FlatBuffers.Test.exe + build-dotnet-linux: + name: Build .NET Linux + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: Setup .NET SDK + uses: actions/setup-dotnet@v4.2.0 + with: + dotnet-version: '10.0.x' + - name: Build + run: | + cd net/FlatSpanBuffers.Tests + dotnet new sln --force --name FlatSpanBuffers.Test + dotnet sln FlatSpanBuffers.Test.sln add FlatSpanBuffers.Tests.csproj + dotnet sln FlatSpanBuffers.Test.sln add ../FlatSpanBuffers/FlatSpanBuffers.csproj + dotnet sln FlatSpanBuffers.Test.sln add ../FlatSpanBuffers.GeneratedCode/FlatSpanBuffers.GeneratedCode.csproj + dotnet build -c Release FlatSpanBuffers.Test.sln + - name: Run net10.0 + run: | + cd net/FlatSpanBuffers.Tests/bin/Release/net10.0 + ./FlatSpanBuffers.Tests + build-mac-intel: permissions: contents: write diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bf48e6aecc..d99b2b13d54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,7 +160,10 @@ set(FlatBuffers_Compiler_SRCS src/idl_gen_binary.cpp src/idl_gen_text.cpp src/idl_gen_cpp.cpp + src/idl_gen_csharp.h src/idl_gen_csharp.cpp + src/idl_gen_csharp_spanbufs.h + src/idl_gen_csharp_spanbufs.cpp src/idl_gen_dart.cpp src/idl_gen_kotlin.cpp src/idl_gen_kotlin_kmp.cpp diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 9e58d4be95d..ad380e61f12 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -767,6 +767,7 @@ struct IDLOptions { kNim = 1 << 17, kProto = 1 << 18, kKotlinKmp = 1 << 19, + kCSharpSpanBufs = 1 << 20, kMAX }; diff --git a/net/FlatSpanBuffers.Benchmarks/FlatBufferBenchmarks.cs b/net/FlatSpanBuffers.Benchmarks/FlatBufferBenchmarks.cs new file mode 100644 index 00000000000..d695dfadef1 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/FlatBufferBenchmarks.cs @@ -0,0 +1,646 @@ +// Copyright 2014 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; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; + +// Aliases for the compared implementations. +using OriginalFlatBufferBuilder = Google.FlatBuffers.FlatBufferBuilder; +using OriginalByteBuffer = Google.FlatBuffers.ByteBuffer; +using FlatBufferBuilder = Google.FlatSpanBuffers.FlatBufferBuilder; +using ByteBuffer = Google.FlatSpanBuffers.ByteBuffer; + +using Google.FlatSpanBuffers; + +// Generated types for Google.FlatBuffers (original) +using OriginalFooBarContainer = Benchmarks.OriginalFlatBuffers.FooBarContainer; +using OriginalFooBar = Benchmarks.OriginalFlatBuffers.FooBar; +using OriginalBar = Benchmarks.OriginalFlatBuffers.Bar; +using OriginalFruit = Benchmarks.OriginalFlatBuffers.Fruit; +using OriginalSimpleMonster = Benchmarks.OriginalFlatBuffers.SimpleMonster; + +// Generated types for FlatSpanBuffers (ByteBuffer). +using FlatSpanFooBarContainer = Benchmarks.FlatSpanBuffers.FooBarContainer; +using FlatSpanFooBar = Benchmarks.FlatSpanBuffers.FooBar; +using FlatSpanBar = Benchmarks.FlatSpanBuffers.Bar; +using FlatSpanFruit = Benchmarks.FlatSpanBuffers.Fruit; +using FlatSpanSimpleMonster = Benchmarks.FlatSpanBuffers.SimpleMonster; + +// Generated types for FlatSpanBuffers StackBuffer (span/ref struct). +using StackFooBarContainer = Benchmarks.FlatSpanBuffers.StackBuffer.FooBarContainer; +using StackFooBar = Benchmarks.FlatSpanBuffers.StackBuffer.FooBar; +using StackBar = Benchmarks.FlatSpanBuffers.StackBuffer.Bar; +using StackSimpleMonster = Benchmarks.FlatSpanBuffers.StackBuffer.SimpleMonster; + +// Object API types for Google.FlatBuffers. +using OriginalFooBarContainerT = Benchmarks.OriginalFlatBuffers.FooBarContainerT; +using OriginalFooBarT = Benchmarks.OriginalFlatBuffers.FooBarT; +using OriginalBarT = Benchmarks.OriginalFlatBuffers.BarT; +using OriginalFooT = Benchmarks.OriginalFlatBuffers.FooT; + +// Object API types for FlatSpanBuffers. +using FlatSpanFooBarContainerT = Benchmarks.FlatSpanBuffers.FooBarContainerT; +using FlatSpanFooBarT = Benchmarks.FlatSpanBuffers.FooBarT; +using FlatSpanBarT = Benchmarks.FlatSpanBuffers.BarT; +using FlatSpanFooT = Benchmarks.FlatSpanBuffers.FooT; + +namespace FlatSpanBuffers.Benchmarks; + + +[MemoryDiagnoser] +[SimpleJob(RuntimeMoniker.HostProcess)] +public class EncodeBenchmarks +{ + private string[] _encodeStrings = new string[3]; + private OriginalFlatBufferBuilder _ogfbb = null; + private FlatBufferBuilder _fbb = null; + + [GlobalSetup] + public void Setup() + { + _ogfbb = new OriginalFlatBufferBuilder(512); + _fbb = new FlatBufferBuilder(512); + + for (int i = 0; i < _encodeStrings.Length; i++) + { + _encodeStrings[i] = $"FooBar{i}"; + } + } + + [Benchmark(Baseline = true)] + public void Original_FlatBuffers_Encode() + { + var builder = _ogfbb; + builder.Clear(); + + var fooBarOffsets = new Google.FlatBuffers.Offset[3]; + for (int j = 0; j < _encodeStrings.Length; j++) + { + var nameOffset = builder.CreateString(_encodeStrings[j]); + OriginalFooBar.StartFooBar(builder); + OriginalFooBar.AddSibling(builder, OriginalBar.CreateBar(builder, + (ulong)(3 + j), (short)j, (sbyte)j, (uint)(j * 10), + j * 1000, 0.5f + j, (ushort)(100 + j))); + OriginalFooBar.AddName(builder, nameOffset); + OriginalFooBar.AddRating(builder, 3.14159 + j); + OriginalFooBar.AddPostfix(builder, (byte)j); + fooBarOffsets[j] = OriginalFooBar.EndFooBar(builder); + } + + var listOffset = OriginalFooBarContainer.CreateListVector(builder, fooBarOffsets); + var locationOffset = builder.CreateString("SomeLocation"); + + OriginalFooBarContainer.StartFooBarContainer(builder); + OriginalFooBarContainer.AddList(builder, listOffset); + OriginalFooBarContainer.AddInitialized(builder, true); + OriginalFooBarContainer.AddFruit(builder, OriginalFruit.Bananas); + OriginalFooBarContainer.AddLocation(builder, locationOffset); + var rootOffset = OriginalFooBarContainer.EndFooBarContainer(builder); + OriginalFooBarContainer.FinishFooBarContainerBuffer(builder, rootOffset); + } + + [Benchmark] + public void FlatSpanBuffers_Encode() + { + var builder = _fbb; + builder.Clear(); + + Span> fooBarOffsets = stackalloc Google.FlatSpanBuffers.Offset[3]; + for (int j = 0; j < _encodeStrings.Length; j++) + { + var nameOffset = builder.CreateString(_encodeStrings[j]); + FlatSpanFooBar.StartFooBar(builder); + FlatSpanFooBar.AddSibling(builder, FlatSpanBar.CreateBar(builder, + (ulong)(3 + j), (short)j, (sbyte)j, (uint)(j * 10), + j * 1000, 0.5f + j, (ushort)(100 + j))); + FlatSpanFooBar.AddName(builder, nameOffset); + FlatSpanFooBar.AddRating(builder, 3.14159 + j); + FlatSpanFooBar.AddPostfix(builder, (byte)j); + fooBarOffsets[j] = FlatSpanFooBar.EndFooBar(builder); + } + + var listOffset = FlatSpanFooBarContainer.CreateListVectorBlock(builder, fooBarOffsets); + var locationOffset = builder.CreateString("SomeLocation"); + + FlatSpanFooBarContainer.StartFooBarContainer(builder); + FlatSpanFooBarContainer.AddList(builder, listOffset); + FlatSpanFooBarContainer.AddInitialized(builder, true); + FlatSpanFooBarContainer.AddFruit(builder, FlatSpanFruit.Bananas); + FlatSpanFooBarContainer.AddLocation(builder, locationOffset); + var rootOffset = FlatSpanFooBarContainer.EndFooBarContainer(builder); + FlatSpanFooBarContainer.FinishFooBarContainerBuffer(builder, rootOffset); + } + + [Benchmark] + public void FlatStackBuf_Encode() + { + Span buffer = stackalloc byte[512]; + Span vtableSpace = stackalloc int[16]; + Span vtableOffsetSpace = stackalloc int[16]; + var byteSpanBuffer = new ByteSpanBuffer(buffer); + var builder = new FlatSpanBufferBuilder(byteSpanBuffer, vtableSpace, vtableOffsetSpace); + + Span> fooBarOffsets = stackalloc Google.FlatSpanBuffers.Offset[3]; + for (int j = 0; j < _encodeStrings.Length; j++) + { + var nameOffset = builder.CreateString(_encodeStrings[j]); + StackFooBar.StartFooBar(ref builder); + StackFooBar.AddSibling(ref builder, StackBar.CreateBar(ref builder, + (ulong)(3 + j), (short)j, (sbyte)j, (uint)(j * 10), + j * 1000, 0.5f + j, (ushort)(100 + j))); + StackFooBar.AddName(ref builder, nameOffset); + StackFooBar.AddRating(ref builder, 3.14159 + j); + StackFooBar.AddPostfix(ref builder, (byte)j); + fooBarOffsets[j] = StackFooBar.EndFooBar(ref builder); + } + + var listOffset = StackFooBarContainer.CreateListVector(ref builder, fooBarOffsets); + var locationOffset = builder.CreateString("SomeLocation"); + + // Build FooBarContainer. + StackFooBarContainer.StartFooBarContainer(ref builder); + StackFooBarContainer.AddList(ref builder, listOffset); + StackFooBarContainer.AddInitialized(ref builder, true); + StackFooBarContainer.AddFruit(ref builder, FlatSpanFruit.Bananas); + StackFooBarContainer.AddLocation(ref builder, locationOffset); + var rootOffset = StackFooBarContainer.EndFooBarContainer(ref builder); + builder.Finish(rootOffset.Value); + } +} + +[MemoryDiagnoser] +[SimpleJob(RuntimeMoniker.HostProcess)] +public class DecodeBenchmarks +{ + private byte[] _encodedData = null!; + + [GlobalSetup] + public void Setup() + { + var builder = new OriginalFlatBufferBuilder(256); + + var fooBarOffsets = new Google.FlatBuffers.Offset[3]; + for (int j = 0; j < 3; j++) + { + var nameOffset = builder.CreateString($"FooBar{j}"); + OriginalFooBar.StartFooBar(builder); + OriginalFooBar.AddSibling(builder, OriginalBar.CreateBar(builder, + (ulong)j, (short)j, (sbyte)j, (uint)(j * 10), + j * 1000, 0.5f + j, (ushort)(100 + j))); + OriginalFooBar.AddName(builder, nameOffset); + OriginalFooBar.AddRating(builder, 3.14159 + j); + OriginalFooBar.AddPostfix(builder, (byte)j); + fooBarOffsets[j] = OriginalFooBar.EndFooBar(builder); + } + + var listOffset = OriginalFooBarContainer.CreateListVector(builder, fooBarOffsets); + var locationOffset = builder.CreateString("SomeLocation"); + + OriginalFooBarContainer.StartFooBarContainer(builder); + OriginalFooBarContainer.AddList(builder, listOffset); + OriginalFooBarContainer.AddInitialized(builder, true); + OriginalFooBarContainer.AddFruit(builder, OriginalFruit.Bananas); + OriginalFooBarContainer.AddLocation(builder, locationOffset); + var rootOffset = OriginalFooBarContainer.EndFooBarContainer(builder); + OriginalFooBarContainer.FinishFooBarContainerBuffer(builder, rootOffset); + + _encodedData = builder.SizedByteArray(); + } + + [Benchmark(Baseline = true)] + public long Original_FlatBuffers_Decode() + { + long sum = 0; + var bb = new OriginalByteBuffer(_encodedData); + var container = OriginalFooBarContainer.GetRootAsFooBarContainer(bb); + + sum += container.Initialized ? 1 : 0; + sum += (long)container.Fruit; + + var listLength = container.ListLength; + for (int j = 0; j < listLength; j++) + { + var fooBar = container.List(j); + if (fooBar.HasValue) + { + sum += (long)fooBar.Value.Rating; + sum += fooBar.Value.Postfix; + var sibling = fooBar.Value.Sibling; + if (sibling.HasValue) + { + sum += sibling.Value.Time; + sum += sibling.Value.Size; + var parent = sibling.Value.Parent; + sum += (long)parent.Id; + sum += parent.Count; + } + } + } + return sum; + } + + [Benchmark] + public long FlatSpanBuffers_Decode() + { + long sum = 0; + var bb = new ByteBuffer(_encodedData); + var container = FlatSpanFooBarContainer.GetRootAsFooBarContainer(bb); + + sum += container.Initialized ? 1 : 0; + sum += (long)container.Fruit; + + var list = container.List; + if (list.HasValue) + { + var listValue = list.Value; + for (int j = 0; j < listValue.Length; j++) + { + var fooBar = listValue[j]; + sum += (long)fooBar.Rating; + sum += fooBar.Postfix; + var sibling = fooBar.Sibling; + if (sibling.HasValue) + { + var siblingValue = sibling.Value; + sum += siblingValue.Time; + sum += siblingValue.Size; + var parent = siblingValue.Parent; + sum += (long)parent.Id; + sum += parent.Count; + } + } + } + return sum; + } + + [Benchmark] + public long FlatStackBuf_Decode() + { + long sum = 0; + var bb = new ByteSpanBuffer(_encodedData); + var container = StackFooBarContainer.GetRootAsFooBarContainer(bb); + + sum += container.Initialized ? 1 : 0; + sum += (long)container.Fruit; + + var list = container.List; + if (list.HasValue) + { + var listValue = list.Value; + for (int j = 0; j < listValue.Length; j++) + { + var fooBar = listValue[j]; + sum += (long)fooBar.Rating; + sum += fooBar.Postfix; + var sibling = fooBar.Sibling; + if (sibling.HasValue) + { + var siblingValue = sibling.Value; + sum += siblingValue.Time; + sum += siblingValue.Size; + var parent = siblingValue.Parent; + sum += (long)parent.Id; + sum += parent.Count; + } + } + } + return sum; + } +} + +[MemoryDiagnoser] +[SimpleJob(RuntimeMoniker.HostProcess)] +public class SimpleMonsterBenchmarks +{ + // Preallocating builders/buffers to remove heap allocaiton ovehead from the benchmark. + private OriginalFlatBufferBuilder _ogfbb = null!; + private FlatBufferBuilder _fbb = null; + private byte[] _spanBuffer = null!; + private int[] _vtableSpace = null!; + private int[] _vtableOffsetSpace = null!; + + [GlobalSetup] + public void Setup() + { + _ogfbb = new OriginalFlatBufferBuilder(256); + _fbb = new FlatBufferBuilder(256); + + _spanBuffer = new byte[256]; + _vtableSpace = new int[16]; + _vtableOffsetSpace = new int[16]; + } + + [Benchmark(Baseline = true)] + public void Original_FlatBuffers_BuildSimpleMonster() + { + _ogfbb.Clear(); + var nameOffset = _ogfbb.CreateString("MonsterName"); + OriginalSimpleMonster.StartSimpleMonster(_ogfbb); + OriginalSimpleMonster.AddName(_ogfbb, nameOffset); + OriginalSimpleMonster.AddHp(_ogfbb, 600); + OriginalSimpleMonster.AddMana(_ogfbb, 1024); + OriginalSimpleMonster.AddColor(_ogfbb, 2); + OriginalSimpleMonster.AddTestbool(_ogfbb, true); + OriginalSimpleMonster.AddTestf(_ogfbb, 0.3f); + OriginalSimpleMonster.AddTestf2(_ogfbb, 0.2f); + OriginalSimpleMonster.AddTestf3(_ogfbb, 0.1f); + var monsterOffset = OriginalSimpleMonster.EndSimpleMonster(_ogfbb); + _ogfbb.Finish(monsterOffset.Value); + } + + [Benchmark] + public void FlatSpanBuffers_BuildSimpleMonster() + { + _fbb.Clear(); + var nameOffset = _fbb.CreateString("MonsterName"); + FlatSpanSimpleMonster.StartSimpleMonster(_fbb); + FlatSpanSimpleMonster.AddName(_fbb, nameOffset); + FlatSpanSimpleMonster.AddHp(_fbb, 600); + FlatSpanSimpleMonster.AddMana(_fbb, 1024); + FlatSpanSimpleMonster.AddColor(_fbb, 2); + FlatSpanSimpleMonster.AddTestbool(_fbb, true); + FlatSpanSimpleMonster.AddTestf(_fbb, 0.3f); + FlatSpanSimpleMonster.AddTestf2(_fbb, 0.2f); + FlatSpanSimpleMonster.AddTestf3(_fbb, 0.1f); + var monsterOffset = FlatSpanSimpleMonster.EndSimpleMonster(_fbb); + _fbb.Finish(monsterOffset.Value); + } + + [Benchmark] + public void FlatStackBuf_BuildSimpleMonster() + { + var spanBb = new ByteSpanBuffer(_spanBuffer); + var spanFbb = new FlatSpanBufferBuilder(spanBb, _vtableSpace, _vtableOffsetSpace); + spanFbb.Clear(); + + var nameOffset = spanFbb.CreateString("MonsterName"); + StackSimpleMonster.StartSimpleMonster(ref spanFbb); + StackSimpleMonster.AddName(ref spanFbb, nameOffset); + StackSimpleMonster.AddHp(ref spanFbb, 600); + StackSimpleMonster.AddMana(ref spanFbb, 1024); + StackSimpleMonster.AddColor(ref spanFbb, 2); + StackSimpleMonster.AddTestbool(ref spanFbb, true); + StackSimpleMonster.AddTestf(ref spanFbb, 0.3f); + StackSimpleMonster.AddTestf2(ref spanFbb, 0.2f); + StackSimpleMonster.AddTestf3(ref spanFbb, 0.1f); + var monsterOffset = StackSimpleMonster.EndSimpleMonster(ref spanFbb); + spanFbb.Finish(monsterOffset.Value); + } +} + +[MemoryDiagnoser] +[SimpleJob(RuntimeMoniker.HostProcess)] +public class EncodeObjectApiBenchmarks +{ + const int ListCount = 3; + + private OriginalFlatBufferBuilder _ogfbb = null; + private FlatBufferBuilder _fbb = null; + + private OriginalFooBarContainerT _originalContainerT = null!; + private FlatSpanFooBarContainerT _flatSpanContainerT = null!; + + [GlobalSetup] + public void Setup() + { + _ogfbb = new OriginalFlatBufferBuilder(512); + _fbb = new FlatBufferBuilder(512); + + // Create Original FlatBuffers Object API container + _originalContainerT = new OriginalFooBarContainerT + { + List = new System.Collections.Generic.List(), + Initialized = true, + Fruit = OriginalFruit.Bananas, + Location = "SomeLocation" + }; + + for (int j = 0; j < ListCount; j++) + { + _originalContainerT.List.Add(new OriginalFooBarT + { + Sibling = new OriginalBarT + { + Parent = new OriginalFooT + { + Id = (ulong)(3 + j), + Count = (short)j, + Prefix = (sbyte)j, + Length = (uint)(j * 10) + }, + Time = j * 1000, + Ratio = 0.5f + j, + Size = (ushort)(100 + j) + }, + Name = $"FooBar{j}", + Rating = 3.14159 + j, + Postfix = (byte)j + }); + } + + // Create Stack FlatBuffers Object API container (same structure) + _flatSpanContainerT = new FlatSpanFooBarContainerT + { + List = new System.Collections.Generic.List(), + Initialized = true, + Fruit = FlatSpanFruit.Bananas, + Location = "SomeLocation" + }; + + for (int j = 0; j < ListCount; j++) + { + _flatSpanContainerT.List.Add(new FlatSpanFooBarT + { + Sibling = new FlatSpanBarT + { + Parent = new FlatSpanFooT + { + Id = (ulong)(3 + j), + Count = (short)j, + Prefix = (sbyte)j, + Length = (uint)(j * 10) + }, + Time = j * 1000, + Ratio = 0.5f + j, + Size = (ushort)(100 + j) + }, + Name = $"FooBar{j}", + Rating = 3.14159 + j, + Postfix = (byte)j + }); + } + } + + [Benchmark(Baseline = true)] + public void Original_FlatBuffers_ObjectApi_Encode() + { + var builder = _ogfbb; + builder.Clear(); + var offset = OriginalFooBarContainer.Pack(builder, _originalContainerT); + OriginalFooBarContainer.FinishFooBarContainerBuffer(builder, offset); + } + + [Benchmark] + public void FlatSpanBuffers_ObjectApi_Encode() + { + var builder = _fbb; + builder.Clear(); + var offset = FlatSpanFooBarContainer.Pack(builder, _flatSpanContainerT); + FlatSpanFooBarContainer.FinishFooBarContainerBuffer(builder, offset); + } + + [Benchmark] + public void FlatStackBuf_ObjectApi_Encode() + { + Span buffer = stackalloc byte[512]; + Span vtableSpace = stackalloc int[16]; + Span vtableOffsetSpace = stackalloc int[16]; + var byteSpanBuffer = new ByteSpanBuffer(buffer); + var builder = new FlatSpanBufferBuilder(byteSpanBuffer, vtableSpace, vtableOffsetSpace); + + var offset = StackFooBarContainer.Pack(ref builder, _flatSpanContainerT); + builder.Finish(offset.Value); + } +} + +[MemoryDiagnoser] +[SimpleJob(RuntimeMoniker.HostProcess)] +public class DecodeObjectApiBenchmarks +{ + private byte[] _encodedData = null!; + + [GlobalSetup] + public void Setup() + { + var builder = new OriginalFlatBufferBuilder(256); + + var fooBarOffsets = new Google.FlatBuffers.Offset[3]; + for (int j = 0; j < 3; j++) + { + var nameOffset = builder.CreateString($"FooBar{j}"); + OriginalFooBar.StartFooBar(builder); + OriginalFooBar.AddSibling(builder, OriginalBar.CreateBar(builder, + (ulong)j, (short)j, (sbyte)j, (uint)(j * 10), + j * 1000, 0.5f + j, (ushort)(100 + j))); + OriginalFooBar.AddName(builder, nameOffset); + OriginalFooBar.AddRating(builder, 3.14159 + j); + OriginalFooBar.AddPostfix(builder, (byte)j); + fooBarOffsets[j] = OriginalFooBar.EndFooBar(builder); + } + + var listOffset = OriginalFooBarContainer.CreateListVector(builder, fooBarOffsets); + var locationOffset = builder.CreateString("SomeLocation"); + + OriginalFooBarContainer.StartFooBarContainer(builder); + OriginalFooBarContainer.AddList(builder, listOffset); + OriginalFooBarContainer.AddInitialized(builder, true); + OriginalFooBarContainer.AddFruit(builder, OriginalFruit.Bananas); + OriginalFooBarContainer.AddLocation(builder, locationOffset); + var rootOffset = OriginalFooBarContainer.EndFooBarContainer(builder); + OriginalFooBarContainer.FinishFooBarContainerBuffer(builder, rootOffset); + + _encodedData = builder.SizedByteArray(); + } + + [Benchmark(Baseline = true)] + public OriginalFooBarContainerT Original_FlatBuffers_ObjectApi_Decode() + { + var bb = new OriginalByteBuffer(_encodedData); + var container = OriginalFooBarContainer.GetRootAsFooBarContainer(bb); + return container.UnPack(); + } + + [Benchmark] + public FlatSpanFooBarContainerT FlatSpanBuffers_ObjectApi_Decode() + { + var bb = new ByteBuffer(_encodedData); + var container = FlatSpanFooBarContainer.GetRootAsFooBarContainer(bb); + return container.UnPack(); + } + + [Benchmark] + public FlatSpanFooBarContainerT FlatStackBuf_ObjectApi_Decode() + { + var bb = new ByteSpanBuffer(_encodedData); + var container = StackFooBarContainer.GetRootAsFooBarContainer(bb); + return container.UnPack(); + } +} + +[MemoryDiagnoser] +[SimpleJob(RuntimeMoniker.HostProcess)] +public class VerifyBenchmarks +{ + private byte[] _encodedData = null!; + + [GlobalSetup] + public void Setup() + { + var builder = new OriginalFlatBufferBuilder(256); + + var fooBarOffsets = new Google.FlatBuffers.Offset[3]; + for (int j = 0; j < 3; j++) + { + var nameOffset = builder.CreateString($"FooBar{j}"); + OriginalFooBar.StartFooBar(builder); + OriginalFooBar.AddSibling(builder, OriginalBar.CreateBar(builder, + (ulong)j, (short)j, (sbyte)j, (uint)(j * 10), + j * 1000, 0.5f + j, (ushort)(100 + j))); + OriginalFooBar.AddName(builder, nameOffset); + OriginalFooBar.AddRating(builder, 3.14159 + j); + OriginalFooBar.AddPostfix(builder, (byte)j); + fooBarOffsets[j] = OriginalFooBar.EndFooBar(builder); + } + + var listOffset = OriginalFooBarContainer.CreateListVector(builder, fooBarOffsets); + var locationOffset = builder.CreateString("SomeLocation"); + + OriginalFooBarContainer.StartFooBarContainer(builder); + OriginalFooBarContainer.AddList(builder, listOffset); + OriginalFooBarContainer.AddInitialized(builder, true); + OriginalFooBarContainer.AddFruit(builder, OriginalFruit.Bananas); + OriginalFooBarContainer.AddLocation(builder, locationOffset); + var rootOffset = OriginalFooBarContainer.EndFooBarContainer(builder); + OriginalFooBarContainer.FinishFooBarContainerBuffer(builder, rootOffset); + + _encodedData = builder.SizedByteArray(); + } + + [Benchmark(Baseline = true)] + public bool Original_FlatBuffers_Verify() + { + var bb = new OriginalByteBuffer(_encodedData); + // Work around original Google.FlatBuffers.Verifier.CheckBufferFromStart + // where empty string identifier causes ArgumentException in BufferHasIdentifier. + var verifier = new Google.FlatBuffers.Verifier(bb); + return verifier.VerifyBuffer(null, false, + global::Benchmarks.OriginalFlatBuffers.FooBarContainerVerify.Verify); + } + + // this bench function is only here for consistency... ByteBuffer is converted into ByteSpanBuffer then verification runs. + [Benchmark] + public bool FlatSpanBuffers_Verify() + { + var bb = new ByteBuffer(_encodedData); + return FlatSpanFooBarContainer.VerifyFooBarContainer(bb); + } + + [Benchmark] + public bool FlatStackBuf_Verify() + { + var bb = new ByteSpanBuffer(_encodedData); + return StackFooBarContainer.VerifyFooBarContainer(bb); + } +} diff --git a/net/FlatSpanBuffers.Benchmarks/FlatSpanBuffers.Benchmarks.csproj b/net/FlatSpanBuffers.Benchmarks/FlatSpanBuffers.Benchmarks.csproj new file mode 100644 index 00000000000..236c91b3f1b --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/FlatSpanBuffers.Benchmarks.csproj @@ -0,0 +1,30 @@ + + + + Exe + net10.0 + $(DefineConstants);ENABLE_SPAN_T;UNSAFE_BYTEBUFFER + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/Bar.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/Bar.cs new file mode 100644 index 00000000000..d4a61c2035e --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/Bar.cs @@ -0,0 +1,91 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Bar : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Bar __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public Benchmarks.FlatSpanBuffers.Foo Parent { get { return (new Benchmarks.FlatSpanBuffers.Foo()).__assign(__p.bb_pos + 0, __p.bb); } } + public int Time { get { return __p.bb.Get(__p.bb_pos + 16); } } + public void MutateTime(int time) { __p.bb.Put(__p.bb_pos + 16, time); } + public float Ratio { get { return __p.bb.Get(__p.bb_pos + 20); } } + public void MutateRatio(float ratio) { __p.bb.Put(__p.bb_pos + 20, ratio); } + public ushort Size { get { return __p.bb.Get(__p.bb_pos + 24); } } + public void MutateSize(ushort size) { __p.bb.Put(__p.bb_pos + 24, size); } + + public static Offset CreateBar(FlatBufferBuilder builder, ulong parent_Id, short parent_Count, sbyte parent_Prefix, uint parent_Length, int Time, float Ratio, ushort Size) { + builder.Prep(8, 32); + builder.Pad(6); + builder.Put(Size); + builder.Put(Ratio); + builder.Put(Time); + builder.Prep(8, 16); + builder.Put(parent_Length); + builder.Pad(1); + builder.Put(parent_Prefix); + builder.Put(parent_Count); + builder.Put(parent_Id); + return new Offset(builder.Offset); + } + public BarT UnPack() { + var _o = new BarT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(BarT _o) { + if (_o.Parent == null) _o.Parent = new Benchmarks.FlatSpanBuffers.FooT(); + this.Parent.UnPackTo(_o.Parent); + _o.Time = this.Time; + _o.Ratio = this.Ratio; + _o.Size = this.Size; + } + public static Offset Pack(FlatBufferBuilder builder, BarT _o) { + if (_o == null) return default(Offset); + var _parent_id = _o.Parent.Id; + var _parent_count = _o.Parent.Count; + var _parent_prefix = _o.Parent.Prefix; + var _parent_length = _o.Parent.Length; + return CreateBar( + builder, + _parent_id, + _parent_count, + _parent_prefix, + _parent_length, + _o.Time, + _o.Ratio, + _o.Size); + } +} + +public class BarT +{ + public Benchmarks.FlatSpanBuffers.FooT Parent { get; set; } + public int Time { get; set; } + public float Ratio { get; set; } + public ushort Size { get; set; } + + public BarT() { + this.Parent = new Benchmarks.FlatSpanBuffers.FooT(); + this.Time = 0; + this.Ratio = 0.0f; + this.Size = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/Foo.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/Foo.cs new file mode 100644 index 00000000000..254d5ebca07 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/Foo.cs @@ -0,0 +1,79 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Foo : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Foo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ulong Id { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateId(ulong id) { __p.bb.Put(__p.bb_pos + 0, id); } + public short Count { get { return __p.bb.Get(__p.bb_pos + 8); } } + public void MutateCount(short count) { __p.bb.Put(__p.bb_pos + 8, count); } + public sbyte Prefix { get { return __p.bb.Get(__p.bb_pos + 10); } } + public void MutatePrefix(sbyte prefix) { __p.bb.Put(__p.bb_pos + 10, prefix); } + public uint Length { get { return __p.bb.Get(__p.bb_pos + 12); } } + public void MutateLength(uint length) { __p.bb.Put(__p.bb_pos + 12, length); } + + public static Offset CreateFoo(FlatBufferBuilder builder, ulong Id, short Count, sbyte Prefix, uint Length) { + builder.Prep(8, 16); + builder.Put(Length); + builder.Pad(1); + builder.Put(Prefix); + builder.Put(Count); + builder.Put(Id); + return new Offset(builder.Offset); + } + public FooT UnPack() { + var _o = new FooT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FooT _o) { + _o.Id = this.Id; + _o.Count = this.Count; + _o.Prefix = this.Prefix; + _o.Length = this.Length; + } + public static Offset Pack(FlatBufferBuilder builder, FooT _o) { + if (_o == null) return default(Offset); + return CreateFoo( + builder, + _o.Id, + _o.Count, + _o.Prefix, + _o.Length); + } +} + +public class FooT +{ + public ulong Id { get; set; } + public short Count { get; set; } + public sbyte Prefix { get; set; } + public uint Length { get; set; } + + public FooT() { + this.Id = 0; + this.Count = 0; + this.Prefix = 0; + this.Length = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/FooBar.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/FooBar.cs new file mode 100644 index 00000000000..27a59152e9d --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/FooBar.cs @@ -0,0 +1,114 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct FooBar : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static FooBar GetRootAsFooBar(ByteBuffer _bb) { return GetRootAsFooBar(_bb, new FooBar()); } + public static FooBar GetRootAsFooBar(ByteBuffer _bb, FooBar obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public FooBar __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public Benchmarks.FlatSpanBuffers.Bar? Sibling { get { int o = __p.__offset(4); return o != 0 ? (Benchmarks.FlatSpanBuffers.Bar?)(new Benchmarks.FlatSpanBuffers.Bar()).__assign(o + __p.bb_pos, __p.bb) : null; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(6); } + public RefStructNullable> MutableName { get { int o = __p.__offset(6); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(6)) : default; } } + public double Rating { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double)0.0; } } + public bool MutateRating(double rating) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(o + __p.bb_pos, rating); return true; } else { return false; } } + public byte Postfix { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)0; } } + public bool MutatePostfix(byte postfix) { int o = __p.__offset(10); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, postfix); return true; } else { return false; } } + + public static Offset CreateFooBar(FlatBufferBuilder builder, + Benchmarks.FlatSpanBuffers.BarT sibling = null, + StringOffset nameOffset = default(StringOffset), + double rating = 0.0, + byte postfix = 0) { + builder.StartTable(4); + FooBar.AddRating(builder, rating); + FooBar.AddName(builder, nameOffset); + FooBar.AddSibling(builder, Benchmarks.FlatSpanBuffers.Bar.Pack(builder, sibling)); + FooBar.AddPostfix(builder, postfix); + return FooBar.EndFooBar(builder); + } + + public static void StartFooBar(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddSibling(FlatBufferBuilder builder, Offset siblingOffset) { builder.AddStruct(0, siblingOffset, 0); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset, 0); } + public static void AddRating(FlatBufferBuilder builder, double rating) { builder.Add(2, rating, 0.0); } + public static void AddPostfix(FlatBufferBuilder builder, byte postfix) { builder.Add(3, postfix, 0); } + public static Offset EndFooBar(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public FooBarT UnPack() { + var _o = new FooBarT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FooBarT _o) { + if (this.Sibling.HasValue) { + if (_o.Sibling == null) _o.Sibling = new Benchmarks.FlatSpanBuffers.BarT(); + this.Sibling.Value.UnPackTo(_o.Sibling); + } else { + _o.Sibling = null; + } + _o.Name = this.Name; + _o.Rating = this.Rating; + _o.Postfix = this.Postfix; + } + public static Offset Pack(FlatBufferBuilder builder, FooBarT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateFooBar( + builder, + _o.Sibling, + _name, + _o.Rating, + _o.Postfix); + } +} + +public class FooBarT +{ + public Benchmarks.FlatSpanBuffers.BarT Sibling { get; set; } + public string Name { get; set; } + public double Rating { get; set; } + public byte Postfix { get; set; } + + public FooBarT() { + this.Sibling = new Benchmarks.FlatSpanBuffers.BarT(); + this.Name = null; + this.Rating = 0.0; + this.Postfix = 0; + } +} + + +static public class FooBarVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Sibling*/, 32 /*Benchmarks.FlatSpanBuffers.Bar*/, 8, false) + && verifier.VerifyString(tablePos, 6 /*Name*/, false) + && verifier.VerifyField(tablePos, 8 /*Rating*/, 8 /*double*/, 8, false) + && verifier.VerifyField(tablePos, 10 /*Postfix*/, 1 /*byte*/, 1, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/FooBarContainer.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/FooBarContainer.cs new file mode 100644 index 00000000000..07328560549 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/FooBarContainer.cs @@ -0,0 +1,150 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct FooBarContainer : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static FooBarContainer GetRootAsFooBarContainer(ByteBuffer _bb) { return GetRootAsFooBarContainer(_bb, new FooBarContainer()); } + public static FooBarContainer GetRootAsFooBarContainer(ByteBuffer _bb, FooBarContainer obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool VerifyFooBarContainer(ByteBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, Benchmarks.FlatSpanBuffers.FooBarContainerVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public FooBarContainer __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public TableVector? List { get { int o = __p.__offset(4); return o != 0 ? new TableVector(__p, o, 4) : null; } } + public bool Initialized { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public bool MutateInitialized(bool initialized) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, (byte)(initialized ? 1 : 0)); return true; } else { return false; } } + public Benchmarks.FlatSpanBuffers.Fruit Fruit { get { int o = __p.__offset(8); return o != 0 ? (Benchmarks.FlatSpanBuffers.Fruit)__p.bb.Get(o + __p.bb_pos) : Benchmarks.FlatSpanBuffers.Fruit.Apples; } } + public bool MutateFruit(Benchmarks.FlatSpanBuffers.Fruit fruit) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (short)fruit); return true; } else { return false; } } + public string Location { get { int o = __p.__offset(10); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetLocationBytes() { return __p.__vector_as_span(10); } + public RefStructNullable> MutableLocation { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(10)) : default; } } + + public static Offset CreateFooBarContainer(FlatBufferBuilder builder, + VectorOffset listOffset = default(VectorOffset), + bool initialized = false, + Benchmarks.FlatSpanBuffers.Fruit fruit = Benchmarks.FlatSpanBuffers.Fruit.Apples, + StringOffset locationOffset = default(StringOffset)) { + builder.StartTable(4); + FooBarContainer.AddLocation(builder, locationOffset); + FooBarContainer.AddList(builder, listOffset); + FooBarContainer.AddFruit(builder, fruit); + FooBarContainer.AddInitialized(builder, initialized); + return FooBarContainer.EndFooBarContainer(builder); + } + + public static void StartFooBarContainer(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddList(FlatBufferBuilder builder, VectorOffset listOffset) { builder.AddOffset(0, listOffset, 0); } + public static VectorOffset CreateListVectorBlock(FlatBufferBuilder builder, Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateListVector(FlatBufferBuilder builder, Span> data) { return CreateListVectorBlock(builder, data); } + public static void StartListVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddInitialized(FlatBufferBuilder builder, bool initialized) { builder.Add(1, initialized, false); } + public static void AddFruit(FlatBufferBuilder builder, Benchmarks.FlatSpanBuffers.Fruit fruit) { builder.Add(2, (short)fruit, 0); } + public static void AddLocation(FlatBufferBuilder builder, StringOffset locationOffset) { builder.AddOffset(3, locationOffset, 0); } + public static Offset EndFooBarContainer(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishFooBarContainerBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedFooBarContainerBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + public FooBarContainerT UnPack() { + var _o = new FooBarContainerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FooBarContainerT _o) { + var _list_vec = this.List; + var _list_len = _list_vec.HasValue ? _list_vec.Value.Length : 0; + if (_o.List == null) { + _o.List = new List(_list_len); + } + ObjectApiUtil.ResizeList(_o.List, _list_len); + if (_list_vec.HasValue) { + var _list_value = _list_vec.Value; + for (var _j = 0; _j < _list_len; ++_j) { + var _src = _list_value[_j]; + if (_o.List[_j] == null) { _o.List[_j] = new FooBarT(); } + _src.UnPackTo(_o.List[_j]); + } + } + _o.Initialized = this.Initialized; + _o.Fruit = this.Fruit; + _o.Location = this.Location; + } + public static Offset Pack(FlatBufferBuilder builder, FooBarContainerT _o) { + if (_o == null) return default(Offset); + var _list = default(VectorOffset); + if (_o.List != null) { + var _list_len = _o.List.Count; + Offset[] _list_arr = null; + try { + Span> __list = _list_len <= 64 + ? stackalloc Offset[_list_len] + : (_list_arr = ArrayPool>.Shared.Rent(_list_len)).AsSpan(0, _list_len); + for (var _j = 0; _j < _list_len; ++_j) { __list[_j] = Benchmarks.FlatSpanBuffers.FooBar.Pack(builder, _o.List[_j]); } + _list = CreateListVector(builder, __list); + } finally { + if (_list_arr != null) { ArrayPool>.Shared.Return(_list_arr); } + } + } + var _location = _o.Location == null ? default(StringOffset) : builder.CreateString(_o.Location); + return CreateFooBarContainer( + builder, + _list, + _o.Initialized, + _o.Fruit, + _location); + } +} + +public class FooBarContainerT +{ + public List List { get; set; } + public bool Initialized { get; set; } + public Benchmarks.FlatSpanBuffers.Fruit Fruit { get; set; } + public string Location { get; set; } + + public FooBarContainerT() { + this.List = null; + this.Initialized = false; + this.Fruit = Benchmarks.FlatSpanBuffers.Fruit.Apples; + this.Location = null; + } + public static FooBarContainerT DeserializeFromBinary(byte[] fbBuffer) { + return FooBarContainer.GetRootAsFooBarContainer(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + FooBarContainer.FinishFooBarContainerBuffer(fbb, FooBarContainer.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedSpan().ToArray(); + } +} + + +static public class FooBarContainerVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyVectorOfTables(tablePos, 4 /*List*/, Benchmarks.FlatSpanBuffers.FooBarVerify.Verify, false) + && verifier.VerifyField(tablePos, 6 /*Initialized*/, 1 /*bool*/, 1, false) + && verifier.VerifyField(tablePos, 8 /*Fruit*/, 2 /*Benchmarks.FlatSpanBuffers.Fruit*/, 2, false) + && verifier.VerifyString(tablePos, 10 /*Location*/, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/Fruit.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/Fruit.cs new file mode 100644 index 00000000000..d05f28bf655 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/Fruit.cs @@ -0,0 +1,16 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers +{ + +public enum Fruit : short +{ + Apples = 0, + Pears = 1, + Bananas = 2, +}; + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/SimpleMonster.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/SimpleMonster.cs new file mode 100644 index 00000000000..a76655068a5 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/SimpleMonster.cs @@ -0,0 +1,150 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct SimpleMonster : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static SimpleMonster GetRootAsSimpleMonster(ByteBuffer _bb) { return GetRootAsSimpleMonster(_bb, new SimpleMonster()); } + public static SimpleMonster GetRootAsSimpleMonster(ByteBuffer _bb, SimpleMonster obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public SimpleMonster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public RefStructNullable> MutableName { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(4)) : default; } } + public short Hp { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)100; } } + public bool MutateHp(short hp) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, hp); return true; } else { return false; } } + public short Mana { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)150; } } + public bool MutateMana(short mana) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(o + __p.bb_pos, mana); return true; } else { return false; } } + public byte Color { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)2; } } + public bool MutateColor(byte color) { int o = __p.__offset(10); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, color); return true; } else { return false; } } + public bool Testbool { get { int o = __p.__offset(12); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public bool MutateTestbool(bool testbool) { int o = __p.__offset(12); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } } + public float Testf { get { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)3.14159f; } } + public bool MutateTestf(float testf) { int o = __p.__offset(14); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf); return true; } else { return false; } } + public float Testf2 { get { int o = __p.__offset(16); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)3.0f; } } + public bool MutateTestf2(float testf2) { int o = __p.__offset(16); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf2); return true; } else { return false; } } + public float Testf3 { get { int o = __p.__offset(18); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)0.0f; } } + public bool MutateTestf3(float testf3) { int o = __p.__offset(18); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf3); return true; } else { return false; } } + + public static Offset CreateSimpleMonster(FlatBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + short hp = 100, + short mana = 150, + byte color = 2, + bool testbool = false, + float testf = 3.14159f, + float testf2 = 3.0f, + float testf3 = 0.0f) { + builder.StartTable(8); + SimpleMonster.AddTestf3(builder, testf3); + SimpleMonster.AddTestf2(builder, testf2); + SimpleMonster.AddTestf(builder, testf); + SimpleMonster.AddName(builder, nameOffset); + SimpleMonster.AddMana(builder, mana); + SimpleMonster.AddHp(builder, hp); + SimpleMonster.AddTestbool(builder, testbool); + SimpleMonster.AddColor(builder, color); + return SimpleMonster.EndSimpleMonster(builder); + } + + public static void StartSimpleMonster(FlatBufferBuilder builder) { builder.StartTable(8); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddHp(FlatBufferBuilder builder, short hp) { builder.Add(1, hp, 100); } + public static void AddMana(FlatBufferBuilder builder, short mana) { builder.Add(2, mana, 150); } + public static void AddColor(FlatBufferBuilder builder, byte color) { builder.Add(3, color, 2); } + public static void AddTestbool(FlatBufferBuilder builder, bool testbool) { builder.Add(4, testbool, false); } + public static void AddTestf(FlatBufferBuilder builder, float testf) { builder.Add(5, testf, 3.14159f); } + public static void AddTestf2(FlatBufferBuilder builder, float testf2) { builder.Add(6, testf2, 3.0f); } + public static void AddTestf3(FlatBufferBuilder builder, float testf3) { builder.Add(7, testf3, 0.0f); } + public static Offset EndSimpleMonster(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public SimpleMonsterT UnPack() { + var _o = new SimpleMonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(SimpleMonsterT _o) { + _o.Name = this.Name; + _o.Hp = this.Hp; + _o.Mana = this.Mana; + _o.Color = this.Color; + _o.Testbool = this.Testbool; + _o.Testf = this.Testf; + _o.Testf2 = this.Testf2; + _o.Testf3 = this.Testf3; + } + public static Offset Pack(FlatBufferBuilder builder, SimpleMonsterT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateSimpleMonster( + builder, + _name, + _o.Hp, + _o.Mana, + _o.Color, + _o.Testbool, + _o.Testf, + _o.Testf2, + _o.Testf3); + } +} + +public class SimpleMonsterT +{ + public string Name { get; set; } + public short Hp { get; set; } + public short Mana { get; set; } + public byte Color { get; set; } + public bool Testbool { get; set; } + public float Testf { get; set; } + public float Testf2 { get; set; } + public float Testf3 { get; set; } + + public SimpleMonsterT() { + this.Name = null; + this.Hp = 100; + this.Mana = 150; + this.Color = 2; + this.Testbool = false; + this.Testf = 3.14159f; + this.Testf2 = 3.0f; + this.Testf3 = 0.0f; + } +} + + +static public class SimpleMonsterVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*Name*/, false) + && verifier.VerifyField(tablePos, 6 /*Hp*/, 2 /*short*/, 2, false) + && verifier.VerifyField(tablePos, 8 /*Mana*/, 2 /*short*/, 2, false) + && verifier.VerifyField(tablePos, 10 /*Color*/, 1 /*byte*/, 1, false) + && verifier.VerifyField(tablePos, 12 /*Testbool*/, 1 /*bool*/, 1, false) + && verifier.VerifyField(tablePos, 14 /*Testf*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 16 /*Testf2*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 18 /*Testf3*/, 4 /*float*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/Bar.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/Bar.cs new file mode 100644 index 00000000000..3c830283928 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/Bar.cs @@ -0,0 +1,76 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Bar : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Bar __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public Benchmarks.FlatSpanBuffers.StackBuffer.Foo Parent { get { return (new Benchmarks.FlatSpanBuffers.StackBuffer.Foo()).__assign(__p.bb_pos + 0, __p.bb); } } + public int Time { get { return __p.bb.Get(__p.bb_pos + 16); } } + public void MutateTime(int time) { __p.bb.Put(__p.bb_pos + 16, time); } + public float Ratio { get { return __p.bb.Get(__p.bb_pos + 20); } } + public void MutateRatio(float ratio) { __p.bb.Put(__p.bb_pos + 20, ratio); } + public ushort Size { get { return __p.bb.Get(__p.bb_pos + 24); } } + public void MutateSize(ushort size) { __p.bb.Put(__p.bb_pos + 24, size); } + + public static Offset CreateBar(ref FlatSpanBufferBuilder builder, ulong parent_Id, short parent_Count, sbyte parent_Prefix, uint parent_Length, int Time, float Ratio, ushort Size) { + builder.Prep(8, 32); + builder.Pad(6); + builder.Put(Size); + builder.Put(Ratio); + builder.Put(Time); + builder.Prep(8, 16); + builder.Put(parent_Length); + builder.Pad(1); + builder.Put(parent_Prefix); + builder.Put(parent_Count); + builder.Put(parent_Id); + return new Offset(builder.Offset); + } + public BarT UnPack() { + var _o = new BarT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(BarT _o) { + if (_o.Parent == null) _o.Parent = new Benchmarks.FlatSpanBuffers.FooT(); + this.Parent.UnPackTo(_o.Parent); + _o.Time = this.Time; + _o.Ratio = this.Ratio; + _o.Size = this.Size; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, BarT _o) { + if (_o == null) return default(Offset); + var _parent_id = _o.Parent.Id; + var _parent_count = _o.Parent.Count; + var _parent_prefix = _o.Parent.Prefix; + var _parent_length = _o.Parent.Length; + return CreateBar( + ref builder, + _parent_id, + _parent_count, + _parent_prefix, + _parent_length, + _o.Time, + _o.Ratio, + _o.Size); + } +} + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/Foo.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/Foo.cs new file mode 100644 index 00000000000..6d9e8bc572c --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/Foo.cs @@ -0,0 +1,64 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Foo : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Foo __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public ulong Id { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateId(ulong id) { __p.bb.Put(__p.bb_pos + 0, id); } + public short Count { get { return __p.bb.Get(__p.bb_pos + 8); } } + public void MutateCount(short count) { __p.bb.Put(__p.bb_pos + 8, count); } + public sbyte Prefix { get { return __p.bb.Get(__p.bb_pos + 10); } } + public void MutatePrefix(sbyte prefix) { __p.bb.Put(__p.bb_pos + 10, prefix); } + public uint Length { get { return __p.bb.Get(__p.bb_pos + 12); } } + public void MutateLength(uint length) { __p.bb.Put(__p.bb_pos + 12, length); } + + public static Offset CreateFoo(ref FlatSpanBufferBuilder builder, ulong Id, short Count, sbyte Prefix, uint Length) { + builder.Prep(8, 16); + builder.Put(Length); + builder.Pad(1); + builder.Put(Prefix); + builder.Put(Count); + builder.Put(Id); + return new Offset(builder.Offset); + } + public FooT UnPack() { + var _o = new FooT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FooT _o) { + _o.Id = this.Id; + _o.Count = this.Count; + _o.Prefix = this.Prefix; + _o.Length = this.Length; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, FooT _o) { + if (_o == null) return default(Offset); + return CreateFoo( + ref builder, + _o.Id, + _o.Count, + _o.Prefix, + _o.Length); + } +} + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/FooBar.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/FooBar.cs new file mode 100644 index 00000000000..072461fa0cf --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/FooBar.cs @@ -0,0 +1,73 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct FooBar : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static FooBar GetRootAsFooBar(ByteSpanBuffer _bb) { return GetRootAsFooBar(_bb, new FooBar()); } + public static FooBar GetRootAsFooBar(ByteSpanBuffer _bb, FooBar obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public FooBar __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public RefStructNullable Sibling { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable((new Benchmarks.FlatSpanBuffers.StackBuffer.Bar()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(6); } + public RefStructNullable> MutableName { get { int o = __p.__offset(6); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(6)) : default; } } + public double Rating { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double)0.0; } } + public bool MutateRating(double rating) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(o + __p.bb_pos, rating); return true; } else { return false; } } + public byte Postfix { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)0; } } + public bool MutatePostfix(byte postfix) { int o = __p.__offset(10); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, postfix); return true; } else { return false; } } + + public static void StartFooBar(ref FlatSpanBufferBuilder builder) { builder.StartTable(4); } + public static void AddSibling(ref FlatSpanBufferBuilder builder, Offset siblingOffset) { builder.AddStruct(0, siblingOffset, 0); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset, 0); } + public static void AddRating(ref FlatSpanBufferBuilder builder, double rating) { builder.Add(2, rating, 0.0); } + public static void AddPostfix(ref FlatSpanBufferBuilder builder, byte postfix) { builder.Add(3, postfix, 0); } + public static Offset EndFooBar(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public FooBarT UnPack() { + var _o = new FooBarT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FooBarT _o) { + if (this.Sibling.HasValue) { + if (_o.Sibling == null) _o.Sibling = new Benchmarks.FlatSpanBuffers.BarT(); + this.Sibling.Value.UnPackTo(_o.Sibling); + } else { + _o.Sibling = null; + } + _o.Name = this.Name; + _o.Rating = this.Rating; + _o.Postfix = this.Postfix; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, FooBarT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + StartFooBar(ref builder); + AddSibling(ref builder, Benchmarks.FlatSpanBuffers.StackBuffer.Bar.Pack(ref builder, _o.Sibling)); + AddName(ref builder, _name); + AddRating(ref builder, _o.Rating); + AddPostfix(ref builder, _o.Postfix); + return EndFooBar(ref builder); + } +} + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/FooBarContainer.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/FooBarContainer.cs new file mode 100644 index 00000000000..42ac0627c3c --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/FooBarContainer.cs @@ -0,0 +1,114 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct FooBarContainer : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static FooBarContainer GetRootAsFooBarContainer(ByteSpanBuffer _bb) { return GetRootAsFooBarContainer(_bb, new FooBarContainer()); } + public static FooBarContainer GetRootAsFooBarContainer(ByteSpanBuffer _bb, FooBarContainer obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool VerifyFooBarContainer(ByteSpanBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, Benchmarks.FlatSpanBuffers.FooBarContainerVerify.Verify); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public FooBarContainer __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public RefStructNullable> List { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(new TableVectorSpan(__p, o, 4)) : default; } } + public bool Initialized { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public bool MutateInitialized(bool initialized) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, (byte)(initialized ? 1 : 0)); return true; } else { return false; } } + public Benchmarks.FlatSpanBuffers.Fruit Fruit { get { int o = __p.__offset(8); return o != 0 ? (Benchmarks.FlatSpanBuffers.Fruit)__p.bb.Get(o + __p.bb_pos) : Benchmarks.FlatSpanBuffers.Fruit.Apples; } } + public bool MutateFruit(Benchmarks.FlatSpanBuffers.Fruit fruit) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (short)fruit); return true; } else { return false; } } + public string Location { get { int o = __p.__offset(10); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetLocationBytes() { return __p.__vector_as_span(10); } + public RefStructNullable> MutableLocation { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(10)) : default; } } + + public static Offset CreateFooBarContainer(ref FlatSpanBufferBuilder builder, + VectorOffset listOffset = default(VectorOffset), + bool initialized = false, + Benchmarks.FlatSpanBuffers.Fruit fruit = Benchmarks.FlatSpanBuffers.Fruit.Apples, + StringOffset locationOffset = default(StringOffset)) { + builder.StartTable(4); + FooBarContainer.AddLocation(ref builder, locationOffset); + FooBarContainer.AddList(ref builder, listOffset); + FooBarContainer.AddFruit(ref builder, fruit); + FooBarContainer.AddInitialized(ref builder, initialized); + return FooBarContainer.EndFooBarContainer(ref builder); + } + + public static void StartFooBarContainer(ref FlatSpanBufferBuilder builder) { builder.StartTable(4); } + public static void AddList(ref FlatSpanBufferBuilder builder, VectorOffset listOffset) { builder.AddOffset(0, listOffset, 0); } + public static VectorOffset CreateListVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateListVector(ref FlatSpanBufferBuilder builder, scoped Span> data) { return CreateListVectorBlock(ref builder, data); } + public static void StartListVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddInitialized(ref FlatSpanBufferBuilder builder, bool initialized) { builder.Add(1, initialized, false); } + public static void AddFruit(ref FlatSpanBufferBuilder builder, Benchmarks.FlatSpanBuffers.Fruit fruit) { builder.Add(2, (short)fruit, 0); } + public static void AddLocation(ref FlatSpanBufferBuilder builder, StringOffset locationOffset) { builder.AddOffset(3, locationOffset, 0); } + public static Offset EndFooBarContainer(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishFooBarContainerBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedFooBarContainerBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + public FooBarContainerT UnPack() { + var _o = new FooBarContainerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FooBarContainerT _o) { + var _list_vec = this.List; + var _list_len = _list_vec.HasValue ? _list_vec.Value.Length : 0; + if (_o.List == null) { + _o.List = new List(_list_len); + } + ObjectApiUtil.ResizeList(_o.List, _list_len); + if (_list_vec.HasValue) { + var _list_value = _list_vec.Value; + for (var _j = 0; _j < _list_len; ++_j) { + var _src = _list_value[_j]; + if (_o.List[_j] == null) { _o.List[_j] = new FooBarT(); } + _src.UnPackTo(_o.List[_j]); + } + } + _o.Initialized = this.Initialized; + _o.Fruit = this.Fruit; + _o.Location = this.Location; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, FooBarContainerT _o) { + if (_o == null) return default(Offset); + var _list = default(VectorOffset); + if (_o.List != null) { + var _list_len = _o.List.Count; + Offset[] _list_arr = null; + try { + Span> __list = _list_len <= 64 + ? stackalloc Offset[_list_len] + : (_list_arr = ArrayPool>.Shared.Rent(_list_len)).AsSpan(0, _list_len); + for (var _j = 0; _j < _list_len; ++_j) { __list[_j] = Benchmarks.FlatSpanBuffers.StackBuffer.FooBar.Pack(ref builder, _o.List[_j]); } + _list = CreateListVector(ref builder, __list); + } finally { + if (_list_arr != null) { ArrayPool>.Shared.Return(_list_arr); } + } + } + var _location = _o.Location == null ? default(StringOffset) : builder.CreateString(_o.Location); + return CreateFooBarContainer( + ref builder, + _list, + _o.Initialized, + _o.Fruit, + _location); + } +} + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/SimpleMonster.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/SimpleMonster.cs new file mode 100644 index 00000000000..95849db21e2 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/SimpleMonster.cs @@ -0,0 +1,110 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct SimpleMonster : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static SimpleMonster GetRootAsSimpleMonster(ByteSpanBuffer _bb) { return GetRootAsSimpleMonster(_bb, new SimpleMonster()); } + public static SimpleMonster GetRootAsSimpleMonster(ByteSpanBuffer _bb, SimpleMonster obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public SimpleMonster __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public RefStructNullable> MutableName { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(4)) : default; } } + public short Hp { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)100; } } + public bool MutateHp(short hp) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, hp); return true; } else { return false; } } + public short Mana { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)150; } } + public bool MutateMana(short mana) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(o + __p.bb_pos, mana); return true; } else { return false; } } + public byte Color { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)2; } } + public bool MutateColor(byte color) { int o = __p.__offset(10); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, color); return true; } else { return false; } } + public bool Testbool { get { int o = __p.__offset(12); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public bool MutateTestbool(bool testbool) { int o = __p.__offset(12); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } } + public float Testf { get { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)3.14159f; } } + public bool MutateTestf(float testf) { int o = __p.__offset(14); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf); return true; } else { return false; } } + public float Testf2 { get { int o = __p.__offset(16); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)3.0f; } } + public bool MutateTestf2(float testf2) { int o = __p.__offset(16); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf2); return true; } else { return false; } } + public float Testf3 { get { int o = __p.__offset(18); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)0.0f; } } + public bool MutateTestf3(float testf3) { int o = __p.__offset(18); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf3); return true; } else { return false; } } + + public static Offset CreateSimpleMonster(ref FlatSpanBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + short hp = 100, + short mana = 150, + byte color = 2, + bool testbool = false, + float testf = 3.14159f, + float testf2 = 3.0f, + float testf3 = 0.0f) { + builder.StartTable(8); + SimpleMonster.AddTestf3(ref builder, testf3); + SimpleMonster.AddTestf2(ref builder, testf2); + SimpleMonster.AddTestf(ref builder, testf); + SimpleMonster.AddName(ref builder, nameOffset); + SimpleMonster.AddMana(ref builder, mana); + SimpleMonster.AddHp(ref builder, hp); + SimpleMonster.AddTestbool(ref builder, testbool); + SimpleMonster.AddColor(ref builder, color); + return SimpleMonster.EndSimpleMonster(ref builder); + } + + public static void StartSimpleMonster(ref FlatSpanBufferBuilder builder) { builder.StartTable(8); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddHp(ref FlatSpanBufferBuilder builder, short hp) { builder.Add(1, hp, 100); } + public static void AddMana(ref FlatSpanBufferBuilder builder, short mana) { builder.Add(2, mana, 150); } + public static void AddColor(ref FlatSpanBufferBuilder builder, byte color) { builder.Add(3, color, 2); } + public static void AddTestbool(ref FlatSpanBufferBuilder builder, bool testbool) { builder.Add(4, testbool, false); } + public static void AddTestf(ref FlatSpanBufferBuilder builder, float testf) { builder.Add(5, testf, 3.14159f); } + public static void AddTestf2(ref FlatSpanBufferBuilder builder, float testf2) { builder.Add(6, testf2, 3.0f); } + public static void AddTestf3(ref FlatSpanBufferBuilder builder, float testf3) { builder.Add(7, testf3, 0.0f); } + public static Offset EndSimpleMonster(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public SimpleMonsterT UnPack() { + var _o = new SimpleMonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(SimpleMonsterT _o) { + _o.Name = this.Name; + _o.Hp = this.Hp; + _o.Mana = this.Mana; + _o.Color = this.Color; + _o.Testbool = this.Testbool; + _o.Testf = this.Testf; + _o.Testf2 = this.Testf2; + _o.Testf3 = this.Testf3; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, SimpleMonsterT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateSimpleMonster( + ref builder, + _name, + _o.Hp, + _o.Mana, + _o.Color, + _o.Testbool, + _o.Testf, + _o.Testf2, + _o.Testf3); + } +} + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/VectorContainer.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/VectorContainer.cs new file mode 100644 index 00000000000..7d07be269ef --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/StackBuffer/VectorContainer.cs @@ -0,0 +1,208 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct VectorContainer : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static VectorContainer GetRootAsVectorContainer(ByteSpanBuffer _bb) { return GetRootAsVectorContainer(_bb, new VectorContainer()); } + public static VectorContainer GetRootAsVectorContainer(ByteSpanBuffer _bb, VectorContainer obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public VectorContainer __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public RefStructNullable> Bytes { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(4)) : default; } } + public RefStructNullable> MutableBytes { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(4)) : default; } } + public RefStructNullable> Shorts { get { int o = __p.__offset(6); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(6)) : default; } } + public RefStructNullable> MutableShorts { get { int o = __p.__offset(6); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(6)) : default; } } + public RefStructNullable> Ints { get { int o = __p.__offset(8); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(8)) : default; } } + public RefStructNullable> MutableInts { get { int o = __p.__offset(8); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(8)) : default; } } + public RefStructNullable> Longs { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(10)) : default; } } + public RefStructNullable> MutableLongs { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(10)) : default; } } + public RefStructNullable> Floats { get { int o = __p.__offset(12); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(12)) : default; } } + public RefStructNullable> MutableFloats { get { int o = __p.__offset(12); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(12)) : default; } } + public RefStructNullable> Doubles { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public RefStructNullable> MutableDoubles { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public RefStructNullable Strings { get { int o = __p.__offset(16); return o != 0 ? new RefStructNullable(new StringVectorSpan(__p, o)) : default; } } + + public static Offset CreateVectorContainer(ref FlatSpanBufferBuilder builder, + VectorOffset bytesOffset = default(VectorOffset), + VectorOffset shortsOffset = default(VectorOffset), + VectorOffset intsOffset = default(VectorOffset), + VectorOffset longsOffset = default(VectorOffset), + VectorOffset floatsOffset = default(VectorOffset), + VectorOffset doublesOffset = default(VectorOffset), + VectorOffset stringsOffset = default(VectorOffset)) { + builder.StartTable(7); + VectorContainer.AddStrings(ref builder, stringsOffset); + VectorContainer.AddDoubles(ref builder, doublesOffset); + VectorContainer.AddFloats(ref builder, floatsOffset); + VectorContainer.AddLongs(ref builder, longsOffset); + VectorContainer.AddInts(ref builder, intsOffset); + VectorContainer.AddShorts(ref builder, shortsOffset); + VectorContainer.AddBytes(ref builder, bytesOffset); + return VectorContainer.EndVectorContainer(ref builder); + } + + public static void StartVectorContainer(ref FlatSpanBufferBuilder builder) { builder.StartTable(7); } + public static void AddBytes(ref FlatSpanBufferBuilder builder, VectorOffset bytesOffset) { builder.AddOffset(0, bytesOffset, 0); } + public static VectorOffset CreateBytesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateBytesVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateBytesVectorBlock(ref builder, data); } + public static void StartBytesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddShorts(ref FlatSpanBufferBuilder builder, VectorOffset shortsOffset) { builder.AddOffset(1, shortsOffset, 0); } + public static VectorOffset CreateShortsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(2, data.Length, 2); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateShortsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateShortsVectorBlock(ref builder, data); } + public static void StartShortsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(2, numElems, 2); } + public static void AddInts(ref FlatSpanBufferBuilder builder, VectorOffset intsOffset) { builder.AddOffset(2, intsOffset, 0); } + public static VectorOffset CreateIntsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateIntsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateIntsVectorBlock(ref builder, data); } + public static void StartIntsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddLongs(ref FlatSpanBufferBuilder builder, VectorOffset longsOffset) { builder.AddOffset(3, longsOffset, 0); } + public static VectorOffset CreateLongsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateLongsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateLongsVectorBlock(ref builder, data); } + public static void StartLongsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddFloats(ref FlatSpanBufferBuilder builder, VectorOffset floatsOffset) { builder.AddOffset(4, floatsOffset, 0); } + public static VectorOffset CreateFloatsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateFloatsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateFloatsVectorBlock(ref builder, data); } + public static void StartFloatsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddDoubles(ref FlatSpanBufferBuilder builder, VectorOffset doublesOffset) { builder.AddOffset(5, doublesOffset, 0); } + public static VectorOffset CreateDoublesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateDoublesVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateDoublesVectorBlock(ref builder, data); } + public static void StartDoublesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddStrings(ref FlatSpanBufferBuilder builder, VectorOffset stringsOffset) { builder.AddOffset(6, stringsOffset, 0); } + public static VectorOffset CreateStringsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateStringsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateStringsVectorBlock(ref builder, data); } + public static void StartStringsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static Offset EndVectorContainer(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public VectorContainerT UnPack() { + var _o = new VectorContainerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(VectorContainerT _o) { + var _bytes_vec = this.Bytes; + var _bytes_len = _bytes_vec.HasValue ? _bytes_vec.Value.Length : 0; + if (_o.Bytes == null) { + _o.Bytes = new List(_bytes_len); + } + ObjectApiUtil.ResizeList(_o.Bytes, _bytes_len); + if (_bytes_vec.HasValue) { _bytes_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Bytes)); } + var _shorts_vec = this.Shorts; + var _shorts_len = _shorts_vec.HasValue ? _shorts_vec.Value.Length : 0; + if (_o.Shorts == null) { + _o.Shorts = new List(_shorts_len); + } + ObjectApiUtil.ResizeList(_o.Shorts, _shorts_len); + if (_shorts_vec.HasValue) { _shorts_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Shorts)); } + var _ints_vec = this.Ints; + var _ints_len = _ints_vec.HasValue ? _ints_vec.Value.Length : 0; + if (_o.Ints == null) { + _o.Ints = new List(_ints_len); + } + ObjectApiUtil.ResizeList(_o.Ints, _ints_len); + if (_ints_vec.HasValue) { _ints_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Ints)); } + var _longs_vec = this.Longs; + var _longs_len = _longs_vec.HasValue ? _longs_vec.Value.Length : 0; + if (_o.Longs == null) { + _o.Longs = new List(_longs_len); + } + ObjectApiUtil.ResizeList(_o.Longs, _longs_len); + if (_longs_vec.HasValue) { _longs_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Longs)); } + var _floats_vec = this.Floats; + var _floats_len = _floats_vec.HasValue ? _floats_vec.Value.Length : 0; + if (_o.Floats == null) { + _o.Floats = new List(_floats_len); + } + ObjectApiUtil.ResizeList(_o.Floats, _floats_len); + if (_floats_vec.HasValue) { _floats_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Floats)); } + var _doubles_vec = this.Doubles; + var _doubles_len = _doubles_vec.HasValue ? _doubles_vec.Value.Length : 0; + if (_o.Doubles == null) { + _o.Doubles = new List(_doubles_len); + } + ObjectApiUtil.ResizeList(_o.Doubles, _doubles_len); + if (_doubles_vec.HasValue) { _doubles_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Doubles)); } + var _strings_vec = this.Strings; + var _strings_len = _strings_vec.HasValue ? _strings_vec.Value.Length : 0; + if (_o.Strings == null) { + _o.Strings = new List(_strings_len); + } else { + _o.Strings.Clear(); + if (_o.Strings.Capacity < _strings_len) { + _o.Strings.Capacity = _strings_len; + } + } + if (_strings_vec.HasValue) { + var _strings_value = _strings_vec.Value; + for (var _j = 0; _j < _strings_len; ++_j) { _o.Strings.Add(_strings_value[_j]); } + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, VectorContainerT _o) { + if (_o == null) return default(Offset); + var _bytes = default(VectorOffset); + if (_o.Bytes != null) { + _bytes = CreateBytesVector(ref builder, CollectionsMarshal.AsSpan(_o.Bytes)); + } + var _shorts = default(VectorOffset); + if (_o.Shorts != null) { + _shorts = CreateShortsVector(ref builder, CollectionsMarshal.AsSpan(_o.Shorts)); + } + var _ints = default(VectorOffset); + if (_o.Ints != null) { + _ints = CreateIntsVector(ref builder, CollectionsMarshal.AsSpan(_o.Ints)); + } + var _longs = default(VectorOffset); + if (_o.Longs != null) { + _longs = CreateLongsVector(ref builder, CollectionsMarshal.AsSpan(_o.Longs)); + } + var _floats = default(VectorOffset); + if (_o.Floats != null) { + _floats = CreateFloatsVector(ref builder, CollectionsMarshal.AsSpan(_o.Floats)); + } + var _doubles = default(VectorOffset); + if (_o.Doubles != null) { + _doubles = CreateDoublesVector(ref builder, CollectionsMarshal.AsSpan(_o.Doubles)); + } + var _strings = default(VectorOffset); + if (_o.Strings != null) { + var _strings_len = _o.Strings.Count; + StringOffset[] _strings_arr = null; + try { + Span __strings = _strings_len <= 64 + ? stackalloc StringOffset[_strings_len] + : (_strings_arr = ArrayPool.Shared.Rent(_strings_len)).AsSpan(0, _strings_len); + for (var _j = 0; _j < _strings_len; ++_j) { __strings[_j] = builder.CreateString(_o.Strings[_j]); } + _strings = CreateStringsVector(ref builder, __strings); + } finally { + if (_strings_arr != null) { ArrayPool.Shared.Return(_strings_arr); } + } + } + return CreateVectorContainer( + ref builder, + _bytes, + _shorts, + _ints, + _longs, + _floats, + _doubles, + _strings); + } +} + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/VectorContainer.cs b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/VectorContainer.cs new file mode 100644 index 00000000000..f93c7e60a74 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/FlatSpanBuffers/Benchmarks/FlatSpanBuffers/VectorContainer.cs @@ -0,0 +1,245 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.FlatSpanBuffers +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct VectorContainer : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static VectorContainer GetRootAsVectorContainer(ByteBuffer _bb) { return GetRootAsVectorContainer(_bb, new VectorContainer()); } + public static VectorContainer GetRootAsVectorContainer(ByteBuffer _bb, VectorContainer obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public VectorContainer __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public RefStructNullable> Bytes { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(4)) : default; } } + public RefStructNullable> MutableBytes { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(4)) : default; } } + public RefStructNullable> Shorts { get { int o = __p.__offset(6); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(6)) : default; } } + public RefStructNullable> MutableShorts { get { int o = __p.__offset(6); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(6)) : default; } } + public RefStructNullable> Ints { get { int o = __p.__offset(8); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(8)) : default; } } + public RefStructNullable> MutableInts { get { int o = __p.__offset(8); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(8)) : default; } } + public RefStructNullable> Longs { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(10)) : default; } } + public RefStructNullable> MutableLongs { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(10)) : default; } } + public RefStructNullable> Floats { get { int o = __p.__offset(12); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(12)) : default; } } + public RefStructNullable> MutableFloats { get { int o = __p.__offset(12); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(12)) : default; } } + public RefStructNullable> Doubles { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public RefStructNullable> MutableDoubles { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public StringVector? Strings { get { int o = __p.__offset(16); return o != 0 ? new StringVector(__p, o) : null; } } + + public static Offset CreateVectorContainer(FlatBufferBuilder builder, + VectorOffset bytesOffset = default(VectorOffset), + VectorOffset shortsOffset = default(VectorOffset), + VectorOffset intsOffset = default(VectorOffset), + VectorOffset longsOffset = default(VectorOffset), + VectorOffset floatsOffset = default(VectorOffset), + VectorOffset doublesOffset = default(VectorOffset), + VectorOffset stringsOffset = default(VectorOffset)) { + builder.StartTable(7); + VectorContainer.AddStrings(builder, stringsOffset); + VectorContainer.AddDoubles(builder, doublesOffset); + VectorContainer.AddFloats(builder, floatsOffset); + VectorContainer.AddLongs(builder, longsOffset); + VectorContainer.AddInts(builder, intsOffset); + VectorContainer.AddShorts(builder, shortsOffset); + VectorContainer.AddBytes(builder, bytesOffset); + return VectorContainer.EndVectorContainer(builder); + } + + public static void StartVectorContainer(FlatBufferBuilder builder) { builder.StartTable(7); } + public static void AddBytes(FlatBufferBuilder builder, VectorOffset bytesOffset) { builder.AddOffset(0, bytesOffset, 0); } + public static VectorOffset CreateBytesVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateBytesVector(FlatBufferBuilder builder, Span data) { return CreateBytesVectorBlock(builder, data); } + public static void StartBytesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddShorts(FlatBufferBuilder builder, VectorOffset shortsOffset) { builder.AddOffset(1, shortsOffset, 0); } + public static VectorOffset CreateShortsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(2, data.Length, 2); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateShortsVector(FlatBufferBuilder builder, Span data) { return CreateShortsVectorBlock(builder, data); } + public static void StartShortsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(2, numElems, 2); } + public static void AddInts(FlatBufferBuilder builder, VectorOffset intsOffset) { builder.AddOffset(2, intsOffset, 0); } + public static VectorOffset CreateIntsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateIntsVector(FlatBufferBuilder builder, Span data) { return CreateIntsVectorBlock(builder, data); } + public static void StartIntsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddLongs(FlatBufferBuilder builder, VectorOffset longsOffset) { builder.AddOffset(3, longsOffset, 0); } + public static VectorOffset CreateLongsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateLongsVector(FlatBufferBuilder builder, Span data) { return CreateLongsVectorBlock(builder, data); } + public static void StartLongsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddFloats(FlatBufferBuilder builder, VectorOffset floatsOffset) { builder.AddOffset(4, floatsOffset, 0); } + public static VectorOffset CreateFloatsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateFloatsVector(FlatBufferBuilder builder, Span data) { return CreateFloatsVectorBlock(builder, data); } + public static void StartFloatsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddDoubles(FlatBufferBuilder builder, VectorOffset doublesOffset) { builder.AddOffset(5, doublesOffset, 0); } + public static VectorOffset CreateDoublesVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateDoublesVector(FlatBufferBuilder builder, Span data) { return CreateDoublesVectorBlock(builder, data); } + public static void StartDoublesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddStrings(FlatBufferBuilder builder, VectorOffset stringsOffset) { builder.AddOffset(6, stringsOffset, 0); } + public static VectorOffset CreateStringsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateStringsVector(FlatBufferBuilder builder, Span data) { return CreateStringsVectorBlock(builder, data); } + public static void StartStringsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static Offset EndVectorContainer(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public VectorContainerT UnPack() { + var _o = new VectorContainerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(VectorContainerT _o) { + var _bytes_vec = this.Bytes; + var _bytes_len = _bytes_vec.HasValue ? _bytes_vec.Value.Length : 0; + if (_o.Bytes == null) { + _o.Bytes = new List(_bytes_len); + } + ObjectApiUtil.ResizeList(_o.Bytes, _bytes_len); + if (_bytes_vec.HasValue) { _bytes_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Bytes)); } + var _shorts_vec = this.Shorts; + var _shorts_len = _shorts_vec.HasValue ? _shorts_vec.Value.Length : 0; + if (_o.Shorts == null) { + _o.Shorts = new List(_shorts_len); + } + ObjectApiUtil.ResizeList(_o.Shorts, _shorts_len); + if (_shorts_vec.HasValue) { _shorts_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Shorts)); } + var _ints_vec = this.Ints; + var _ints_len = _ints_vec.HasValue ? _ints_vec.Value.Length : 0; + if (_o.Ints == null) { + _o.Ints = new List(_ints_len); + } + ObjectApiUtil.ResizeList(_o.Ints, _ints_len); + if (_ints_vec.HasValue) { _ints_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Ints)); } + var _longs_vec = this.Longs; + var _longs_len = _longs_vec.HasValue ? _longs_vec.Value.Length : 0; + if (_o.Longs == null) { + _o.Longs = new List(_longs_len); + } + ObjectApiUtil.ResizeList(_o.Longs, _longs_len); + if (_longs_vec.HasValue) { _longs_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Longs)); } + var _floats_vec = this.Floats; + var _floats_len = _floats_vec.HasValue ? _floats_vec.Value.Length : 0; + if (_o.Floats == null) { + _o.Floats = new List(_floats_len); + } + ObjectApiUtil.ResizeList(_o.Floats, _floats_len); + if (_floats_vec.HasValue) { _floats_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Floats)); } + var _doubles_vec = this.Doubles; + var _doubles_len = _doubles_vec.HasValue ? _doubles_vec.Value.Length : 0; + if (_o.Doubles == null) { + _o.Doubles = new List(_doubles_len); + } + ObjectApiUtil.ResizeList(_o.Doubles, _doubles_len); + if (_doubles_vec.HasValue) { _doubles_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Doubles)); } + var _strings_vec = this.Strings; + var _strings_len = _strings_vec.HasValue ? _strings_vec.Value.Length : 0; + if (_o.Strings == null) { + _o.Strings = new List(_strings_len); + } else { + _o.Strings.Clear(); + if (_o.Strings.Capacity < _strings_len) { + _o.Strings.Capacity = _strings_len; + } + } + if (_strings_vec.HasValue) { + var _strings_value = _strings_vec.Value; + for (var _j = 0; _j < _strings_len; ++_j) { _o.Strings.Add(_strings_value[_j]); } + } + } + public static Offset Pack(FlatBufferBuilder builder, VectorContainerT _o) { + if (_o == null) return default(Offset); + var _bytes = default(VectorOffset); + if (_o.Bytes != null) { + _bytes = CreateBytesVector(builder, CollectionsMarshal.AsSpan(_o.Bytes)); + } + var _shorts = default(VectorOffset); + if (_o.Shorts != null) { + _shorts = CreateShortsVector(builder, CollectionsMarshal.AsSpan(_o.Shorts)); + } + var _ints = default(VectorOffset); + if (_o.Ints != null) { + _ints = CreateIntsVector(builder, CollectionsMarshal.AsSpan(_o.Ints)); + } + var _longs = default(VectorOffset); + if (_o.Longs != null) { + _longs = CreateLongsVector(builder, CollectionsMarshal.AsSpan(_o.Longs)); + } + var _floats = default(VectorOffset); + if (_o.Floats != null) { + _floats = CreateFloatsVector(builder, CollectionsMarshal.AsSpan(_o.Floats)); + } + var _doubles = default(VectorOffset); + if (_o.Doubles != null) { + _doubles = CreateDoublesVector(builder, CollectionsMarshal.AsSpan(_o.Doubles)); + } + var _strings = default(VectorOffset); + if (_o.Strings != null) { + var _strings_len = _o.Strings.Count; + StringOffset[] _strings_arr = null; + try { + Span __strings = _strings_len <= 64 + ? stackalloc StringOffset[_strings_len] + : (_strings_arr = ArrayPool.Shared.Rent(_strings_len)).AsSpan(0, _strings_len); + for (var _j = 0; _j < _strings_len; ++_j) { __strings[_j] = builder.CreateString(_o.Strings[_j]); } + _strings = CreateStringsVector(builder, __strings); + } finally { + if (_strings_arr != null) { ArrayPool.Shared.Return(_strings_arr); } + } + } + return CreateVectorContainer( + builder, + _bytes, + _shorts, + _ints, + _longs, + _floats, + _doubles, + _strings); + } +} + +public class VectorContainerT +{ + public List Bytes { get; set; } + public List Shorts { get; set; } + public List Ints { get; set; } + public List Longs { get; set; } + public List Floats { get; set; } + public List Doubles { get; set; } + public List Strings { get; set; } + + public VectorContainerT() { + this.Bytes = null; + this.Shorts = null; + this.Ints = null; + this.Longs = null; + this.Floats = null; + this.Doubles = null; + this.Strings = null; + } +} + + +static public class VectorContainerVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyVectorOfData(tablePos, 4 /*Bytes*/, 1 /*byte*/, false) + && verifier.VerifyVectorOfData(tablePos, 6 /*Shorts*/, 2 /*short*/, false) + && verifier.VerifyVectorOfData(tablePos, 8 /*Ints*/, 4 /*int*/, false) + && verifier.VerifyVectorOfData(tablePos, 10 /*Longs*/, 8 /*long*/, false) + && verifier.VerifyVectorOfData(tablePos, 12 /*Floats*/, 4 /*float*/, false) + && verifier.VerifyVectorOfData(tablePos, 14 /*Doubles*/, 8 /*double*/, false) + && verifier.VerifyVectorOfStrings(tablePos, 16 /*Strings*/, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/Bar.cs b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/Bar.cs new file mode 100644 index 00000000000..9dc5386c36b --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/Bar.cs @@ -0,0 +1,83 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.OriginalFlatBuffers +{ + +using global::System; +using global::System.Collections.Generic; +using global::Google.FlatBuffers; + +public struct Bar : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Bar __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public Benchmarks.OriginalFlatBuffers.Foo Parent { get { return (new Benchmarks.OriginalFlatBuffers.Foo()).__assign(__p.bb_pos + 0, __p.bb); } } + public int Time { get { return __p.bb.GetInt(__p.bb_pos + 16); } } + public float Ratio { get { return __p.bb.GetFloat(__p.bb_pos + 20); } } + public ushort Size { get { return __p.bb.GetUshort(__p.bb_pos + 24); } } + + public static Offset CreateBar(FlatBufferBuilder builder, ulong parent_Id, short parent_Count, sbyte parent_Prefix, uint parent_Length, int Time, float Ratio, ushort Size) { + builder.Prep(8, 32); + builder.Pad(6); + builder.PutUshort(Size); + builder.PutFloat(Ratio); + builder.PutInt(Time); + builder.Prep(8, 16); + builder.PutUint(parent_Length); + builder.Pad(1); + builder.PutSbyte(parent_Prefix); + builder.PutShort(parent_Count); + builder.PutUlong(parent_Id); + return new Offset(builder.Offset); + } + public BarT UnPack() { + var _o = new BarT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(BarT _o) { + _o.Parent = this.Parent.UnPack(); + _o.Time = this.Time; + _o.Ratio = this.Ratio; + _o.Size = this.Size; + } + public static Offset Pack(FlatBufferBuilder builder, BarT _o) { + if (_o == null) return default(Offset); + var _parent_id = _o.Parent.Id; + var _parent_count = _o.Parent.Count; + var _parent_prefix = _o.Parent.Prefix; + var _parent_length = _o.Parent.Length; + return CreateBar( + builder, + _parent_id, + _parent_count, + _parent_prefix, + _parent_length, + _o.Time, + _o.Ratio, + _o.Size); + } +} + +public class BarT +{ + public Benchmarks.OriginalFlatBuffers.FooT Parent { get; set; } + public int Time { get; set; } + public float Ratio { get; set; } + public ushort Size { get; set; } + + public BarT() { + this.Parent = new Benchmarks.OriginalFlatBuffers.FooT(); + this.Time = 0; + this.Ratio = 0.0f; + this.Size = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/Foo.cs b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/Foo.cs new file mode 100644 index 00000000000..b46b4dcc364 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/Foo.cs @@ -0,0 +1,71 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.OriginalFlatBuffers +{ + +using global::System; +using global::System.Collections.Generic; +using global::Google.FlatBuffers; + +public struct Foo : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Foo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ulong Id { get { return __p.bb.GetUlong(__p.bb_pos + 0); } } + public short Count { get { return __p.bb.GetShort(__p.bb_pos + 8); } } + public sbyte Prefix { get { return __p.bb.GetSbyte(__p.bb_pos + 10); } } + public uint Length { get { return __p.bb.GetUint(__p.bb_pos + 12); } } + + public static Offset CreateFoo(FlatBufferBuilder builder, ulong Id, short Count, sbyte Prefix, uint Length) { + builder.Prep(8, 16); + builder.PutUint(Length); + builder.Pad(1); + builder.PutSbyte(Prefix); + builder.PutShort(Count); + builder.PutUlong(Id); + return new Offset(builder.Offset); + } + public FooT UnPack() { + var _o = new FooT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FooT _o) { + _o.Id = this.Id; + _o.Count = this.Count; + _o.Prefix = this.Prefix; + _o.Length = this.Length; + } + public static Offset Pack(FlatBufferBuilder builder, FooT _o) { + if (_o == null) return default(Offset); + return CreateFoo( + builder, + _o.Id, + _o.Count, + _o.Prefix, + _o.Length); + } +} + +public class FooT +{ + public ulong Id { get; set; } + public short Count { get; set; } + public sbyte Prefix { get; set; } + public uint Length { get; set; } + + public FooT() { + this.Id = 0; + this.Count = 0; + this.Prefix = 0; + this.Length = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/FooBar.cs b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/FooBar.cs new file mode 100644 index 00000000000..c45f4bcf268 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/FooBar.cs @@ -0,0 +1,107 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.OriginalFlatBuffers +{ + +using global::System; +using global::System.Collections.Generic; +using global::Google.FlatBuffers; + +public struct FooBar : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_12_19(); } + public static FooBar GetRootAsFooBar(ByteBuffer _bb) { return GetRootAsFooBar(_bb, new FooBar()); } + public static FooBar GetRootAsFooBar(ByteBuffer _bb, FooBar obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public FooBar __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public Benchmarks.OriginalFlatBuffers.Bar? Sibling { get { int o = __p.__offset(4); return o != 0 ? (Benchmarks.OriginalFlatBuffers.Bar?)(new Benchmarks.OriginalFlatBuffers.Bar()).__assign(o + __p.bb_pos, __p.bb) : null; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetNameBytes() { return __p.__vector_as_span(6, 1); } +#else + public ArraySegment? GetNameBytes() { return __p.__vector_as_arraysegment(6); } +#endif + public byte[] GetNameArray() { return __p.__vector_as_array(6); } + public double Rating { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetDouble(o + __p.bb_pos) : (double)0.0; } } + public byte Postfix { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)0; } } + + public static Offset CreateFooBar(FlatBufferBuilder builder, + Benchmarks.OriginalFlatBuffers.BarT sibling = null, + StringOffset nameOffset = default(StringOffset), + double rating = 0.0, + byte postfix = 0) { + builder.StartTable(4); + FooBar.AddRating(builder, rating); + FooBar.AddName(builder, nameOffset); + FooBar.AddSibling(builder, Benchmarks.OriginalFlatBuffers.Bar.Pack(builder, sibling)); + FooBar.AddPostfix(builder, postfix); + return FooBar.EndFooBar(builder); + } + + public static void StartFooBar(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddSibling(FlatBufferBuilder builder, Offset siblingOffset) { builder.AddStruct(0, siblingOffset.Value, 0); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset.Value, 0); } + public static void AddRating(FlatBufferBuilder builder, double rating) { builder.AddDouble(2, rating, 0.0); } + public static void AddPostfix(FlatBufferBuilder builder, byte postfix) { builder.AddByte(3, postfix, 0); } + public static Offset EndFooBar(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public FooBarT UnPack() { + var _o = new FooBarT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FooBarT _o) { + _o.Sibling = this.Sibling.HasValue ? this.Sibling.Value.UnPack() : null; + _o.Name = this.Name; + _o.Rating = this.Rating; + _o.Postfix = this.Postfix; + } + public static Offset Pack(FlatBufferBuilder builder, FooBarT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateFooBar( + builder, + _o.Sibling, + _name, + _o.Rating, + _o.Postfix); + } +} + +public class FooBarT +{ + public Benchmarks.OriginalFlatBuffers.BarT Sibling { get; set; } + public string Name { get; set; } + public double Rating { get; set; } + public byte Postfix { get; set; } + + public FooBarT() { + this.Sibling = new Benchmarks.OriginalFlatBuffers.BarT(); + this.Name = null; + this.Rating = 0.0; + this.Postfix = 0; + } +} + + +static public class FooBarVerify +{ + static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Sibling*/, 32 /*Benchmarks.OriginalFlatBuffers.Bar*/, 8, false) + && verifier.VerifyString(tablePos, 6 /*Name*/, false) + && verifier.VerifyField(tablePos, 8 /*Rating*/, 8 /*double*/, 8, false) + && verifier.VerifyField(tablePos, 10 /*Postfix*/, 1 /*byte*/, 1, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/FooBarContainer.cs b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/FooBarContainer.cs new file mode 100644 index 00000000000..0092ce7c102 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/FooBarContainer.cs @@ -0,0 +1,131 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.OriginalFlatBuffers +{ + +using global::System; +using global::System.Collections.Generic; +using global::Google.FlatBuffers; + +public struct FooBarContainer : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_12_19(); } + public static FooBarContainer GetRootAsFooBarContainer(ByteBuffer _bb) { return GetRootAsFooBarContainer(_bb, new FooBarContainer()); } + public static FooBarContainer GetRootAsFooBarContainer(ByteBuffer _bb, FooBarContainer obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public static bool VerifyFooBarContainer(ByteBuffer _bb) {Google.FlatBuffers.Verifier verifier = new Google.FlatBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, FooBarContainerVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public FooBarContainer __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public Benchmarks.OriginalFlatBuffers.FooBar? List(int j) { int o = __p.__offset(4); return o != 0 ? (Benchmarks.OriginalFlatBuffers.FooBar?)(new Benchmarks.OriginalFlatBuffers.FooBar()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; } + public int ListLength { get { int o = __p.__offset(4); return o != 0 ? __p.__vector_len(o) : 0; } } + public bool Initialized { get { int o = __p.__offset(6); return o != 0 ? 0!=__p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public Benchmarks.OriginalFlatBuffers.Fruit Fruit { get { int o = __p.__offset(8); return o != 0 ? (Benchmarks.OriginalFlatBuffers.Fruit)__p.bb.GetShort(o + __p.bb_pos) : Benchmarks.OriginalFlatBuffers.Fruit.Apples; } } + public string Location { get { int o = __p.__offset(10); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetLocationBytes() { return __p.__vector_as_span(10, 1); } +#else + public ArraySegment? GetLocationBytes() { return __p.__vector_as_arraysegment(10); } +#endif + public byte[] GetLocationArray() { return __p.__vector_as_array(10); } + + public static Offset CreateFooBarContainer(FlatBufferBuilder builder, + VectorOffset listOffset = default(VectorOffset), + bool initialized = false, + Benchmarks.OriginalFlatBuffers.Fruit fruit = Benchmarks.OriginalFlatBuffers.Fruit.Apples, + StringOffset locationOffset = default(StringOffset)) { + builder.StartTable(4); + FooBarContainer.AddLocation(builder, locationOffset); + FooBarContainer.AddList(builder, listOffset); + FooBarContainer.AddFruit(builder, fruit); + FooBarContainer.AddInitialized(builder, initialized); + return FooBarContainer.EndFooBarContainer(builder); + } + + public static void StartFooBarContainer(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddList(FlatBufferBuilder builder, VectorOffset listOffset) { builder.AddOffset(0, listOffset.Value, 0); } + public static VectorOffset CreateListVector(FlatBufferBuilder builder, Offset[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); } + public static VectorOffset CreateListVectorBlock(FlatBufferBuilder builder, Offset[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateListVectorBlock(FlatBufferBuilder builder, ArraySegment> data) { builder.StartVector(4, data.Count, 4); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateListVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add>(dataPtr, sizeInBytes); return builder.EndVector(); } + public static void StartListVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddInitialized(FlatBufferBuilder builder, bool initialized) { builder.AddBool(1, initialized, false); } + public static void AddFruit(FlatBufferBuilder builder, Benchmarks.OriginalFlatBuffers.Fruit fruit) { builder.AddShort(2, (short)fruit, 0); } + public static void AddLocation(FlatBufferBuilder builder, StringOffset locationOffset) { builder.AddOffset(3, locationOffset.Value, 0); } + public static Offset EndFooBarContainer(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishFooBarContainerBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedFooBarContainerBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + public FooBarContainerT UnPack() { + var _o = new FooBarContainerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FooBarContainerT _o) { + _o.List = new List(); + for (var _j = 0; _j < this.ListLength; ++_j) {_o.List.Add(this.List(_j).HasValue ? this.List(_j).Value.UnPack() : null);} + _o.Initialized = this.Initialized; + _o.Fruit = this.Fruit; + _o.Location = this.Location; + } + public static Offset Pack(FlatBufferBuilder builder, FooBarContainerT _o) { + if (_o == null) return default(Offset); + var _list = default(VectorOffset); + if (_o.List != null) { + var __list = new Offset[_o.List.Count]; + for (var _j = 0; _j < __list.Length; ++_j) { __list[_j] = Benchmarks.OriginalFlatBuffers.FooBar.Pack(builder, _o.List[_j]); } + _list = CreateListVector(builder, __list); + } + var _location = _o.Location == null ? default(StringOffset) : builder.CreateString(_o.Location); + return CreateFooBarContainer( + builder, + _list, + _o.Initialized, + _o.Fruit, + _location); + } +} + +public class FooBarContainerT +{ + public List List { get; set; } + public bool Initialized { get; set; } + public Benchmarks.OriginalFlatBuffers.Fruit Fruit { get; set; } + public string Location { get; set; } + + public FooBarContainerT() { + this.List = null; + this.Initialized = false; + this.Fruit = Benchmarks.OriginalFlatBuffers.Fruit.Apples; + this.Location = null; + } + public static FooBarContainerT DeserializeFromBinary(byte[] fbBuffer) { + return FooBarContainer.GetRootAsFooBarContainer(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + FooBarContainer.FinishFooBarContainerBuffer(fbb, FooBarContainer.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedArray(); + } +} + + +static public class FooBarContainerVerify +{ + static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyVectorOfTables(tablePos, 4 /*List*/, Benchmarks.OriginalFlatBuffers.FooBarVerify.Verify, false) + && verifier.VerifyField(tablePos, 6 /*Initialized*/, 1 /*bool*/, 1, false) + && verifier.VerifyField(tablePos, 8 /*Fruit*/, 2 /*Benchmarks.OriginalFlatBuffers.Fruit*/, 2, false) + && verifier.VerifyString(tablePos, 10 /*Location*/, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/Fruit.cs b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/Fruit.cs new file mode 100644 index 00000000000..67da5ff6bca --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/Fruit.cs @@ -0,0 +1,16 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.OriginalFlatBuffers +{ + +public enum Fruit : short +{ + Apples = 0, + Pears = 1, + Bananas = 2, +}; + + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/SimpleMonster.cs b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/SimpleMonster.cs new file mode 100644 index 00000000000..d03a44e48c6 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/SimpleMonster.cs @@ -0,0 +1,143 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.OriginalFlatBuffers +{ + +using global::System; +using global::System.Collections.Generic; +using global::Google.FlatBuffers; + +public struct SimpleMonster : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_12_19(); } + public static SimpleMonster GetRootAsSimpleMonster(ByteBuffer _bb) { return GetRootAsSimpleMonster(_bb, new SimpleMonster()); } + public static SimpleMonster GetRootAsSimpleMonster(ByteBuffer _bb, SimpleMonster obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public SimpleMonster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } +#if ENABLE_SPAN_T + public Span GetNameBytes() { return __p.__vector_as_span(4, 1); } +#else + public ArraySegment? GetNameBytes() { return __p.__vector_as_arraysegment(4); } +#endif + public byte[] GetNameArray() { return __p.__vector_as_array(4); } + public short Hp { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetShort(o + __p.bb_pos) : (short)100; } } + public short Mana { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetShort(o + __p.bb_pos) : (short)150; } } + public byte Color { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)2; } } + public bool Testbool { get { int o = __p.__offset(12); return o != 0 ? 0!=__p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public float Testf { get { int o = __p.__offset(14); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)3.14159f; } } + public float Testf2 { get { int o = __p.__offset(16); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)3.0f; } } + public float Testf3 { get { int o = __p.__offset(18); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)0.0f; } } + + public static Offset CreateSimpleMonster(FlatBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + short hp = 100, + short mana = 150, + byte color = 2, + bool testbool = false, + float testf = 3.14159f, + float testf2 = 3.0f, + float testf3 = 0.0f) { + builder.StartTable(8); + SimpleMonster.AddTestf3(builder, testf3); + SimpleMonster.AddTestf2(builder, testf2); + SimpleMonster.AddTestf(builder, testf); + SimpleMonster.AddName(builder, nameOffset); + SimpleMonster.AddMana(builder, mana); + SimpleMonster.AddHp(builder, hp); + SimpleMonster.AddTestbool(builder, testbool); + SimpleMonster.AddColor(builder, color); + return SimpleMonster.EndSimpleMonster(builder); + } + + public static void StartSimpleMonster(FlatBufferBuilder builder) { builder.StartTable(8); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset.Value, 0); } + public static void AddHp(FlatBufferBuilder builder, short hp) { builder.AddShort(1, hp, 100); } + public static void AddMana(FlatBufferBuilder builder, short mana) { builder.AddShort(2, mana, 150); } + public static void AddColor(FlatBufferBuilder builder, byte color) { builder.AddByte(3, color, 2); } + public static void AddTestbool(FlatBufferBuilder builder, bool testbool) { builder.AddBool(4, testbool, false); } + public static void AddTestf(FlatBufferBuilder builder, float testf) { builder.AddFloat(5, testf, 3.14159f); } + public static void AddTestf2(FlatBufferBuilder builder, float testf2) { builder.AddFloat(6, testf2, 3.0f); } + public static void AddTestf3(FlatBufferBuilder builder, float testf3) { builder.AddFloat(7, testf3, 0.0f); } + public static Offset EndSimpleMonster(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public SimpleMonsterT UnPack() { + var _o = new SimpleMonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(SimpleMonsterT _o) { + _o.Name = this.Name; + _o.Hp = this.Hp; + _o.Mana = this.Mana; + _o.Color = this.Color; + _o.Testbool = this.Testbool; + _o.Testf = this.Testf; + _o.Testf2 = this.Testf2; + _o.Testf3 = this.Testf3; + } + public static Offset Pack(FlatBufferBuilder builder, SimpleMonsterT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateSimpleMonster( + builder, + _name, + _o.Hp, + _o.Mana, + _o.Color, + _o.Testbool, + _o.Testf, + _o.Testf2, + _o.Testf3); + } +} + +public class SimpleMonsterT +{ + public string Name { get; set; } + public short Hp { get; set; } + public short Mana { get; set; } + public byte Color { get; set; } + public bool Testbool { get; set; } + public float Testf { get; set; } + public float Testf2 { get; set; } + public float Testf3 { get; set; } + + public SimpleMonsterT() { + this.Name = null; + this.Hp = 100; + this.Mana = 150; + this.Color = 2; + this.Testbool = false; + this.Testf = 3.14159f; + this.Testf2 = 3.0f; + this.Testf3 = 0.0f; + } +} + + +static public class SimpleMonsterVerify +{ + static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*Name*/, false) + && verifier.VerifyField(tablePos, 6 /*Hp*/, 2 /*short*/, 2, false) + && verifier.VerifyField(tablePos, 8 /*Mana*/, 2 /*short*/, 2, false) + && verifier.VerifyField(tablePos, 10 /*Color*/, 1 /*byte*/, 1, false) + && verifier.VerifyField(tablePos, 12 /*Testbool*/, 1 /*bool*/, 1, false) + && verifier.VerifyField(tablePos, 14 /*Testf*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 16 /*Testf2*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 18 /*Testf3*/, 4 /*float*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/VectorContainer.cs b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/VectorContainer.cs new file mode 100644 index 00000000000..8f56a1b4212 --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Generated/OriginalFlatBuffers/Benchmarks/OriginalFlatBuffers/VectorContainer.cs @@ -0,0 +1,248 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace Benchmarks.OriginalFlatBuffers +{ + +using global::System; +using global::System.Collections.Generic; +using global::Google.FlatBuffers; + +public struct VectorContainer : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_12_19(); } + public static VectorContainer GetRootAsVectorContainer(ByteBuffer _bb) { return GetRootAsVectorContainer(_bb, new VectorContainer()); } + public static VectorContainer GetRootAsVectorContainer(ByteBuffer _bb, VectorContainer obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public VectorContainer __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public byte Bytes(int j) { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; } + public int BytesLength { get { int o = __p.__offset(4); return o != 0 ? __p.__vector_len(o) : 0; } } +#if ENABLE_SPAN_T + public Span GetBytesBytes() { return __p.__vector_as_span(4, 1); } +#else + public ArraySegment? GetBytesBytes() { return __p.__vector_as_arraysegment(4); } +#endif + public byte[] GetBytesArray() { return __p.__vector_as_array(4); } + public short Shorts(int j) { int o = __p.__offset(6); return o != 0 ? __p.bb.GetShort(__p.__vector(o) + j * 2) : (short)0; } + public int ShortsLength { get { int o = __p.__offset(6); return o != 0 ? __p.__vector_len(o) : 0; } } +#if ENABLE_SPAN_T + public Span GetShortsBytes() { return __p.__vector_as_span(6, 2); } +#else + public ArraySegment? GetShortsBytes() { return __p.__vector_as_arraysegment(6); } +#endif + public short[] GetShortsArray() { return __p.__vector_as_array(6); } + public int Ints(int j) { int o = __p.__offset(8); return o != 0 ? __p.bb.GetInt(__p.__vector(o) + j * 4) : (int)0; } + public int IntsLength { get { int o = __p.__offset(8); return o != 0 ? __p.__vector_len(o) : 0; } } +#if ENABLE_SPAN_T + public Span GetIntsBytes() { return __p.__vector_as_span(8, 4); } +#else + public ArraySegment? GetIntsBytes() { return __p.__vector_as_arraysegment(8); } +#endif + public int[] GetIntsArray() { return __p.__vector_as_array(8); } + public long Longs(int j) { int o = __p.__offset(10); return o != 0 ? __p.bb.GetLong(__p.__vector(o) + j * 8) : (long)0; } + public int LongsLength { get { int o = __p.__offset(10); return o != 0 ? __p.__vector_len(o) : 0; } } +#if ENABLE_SPAN_T + public Span GetLongsBytes() { return __p.__vector_as_span(10, 8); } +#else + public ArraySegment? GetLongsBytes() { return __p.__vector_as_arraysegment(10); } +#endif + public long[] GetLongsArray() { return __p.__vector_as_array(10); } + public float Floats(int j) { int o = __p.__offset(12); return o != 0 ? __p.bb.GetFloat(__p.__vector(o) + j * 4) : (float)0; } + public int FloatsLength { get { int o = __p.__offset(12); return o != 0 ? __p.__vector_len(o) : 0; } } +#if ENABLE_SPAN_T + public Span GetFloatsBytes() { return __p.__vector_as_span(12, 4); } +#else + public ArraySegment? GetFloatsBytes() { return __p.__vector_as_arraysegment(12); } +#endif + public float[] GetFloatsArray() { return __p.__vector_as_array(12); } + public double Doubles(int j) { int o = __p.__offset(14); return o != 0 ? __p.bb.GetDouble(__p.__vector(o) + j * 8) : (double)0; } + public int DoublesLength { get { int o = __p.__offset(14); return o != 0 ? __p.__vector_len(o) : 0; } } +#if ENABLE_SPAN_T + public Span GetDoublesBytes() { return __p.__vector_as_span(14, 8); } +#else + public ArraySegment? GetDoublesBytes() { return __p.__vector_as_arraysegment(14); } +#endif + public double[] GetDoublesArray() { return __p.__vector_as_array(14); } + public string Strings(int j) { int o = __p.__offset(16); return o != 0 ? __p.__string(__p.__vector(o) + j * 4) : null; } + public int StringsLength { get { int o = __p.__offset(16); return o != 0 ? __p.__vector_len(o) : 0; } } + + public static Offset CreateVectorContainer(FlatBufferBuilder builder, + VectorOffset bytesOffset = default(VectorOffset), + VectorOffset shortsOffset = default(VectorOffset), + VectorOffset intsOffset = default(VectorOffset), + VectorOffset longsOffset = default(VectorOffset), + VectorOffset floatsOffset = default(VectorOffset), + VectorOffset doublesOffset = default(VectorOffset), + VectorOffset stringsOffset = default(VectorOffset)) { + builder.StartTable(7); + VectorContainer.AddStrings(builder, stringsOffset); + VectorContainer.AddDoubles(builder, doublesOffset); + VectorContainer.AddFloats(builder, floatsOffset); + VectorContainer.AddLongs(builder, longsOffset); + VectorContainer.AddInts(builder, intsOffset); + VectorContainer.AddShorts(builder, shortsOffset); + VectorContainer.AddBytes(builder, bytesOffset); + return VectorContainer.EndVectorContainer(builder); + } + + public static void StartVectorContainer(FlatBufferBuilder builder) { builder.StartTable(7); } + public static void AddBytes(FlatBufferBuilder builder, VectorOffset bytesOffset) { builder.AddOffset(0, bytesOffset.Value, 0); } + public static VectorOffset CreateBytesVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); } + public static VectorOffset CreateBytesVectorBlock(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateBytesVectorBlock(FlatBufferBuilder builder, ArraySegment data) { builder.StartVector(1, data.Count, 1); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateBytesVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add(dataPtr, sizeInBytes); return builder.EndVector(); } + public static void StartBytesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddShorts(FlatBufferBuilder builder, VectorOffset shortsOffset) { builder.AddOffset(1, shortsOffset.Value, 0); } + public static VectorOffset CreateShortsVector(FlatBufferBuilder builder, short[] data) { builder.StartVector(2, data.Length, 2); for (int i = data.Length - 1; i >= 0; i--) builder.AddShort(data[i]); return builder.EndVector(); } + public static VectorOffset CreateShortsVectorBlock(FlatBufferBuilder builder, short[] data) { builder.StartVector(2, data.Length, 2); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateShortsVectorBlock(FlatBufferBuilder builder, ArraySegment data) { builder.StartVector(2, data.Count, 2); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateShortsVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add(dataPtr, sizeInBytes); return builder.EndVector(); } + public static void StartShortsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(2, numElems, 2); } + public static void AddInts(FlatBufferBuilder builder, VectorOffset intsOffset) { builder.AddOffset(2, intsOffset.Value, 0); } + public static VectorOffset CreateIntsVector(FlatBufferBuilder builder, int[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddInt(data[i]); return builder.EndVector(); } + public static VectorOffset CreateIntsVectorBlock(FlatBufferBuilder builder, int[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateIntsVectorBlock(FlatBufferBuilder builder, ArraySegment data) { builder.StartVector(4, data.Count, 4); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateIntsVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add(dataPtr, sizeInBytes); return builder.EndVector(); } + public static void StartIntsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddLongs(FlatBufferBuilder builder, VectorOffset longsOffset) { builder.AddOffset(3, longsOffset.Value, 0); } + public static VectorOffset CreateLongsVector(FlatBufferBuilder builder, long[] data) { builder.StartVector(8, data.Length, 8); for (int i = data.Length - 1; i >= 0; i--) builder.AddLong(data[i]); return builder.EndVector(); } + public static VectorOffset CreateLongsVectorBlock(FlatBufferBuilder builder, long[] data) { builder.StartVector(8, data.Length, 8); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateLongsVectorBlock(FlatBufferBuilder builder, ArraySegment data) { builder.StartVector(8, data.Count, 8); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateLongsVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add(dataPtr, sizeInBytes); return builder.EndVector(); } + public static void StartLongsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddFloats(FlatBufferBuilder builder, VectorOffset floatsOffset) { builder.AddOffset(4, floatsOffset.Value, 0); } + public static VectorOffset CreateFloatsVector(FlatBufferBuilder builder, float[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddFloat(data[i]); return builder.EndVector(); } + public static VectorOffset CreateFloatsVectorBlock(FlatBufferBuilder builder, float[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateFloatsVectorBlock(FlatBufferBuilder builder, ArraySegment data) { builder.StartVector(4, data.Count, 4); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateFloatsVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add(dataPtr, sizeInBytes); return builder.EndVector(); } + public static void StartFloatsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddDoubles(FlatBufferBuilder builder, VectorOffset doublesOffset) { builder.AddOffset(5, doublesOffset.Value, 0); } + public static VectorOffset CreateDoublesVector(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); for (int i = data.Length - 1; i >= 0; i--) builder.AddDouble(data[i]); return builder.EndVector(); } + public static VectorOffset CreateDoublesVectorBlock(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateDoublesVectorBlock(FlatBufferBuilder builder, ArraySegment data) { builder.StartVector(8, data.Count, 8); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateDoublesVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add(dataPtr, sizeInBytes); return builder.EndVector(); } + public static void StartDoublesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddStrings(FlatBufferBuilder builder, VectorOffset stringsOffset) { builder.AddOffset(6, stringsOffset.Value, 0); } + public static VectorOffset CreateStringsVector(FlatBufferBuilder builder, StringOffset[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); } + public static VectorOffset CreateStringsVectorBlock(FlatBufferBuilder builder, StringOffset[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateStringsVectorBlock(FlatBufferBuilder builder, ArraySegment data) { builder.StartVector(4, data.Count, 4); builder.Add(data); return builder.EndVector(); } + public static VectorOffset CreateStringsVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add(dataPtr, sizeInBytes); return builder.EndVector(); } + public static void StartStringsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static Offset EndVectorContainer(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public VectorContainerT UnPack() { + var _o = new VectorContainerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(VectorContainerT _o) { + _o.Bytes = new List(); + for (var _j = 0; _j < this.BytesLength; ++_j) {_o.Bytes.Add(this.Bytes(_j));} + _o.Shorts = new List(); + for (var _j = 0; _j < this.ShortsLength; ++_j) {_o.Shorts.Add(this.Shorts(_j));} + _o.Ints = new List(); + for (var _j = 0; _j < this.IntsLength; ++_j) {_o.Ints.Add(this.Ints(_j));} + _o.Longs = new List(); + for (var _j = 0; _j < this.LongsLength; ++_j) {_o.Longs.Add(this.Longs(_j));} + _o.Floats = new List(); + for (var _j = 0; _j < this.FloatsLength; ++_j) {_o.Floats.Add(this.Floats(_j));} + _o.Doubles = new List(); + for (var _j = 0; _j < this.DoublesLength; ++_j) {_o.Doubles.Add(this.Doubles(_j));} + _o.Strings = new List(); + for (var _j = 0; _j < this.StringsLength; ++_j) {_o.Strings.Add(this.Strings(_j));} + } + public static Offset Pack(FlatBufferBuilder builder, VectorContainerT _o) { + if (_o == null) return default(Offset); + var _bytes = default(VectorOffset); + if (_o.Bytes != null) { + var __bytes = _o.Bytes.ToArray(); + _bytes = CreateBytesVector(builder, __bytes); + } + var _shorts = default(VectorOffset); + if (_o.Shorts != null) { + var __shorts = _o.Shorts.ToArray(); + _shorts = CreateShortsVector(builder, __shorts); + } + var _ints = default(VectorOffset); + if (_o.Ints != null) { + var __ints = _o.Ints.ToArray(); + _ints = CreateIntsVector(builder, __ints); + } + var _longs = default(VectorOffset); + if (_o.Longs != null) { + var __longs = _o.Longs.ToArray(); + _longs = CreateLongsVector(builder, __longs); + } + var _floats = default(VectorOffset); + if (_o.Floats != null) { + var __floats = _o.Floats.ToArray(); + _floats = CreateFloatsVector(builder, __floats); + } + var _doubles = default(VectorOffset); + if (_o.Doubles != null) { + var __doubles = _o.Doubles.ToArray(); + _doubles = CreateDoublesVector(builder, __doubles); + } + var _strings = default(VectorOffset); + if (_o.Strings != null) { + var __strings = new StringOffset[_o.Strings.Count]; + for (var _j = 0; _j < __strings.Length; ++_j) { __strings[_j] = builder.CreateString(_o.Strings[_j]); } + _strings = CreateStringsVector(builder, __strings); + } + return CreateVectorContainer( + builder, + _bytes, + _shorts, + _ints, + _longs, + _floats, + _doubles, + _strings); + } +} + +public class VectorContainerT +{ + public List Bytes { get; set; } + public List Shorts { get; set; } + public List Ints { get; set; } + public List Longs { get; set; } + public List Floats { get; set; } + public List Doubles { get; set; } + public List Strings { get; set; } + + public VectorContainerT() { + this.Bytes = null; + this.Shorts = null; + this.Ints = null; + this.Longs = null; + this.Floats = null; + this.Doubles = null; + this.Strings = null; + } +} + + +static public class VectorContainerVerify +{ + static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyVectorOfData(tablePos, 4 /*Bytes*/, 1 /*byte*/, false) + && verifier.VerifyVectorOfData(tablePos, 6 /*Shorts*/, 2 /*short*/, false) + && verifier.VerifyVectorOfData(tablePos, 8 /*Ints*/, 4 /*int*/, false) + && verifier.VerifyVectorOfData(tablePos, 10 /*Longs*/, 8 /*long*/, false) + && verifier.VerifyVectorOfData(tablePos, 12 /*Floats*/, 4 /*float*/, false) + && verifier.VerifyVectorOfData(tablePos, 14 /*Doubles*/, 8 /*double*/, false) + && verifier.VerifyVectorOfStrings(tablePos, 16 /*Strings*/, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.Benchmarks/Program.cs b/net/FlatSpanBuffers.Benchmarks/Program.cs new file mode 100644 index 00000000000..f1d079782fb --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/Program.cs @@ -0,0 +1,76 @@ +// Copyright 2014 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; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using BenchmarkDotNet.Environments; +using BenchmarkDotNet.Exporters; +using BenchmarkDotNet.Loggers; +using BenchmarkDotNet.Reports; +using BenchmarkDotNet.Running; + +namespace FlatSpanBuffers.Benchmarks; + +public static class Program +{ + public static void Main(string[] args) + { + List results = + [ + BenchmarkRunner.Run(), + BenchmarkRunner.Run(), + BenchmarkRunner.Run(), + BenchmarkRunner.Run(), + BenchmarkRunner.Run(), + BenchmarkRunner.Run(), + ]; + + if (results.Count == 0) + return; + + var logger = ConsoleLogger.Default; + + Console.WriteLine(); + logger.WriteLine(LogKind.Header, @"// * Final Summary *"); + Console.WriteLine(); + + logger.WriteLine(LogKind.Default, "```"); + logger.WriteLine(LogKind.Info, HostEnvironmentInfo.GetInformation()); + foreach (var summary in results) + { + logger.WriteLine(LogKind.Header, $"{summary.Title}"); + PrintTableViaReflection(summary, logger, MarkdownExporter.Console); + Console.WriteLine(); + } + logger.WriteLine(LogKind.Default, "```"); + } + + private static void PrintTableViaReflection(Summary summary, ILogger logger, IExporter exporter) + { + var exporterType = exporter.GetType(); + var printTableMethod = exporterType.GetMethod( + "PrintTable", + BindingFlags.NonPublic | BindingFlags.Instance, null, + new[] { typeof(SummaryTable), typeof(ILogger) }, null); + + if (printTableMethod == null) + { + logger.WriteLine(LogKind.Error, "Could not find PrintTable method via reflection"); + } + + printTableMethod.Invoke(exporter, new object[] { summary.Table, logger }); + } +} diff --git a/net/FlatSpanBuffers.Benchmarks/fbs/benchmark.fbs b/net/FlatSpanBuffers.Benchmarks/fbs/benchmark.fbs new file mode 100644 index 00000000000..7fd167acc5b --- /dev/null +++ b/net/FlatSpanBuffers.Benchmarks/fbs/benchmark.fbs @@ -0,0 +1,59 @@ +// Benchmark schema for FlatBuffers performance testing +// Based on the C++ bench.fbs schema. + +namespace Benchmarks.FlatSpanBuffers; + +enum Fruit : short { Apples = 0, Pears, Bananas } + +struct Foo { + id:ulong; + count:short; + prefix:byte; + length:uint; +} + +struct Bar { + parent:Foo; + time:int; + ratio:float; + size:ushort; +} + +table FooBar { + sibling:Bar; + name:string; + rating:double; + postfix:ubyte; +} + +table FooBarContainer { + list:[FooBar]; + initialized:bool; + fruit:Fruit; + location:string; +} + +// Simple monster for basic tests +table SimpleMonster { + name:string; + hp:short = 100; + mana:short = 150; + color:ubyte = 2; + testbool:bool = false; + testf:float = 3.14159; + testf2:float = 3.0; + testf3:float = 0.0; +} + +// A table with various vector types for vector access benchmarks +table VectorContainer { + bytes:[ubyte]; + shorts:[short]; + ints:[int]; + longs:[long]; + floats:[float]; + doubles:[double]; + strings:[string]; +} + +root_type FooBarContainer; diff --git a/net/FlatSpanBuffers.GeneratedCode/FlatSpanBuffers.GeneratedCode.csproj b/net/FlatSpanBuffers.GeneratedCode/FlatSpanBuffers.GeneratedCode.csproj new file mode 100644 index 00000000000..572acfe682d --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/FlatSpanBuffers.GeneratedCode.csproj @@ -0,0 +1,31 @@ + + + + net10.0 + false + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/ArrayStruct.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/ArrayStruct.cs new file mode 100644 index 00000000000..e10da747970 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/ArrayStruct.cs @@ -0,0 +1,131 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct ArrayStruct : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public ArrayStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public float A { get { return __p.bb.Get(__p.bb_pos + 0); } } + public int B(int j) { return __p.bb.Get(__p.bb_pos + 4 + j * 4); } + public const int BLength = 15; + public ReadOnlySpan GetBBytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 4, 15); } + public sbyte C { get { return __p.bb.Get(__p.bb_pos + 64); } } + public MyGame.Example.NestedStruct D(int j) { return (new MyGame.Example.NestedStruct()).__assign(__p.bb_pos + 72 + j * 32, __p.bb); } + public int E { get { return __p.bb.Get(__p.bb_pos + 136); } } + public long F(int j) { return __p.bb.Get(__p.bb_pos + 144 + j * 8); } + public const int FLength = 2; + public ReadOnlySpan GetFBytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 144, 2); } + + public static Offset CreateArrayStruct(FlatBufferBuilder builder, float A, int[] B, sbyte C, int[,] d_A, MyGame.Example.TestEnum[] d_B, MyGame.Example.TestEnum[,] d_C, long[,] d_D, int E, long[] F) { + builder.Prep(8, 160); + for (int _idx0 = 2; _idx0 > 0; _idx0--) { + builder.Put(F[_idx0-1]); + } + builder.Pad(4); + builder.Put(E); + for (int _idx0 = 2; _idx0 > 0; _idx0--) { + builder.Prep(8, 32); + for (int _idx1 = 2; _idx1 > 0; _idx1--) { + builder.Put(d_D[_idx0-1,_idx1-1]); + } + builder.Pad(5); + for (int _idx1 = 2; _idx1 > 0; _idx1--) { + builder.Put((sbyte)d_C[_idx0-1,_idx1-1]); + } + builder.Put((sbyte)d_B[_idx0-1]); + for (int _idx1 = 2; _idx1 > 0; _idx1--) { + builder.Put(d_A[_idx0-1,_idx1-1]); + } + } + builder.Pad(7); + builder.Put(C); + for (int _idx0 = 15; _idx0 > 0; _idx0--) { + builder.Put(B[_idx0-1]); + } + builder.Put(A); + return new Offset(builder.Offset); + } + public ArrayStructT UnPack() { + var _o = new ArrayStructT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ArrayStructT _o) { + _o.A = this.A; + _o.B = new int[15]; + for (var _j = 0; _j < 15; ++_j) { _o.B[_j] = this.B(_j); } + _o.C = this.C; + _o.D = new MyGame.Example.NestedStructT[2]; + for (var _j = 0; _j < 2; ++_j) { _o.D[_j] = this.D(_j).UnPack(); } + _o.E = this.E; + _o.F = new long[2]; + for (var _j = 0; _j < 2; ++_j) { _o.F[_j] = this.F(_j); } + } + public static Offset Pack(FlatBufferBuilder builder, ArrayStructT _o) { + if (_o == null) return default(Offset); + var _b = _o.B; + var _d_a = new int[2,2]; + for (var idx0 = 0; idx0 < 2; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_d_a[idx0,idx1] = _o.D[idx0].A[idx1];}} + var _d_b = new MyGame.Example.TestEnum[2]; + for (var idx0 = 0; idx0 < 2; ++idx0) {_d_b[idx0] = _o.D[idx0].B;} + var _d_c = new MyGame.Example.TestEnum[2,2]; + for (var idx0 = 0; idx0 < 2; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_d_c[idx0,idx1] = _o.D[idx0].C[idx1];}} + var _d_d = new long[2,2]; + for (var idx0 = 0; idx0 < 2; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_d_d[idx0,idx1] = _o.D[idx0].D[idx1];}} + var _f = _o.F; + return CreateArrayStruct( + builder, + _o.A, + _b, + _o.C, + _d_a, + _d_b, + _d_c, + _d_d, + _o.E, + _f); + } +} + +public class ArrayStructT +{ + [System.Text.Json.Serialization.JsonPropertyName("a")] + public float A { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("b")] + public int[] B { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("c")] + public sbyte C { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("d")] + public MyGame.Example.NestedStructT[] D { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("e")] + public int E { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("f")] + public long[] F { get; set; } + + public ArrayStructT() { + this.A = 0.0f; + this.B = new int[15]; + this.C = 0; + this.D = new MyGame.Example.NestedStructT[2]; + this.E = 0; + this.F = new long[2]; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/ArrayTable.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/ArrayTable.cs new file mode 100644 index 00000000000..3cccdcc7191 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/ArrayTable.cs @@ -0,0 +1,96 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct ArrayTable : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb) { return GetRootAsArrayTable(_bb, new ArrayTable()); } + public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "ARRT"); } + public static bool VerifyArrayTable(ByteBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("ARRT", false, MyGame.Example.ArrayTableVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public ArrayTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Example.ArrayStruct? A { get { int o = __p.__offset(4); return o != 0 ? (MyGame.Example.ArrayStruct?)(new MyGame.Example.ArrayStruct()).__assign(o + __p.bb_pos, __p.bb) : null; } } + + public static void StartArrayTable(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddA(FlatBufferBuilder builder, Offset aOffset) { builder.AddStruct(0, aOffset, 0); } + public static Offset EndArrayTable(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishArrayTableBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "ARRT"); } + public static void FinishSizePrefixedArrayTableBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "ARRT"); } + public ArrayTableT UnPack() { + var _o = new ArrayTableT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ArrayTableT _o) { + if (this.A.HasValue) { + if (_o.A == null) _o.A = new MyGame.Example.ArrayStructT(); + this.A.Value.UnPackTo(_o.A); + } else { + _o.A = null; + } + } + public static Offset Pack(FlatBufferBuilder builder, ArrayTableT _o) { + if (_o == null) return default(Offset); + StartArrayTable(builder); + AddA(builder, MyGame.Example.ArrayStruct.Pack(builder, _o.A)); + return EndArrayTable(builder); + } +} + +public class ArrayTableT +{ + [System.Text.Json.Serialization.JsonPropertyName("a")] + public MyGame.Example.ArrayStructT A { get; set; } + + public ArrayTableT() { + this.A = new MyGame.Example.ArrayStructT(); + } + + private static readonly System.Text.Json.JsonSerializerOptions _jsonOptions = new System.Text.Json.JsonSerializerOptions { WriteIndented = true, NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals, Converters = { new System.Text.Json.Serialization.JsonStringEnumConverter() } }; + public static ArrayTableT DeserializeFromJson(string jsonText) { + return System.Text.Json.JsonSerializer.Deserialize(jsonText, _jsonOptions); + } + public string SerializeToJson() { + return System.Text.Json.JsonSerializer.Serialize(this, _jsonOptions); + } + public static ArrayTableT DeserializeFromBinary(byte[] fbBuffer) { + return ArrayTable.GetRootAsArrayTable(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + ArrayTable.FinishArrayTableBuffer(fbb, ArrayTable.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedSpan().ToArray(); + } +} + + +static public class ArrayTableVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*A*/, 160 /*MyGame.Example.ArrayStruct*/, 8, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/NestedStruct.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/NestedStruct.cs new file mode 100644 index 00000000000..33e7d4c2fc3 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/NestedStruct.cs @@ -0,0 +1,97 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct NestedStruct : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public NestedStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int A(int j) { return __p.bb.Get(__p.bb_pos + 0 + j * 4); } + public const int ALength = 2; + public ReadOnlySpan GetABytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 0, 2); } + public MyGame.Example.TestEnum B { get { return (MyGame.Example.TestEnum)__p.bb.Get(__p.bb_pos + 8); } } + public MyGame.Example.TestEnum C(int j) { return (MyGame.Example.TestEnum)__p.bb.Get(__p.bb_pos + 9 + j * 1); } + public const int CLength = 2; + public ReadOnlySpan GetCBytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 9, 2); } + public long D(int j) { return __p.bb.Get(__p.bb_pos + 16 + j * 8); } + public const int DLength = 2; + public ReadOnlySpan GetDBytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 16, 2); } + + public static Offset CreateNestedStruct(FlatBufferBuilder builder, int[] A, MyGame.Example.TestEnum B, MyGame.Example.TestEnum[] C, long[] D) { + builder.Prep(8, 32); + for (int _idx0 = 2; _idx0 > 0; _idx0--) { + builder.Put(D[_idx0-1]); + } + builder.Pad(5); + for (int _idx0 = 2; _idx0 > 0; _idx0--) { + builder.Put((sbyte)C[_idx0-1]); + } + builder.Put((sbyte)B); + for (int _idx0 = 2; _idx0 > 0; _idx0--) { + builder.Put(A[_idx0-1]); + } + return new Offset(builder.Offset); + } + public NestedStructT UnPack() { + var _o = new NestedStructT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(NestedStructT _o) { + _o.A = new int[2]; + for (var _j = 0; _j < 2; ++_j) { _o.A[_j] = this.A(_j); } + _o.B = this.B; + _o.C = new MyGame.Example.TestEnum[2]; + for (var _j = 0; _j < 2; ++_j) { _o.C[_j] = this.C(_j); } + _o.D = new long[2]; + for (var _j = 0; _j < 2; ++_j) { _o.D[_j] = this.D(_j); } + } + public static Offset Pack(FlatBufferBuilder builder, NestedStructT _o) { + if (_o == null) return default(Offset); + var _a = _o.A; + var _c = _o.C; + var _d = _o.D; + return CreateNestedStruct( + builder, + _a, + _o.B, + _c, + _d); + } +} + +public class NestedStructT +{ + [System.Text.Json.Serialization.JsonPropertyName("a")] + public int[] A { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("b")] + public MyGame.Example.TestEnum B { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("c")] + public MyGame.Example.TestEnum[] C { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("d")] + public long[] D { get; set; } + + public NestedStructT() { + this.A = new int[2]; + this.B = MyGame.Example.TestEnum.A; + this.C = new MyGame.Example.TestEnum[2]; + this.D = new long[2]; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/StackBuffer/ArrayStruct.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/StackBuffer/ArrayStruct.cs new file mode 100644 index 00000000000..6a5bf456e8b --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/StackBuffer/ArrayStruct.cs @@ -0,0 +1,106 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct ArrayStruct : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public ArrayStruct __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public float A { get { return __p.bb.Get(__p.bb_pos + 0); } } + public int B(int j) { return __p.bb.Get(__p.bb_pos + 4 + j * 4); } + public const int BLength = 15; + public ReadOnlySpan GetBBytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 4, 15); } + public sbyte C { get { return __p.bb.Get(__p.bb_pos + 64); } } + public MyGame.Example.StackBuffer.NestedStruct D(int j) { return (new MyGame.Example.StackBuffer.NestedStruct()).__assign(__p.bb_pos + 72 + j * 32, __p.bb); } + public int E { get { return __p.bb.Get(__p.bb_pos + 136); } } + public long F(int j) { return __p.bb.Get(__p.bb_pos + 144 + j * 8); } + public const int FLength = 2; + public ReadOnlySpan GetFBytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 144, 2); } + + public static Offset CreateArrayStruct(ref FlatSpanBufferBuilder builder, float A, int[] B, sbyte C, int[,] d_A, MyGame.Example.TestEnum[] d_B, MyGame.Example.TestEnum[,] d_C, long[,] d_D, int E, long[] F) { + builder.Prep(8, 160); + for (int _idx0 = 2; _idx0 > 0; _idx0--) { + builder.Put(F[_idx0-1]); + } + builder.Pad(4); + builder.Put(E); + for (int _idx0 = 2; _idx0 > 0; _idx0--) { + builder.Prep(8, 32); + for (int _idx1 = 2; _idx1 > 0; _idx1--) { + builder.Put(d_D[_idx0-1,_idx1-1]); + } + builder.Pad(5); + for (int _idx1 = 2; _idx1 > 0; _idx1--) { + builder.Put((sbyte)d_C[_idx0-1,_idx1-1]); + } + builder.Put((sbyte)d_B[_idx0-1]); + for (int _idx1 = 2; _idx1 > 0; _idx1--) { + builder.Put(d_A[_idx0-1,_idx1-1]); + } + } + builder.Pad(7); + builder.Put(C); + for (int _idx0 = 15; _idx0 > 0; _idx0--) { + builder.Put(B[_idx0-1]); + } + builder.Put(A); + return new Offset(builder.Offset); + } + public ArrayStructT UnPack() { + var _o = new ArrayStructT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ArrayStructT _o) { + _o.A = this.A; + _o.B = new int[15]; + for (var _j = 0; _j < 15; ++_j) { _o.B[_j] = this.B(_j); } + _o.C = this.C; + _o.D = new MyGame.Example.NestedStructT[2]; + for (var _j = 0; _j < 2; ++_j) { _o.D[_j] = this.D(_j).UnPack(); } + _o.E = this.E; + _o.F = new long[2]; + for (var _j = 0; _j < 2; ++_j) { _o.F[_j] = this.F(_j); } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, ArrayStructT _o) { + if (_o == null) return default(Offset); + var _b = _o.B; + var _d_a = new int[2,2]; + for (var idx0 = 0; idx0 < 2; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_d_a[idx0,idx1] = _o.D[idx0].A[idx1];}} + var _d_b = new MyGame.Example.TestEnum[2]; + for (var idx0 = 0; idx0 < 2; ++idx0) {_d_b[idx0] = _o.D[idx0].B;} + var _d_c = new MyGame.Example.TestEnum[2,2]; + for (var idx0 = 0; idx0 < 2; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_d_c[idx0,idx1] = _o.D[idx0].C[idx1];}} + var _d_d = new long[2,2]; + for (var idx0 = 0; idx0 < 2; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_d_d[idx0,idx1] = _o.D[idx0].D[idx1];}} + var _f = _o.F; + return CreateArrayStruct( + ref builder, + _o.A, + _b, + _o.C, + _d_a, + _d_b, + _d_c, + _d_d, + _o.E, + _f); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/StackBuffer/ArrayTable.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/StackBuffer/ArrayTable.cs new file mode 100644 index 00000000000..ddd9bc2ba13 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/StackBuffer/ArrayTable.cs @@ -0,0 +1,60 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct ArrayTable : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static ArrayTable GetRootAsArrayTable(ByteSpanBuffer _bb) { return GetRootAsArrayTable(_bb, new ArrayTable()); } + public static ArrayTable GetRootAsArrayTable(ByteSpanBuffer _bb, ArrayTable obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool ArrayTableBufferHasIdentifier(ByteSpanBuffer _bb) { return TableSpan.__has_identifier(_bb, "ARRT"); } + public static bool VerifyArrayTable(ByteSpanBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("ARRT", false, MyGame.Example.ArrayTableVerify.Verify); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public ArrayTable __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public RefStructNullable A { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable((new MyGame.Example.StackBuffer.ArrayStruct()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + + public static void StartArrayTable(ref FlatSpanBufferBuilder builder) { builder.StartTable(1); } + public static void AddA(ref FlatSpanBufferBuilder builder, Offset aOffset) { builder.AddStruct(0, aOffset, 0); } + public static Offset EndArrayTable(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishArrayTableBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "ARRT"); } + public static void FinishSizePrefixedArrayTableBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "ARRT"); } + public ArrayTableT UnPack() { + var _o = new ArrayTableT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ArrayTableT _o) { + if (this.A.HasValue) { + if (_o.A == null) _o.A = new MyGame.Example.ArrayStructT(); + this.A.Value.UnPackTo(_o.A); + } else { + _o.A = null; + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, ArrayTableT _o) { + if (_o == null) return default(Offset); + StartArrayTable(ref builder); + AddA(ref builder, MyGame.Example.StackBuffer.ArrayStruct.Pack(ref builder, _o.A)); + return EndArrayTable(ref builder); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/StackBuffer/NestedStruct.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/StackBuffer/NestedStruct.cs new file mode 100644 index 00000000000..67076cc7aa7 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/StackBuffer/NestedStruct.cs @@ -0,0 +1,78 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct NestedStruct : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public NestedStruct __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int A(int j) { return __p.bb.Get(__p.bb_pos + 0 + j * 4); } + public const int ALength = 2; + public ReadOnlySpan GetABytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 0, 2); } + public MyGame.Example.TestEnum B { get { return (MyGame.Example.TestEnum)__p.bb.Get(__p.bb_pos + 8); } } + public MyGame.Example.TestEnum C(int j) { return (MyGame.Example.TestEnum)__p.bb.Get(__p.bb_pos + 9 + j * 1); } + public const int CLength = 2; + public ReadOnlySpan GetCBytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 9, 2); } + public long D(int j) { return __p.bb.Get(__p.bb_pos + 16 + j * 8); } + public const int DLength = 2; + public ReadOnlySpan GetDBytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 16, 2); } + + public static Offset CreateNestedStruct(ref FlatSpanBufferBuilder builder, int[] A, MyGame.Example.TestEnum B, MyGame.Example.TestEnum[] C, long[] D) { + builder.Prep(8, 32); + for (int _idx0 = 2; _idx0 > 0; _idx0--) { + builder.Put(D[_idx0-1]); + } + builder.Pad(5); + for (int _idx0 = 2; _idx0 > 0; _idx0--) { + builder.Put((sbyte)C[_idx0-1]); + } + builder.Put((sbyte)B); + for (int _idx0 = 2; _idx0 > 0; _idx0--) { + builder.Put(A[_idx0-1]); + } + return new Offset(builder.Offset); + } + public NestedStructT UnPack() { + var _o = new NestedStructT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(NestedStructT _o) { + _o.A = new int[2]; + for (var _j = 0; _j < 2; ++_j) { _o.A[_j] = this.A(_j); } + _o.B = this.B; + _o.C = new MyGame.Example.TestEnum[2]; + for (var _j = 0; _j < 2; ++_j) { _o.C[_j] = this.C(_j); } + _o.D = new long[2]; + for (var _j = 0; _j < 2; ++_j) { _o.D[_j] = this.D(_j); } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, NestedStructT _o) { + if (_o == null) return default(Offset); + var _a = _o.A; + var _c = _o.C; + var _d = _o.D; + return CreateNestedStruct( + ref builder, + _a, + _o.B, + _c, + _d); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/TestEnum.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/TestEnum.cs new file mode 100644 index 00000000000..9668306368d --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/arrays_test/MyGame/Example/TestEnum.cs @@ -0,0 +1,17 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +public enum TestEnum : sbyte +{ + A = 0, + B = 1, + C = 2, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Armor.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Armor.cs new file mode 100644 index 00000000000..4db9deb4b69 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Armor.cs @@ -0,0 +1,112 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Armor : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Armor GetRootAsArmor(ByteBuffer _bb) { return GetRootAsArmor(_bb, new Armor()); } + public static Armor GetRootAsArmor(ByteBuffer _bb, Armor obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Armor __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public int Defense { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)5; } } + public float Weight { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)1.0f; } } + public ComprehensiveTest.Transform? Transform { get { int o = __p.__offset(10); return o != 0 ? (ComprehensiveTest.Transform?)(new ComprehensiveTest.Transform()).__assign(o + __p.bb_pos, __p.bb) : null; } } + + public static Offset CreateArmor(FlatBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + int defense = 5, + float weight = 1.0f, + ComprehensiveTest.TransformT transform = null) { + builder.StartTable(4); + Armor.AddTransform(builder, ComprehensiveTest.Transform.Pack(builder, transform)); + Armor.AddWeight(builder, weight); + Armor.AddDefense(builder, defense); + Armor.AddName(builder, nameOffset); + return Armor.EndArmor(builder); + } + + public static void StartArmor(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddDefense(FlatBufferBuilder builder, int defense) { builder.Add(1, defense, 5); } + public static void AddWeight(FlatBufferBuilder builder, float weight) { builder.Add(2, weight, 1.0f); } + public static void AddTransform(FlatBufferBuilder builder, Offset transformOffset) { builder.AddStruct(3, transformOffset, 0); } + public static Offset EndArmor(FlatBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 4); // name + return new Offset(o); + } + public ArmorT UnPack() { + var _o = new ArmorT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ArmorT _o) { + _o.Name = this.Name; + _o.Defense = this.Defense; + _o.Weight = this.Weight; + if (this.Transform.HasValue) { + if (_o.Transform == null) _o.Transform = new ComprehensiveTest.TransformT(); + this.Transform.Value.UnPackTo(_o.Transform); + } else { + _o.Transform = null; + } + } + public static Offset Pack(FlatBufferBuilder builder, ArmorT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateArmor( + builder, + _name, + _o.Defense, + _o.Weight, + _o.Transform); + } +} + +public class ArmorT +{ + public string Name { get; set; } + public int Defense { get; set; } + public float Weight { get; set; } + public ComprehensiveTest.TransformT Transform { get; set; } + + public ArmorT() { + this.Name = null; + this.Defense = 5; + this.Weight = 1.0f; + this.Transform = new ComprehensiveTest.TransformT(); + } +} + + +static public class ArmorVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*Name*/, true) + && verifier.VerifyField(tablePos, 6 /*Defense*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 8 /*Weight*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 10 /*Transform*/, 36 /*ComprehensiveTest.Transform*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Color.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Color.cs new file mode 100644 index 00000000000..d4d5412bdc4 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Color.cs @@ -0,0 +1,16 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +public enum Color : sbyte +{ + Red = 0, + Green = 1, + Blue = 2, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Equipment.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Equipment.cs new file mode 100644 index 00000000000..c6eed60e2d8 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Equipment.cs @@ -0,0 +1,69 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +public enum Equipment : byte +{ + NONE = 0, + Weapon = 1, + Armor = 2, +}; + +public class EquipmentUnion { + public Equipment Type { get; set; } + public object Value { get; set; } + + public EquipmentUnion() { + this.Type = Equipment.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public ComprehensiveTest.WeaponT AsWeapon() { return this.As(); } + public static EquipmentUnion FromWeapon(ComprehensiveTest.WeaponT _weapon) { return new EquipmentUnion{ Type = Equipment.Weapon, Value = _weapon }; } + public ComprehensiveTest.ArmorT AsArmor() { return this.As(); } + public static EquipmentUnion FromArmor(ComprehensiveTest.ArmorT _armor) { return new EquipmentUnion{ Type = Equipment.Armor, Value = _armor }; } + + public static int Pack(Google.FlatSpanBuffers.FlatBufferBuilder builder, EquipmentUnion _o) { + switch (_o.Type) { + default: return 0; + case Equipment.Weapon: return ComprehensiveTest.Weapon.Pack(builder, _o.AsWeapon()).Value; + case Equipment.Armor: return ComprehensiveTest.Armor.Pack(builder, _o.AsArmor()).Value; + } + } + public static int Pack(ref Google.FlatSpanBuffers.FlatSpanBufferBuilder builder, EquipmentUnion _o) { + switch (_o.Type) { + default: return 0; + case Equipment.Weapon: return ComprehensiveTest.StackBuffer.Weapon.Pack(ref builder, _o.AsWeapon()).Value; + case Equipment.Armor: return ComprehensiveTest.StackBuffer.Armor.Pack(ref builder, _o.AsArmor()).Value; + } + } +} + + + +static public class EquipmentVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, byte typeId, uint tablePos) + { + bool result = true; + switch((Equipment)typeId) + { + case Equipment.Weapon: + result = ComprehensiveTest.WeaponVerify.Verify(ref verifier, tablePos); + break; + case Equipment.Armor: + result = ComprehensiveTest.ArmorVerify.Verify(ref verifier, tablePos); + break; + default: result = true; + break; + } + return result; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/FixedStats.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/FixedStats.cs new file mode 100644 index 00000000000..706ef875f81 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/FixedStats.cs @@ -0,0 +1,62 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct FixedStats : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public FixedStats __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int Values(int j) { return __p.bb.Get(__p.bb_pos + 0 + j * 4); } + public const int ValuesLength = 4; + public ReadOnlySpan GetValuesBytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 0, 4); } + + public static Offset CreateFixedStats(FlatBufferBuilder builder, int[] Values) { + builder.Prep(4, 16); + for (int _idx0 = 4; _idx0 > 0; _idx0--) { + builder.Put(Values[_idx0-1]); + } + return new Offset(builder.Offset); + } + public FixedStatsT UnPack() { + var _o = new FixedStatsT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FixedStatsT _o) { + _o.Values = new int[4]; + for (var _j = 0; _j < 4; ++_j) { _o.Values[_j] = this.Values(_j); } + } + public static Offset Pack(FlatBufferBuilder builder, FixedStatsT _o) { + if (_o == null) return default(Offset); + var _values = _o.Values; + return CreateFixedStats( + builder, + _values); + } +} + +public class FixedStatsT +{ + public int[] Values { get; set; } + + public FixedStatsT() { + this.Values = new int[4]; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/GameSession.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/GameSession.cs new file mode 100644 index 00000000000..8bf3054e484 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/GameSession.cs @@ -0,0 +1,150 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct GameSession : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static GameSession GetRootAsGameSession(ByteBuffer _bb) { return GetRootAsGameSession(_bb, new GameSession()); } + public static GameSession GetRootAsGameSession(ByteBuffer _bb, GameSession obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool GameSessionBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "TEST"); } + public static bool VerifyGameSession(ByteBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("TEST", false, ComprehensiveTest.GameSessionVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public GameSession __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string SessionId { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetSessionIdBytes() { return __p.__vector_as_span(4); } + public int PlayerCount { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public long StartTime { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public TableVector? Players { get { int o = __p.__offset(12); return o != 0 ? new TableVector(__p, o, 4) : null; } } + public bool TryGetPlayersByKey(int key, out ComprehensiveTest.Player value) { int o = __p.__offset(12); if (o != 0) { return ComprehensiveTest.Player.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + + public static Offset CreateGameSession(FlatBufferBuilder builder, + StringOffset session_idOffset = default(StringOffset), + int player_count = 0, + long start_time = 0, + VectorOffset playersOffset = default(VectorOffset)) { + builder.StartTable(5); + GameSession.AddStartTime(builder, start_time); + GameSession.AddPlayers(builder, playersOffset); + GameSession.AddPlayerCount(builder, player_count); + GameSession.AddSessionId(builder, session_idOffset); + return GameSession.EndGameSession(builder); + } + + public static void StartGameSession(FlatBufferBuilder builder) { builder.StartTable(5); } + public static void AddSessionId(FlatBufferBuilder builder, StringOffset sessionIdOffset) { builder.AddOffset(0, sessionIdOffset, 0); } + public static void AddPlayerCount(FlatBufferBuilder builder, int playerCount) { builder.Add(1, playerCount, 0); } + public static void AddStartTime(FlatBufferBuilder builder, long startTime) { builder.Add(2, startTime, 0); } + public static void AddPlayers(FlatBufferBuilder builder, VectorOffset playersOffset) { builder.AddOffset(4, playersOffset, 0); } + public static VectorOffset CreatePlayersVectorBlock(FlatBufferBuilder builder, Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreatePlayersVector(FlatBufferBuilder builder, Span> data) { return CreatePlayersVectorBlock(builder, data); } + public static void StartPlayersVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static Offset EndGameSession(FlatBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 4); // session_id + return new Offset(o); + } + public static void FinishGameSessionBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "TEST"); } + public static void FinishSizePrefixedGameSessionBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "TEST"); } + public GameSessionT UnPack() { + var _o = new GameSessionT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(GameSessionT _o) { + _o.SessionId = this.SessionId; + _o.PlayerCount = this.PlayerCount; + _o.StartTime = this.StartTime; + var _players_vec = this.Players; + var _players_len = _players_vec.HasValue ? _players_vec.Value.Length : 0; + if (_o.Players == null) { + _o.Players = new List(_players_len); + } + ObjectApiUtil.ResizeList(_o.Players, _players_len); + if (_players_vec.HasValue) { + var _players_value = _players_vec.Value; + for (var _j = 0; _j < _players_len; ++_j) { + var _src = _players_value[_j]; + if (_o.Players[_j] == null) { _o.Players[_j] = new PlayerT(); } + _src.UnPackTo(_o.Players[_j]); + } + } + } + public static Offset Pack(FlatBufferBuilder builder, GameSessionT _o) { + if (_o == null) return default(Offset); + var _session_id = _o.SessionId == null ? default(StringOffset) : builder.CreateString(_o.SessionId); + var _players = default(VectorOffset); + if (_o.Players != null) { + var _players_len = _o.Players.Count; + Offset[] _players_arr = null; + try { + Span> __players = _players_len <= 64 + ? stackalloc Offset[_players_len] + : (_players_arr = ArrayPool>.Shared.Rent(_players_len)).AsSpan(0, _players_len); + for (var _j = 0; _j < _players_len; ++_j) { __players[_j] = ComprehensiveTest.Player.Pack(builder, _o.Players[_j]); } + _players = CreatePlayersVector(builder, __players); + } finally { + if (_players_arr != null) { ArrayPool>.Shared.Return(_players_arr); } + } + } + return CreateGameSession( + builder, + _session_id, + _o.PlayerCount, + _o.StartTime, + _players); + } +} + +public class GameSessionT +{ + public string SessionId { get; set; } + public int PlayerCount { get; set; } + public long StartTime { get; set; } + public List Players { get; set; } + + public GameSessionT() { + this.SessionId = null; + this.PlayerCount = 0; + this.StartTime = 0; + this.Players = null; + } + public static GameSessionT DeserializeFromBinary(byte[] fbBuffer) { + return GameSession.GetRootAsGameSession(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + GameSession.FinishGameSessionBuffer(fbb, GameSession.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedSpan().ToArray(); + } +} + + +static public class GameSessionVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*SessionId*/, true) + && verifier.VerifyField(tablePos, 6 /*PlayerCount*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 8 /*StartTime*/, 8 /*long*/, 8, false) + && verifier.VerifyVectorOfTables(tablePos, 12 /*Players*/, ComprehensiveTest.PlayerVerify.Verify, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/NestedData.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/NestedData.cs new file mode 100644 index 00000000000..617c8ccdc5f --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/NestedData.cs @@ -0,0 +1,77 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct NestedData : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static NestedData GetRootAsNestedData(ByteBuffer _bb) { return GetRootAsNestedData(_bb, new NestedData()); } + public static NestedData GetRootAsNestedData(ByteBuffer _bb, NestedData obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public NestedData __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int Value { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateNestedData(FlatBufferBuilder builder, + int value = 0) { + builder.StartTable(1); + NestedData.AddValue(builder, value); + return NestedData.EndNestedData(builder); + } + + public static void StartNestedData(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddValue(FlatBufferBuilder builder, int value) { builder.Add(0, value, 0); } + public static Offset EndNestedData(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public NestedDataT UnPack() { + var _o = new NestedDataT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(NestedDataT _o) { + _o.Value = this.Value; + } + public static Offset Pack(FlatBufferBuilder builder, NestedDataT _o) { + if (_o == null) return default(Offset); + return CreateNestedData( + builder, + _o.Value); + } +} + +public class NestedDataT +{ + public int Value { get; set; } + + public NestedDataT() { + this.Value = 0; + } +} + + +static public class NestedDataVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Value*/, 4 /*int*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Player.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Player.cs new file mode 100644 index 00000000000..4a72f5b4cc5 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Player.cs @@ -0,0 +1,406 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Player : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Player GetRootAsPlayer(ByteBuffer _bb) { return GetRootAsPlayer(_bb, new Player()); } + public static Player GetRootAsPlayer(ByteBuffer _bb, Player obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Player __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(6); } + public int Level { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)1; } } + public long Experience { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public float Health { get { int o = __p.__offset(12); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)100.0f; } } + public float Mana { get { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)50.0f; } } + public RefStructNullable> InventoryType { get { int o = __p.__offset(16); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(16)) : default; } } + public UnionVector? Inventory { get { int o = __p.__offset(18); return o != 0 ? new UnionVector(__p, o, 4) : null; } } + public StringVector? Skills { get { int o = __p.__offset(20); return o != 0 ? new StringVector(__p, o) : null; } } + public RefStructNullable> Stats { get { int o = __p.__offset(22); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(22)) : default; } } + public ComprehensiveTest.Vec3? SpawnPoint { get { int o = __p.__offset(24); return o != 0 ? (ComprehensiveTest.Vec3?)(new ComprehensiveTest.Vec3()).__assign(o + __p.bb_pos, __p.bb) : null; } } + public ComprehensiveTest.Status Status { get { int o = __p.__offset(26); return o != 0 ? (ComprehensiveTest.Status)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Status.Pending; } } + public ComprehensiveTest.Equipment EquippedTypeType { get { int o = __p.__offset(28); return o != 0 ? (ComprehensiveTest.Equipment)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Equipment.NONE; } } + public TTable? EquippedType() where TTable : struct, IFlatbufferObject { int o = __p.__offset(30); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public ComprehensiveTest.Weapon EquippedTypeAsWeapon() { return EquippedType().Value; } + public ComprehensiveTest.Armor EquippedTypeAsArmor() { return EquippedType().Value; } + public ComprehensiveTest.Equipment EquippedItemType { get { int o = __p.__offset(32); return o != 0 ? (ComprehensiveTest.Equipment)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Equipment.NONE; } } + public TTable? EquippedItem() where TTable : struct, IFlatbufferObject { int o = __p.__offset(34); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public ComprehensiveTest.Weapon EquippedItemAsWeapon() { return EquippedItem().Value; } + public ComprehensiveTest.Armor EquippedItemAsArmor() { return EquippedItem().Value; } + + public static Offset CreatePlayer(FlatBufferBuilder builder, + int id = 0, + StringOffset nameOffset = default(StringOffset), + int level = 1, + long experience = 0, + float health = 100.0f, + float mana = 50.0f, + VectorOffset inventory_typeOffset = default(VectorOffset), + VectorOffset inventoryOffset = default(VectorOffset), + VectorOffset skillsOffset = default(VectorOffset), + VectorOffset statsOffset = default(VectorOffset), + ComprehensiveTest.Vec3T spawn_point = null, + ComprehensiveTest.Status status = ComprehensiveTest.Status.Pending, + ComprehensiveTest.Equipment equipped_type_type = ComprehensiveTest.Equipment.NONE, + int equipped_typeOffset = 0, + ComprehensiveTest.Equipment equipped_item_type = ComprehensiveTest.Equipment.NONE, + int equipped_itemOffset = 0) { + builder.StartTable(16); + Player.AddExperience(builder, experience); + Player.AddEquippedItem(builder, equipped_itemOffset); + Player.AddEquippedType(builder, equipped_typeOffset); + Player.AddStatus(builder, status); + Player.AddSpawnPoint(builder, ComprehensiveTest.Vec3.Pack(builder, spawn_point)); + Player.AddStats(builder, statsOffset); + Player.AddSkills(builder, skillsOffset); + Player.AddInventory(builder, inventoryOffset); + Player.AddInventoryType(builder, inventory_typeOffset); + Player.AddMana(builder, mana); + Player.AddHealth(builder, health); + Player.AddLevel(builder, level); + Player.AddName(builder, nameOffset); + Player.AddId(builder, id); + Player.AddEquippedItemType(builder, equipped_item_type); + Player.AddEquippedTypeType(builder, equipped_type_type); + return Player.EndPlayer(builder); + } + + public static void StartPlayer(FlatBufferBuilder builder) { builder.StartTable(16); } + public static void AddId(FlatBufferBuilder builder, int id) { builder.Add(0, id, 0); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset, 0); } + public static void AddLevel(FlatBufferBuilder builder, int level) { builder.Add(2, level, 1); } + public static void AddExperience(FlatBufferBuilder builder, long experience) { builder.Add(3, experience, 0); } + public static void AddHealth(FlatBufferBuilder builder, float health) { builder.Add(4, health, 100.0f); } + public static void AddMana(FlatBufferBuilder builder, float mana) { builder.Add(5, mana, 50.0f); } + public static void AddInventoryType(FlatBufferBuilder builder, VectorOffset inventoryTypeOffset) { builder.AddOffset(6, inventoryTypeOffset, 0); } + public static VectorOffset CreateInventoryTypeVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateInventoryTypeVector(FlatBufferBuilder builder, Span data) { return CreateInventoryTypeVectorBlock(builder, data); } + public static void StartInventoryTypeVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddInventory(FlatBufferBuilder builder, VectorOffset inventoryOffset) { builder.AddOffset(7, inventoryOffset, 0); } + public static VectorOffset CreateInventoryVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateInventoryVector(FlatBufferBuilder builder, Span data) { return CreateInventoryVectorBlock(builder, data); } + public static void StartInventoryVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddSkills(FlatBufferBuilder builder, VectorOffset skillsOffset) { builder.AddOffset(8, skillsOffset, 0); } + public static VectorOffset CreateSkillsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateSkillsVector(FlatBufferBuilder builder, Span data) { return CreateSkillsVectorBlock(builder, data); } + public static void StartSkillsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddStats(FlatBufferBuilder builder, VectorOffset statsOffset) { builder.AddOffset(9, statsOffset, 0); } + public static VectorOffset CreateStatsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateStatsVector(FlatBufferBuilder builder, Span data) { return CreateStatsVectorBlock(builder, data); } + public static void StartStatsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddSpawnPoint(FlatBufferBuilder builder, Offset spawnPointOffset) { builder.AddStruct(10, spawnPointOffset, 0); } + public static void AddStatus(FlatBufferBuilder builder, ComprehensiveTest.Status status) { builder.Add(11, (int)status, 0); } + public static void AddEquippedTypeType(FlatBufferBuilder builder, ComprehensiveTest.Equipment equippedTypeType) { builder.Add(12, (byte)equippedTypeType, 0); } + public static void AddEquippedType(FlatBufferBuilder builder, int equippedTypeOffset) { builder.AddOffset(13, equippedTypeOffset, 0); } + public static void AddEquippedItemType(FlatBufferBuilder builder, ComprehensiveTest.Equipment equippedItemType) { builder.Add(14, (byte)equippedItemType, 0); } + public static void AddEquippedItem(FlatBufferBuilder builder, int equippedItemOffset) { builder.AddOffset(15, equippedItemOffset, 0); } + public static Offset EndPlayer(FlatBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 6); // name + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfPlayer(FlatBufferBuilder builder, Span> offsets) { + var comparer = new SortedVectorUtils.ScalarOffsetComparer(builder.DataBuffer, 4); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, int key, ByteBuffer bb, out Player value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 4, 0, out value); + } + public PlayerT UnPack() { + var _o = new PlayerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(PlayerT _o) { + _o.Id = this.Id; + _o.Name = this.Name; + _o.Level = this.Level; + _o.Experience = this.Experience; + _o.Health = this.Health; + _o.Mana = this.Mana; + var _inventory_types = this.InventoryType; + var _inventory = this.Inventory; + var _inventory_len = _inventory.HasValue ? _inventory.Value.Length : 0; + if (_o.Inventory == null) { + _o.Inventory = new List(_inventory_len); + } + ObjectApiUtil.ResizeList(_o.Inventory, _inventory_len); + if (_inventory.HasValue) { + var _inventory_value = _inventory.Value; + var _inventory_types_value = _inventory_types.Value; + for (var _j = 0; _j < _inventory_len; ++_j) { + var _inventory_type = _inventory_types_value[_j]; + var _o_Inventory = _o.Inventory[_j]; + if (_o_Inventory == null) { + _o_Inventory = new ComprehensiveTest.EquipmentUnion(); + _o.Inventory[_j] = _o_Inventory; + } + var _inventory_old_type = _o_Inventory.Type; + _o_Inventory.Type = _inventory_type; + switch (_inventory_type) { + default: + _o_Inventory.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (_inventory_old_type == ComprehensiveTest.Equipment.Weapon) { + _inventory_value.GetAs(_j).UnPackTo((ComprehensiveTest.WeaponT)_o_Inventory.Value); + } else { + _o_Inventory.Value = _inventory_value.GetAs(_j).UnPack(); + } + break; + case ComprehensiveTest.Equipment.Armor: + if (_inventory_old_type == ComprehensiveTest.Equipment.Armor) { + _inventory_value.GetAs(_j).UnPackTo((ComprehensiveTest.ArmorT)_o_Inventory.Value); + } else { + _o_Inventory.Value = _inventory_value.GetAs(_j).UnPack(); + } + break; + } + } + } + var _skills_vec = this.Skills; + var _skills_len = _skills_vec.HasValue ? _skills_vec.Value.Length : 0; + if (_o.Skills == null) { + _o.Skills = new List(_skills_len); + } else { + _o.Skills.Clear(); + if (_o.Skills.Capacity < _skills_len) { + _o.Skills.Capacity = _skills_len; + } + } + if (_skills_vec.HasValue) { + var _skills_value = _skills_vec.Value; + for (var _j = 0; _j < _skills_len; ++_j) { _o.Skills.Add(_skills_value[_j]); } + } + var _stats_vec = this.Stats; + var _stats_len = _stats_vec.HasValue ? _stats_vec.Value.Length : 0; + if (_o.Stats == null) { + _o.Stats = new List(_stats_len); + } + ObjectApiUtil.ResizeList(_o.Stats, _stats_len); + if (_stats_vec.HasValue) { _stats_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Stats)); } + if (this.SpawnPoint.HasValue) { + if (_o.SpawnPoint == null) _o.SpawnPoint = new ComprehensiveTest.Vec3T(); + this.SpawnPoint.Value.UnPackTo(_o.SpawnPoint); + } else { + _o.SpawnPoint = null; + } + _o.Status = this.Status; + if (_o.EquippedType == null) { + _o.EquippedType = new ComprehensiveTest.EquipmentUnion(); + } + var _EquippedTypeOldType = _o.EquippedType.Type; + _o.EquippedType.Type = this.EquippedTypeType; + switch (this.EquippedTypeType) { + default: + _o.EquippedType.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (this.EquippedType().HasValue) { + if (_EquippedTypeOldType == ComprehensiveTest.Equipment.Weapon) { + this.EquippedType().Value.UnPackTo((ComprehensiveTest.WeaponT)_o.EquippedType.Value); + } else { + _o.EquippedType.Value = this.EquippedType().Value.UnPack(); + } + } else { + _o.EquippedType.Value = null; + } + break; + case ComprehensiveTest.Equipment.Armor: + if (this.EquippedType().HasValue) { + if (_EquippedTypeOldType == ComprehensiveTest.Equipment.Armor) { + this.EquippedType().Value.UnPackTo((ComprehensiveTest.ArmorT)_o.EquippedType.Value); + } else { + _o.EquippedType.Value = this.EquippedType().Value.UnPack(); + } + } else { + _o.EquippedType.Value = null; + } + break; + } + if (_o.EquippedItem == null) { + _o.EquippedItem = new ComprehensiveTest.EquipmentUnion(); + } + var _EquippedItemOldType = _o.EquippedItem.Type; + _o.EquippedItem.Type = this.EquippedItemType; + switch (this.EquippedItemType) { + default: + _o.EquippedItem.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (this.EquippedItem().HasValue) { + if (_EquippedItemOldType == ComprehensiveTest.Equipment.Weapon) { + this.EquippedItem().Value.UnPackTo((ComprehensiveTest.WeaponT)_o.EquippedItem.Value); + } else { + _o.EquippedItem.Value = this.EquippedItem().Value.UnPack(); + } + } else { + _o.EquippedItem.Value = null; + } + break; + case ComprehensiveTest.Equipment.Armor: + if (this.EquippedItem().HasValue) { + if (_EquippedItemOldType == ComprehensiveTest.Equipment.Armor) { + this.EquippedItem().Value.UnPackTo((ComprehensiveTest.ArmorT)_o.EquippedItem.Value); + } else { + _o.EquippedItem.Value = this.EquippedItem().Value.UnPack(); + } + } else { + _o.EquippedItem.Value = null; + } + break; + } + } + public static Offset Pack(FlatBufferBuilder builder, PlayerT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + var _inventory_type = default(VectorOffset); + if (_o.Inventory != null) { + var _inventory_type_len = _o.Inventory.Count; + ComprehensiveTest.Equipment[] _inventory_type_arr = null; + try { + Span __inventory_type = _inventory_type_len <= 256 + ? stackalloc ComprehensiveTest.Equipment[_inventory_type_len] + : (_inventory_type_arr = ArrayPool.Shared.Rent(_inventory_type_len)).AsSpan(0, _inventory_type_len); + for (var _j = 0; _j < _inventory_type_len; ++_j) { __inventory_type[_j] = _o.Inventory[_j].Type; } + _inventory_type = CreateInventoryTypeVector(builder, __inventory_type); + } finally { + if (_inventory_type_arr != null) { ArrayPool.Shared.Return(_inventory_type_arr); } + } + } + var _inventory = default(VectorOffset); + if (_o.Inventory != null) { + var _inventory_len = _o.Inventory.Count; + int[] _inventory_arr = null; + try { + Span __inventory = _inventory_len <= 64 + ? stackalloc int[_inventory_len] + : (_inventory_arr = ArrayPool.Shared.Rent(_inventory_len)).AsSpan(0, _inventory_len); + for (var _j = 0; _j < _inventory_len; ++_j) { __inventory[_j] = ComprehensiveTest.EquipmentUnion.Pack(builder, _o.Inventory[_j]); } + _inventory = CreateInventoryVector(builder, __inventory); + } finally { + if (_inventory_arr != null) { ArrayPool.Shared.Return(_inventory_arr); } + } + } + var _skills = default(VectorOffset); + if (_o.Skills != null) { + var _skills_len = _o.Skills.Count; + StringOffset[] _skills_arr = null; + try { + Span __skills = _skills_len <= 64 + ? stackalloc StringOffset[_skills_len] + : (_skills_arr = ArrayPool.Shared.Rent(_skills_len)).AsSpan(0, _skills_len); + for (var _j = 0; _j < _skills_len; ++_j) { __skills[_j] = builder.CreateString(_o.Skills[_j]); } + _skills = CreateSkillsVector(builder, __skills); + } finally { + if (_skills_arr != null) { ArrayPool.Shared.Return(_skills_arr); } + } + } + var _stats = default(VectorOffset); + if (_o.Stats != null) { + _stats = CreateStatsVector(builder, CollectionsMarshal.AsSpan(_o.Stats)); + } + var _equipped_type_type = _o.EquippedType == null ? ComprehensiveTest.Equipment.NONE : _o.EquippedType.Type; + var _equipped_type = _o.EquippedType == null ? 0 : ComprehensiveTest.EquipmentUnion.Pack(builder, _o.EquippedType); + var _equipped_item_type = _o.EquippedItem == null ? ComprehensiveTest.Equipment.NONE : _o.EquippedItem.Type; + var _equipped_item = _o.EquippedItem == null ? 0 : ComprehensiveTest.EquipmentUnion.Pack(builder, _o.EquippedItem); + return CreatePlayer( + builder, + _o.Id, + _name, + _o.Level, + _o.Experience, + _o.Health, + _o.Mana, + _inventory_type, + _inventory, + _skills, + _stats, + _o.SpawnPoint, + _o.Status, + _equipped_type_type, + _equipped_type, + _equipped_item_type, + _equipped_item); + } +} + +public class PlayerT +{ + public int Id { get; set; } + public string Name { get; set; } + public int Level { get; set; } + public long Experience { get; set; } + public float Health { get; set; } + public float Mana { get; set; } + public List Inventory { get; set; } + public List Skills { get; set; } + public List Stats { get; set; } + public ComprehensiveTest.Vec3T SpawnPoint { get; set; } + public ComprehensiveTest.Status Status { get; set; } + public ComprehensiveTest.EquipmentUnion EquippedType { get; set; } + public ComprehensiveTest.EquipmentUnion EquippedItem { get; set; } + + public PlayerT() { + this.Id = 0; + this.Name = null; + this.Level = 1; + this.Experience = 0; + this.Health = 100.0f; + this.Mana = 50.0f; + this.Inventory = null; + this.Skills = null; + this.Stats = null; + this.SpawnPoint = new ComprehensiveTest.Vec3T(); + this.Status = ComprehensiveTest.Status.Pending; + this.EquippedType = null; + this.EquippedItem = null; + } +} + + +static public class PlayerVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Id*/, 4 /*int*/, 4, false) + && verifier.VerifyString(tablePos, 6 /*Name*/, true) + && verifier.VerifyField(tablePos, 8 /*Level*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 10 /*Experience*/, 8 /*long*/, 8, false) + && verifier.VerifyField(tablePos, 12 /*Health*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 14 /*Mana*/, 4 /*float*/, 4, false) + && verifier.VerifyVectorOfData(tablePos, 16 /*InventoryType*/, 1 /*ComprehensiveTest.Equipment*/, false) + && verifier.VerifyVectorOfStrings(tablePos, 20 /*Skills*/, false) + && verifier.VerifyVectorOfData(tablePos, 22 /*Stats*/, 4 /*int*/, false) + && verifier.VerifyField(tablePos, 24 /*SpawnPoint*/, 12 /*ComprehensiveTest.Vec3*/, 4, false) + && verifier.VerifyField(tablePos, 26 /*Status*/, 4 /*ComprehensiveTest.Status*/, 4, false) + && verifier.VerifyField(tablePos, 28 /*EquippedTypeType*/, 1 /*ComprehensiveTest.Equipment*/, 1, false) + && verifier.VerifyUnion(tablePos, 28, 30 /*EquippedType*/, ComprehensiveTest.EquipmentVerify.Verify, false) + && verifier.VerifyField(tablePos, 32 /*EquippedItemType*/, 1 /*ComprehensiveTest.Equipment*/, 1, false) + && verifier.VerifyUnion(tablePos, 32, 34 /*EquippedItem*/, ComprehensiveTest.EquipmentVerify.Verify, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/PositionHistory.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/PositionHistory.cs new file mode 100644 index 00000000000..045dc2f57b8 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/PositionHistory.cs @@ -0,0 +1,70 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct PositionHistory : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public PositionHistory __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ComprehensiveTest.Vec3 Positions(int j) { return (new ComprehensiveTest.Vec3()).__assign(__p.bb_pos + 0 + j * 12, __p.bb); } + + public static Offset CreatePositionHistory(FlatBufferBuilder builder, float[] positions_X, float[] positions_Y, float[] positions_Z) { + builder.Prep(4, 120); + for (int _idx0 = 10; _idx0 > 0; _idx0--) { + builder.Prep(4, 12); + builder.Put(positions_Z[_idx0-1]); + builder.Put(positions_Y[_idx0-1]); + builder.Put(positions_X[_idx0-1]); + } + return new Offset(builder.Offset); + } + public PositionHistoryT UnPack() { + var _o = new PositionHistoryT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(PositionHistoryT _o) { + _o.Positions = new ComprehensiveTest.Vec3T[10]; + for (var _j = 0; _j < 10; ++_j) { _o.Positions[_j] = this.Positions(_j).UnPack(); } + } + public static Offset Pack(FlatBufferBuilder builder, PositionHistoryT _o) { + if (_o == null) return default(Offset); + var _positions_x = new float[10]; + for (var idx0 = 0; idx0 < 10; ++idx0) {_positions_x[idx0] = _o.Positions[idx0].X;} + var _positions_y = new float[10]; + for (var idx0 = 0; idx0 < 10; ++idx0) {_positions_y[idx0] = _o.Positions[idx0].Y;} + var _positions_z = new float[10]; + for (var idx0 = 0; idx0 < 10; ++idx0) {_positions_z[idx0] = _o.Positions[idx0].Z;} + return CreatePositionHistory( + builder, + _positions_x, + _positions_y, + _positions_z); + } +} + +public class PositionHistoryT +{ + public ComprehensiveTest.Vec3T[] Positions { get; set; } + + public PositionHistoryT() { + this.Positions = new ComprehensiveTest.Vec3T[10]; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Armor.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Armor.cs new file mode 100644 index 00000000000..ee681cc6c6d --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Armor.cs @@ -0,0 +1,71 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Armor : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Armor GetRootAsArmor(ByteSpanBuffer _bb) { return GetRootAsArmor(_bb, new Armor()); } + public static Armor GetRootAsArmor(ByteSpanBuffer _bb, Armor obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Armor __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public int Defense { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)5; } } + public float Weight { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)1.0f; } } + public RefStructNullable Transform { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable((new ComprehensiveTest.StackBuffer.Transform()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + + public static void StartArmor(ref FlatSpanBufferBuilder builder) { builder.StartTable(4); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddDefense(ref FlatSpanBufferBuilder builder, int defense) { builder.Add(1, defense, 5); } + public static void AddWeight(ref FlatSpanBufferBuilder builder, float weight) { builder.Add(2, weight, 1.0f); } + public static void AddTransform(ref FlatSpanBufferBuilder builder, Offset transformOffset) { builder.AddStruct(3, transformOffset, 0); } + public static Offset EndArmor(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 4); // name + return new Offset(o); + } + public ArmorT UnPack() { + var _o = new ArmorT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ArmorT _o) { + _o.Name = this.Name; + _o.Defense = this.Defense; + _o.Weight = this.Weight; + if (this.Transform.HasValue) { + if (_o.Transform == null) _o.Transform = new ComprehensiveTest.TransformT(); + this.Transform.Value.UnPackTo(_o.Transform); + } else { + _o.Transform = null; + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, ArmorT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + StartArmor(ref builder); + AddName(ref builder, _name); + AddDefense(ref builder, _o.Defense); + AddWeight(ref builder, _o.Weight); + AddTransform(ref builder, ComprehensiveTest.StackBuffer.Transform.Pack(ref builder, _o.Transform)); + return EndArmor(ref builder); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/FixedStats.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/FixedStats.cs new file mode 100644 index 00000000000..633821d921e --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/FixedStats.cs @@ -0,0 +1,53 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct FixedStats : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public FixedStats __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int Values(int j) { return __p.bb.Get(__p.bb_pos + 0 + j * 4); } + public const int ValuesLength = 4; + public ReadOnlySpan GetValuesBytes() { return __p.bb.GetReadOnlySpan(__p.bb_pos + 0, 4); } + + public static Offset CreateFixedStats(ref FlatSpanBufferBuilder builder, int[] Values) { + builder.Prep(4, 16); + for (int _idx0 = 4; _idx0 > 0; _idx0--) { + builder.Put(Values[_idx0-1]); + } + return new Offset(builder.Offset); + } + public FixedStatsT UnPack() { + var _o = new FixedStatsT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FixedStatsT _o) { + _o.Values = new int[4]; + for (var _j = 0; _j < 4; ++_j) { _o.Values[_j] = this.Values(_j); } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, FixedStatsT _o) { + if (_o == null) return default(Offset); + var _values = _o.Values; + return CreateFixedStats( + ref builder, + _values); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/GameSession.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/GameSession.cs new file mode 100644 index 00000000000..4860d8860b5 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/GameSession.cs @@ -0,0 +1,114 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct GameSession : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static GameSession GetRootAsGameSession(ByteSpanBuffer _bb) { return GetRootAsGameSession(_bb, new GameSession()); } + public static GameSession GetRootAsGameSession(ByteSpanBuffer _bb, GameSession obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool GameSessionBufferHasIdentifier(ByteSpanBuffer _bb) { return TableSpan.__has_identifier(_bb, "TEST"); } + public static bool VerifyGameSession(ByteSpanBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("TEST", false, ComprehensiveTest.GameSessionVerify.Verify); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public GameSession __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public string SessionId { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetSessionIdBytes() { return __p.__vector_as_span(4); } + public int PlayerCount { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public long StartTime { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public RefStructNullable> Players { get { int o = __p.__offset(12); return o != 0 ? new RefStructNullable>(new TableVectorSpan(__p, o, 4)) : default; } } + public bool TryGetPlayersByKey(int key, out ComprehensiveTest.StackBuffer.Player value) { int o = __p.__offset(12); if (o != 0) { return ComprehensiveTest.StackBuffer.Player.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + + public static Offset CreateGameSession(ref FlatSpanBufferBuilder builder, + StringOffset session_idOffset = default(StringOffset), + int player_count = 0, + long start_time = 0, + VectorOffset playersOffset = default(VectorOffset)) { + builder.StartTable(5); + GameSession.AddStartTime(ref builder, start_time); + GameSession.AddPlayers(ref builder, playersOffset); + GameSession.AddPlayerCount(ref builder, player_count); + GameSession.AddSessionId(ref builder, session_idOffset); + return GameSession.EndGameSession(ref builder); + } + + public static void StartGameSession(ref FlatSpanBufferBuilder builder) { builder.StartTable(5); } + public static void AddSessionId(ref FlatSpanBufferBuilder builder, StringOffset sessionIdOffset) { builder.AddOffset(0, sessionIdOffset, 0); } + public static void AddPlayerCount(ref FlatSpanBufferBuilder builder, int playerCount) { builder.Add(1, playerCount, 0); } + public static void AddStartTime(ref FlatSpanBufferBuilder builder, long startTime) { builder.Add(2, startTime, 0); } + public static void AddPlayers(ref FlatSpanBufferBuilder builder, VectorOffset playersOffset) { builder.AddOffset(4, playersOffset, 0); } + public static VectorOffset CreatePlayersVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreatePlayersVector(ref FlatSpanBufferBuilder builder, scoped Span> data) { return CreatePlayersVectorBlock(ref builder, data); } + public static void StartPlayersVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static Offset EndGameSession(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 4); // session_id + return new Offset(o); + } + public static void FinishGameSessionBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "TEST"); } + public static void FinishSizePrefixedGameSessionBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "TEST"); } + public GameSessionT UnPack() { + var _o = new GameSessionT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(GameSessionT _o) { + _o.SessionId = this.SessionId; + _o.PlayerCount = this.PlayerCount; + _o.StartTime = this.StartTime; + var _players_vec = this.Players; + var _players_len = _players_vec.HasValue ? _players_vec.Value.Length : 0; + if (_o.Players == null) { + _o.Players = new List(_players_len); + } + ObjectApiUtil.ResizeList(_o.Players, _players_len); + if (_players_vec.HasValue) { + var _players_value = _players_vec.Value; + for (var _j = 0; _j < _players_len; ++_j) { + var _src = _players_value[_j]; + if (_o.Players[_j] == null) { _o.Players[_j] = new PlayerT(); } + _src.UnPackTo(_o.Players[_j]); + } + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, GameSessionT _o) { + if (_o == null) return default(Offset); + var _session_id = _o.SessionId == null ? default(StringOffset) : builder.CreateString(_o.SessionId); + var _players = default(VectorOffset); + if (_o.Players != null) { + var _players_len = _o.Players.Count; + Offset[] _players_arr = null; + try { + Span> __players = _players_len <= 64 + ? stackalloc Offset[_players_len] + : (_players_arr = ArrayPool>.Shared.Rent(_players_len)).AsSpan(0, _players_len); + for (var _j = 0; _j < _players_len; ++_j) { __players[_j] = ComprehensiveTest.StackBuffer.Player.Pack(ref builder, _o.Players[_j]); } + _players = CreatePlayersVector(ref builder, __players); + } finally { + if (_players_arr != null) { ArrayPool>.Shared.Return(_players_arr); } + } + } + return CreateGameSession( + ref builder, + _session_id, + _o.PlayerCount, + _o.StartTime, + _players); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/NestedData.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/NestedData.cs new file mode 100644 index 00000000000..0e6e9f487ac --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/NestedData.cs @@ -0,0 +1,58 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct NestedData : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static NestedData GetRootAsNestedData(ByteSpanBuffer _bb) { return GetRootAsNestedData(_bb, new NestedData()); } + public static NestedData GetRootAsNestedData(ByteSpanBuffer _bb, NestedData obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public NestedData __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int Value { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateNestedData(ref FlatSpanBufferBuilder builder, + int value = 0) { + builder.StartTable(1); + NestedData.AddValue(ref builder, value); + return NestedData.EndNestedData(ref builder); + } + + public static void StartNestedData(ref FlatSpanBufferBuilder builder) { builder.StartTable(1); } + public static void AddValue(ref FlatSpanBufferBuilder builder, int value) { builder.Add(0, value, 0); } + public static Offset EndNestedData(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public NestedDataT UnPack() { + var _o = new NestedDataT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(NestedDataT _o) { + _o.Value = this.Value; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, NestedDataT _o) { + if (_o == null) return default(Offset); + return CreateNestedData( + ref builder, + _o.Value); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Player.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Player.cs new file mode 100644 index 00000000000..b15f9bd3f98 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Player.cs @@ -0,0 +1,312 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Player : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Player GetRootAsPlayer(ByteSpanBuffer _bb) { return GetRootAsPlayer(_bb, new Player()); } + public static Player GetRootAsPlayer(ByteSpanBuffer _bb, Player obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Player __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(6); } + public int Level { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)1; } } + public long Experience { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public float Health { get { int o = __p.__offset(12); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)100.0f; } } + public float Mana { get { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)50.0f; } } + public RefStructNullable> InventoryType { get { int o = __p.__offset(16); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(16)) : default; } } + public RefStructNullable Inventory { get { int o = __p.__offset(18); return o != 0 ? new RefStructNullable(new UnionVectorSpan(__p, o, 4)) : default; } } + public RefStructNullable Skills { get { int o = __p.__offset(20); return o != 0 ? new RefStructNullable(new StringVectorSpan(__p, o)) : default; } } + public RefStructNullable> Stats { get { int o = __p.__offset(22); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(22)) : default; } } + public RefStructNullable SpawnPoint { get { int o = __p.__offset(24); return o != 0 ? new RefStructNullable((new ComprehensiveTest.StackBuffer.Vec3()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + public ComprehensiveTest.Status Status { get { int o = __p.__offset(26); return o != 0 ? (ComprehensiveTest.Status)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Status.Pending; } } + public ComprehensiveTest.Equipment EquippedTypeType { get { int o = __p.__offset(28); return o != 0 ? (ComprehensiveTest.Equipment)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Equipment.NONE; } } + public RefStructNullable EquippedType() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(30); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public ComprehensiveTest.StackBuffer.Weapon EquippedTypeAsWeapon() { return EquippedType().Value; } + public ComprehensiveTest.StackBuffer.Armor EquippedTypeAsArmor() { return EquippedType().Value; } + public ComprehensiveTest.Equipment EquippedItemType { get { int o = __p.__offset(32); return o != 0 ? (ComprehensiveTest.Equipment)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Equipment.NONE; } } + public RefStructNullable EquippedItem() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(34); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public ComprehensiveTest.StackBuffer.Weapon EquippedItemAsWeapon() { return EquippedItem().Value; } + public ComprehensiveTest.StackBuffer.Armor EquippedItemAsArmor() { return EquippedItem().Value; } + + public static void StartPlayer(ref FlatSpanBufferBuilder builder) { builder.StartTable(16); } + public static void AddId(ref FlatSpanBufferBuilder builder, int id) { builder.Add(0, id, 0); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset, 0); } + public static void AddLevel(ref FlatSpanBufferBuilder builder, int level) { builder.Add(2, level, 1); } + public static void AddExperience(ref FlatSpanBufferBuilder builder, long experience) { builder.Add(3, experience, 0); } + public static void AddHealth(ref FlatSpanBufferBuilder builder, float health) { builder.Add(4, health, 100.0f); } + public static void AddMana(ref FlatSpanBufferBuilder builder, float mana) { builder.Add(5, mana, 50.0f); } + public static void AddInventoryType(ref FlatSpanBufferBuilder builder, VectorOffset inventoryTypeOffset) { builder.AddOffset(6, inventoryTypeOffset, 0); } + public static VectorOffset CreateInventoryTypeVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateInventoryTypeVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateInventoryTypeVectorBlock(ref builder, data); } + public static void StartInventoryTypeVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddInventory(ref FlatSpanBufferBuilder builder, VectorOffset inventoryOffset) { builder.AddOffset(7, inventoryOffset, 0); } + public static VectorOffset CreateInventoryVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateInventoryVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateInventoryVectorBlock(ref builder, data); } + public static void StartInventoryVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddSkills(ref FlatSpanBufferBuilder builder, VectorOffset skillsOffset) { builder.AddOffset(8, skillsOffset, 0); } + public static VectorOffset CreateSkillsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateSkillsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateSkillsVectorBlock(ref builder, data); } + public static void StartSkillsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddStats(ref FlatSpanBufferBuilder builder, VectorOffset statsOffset) { builder.AddOffset(9, statsOffset, 0); } + public static VectorOffset CreateStatsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateStatsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateStatsVectorBlock(ref builder, data); } + public static void StartStatsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddSpawnPoint(ref FlatSpanBufferBuilder builder, Offset spawnPointOffset) { builder.AddStruct(10, spawnPointOffset, 0); } + public static void AddStatus(ref FlatSpanBufferBuilder builder, ComprehensiveTest.Status status) { builder.Add(11, (int)status, 0); } + public static void AddEquippedTypeType(ref FlatSpanBufferBuilder builder, ComprehensiveTest.Equipment equippedTypeType) { builder.Add(12, (byte)equippedTypeType, 0); } + public static void AddEquippedType(ref FlatSpanBufferBuilder builder, int equippedTypeOffset) { builder.AddOffset(13, equippedTypeOffset, 0); } + public static void AddEquippedItemType(ref FlatSpanBufferBuilder builder, ComprehensiveTest.Equipment equippedItemType) { builder.Add(14, (byte)equippedItemType, 0); } + public static void AddEquippedItem(ref FlatSpanBufferBuilder builder, int equippedItemOffset) { builder.AddOffset(15, equippedItemOffset, 0); } + public static Offset EndPlayer(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 6); // name + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfPlayer(ref FlatSpanBufferBuilder builder, scoped Span> offsets) { + var comparer = new SortedVectorUtils.ScalarOffsetComparer(builder.DataBuffer, 4); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, int key, ByteSpanBuffer bb, out Player value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 4, 0, out value); + } + public PlayerT UnPack() { + var _o = new PlayerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(PlayerT _o) { + _o.Id = this.Id; + _o.Name = this.Name; + _o.Level = this.Level; + _o.Experience = this.Experience; + _o.Health = this.Health; + _o.Mana = this.Mana; + var _inventory_types = this.InventoryType; + var _inventory = this.Inventory; + var _inventory_len = _inventory.HasValue ? _inventory.Value.Length : 0; + if (_o.Inventory == null) { + _o.Inventory = new List(_inventory_len); + } + ObjectApiUtil.ResizeList(_o.Inventory, _inventory_len); + if (_inventory.HasValue) { + var _inventory_value = _inventory.Value; + var _inventory_types_value = _inventory_types.Value; + for (var _j = 0; _j < _inventory_len; ++_j) { + var _inventory_type = _inventory_types_value[_j]; + var _o_Inventory = _o.Inventory[_j]; + if (_o_Inventory == null) { + _o_Inventory = new ComprehensiveTest.EquipmentUnion(); + _o.Inventory[_j] = _o_Inventory; + } + var _inventory_old_type = _o_Inventory.Type; + _o_Inventory.Type = _inventory_type; + switch (_inventory_type) { + default: + _o_Inventory.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (_inventory_old_type == ComprehensiveTest.Equipment.Weapon) { + _inventory_value.GetAs(_j).UnPackTo((ComprehensiveTest.WeaponT)_o_Inventory.Value); + } else { + _o_Inventory.Value = _inventory_value.GetAs(_j).UnPack(); + } + break; + case ComprehensiveTest.Equipment.Armor: + if (_inventory_old_type == ComprehensiveTest.Equipment.Armor) { + _inventory_value.GetAs(_j).UnPackTo((ComprehensiveTest.ArmorT)_o_Inventory.Value); + } else { + _o_Inventory.Value = _inventory_value.GetAs(_j).UnPack(); + } + break; + } + } + } + var _skills_vec = this.Skills; + var _skills_len = _skills_vec.HasValue ? _skills_vec.Value.Length : 0; + if (_o.Skills == null) { + _o.Skills = new List(_skills_len); + } else { + _o.Skills.Clear(); + if (_o.Skills.Capacity < _skills_len) { + _o.Skills.Capacity = _skills_len; + } + } + if (_skills_vec.HasValue) { + var _skills_value = _skills_vec.Value; + for (var _j = 0; _j < _skills_len; ++_j) { _o.Skills.Add(_skills_value[_j]); } + } + var _stats_vec = this.Stats; + var _stats_len = _stats_vec.HasValue ? _stats_vec.Value.Length : 0; + if (_o.Stats == null) { + _o.Stats = new List(_stats_len); + } + ObjectApiUtil.ResizeList(_o.Stats, _stats_len); + if (_stats_vec.HasValue) { _stats_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Stats)); } + if (this.SpawnPoint.HasValue) { + if (_o.SpawnPoint == null) _o.SpawnPoint = new ComprehensiveTest.Vec3T(); + this.SpawnPoint.Value.UnPackTo(_o.SpawnPoint); + } else { + _o.SpawnPoint = null; + } + _o.Status = this.Status; + if (_o.EquippedType == null) { + _o.EquippedType = new ComprehensiveTest.EquipmentUnion(); + } + var _EquippedTypeOldType = _o.EquippedType.Type; + _o.EquippedType.Type = this.EquippedTypeType; + switch (this.EquippedTypeType) { + default: + _o.EquippedType.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (this.EquippedType().HasValue) { + if (_EquippedTypeOldType == ComprehensiveTest.Equipment.Weapon) { + this.EquippedType().Value.UnPackTo((ComprehensiveTest.WeaponT)_o.EquippedType.Value); + } else { + _o.EquippedType.Value = this.EquippedType().Value.UnPack(); + } + } else { + _o.EquippedType.Value = null; + } + break; + case ComprehensiveTest.Equipment.Armor: + if (this.EquippedType().HasValue) { + if (_EquippedTypeOldType == ComprehensiveTest.Equipment.Armor) { + this.EquippedType().Value.UnPackTo((ComprehensiveTest.ArmorT)_o.EquippedType.Value); + } else { + _o.EquippedType.Value = this.EquippedType().Value.UnPack(); + } + } else { + _o.EquippedType.Value = null; + } + break; + } + if (_o.EquippedItem == null) { + _o.EquippedItem = new ComprehensiveTest.EquipmentUnion(); + } + var _EquippedItemOldType = _o.EquippedItem.Type; + _o.EquippedItem.Type = this.EquippedItemType; + switch (this.EquippedItemType) { + default: + _o.EquippedItem.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (this.EquippedItem().HasValue) { + if (_EquippedItemOldType == ComprehensiveTest.Equipment.Weapon) { + this.EquippedItem().Value.UnPackTo((ComprehensiveTest.WeaponT)_o.EquippedItem.Value); + } else { + _o.EquippedItem.Value = this.EquippedItem().Value.UnPack(); + } + } else { + _o.EquippedItem.Value = null; + } + break; + case ComprehensiveTest.Equipment.Armor: + if (this.EquippedItem().HasValue) { + if (_EquippedItemOldType == ComprehensiveTest.Equipment.Armor) { + this.EquippedItem().Value.UnPackTo((ComprehensiveTest.ArmorT)_o.EquippedItem.Value); + } else { + _o.EquippedItem.Value = this.EquippedItem().Value.UnPack(); + } + } else { + _o.EquippedItem.Value = null; + } + break; + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, PlayerT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + var _inventory_type = default(VectorOffset); + if (_o.Inventory != null) { + var _inventory_type_len = _o.Inventory.Count; + ComprehensiveTest.Equipment[] _inventory_type_arr = null; + try { + Span __inventory_type = _inventory_type_len <= 256 + ? stackalloc ComprehensiveTest.Equipment[_inventory_type_len] + : (_inventory_type_arr = ArrayPool.Shared.Rent(_inventory_type_len)).AsSpan(0, _inventory_type_len); + for (var _j = 0; _j < _inventory_type_len; ++_j) { __inventory_type[_j] = _o.Inventory[_j].Type; } + _inventory_type = CreateInventoryTypeVector(ref builder, __inventory_type); + } finally { + if (_inventory_type_arr != null) { ArrayPool.Shared.Return(_inventory_type_arr); } + } + } + var _inventory = default(VectorOffset); + if (_o.Inventory != null) { + var _inventory_len = _o.Inventory.Count; + int[] _inventory_arr = null; + try { + Span __inventory = _inventory_len <= 64 + ? stackalloc int[_inventory_len] + : (_inventory_arr = ArrayPool.Shared.Rent(_inventory_len)).AsSpan(0, _inventory_len); + for (var _j = 0; _j < _inventory_len; ++_j) { __inventory[_j] = ComprehensiveTest.EquipmentUnion.Pack(ref builder, _o.Inventory[_j]); } + _inventory = CreateInventoryVector(ref builder, __inventory); + } finally { + if (_inventory_arr != null) { ArrayPool.Shared.Return(_inventory_arr); } + } + } + var _skills = default(VectorOffset); + if (_o.Skills != null) { + var _skills_len = _o.Skills.Count; + StringOffset[] _skills_arr = null; + try { + Span __skills = _skills_len <= 64 + ? stackalloc StringOffset[_skills_len] + : (_skills_arr = ArrayPool.Shared.Rent(_skills_len)).AsSpan(0, _skills_len); + for (var _j = 0; _j < _skills_len; ++_j) { __skills[_j] = builder.CreateString(_o.Skills[_j]); } + _skills = CreateSkillsVector(ref builder, __skills); + } finally { + if (_skills_arr != null) { ArrayPool.Shared.Return(_skills_arr); } + } + } + var _stats = default(VectorOffset); + if (_o.Stats != null) { + _stats = CreateStatsVector(ref builder, CollectionsMarshal.AsSpan(_o.Stats)); + } + var _equipped_type_type = _o.EquippedType == null ? ComprehensiveTest.Equipment.NONE : _o.EquippedType.Type; + var _equipped_type = _o.EquippedType == null ? 0 : ComprehensiveTest.EquipmentUnion.Pack(ref builder, _o.EquippedType); + var _equipped_item_type = _o.EquippedItem == null ? ComprehensiveTest.Equipment.NONE : _o.EquippedItem.Type; + var _equipped_item = _o.EquippedItem == null ? 0 : ComprehensiveTest.EquipmentUnion.Pack(ref builder, _o.EquippedItem); + StartPlayer(ref builder); + AddId(ref builder, _o.Id); + AddName(ref builder, _name); + AddLevel(ref builder, _o.Level); + AddExperience(ref builder, _o.Experience); + AddHealth(ref builder, _o.Health); + AddMana(ref builder, _o.Mana); + AddInventoryType(ref builder, _inventory_type); + AddInventory(ref builder, _inventory); + AddSkills(ref builder, _skills); + AddStats(ref builder, _stats); + AddSpawnPoint(ref builder, ComprehensiveTest.StackBuffer.Vec3.Pack(ref builder, _o.SpawnPoint)); + AddStatus(ref builder, _o.Status); + AddEquippedTypeType(ref builder, _equipped_type_type); + AddEquippedType(ref builder, _equipped_type); + AddEquippedItemType(ref builder, _equipped_item_type); + AddEquippedItem(ref builder, _equipped_item); + return EndPlayer(ref builder); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/PositionHistory.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/PositionHistory.cs new file mode 100644 index 00000000000..6f1bb8ed02a --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/PositionHistory.cs @@ -0,0 +1,61 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct PositionHistory : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public PositionHistory __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public ComprehensiveTest.StackBuffer.Vec3 Positions(int j) { return (new ComprehensiveTest.StackBuffer.Vec3()).__assign(__p.bb_pos + 0 + j * 12, __p.bb); } + + public static Offset CreatePositionHistory(ref FlatSpanBufferBuilder builder, float[] positions_X, float[] positions_Y, float[] positions_Z) { + builder.Prep(4, 120); + for (int _idx0 = 10; _idx0 > 0; _idx0--) { + builder.Prep(4, 12); + builder.Put(positions_Z[_idx0-1]); + builder.Put(positions_Y[_idx0-1]); + builder.Put(positions_X[_idx0-1]); + } + return new Offset(builder.Offset); + } + public PositionHistoryT UnPack() { + var _o = new PositionHistoryT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(PositionHistoryT _o) { + _o.Positions = new ComprehensiveTest.Vec3T[10]; + for (var _j = 0; _j < 10; ++_j) { _o.Positions[_j] = this.Positions(_j).UnPack(); } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, PositionHistoryT _o) { + if (_o == null) return default(Offset); + var _positions_x = new float[10]; + for (var idx0 = 0; idx0 < 10; ++idx0) {_positions_x[idx0] = _o.Positions[idx0].X;} + var _positions_y = new float[10]; + for (var idx0 = 0; idx0 < 10; ++idx0) {_positions_y[idx0] = _o.Positions[idx0].Y;} + var _positions_z = new float[10]; + for (var idx0 = 0; idx0 < 10; ++idx0) {_positions_z[idx0] = _o.Positions[idx0].Z;} + return CreatePositionHistory( + ref builder, + _positions_x, + _positions_y, + _positions_z); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Transform.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Transform.cs new file mode 100644 index 00000000000..6b5400e7b56 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Transform.cs @@ -0,0 +1,82 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Transform : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Transform __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public ComprehensiveTest.StackBuffer.Vec3 Position { get { return (new ComprehensiveTest.StackBuffer.Vec3()).__assign(__p.bb_pos + 0, __p.bb); } } + public ComprehensiveTest.StackBuffer.Vec3 Rotation { get { return (new ComprehensiveTest.StackBuffer.Vec3()).__assign(__p.bb_pos + 12, __p.bb); } } + public ComprehensiveTest.StackBuffer.Vec3 Scale { get { return (new ComprehensiveTest.StackBuffer.Vec3()).__assign(__p.bb_pos + 24, __p.bb); } } + + public static Offset CreateTransform(ref FlatSpanBufferBuilder builder, float position_X, float position_Y, float position_Z, float rotation_X, float rotation_Y, float rotation_Z, float scale_X, float scale_Y, float scale_Z) { + builder.Prep(4, 36); + builder.Prep(4, 12); + builder.Put(scale_Z); + builder.Put(scale_Y); + builder.Put(scale_X); + builder.Prep(4, 12); + builder.Put(rotation_Z); + builder.Put(rotation_Y); + builder.Put(rotation_X); + builder.Prep(4, 12); + builder.Put(position_Z); + builder.Put(position_Y); + builder.Put(position_X); + return new Offset(builder.Offset); + } + public TransformT UnPack() { + var _o = new TransformT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TransformT _o) { + if (_o.Position == null) _o.Position = new ComprehensiveTest.Vec3T(); + this.Position.UnPackTo(_o.Position); + if (_o.Rotation == null) _o.Rotation = new ComprehensiveTest.Vec3T(); + this.Rotation.UnPackTo(_o.Rotation); + if (_o.Scale == null) _o.Scale = new ComprehensiveTest.Vec3T(); + this.Scale.UnPackTo(_o.Scale); + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, TransformT _o) { + if (_o == null) return default(Offset); + var _position_x = _o.Position.X; + var _position_y = _o.Position.Y; + var _position_z = _o.Position.Z; + var _rotation_x = _o.Rotation.X; + var _rotation_y = _o.Rotation.Y; + var _rotation_z = _o.Rotation.Z; + var _scale_x = _o.Scale.X; + var _scale_y = _o.Scale.Y; + var _scale_z = _o.Scale.Z; + return CreateTransform( + ref builder, + _position_x, + _position_y, + _position_z, + _rotation_x, + _rotation_y, + _rotation_z, + _scale_x, + _scale_y, + _scale_z); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Vec3.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Vec3.cs new file mode 100644 index 00000000000..11638aad58e --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Vec3.cs @@ -0,0 +1,55 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Vec3 : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Vec3 __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public float X { get { return __p.bb.Get(__p.bb_pos + 0); } } + public float Y { get { return __p.bb.Get(__p.bb_pos + 4); } } + public float Z { get { return __p.bb.Get(__p.bb_pos + 8); } } + + public static Offset CreateVec3(ref FlatSpanBufferBuilder builder, float X, float Y, float Z) { + builder.Prep(4, 12); + builder.Put(Z); + builder.Put(Y); + builder.Put(X); + return new Offset(builder.Offset); + } + public Vec3T UnPack() { + var _o = new Vec3T(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(Vec3T _o) { + _o.X = this.X; + _o.Y = this.Y; + _o.Z = this.Z; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, Vec3T _o) { + if (_o == null) return default(Offset); + return CreateVec3( + ref builder, + _o.X, + _o.Y, + _o.Z); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Weapon.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Weapon.cs new file mode 100644 index 00000000000..7899710d569 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/StackBuffer/Weapon.cs @@ -0,0 +1,468 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Weapon : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Weapon GetRootAsWeapon(ByteSpanBuffer _bb) { return GetRootAsWeapon(_bb, new Weapon()); } + public static Weapon GetRootAsWeapon(ByteSpanBuffer _bb, Weapon obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Weapon __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public int Damage { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)10; } } + public float Durability { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)100.0f; } } + public bool Enchanted { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public RefStructNullable Tags { get { int o = __p.__offset(12); return o != 0 ? new RefStructNullable(new StringVectorSpan(__p, o)) : default; } } + public RefStructNullable> DamageValues { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public RefStructNullable> Modifiers { get { int o = __p.__offset(16); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(16)) : default; } } + public RefStructNullable Transform { get { int o = __p.__offset(18); return o != 0 ? new RefStructNullable((new ComprehensiveTest.StackBuffer.Transform()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + public RefStructNullable> HitPoints { get { int o = __p.__offset(20); return o != 0 ? new RefStructNullable>(new StructVectorSpan(__p, o, 12)) : default; } } + public ComprehensiveTest.Color Rarity { get { int o = __p.__offset(22); return o != 0 ? (ComprehensiveTest.Color)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Color.Red; } } + public RefStructNullable> ValidColors { get { int o = __p.__offset(24); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(24)) : default; } } + public ComprehensiveTest.Equipment WeaponTypeType { get { int o = __p.__offset(26); return o != 0 ? (ComprehensiveTest.Equipment)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Equipment.NONE; } } + public RefStructNullable WeaponType() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(28); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public ComprehensiveTest.StackBuffer.Weapon WeaponTypeAsWeapon() { return WeaponType().Value; } + public ComprehensiveTest.StackBuffer.Armor WeaponTypeAsArmor() { return WeaponType().Value; } + public ComprehensiveTest.Equipment WeaponEquipmentType { get { int o = __p.__offset(30); return o != 0 ? (ComprehensiveTest.Equipment)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Equipment.NONE; } } + public RefStructNullable WeaponEquipment() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(32); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public ComprehensiveTest.StackBuffer.Weapon WeaponEquipmentAsWeapon() { return WeaponEquipment().Value; } + public ComprehensiveTest.StackBuffer.Armor WeaponEquipmentAsArmor() { return WeaponEquipment().Value; } + public RefStructNullable> CompatibleTypesType { get { int o = __p.__offset(34); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(34)) : default; } } + public RefStructNullable CompatibleTypes { get { int o = __p.__offset(36); return o != 0 ? new RefStructNullable(new UnionVectorSpan(__p, o, 4)) : default; } } + public RefStructNullable> CompatibleItemsType { get { int o = __p.__offset(38); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(38)) : default; } } + public RefStructNullable CompatibleItems { get { int o = __p.__offset(40); return o != 0 ? new RefStructNullable(new UnionVectorSpan(__p, o, 4)) : default; } } + public RefStructNullable> Metadata { get { int o = __p.__offset(42); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(42)) : default; } } + public ComprehensiveTest.StackBuffer.NestedData GetMetadataAsNestedData() { int o = __p.__offset(42); return o != 0 ? (new ComprehensiveTest.StackBuffer.NestedData()).__assign(__p.__indirect(__p.__vector(o)), __p.bb) : default; } + public RefStructNullable FixedStats { get { int o = __p.__offset(44); return o != 0 ? new RefStructNullable((new ComprehensiveTest.StackBuffer.FixedStats()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + public RefStructNullable PositionHistory { get { int o = __p.__offset(46); return o != 0 ? new RefStructNullable((new ComprehensiveTest.StackBuffer.PositionHistory()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + + public static void StartWeapon(ref FlatSpanBufferBuilder builder) { builder.StartTable(22); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddDamage(ref FlatSpanBufferBuilder builder, int damage) { builder.Add(1, damage, 10); } + public static void AddDurability(ref FlatSpanBufferBuilder builder, float durability) { builder.Add(2, durability, 100.0f); } + public static void AddEnchanted(ref FlatSpanBufferBuilder builder, bool enchanted) { builder.Add(3, enchanted, false); } + public static void AddTags(ref FlatSpanBufferBuilder builder, VectorOffset tagsOffset) { builder.AddOffset(4, tagsOffset, 0); } + public static VectorOffset CreateTagsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTagsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateTagsVectorBlock(ref builder, data); } + public static void StartTagsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddDamageValues(ref FlatSpanBufferBuilder builder, VectorOffset damageValuesOffset) { builder.AddOffset(5, damageValuesOffset, 0); } + public static VectorOffset CreateDamageValuesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateDamageValuesVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateDamageValuesVectorBlock(ref builder, data); } + public static void StartDamageValuesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddModifiers(ref FlatSpanBufferBuilder builder, VectorOffset modifiersOffset) { builder.AddOffset(6, modifiersOffset, 0); } + public static VectorOffset CreateModifiersVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateModifiersVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateModifiersVectorBlock(ref builder, data); } + public static void StartModifiersVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddTransform(ref FlatSpanBufferBuilder builder, Offset transformOffset) { builder.AddStruct(7, transformOffset, 0); } + public static void AddHitPoints(ref FlatSpanBufferBuilder builder, VectorOffset hitPointsOffset) { builder.AddOffset(8, hitPointsOffset, 0); } + public static void StartHitPointsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(12, numElems, 4); } + public static void AddRarity(ref FlatSpanBufferBuilder builder, ComprehensiveTest.Color rarity) { builder.Add(9, (sbyte)rarity, 0); } + public static void AddValidColors(ref FlatSpanBufferBuilder builder, VectorOffset validColorsOffset) { builder.AddOffset(10, validColorsOffset, 0); } + public static VectorOffset CreateValidColorsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateValidColorsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateValidColorsVectorBlock(ref builder, data); } + public static void StartValidColorsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddWeaponTypeType(ref FlatSpanBufferBuilder builder, ComprehensiveTest.Equipment weaponTypeType) { builder.Add(11, (byte)weaponTypeType, 0); } + public static void AddWeaponType(ref FlatSpanBufferBuilder builder, int weaponTypeOffset) { builder.AddOffset(12, weaponTypeOffset, 0); } + public static void AddWeaponEquipmentType(ref FlatSpanBufferBuilder builder, ComprehensiveTest.Equipment weaponEquipmentType) { builder.Add(13, (byte)weaponEquipmentType, 0); } + public static void AddWeaponEquipment(ref FlatSpanBufferBuilder builder, int weaponEquipmentOffset) { builder.AddOffset(14, weaponEquipmentOffset, 0); } + public static void AddCompatibleTypesType(ref FlatSpanBufferBuilder builder, VectorOffset compatibleTypesTypeOffset) { builder.AddOffset(15, compatibleTypesTypeOffset, 0); } + public static VectorOffset CreateCompatibleTypesTypeVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCompatibleTypesTypeVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateCompatibleTypesTypeVectorBlock(ref builder, data); } + public static void StartCompatibleTypesTypeVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddCompatibleTypes(ref FlatSpanBufferBuilder builder, VectorOffset compatibleTypesOffset) { builder.AddOffset(16, compatibleTypesOffset, 0); } + public static VectorOffset CreateCompatibleTypesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCompatibleTypesVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateCompatibleTypesVectorBlock(ref builder, data); } + public static void StartCompatibleTypesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddCompatibleItemsType(ref FlatSpanBufferBuilder builder, VectorOffset compatibleItemsTypeOffset) { builder.AddOffset(17, compatibleItemsTypeOffset, 0); } + public static VectorOffset CreateCompatibleItemsTypeVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCompatibleItemsTypeVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateCompatibleItemsTypeVectorBlock(ref builder, data); } + public static void StartCompatibleItemsTypeVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddCompatibleItems(ref FlatSpanBufferBuilder builder, VectorOffset compatibleItemsOffset) { builder.AddOffset(18, compatibleItemsOffset, 0); } + public static VectorOffset CreateCompatibleItemsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCompatibleItemsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateCompatibleItemsVectorBlock(ref builder, data); } + public static void StartCompatibleItemsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddMetadata(ref FlatSpanBufferBuilder builder, VectorOffset metadataOffset) { builder.AddOffset(19, metadataOffset, 0); } + public static VectorOffset CreateMetadataVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateMetadataVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateMetadataVectorBlock(ref builder, data); } + public static void StartMetadataVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddFixedStats(ref FlatSpanBufferBuilder builder, Offset fixedStatsOffset) { builder.AddStruct(20, fixedStatsOffset, 0); } + public static void AddPositionHistory(ref FlatSpanBufferBuilder builder, Offset positionHistoryOffset) { builder.AddStruct(21, positionHistoryOffset, 0); } + public static Offset EndWeapon(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 4); // name + return new Offset(o); + } + public WeaponT UnPack() { + var _o = new WeaponT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(WeaponT _o) { + _o.Name = this.Name; + _o.Damage = this.Damage; + _o.Durability = this.Durability; + _o.Enchanted = this.Enchanted; + var _tags_vec = this.Tags; + var _tags_len = _tags_vec.HasValue ? _tags_vec.Value.Length : 0; + if (_o.Tags == null) { + _o.Tags = new List(_tags_len); + } else { + _o.Tags.Clear(); + if (_o.Tags.Capacity < _tags_len) { + _o.Tags.Capacity = _tags_len; + } + } + if (_tags_vec.HasValue) { + var _tags_value = _tags_vec.Value; + for (var _j = 0; _j < _tags_len; ++_j) { _o.Tags.Add(_tags_value[_j]); } + } + var _damage_values_vec = this.DamageValues; + var _damage_values_len = _damage_values_vec.HasValue ? _damage_values_vec.Value.Length : 0; + if (_o.DamageValues == null) { + _o.DamageValues = new List(_damage_values_len); + } + ObjectApiUtil.ResizeList(_o.DamageValues, _damage_values_len); + if (_damage_values_vec.HasValue) { _damage_values_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.DamageValues)); } + var _modifiers_vec = this.Modifiers; + var _modifiers_len = _modifiers_vec.HasValue ? _modifiers_vec.Value.Length : 0; + if (_o.Modifiers == null) { + _o.Modifiers = new List(_modifiers_len); + } + ObjectApiUtil.ResizeList(_o.Modifiers, _modifiers_len); + if (_modifiers_vec.HasValue) { _modifiers_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Modifiers)); } + if (this.Transform.HasValue) { + if (_o.Transform == null) _o.Transform = new ComprehensiveTest.TransformT(); + this.Transform.Value.UnPackTo(_o.Transform); + } else { + _o.Transform = null; + } + var _hit_points_vec = this.HitPoints; + var _hit_points_len = _hit_points_vec.HasValue ? _hit_points_vec.Value.Length : 0; + if (_o.HitPoints == null) { + _o.HitPoints = new List(_hit_points_len); + } + ObjectApiUtil.ResizeList(_o.HitPoints, _hit_points_len); + if (_hit_points_vec.HasValue) { + var _hit_points_value = _hit_points_vec.Value; + for (var _j = 0; _j < _hit_points_len; ++_j) { + var _src = _hit_points_value[_j]; + if (_o.HitPoints[_j] == null) { _o.HitPoints[_j] = new Vec3T(); } + _src.UnPackTo(_o.HitPoints[_j]); + } + } + _o.Rarity = this.Rarity; + var _valid_colors_vec = this.ValidColors; + var _valid_colors_len = _valid_colors_vec.HasValue ? _valid_colors_vec.Value.Length : 0; + if (_o.ValidColors == null) { + _o.ValidColors = new List(_valid_colors_len); + } + ObjectApiUtil.ResizeList(_o.ValidColors, _valid_colors_len); + if (_valid_colors_vec.HasValue) { _valid_colors_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.ValidColors)); } + if (_o.WeaponType == null) { + _o.WeaponType = new ComprehensiveTest.EquipmentUnion(); + } + var _WeaponTypeOldType = _o.WeaponType.Type; + _o.WeaponType.Type = this.WeaponTypeType; + switch (this.WeaponTypeType) { + default: + _o.WeaponType.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (this.WeaponType().HasValue) { + if (_WeaponTypeOldType == ComprehensiveTest.Equipment.Weapon) { + this.WeaponType().Value.UnPackTo((ComprehensiveTest.WeaponT)_o.WeaponType.Value); + } else { + _o.WeaponType.Value = this.WeaponType().Value.UnPack(); + } + } else { + _o.WeaponType.Value = null; + } + break; + case ComprehensiveTest.Equipment.Armor: + if (this.WeaponType().HasValue) { + if (_WeaponTypeOldType == ComprehensiveTest.Equipment.Armor) { + this.WeaponType().Value.UnPackTo((ComprehensiveTest.ArmorT)_o.WeaponType.Value); + } else { + _o.WeaponType.Value = this.WeaponType().Value.UnPack(); + } + } else { + _o.WeaponType.Value = null; + } + break; + } + if (_o.WeaponEquipment == null) { + _o.WeaponEquipment = new ComprehensiveTest.EquipmentUnion(); + } + var _WeaponEquipmentOldType = _o.WeaponEquipment.Type; + _o.WeaponEquipment.Type = this.WeaponEquipmentType; + switch (this.WeaponEquipmentType) { + default: + _o.WeaponEquipment.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (this.WeaponEquipment().HasValue) { + if (_WeaponEquipmentOldType == ComprehensiveTest.Equipment.Weapon) { + this.WeaponEquipment().Value.UnPackTo((ComprehensiveTest.WeaponT)_o.WeaponEquipment.Value); + } else { + _o.WeaponEquipment.Value = this.WeaponEquipment().Value.UnPack(); + } + } else { + _o.WeaponEquipment.Value = null; + } + break; + case ComprehensiveTest.Equipment.Armor: + if (this.WeaponEquipment().HasValue) { + if (_WeaponEquipmentOldType == ComprehensiveTest.Equipment.Armor) { + this.WeaponEquipment().Value.UnPackTo((ComprehensiveTest.ArmorT)_o.WeaponEquipment.Value); + } else { + _o.WeaponEquipment.Value = this.WeaponEquipment().Value.UnPack(); + } + } else { + _o.WeaponEquipment.Value = null; + } + break; + } + var _compatible_types_types = this.CompatibleTypesType; + var _compatible_types = this.CompatibleTypes; + var _compatible_types_len = _compatible_types.HasValue ? _compatible_types.Value.Length : 0; + if (_o.CompatibleTypes == null) { + _o.CompatibleTypes = new List(_compatible_types_len); + } + ObjectApiUtil.ResizeList(_o.CompatibleTypes, _compatible_types_len); + if (_compatible_types.HasValue) { + var _compatible_types_value = _compatible_types.Value; + var _compatible_types_types_value = _compatible_types_types.Value; + for (var _j = 0; _j < _compatible_types_len; ++_j) { + var _compatible_types_type = _compatible_types_types_value[_j]; + var _o_CompatibleTypes = _o.CompatibleTypes[_j]; + if (_o_CompatibleTypes == null) { + _o_CompatibleTypes = new ComprehensiveTest.EquipmentUnion(); + _o.CompatibleTypes[_j] = _o_CompatibleTypes; + } + var _compatible_types_old_type = _o_CompatibleTypes.Type; + _o_CompatibleTypes.Type = _compatible_types_type; + switch (_compatible_types_type) { + default: + _o_CompatibleTypes.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (_compatible_types_old_type == ComprehensiveTest.Equipment.Weapon) { + _compatible_types_value.GetAs(_j).UnPackTo((ComprehensiveTest.WeaponT)_o_CompatibleTypes.Value); + } else { + _o_CompatibleTypes.Value = _compatible_types_value.GetAs(_j).UnPack(); + } + break; + case ComprehensiveTest.Equipment.Armor: + if (_compatible_types_old_type == ComprehensiveTest.Equipment.Armor) { + _compatible_types_value.GetAs(_j).UnPackTo((ComprehensiveTest.ArmorT)_o_CompatibleTypes.Value); + } else { + _o_CompatibleTypes.Value = _compatible_types_value.GetAs(_j).UnPack(); + } + break; + } + } + } + var _compatible_items_types = this.CompatibleItemsType; + var _compatible_items = this.CompatibleItems; + var _compatible_items_len = _compatible_items.HasValue ? _compatible_items.Value.Length : 0; + if (_o.CompatibleItems == null) { + _o.CompatibleItems = new List(_compatible_items_len); + } + ObjectApiUtil.ResizeList(_o.CompatibleItems, _compatible_items_len); + if (_compatible_items.HasValue) { + var _compatible_items_value = _compatible_items.Value; + var _compatible_items_types_value = _compatible_items_types.Value; + for (var _j = 0; _j < _compatible_items_len; ++_j) { + var _compatible_items_type = _compatible_items_types_value[_j]; + var _o_CompatibleItems = _o.CompatibleItems[_j]; + if (_o_CompatibleItems == null) { + _o_CompatibleItems = new ComprehensiveTest.EquipmentUnion(); + _o.CompatibleItems[_j] = _o_CompatibleItems; + } + var _compatible_items_old_type = _o_CompatibleItems.Type; + _o_CompatibleItems.Type = _compatible_items_type; + switch (_compatible_items_type) { + default: + _o_CompatibleItems.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (_compatible_items_old_type == ComprehensiveTest.Equipment.Weapon) { + _compatible_items_value.GetAs(_j).UnPackTo((ComprehensiveTest.WeaponT)_o_CompatibleItems.Value); + } else { + _o_CompatibleItems.Value = _compatible_items_value.GetAs(_j).UnPack(); + } + break; + case ComprehensiveTest.Equipment.Armor: + if (_compatible_items_old_type == ComprehensiveTest.Equipment.Armor) { + _compatible_items_value.GetAs(_j).UnPackTo((ComprehensiveTest.ArmorT)_o_CompatibleItems.Value); + } else { + _o_CompatibleItems.Value = _compatible_items_value.GetAs(_j).UnPack(); + } + break; + } + } + } + var _metadata_vec = this.Metadata; + var _metadata_len = _metadata_vec.HasValue ? _metadata_vec.Value.Length : 0; + if (_o.Metadata == null) { + _o.Metadata = new List(_metadata_len); + } + ObjectApiUtil.ResizeList(_o.Metadata, _metadata_len); + if (_metadata_vec.HasValue) { _metadata_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Metadata)); } + if (this.FixedStats.HasValue) { + if (_o.FixedStats == null) _o.FixedStats = new ComprehensiveTest.FixedStatsT(); + this.FixedStats.Value.UnPackTo(_o.FixedStats); + } else { + _o.FixedStats = null; + } + if (this.PositionHistory.HasValue) { + if (_o.PositionHistory == null) _o.PositionHistory = new ComprehensiveTest.PositionHistoryT(); + this.PositionHistory.Value.UnPackTo(_o.PositionHistory); + } else { + _o.PositionHistory = null; + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, WeaponT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + var _tags = default(VectorOffset); + if (_o.Tags != null) { + var _tags_len = _o.Tags.Count; + StringOffset[] _tags_arr = null; + try { + Span __tags = _tags_len <= 64 + ? stackalloc StringOffset[_tags_len] + : (_tags_arr = ArrayPool.Shared.Rent(_tags_len)).AsSpan(0, _tags_len); + for (var _j = 0; _j < _tags_len; ++_j) { __tags[_j] = builder.CreateString(_o.Tags[_j]); } + _tags = CreateTagsVector(ref builder, __tags); + } finally { + if (_tags_arr != null) { ArrayPool.Shared.Return(_tags_arr); } + } + } + var _damage_values = default(VectorOffset); + if (_o.DamageValues != null) { + _damage_values = CreateDamageValuesVector(ref builder, CollectionsMarshal.AsSpan(_o.DamageValues)); + } + var _modifiers = default(VectorOffset); + if (_o.Modifiers != null) { + _modifiers = CreateModifiersVector(ref builder, CollectionsMarshal.AsSpan(_o.Modifiers)); + } + var _hit_points = default(VectorOffset); + if (_o.HitPoints != null) { + StartHitPointsVector(ref builder, _o.HitPoints.Count); + for (var _j = _o.HitPoints.Count - 1; _j >= 0; --_j) { ComprehensiveTest.StackBuffer.Vec3.Pack(ref builder, _o.HitPoints[_j]); } + _hit_points = builder.EndVector(); + } + var _valid_colors = default(VectorOffset); + if (_o.ValidColors != null) { + _valid_colors = CreateValidColorsVector(ref builder, CollectionsMarshal.AsSpan(_o.ValidColors)); + } + var _weapon_type_type = _o.WeaponType == null ? ComprehensiveTest.Equipment.NONE : _o.WeaponType.Type; + var _weapon_type = _o.WeaponType == null ? 0 : ComprehensiveTest.EquipmentUnion.Pack(ref builder, _o.WeaponType); + var _weapon_equipment_type = _o.WeaponEquipment == null ? ComprehensiveTest.Equipment.NONE : _o.WeaponEquipment.Type; + var _weapon_equipment = _o.WeaponEquipment == null ? 0 : ComprehensiveTest.EquipmentUnion.Pack(ref builder, _o.WeaponEquipment); + var _compatible_types_type = default(VectorOffset); + if (_o.CompatibleTypes != null) { + var _compatible_types_type_len = _o.CompatibleTypes.Count; + ComprehensiveTest.Equipment[] _compatible_types_type_arr = null; + try { + Span __compatible_types_type = _compatible_types_type_len <= 256 + ? stackalloc ComprehensiveTest.Equipment[_compatible_types_type_len] + : (_compatible_types_type_arr = ArrayPool.Shared.Rent(_compatible_types_type_len)).AsSpan(0, _compatible_types_type_len); + for (var _j = 0; _j < _compatible_types_type_len; ++_j) { __compatible_types_type[_j] = _o.CompatibleTypes[_j].Type; } + _compatible_types_type = CreateCompatibleTypesTypeVector(ref builder, __compatible_types_type); + } finally { + if (_compatible_types_type_arr != null) { ArrayPool.Shared.Return(_compatible_types_type_arr); } + } + } + var _compatible_types = default(VectorOffset); + if (_o.CompatibleTypes != null) { + var _compatible_types_len = _o.CompatibleTypes.Count; + int[] _compatible_types_arr = null; + try { + Span __compatible_types = _compatible_types_len <= 64 + ? stackalloc int[_compatible_types_len] + : (_compatible_types_arr = ArrayPool.Shared.Rent(_compatible_types_len)).AsSpan(0, _compatible_types_len); + for (var _j = 0; _j < _compatible_types_len; ++_j) { __compatible_types[_j] = ComprehensiveTest.EquipmentUnion.Pack(ref builder, _o.CompatibleTypes[_j]); } + _compatible_types = CreateCompatibleTypesVector(ref builder, __compatible_types); + } finally { + if (_compatible_types_arr != null) { ArrayPool.Shared.Return(_compatible_types_arr); } + } + } + var _compatible_items_type = default(VectorOffset); + if (_o.CompatibleItems != null) { + var _compatible_items_type_len = _o.CompatibleItems.Count; + ComprehensiveTest.Equipment[] _compatible_items_type_arr = null; + try { + Span __compatible_items_type = _compatible_items_type_len <= 256 + ? stackalloc ComprehensiveTest.Equipment[_compatible_items_type_len] + : (_compatible_items_type_arr = ArrayPool.Shared.Rent(_compatible_items_type_len)).AsSpan(0, _compatible_items_type_len); + for (var _j = 0; _j < _compatible_items_type_len; ++_j) { __compatible_items_type[_j] = _o.CompatibleItems[_j].Type; } + _compatible_items_type = CreateCompatibleItemsTypeVector(ref builder, __compatible_items_type); + } finally { + if (_compatible_items_type_arr != null) { ArrayPool.Shared.Return(_compatible_items_type_arr); } + } + } + var _compatible_items = default(VectorOffset); + if (_o.CompatibleItems != null) { + var _compatible_items_len = _o.CompatibleItems.Count; + int[] _compatible_items_arr = null; + try { + Span __compatible_items = _compatible_items_len <= 64 + ? stackalloc int[_compatible_items_len] + : (_compatible_items_arr = ArrayPool.Shared.Rent(_compatible_items_len)).AsSpan(0, _compatible_items_len); + for (var _j = 0; _j < _compatible_items_len; ++_j) { __compatible_items[_j] = ComprehensiveTest.EquipmentUnion.Pack(ref builder, _o.CompatibleItems[_j]); } + _compatible_items = CreateCompatibleItemsVector(ref builder, __compatible_items); + } finally { + if (_compatible_items_arr != null) { ArrayPool.Shared.Return(_compatible_items_arr); } + } + } + var _metadata = default(VectorOffset); + if (_o.Metadata != null) { + _metadata = CreateMetadataVector(ref builder, CollectionsMarshal.AsSpan(_o.Metadata)); + } + StartWeapon(ref builder); + AddName(ref builder, _name); + AddDamage(ref builder, _o.Damage); + AddDurability(ref builder, _o.Durability); + AddEnchanted(ref builder, _o.Enchanted); + AddTags(ref builder, _tags); + AddDamageValues(ref builder, _damage_values); + AddModifiers(ref builder, _modifiers); + AddTransform(ref builder, ComprehensiveTest.StackBuffer.Transform.Pack(ref builder, _o.Transform)); + AddHitPoints(ref builder, _hit_points); + AddRarity(ref builder, _o.Rarity); + AddValidColors(ref builder, _valid_colors); + AddWeaponTypeType(ref builder, _weapon_type_type); + AddWeaponType(ref builder, _weapon_type); + AddWeaponEquipmentType(ref builder, _weapon_equipment_type); + AddWeaponEquipment(ref builder, _weapon_equipment); + AddCompatibleTypesType(ref builder, _compatible_types_type); + AddCompatibleTypes(ref builder, _compatible_types); + AddCompatibleItemsType(ref builder, _compatible_items_type); + AddCompatibleItems(ref builder, _compatible_items); + AddMetadata(ref builder, _metadata); + AddFixedStats(ref builder, ComprehensiveTest.StackBuffer.FixedStats.Pack(ref builder, _o.FixedStats)); + AddPositionHistory(ref builder, ComprehensiveTest.StackBuffer.PositionHistory.Pack(ref builder, _o.PositionHistory)); + return EndWeapon(ref builder); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Status.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Status.cs new file mode 100644 index 00000000000..4ab895fb1b9 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Status.cs @@ -0,0 +1,17 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +public enum Status : int +{ + Unknown = -1, + Pending = 0, + Active = 1, + Inactive = 2, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Transform.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Transform.cs new file mode 100644 index 00000000000..ba638cad9b4 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Transform.cs @@ -0,0 +1,95 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Transform : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Transform __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ComprehensiveTest.Vec3 Position { get { return (new ComprehensiveTest.Vec3()).__assign(__p.bb_pos + 0, __p.bb); } } + public ComprehensiveTest.Vec3 Rotation { get { return (new ComprehensiveTest.Vec3()).__assign(__p.bb_pos + 12, __p.bb); } } + public ComprehensiveTest.Vec3 Scale { get { return (new ComprehensiveTest.Vec3()).__assign(__p.bb_pos + 24, __p.bb); } } + + public static Offset CreateTransform(FlatBufferBuilder builder, float position_X, float position_Y, float position_Z, float rotation_X, float rotation_Y, float rotation_Z, float scale_X, float scale_Y, float scale_Z) { + builder.Prep(4, 36); + builder.Prep(4, 12); + builder.Put(scale_Z); + builder.Put(scale_Y); + builder.Put(scale_X); + builder.Prep(4, 12); + builder.Put(rotation_Z); + builder.Put(rotation_Y); + builder.Put(rotation_X); + builder.Prep(4, 12); + builder.Put(position_Z); + builder.Put(position_Y); + builder.Put(position_X); + return new Offset(builder.Offset); + } + public TransformT UnPack() { + var _o = new TransformT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TransformT _o) { + if (_o.Position == null) _o.Position = new ComprehensiveTest.Vec3T(); + this.Position.UnPackTo(_o.Position); + if (_o.Rotation == null) _o.Rotation = new ComprehensiveTest.Vec3T(); + this.Rotation.UnPackTo(_o.Rotation); + if (_o.Scale == null) _o.Scale = new ComprehensiveTest.Vec3T(); + this.Scale.UnPackTo(_o.Scale); + } + public static Offset Pack(FlatBufferBuilder builder, TransformT _o) { + if (_o == null) return default(Offset); + var _position_x = _o.Position.X; + var _position_y = _o.Position.Y; + var _position_z = _o.Position.Z; + var _rotation_x = _o.Rotation.X; + var _rotation_y = _o.Rotation.Y; + var _rotation_z = _o.Rotation.Z; + var _scale_x = _o.Scale.X; + var _scale_y = _o.Scale.Y; + var _scale_z = _o.Scale.Z; + return CreateTransform( + builder, + _position_x, + _position_y, + _position_z, + _rotation_x, + _rotation_y, + _rotation_z, + _scale_x, + _scale_y, + _scale_z); + } +} + +public class TransformT +{ + public ComprehensiveTest.Vec3T Position { get; set; } + public ComprehensiveTest.Vec3T Rotation { get; set; } + public ComprehensiveTest.Vec3T Scale { get; set; } + + public TransformT() { + this.Position = new ComprehensiveTest.Vec3T(); + this.Rotation = new ComprehensiveTest.Vec3T(); + this.Scale = new ComprehensiveTest.Vec3T(); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Vec3.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Vec3.cs new file mode 100644 index 00000000000..921a391912b --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Vec3.cs @@ -0,0 +1,68 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Vec3 : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Vec3 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public float X { get { return __p.bb.Get(__p.bb_pos + 0); } } + public float Y { get { return __p.bb.Get(__p.bb_pos + 4); } } + public float Z { get { return __p.bb.Get(__p.bb_pos + 8); } } + + public static Offset CreateVec3(FlatBufferBuilder builder, float X, float Y, float Z) { + builder.Prep(4, 12); + builder.Put(Z); + builder.Put(Y); + builder.Put(X); + return new Offset(builder.Offset); + } + public Vec3T UnPack() { + var _o = new Vec3T(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(Vec3T _o) { + _o.X = this.X; + _o.Y = this.Y; + _o.Z = this.Z; + } + public static Offset Pack(FlatBufferBuilder builder, Vec3T _o) { + if (_o == null) return default(Offset); + return CreateVec3( + builder, + _o.X, + _o.Y, + _o.Z); + } +} + +public class Vec3T +{ + public float X { get; set; } + public float Y { get; set; } + public float Z { get; set; } + + public Vec3T() { + this.X = 0.0f; + this.Y = 0.0f; + this.Z = 0.0f; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Weapon.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Weapon.cs new file mode 100644 index 00000000000..6ff695e3db9 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/comprehensive_test/ComprehensiveTest/Weapon.cs @@ -0,0 +1,589 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace ComprehensiveTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Weapon : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Weapon GetRootAsWeapon(ByteBuffer _bb) { return GetRootAsWeapon(_bb, new Weapon()); } + public static Weapon GetRootAsWeapon(ByteBuffer _bb, Weapon obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Weapon __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public int Damage { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)10; } } + public float Durability { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)100.0f; } } + public bool Enchanted { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public StringVector? Tags { get { int o = __p.__offset(12); return o != 0 ? new StringVector(__p, o) : null; } } + public RefStructNullable> DamageValues { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public RefStructNullable> Modifiers { get { int o = __p.__offset(16); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(16)) : default; } } + public ComprehensiveTest.Transform? Transform { get { int o = __p.__offset(18); return o != 0 ? (ComprehensiveTest.Transform?)(new ComprehensiveTest.Transform()).__assign(o + __p.bb_pos, __p.bb) : null; } } + public StructVector? HitPoints { get { int o = __p.__offset(20); return o != 0 ? new StructVector(__p, o, 12) : null; } } + public ComprehensiveTest.Color Rarity { get { int o = __p.__offset(22); return o != 0 ? (ComprehensiveTest.Color)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Color.Red; } } + public RefStructNullable> ValidColors { get { int o = __p.__offset(24); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(24)) : default; } } + public ComprehensiveTest.Equipment WeaponTypeType { get { int o = __p.__offset(26); return o != 0 ? (ComprehensiveTest.Equipment)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Equipment.NONE; } } + public TTable? WeaponType() where TTable : struct, IFlatbufferObject { int o = __p.__offset(28); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public ComprehensiveTest.Weapon WeaponTypeAsWeapon() { return WeaponType().Value; } + public ComprehensiveTest.Armor WeaponTypeAsArmor() { return WeaponType().Value; } + public ComprehensiveTest.Equipment WeaponEquipmentType { get { int o = __p.__offset(30); return o != 0 ? (ComprehensiveTest.Equipment)__p.bb.Get(o + __p.bb_pos) : ComprehensiveTest.Equipment.NONE; } } + public TTable? WeaponEquipment() where TTable : struct, IFlatbufferObject { int o = __p.__offset(32); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public ComprehensiveTest.Weapon WeaponEquipmentAsWeapon() { return WeaponEquipment().Value; } + public ComprehensiveTest.Armor WeaponEquipmentAsArmor() { return WeaponEquipment().Value; } + public RefStructNullable> CompatibleTypesType { get { int o = __p.__offset(34); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(34)) : default; } } + public UnionVector? CompatibleTypes { get { int o = __p.__offset(36); return o != 0 ? new UnionVector(__p, o, 4) : null; } } + public RefStructNullable> CompatibleItemsType { get { int o = __p.__offset(38); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(38)) : default; } } + public UnionVector? CompatibleItems { get { int o = __p.__offset(40); return o != 0 ? new UnionVector(__p, o, 4) : null; } } + public RefStructNullable> Metadata { get { int o = __p.__offset(42); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(42)) : default; } } + public ComprehensiveTest.NestedData? GetMetadataAsNestedData() { int o = __p.__offset(42); return o != 0 ? (ComprehensiveTest.NestedData?)(new ComprehensiveTest.NestedData()).__assign(__p.__indirect(__p.__vector(o)), __p.bb) : null; } + public ComprehensiveTest.FixedStats? FixedStats { get { int o = __p.__offset(44); return o != 0 ? (ComprehensiveTest.FixedStats?)(new ComprehensiveTest.FixedStats()).__assign(o + __p.bb_pos, __p.bb) : null; } } + public ComprehensiveTest.PositionHistory? PositionHistory { get { int o = __p.__offset(46); return o != 0 ? (ComprehensiveTest.PositionHistory?)(new ComprehensiveTest.PositionHistory()).__assign(o + __p.bb_pos, __p.bb) : null; } } + + public static Offset CreateWeapon(FlatBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + int damage = 10, + float durability = 100.0f, + bool enchanted = false, + VectorOffset tagsOffset = default(VectorOffset), + VectorOffset damage_valuesOffset = default(VectorOffset), + VectorOffset modifiersOffset = default(VectorOffset), + ComprehensiveTest.TransformT transform = null, + VectorOffset hit_pointsOffset = default(VectorOffset), + ComprehensiveTest.Color rarity = ComprehensiveTest.Color.Red, + VectorOffset valid_colorsOffset = default(VectorOffset), + ComprehensiveTest.Equipment weapon_type_type = ComprehensiveTest.Equipment.NONE, + int weapon_typeOffset = 0, + ComprehensiveTest.Equipment weapon_equipment_type = ComprehensiveTest.Equipment.NONE, + int weapon_equipmentOffset = 0, + VectorOffset compatible_types_typeOffset = default(VectorOffset), + VectorOffset compatible_typesOffset = default(VectorOffset), + VectorOffset compatible_items_typeOffset = default(VectorOffset), + VectorOffset compatible_itemsOffset = default(VectorOffset), + VectorOffset metadataOffset = default(VectorOffset), + ComprehensiveTest.FixedStatsT fixed_stats = null, + ComprehensiveTest.PositionHistoryT position_history = null) { + builder.StartTable(22); + Weapon.AddPositionHistory(builder, ComprehensiveTest.PositionHistory.Pack(builder, position_history)); + Weapon.AddFixedStats(builder, ComprehensiveTest.FixedStats.Pack(builder, fixed_stats)); + Weapon.AddMetadata(builder, metadataOffset); + Weapon.AddCompatibleItems(builder, compatible_itemsOffset); + Weapon.AddCompatibleItemsType(builder, compatible_items_typeOffset); + Weapon.AddCompatibleTypes(builder, compatible_typesOffset); + Weapon.AddCompatibleTypesType(builder, compatible_types_typeOffset); + Weapon.AddWeaponEquipment(builder, weapon_equipmentOffset); + Weapon.AddWeaponType(builder, weapon_typeOffset); + Weapon.AddValidColors(builder, valid_colorsOffset); + Weapon.AddHitPoints(builder, hit_pointsOffset); + Weapon.AddTransform(builder, ComprehensiveTest.Transform.Pack(builder, transform)); + Weapon.AddModifiers(builder, modifiersOffset); + Weapon.AddDamageValues(builder, damage_valuesOffset); + Weapon.AddTags(builder, tagsOffset); + Weapon.AddDurability(builder, durability); + Weapon.AddDamage(builder, damage); + Weapon.AddName(builder, nameOffset); + Weapon.AddWeaponEquipmentType(builder, weapon_equipment_type); + Weapon.AddWeaponTypeType(builder, weapon_type_type); + Weapon.AddRarity(builder, rarity); + Weapon.AddEnchanted(builder, enchanted); + return Weapon.EndWeapon(builder); + } + + public static void StartWeapon(FlatBufferBuilder builder) { builder.StartTable(22); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddDamage(FlatBufferBuilder builder, int damage) { builder.Add(1, damage, 10); } + public static void AddDurability(FlatBufferBuilder builder, float durability) { builder.Add(2, durability, 100.0f); } + public static void AddEnchanted(FlatBufferBuilder builder, bool enchanted) { builder.Add(3, enchanted, false); } + public static void AddTags(FlatBufferBuilder builder, VectorOffset tagsOffset) { builder.AddOffset(4, tagsOffset, 0); } + public static VectorOffset CreateTagsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTagsVector(FlatBufferBuilder builder, Span data) { return CreateTagsVectorBlock(builder, data); } + public static void StartTagsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddDamageValues(FlatBufferBuilder builder, VectorOffset damageValuesOffset) { builder.AddOffset(5, damageValuesOffset, 0); } + public static VectorOffset CreateDamageValuesVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateDamageValuesVector(FlatBufferBuilder builder, Span data) { return CreateDamageValuesVectorBlock(builder, data); } + public static void StartDamageValuesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddModifiers(FlatBufferBuilder builder, VectorOffset modifiersOffset) { builder.AddOffset(6, modifiersOffset, 0); } + public static VectorOffset CreateModifiersVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateModifiersVector(FlatBufferBuilder builder, Span data) { return CreateModifiersVectorBlock(builder, data); } + public static void StartModifiersVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddTransform(FlatBufferBuilder builder, Offset transformOffset) { builder.AddStruct(7, transformOffset, 0); } + public static void AddHitPoints(FlatBufferBuilder builder, VectorOffset hitPointsOffset) { builder.AddOffset(8, hitPointsOffset, 0); } + public static void StartHitPointsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(12, numElems, 4); } + public static void AddRarity(FlatBufferBuilder builder, ComprehensiveTest.Color rarity) { builder.Add(9, (sbyte)rarity, 0); } + public static void AddValidColors(FlatBufferBuilder builder, VectorOffset validColorsOffset) { builder.AddOffset(10, validColorsOffset, 0); } + public static VectorOffset CreateValidColorsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateValidColorsVector(FlatBufferBuilder builder, Span data) { return CreateValidColorsVectorBlock(builder, data); } + public static void StartValidColorsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddWeaponTypeType(FlatBufferBuilder builder, ComprehensiveTest.Equipment weaponTypeType) { builder.Add(11, (byte)weaponTypeType, 0); } + public static void AddWeaponType(FlatBufferBuilder builder, int weaponTypeOffset) { builder.AddOffset(12, weaponTypeOffset, 0); } + public static void AddWeaponEquipmentType(FlatBufferBuilder builder, ComprehensiveTest.Equipment weaponEquipmentType) { builder.Add(13, (byte)weaponEquipmentType, 0); } + public static void AddWeaponEquipment(FlatBufferBuilder builder, int weaponEquipmentOffset) { builder.AddOffset(14, weaponEquipmentOffset, 0); } + public static void AddCompatibleTypesType(FlatBufferBuilder builder, VectorOffset compatibleTypesTypeOffset) { builder.AddOffset(15, compatibleTypesTypeOffset, 0); } + public static VectorOffset CreateCompatibleTypesTypeVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCompatibleTypesTypeVector(FlatBufferBuilder builder, Span data) { return CreateCompatibleTypesTypeVectorBlock(builder, data); } + public static void StartCompatibleTypesTypeVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddCompatibleTypes(FlatBufferBuilder builder, VectorOffset compatibleTypesOffset) { builder.AddOffset(16, compatibleTypesOffset, 0); } + public static VectorOffset CreateCompatibleTypesVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCompatibleTypesVector(FlatBufferBuilder builder, Span data) { return CreateCompatibleTypesVectorBlock(builder, data); } + public static void StartCompatibleTypesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddCompatibleItemsType(FlatBufferBuilder builder, VectorOffset compatibleItemsTypeOffset) { builder.AddOffset(17, compatibleItemsTypeOffset, 0); } + public static VectorOffset CreateCompatibleItemsTypeVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCompatibleItemsTypeVector(FlatBufferBuilder builder, Span data) { return CreateCompatibleItemsTypeVectorBlock(builder, data); } + public static void StartCompatibleItemsTypeVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddCompatibleItems(FlatBufferBuilder builder, VectorOffset compatibleItemsOffset) { builder.AddOffset(18, compatibleItemsOffset, 0); } + public static VectorOffset CreateCompatibleItemsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCompatibleItemsVector(FlatBufferBuilder builder, Span data) { return CreateCompatibleItemsVectorBlock(builder, data); } + public static void StartCompatibleItemsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddMetadata(FlatBufferBuilder builder, VectorOffset metadataOffset) { builder.AddOffset(19, metadataOffset, 0); } + public static VectorOffset CreateMetadataVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateMetadataVector(FlatBufferBuilder builder, Span data) { return CreateMetadataVectorBlock(builder, data); } + public static void StartMetadataVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddFixedStats(FlatBufferBuilder builder, Offset fixedStatsOffset) { builder.AddStruct(20, fixedStatsOffset, 0); } + public static void AddPositionHistory(FlatBufferBuilder builder, Offset positionHistoryOffset) { builder.AddStruct(21, positionHistoryOffset, 0); } + public static Offset EndWeapon(FlatBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 4); // name + return new Offset(o); + } + public WeaponT UnPack() { + var _o = new WeaponT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(WeaponT _o) { + _o.Name = this.Name; + _o.Damage = this.Damage; + _o.Durability = this.Durability; + _o.Enchanted = this.Enchanted; + var _tags_vec = this.Tags; + var _tags_len = _tags_vec.HasValue ? _tags_vec.Value.Length : 0; + if (_o.Tags == null) { + _o.Tags = new List(_tags_len); + } else { + _o.Tags.Clear(); + if (_o.Tags.Capacity < _tags_len) { + _o.Tags.Capacity = _tags_len; + } + } + if (_tags_vec.HasValue) { + var _tags_value = _tags_vec.Value; + for (var _j = 0; _j < _tags_len; ++_j) { _o.Tags.Add(_tags_value[_j]); } + } + var _damage_values_vec = this.DamageValues; + var _damage_values_len = _damage_values_vec.HasValue ? _damage_values_vec.Value.Length : 0; + if (_o.DamageValues == null) { + _o.DamageValues = new List(_damage_values_len); + } + ObjectApiUtil.ResizeList(_o.DamageValues, _damage_values_len); + if (_damage_values_vec.HasValue) { _damage_values_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.DamageValues)); } + var _modifiers_vec = this.Modifiers; + var _modifiers_len = _modifiers_vec.HasValue ? _modifiers_vec.Value.Length : 0; + if (_o.Modifiers == null) { + _o.Modifiers = new List(_modifiers_len); + } + ObjectApiUtil.ResizeList(_o.Modifiers, _modifiers_len); + if (_modifiers_vec.HasValue) { _modifiers_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Modifiers)); } + if (this.Transform.HasValue) { + if (_o.Transform == null) _o.Transform = new ComprehensiveTest.TransformT(); + this.Transform.Value.UnPackTo(_o.Transform); + } else { + _o.Transform = null; + } + var _hit_points_vec = this.HitPoints; + var _hit_points_len = _hit_points_vec.HasValue ? _hit_points_vec.Value.Length : 0; + if (_o.HitPoints == null) { + _o.HitPoints = new List(_hit_points_len); + } + ObjectApiUtil.ResizeList(_o.HitPoints, _hit_points_len); + if (_hit_points_vec.HasValue) { + var _hit_points_value = _hit_points_vec.Value; + for (var _j = 0; _j < _hit_points_len; ++_j) { + var _src = _hit_points_value[_j]; + if (_o.HitPoints[_j] == null) { _o.HitPoints[_j] = new Vec3T(); } + _src.UnPackTo(_o.HitPoints[_j]); + } + } + _o.Rarity = this.Rarity; + var _valid_colors_vec = this.ValidColors; + var _valid_colors_len = _valid_colors_vec.HasValue ? _valid_colors_vec.Value.Length : 0; + if (_o.ValidColors == null) { + _o.ValidColors = new List(_valid_colors_len); + } + ObjectApiUtil.ResizeList(_o.ValidColors, _valid_colors_len); + if (_valid_colors_vec.HasValue) { _valid_colors_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.ValidColors)); } + if (_o.WeaponType == null) { + _o.WeaponType = new ComprehensiveTest.EquipmentUnion(); + } + var _WeaponTypeOldType = _o.WeaponType.Type; + _o.WeaponType.Type = this.WeaponTypeType; + switch (this.WeaponTypeType) { + default: + _o.WeaponType.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (this.WeaponType().HasValue) { + if (_WeaponTypeOldType == ComprehensiveTest.Equipment.Weapon) { + this.WeaponType().Value.UnPackTo((ComprehensiveTest.WeaponT)_o.WeaponType.Value); + } else { + _o.WeaponType.Value = this.WeaponType().Value.UnPack(); + } + } else { + _o.WeaponType.Value = null; + } + break; + case ComprehensiveTest.Equipment.Armor: + if (this.WeaponType().HasValue) { + if (_WeaponTypeOldType == ComprehensiveTest.Equipment.Armor) { + this.WeaponType().Value.UnPackTo((ComprehensiveTest.ArmorT)_o.WeaponType.Value); + } else { + _o.WeaponType.Value = this.WeaponType().Value.UnPack(); + } + } else { + _o.WeaponType.Value = null; + } + break; + } + if (_o.WeaponEquipment == null) { + _o.WeaponEquipment = new ComprehensiveTest.EquipmentUnion(); + } + var _WeaponEquipmentOldType = _o.WeaponEquipment.Type; + _o.WeaponEquipment.Type = this.WeaponEquipmentType; + switch (this.WeaponEquipmentType) { + default: + _o.WeaponEquipment.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (this.WeaponEquipment().HasValue) { + if (_WeaponEquipmentOldType == ComprehensiveTest.Equipment.Weapon) { + this.WeaponEquipment().Value.UnPackTo((ComprehensiveTest.WeaponT)_o.WeaponEquipment.Value); + } else { + _o.WeaponEquipment.Value = this.WeaponEquipment().Value.UnPack(); + } + } else { + _o.WeaponEquipment.Value = null; + } + break; + case ComprehensiveTest.Equipment.Armor: + if (this.WeaponEquipment().HasValue) { + if (_WeaponEquipmentOldType == ComprehensiveTest.Equipment.Armor) { + this.WeaponEquipment().Value.UnPackTo((ComprehensiveTest.ArmorT)_o.WeaponEquipment.Value); + } else { + _o.WeaponEquipment.Value = this.WeaponEquipment().Value.UnPack(); + } + } else { + _o.WeaponEquipment.Value = null; + } + break; + } + var _compatible_types_types = this.CompatibleTypesType; + var _compatible_types = this.CompatibleTypes; + var _compatible_types_len = _compatible_types.HasValue ? _compatible_types.Value.Length : 0; + if (_o.CompatibleTypes == null) { + _o.CompatibleTypes = new List(_compatible_types_len); + } + ObjectApiUtil.ResizeList(_o.CompatibleTypes, _compatible_types_len); + if (_compatible_types.HasValue) { + var _compatible_types_value = _compatible_types.Value; + var _compatible_types_types_value = _compatible_types_types.Value; + for (var _j = 0; _j < _compatible_types_len; ++_j) { + var _compatible_types_type = _compatible_types_types_value[_j]; + var _o_CompatibleTypes = _o.CompatibleTypes[_j]; + if (_o_CompatibleTypes == null) { + _o_CompatibleTypes = new ComprehensiveTest.EquipmentUnion(); + _o.CompatibleTypes[_j] = _o_CompatibleTypes; + } + var _compatible_types_old_type = _o_CompatibleTypes.Type; + _o_CompatibleTypes.Type = _compatible_types_type; + switch (_compatible_types_type) { + default: + _o_CompatibleTypes.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (_compatible_types_old_type == ComprehensiveTest.Equipment.Weapon) { + _compatible_types_value.GetAs(_j).UnPackTo((ComprehensiveTest.WeaponT)_o_CompatibleTypes.Value); + } else { + _o_CompatibleTypes.Value = _compatible_types_value.GetAs(_j).UnPack(); + } + break; + case ComprehensiveTest.Equipment.Armor: + if (_compatible_types_old_type == ComprehensiveTest.Equipment.Armor) { + _compatible_types_value.GetAs(_j).UnPackTo((ComprehensiveTest.ArmorT)_o_CompatibleTypes.Value); + } else { + _o_CompatibleTypes.Value = _compatible_types_value.GetAs(_j).UnPack(); + } + break; + } + } + } + var _compatible_items_types = this.CompatibleItemsType; + var _compatible_items = this.CompatibleItems; + var _compatible_items_len = _compatible_items.HasValue ? _compatible_items.Value.Length : 0; + if (_o.CompatibleItems == null) { + _o.CompatibleItems = new List(_compatible_items_len); + } + ObjectApiUtil.ResizeList(_o.CompatibleItems, _compatible_items_len); + if (_compatible_items.HasValue) { + var _compatible_items_value = _compatible_items.Value; + var _compatible_items_types_value = _compatible_items_types.Value; + for (var _j = 0; _j < _compatible_items_len; ++_j) { + var _compatible_items_type = _compatible_items_types_value[_j]; + var _o_CompatibleItems = _o.CompatibleItems[_j]; + if (_o_CompatibleItems == null) { + _o_CompatibleItems = new ComprehensiveTest.EquipmentUnion(); + _o.CompatibleItems[_j] = _o_CompatibleItems; + } + var _compatible_items_old_type = _o_CompatibleItems.Type; + _o_CompatibleItems.Type = _compatible_items_type; + switch (_compatible_items_type) { + default: + _o_CompatibleItems.Value = null; + break; + case ComprehensiveTest.Equipment.Weapon: + if (_compatible_items_old_type == ComprehensiveTest.Equipment.Weapon) { + _compatible_items_value.GetAs(_j).UnPackTo((ComprehensiveTest.WeaponT)_o_CompatibleItems.Value); + } else { + _o_CompatibleItems.Value = _compatible_items_value.GetAs(_j).UnPack(); + } + break; + case ComprehensiveTest.Equipment.Armor: + if (_compatible_items_old_type == ComprehensiveTest.Equipment.Armor) { + _compatible_items_value.GetAs(_j).UnPackTo((ComprehensiveTest.ArmorT)_o_CompatibleItems.Value); + } else { + _o_CompatibleItems.Value = _compatible_items_value.GetAs(_j).UnPack(); + } + break; + } + } + } + var _metadata_vec = this.Metadata; + var _metadata_len = _metadata_vec.HasValue ? _metadata_vec.Value.Length : 0; + if (_o.Metadata == null) { + _o.Metadata = new List(_metadata_len); + } + ObjectApiUtil.ResizeList(_o.Metadata, _metadata_len); + if (_metadata_vec.HasValue) { _metadata_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Metadata)); } + if (this.FixedStats.HasValue) { + if (_o.FixedStats == null) _o.FixedStats = new ComprehensiveTest.FixedStatsT(); + this.FixedStats.Value.UnPackTo(_o.FixedStats); + } else { + _o.FixedStats = null; + } + if (this.PositionHistory.HasValue) { + if (_o.PositionHistory == null) _o.PositionHistory = new ComprehensiveTest.PositionHistoryT(); + this.PositionHistory.Value.UnPackTo(_o.PositionHistory); + } else { + _o.PositionHistory = null; + } + } + public static Offset Pack(FlatBufferBuilder builder, WeaponT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + var _tags = default(VectorOffset); + if (_o.Tags != null) { + var _tags_len = _o.Tags.Count; + StringOffset[] _tags_arr = null; + try { + Span __tags = _tags_len <= 64 + ? stackalloc StringOffset[_tags_len] + : (_tags_arr = ArrayPool.Shared.Rent(_tags_len)).AsSpan(0, _tags_len); + for (var _j = 0; _j < _tags_len; ++_j) { __tags[_j] = builder.CreateString(_o.Tags[_j]); } + _tags = CreateTagsVector(builder, __tags); + } finally { + if (_tags_arr != null) { ArrayPool.Shared.Return(_tags_arr); } + } + } + var _damage_values = default(VectorOffset); + if (_o.DamageValues != null) { + _damage_values = CreateDamageValuesVector(builder, CollectionsMarshal.AsSpan(_o.DamageValues)); + } + var _modifiers = default(VectorOffset); + if (_o.Modifiers != null) { + _modifiers = CreateModifiersVector(builder, CollectionsMarshal.AsSpan(_o.Modifiers)); + } + var _hit_points = default(VectorOffset); + if (_o.HitPoints != null) { + StartHitPointsVector(builder, _o.HitPoints.Count); + for (var _j = _o.HitPoints.Count - 1; _j >= 0; --_j) { ComprehensiveTest.Vec3.Pack(builder, _o.HitPoints[_j]); } + _hit_points = builder.EndVector(); + } + var _valid_colors = default(VectorOffset); + if (_o.ValidColors != null) { + _valid_colors = CreateValidColorsVector(builder, CollectionsMarshal.AsSpan(_o.ValidColors)); + } + var _weapon_type_type = _o.WeaponType == null ? ComprehensiveTest.Equipment.NONE : _o.WeaponType.Type; + var _weapon_type = _o.WeaponType == null ? 0 : ComprehensiveTest.EquipmentUnion.Pack(builder, _o.WeaponType); + var _weapon_equipment_type = _o.WeaponEquipment == null ? ComprehensiveTest.Equipment.NONE : _o.WeaponEquipment.Type; + var _weapon_equipment = _o.WeaponEquipment == null ? 0 : ComprehensiveTest.EquipmentUnion.Pack(builder, _o.WeaponEquipment); + var _compatible_types_type = default(VectorOffset); + if (_o.CompatibleTypes != null) { + var _compatible_types_type_len = _o.CompatibleTypes.Count; + ComprehensiveTest.Equipment[] _compatible_types_type_arr = null; + try { + Span __compatible_types_type = _compatible_types_type_len <= 256 + ? stackalloc ComprehensiveTest.Equipment[_compatible_types_type_len] + : (_compatible_types_type_arr = ArrayPool.Shared.Rent(_compatible_types_type_len)).AsSpan(0, _compatible_types_type_len); + for (var _j = 0; _j < _compatible_types_type_len; ++_j) { __compatible_types_type[_j] = _o.CompatibleTypes[_j].Type; } + _compatible_types_type = CreateCompatibleTypesTypeVector(builder, __compatible_types_type); + } finally { + if (_compatible_types_type_arr != null) { ArrayPool.Shared.Return(_compatible_types_type_arr); } + } + } + var _compatible_types = default(VectorOffset); + if (_o.CompatibleTypes != null) { + var _compatible_types_len = _o.CompatibleTypes.Count; + int[] _compatible_types_arr = null; + try { + Span __compatible_types = _compatible_types_len <= 64 + ? stackalloc int[_compatible_types_len] + : (_compatible_types_arr = ArrayPool.Shared.Rent(_compatible_types_len)).AsSpan(0, _compatible_types_len); + for (var _j = 0; _j < _compatible_types_len; ++_j) { __compatible_types[_j] = ComprehensiveTest.EquipmentUnion.Pack(builder, _o.CompatibleTypes[_j]); } + _compatible_types = CreateCompatibleTypesVector(builder, __compatible_types); + } finally { + if (_compatible_types_arr != null) { ArrayPool.Shared.Return(_compatible_types_arr); } + } + } + var _compatible_items_type = default(VectorOffset); + if (_o.CompatibleItems != null) { + var _compatible_items_type_len = _o.CompatibleItems.Count; + ComprehensiveTest.Equipment[] _compatible_items_type_arr = null; + try { + Span __compatible_items_type = _compatible_items_type_len <= 256 + ? stackalloc ComprehensiveTest.Equipment[_compatible_items_type_len] + : (_compatible_items_type_arr = ArrayPool.Shared.Rent(_compatible_items_type_len)).AsSpan(0, _compatible_items_type_len); + for (var _j = 0; _j < _compatible_items_type_len; ++_j) { __compatible_items_type[_j] = _o.CompatibleItems[_j].Type; } + _compatible_items_type = CreateCompatibleItemsTypeVector(builder, __compatible_items_type); + } finally { + if (_compatible_items_type_arr != null) { ArrayPool.Shared.Return(_compatible_items_type_arr); } + } + } + var _compatible_items = default(VectorOffset); + if (_o.CompatibleItems != null) { + var _compatible_items_len = _o.CompatibleItems.Count; + int[] _compatible_items_arr = null; + try { + Span __compatible_items = _compatible_items_len <= 64 + ? stackalloc int[_compatible_items_len] + : (_compatible_items_arr = ArrayPool.Shared.Rent(_compatible_items_len)).AsSpan(0, _compatible_items_len); + for (var _j = 0; _j < _compatible_items_len; ++_j) { __compatible_items[_j] = ComprehensiveTest.EquipmentUnion.Pack(builder, _o.CompatibleItems[_j]); } + _compatible_items = CreateCompatibleItemsVector(builder, __compatible_items); + } finally { + if (_compatible_items_arr != null) { ArrayPool.Shared.Return(_compatible_items_arr); } + } + } + var _metadata = default(VectorOffset); + if (_o.Metadata != null) { + _metadata = CreateMetadataVector(builder, CollectionsMarshal.AsSpan(_o.Metadata)); + } + return CreateWeapon( + builder, + _name, + _o.Damage, + _o.Durability, + _o.Enchanted, + _tags, + _damage_values, + _modifiers, + _o.Transform, + _hit_points, + _o.Rarity, + _valid_colors, + _weapon_type_type, + _weapon_type, + _weapon_equipment_type, + _weapon_equipment, + _compatible_types_type, + _compatible_types, + _compatible_items_type, + _compatible_items, + _metadata, + _o.FixedStats, + _o.PositionHistory); + } +} + +public class WeaponT +{ + public string Name { get; set; } + public int Damage { get; set; } + public float Durability { get; set; } + public bool Enchanted { get; set; } + public List Tags { get; set; } + public List DamageValues { get; set; } + public List Modifiers { get; set; } + public ComprehensiveTest.TransformT Transform { get; set; } + public List HitPoints { get; set; } + public ComprehensiveTest.Color Rarity { get; set; } + public List ValidColors { get; set; } + public ComprehensiveTest.EquipmentUnion WeaponType { get; set; } + public ComprehensiveTest.EquipmentUnion WeaponEquipment { get; set; } + public List CompatibleTypes { get; set; } + public List CompatibleItems { get; set; } + public List Metadata { get; set; } + public ComprehensiveTest.FixedStatsT FixedStats { get; set; } + public ComprehensiveTest.PositionHistoryT PositionHistory { get; set; } + + public WeaponT() { + this.Name = null; + this.Damage = 10; + this.Durability = 100.0f; + this.Enchanted = false; + this.Tags = null; + this.DamageValues = null; + this.Modifiers = null; + this.Transform = new ComprehensiveTest.TransformT(); + this.HitPoints = null; + this.Rarity = ComprehensiveTest.Color.Red; + this.ValidColors = null; + this.WeaponType = null; + this.WeaponEquipment = null; + this.CompatibleTypes = null; + this.CompatibleItems = null; + this.Metadata = null; + this.FixedStats = new ComprehensiveTest.FixedStatsT(); + this.PositionHistory = new ComprehensiveTest.PositionHistoryT(); + } +} + + +static public class WeaponVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*Name*/, true) + && verifier.VerifyField(tablePos, 6 /*Damage*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 8 /*Durability*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 10 /*Enchanted*/, 1 /*bool*/, 1, false) + && verifier.VerifyVectorOfStrings(tablePos, 12 /*Tags*/, false) + && verifier.VerifyVectorOfData(tablePos, 14 /*DamageValues*/, 4 /*int*/, false) + && verifier.VerifyVectorOfData(tablePos, 16 /*Modifiers*/, 4 /*float*/, false) + && verifier.VerifyField(tablePos, 18 /*Transform*/, 36 /*ComprehensiveTest.Transform*/, 4, false) + && verifier.VerifyVectorOfData(tablePos, 20 /*HitPoints*/, 12 /*ComprehensiveTest.Vec3*/, false) + && verifier.VerifyField(tablePos, 22 /*Rarity*/, 1 /*ComprehensiveTest.Color*/, 1, false) + && verifier.VerifyVectorOfData(tablePos, 24 /*ValidColors*/, 1 /*ComprehensiveTest.Color*/, false) + && verifier.VerifyField(tablePos, 26 /*WeaponTypeType*/, 1 /*ComprehensiveTest.Equipment*/, 1, false) + && verifier.VerifyUnion(tablePos, 26, 28 /*WeaponType*/, ComprehensiveTest.EquipmentVerify.Verify, false) + && verifier.VerifyField(tablePos, 30 /*WeaponEquipmentType*/, 1 /*ComprehensiveTest.Equipment*/, 1, false) + && verifier.VerifyUnion(tablePos, 30, 32 /*WeaponEquipment*/, ComprehensiveTest.EquipmentVerify.Verify, false) + && verifier.VerifyVectorOfData(tablePos, 34 /*CompatibleTypesType*/, 1 /*ComprehensiveTest.Equipment*/, false) + && verifier.VerifyVectorOfData(tablePos, 38 /*CompatibleItemsType*/, 1 /*ComprehensiveTest.Equipment*/, false) + && verifier.VerifyNestedBuffer(tablePos, 42 /*Metadata*/, ComprehensiveTest.NestedDataVerify.Verify, false) + && verifier.VerifyField(tablePos, 44 /*FixedStats*/, 16 /*ComprehensiveTest.FixedStats*/, 4, false) + && verifier.VerifyField(tablePos, 46 /*PositionHistory*/, 120 /*ComprehensiveTest.PositionHistory*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Armor.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Armor.cs new file mode 100644 index 00000000000..e9f42c61e1d --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Armor.cs @@ -0,0 +1,90 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Armor : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Armor GetRootAsArmor(ByteBuffer _bb) { return GetRootAsArmor(_bb, new Armor()); } + public static Armor GetRootAsArmor(ByteBuffer _bb, Armor obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Armor __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public int Defense { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateArmor(FlatBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + int defense = 0) { + builder.StartTable(2); + Armor.AddDefense(builder, defense); + Armor.AddName(builder, nameOffset); + return Armor.EndArmor(builder); + } + + public static void StartArmor(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddDefense(FlatBufferBuilder builder, int defense) { builder.Add(1, defense, 0); } + public static Offset EndArmor(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public ArmorT UnPack() { + var _o = new ArmorT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ArmorT _o) { + _o.Name = this.Name; + _o.Defense = this.Defense; + } + public static Offset Pack(FlatBufferBuilder builder, ArmorT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateArmor( + builder, + _name, + _o.Defense); + } +} + +public class ArmorT +{ + [System.Text.Json.Serialization.JsonPropertyName("name")] + public string Name { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("defense")] + public int Defense { get; set; } + + public ArmorT() { + this.Name = null; + this.Defense = 0; + } +} + + +static public class ArmorVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*Name*/, false) + && verifier.VerifyField(tablePos, 6 /*Defense*/, 4 /*int*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Color.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Color.cs new file mode 100644 index 00000000000..f6817c73fcd --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Color.cs @@ -0,0 +1,78 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Color : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Color __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public byte R { get { return __p.bb.Get(__p.bb_pos + 0); } } + public byte G { get { return __p.bb.Get(__p.bb_pos + 1); } } + public byte B { get { return __p.bb.Get(__p.bb_pos + 2); } } + public byte A { get { return __p.bb.Get(__p.bb_pos + 3); } } + + public static Offset CreateColor(FlatBufferBuilder builder, byte R, byte G, byte B, byte A) { + builder.Prep(1, 4); + builder.Put(A); + builder.Put(B); + builder.Put(G); + builder.Put(R); + return new Offset(builder.Offset); + } + public ColorT UnPack() { + var _o = new ColorT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ColorT _o) { + _o.R = this.R; + _o.G = this.G; + _o.B = this.B; + _o.A = this.A; + } + public static Offset Pack(FlatBufferBuilder builder, ColorT _o) { + if (_o == null) return default(Offset); + return CreateColor( + builder, + _o.R, + _o.G, + _o.B, + _o.A); + } +} + +public class ColorT +{ + [System.Text.Json.Serialization.JsonPropertyName("r")] + public byte R { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("g")] + public byte G { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("b")] + public byte B { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("a")] + public byte A { get; set; } + + public ColorT() { + this.R = 0; + this.G = 0; + this.B = 0; + this.A = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Equipment.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Equipment.cs new file mode 100644 index 00000000000..20ea59bd3f1 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Equipment.cs @@ -0,0 +1,115 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +public enum Equipment : byte +{ + NONE = 0, + Weapon = 1, + Armor = 2, +}; + +[System.Text.Json.Serialization.JsonConverter(typeof(EquipmentUnion_JsonConverter))] +public class EquipmentUnion { + public Equipment Type { get; set; } + public object Value { get; set; } + + public EquipmentUnion() { + this.Type = Equipment.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public JsonTest.WeaponT AsWeapon() { return this.As(); } + public static EquipmentUnion FromWeapon(JsonTest.WeaponT _weapon) { return new EquipmentUnion{ Type = Equipment.Weapon, Value = _weapon }; } + public JsonTest.ArmorT AsArmor() { return this.As(); } + public static EquipmentUnion FromArmor(JsonTest.ArmorT _armor) { return new EquipmentUnion{ Type = Equipment.Armor, Value = _armor }; } + + public static int Pack(Google.FlatSpanBuffers.FlatBufferBuilder builder, EquipmentUnion _o) { + switch (_o.Type) { + default: return 0; + case Equipment.Weapon: return JsonTest.Weapon.Pack(builder, _o.AsWeapon()).Value; + case Equipment.Armor: return JsonTest.Armor.Pack(builder, _o.AsArmor()).Value; + } + } + public static int Pack(ref Google.FlatSpanBuffers.FlatSpanBufferBuilder builder, EquipmentUnion _o) { + switch (_o.Type) { + default: return 0; + case Equipment.Weapon: return JsonTest.StackBuffer.Weapon.Pack(ref builder, _o.AsWeapon()).Value; + case Equipment.Armor: return JsonTest.StackBuffer.Armor.Pack(ref builder, _o.AsArmor()).Value; + } + } +} + +public class EquipmentUnion_JsonConverter : System.Text.Json.Serialization.JsonConverter { + public override EquipmentUnion Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { + if (reader.TokenType == System.Text.Json.JsonTokenType.Null) { reader.Read(); return null; } + if (reader.TokenType != System.Text.Json.JsonTokenType.StartObject) throw new System.Text.Json.JsonException("Expected start of object for union type"); + Equipment unionType = Equipment.NONE; + EquipmentUnion result = new EquipmentUnion(); + while (reader.Read()) { + if (reader.TokenType == System.Text.Json.JsonTokenType.EndObject) break; + if (reader.TokenType != System.Text.Json.JsonTokenType.PropertyName) continue; + string propName = reader.GetString(); + reader.Read(); + if (propName == "Type") { + string typeName = reader.GetString(); + if (System.Enum.TryParse(typeName, out var parsed)) unionType = parsed; + } else if (propName == "Value") { + result.Type = unionType; + switch (unionType) { + default: break; + case Equipment.Weapon: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Equipment.Armor: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + } + } + return result; + } + public EquipmentUnion ReadWithTypeContext(ref System.Text.Json.Utf8JsonReader reader, EquipmentUnion _o, System.Text.Json.JsonSerializerOptions options) { + if (_o == null) return null; + switch (_o.Type) { + default: break; + case Equipment.Weapon: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Equipment.Armor: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + return _o; + } + public override void Write(System.Text.Json.Utf8JsonWriter writer, EquipmentUnion value, System.Text.Json.JsonSerializerOptions options) { + if (value == null || value.Value == null) { writer.WriteNullValue(); return; } + writer.WriteStartObject(); + writer.WriteString("Type", value.Type.ToString()); + writer.WritePropertyName("Value"); + System.Text.Json.JsonSerializer.Serialize(writer, value.Value, value.Value.GetType(), options); + writer.WriteEndObject(); + } +} + + + +static public class EquipmentVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, byte typeId, uint tablePos) + { + bool result = true; + switch((Equipment)typeId) + { + case Equipment.Weapon: + result = JsonTest.WeaponVerify.Verify(ref verifier, tablePos); + break; + case Equipment.Armor: + result = JsonTest.ArmorVerify.Verify(ref verifier, tablePos); + break; + default: result = true; + break; + } + return result; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/GameState.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/GameState.cs new file mode 100644 index 00000000000..2a3223d212b --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/GameState.cs @@ -0,0 +1,161 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct GameState : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static GameState GetRootAsGameState(ByteBuffer _bb) { return GetRootAsGameState(_bb, new GameState()); } + public static GameState GetRootAsGameState(ByteBuffer _bb, GameState obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool GameStateBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "JSON"); } + public static bool VerifyGameState(ByteBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("JSON", false, JsonTest.GameStateVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public GameState __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Version { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetVersionBytes() { return __p.__vector_as_span(4); } + public TableVector? Players { get { int o = __p.__offset(6); return o != 0 ? new TableVector(__p, o, 4) : null; } } + public bool TryGetPlayersByKey(string key, out JsonTest.Player value) { int o = __p.__offset(6); if (o != 0) { return JsonTest.Player.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public long ActivePlayerId { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public long Timestamp { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + + public static Offset CreateGameState(FlatBufferBuilder builder, + StringOffset versionOffset = default(StringOffset), + VectorOffset playersOffset = default(VectorOffset), + long active_player_id = 0, + long timestamp = 0) { + builder.StartTable(4); + GameState.AddTimestamp(builder, timestamp); + GameState.AddActivePlayerId(builder, active_player_id); + GameState.AddPlayers(builder, playersOffset); + GameState.AddVersion(builder, versionOffset); + return GameState.EndGameState(builder); + } + + public static void StartGameState(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddVersion(FlatBufferBuilder builder, StringOffset versionOffset) { builder.AddOffset(0, versionOffset, 0); } + public static void AddPlayers(FlatBufferBuilder builder, VectorOffset playersOffset) { builder.AddOffset(1, playersOffset, 0); } + public static VectorOffset CreatePlayersVectorBlock(FlatBufferBuilder builder, Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreatePlayersVector(FlatBufferBuilder builder, Span> data) { return CreatePlayersVectorBlock(builder, data); } + public static void StartPlayersVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddActivePlayerId(FlatBufferBuilder builder, long activePlayerId) { builder.Add(2, activePlayerId, 0); } + public static void AddTimestamp(FlatBufferBuilder builder, long timestamp) { builder.Add(3, timestamp, 0); } + public static Offset EndGameState(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishGameStateBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "JSON"); } + public static void FinishSizePrefixedGameStateBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "JSON"); } + public GameStateT UnPack() { + var _o = new GameStateT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(GameStateT _o) { + _o.Version = this.Version; + var _players_vec = this.Players; + var _players_len = _players_vec.HasValue ? _players_vec.Value.Length : 0; + if (_o.Players == null) { + _o.Players = new List(_players_len); + } + ObjectApiUtil.ResizeList(_o.Players, _players_len); + if (_players_vec.HasValue) { + var _players_value = _players_vec.Value; + for (var _j = 0; _j < _players_len; ++_j) { + var _src = _players_value[_j]; + if (_o.Players[_j] == null) { _o.Players[_j] = new PlayerT(); } + _src.UnPackTo(_o.Players[_j]); + } + } + _o.ActivePlayerId = this.ActivePlayerId; + _o.Timestamp = this.Timestamp; + } + public static Offset Pack(FlatBufferBuilder builder, GameStateT _o) { + if (_o == null) return default(Offset); + var _version = _o.Version == null ? default(StringOffset) : builder.CreateString(_o.Version); + var _players = default(VectorOffset); + if (_o.Players != null) { + var _players_len = _o.Players.Count; + Offset[] _players_arr = null; + try { + Span> __players = _players_len <= 64 + ? stackalloc Offset[_players_len] + : (_players_arr = ArrayPool>.Shared.Rent(_players_len)).AsSpan(0, _players_len); + for (var _j = 0; _j < _players_len; ++_j) { __players[_j] = JsonTest.Player.Pack(builder, _o.Players[_j]); } + _players = CreatePlayersVector(builder, __players); + } finally { + if (_players_arr != null) { ArrayPool>.Shared.Return(_players_arr); } + } + } + return CreateGameState( + builder, + _version, + _players, + _o.ActivePlayerId, + _o.Timestamp); + } +} + +public class GameStateT +{ + [System.Text.Json.Serialization.JsonPropertyName("version")] + public string Version { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("players")] + public List Players { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("active_player_id")] + public long ActivePlayerId { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("timestamp")] + public long Timestamp { get; set; } + + public GameStateT() { + this.Version = null; + this.Players = null; + this.ActivePlayerId = 0; + this.Timestamp = 0; + } + + private static readonly System.Text.Json.JsonSerializerOptions _jsonOptions = new System.Text.Json.JsonSerializerOptions { WriteIndented = true, NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals, Converters = { new System.Text.Json.Serialization.JsonStringEnumConverter() } }; + public static GameStateT DeserializeFromJson(string jsonText) { + return System.Text.Json.JsonSerializer.Deserialize(jsonText, _jsonOptions); + } + public string SerializeToJson() { + return System.Text.Json.JsonSerializer.Serialize(this, _jsonOptions); + } + public static GameStateT DeserializeFromBinary(byte[] fbBuffer) { + return GameState.GetRootAsGameState(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + GameState.FinishGameStateBuffer(fbb, GameState.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedSpan().ToArray(); + } +} + + +static public class GameStateVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*Version*/, false) + && verifier.VerifyVectorOfTables(tablePos, 6 /*Players*/, JsonTest.PlayerVerify.Verify, false) + && verifier.VerifyField(tablePos, 8 /*ActivePlayerId*/, 8 /*long*/, 8, false) + && verifier.VerifyField(tablePos, 10 /*Timestamp*/, 8 /*long*/, 8, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Item.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Item.cs new file mode 100644 index 00000000000..1bfefe5dbe2 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Item.cs @@ -0,0 +1,110 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Item : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Item GetRootAsItem(ByteBuffer _bb) { return GetRootAsItem(_bb, new Item()); } + public static Item GetRootAsItem(ByteBuffer _bb, Item obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Item __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(6); } + public float Value { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)0.0f; } } + + public static Offset CreateItem(FlatBufferBuilder builder, + int id = 0, + StringOffset nameOffset = default(StringOffset), + float value = 0.0f) { + builder.StartTable(3); + Item.AddValue(builder, value); + Item.AddName(builder, nameOffset); + Item.AddId(builder, id); + return Item.EndItem(builder); + } + + public static void StartItem(FlatBufferBuilder builder) { builder.StartTable(3); } + public static void AddId(FlatBufferBuilder builder, int id) { builder.Add(0, id, 0); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset, 0); } + public static void AddValue(FlatBufferBuilder builder, float value) { builder.Add(2, value, 0.0f); } + public static Offset EndItem(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfItem(FlatBufferBuilder builder, Span> offsets) { + var comparer = new SortedVectorUtils.ScalarOffsetComparer(builder.DataBuffer, 4); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, int key, ByteBuffer bb, out Item value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 4, 0, out value); + } + public ItemT UnPack() { + var _o = new ItemT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ItemT _o) { + _o.Id = this.Id; + _o.Name = this.Name; + _o.Value = this.Value; + } + public static Offset Pack(FlatBufferBuilder builder, ItemT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateItem( + builder, + _o.Id, + _name, + _o.Value); + } +} + +public class ItemT +{ + [System.Text.Json.Serialization.JsonPropertyName("id")] + public int Id { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("name")] + public string Name { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("value")] + public float Value { get; set; } + + public ItemT() { + this.Id = 0; + this.Name = null; + this.Value = 0.0f; + } +} + + +static public class ItemVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Id*/, 4 /*int*/, 4, false) + && verifier.VerifyString(tablePos, 6 /*Name*/, false) + && verifier.VerifyField(tablePos, 8 /*Value*/, 4 /*float*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Player.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Player.cs new file mode 100644 index 00000000000..7f4c8d8e9f2 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Player.cs @@ -0,0 +1,337 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Player : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Player GetRootAsPlayer(ByteBuffer _bb) { return GetRootAsPlayer(_bb, new Player()); } + public static Player GetRootAsPlayer(ByteBuffer _bb, Player obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Player __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public long Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(6); } + public int Level { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)1; } } + public float Health { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)100.0f; } } + public JsonTest.Vec2? Position { get { int o = __p.__offset(12); return o != 0 ? (JsonTest.Vec2?)(new JsonTest.Vec2()).__assign(o + __p.bb_pos, __p.bb) : null; } } + public JsonTest.Status Status { get { int o = __p.__offset(14); return o != 0 ? (JsonTest.Status)__p.bb.Get(o + __p.bb_pos) : JsonTest.Status.Active; } } + public JsonTest.Priority Priorities { get { int o = __p.__offset(16); return o != 0 ? (JsonTest.Priority)__p.bb.Get(o + __p.bb_pos) : 0; } } + public TableVector? Inventory { get { int o = __p.__offset(18); return o != 0 ? new TableVector(__p, o, 4) : null; } } + public bool TryGetInventoryByKey(int key, out JsonTest.Item value) { int o = __p.__offset(18); if (o != 0) { return JsonTest.Item.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public JsonTest.Equipment EquippedType { get { int o = __p.__offset(20); return o != 0 ? (JsonTest.Equipment)__p.bb.Get(o + __p.bb_pos) : JsonTest.Equipment.NONE; } } + public TTable? Equipped() where TTable : struct, IFlatbufferObject { int o = __p.__offset(22); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public JsonTest.Weapon EquippedAsWeapon() { return Equipped().Value; } + public JsonTest.Armor EquippedAsArmor() { return Equipped().Value; } + public StringVector? Tags { get { int o = __p.__offset(24); return o != 0 ? new StringVector(__p, o) : null; } } + public RefStructNullable> Scores { get { int o = __p.__offset(26); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(26)) : default; } } + public JsonTest.Color? Color { get { int o = __p.__offset(28); return o != 0 ? (JsonTest.Color?)(new JsonTest.Color()).__assign(o + __p.bb_pos, __p.bb) : null; } } + + public static Offset CreatePlayer(FlatBufferBuilder builder, + long id = 0, + StringOffset nameOffset = default(StringOffset), + int level = 1, + float health = 100.0f, + JsonTest.Vec2T position = null, + JsonTest.Status status = JsonTest.Status.Active, + JsonTest.Priority priorities = 0, + VectorOffset inventoryOffset = default(VectorOffset), + JsonTest.Equipment equipped_type = JsonTest.Equipment.NONE, + int equippedOffset = 0, + VectorOffset tagsOffset = default(VectorOffset), + VectorOffset scoresOffset = default(VectorOffset), + JsonTest.ColorT color = null) { + builder.StartTable(13); + Player.AddId(builder, id); + Player.AddColor(builder, JsonTest.Color.Pack(builder, color)); + Player.AddScores(builder, scoresOffset); + Player.AddTags(builder, tagsOffset); + Player.AddEquipped(builder, equippedOffset); + Player.AddInventory(builder, inventoryOffset); + Player.AddPosition(builder, JsonTest.Vec2.Pack(builder, position)); + Player.AddHealth(builder, health); + Player.AddLevel(builder, level); + Player.AddName(builder, nameOffset); + Player.AddEquippedType(builder, equipped_type); + Player.AddPriorities(builder, priorities); + Player.AddStatus(builder, status); + return Player.EndPlayer(builder); + } + + public static void StartPlayer(FlatBufferBuilder builder) { builder.StartTable(13); } + public static void AddId(FlatBufferBuilder builder, long id) { builder.Add(0, id, 0); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset, 0); } + public static void AddLevel(FlatBufferBuilder builder, int level) { builder.Add(2, level, 1); } + public static void AddHealth(FlatBufferBuilder builder, float health) { builder.Add(3, health, 100.0f); } + public static void AddPosition(FlatBufferBuilder builder, Offset positionOffset) { builder.AddStruct(4, positionOffset, 0); } + public static void AddStatus(FlatBufferBuilder builder, JsonTest.Status status) { builder.Add(5, (sbyte)status, 1); } + public static void AddPriorities(FlatBufferBuilder builder, JsonTest.Priority priorities) { builder.Add(6, (byte)priorities, 0); } + public static void AddInventory(FlatBufferBuilder builder, VectorOffset inventoryOffset) { builder.AddOffset(7, inventoryOffset, 0); } + public static VectorOffset CreateInventoryVectorBlock(FlatBufferBuilder builder, Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateInventoryVector(FlatBufferBuilder builder, Span> data) { return CreateInventoryVectorBlock(builder, data); } + public static void StartInventoryVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddEquippedType(FlatBufferBuilder builder, JsonTest.Equipment equippedType) { builder.Add(8, (byte)equippedType, 0); } + public static void AddEquipped(FlatBufferBuilder builder, int equippedOffset) { builder.AddOffset(9, equippedOffset, 0); } + public static void AddTags(FlatBufferBuilder builder, VectorOffset tagsOffset) { builder.AddOffset(10, tagsOffset, 0); } + public static VectorOffset CreateTagsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTagsVector(FlatBufferBuilder builder, Span data) { return CreateTagsVectorBlock(builder, data); } + public static void StartTagsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddScores(FlatBufferBuilder builder, VectorOffset scoresOffset) { builder.AddOffset(11, scoresOffset, 0); } + public static VectorOffset CreateScoresVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateScoresVector(FlatBufferBuilder builder, Span data) { return CreateScoresVectorBlock(builder, data); } + public static void StartScoresVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddColor(FlatBufferBuilder builder, Offset colorOffset) { builder.AddStruct(12, colorOffset, 0); } + public static Offset EndPlayer(FlatBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 6); // name + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfPlayer(FlatBufferBuilder builder, Span> offsets) { + var comparer = new SortedVectorUtils.VectorOffsetComparer(builder.DataBuffer, 6); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, string key, ByteBuffer bb, out Player value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 6, out value); + } + public PlayerT UnPack() { + var _o = new PlayerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(PlayerT _o) { + _o.Id = this.Id; + _o.Name = this.Name; + _o.Level = this.Level; + _o.Health = this.Health; + if (this.Position.HasValue) { + if (_o.Position == null) _o.Position = new JsonTest.Vec2T(); + this.Position.Value.UnPackTo(_o.Position); + } else { + _o.Position = null; + } + _o.Status = this.Status; + _o.Priorities = this.Priorities; + var _inventory_vec = this.Inventory; + var _inventory_len = _inventory_vec.HasValue ? _inventory_vec.Value.Length : 0; + if (_o.Inventory == null) { + _o.Inventory = new List(_inventory_len); + } + ObjectApiUtil.ResizeList(_o.Inventory, _inventory_len); + if (_inventory_vec.HasValue) { + var _inventory_value = _inventory_vec.Value; + for (var _j = 0; _j < _inventory_len; ++_j) { + var _src = _inventory_value[_j]; + if (_o.Inventory[_j] == null) { _o.Inventory[_j] = new ItemT(); } + _src.UnPackTo(_o.Inventory[_j]); + } + } + if (_o.Equipped == null) { + _o.Equipped = new JsonTest.EquipmentUnion(); + } + var _EquippedOldType = _o.Equipped.Type; + _o.Equipped.Type = this.EquippedType; + switch (this.EquippedType) { + default: + _o.Equipped.Value = null; + break; + case JsonTest.Equipment.Weapon: + if (this.Equipped().HasValue) { + if (_EquippedOldType == JsonTest.Equipment.Weapon) { + this.Equipped().Value.UnPackTo((JsonTest.WeaponT)_o.Equipped.Value); + } else { + _o.Equipped.Value = this.Equipped().Value.UnPack(); + } + } else { + _o.Equipped.Value = null; + } + break; + case JsonTest.Equipment.Armor: + if (this.Equipped().HasValue) { + if (_EquippedOldType == JsonTest.Equipment.Armor) { + this.Equipped().Value.UnPackTo((JsonTest.ArmorT)_o.Equipped.Value); + } else { + _o.Equipped.Value = this.Equipped().Value.UnPack(); + } + } else { + _o.Equipped.Value = null; + } + break; + } + var _tags_vec = this.Tags; + var _tags_len = _tags_vec.HasValue ? _tags_vec.Value.Length : 0; + if (_o.Tags == null) { + _o.Tags = new List(_tags_len); + } else { + _o.Tags.Clear(); + if (_o.Tags.Capacity < _tags_len) { + _o.Tags.Capacity = _tags_len; + } + } + if (_tags_vec.HasValue) { + var _tags_value = _tags_vec.Value; + for (var _j = 0; _j < _tags_len; ++_j) { _o.Tags.Add(_tags_value[_j]); } + } + var _scores_vec = this.Scores; + var _scores_len = _scores_vec.HasValue ? _scores_vec.Value.Length : 0; + if (_o.Scores == null) { + _o.Scores = new List(_scores_len); + } + ObjectApiUtil.ResizeList(_o.Scores, _scores_len); + if (_scores_vec.HasValue) { _scores_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Scores)); } + if (this.Color.HasValue) { + if (_o.Color == null) _o.Color = new JsonTest.ColorT(); + this.Color.Value.UnPackTo(_o.Color); + } else { + _o.Color = null; + } + } + public static Offset Pack(FlatBufferBuilder builder, PlayerT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + var _inventory = default(VectorOffset); + if (_o.Inventory != null) { + var _inventory_len = _o.Inventory.Count; + Offset[] _inventory_arr = null; + try { + Span> __inventory = _inventory_len <= 64 + ? stackalloc Offset[_inventory_len] + : (_inventory_arr = ArrayPool>.Shared.Rent(_inventory_len)).AsSpan(0, _inventory_len); + for (var _j = 0; _j < _inventory_len; ++_j) { __inventory[_j] = JsonTest.Item.Pack(builder, _o.Inventory[_j]); } + _inventory = CreateInventoryVector(builder, __inventory); + } finally { + if (_inventory_arr != null) { ArrayPool>.Shared.Return(_inventory_arr); } + } + } + var _equipped_type = _o.Equipped == null ? JsonTest.Equipment.NONE : _o.Equipped.Type; + var _equipped = _o.Equipped == null ? 0 : JsonTest.EquipmentUnion.Pack(builder, _o.Equipped); + var _tags = default(VectorOffset); + if (_o.Tags != null) { + var _tags_len = _o.Tags.Count; + StringOffset[] _tags_arr = null; + try { + Span __tags = _tags_len <= 64 + ? stackalloc StringOffset[_tags_len] + : (_tags_arr = ArrayPool.Shared.Rent(_tags_len)).AsSpan(0, _tags_len); + for (var _j = 0; _j < _tags_len; ++_j) { __tags[_j] = builder.CreateString(_o.Tags[_j]); } + _tags = CreateTagsVector(builder, __tags); + } finally { + if (_tags_arr != null) { ArrayPool.Shared.Return(_tags_arr); } + } + } + var _scores = default(VectorOffset); + if (_o.Scores != null) { + _scores = CreateScoresVector(builder, CollectionsMarshal.AsSpan(_o.Scores)); + } + return CreatePlayer( + builder, + _o.Id, + _name, + _o.Level, + _o.Health, + _o.Position, + _o.Status, + _o.Priorities, + _inventory, + _equipped_type, + _equipped, + _tags, + _scores, + _o.Color); + } +} + +public class PlayerT +{ + [System.Text.Json.Serialization.JsonPropertyName("id")] + public long Id { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("name")] + public string Name { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("level")] + public int Level { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("health")] + public float Health { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("position")] + public JsonTest.Vec2T Position { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("status")] + public JsonTest.Status Status { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("priorities")] + public JsonTest.Priority Priorities { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("inventory")] + public List Inventory { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("equipped_type")] + private JsonTest.Equipment EquippedType { + get { + return this.Equipped != null ? this.Equipped.Type : JsonTest.Equipment.NONE; + } + set { + this.Equipped = new JsonTest.EquipmentUnion(); + this.Equipped.Type = value; + } + } + [System.Text.Json.Serialization.JsonPropertyName("equipped")] + [System.Text.Json.Serialization.JsonConverter(typeof(JsonTest.EquipmentUnion_JsonConverter))] + public JsonTest.EquipmentUnion Equipped { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("tags")] + public List Tags { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("scores")] + public List Scores { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("color")] + public JsonTest.ColorT Color { get; set; } + + public PlayerT() { + this.Id = 0; + this.Name = null; + this.Level = 1; + this.Health = 100.0f; + this.Position = new JsonTest.Vec2T(); + this.Status = JsonTest.Status.Active; + this.Priorities = 0; + this.Inventory = null; + this.Equipped = null; + this.Tags = null; + this.Scores = null; + this.Color = new JsonTest.ColorT(); + } +} + + +static public class PlayerVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Id*/, 8 /*long*/, 8, false) + && verifier.VerifyString(tablePos, 6 /*Name*/, true) + && verifier.VerifyField(tablePos, 8 /*Level*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 10 /*Health*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 12 /*Position*/, 8 /*JsonTest.Vec2*/, 4, false) + && verifier.VerifyField(tablePos, 14 /*Status*/, 1 /*JsonTest.Status*/, 1, false) + && verifier.VerifyField(tablePos, 16 /*Priorities*/, 1 /*JsonTest.Priority*/, 1, false) + && verifier.VerifyVectorOfTables(tablePos, 18 /*Inventory*/, JsonTest.ItemVerify.Verify, false) + && verifier.VerifyField(tablePos, 20 /*EquippedType*/, 1 /*JsonTest.Equipment*/, 1, false) + && verifier.VerifyUnion(tablePos, 20, 22 /*Equipped*/, JsonTest.EquipmentVerify.Verify, false) + && verifier.VerifyVectorOfStrings(tablePos, 24 /*Tags*/, false) + && verifier.VerifyVectorOfData(tablePos, 26 /*Scores*/, 4 /*int*/, false) + && verifier.VerifyField(tablePos, 28 /*Color*/, 4 /*JsonTest.Color*/, 1, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Priority.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Priority.cs new file mode 100644 index 00000000000..dcd2502fd42 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Priority.cs @@ -0,0 +1,19 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +[System.FlagsAttribute] +public enum Priority : byte +{ + Low = 1, + Medium = 2, + High = 4, + Critical = 8, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Armor.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Armor.cs new file mode 100644 index 00000000000..bd5efe7d723 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Armor.cs @@ -0,0 +1,66 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Armor : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Armor GetRootAsArmor(ByteSpanBuffer _bb) { return GetRootAsArmor(_bb, new Armor()); } + public static Armor GetRootAsArmor(ByteSpanBuffer _bb, Armor obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Armor __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public int Defense { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateArmor(ref FlatSpanBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + int defense = 0) { + builder.StartTable(2); + Armor.AddDefense(ref builder, defense); + Armor.AddName(ref builder, nameOffset); + return Armor.EndArmor(ref builder); + } + + public static void StartArmor(ref FlatSpanBufferBuilder builder) { builder.StartTable(2); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddDefense(ref FlatSpanBufferBuilder builder, int defense) { builder.Add(1, defense, 0); } + public static Offset EndArmor(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public ArmorT UnPack() { + var _o = new ArmorT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ArmorT _o) { + _o.Name = this.Name; + _o.Defense = this.Defense; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, ArmorT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateArmor( + ref builder, + _name, + _o.Defense); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Color.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Color.cs new file mode 100644 index 00000000000..386e11eb1a5 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Color.cs @@ -0,0 +1,59 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Color : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Color __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public byte R { get { return __p.bb.Get(__p.bb_pos + 0); } } + public byte G { get { return __p.bb.Get(__p.bb_pos + 1); } } + public byte B { get { return __p.bb.Get(__p.bb_pos + 2); } } + public byte A { get { return __p.bb.Get(__p.bb_pos + 3); } } + + public static Offset CreateColor(ref FlatSpanBufferBuilder builder, byte R, byte G, byte B, byte A) { + builder.Prep(1, 4); + builder.Put(A); + builder.Put(B); + builder.Put(G); + builder.Put(R); + return new Offset(builder.Offset); + } + public ColorT UnPack() { + var _o = new ColorT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ColorT _o) { + _o.R = this.R; + _o.G = this.G; + _o.B = this.B; + _o.A = this.A; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, ColorT _o) { + if (_o == null) return default(Offset); + return CreateColor( + ref builder, + _o.R, + _o.G, + _o.B, + _o.A); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/GameState.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/GameState.cs new file mode 100644 index 00000000000..5d045eb7649 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/GameState.cs @@ -0,0 +1,113 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct GameState : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static GameState GetRootAsGameState(ByteSpanBuffer _bb) { return GetRootAsGameState(_bb, new GameState()); } + public static GameState GetRootAsGameState(ByteSpanBuffer _bb, GameState obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool GameStateBufferHasIdentifier(ByteSpanBuffer _bb) { return TableSpan.__has_identifier(_bb, "JSON"); } + public static bool VerifyGameState(ByteSpanBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("JSON", false, JsonTest.GameStateVerify.Verify); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public GameState __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public string Version { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetVersionBytes() { return __p.__vector_as_span(4); } + public RefStructNullable> Players { get { int o = __p.__offset(6); return o != 0 ? new RefStructNullable>(new TableVectorSpan(__p, o, 4)) : default; } } + public bool TryGetPlayersByKey(string key, out JsonTest.StackBuffer.Player value) { int o = __p.__offset(6); if (o != 0) { return JsonTest.StackBuffer.Player.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public long ActivePlayerId { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public long Timestamp { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + + public static Offset CreateGameState(ref FlatSpanBufferBuilder builder, + StringOffset versionOffset = default(StringOffset), + VectorOffset playersOffset = default(VectorOffset), + long active_player_id = 0, + long timestamp = 0) { + builder.StartTable(4); + GameState.AddTimestamp(ref builder, timestamp); + GameState.AddActivePlayerId(ref builder, active_player_id); + GameState.AddPlayers(ref builder, playersOffset); + GameState.AddVersion(ref builder, versionOffset); + return GameState.EndGameState(ref builder); + } + + public static void StartGameState(ref FlatSpanBufferBuilder builder) { builder.StartTable(4); } + public static void AddVersion(ref FlatSpanBufferBuilder builder, StringOffset versionOffset) { builder.AddOffset(0, versionOffset, 0); } + public static void AddPlayers(ref FlatSpanBufferBuilder builder, VectorOffset playersOffset) { builder.AddOffset(1, playersOffset, 0); } + public static VectorOffset CreatePlayersVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreatePlayersVector(ref FlatSpanBufferBuilder builder, scoped Span> data) { return CreatePlayersVectorBlock(ref builder, data); } + public static void StartPlayersVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddActivePlayerId(ref FlatSpanBufferBuilder builder, long activePlayerId) { builder.Add(2, activePlayerId, 0); } + public static void AddTimestamp(ref FlatSpanBufferBuilder builder, long timestamp) { builder.Add(3, timestamp, 0); } + public static Offset EndGameState(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishGameStateBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "JSON"); } + public static void FinishSizePrefixedGameStateBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "JSON"); } + public GameStateT UnPack() { + var _o = new GameStateT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(GameStateT _o) { + _o.Version = this.Version; + var _players_vec = this.Players; + var _players_len = _players_vec.HasValue ? _players_vec.Value.Length : 0; + if (_o.Players == null) { + _o.Players = new List(_players_len); + } + ObjectApiUtil.ResizeList(_o.Players, _players_len); + if (_players_vec.HasValue) { + var _players_value = _players_vec.Value; + for (var _j = 0; _j < _players_len; ++_j) { + var _src = _players_value[_j]; + if (_o.Players[_j] == null) { _o.Players[_j] = new PlayerT(); } + _src.UnPackTo(_o.Players[_j]); + } + } + _o.ActivePlayerId = this.ActivePlayerId; + _o.Timestamp = this.Timestamp; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, GameStateT _o) { + if (_o == null) return default(Offset); + var _version = _o.Version == null ? default(StringOffset) : builder.CreateString(_o.Version); + var _players = default(VectorOffset); + if (_o.Players != null) { + var _players_len = _o.Players.Count; + Offset[] _players_arr = null; + try { + Span> __players = _players_len <= 64 + ? stackalloc Offset[_players_len] + : (_players_arr = ArrayPool>.Shared.Rent(_players_len)).AsSpan(0, _players_len); + for (var _j = 0; _j < _players_len; ++_j) { __players[_j] = JsonTest.StackBuffer.Player.Pack(ref builder, _o.Players[_j]); } + _players = CreatePlayersVector(ref builder, __players); + } finally { + if (_players_arr != null) { ArrayPool>.Shared.Return(_players_arr); } + } + } + return CreateGameState( + ref builder, + _version, + _players, + _o.ActivePlayerId, + _o.Timestamp); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Item.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Item.cs new file mode 100644 index 00000000000..bb661f75f4e --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Item.cs @@ -0,0 +1,82 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Item : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Item GetRootAsItem(ByteSpanBuffer _bb) { return GetRootAsItem(_bb, new Item()); } + public static Item GetRootAsItem(ByteSpanBuffer _bb, Item obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Item __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(6); } + public float Value { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)0.0f; } } + + public static Offset CreateItem(ref FlatSpanBufferBuilder builder, + int id = 0, + StringOffset nameOffset = default(StringOffset), + float value = 0.0f) { + builder.StartTable(3); + Item.AddValue(ref builder, value); + Item.AddName(ref builder, nameOffset); + Item.AddId(ref builder, id); + return Item.EndItem(ref builder); + } + + public static void StartItem(ref FlatSpanBufferBuilder builder) { builder.StartTable(3); } + public static void AddId(ref FlatSpanBufferBuilder builder, int id) { builder.Add(0, id, 0); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset, 0); } + public static void AddValue(ref FlatSpanBufferBuilder builder, float value) { builder.Add(2, value, 0.0f); } + public static Offset EndItem(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfItem(ref FlatSpanBufferBuilder builder, scoped Span> offsets) { + var comparer = new SortedVectorUtils.ScalarOffsetComparer(builder.DataBuffer, 4); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, int key, ByteSpanBuffer bb, out Item value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 4, 0, out value); + } + public ItemT UnPack() { + var _o = new ItemT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ItemT _o) { + _o.Id = this.Id; + _o.Name = this.Name; + _o.Value = this.Value; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, ItemT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateItem( + ref builder, + _o.Id, + _name, + _o.Value); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Player.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Player.cs new file mode 100644 index 00000000000..ab952c4666c --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Player.cs @@ -0,0 +1,230 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Player : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Player GetRootAsPlayer(ByteSpanBuffer _bb) { return GetRootAsPlayer(_bb, new Player()); } + public static Player GetRootAsPlayer(ByteSpanBuffer _bb, Player obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Player __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public long Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(6); } + public int Level { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)1; } } + public float Health { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)100.0f; } } + public RefStructNullable Position { get { int o = __p.__offset(12); return o != 0 ? new RefStructNullable((new JsonTest.StackBuffer.Vec2()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + public JsonTest.Status Status { get { int o = __p.__offset(14); return o != 0 ? (JsonTest.Status)__p.bb.Get(o + __p.bb_pos) : JsonTest.Status.Active; } } + public JsonTest.Priority Priorities { get { int o = __p.__offset(16); return o != 0 ? (JsonTest.Priority)__p.bb.Get(o + __p.bb_pos) : 0; } } + public RefStructNullable> Inventory { get { int o = __p.__offset(18); return o != 0 ? new RefStructNullable>(new TableVectorSpan(__p, o, 4)) : default; } } + public bool TryGetInventoryByKey(int key, out JsonTest.StackBuffer.Item value) { int o = __p.__offset(18); if (o != 0) { return JsonTest.StackBuffer.Item.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public JsonTest.Equipment EquippedType { get { int o = __p.__offset(20); return o != 0 ? (JsonTest.Equipment)__p.bb.Get(o + __p.bb_pos) : JsonTest.Equipment.NONE; } } + public RefStructNullable Equipped() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(22); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public JsonTest.StackBuffer.Weapon EquippedAsWeapon() { return Equipped().Value; } + public JsonTest.StackBuffer.Armor EquippedAsArmor() { return Equipped().Value; } + public RefStructNullable Tags { get { int o = __p.__offset(24); return o != 0 ? new RefStructNullable(new StringVectorSpan(__p, o)) : default; } } + public RefStructNullable> Scores { get { int o = __p.__offset(26); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(26)) : default; } } + public RefStructNullable Color { get { int o = __p.__offset(28); return o != 0 ? new RefStructNullable((new JsonTest.StackBuffer.Color()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + + public static void StartPlayer(ref FlatSpanBufferBuilder builder) { builder.StartTable(13); } + public static void AddId(ref FlatSpanBufferBuilder builder, long id) { builder.Add(0, id, 0); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset, 0); } + public static void AddLevel(ref FlatSpanBufferBuilder builder, int level) { builder.Add(2, level, 1); } + public static void AddHealth(ref FlatSpanBufferBuilder builder, float health) { builder.Add(3, health, 100.0f); } + public static void AddPosition(ref FlatSpanBufferBuilder builder, Offset positionOffset) { builder.AddStruct(4, positionOffset, 0); } + public static void AddStatus(ref FlatSpanBufferBuilder builder, JsonTest.Status status) { builder.Add(5, (sbyte)status, 1); } + public static void AddPriorities(ref FlatSpanBufferBuilder builder, JsonTest.Priority priorities) { builder.Add(6, (byte)priorities, 0); } + public static void AddInventory(ref FlatSpanBufferBuilder builder, VectorOffset inventoryOffset) { builder.AddOffset(7, inventoryOffset, 0); } + public static VectorOffset CreateInventoryVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateInventoryVector(ref FlatSpanBufferBuilder builder, scoped Span> data) { return CreateInventoryVectorBlock(ref builder, data); } + public static void StartInventoryVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddEquippedType(ref FlatSpanBufferBuilder builder, JsonTest.Equipment equippedType) { builder.Add(8, (byte)equippedType, 0); } + public static void AddEquipped(ref FlatSpanBufferBuilder builder, int equippedOffset) { builder.AddOffset(9, equippedOffset, 0); } + public static void AddTags(ref FlatSpanBufferBuilder builder, VectorOffset tagsOffset) { builder.AddOffset(10, tagsOffset, 0); } + public static VectorOffset CreateTagsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTagsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateTagsVectorBlock(ref builder, data); } + public static void StartTagsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddScores(ref FlatSpanBufferBuilder builder, VectorOffset scoresOffset) { builder.AddOffset(11, scoresOffset, 0); } + public static VectorOffset CreateScoresVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateScoresVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateScoresVectorBlock(ref builder, data); } + public static void StartScoresVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddColor(ref FlatSpanBufferBuilder builder, Offset colorOffset) { builder.AddStruct(12, colorOffset, 0); } + public static Offset EndPlayer(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 6); // name + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfPlayer(ref FlatSpanBufferBuilder builder, scoped Span> offsets) { + var comparer = new SortedVectorUtils.VectorOffsetComparer(builder.DataBuffer, 6); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, string key, ByteSpanBuffer bb, out Player value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 6, out value); + } + public PlayerT UnPack() { + var _o = new PlayerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(PlayerT _o) { + _o.Id = this.Id; + _o.Name = this.Name; + _o.Level = this.Level; + _o.Health = this.Health; + if (this.Position.HasValue) { + if (_o.Position == null) _o.Position = new JsonTest.Vec2T(); + this.Position.Value.UnPackTo(_o.Position); + } else { + _o.Position = null; + } + _o.Status = this.Status; + _o.Priorities = this.Priorities; + var _inventory_vec = this.Inventory; + var _inventory_len = _inventory_vec.HasValue ? _inventory_vec.Value.Length : 0; + if (_o.Inventory == null) { + _o.Inventory = new List(_inventory_len); + } + ObjectApiUtil.ResizeList(_o.Inventory, _inventory_len); + if (_inventory_vec.HasValue) { + var _inventory_value = _inventory_vec.Value; + for (var _j = 0; _j < _inventory_len; ++_j) { + var _src = _inventory_value[_j]; + if (_o.Inventory[_j] == null) { _o.Inventory[_j] = new ItemT(); } + _src.UnPackTo(_o.Inventory[_j]); + } + } + if (_o.Equipped == null) { + _o.Equipped = new JsonTest.EquipmentUnion(); + } + var _EquippedOldType = _o.Equipped.Type; + _o.Equipped.Type = this.EquippedType; + switch (this.EquippedType) { + default: + _o.Equipped.Value = null; + break; + case JsonTest.Equipment.Weapon: + if (this.Equipped().HasValue) { + if (_EquippedOldType == JsonTest.Equipment.Weapon) { + this.Equipped().Value.UnPackTo((JsonTest.WeaponT)_o.Equipped.Value); + } else { + _o.Equipped.Value = this.Equipped().Value.UnPack(); + } + } else { + _o.Equipped.Value = null; + } + break; + case JsonTest.Equipment.Armor: + if (this.Equipped().HasValue) { + if (_EquippedOldType == JsonTest.Equipment.Armor) { + this.Equipped().Value.UnPackTo((JsonTest.ArmorT)_o.Equipped.Value); + } else { + _o.Equipped.Value = this.Equipped().Value.UnPack(); + } + } else { + _o.Equipped.Value = null; + } + break; + } + var _tags_vec = this.Tags; + var _tags_len = _tags_vec.HasValue ? _tags_vec.Value.Length : 0; + if (_o.Tags == null) { + _o.Tags = new List(_tags_len); + } else { + _o.Tags.Clear(); + if (_o.Tags.Capacity < _tags_len) { + _o.Tags.Capacity = _tags_len; + } + } + if (_tags_vec.HasValue) { + var _tags_value = _tags_vec.Value; + for (var _j = 0; _j < _tags_len; ++_j) { _o.Tags.Add(_tags_value[_j]); } + } + var _scores_vec = this.Scores; + var _scores_len = _scores_vec.HasValue ? _scores_vec.Value.Length : 0; + if (_o.Scores == null) { + _o.Scores = new List(_scores_len); + } + ObjectApiUtil.ResizeList(_o.Scores, _scores_len); + if (_scores_vec.HasValue) { _scores_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Scores)); } + if (this.Color.HasValue) { + if (_o.Color == null) _o.Color = new JsonTest.ColorT(); + this.Color.Value.UnPackTo(_o.Color); + } else { + _o.Color = null; + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, PlayerT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + var _inventory = default(VectorOffset); + if (_o.Inventory != null) { + var _inventory_len = _o.Inventory.Count; + Offset[] _inventory_arr = null; + try { + Span> __inventory = _inventory_len <= 64 + ? stackalloc Offset[_inventory_len] + : (_inventory_arr = ArrayPool>.Shared.Rent(_inventory_len)).AsSpan(0, _inventory_len); + for (var _j = 0; _j < _inventory_len; ++_j) { __inventory[_j] = JsonTest.StackBuffer.Item.Pack(ref builder, _o.Inventory[_j]); } + _inventory = CreateInventoryVector(ref builder, __inventory); + } finally { + if (_inventory_arr != null) { ArrayPool>.Shared.Return(_inventory_arr); } + } + } + var _equipped_type = _o.Equipped == null ? JsonTest.Equipment.NONE : _o.Equipped.Type; + var _equipped = _o.Equipped == null ? 0 : JsonTest.EquipmentUnion.Pack(ref builder, _o.Equipped); + var _tags = default(VectorOffset); + if (_o.Tags != null) { + var _tags_len = _o.Tags.Count; + StringOffset[] _tags_arr = null; + try { + Span __tags = _tags_len <= 64 + ? stackalloc StringOffset[_tags_len] + : (_tags_arr = ArrayPool.Shared.Rent(_tags_len)).AsSpan(0, _tags_len); + for (var _j = 0; _j < _tags_len; ++_j) { __tags[_j] = builder.CreateString(_o.Tags[_j]); } + _tags = CreateTagsVector(ref builder, __tags); + } finally { + if (_tags_arr != null) { ArrayPool.Shared.Return(_tags_arr); } + } + } + var _scores = default(VectorOffset); + if (_o.Scores != null) { + _scores = CreateScoresVector(ref builder, CollectionsMarshal.AsSpan(_o.Scores)); + } + StartPlayer(ref builder); + AddId(ref builder, _o.Id); + AddName(ref builder, _name); + AddLevel(ref builder, _o.Level); + AddHealth(ref builder, _o.Health); + AddPosition(ref builder, JsonTest.StackBuffer.Vec2.Pack(ref builder, _o.Position)); + AddStatus(ref builder, _o.Status); + AddPriorities(ref builder, _o.Priorities); + AddInventory(ref builder, _inventory); + AddEquippedType(ref builder, _equipped_type); + AddEquipped(ref builder, _equipped); + AddTags(ref builder, _tags); + AddScores(ref builder, _scores); + AddColor(ref builder, JsonTest.StackBuffer.Color.Pack(ref builder, _o.Color)); + return EndPlayer(ref builder); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Vec2.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Vec2.cs new file mode 100644 index 00000000000..715788dd18f --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Vec2.cs @@ -0,0 +1,51 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Vec2 : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Vec2 __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public float X { get { return __p.bb.Get(__p.bb_pos + 0); } } + public float Y { get { return __p.bb.Get(__p.bb_pos + 4); } } + + public static Offset CreateVec2(ref FlatSpanBufferBuilder builder, float X, float Y) { + builder.Prep(4, 8); + builder.Put(Y); + builder.Put(X); + return new Offset(builder.Offset); + } + public Vec2T UnPack() { + var _o = new Vec2T(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(Vec2T _o) { + _o.X = this.X; + _o.Y = this.Y; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, Vec2T _o) { + if (_o == null) return default(Offset); + return CreateVec2( + ref builder, + _o.X, + _o.Y); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Weapon.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Weapon.cs new file mode 100644 index 00000000000..2898a573a5d --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/StackBuffer/Weapon.cs @@ -0,0 +1,66 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Weapon : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Weapon GetRootAsWeapon(ByteSpanBuffer _bb) { return GetRootAsWeapon(_bb, new Weapon()); } + public static Weapon GetRootAsWeapon(ByteSpanBuffer _bb, Weapon obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Weapon __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public int Damage { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateWeapon(ref FlatSpanBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + int damage = 0) { + builder.StartTable(2); + Weapon.AddDamage(ref builder, damage); + Weapon.AddName(ref builder, nameOffset); + return Weapon.EndWeapon(ref builder); + } + + public static void StartWeapon(ref FlatSpanBufferBuilder builder) { builder.StartTable(2); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddDamage(ref FlatSpanBufferBuilder builder, int damage) { builder.Add(1, damage, 0); } + public static Offset EndWeapon(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public WeaponT UnPack() { + var _o = new WeaponT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(WeaponT _o) { + _o.Name = this.Name; + _o.Damage = this.Damage; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, WeaponT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateWeapon( + ref builder, + _name, + _o.Damage); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Status.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Status.cs new file mode 100644 index 00000000000..0c752af9872 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Status.cs @@ -0,0 +1,18 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +public enum Status : sbyte +{ + Unknown = 0, + Active = 1, + Inactive = 2, + Suspended = 3, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Vec2.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Vec2.cs new file mode 100644 index 00000000000..44fdc5c9a45 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Vec2.cs @@ -0,0 +1,64 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Vec2 : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Vec2 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public float X { get { return __p.bb.Get(__p.bb_pos + 0); } } + public float Y { get { return __p.bb.Get(__p.bb_pos + 4); } } + + public static Offset CreateVec2(FlatBufferBuilder builder, float X, float Y) { + builder.Prep(4, 8); + builder.Put(Y); + builder.Put(X); + return new Offset(builder.Offset); + } + public Vec2T UnPack() { + var _o = new Vec2T(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(Vec2T _o) { + _o.X = this.X; + _o.Y = this.Y; + } + public static Offset Pack(FlatBufferBuilder builder, Vec2T _o) { + if (_o == null) return default(Offset); + return CreateVec2( + builder, + _o.X, + _o.Y); + } +} + +public class Vec2T +{ + [System.Text.Json.Serialization.JsonPropertyName("x")] + public float X { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("y")] + public float Y { get; set; } + + public Vec2T() { + this.X = 0.0f; + this.Y = 0.0f; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Weapon.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Weapon.cs new file mode 100644 index 00000000000..adeee35fe1e --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/json_test/JsonTest/Weapon.cs @@ -0,0 +1,90 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace JsonTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Weapon : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Weapon GetRootAsWeapon(ByteBuffer _bb) { return GetRootAsWeapon(_bb, new Weapon()); } + public static Weapon GetRootAsWeapon(ByteBuffer _bb, Weapon obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Weapon __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public int Damage { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateWeapon(FlatBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + int damage = 0) { + builder.StartTable(2); + Weapon.AddDamage(builder, damage); + Weapon.AddName(builder, nameOffset); + return Weapon.EndWeapon(builder); + } + + public static void StartWeapon(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddDamage(FlatBufferBuilder builder, int damage) { builder.Add(1, damage, 0); } + public static Offset EndWeapon(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public WeaponT UnPack() { + var _o = new WeaponT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(WeaponT _o) { + _o.Name = this.Name; + _o.Damage = this.Damage; + } + public static Offset Pack(FlatBufferBuilder builder, WeaponT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateWeapon( + builder, + _name, + _o.Damage); + } +} + +public class WeaponT +{ + [System.Text.Json.Serialization.JsonPropertyName("name")] + public string Name { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("damage")] + public int Damage { get; set; } + + public WeaponT() { + this.Name = null; + this.Damage = 0; + } +} + + +static public class WeaponVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*Name*/, false) + && verifier.VerifyField(tablePos, 6 /*Damage*/, 4 /*int*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/KeyTestMonster.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/KeyTestMonster.cs new file mode 100644 index 00000000000..7a6095cc002 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/KeyTestMonster.cs @@ -0,0 +1,110 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeyTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct KeyTestMonster : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static KeyTestMonster GetRootAsKeyTestMonster(ByteBuffer _bb) { return GetRootAsKeyTestMonster(_bb, new KeyTestMonster()); } + public static KeyTestMonster GetRootAsKeyTestMonster(ByteBuffer _bb, KeyTestMonster obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool VerifyKeyTestMonster(ByteBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, KeyTest.KeyTestMonsterVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public KeyTestMonster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public int Hp { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateKeyTestMonster(FlatBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + int hp = 0) { + builder.StartTable(2); + KeyTestMonster.AddHp(builder, hp); + KeyTestMonster.AddName(builder, nameOffset); + return KeyTestMonster.EndKeyTestMonster(builder); + } + + public static void StartKeyTestMonster(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddHp(FlatBufferBuilder builder, int hp) { builder.Add(1, hp, 0); } + public static Offset EndKeyTestMonster(FlatBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 4); // name + return new Offset(o); + } + public static void FinishKeyTestMonsterBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedKeyTestMonsterBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + + public static VectorOffset CreateSortedVectorOfKeyTestMonster(FlatBufferBuilder builder, Span> offsets) { + var comparer = new SortedVectorUtils.VectorOffsetComparer(builder.DataBuffer, 4); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, string key, ByteBuffer bb, out KeyTestMonster value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 4, out value); + } + public KeyTestMonsterT UnPack() { + var _o = new KeyTestMonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(KeyTestMonsterT _o) { + _o.Name = this.Name; + _o.Hp = this.Hp; + } + public static Offset Pack(FlatBufferBuilder builder, KeyTestMonsterT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateKeyTestMonster( + builder, + _name, + _o.Hp); + } +} + +public class KeyTestMonsterT +{ + public string Name { get; set; } + public int Hp { get; set; } + + public KeyTestMonsterT() { + this.Name = null; + this.Hp = 0; + } + public static KeyTestMonsterT DeserializeFromBinary(byte[] fbBuffer) { + return KeyTestMonster.GetRootAsKeyTestMonster(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + KeyTestMonster.FinishKeyTestMonsterBuffer(fbb, KeyTestMonster.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedSpan().ToArray(); + } +} + + +static public class KeyTestMonsterVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*Name*/, true) + && verifier.VerifyField(tablePos, 6 /*Hp*/, 4 /*int*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/KeyTestWeapon.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/KeyTestWeapon.cs new file mode 100644 index 00000000000..60f5505ce00 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/KeyTestWeapon.cs @@ -0,0 +1,107 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeyTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct KeyTestWeapon : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static KeyTestWeapon GetRootAsKeyTestWeapon(ByteBuffer _bb) { return GetRootAsKeyTestWeapon(_bb, new KeyTestWeapon()); } + public static KeyTestWeapon GetRootAsKeyTestWeapon(ByteBuffer _bb, KeyTestWeapon obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public KeyTestWeapon __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(6); } + public int Damage { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateKeyTestWeapon(FlatBufferBuilder builder, + int id = 0, + StringOffset nameOffset = default(StringOffset), + int damage = 0) { + builder.StartTable(3); + KeyTestWeapon.AddDamage(builder, damage); + KeyTestWeapon.AddName(builder, nameOffset); + KeyTestWeapon.AddId(builder, id); + return KeyTestWeapon.EndKeyTestWeapon(builder); + } + + public static void StartKeyTestWeapon(FlatBufferBuilder builder) { builder.StartTable(3); } + public static void AddId(FlatBufferBuilder builder, int id) { builder.Add(0, id, 0); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset, 0); } + public static void AddDamage(FlatBufferBuilder builder, int damage) { builder.Add(2, damage, 0); } + public static Offset EndKeyTestWeapon(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfKeyTestWeapon(FlatBufferBuilder builder, Span> offsets) { + var comparer = new SortedVectorUtils.ScalarOffsetComparer(builder.DataBuffer, 4); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, int key, ByteBuffer bb, out KeyTestWeapon value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 4, 0, out value); + } + public KeyTestWeaponT UnPack() { + var _o = new KeyTestWeaponT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(KeyTestWeaponT _o) { + _o.Id = this.Id; + _o.Name = this.Name; + _o.Damage = this.Damage; + } + public static Offset Pack(FlatBufferBuilder builder, KeyTestWeaponT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateKeyTestWeapon( + builder, + _o.Id, + _name, + _o.Damage); + } +} + +public class KeyTestWeaponT +{ + public int Id { get; set; } + public string Name { get; set; } + public int Damage { get; set; } + + public KeyTestWeaponT() { + this.Id = 0; + this.Name = null; + this.Damage = 0; + } +} + + +static public class KeyTestWeaponVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Id*/, 4 /*int*/, 4, false) + && verifier.VerifyString(tablePos, 6 /*Name*/, false) + && verifier.VerifyField(tablePos, 8 /*Damage*/, 4 /*int*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/StackBuffer/KeyTestMonster.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/StackBuffer/KeyTestMonster.cs new file mode 100644 index 00000000000..4a5f12afc3b --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/StackBuffer/KeyTestMonster.cs @@ -0,0 +1,80 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeyTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct KeyTestMonster : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static KeyTestMonster GetRootAsKeyTestMonster(ByteSpanBuffer _bb) { return GetRootAsKeyTestMonster(_bb, new KeyTestMonster()); } + public static KeyTestMonster GetRootAsKeyTestMonster(ByteSpanBuffer _bb, KeyTestMonster obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool VerifyKeyTestMonster(ByteSpanBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, KeyTest.KeyTestMonsterVerify.Verify); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public KeyTestMonster __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public int Hp { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateKeyTestMonster(ref FlatSpanBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + int hp = 0) { + builder.StartTable(2); + KeyTestMonster.AddHp(ref builder, hp); + KeyTestMonster.AddName(ref builder, nameOffset); + return KeyTestMonster.EndKeyTestMonster(ref builder); + } + + public static void StartKeyTestMonster(ref FlatSpanBufferBuilder builder) { builder.StartTable(2); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddHp(ref FlatSpanBufferBuilder builder, int hp) { builder.Add(1, hp, 0); } + public static Offset EndKeyTestMonster(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 4); // name + return new Offset(o); + } + public static void FinishKeyTestMonsterBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedKeyTestMonsterBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + + public static VectorOffset CreateSortedVectorOfKeyTestMonster(ref FlatSpanBufferBuilder builder, scoped Span> offsets) { + var comparer = new SortedVectorUtils.VectorOffsetComparer(builder.DataBuffer, 4); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, string key, ByteSpanBuffer bb, out KeyTestMonster value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 4, out value); + } + public KeyTestMonsterT UnPack() { + var _o = new KeyTestMonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(KeyTestMonsterT _o) { + _o.Name = this.Name; + _o.Hp = this.Hp; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, KeyTestMonsterT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateKeyTestMonster( + ref builder, + _name, + _o.Hp); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/StackBuffer/KeyTestWeapon.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/StackBuffer/KeyTestWeapon.cs new file mode 100644 index 00000000000..a1837105c36 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/key_test/KeyTest/StackBuffer/KeyTestWeapon.cs @@ -0,0 +1,82 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeyTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct KeyTestWeapon : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static KeyTestWeapon GetRootAsKeyTestWeapon(ByteSpanBuffer _bb) { return GetRootAsKeyTestWeapon(_bb, new KeyTestWeapon()); } + public static KeyTestWeapon GetRootAsKeyTestWeapon(ByteSpanBuffer _bb, KeyTestWeapon obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public KeyTestWeapon __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(6); } + public int Damage { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateKeyTestWeapon(ref FlatSpanBufferBuilder builder, + int id = 0, + StringOffset nameOffset = default(StringOffset), + int damage = 0) { + builder.StartTable(3); + KeyTestWeapon.AddDamage(ref builder, damage); + KeyTestWeapon.AddName(ref builder, nameOffset); + KeyTestWeapon.AddId(ref builder, id); + return KeyTestWeapon.EndKeyTestWeapon(ref builder); + } + + public static void StartKeyTestWeapon(ref FlatSpanBufferBuilder builder) { builder.StartTable(3); } + public static void AddId(ref FlatSpanBufferBuilder builder, int id) { builder.Add(0, id, 0); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset, 0); } + public static void AddDamage(ref FlatSpanBufferBuilder builder, int damage) { builder.Add(2, damage, 0); } + public static Offset EndKeyTestWeapon(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfKeyTestWeapon(ref FlatSpanBufferBuilder builder, scoped Span> offsets) { + var comparer = new SortedVectorUtils.ScalarOffsetComparer(builder.DataBuffer, 4); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, int key, ByteSpanBuffer bb, out KeyTestWeapon value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 4, 0, out value); + } + public KeyTestWeaponT UnPack() { + var _o = new KeyTestWeaponT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(KeyTestWeaponT _o) { + _o.Id = this.Id; + _o.Name = this.Name; + _o.Damage = this.Damage; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, KeyTestWeaponT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateKeyTestWeapon( + ref builder, + _o.Id, + _name, + _o.Damage); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/ABC.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/ABC.cs new file mode 100644 index 00000000000..1302b5e1be2 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/ABC.cs @@ -0,0 +1,16 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeywordTest +{ + +public enum ABC : int +{ + @void = 0, + where = 1, + @stackalloc = 2, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/KeywordsInTable.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/KeywordsInTable.cs new file mode 100644 index 00000000000..2ab79dad52d --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/KeywordsInTable.cs @@ -0,0 +1,104 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeywordTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct KeywordsInTable : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb) { return GetRootAsKeywordsInTable(_bb, new KeywordsInTable()); } + public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb, KeywordsInTable obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public KeywordsInTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public KeywordTest.ABC Is { get { int o = __p.__offset(4); return o != 0 ? (KeywordTest.ABC)__p.bb.Get(o + __p.bb_pos) : KeywordTest.ABC.@void; } } + public KeywordTest.@public Private { get { int o = __p.__offset(6); return o != 0 ? (KeywordTest.@public)__p.bb.Get(o + __p.bb_pos) : KeywordTest.@public.NONE; } } + public int Type { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public bool Default { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + + public static Offset CreateKeywordsInTable(FlatBufferBuilder builder, + KeywordTest.ABC @is = KeywordTest.ABC.@void, + KeywordTest.@public @private = KeywordTest.@public.NONE, + int type = 0, + bool @default = false) { + builder.StartTable(4); + KeywordsInTable.AddType(builder, type); + KeywordsInTable.AddPrivate(builder, @private); + KeywordsInTable.AddIs(builder, @is); + KeywordsInTable.AddDefault(builder, @default); + return KeywordsInTable.EndKeywordsInTable(builder); + } + + public static void StartKeywordsInTable(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddIs(FlatBufferBuilder builder, KeywordTest.ABC @is) { builder.Add(0, (int)@is, 0); } + public static void AddPrivate(FlatBufferBuilder builder, KeywordTest.@public @private) { builder.Add(1, (int)@private, 0); } + public static void AddType(FlatBufferBuilder builder, int type) { builder.Add(2, type, 0); } + public static void AddDefault(FlatBufferBuilder builder, bool @default) { builder.Add(3, @default, false); } + public static Offset EndKeywordsInTable(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public KeywordsInTableT UnPack() { + var _o = new KeywordsInTableT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(KeywordsInTableT _o) { + _o.Is = this.Is; + _o.Private = this.Private; + _o.Type = this.Type; + _o.Default = this.Default; + } + public static Offset Pack(FlatBufferBuilder builder, KeywordsInTableT _o) { + if (_o == null) return default(Offset); + return CreateKeywordsInTable( + builder, + _o.Is, + _o.Private, + _o.Type, + _o.Default); + } +} + +public class KeywordsInTableT +{ + public KeywordTest.ABC Is { get; set; } + public KeywordTest.@public Private { get; set; } + public int Type { get; set; } + public bool Default { get; set; } + + public KeywordsInTableT() { + this.Is = KeywordTest.ABC.@void; + this.Private = KeywordTest.@public.NONE; + this.Type = 0; + this.Default = false; + } +} + + +static public class KeywordsInTableVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Is*/, 4 /*KeywordTest.ABC*/, 4, false) + && verifier.VerifyField(tablePos, 6 /*Private*/, 4 /*KeywordTest.@public*/, 4, false) + && verifier.VerifyField(tablePos, 8 /*Type*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 10 /*Default*/, 1 /*bool*/, 1, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/KeywordsInUnion.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/KeywordsInUnion.cs new file mode 100644 index 00000000000..1c869d5064f --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/KeywordsInUnion.cs @@ -0,0 +1,69 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeywordTest +{ + +public enum KeywordsInUnion : byte +{ + NONE = 0, + @static = 1, + @internal = 2, +}; + +public class KeywordsInUnionUnion { + public KeywordsInUnion Type { get; set; } + public object Value { get; set; } + + public KeywordsInUnionUnion() { + this.Type = KeywordsInUnion.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public KeywordTest.KeywordsInTableT Asstatic() { return this.As(); } + public static KeywordsInUnionUnion Fromstatic(KeywordTest.KeywordsInTableT _static) { return new KeywordsInUnionUnion{ Type = KeywordsInUnion.@static, Value = _static }; } + public KeywordTest.KeywordsInTableT Asinternal() { return this.As(); } + public static KeywordsInUnionUnion Frominternal(KeywordTest.KeywordsInTableT _internal) { return new KeywordsInUnionUnion{ Type = KeywordsInUnion.@internal, Value = _internal }; } + + public static int Pack(Google.FlatSpanBuffers.FlatBufferBuilder builder, KeywordsInUnionUnion _o) { + switch (_o.Type) { + default: return 0; + case KeywordsInUnion.@static: return KeywordTest.KeywordsInTable.Pack(builder, _o.Asstatic()).Value; + case KeywordsInUnion.@internal: return KeywordTest.KeywordsInTable.Pack(builder, _o.Asinternal()).Value; + } + } + public static int Pack(ref Google.FlatSpanBuffers.FlatSpanBufferBuilder builder, KeywordsInUnionUnion _o) { + switch (_o.Type) { + default: return 0; + case KeywordsInUnion.@static: return KeywordTest.StackBuffer.KeywordsInTable.Pack(ref builder, _o.Asstatic()).Value; + case KeywordsInUnion.@internal: return KeywordTest.StackBuffer.KeywordsInTable.Pack(ref builder, _o.Asinternal()).Value; + } + } +} + + + +static public class KeywordsInUnionVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, byte typeId, uint tablePos) + { + bool result = true; + switch((KeywordsInUnion)typeId) + { + case KeywordsInUnion.@static: + result = KeywordTest.KeywordsInTableVerify.Verify(ref verifier, tablePos); + break; + case KeywordsInUnion.@internal: + result = KeywordTest.KeywordsInTableVerify.Verify(ref verifier, tablePos); + break; + default: result = true; + break; + } + return result; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/StackBuffer/KeywordsInTable.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/StackBuffer/KeywordsInTable.cs new file mode 100644 index 00000000000..e784b115bee --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/StackBuffer/KeywordsInTable.cs @@ -0,0 +1,76 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeywordTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct KeywordsInTable : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static KeywordsInTable GetRootAsKeywordsInTable(ByteSpanBuffer _bb) { return GetRootAsKeywordsInTable(_bb, new KeywordsInTable()); } + public static KeywordsInTable GetRootAsKeywordsInTable(ByteSpanBuffer _bb, KeywordsInTable obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public KeywordsInTable __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public KeywordTest.ABC Is { get { int o = __p.__offset(4); return o != 0 ? (KeywordTest.ABC)__p.bb.Get(o + __p.bb_pos) : KeywordTest.ABC.@void; } } + public KeywordTest.@public Private { get { int o = __p.__offset(6); return o != 0 ? (KeywordTest.@public)__p.bb.Get(o + __p.bb_pos) : KeywordTest.@public.NONE; } } + public int Type { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public bool Default { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + + public static Offset CreateKeywordsInTable(ref FlatSpanBufferBuilder builder, + KeywordTest.ABC @is = KeywordTest.ABC.@void, + KeywordTest.@public @private = KeywordTest.@public.NONE, + int type = 0, + bool @default = false) { + builder.StartTable(4); + KeywordsInTable.AddType(ref builder, type); + KeywordsInTable.AddPrivate(ref builder, @private); + KeywordsInTable.AddIs(ref builder, @is); + KeywordsInTable.AddDefault(ref builder, @default); + return KeywordsInTable.EndKeywordsInTable(ref builder); + } + + public static void StartKeywordsInTable(ref FlatSpanBufferBuilder builder) { builder.StartTable(4); } + public static void AddIs(ref FlatSpanBufferBuilder builder, KeywordTest.ABC @is) { builder.Add(0, (int)@is, 0); } + public static void AddPrivate(ref FlatSpanBufferBuilder builder, KeywordTest.@public @private) { builder.Add(1, (int)@private, 0); } + public static void AddType(ref FlatSpanBufferBuilder builder, int type) { builder.Add(2, type, 0); } + public static void AddDefault(ref FlatSpanBufferBuilder builder, bool @default) { builder.Add(3, @default, false); } + public static Offset EndKeywordsInTable(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public KeywordsInTableT UnPack() { + var _o = new KeywordsInTableT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(KeywordsInTableT _o) { + _o.Is = this.Is; + _o.Private = this.Private; + _o.Type = this.Type; + _o.Default = this.Default; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, KeywordsInTableT _o) { + if (_o == null) return default(Offset); + return CreateKeywordsInTable( + ref builder, + _o.Is, + _o.Private, + _o.Type, + _o.Default); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/StackBuffer/Table2.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/StackBuffer/Table2.cs new file mode 100644 index 00000000000..8e78f62bdfc --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/StackBuffer/Table2.cs @@ -0,0 +1,98 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeywordTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Table2 : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Table2 GetRootAsTable2(ByteSpanBuffer _bb) { return GetRootAsTable2(_bb, new Table2()); } + public static Table2 GetRootAsTable2(ByteSpanBuffer _bb, Table2 obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Table2 __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public KeywordTest.KeywordsInUnion TypeType { get { int o = __p.__offset(4); return o != 0 ? (KeywordTest.KeywordsInUnion)__p.bb.Get(o + __p.bb_pos) : KeywordTest.KeywordsInUnion.NONE; } } + public RefStructNullable Type() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(6); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public KeywordTest.StackBuffer.KeywordsInTable TypeAsstatic() { return Type().Value; } + public KeywordTest.StackBuffer.KeywordsInTable TypeAsinternal() { return Type().Value; } + + public static Offset CreateTable2(ref FlatSpanBufferBuilder builder, + KeywordTest.KeywordsInUnion type_type = KeywordTest.KeywordsInUnion.NONE, + int typeOffset = 0) { + builder.StartTable(2); + Table2.AddType(ref builder, typeOffset); + Table2.AddTypeType(ref builder, type_type); + return Table2.EndTable2(ref builder); + } + + public static void StartTable2(ref FlatSpanBufferBuilder builder) { builder.StartTable(2); } + public static void AddTypeType(ref FlatSpanBufferBuilder builder, KeywordTest.KeywordsInUnion typeType) { builder.Add(0, (byte)typeType, 0); } + public static void AddType(ref FlatSpanBufferBuilder builder, int typeOffset) { builder.AddOffset(1, typeOffset, 0); } + public static Offset EndTable2(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public Table2T UnPack() { + var _o = new Table2T(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(Table2T _o) { + if (_o.Type == null) { + _o.Type = new KeywordTest.KeywordsInUnionUnion(); + } + var _TypeOldType = _o.Type.Type; + _o.Type.Type = this.TypeType; + switch (this.TypeType) { + default: + _o.Type.Value = null; + break; + case KeywordTest.KeywordsInUnion.@static: + if (this.Type().HasValue) { + if (_TypeOldType == KeywordTest.KeywordsInUnion.@static) { + this.Type().Value.UnPackTo((KeywordTest.KeywordsInTableT)_o.Type.Value); + } else { + _o.Type.Value = this.Type().Value.UnPack(); + } + } else { + _o.Type.Value = null; + } + break; + case KeywordTest.KeywordsInUnion.@internal: + if (this.Type().HasValue) { + if (_TypeOldType == KeywordTest.KeywordsInUnion.@internal) { + this.Type().Value.UnPackTo((KeywordTest.KeywordsInTableT)_o.Type.Value); + } else { + _o.Type.Value = this.Type().Value.UnPack(); + } + } else { + _o.Type.Value = null; + } + break; + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, Table2T _o) { + if (_o == null) return default(Offset); + var _type_type = _o.Type == null ? KeywordTest.KeywordsInUnion.NONE : _o.Type.Type; + var _type = _o.Type == null ? 0 : KeywordTest.KeywordsInUnionUnion.Pack(ref builder, _o.Type); + return CreateTable2( + ref builder, + _type_type, + _type); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/Table2.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/Table2.cs new file mode 100644 index 00000000000..2a2b1da3224 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/Table2.cs @@ -0,0 +1,118 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeywordTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Table2 : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Table2 GetRootAsTable2(ByteBuffer _bb) { return GetRootAsTable2(_bb, new Table2()); } + public static Table2 GetRootAsTable2(ByteBuffer _bb, Table2 obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Table2 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public KeywordTest.KeywordsInUnion TypeType { get { int o = __p.__offset(4); return o != 0 ? (KeywordTest.KeywordsInUnion)__p.bb.Get(o + __p.bb_pos) : KeywordTest.KeywordsInUnion.NONE; } } + public TTable? Type() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public KeywordTest.KeywordsInTable TypeAsstatic() { return Type().Value; } + public KeywordTest.KeywordsInTable TypeAsinternal() { return Type().Value; } + + public static Offset CreateTable2(FlatBufferBuilder builder, + KeywordTest.KeywordsInUnion type_type = KeywordTest.KeywordsInUnion.NONE, + int typeOffset = 0) { + builder.StartTable(2); + Table2.AddType(builder, typeOffset); + Table2.AddTypeType(builder, type_type); + return Table2.EndTable2(builder); + } + + public static void StartTable2(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void AddTypeType(FlatBufferBuilder builder, KeywordTest.KeywordsInUnion typeType) { builder.Add(0, (byte)typeType, 0); } + public static void AddType(FlatBufferBuilder builder, int typeOffset) { builder.AddOffset(1, typeOffset, 0); } + public static Offset EndTable2(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public Table2T UnPack() { + var _o = new Table2T(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(Table2T _o) { + if (_o.Type == null) { + _o.Type = new KeywordTest.KeywordsInUnionUnion(); + } + var _TypeOldType = _o.Type.Type; + _o.Type.Type = this.TypeType; + switch (this.TypeType) { + default: + _o.Type.Value = null; + break; + case KeywordTest.KeywordsInUnion.@static: + if (this.Type().HasValue) { + if (_TypeOldType == KeywordTest.KeywordsInUnion.@static) { + this.Type().Value.UnPackTo((KeywordTest.KeywordsInTableT)_o.Type.Value); + } else { + _o.Type.Value = this.Type().Value.UnPack(); + } + } else { + _o.Type.Value = null; + } + break; + case KeywordTest.KeywordsInUnion.@internal: + if (this.Type().HasValue) { + if (_TypeOldType == KeywordTest.KeywordsInUnion.@internal) { + this.Type().Value.UnPackTo((KeywordTest.KeywordsInTableT)_o.Type.Value); + } else { + _o.Type.Value = this.Type().Value.UnPack(); + } + } else { + _o.Type.Value = null; + } + break; + } + } + public static Offset Pack(FlatBufferBuilder builder, Table2T _o) { + if (_o == null) return default(Offset); + var _type_type = _o.Type == null ? KeywordTest.KeywordsInUnion.NONE : _o.Type.Type; + var _type = _o.Type == null ? 0 : KeywordTest.KeywordsInUnionUnion.Pack(builder, _o.Type); + return CreateTable2( + builder, + _type_type, + _type); + } +} + +public class Table2T +{ + public KeywordTest.KeywordsInUnionUnion Type { get; set; } + + public Table2T() { + this.Type = null; + } +} + + +static public class Table2Verify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*TypeType*/, 1 /*KeywordTest.KeywordsInUnion*/, 1, false) + && verifier.VerifyUnion(tablePos, 4, 6 /*Type*/, KeywordTest.KeywordsInUnionVerify.Verify, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/public.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/public.cs new file mode 100644 index 00000000000..3f622b0e29d --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/keyword_test/KeywordTest/public.cs @@ -0,0 +1,14 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace KeywordTest +{ + +public enum @public : int +{ + NONE = 0, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Color.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Color.cs new file mode 100644 index 00000000000..dd6a1ed51cf --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Color.cs @@ -0,0 +1,16 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MonsterTest +{ + +public enum Color : sbyte +{ + Red = 0, + Green = 1, + Blue = 2, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Equipment.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Equipment.cs new file mode 100644 index 00000000000..c797d4bd1df --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Equipment.cs @@ -0,0 +1,61 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MonsterTest +{ + +public enum Equipment : byte +{ + NONE = 0, + Weapon = 1, +}; + +public class EquipmentUnion { + public Equipment Type { get; set; } + public object Value { get; set; } + + public EquipmentUnion() { + this.Type = Equipment.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public MonsterTest.WeaponT AsWeapon() { return this.As(); } + public static EquipmentUnion FromWeapon(MonsterTest.WeaponT _weapon) { return new EquipmentUnion{ Type = Equipment.Weapon, Value = _weapon }; } + + public static int Pack(Google.FlatSpanBuffers.FlatBufferBuilder builder, EquipmentUnion _o) { + switch (_o.Type) { + default: return 0; + case Equipment.Weapon: return MonsterTest.Weapon.Pack(builder, _o.AsWeapon()).Value; + } + } + public static int Pack(ref Google.FlatSpanBuffers.FlatSpanBufferBuilder builder, EquipmentUnion _o) { + switch (_o.Type) { + default: return 0; + case Equipment.Weapon: return MonsterTest.StackBuffer.Weapon.Pack(ref builder, _o.AsWeapon()).Value; + } + } +} + + + +static public class EquipmentVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, byte typeId, uint tablePos) + { + bool result = true; + switch((Equipment)typeId) + { + case Equipment.Weapon: + result = MonsterTest.WeaponVerify.Verify(ref verifier, tablePos); + break; + default: result = true; + break; + } + return result; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Monster.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Monster.cs new file mode 100644 index 00000000000..3a6d7723839 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Monster.cs @@ -0,0 +1,264 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MonsterTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Monster : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); } + public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool VerifyMonster(ByteBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, MonsterTest.MonsterVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public MonsterTest.Vec3? Pos { get { int o = __p.__offset(4); return o != 0 ? (MonsterTest.Vec3?)(new MonsterTest.Vec3()).__assign(o + __p.bb_pos, __p.bb) : null; } } + public short Mana { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)150; } } + public bool MutateMana(short mana) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, mana); return true; } else { return false; } } + public short Hp { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)100; } } + public bool MutateHp(short hp) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(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; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(10); } + public RefStructNullable> MutableName { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(10)) : default; } } + public RefStructNullable> Inventory { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public RefStructNullable> MutableInventory { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public MonsterTest.Color Color { get { int o = __p.__offset(16); return o != 0 ? (MonsterTest.Color)__p.bb.Get(o + __p.bb_pos) : MonsterTest.Color.Blue; } } + public bool MutateColor(MonsterTest.Color color) { int o = __p.__offset(16); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (sbyte)color); return true; } else { return false; } } + public TableVector? Weapons { get { int o = __p.__offset(18); return o != 0 ? new TableVector(__p, o, 4) : null; } } + public MonsterTest.Equipment EquippedType { get { int o = __p.__offset(20); return o != 0 ? (MonsterTest.Equipment)__p.bb.Get(o + __p.bb_pos) : MonsterTest.Equipment.NONE; } } + public TTable? Equipped() where TTable : struct, IFlatbufferObject { int o = __p.__offset(22); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public MonsterTest.Weapon EquippedAsWeapon() { return Equipped().Value; } + public StructVector? Path { get { int o = __p.__offset(24); return o != 0 ? new StructVector(__p, o, 12) : null; } } + + public static Offset CreateMonster(FlatBufferBuilder builder, + MonsterTest.Vec3T pos = null, + short mana = 150, + short hp = 100, + StringOffset nameOffset = default(StringOffset), + VectorOffset inventoryOffset = default(VectorOffset), + MonsterTest.Color color = MonsterTest.Color.Blue, + VectorOffset weaponsOffset = default(VectorOffset), + MonsterTest.Equipment equipped_type = MonsterTest.Equipment.NONE, + int equippedOffset = 0, + VectorOffset pathOffset = default(VectorOffset)) { + builder.StartTable(11); + Monster.AddPath(builder, pathOffset); + Monster.AddEquipped(builder, equippedOffset); + Monster.AddWeapons(builder, weaponsOffset); + Monster.AddInventory(builder, inventoryOffset); + Monster.AddName(builder, nameOffset); + Monster.AddPos(builder, MonsterTest.Vec3.Pack(builder, pos)); + Monster.AddHp(builder, hp); + Monster.AddMana(builder, mana); + Monster.AddEquippedType(builder, equipped_type); + Monster.AddColor(builder, color); + return Monster.EndMonster(builder); + } + + public static void StartMonster(FlatBufferBuilder builder) { builder.StartTable(11); } + public static void AddPos(FlatBufferBuilder builder, Offset posOffset) { builder.AddStruct(0, posOffset, 0); } + public static void AddMana(FlatBufferBuilder builder, short mana) { builder.Add(1, mana, 150); } + public static void AddHp(FlatBufferBuilder builder, short hp) { builder.Add(2, hp, 100); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(3, nameOffset, 0); } + public static void AddInventory(FlatBufferBuilder builder, VectorOffset inventoryOffset) { builder.AddOffset(5, inventoryOffset, 0); } + public static VectorOffset CreateInventoryVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateInventoryVector(FlatBufferBuilder builder, Span data) { return CreateInventoryVectorBlock(builder, data); } + public static void StartInventoryVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddColor(FlatBufferBuilder builder, MonsterTest.Color color) { builder.Add(6, (sbyte)color, 2); } + public static void AddWeapons(FlatBufferBuilder builder, VectorOffset weaponsOffset) { builder.AddOffset(7, weaponsOffset, 0); } + public static VectorOffset CreateWeaponsVectorBlock(FlatBufferBuilder builder, Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateWeaponsVector(FlatBufferBuilder builder, Span> data) { return CreateWeaponsVectorBlock(builder, data); } + public static void StartWeaponsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddEquippedType(FlatBufferBuilder builder, MonsterTest.Equipment equippedType) { builder.Add(8, (byte)equippedType, 0); } + public static void AddEquipped(FlatBufferBuilder builder, int equippedOffset) { builder.AddOffset(9, equippedOffset, 0); } + public static void AddPath(FlatBufferBuilder builder, VectorOffset pathOffset) { builder.AddOffset(10, pathOffset, 0); } + public static void StartPathVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(12, numElems, 4); } + public static Offset EndMonster(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedMonsterBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + public MonsterT UnPack() { + var _o = new MonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(MonsterT _o) { + if (this.Pos.HasValue) { + if (_o.Pos == null) _o.Pos = new MonsterTest.Vec3T(); + this.Pos.Value.UnPackTo(_o.Pos); + } else { + _o.Pos = null; + } + _o.Mana = this.Mana; + _o.Hp = this.Hp; + _o.Name = this.Name; + var _inventory_vec = this.Inventory; + var _inventory_len = _inventory_vec.HasValue ? _inventory_vec.Value.Length : 0; + if (_o.Inventory == null) { + _o.Inventory = new List(_inventory_len); + } + ObjectApiUtil.ResizeList(_o.Inventory, _inventory_len); + if (_inventory_vec.HasValue) { _inventory_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Inventory)); } + _o.Color = this.Color; + var _weapons_vec = this.Weapons; + var _weapons_len = _weapons_vec.HasValue ? _weapons_vec.Value.Length : 0; + if (_o.Weapons == null) { + _o.Weapons = new List(_weapons_len); + } + ObjectApiUtil.ResizeList(_o.Weapons, _weapons_len); + if (_weapons_vec.HasValue) { + var _weapons_value = _weapons_vec.Value; + for (var _j = 0; _j < _weapons_len; ++_j) { + var _src = _weapons_value[_j]; + if (_o.Weapons[_j] == null) { _o.Weapons[_j] = new WeaponT(); } + _src.UnPackTo(_o.Weapons[_j]); + } + } + if (_o.Equipped == null) { + _o.Equipped = new MonsterTest.EquipmentUnion(); + } + var _EquippedOldType = _o.Equipped.Type; + _o.Equipped.Type = this.EquippedType; + switch (this.EquippedType) { + default: + _o.Equipped.Value = null; + break; + case MonsterTest.Equipment.Weapon: + if (this.Equipped().HasValue) { + if (_EquippedOldType == MonsterTest.Equipment.Weapon) { + this.Equipped().Value.UnPackTo((MonsterTest.WeaponT)_o.Equipped.Value); + } else { + _o.Equipped.Value = this.Equipped().Value.UnPack(); + } + } else { + _o.Equipped.Value = null; + } + break; + } + var _path_vec = this.Path; + var _path_len = _path_vec.HasValue ? _path_vec.Value.Length : 0; + if (_o.Path == null) { + _o.Path = new List(_path_len); + } + ObjectApiUtil.ResizeList(_o.Path, _path_len); + if (_path_vec.HasValue) { + var _path_value = _path_vec.Value; + for (var _j = 0; _j < _path_len; ++_j) { + var _src = _path_value[_j]; + if (_o.Path[_j] == null) { _o.Path[_j] = new Vec3T(); } + _src.UnPackTo(_o.Path[_j]); + } + } + } + public static Offset Pack(FlatBufferBuilder builder, MonsterT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + var _inventory = default(VectorOffset); + if (_o.Inventory != null) { + _inventory = CreateInventoryVector(builder, CollectionsMarshal.AsSpan(_o.Inventory)); + } + var _weapons = default(VectorOffset); + if (_o.Weapons != null) { + var _weapons_len = _o.Weapons.Count; + Offset[] _weapons_arr = null; + try { + Span> __weapons = _weapons_len <= 64 + ? stackalloc Offset[_weapons_len] + : (_weapons_arr = ArrayPool>.Shared.Rent(_weapons_len)).AsSpan(0, _weapons_len); + for (var _j = 0; _j < _weapons_len; ++_j) { __weapons[_j] = MonsterTest.Weapon.Pack(builder, _o.Weapons[_j]); } + _weapons = CreateWeaponsVector(builder, __weapons); + } finally { + if (_weapons_arr != null) { ArrayPool>.Shared.Return(_weapons_arr); } + } + } + var _equipped_type = _o.Equipped == null ? MonsterTest.Equipment.NONE : _o.Equipped.Type; + var _equipped = _o.Equipped == null ? 0 : MonsterTest.EquipmentUnion.Pack(builder, _o.Equipped); + var _path = default(VectorOffset); + if (_o.Path != null) { + StartPathVector(builder, _o.Path.Count); + for (var _j = _o.Path.Count - 1; _j >= 0; --_j) { MonsterTest.Vec3.Pack(builder, _o.Path[_j]); } + _path = builder.EndVector(); + } + return CreateMonster( + builder, + _o.Pos, + _o.Mana, + _o.Hp, + _name, + _inventory, + _o.Color, + _weapons, + _equipped_type, + _equipped, + _path); + } +} + +public class MonsterT +{ + public MonsterTest.Vec3T Pos { get; set; } + public short Mana { get; set; } + public short Hp { get; set; } + public string Name { get; set; } + public List Inventory { get; set; } + public MonsterTest.Color Color { get; set; } + public List Weapons { get; set; } + public MonsterTest.EquipmentUnion Equipped { get; set; } + public List Path { get; set; } + + public MonsterT() { + this.Pos = new MonsterTest.Vec3T(); + this.Mana = 150; + this.Hp = 100; + this.Name = null; + this.Inventory = null; + this.Color = MonsterTest.Color.Blue; + this.Weapons = null; + this.Equipped = null; + this.Path = null; + } + public static MonsterT DeserializeFromBinary(byte[] fbBuffer) { + return Monster.GetRootAsMonster(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + Monster.FinishMonsterBuffer(fbb, Monster.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedSpan().ToArray(); + } +} + + +static public class MonsterVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Pos*/, 12 /*MonsterTest.Vec3*/, 4, false) + && verifier.VerifyField(tablePos, 6 /*Mana*/, 2 /*short*/, 2, false) + && verifier.VerifyField(tablePos, 8 /*Hp*/, 2 /*short*/, 2, false) + && verifier.VerifyString(tablePos, 10 /*Name*/, false) + && verifier.VerifyVectorOfData(tablePos, 14 /*Inventory*/, 1 /*byte*/, false) + && verifier.VerifyField(tablePos, 16 /*Color*/, 1 /*MonsterTest.Color*/, 1, false) + && verifier.VerifyVectorOfTables(tablePos, 18 /*Weapons*/, MonsterTest.WeaponVerify.Verify, false) + && verifier.VerifyField(tablePos, 20 /*EquippedType*/, 1 /*MonsterTest.Equipment*/, 1, false) + && verifier.VerifyUnion(tablePos, 20, 22 /*Equipped*/, MonsterTest.EquipmentVerify.Verify, false) + && verifier.VerifyVectorOfData(tablePos, 24 /*Path*/, 12 /*MonsterTest.Vec3*/, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/StackBuffer/Monster.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/StackBuffer/Monster.cs new file mode 100644 index 00000000000..c2817990ed9 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/StackBuffer/Monster.cs @@ -0,0 +1,187 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MonsterTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Monster : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Monster GetRootAsMonster(ByteSpanBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); } + public static Monster GetRootAsMonster(ByteSpanBuffer _bb, Monster obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool VerifyMonster(ByteSpanBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, MonsterTest.MonsterVerify.Verify); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Monster __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public RefStructNullable Pos { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable((new MonsterTest.StackBuffer.Vec3()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + public short Mana { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)150; } } + public bool MutateMana(short mana) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, mana); return true; } else { return false; } } + public short Hp { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)100; } } + public bool MutateHp(short hp) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(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; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(10); } + public RefStructNullable> MutableName { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(10)) : default; } } + public RefStructNullable> Inventory { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public RefStructNullable> MutableInventory { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public MonsterTest.Color Color { get { int o = __p.__offset(16); return o != 0 ? (MonsterTest.Color)__p.bb.Get(o + __p.bb_pos) : MonsterTest.Color.Blue; } } + public bool MutateColor(MonsterTest.Color color) { int o = __p.__offset(16); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (sbyte)color); return true; } else { return false; } } + public RefStructNullable> Weapons { get { int o = __p.__offset(18); return o != 0 ? new RefStructNullable>(new TableVectorSpan(__p, o, 4)) : default; } } + public MonsterTest.Equipment EquippedType { get { int o = __p.__offset(20); return o != 0 ? (MonsterTest.Equipment)__p.bb.Get(o + __p.bb_pos) : MonsterTest.Equipment.NONE; } } + public RefStructNullable Equipped() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(22); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public MonsterTest.StackBuffer.Weapon EquippedAsWeapon() { return Equipped().Value; } + public RefStructNullable> Path { get { int o = __p.__offset(24); return o != 0 ? new RefStructNullable>(new StructVectorSpan(__p, o, 12)) : default; } } + + public static void StartMonster(ref FlatSpanBufferBuilder builder) { builder.StartTable(11); } + public static void AddPos(ref FlatSpanBufferBuilder builder, Offset posOffset) { builder.AddStruct(0, posOffset, 0); } + public static void AddMana(ref FlatSpanBufferBuilder builder, short mana) { builder.Add(1, mana, 150); } + public static void AddHp(ref FlatSpanBufferBuilder builder, short hp) { builder.Add(2, hp, 100); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(3, nameOffset, 0); } + public static void AddInventory(ref FlatSpanBufferBuilder builder, VectorOffset inventoryOffset) { builder.AddOffset(5, inventoryOffset, 0); } + public static VectorOffset CreateInventoryVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateInventoryVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateInventoryVectorBlock(ref builder, data); } + public static void StartInventoryVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddColor(ref FlatSpanBufferBuilder builder, MonsterTest.Color color) { builder.Add(6, (sbyte)color, 2); } + public static void AddWeapons(ref FlatSpanBufferBuilder builder, VectorOffset weaponsOffset) { builder.AddOffset(7, weaponsOffset, 0); } + public static VectorOffset CreateWeaponsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateWeaponsVector(ref FlatSpanBufferBuilder builder, scoped Span> data) { return CreateWeaponsVectorBlock(ref builder, data); } + public static void StartWeaponsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddEquippedType(ref FlatSpanBufferBuilder builder, MonsterTest.Equipment equippedType) { builder.Add(8, (byte)equippedType, 0); } + public static void AddEquipped(ref FlatSpanBufferBuilder builder, int equippedOffset) { builder.AddOffset(9, equippedOffset, 0); } + public static void AddPath(ref FlatSpanBufferBuilder builder, VectorOffset pathOffset) { builder.AddOffset(10, pathOffset, 0); } + public static void StartPathVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(12, numElems, 4); } + public static Offset EndMonster(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishMonsterBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedMonsterBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + public MonsterT UnPack() { + var _o = new MonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(MonsterT _o) { + if (this.Pos.HasValue) { + if (_o.Pos == null) _o.Pos = new MonsterTest.Vec3T(); + this.Pos.Value.UnPackTo(_o.Pos); + } else { + _o.Pos = null; + } + _o.Mana = this.Mana; + _o.Hp = this.Hp; + _o.Name = this.Name; + var _inventory_vec = this.Inventory; + var _inventory_len = _inventory_vec.HasValue ? _inventory_vec.Value.Length : 0; + if (_o.Inventory == null) { + _o.Inventory = new List(_inventory_len); + } + ObjectApiUtil.ResizeList(_o.Inventory, _inventory_len); + if (_inventory_vec.HasValue) { _inventory_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Inventory)); } + _o.Color = this.Color; + var _weapons_vec = this.Weapons; + var _weapons_len = _weapons_vec.HasValue ? _weapons_vec.Value.Length : 0; + if (_o.Weapons == null) { + _o.Weapons = new List(_weapons_len); + } + ObjectApiUtil.ResizeList(_o.Weapons, _weapons_len); + if (_weapons_vec.HasValue) { + var _weapons_value = _weapons_vec.Value; + for (var _j = 0; _j < _weapons_len; ++_j) { + var _src = _weapons_value[_j]; + if (_o.Weapons[_j] == null) { _o.Weapons[_j] = new WeaponT(); } + _src.UnPackTo(_o.Weapons[_j]); + } + } + if (_o.Equipped == null) { + _o.Equipped = new MonsterTest.EquipmentUnion(); + } + var _EquippedOldType = _o.Equipped.Type; + _o.Equipped.Type = this.EquippedType; + switch (this.EquippedType) { + default: + _o.Equipped.Value = null; + break; + case MonsterTest.Equipment.Weapon: + if (this.Equipped().HasValue) { + if (_EquippedOldType == MonsterTest.Equipment.Weapon) { + this.Equipped().Value.UnPackTo((MonsterTest.WeaponT)_o.Equipped.Value); + } else { + _o.Equipped.Value = this.Equipped().Value.UnPack(); + } + } else { + _o.Equipped.Value = null; + } + break; + } + var _path_vec = this.Path; + var _path_len = _path_vec.HasValue ? _path_vec.Value.Length : 0; + if (_o.Path == null) { + _o.Path = new List(_path_len); + } + ObjectApiUtil.ResizeList(_o.Path, _path_len); + if (_path_vec.HasValue) { + var _path_value = _path_vec.Value; + for (var _j = 0; _j < _path_len; ++_j) { + var _src = _path_value[_j]; + if (_o.Path[_j] == null) { _o.Path[_j] = new Vec3T(); } + _src.UnPackTo(_o.Path[_j]); + } + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, MonsterT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + var _inventory = default(VectorOffset); + if (_o.Inventory != null) { + _inventory = CreateInventoryVector(ref builder, CollectionsMarshal.AsSpan(_o.Inventory)); + } + var _weapons = default(VectorOffset); + if (_o.Weapons != null) { + var _weapons_len = _o.Weapons.Count; + Offset[] _weapons_arr = null; + try { + Span> __weapons = _weapons_len <= 64 + ? stackalloc Offset[_weapons_len] + : (_weapons_arr = ArrayPool>.Shared.Rent(_weapons_len)).AsSpan(0, _weapons_len); + for (var _j = 0; _j < _weapons_len; ++_j) { __weapons[_j] = MonsterTest.StackBuffer.Weapon.Pack(ref builder, _o.Weapons[_j]); } + _weapons = CreateWeaponsVector(ref builder, __weapons); + } finally { + if (_weapons_arr != null) { ArrayPool>.Shared.Return(_weapons_arr); } + } + } + var _equipped_type = _o.Equipped == null ? MonsterTest.Equipment.NONE : _o.Equipped.Type; + var _equipped = _o.Equipped == null ? 0 : MonsterTest.EquipmentUnion.Pack(ref builder, _o.Equipped); + var _path = default(VectorOffset); + if (_o.Path != null) { + StartPathVector(ref builder, _o.Path.Count); + for (var _j = _o.Path.Count - 1; _j >= 0; --_j) { MonsterTest.StackBuffer.Vec3.Pack(ref builder, _o.Path[_j]); } + _path = builder.EndVector(); + } + StartMonster(ref builder); + AddPos(ref builder, MonsterTest.StackBuffer.Vec3.Pack(ref builder, _o.Pos)); + AddMana(ref builder, _o.Mana); + AddHp(ref builder, _o.Hp); + AddName(ref builder, _name); + AddInventory(ref builder, _inventory); + AddColor(ref builder, _o.Color); + AddWeapons(ref builder, _weapons); + AddEquippedType(ref builder, _equipped_type); + AddEquipped(ref builder, _equipped); + AddPath(ref builder, _path); + return EndMonster(ref builder); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/StackBuffer/Vec3.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/StackBuffer/Vec3.cs new file mode 100644 index 00000000000..2c30b427aed --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/StackBuffer/Vec3.cs @@ -0,0 +1,58 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MonsterTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Vec3 : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Vec3 __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public float X { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateX(float x) { __p.bb.Put(__p.bb_pos + 0, x); } + public float Y { get { return __p.bb.Get(__p.bb_pos + 4); } } + public void MutateY(float y) { __p.bb.Put(__p.bb_pos + 4, y); } + public float Z { get { return __p.bb.Get(__p.bb_pos + 8); } } + public void MutateZ(float z) { __p.bb.Put(__p.bb_pos + 8, z); } + + public static Offset CreateVec3(ref FlatSpanBufferBuilder builder, float X, float Y, float Z) { + builder.Prep(4, 12); + builder.Put(Z); + builder.Put(Y); + builder.Put(X); + return new Offset(builder.Offset); + } + public Vec3T UnPack() { + var _o = new Vec3T(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(Vec3T _o) { + _o.X = this.X; + _o.Y = this.Y; + _o.Z = this.Z; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, Vec3T _o) { + if (_o == null) return default(Offset); + return CreateVec3( + ref builder, + _o.X, + _o.Y, + _o.Z); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/StackBuffer/Weapon.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/StackBuffer/Weapon.cs new file mode 100644 index 00000000000..65e53d3194a --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/StackBuffer/Weapon.cs @@ -0,0 +1,68 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MonsterTest.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Weapon : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Weapon GetRootAsWeapon(ByteSpanBuffer _bb) { return GetRootAsWeapon(_bb, new Weapon()); } + public static Weapon GetRootAsWeapon(ByteSpanBuffer _bb, Weapon obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Weapon __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public RefStructNullable> MutableName { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(4)) : default; } } + public short Damage { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)0; } } + public bool MutateDamage(short damage) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, damage); return true; } else { return false; } } + + public static Offset CreateWeapon(ref FlatSpanBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + short damage = 0) { + builder.StartTable(2); + Weapon.AddName(ref builder, nameOffset); + Weapon.AddDamage(ref builder, damage); + return Weapon.EndWeapon(ref builder); + } + + public static void StartWeapon(ref FlatSpanBufferBuilder builder) { builder.StartTable(2); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddDamage(ref FlatSpanBufferBuilder builder, short damage) { builder.Add(1, damage, 0); } + public static Offset EndWeapon(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public WeaponT UnPack() { + var _o = new WeaponT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(WeaponT _o) { + _o.Name = this.Name; + _o.Damage = this.Damage; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, WeaponT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateWeapon( + ref builder, + _name, + _o.Damage); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Vec3.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Vec3.cs new file mode 100644 index 00000000000..a01d4a8c3e9 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Vec3.cs @@ -0,0 +1,71 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MonsterTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Vec3 : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Vec3 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public float X { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateX(float x) { __p.bb.Put(__p.bb_pos + 0, x); } + public float Y { get { return __p.bb.Get(__p.bb_pos + 4); } } + public void MutateY(float y) { __p.bb.Put(__p.bb_pos + 4, y); } + public float Z { get { return __p.bb.Get(__p.bb_pos + 8); } } + public void MutateZ(float z) { __p.bb.Put(__p.bb_pos + 8, z); } + + public static Offset CreateVec3(FlatBufferBuilder builder, float X, float Y, float Z) { + builder.Prep(4, 12); + builder.Put(Z); + builder.Put(Y); + builder.Put(X); + return new Offset(builder.Offset); + } + public Vec3T UnPack() { + var _o = new Vec3T(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(Vec3T _o) { + _o.X = this.X; + _o.Y = this.Y; + _o.Z = this.Z; + } + public static Offset Pack(FlatBufferBuilder builder, Vec3T _o) { + if (_o == null) return default(Offset); + return CreateVec3( + builder, + _o.X, + _o.Y, + _o.Z); + } +} + +public class Vec3T +{ + public float X { get; set; } + public float Y { get; set; } + public float Z { get; set; } + + public Vec3T() { + this.X = 0.0f; + this.Y = 0.0f; + this.Z = 0.0f; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Weapon.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Weapon.cs new file mode 100644 index 00000000000..bb1616830c0 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/monster_test/MonsterTest/Weapon.cs @@ -0,0 +1,90 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MonsterTest +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Weapon : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Weapon GetRootAsWeapon(ByteBuffer _bb) { return GetRootAsWeapon(_bb, new Weapon()); } + public static Weapon GetRootAsWeapon(ByteBuffer _bb, Weapon obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Weapon __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(4); } + public RefStructNullable> MutableName { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(4)) : default; } } + public short Damage { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)0; } } + public bool MutateDamage(short damage) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, damage); return true; } else { return false; } } + + public static Offset CreateWeapon(FlatBufferBuilder builder, + StringOffset nameOffset = default(StringOffset), + short damage = 0) { + builder.StartTable(2); + Weapon.AddName(builder, nameOffset); + Weapon.AddDamage(builder, damage); + return Weapon.EndWeapon(builder); + } + + public static void StartWeapon(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(0, nameOffset, 0); } + public static void AddDamage(FlatBufferBuilder builder, short damage) { builder.Add(1, damage, 0); } + public static Offset EndWeapon(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public WeaponT UnPack() { + var _o = new WeaponT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(WeaponT _o) { + _o.Name = this.Name; + _o.Damage = this.Damage; + } + public static Offset Pack(FlatBufferBuilder builder, WeaponT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + return CreateWeapon( + builder, + _name, + _o.Damage); + } +} + +public class WeaponT +{ + public string Name { get; set; } + public short Damage { get; set; } + + public WeaponT() { + this.Name = null; + this.Damage = 0; + } +} + + +static public class WeaponVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*Name*/, false) + && verifier.VerifyField(tablePos, 6 /*Damage*/, 2 /*short*/, 2, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Ability.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Ability.cs new file mode 100644 index 00000000000..79320f21544 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Ability.cs @@ -0,0 +1,66 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Ability : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Ability __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public uint Id { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateId(uint id) { __p.bb.Put(__p.bb_pos + 0, id); } + public uint Distance { get { return __p.bb.Get(__p.bb_pos + 4); } } + public void MutateDistance(uint distance) { __p.bb.Put(__p.bb_pos + 4, distance); } + + public static Offset CreateAbility(FlatBufferBuilder builder, uint Id, uint Distance) { + builder.Prep(4, 8); + builder.Put(Distance); + builder.Put(Id); + return new Offset(builder.Offset); + } + public AbilityT UnPack() { + var _o = new AbilityT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(AbilityT _o) { + _o.Id = this.Id; + _o.Distance = this.Distance; + } + public static Offset Pack(FlatBufferBuilder builder, AbilityT _o) { + if (_o == null) return default(Offset); + return CreateAbility( + builder, + _o.Id, + _o.Distance); + } +} + +public class AbilityT +{ + [System.Text.Json.Serialization.JsonPropertyName("id")] + public uint Id { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("distance")] + public uint Distance { get; set; } + + public AbilityT() { + this.Id = 0; + this.Distance = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Any.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Any.cs new file mode 100644 index 00000000000..48df7776b88 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Any.cs @@ -0,0 +1,125 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +public enum Any : byte +{ + NONE = 0, + Monster = 1, + TestSimpleTableWithEnum = 2, + MyGame_Example2_Monster = 3, +}; + +[System.Text.Json.Serialization.JsonConverter(typeof(AnyUnion_JsonConverter))] +public class AnyUnion { + public Any Type { get; set; } + public object Value { get; set; } + + public AnyUnion() { + this.Type = Any.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public MyGame.Example.MonsterT AsMonster() { return this.As(); } + public static AnyUnion FromMonster(MyGame.Example.MonsterT _monster) { return new AnyUnion{ Type = Any.Monster, Value = _monster }; } + public MyGame.Example.TestSimpleTableWithEnumT AsTestSimpleTableWithEnum() { return this.As(); } + public static AnyUnion FromTestSimpleTableWithEnum(MyGame.Example.TestSimpleTableWithEnumT _testsimpletablewithenum) { return new AnyUnion{ Type = Any.TestSimpleTableWithEnum, Value = _testsimpletablewithenum }; } + public MyGame.Example2.MonsterT AsMyGame_Example2_Monster() { return this.As(); } + public static AnyUnion FromMyGame_Example2_Monster(MyGame.Example2.MonsterT _mygame_example2_monster) { return new AnyUnion{ Type = Any.MyGame_Example2_Monster, Value = _mygame_example2_monster }; } + + public static int Pack(Google.FlatSpanBuffers.FlatBufferBuilder builder, AnyUnion _o) { + switch (_o.Type) { + default: return 0; + case Any.Monster: return MyGame.Example.Monster.Pack(builder, _o.AsMonster()).Value; + case Any.TestSimpleTableWithEnum: return MyGame.Example.TestSimpleTableWithEnum.Pack(builder, _o.AsTestSimpleTableWithEnum()).Value; + case Any.MyGame_Example2_Monster: return MyGame.Example2.Monster.Pack(builder, _o.AsMyGame_Example2_Monster()).Value; + } + } + public static int Pack(ref Google.FlatSpanBuffers.FlatSpanBufferBuilder builder, AnyUnion _o) { + switch (_o.Type) { + default: return 0; + case Any.Monster: return MyGame.Example.StackBuffer.Monster.Pack(ref builder, _o.AsMonster()).Value; + case Any.TestSimpleTableWithEnum: return MyGame.Example.StackBuffer.TestSimpleTableWithEnum.Pack(ref builder, _o.AsTestSimpleTableWithEnum()).Value; + case Any.MyGame_Example2_Monster: return MyGame.Example2.StackBuffer.Monster.Pack(ref builder, _o.AsMyGame_Example2_Monster()).Value; + } + } +} + +public class AnyUnion_JsonConverter : System.Text.Json.Serialization.JsonConverter { + public override AnyUnion Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { + if (reader.TokenType == System.Text.Json.JsonTokenType.Null) { reader.Read(); return null; } + if (reader.TokenType != System.Text.Json.JsonTokenType.StartObject) throw new System.Text.Json.JsonException("Expected start of object for union type"); + Any unionType = Any.NONE; + AnyUnion result = new AnyUnion(); + while (reader.Read()) { + if (reader.TokenType == System.Text.Json.JsonTokenType.EndObject) break; + if (reader.TokenType != System.Text.Json.JsonTokenType.PropertyName) continue; + string propName = reader.GetString(); + reader.Read(); + if (propName == "Type") { + string typeName = reader.GetString(); + if (System.Enum.TryParse(typeName, out var parsed)) unionType = parsed; + } else if (propName == "Value") { + result.Type = unionType; + switch (unionType) { + default: break; + case Any.Monster: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Any.TestSimpleTableWithEnum: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Any.MyGame_Example2_Monster: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + } + } + return result; + } + public AnyUnion ReadWithTypeContext(ref System.Text.Json.Utf8JsonReader reader, AnyUnion _o, System.Text.Json.JsonSerializerOptions options) { + if (_o == null) return null; + switch (_o.Type) { + default: break; + case Any.Monster: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Any.TestSimpleTableWithEnum: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Any.MyGame_Example2_Monster: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + return _o; + } + public override void Write(System.Text.Json.Utf8JsonWriter writer, AnyUnion value, System.Text.Json.JsonSerializerOptions options) { + if (value == null || value.Value == null) { writer.WriteNullValue(); return; } + writer.WriteStartObject(); + writer.WriteString("Type", value.Type.ToString()); + writer.WritePropertyName("Value"); + System.Text.Json.JsonSerializer.Serialize(writer, value.Value, value.Value.GetType(), options); + writer.WriteEndObject(); + } +} + + + +static public class AnyVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, byte typeId, uint tablePos) + { + bool result = true; + switch((Any)typeId) + { + case Any.Monster: + result = MyGame.Example.MonsterVerify.Verify(ref verifier, tablePos); + break; + case Any.TestSimpleTableWithEnum: + result = MyGame.Example.TestSimpleTableWithEnumVerify.Verify(ref verifier, tablePos); + break; + case Any.MyGame_Example2_Monster: + result = MyGame.Example2.MonsterVerify.Verify(ref verifier, tablePos); + break; + default: result = true; + break; + } + return result; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/AnyAmbiguousAliases.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/AnyAmbiguousAliases.cs new file mode 100644 index 00000000000..4decb929ff8 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/AnyAmbiguousAliases.cs @@ -0,0 +1,125 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +public enum AnyAmbiguousAliases : byte +{ + NONE = 0, + M1 = 1, + M2 = 2, + M3 = 3, +}; + +[System.Text.Json.Serialization.JsonConverter(typeof(AnyAmbiguousAliasesUnion_JsonConverter))] +public class AnyAmbiguousAliasesUnion { + public AnyAmbiguousAliases Type { get; set; } + public object Value { get; set; } + + public AnyAmbiguousAliasesUnion() { + this.Type = AnyAmbiguousAliases.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public MyGame.Example.MonsterT AsM1() { return this.As(); } + public static AnyAmbiguousAliasesUnion FromM1(MyGame.Example.MonsterT _m1) { return new AnyAmbiguousAliasesUnion{ Type = AnyAmbiguousAliases.M1, Value = _m1 }; } + public MyGame.Example.MonsterT AsM2() { return this.As(); } + public static AnyAmbiguousAliasesUnion FromM2(MyGame.Example.MonsterT _m2) { return new AnyAmbiguousAliasesUnion{ Type = AnyAmbiguousAliases.M2, Value = _m2 }; } + public MyGame.Example.MonsterT AsM3() { return this.As(); } + public static AnyAmbiguousAliasesUnion FromM3(MyGame.Example.MonsterT _m3) { return new AnyAmbiguousAliasesUnion{ Type = AnyAmbiguousAliases.M3, Value = _m3 }; } + + public static int Pack(Google.FlatSpanBuffers.FlatBufferBuilder builder, AnyAmbiguousAliasesUnion _o) { + switch (_o.Type) { + default: return 0; + case AnyAmbiguousAliases.M1: return MyGame.Example.Monster.Pack(builder, _o.AsM1()).Value; + case AnyAmbiguousAliases.M2: return MyGame.Example.Monster.Pack(builder, _o.AsM2()).Value; + case AnyAmbiguousAliases.M3: return MyGame.Example.Monster.Pack(builder, _o.AsM3()).Value; + } + } + public static int Pack(ref Google.FlatSpanBuffers.FlatSpanBufferBuilder builder, AnyAmbiguousAliasesUnion _o) { + switch (_o.Type) { + default: return 0; + case AnyAmbiguousAliases.M1: return MyGame.Example.StackBuffer.Monster.Pack(ref builder, _o.AsM1()).Value; + case AnyAmbiguousAliases.M2: return MyGame.Example.StackBuffer.Monster.Pack(ref builder, _o.AsM2()).Value; + case AnyAmbiguousAliases.M3: return MyGame.Example.StackBuffer.Monster.Pack(ref builder, _o.AsM3()).Value; + } + } +} + +public class AnyAmbiguousAliasesUnion_JsonConverter : System.Text.Json.Serialization.JsonConverter { + public override AnyAmbiguousAliasesUnion Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { + if (reader.TokenType == System.Text.Json.JsonTokenType.Null) { reader.Read(); return null; } + if (reader.TokenType != System.Text.Json.JsonTokenType.StartObject) throw new System.Text.Json.JsonException("Expected start of object for union type"); + AnyAmbiguousAliases unionType = AnyAmbiguousAliases.NONE; + AnyAmbiguousAliasesUnion result = new AnyAmbiguousAliasesUnion(); + while (reader.Read()) { + if (reader.TokenType == System.Text.Json.JsonTokenType.EndObject) break; + if (reader.TokenType != System.Text.Json.JsonTokenType.PropertyName) continue; + string propName = reader.GetString(); + reader.Read(); + if (propName == "Type") { + string typeName = reader.GetString(); + if (System.Enum.TryParse(typeName, out var parsed)) unionType = parsed; + } else if (propName == "Value") { + result.Type = unionType; + switch (unionType) { + default: break; + case AnyAmbiguousAliases.M1: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case AnyAmbiguousAliases.M2: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case AnyAmbiguousAliases.M3: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + } + } + return result; + } + public AnyAmbiguousAliasesUnion ReadWithTypeContext(ref System.Text.Json.Utf8JsonReader reader, AnyAmbiguousAliasesUnion _o, System.Text.Json.JsonSerializerOptions options) { + if (_o == null) return null; + switch (_o.Type) { + default: break; + case AnyAmbiguousAliases.M1: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case AnyAmbiguousAliases.M2: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case AnyAmbiguousAliases.M3: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + return _o; + } + public override void Write(System.Text.Json.Utf8JsonWriter writer, AnyAmbiguousAliasesUnion value, System.Text.Json.JsonSerializerOptions options) { + if (value == null || value.Value == null) { writer.WriteNullValue(); return; } + writer.WriteStartObject(); + writer.WriteString("Type", value.Type.ToString()); + writer.WritePropertyName("Value"); + System.Text.Json.JsonSerializer.Serialize(writer, value.Value, value.Value.GetType(), options); + writer.WriteEndObject(); + } +} + + + +static public class AnyAmbiguousAliasesVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, byte typeId, uint tablePos) + { + bool result = true; + switch((AnyAmbiguousAliases)typeId) + { + case AnyAmbiguousAliases.M1: + result = MyGame.Example.MonsterVerify.Verify(ref verifier, tablePos); + break; + case AnyAmbiguousAliases.M2: + result = MyGame.Example.MonsterVerify.Verify(ref verifier, tablePos); + break; + case AnyAmbiguousAliases.M3: + result = MyGame.Example.MonsterVerify.Verify(ref verifier, tablePos); + break; + default: result = true; + break; + } + return result; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/AnyUniqueAliases.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/AnyUniqueAliases.cs new file mode 100644 index 00000000000..ae62f6ffcf4 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/AnyUniqueAliases.cs @@ -0,0 +1,125 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +public enum AnyUniqueAliases : byte +{ + NONE = 0, + M = 1, + TS = 2, + M2 = 3, +}; + +[System.Text.Json.Serialization.JsonConverter(typeof(AnyUniqueAliasesUnion_JsonConverter))] +public class AnyUniqueAliasesUnion { + public AnyUniqueAliases Type { get; set; } + public object Value { get; set; } + + public AnyUniqueAliasesUnion() { + this.Type = AnyUniqueAliases.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public MyGame.Example.MonsterT AsM() { return this.As(); } + public static AnyUniqueAliasesUnion FromM(MyGame.Example.MonsterT _m) { return new AnyUniqueAliasesUnion{ Type = AnyUniqueAliases.M, Value = _m }; } + public MyGame.Example.TestSimpleTableWithEnumT AsTS() { return this.As(); } + public static AnyUniqueAliasesUnion FromTS(MyGame.Example.TestSimpleTableWithEnumT _ts) { return new AnyUniqueAliasesUnion{ Type = AnyUniqueAliases.TS, Value = _ts }; } + public MyGame.Example2.MonsterT AsM2() { return this.As(); } + public static AnyUniqueAliasesUnion FromM2(MyGame.Example2.MonsterT _m2) { return new AnyUniqueAliasesUnion{ Type = AnyUniqueAliases.M2, Value = _m2 }; } + + public static int Pack(Google.FlatSpanBuffers.FlatBufferBuilder builder, AnyUniqueAliasesUnion _o) { + switch (_o.Type) { + default: return 0; + case AnyUniqueAliases.M: return MyGame.Example.Monster.Pack(builder, _o.AsM()).Value; + case AnyUniqueAliases.TS: return MyGame.Example.TestSimpleTableWithEnum.Pack(builder, _o.AsTS()).Value; + case AnyUniqueAliases.M2: return MyGame.Example2.Monster.Pack(builder, _o.AsM2()).Value; + } + } + public static int Pack(ref Google.FlatSpanBuffers.FlatSpanBufferBuilder builder, AnyUniqueAliasesUnion _o) { + switch (_o.Type) { + default: return 0; + case AnyUniqueAliases.M: return MyGame.Example.StackBuffer.Monster.Pack(ref builder, _o.AsM()).Value; + case AnyUniqueAliases.TS: return MyGame.Example.StackBuffer.TestSimpleTableWithEnum.Pack(ref builder, _o.AsTS()).Value; + case AnyUniqueAliases.M2: return MyGame.Example2.StackBuffer.Monster.Pack(ref builder, _o.AsM2()).Value; + } + } +} + +public class AnyUniqueAliasesUnion_JsonConverter : System.Text.Json.Serialization.JsonConverter { + public override AnyUniqueAliasesUnion Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { + if (reader.TokenType == System.Text.Json.JsonTokenType.Null) { reader.Read(); return null; } + if (reader.TokenType != System.Text.Json.JsonTokenType.StartObject) throw new System.Text.Json.JsonException("Expected start of object for union type"); + AnyUniqueAliases unionType = AnyUniqueAliases.NONE; + AnyUniqueAliasesUnion result = new AnyUniqueAliasesUnion(); + while (reader.Read()) { + if (reader.TokenType == System.Text.Json.JsonTokenType.EndObject) break; + if (reader.TokenType != System.Text.Json.JsonTokenType.PropertyName) continue; + string propName = reader.GetString(); + reader.Read(); + if (propName == "Type") { + string typeName = reader.GetString(); + if (System.Enum.TryParse(typeName, out var parsed)) unionType = parsed; + } else if (propName == "Value") { + result.Type = unionType; + switch (unionType) { + default: break; + case AnyUniqueAliases.M: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case AnyUniqueAliases.TS: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case AnyUniqueAliases.M2: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + } + } + return result; + } + public AnyUniqueAliasesUnion ReadWithTypeContext(ref System.Text.Json.Utf8JsonReader reader, AnyUniqueAliasesUnion _o, System.Text.Json.JsonSerializerOptions options) { + if (_o == null) return null; + switch (_o.Type) { + default: break; + case AnyUniqueAliases.M: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case AnyUniqueAliases.TS: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case AnyUniqueAliases.M2: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + return _o; + } + public override void Write(System.Text.Json.Utf8JsonWriter writer, AnyUniqueAliasesUnion value, System.Text.Json.JsonSerializerOptions options) { + if (value == null || value.Value == null) { writer.WriteNullValue(); return; } + writer.WriteStartObject(); + writer.WriteString("Type", value.Type.ToString()); + writer.WritePropertyName("Value"); + System.Text.Json.JsonSerializer.Serialize(writer, value.Value, value.Value.GetType(), options); + writer.WriteEndObject(); + } +} + + + +static public class AnyUniqueAliasesVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, byte typeId, uint tablePos) + { + bool result = true; + switch((AnyUniqueAliases)typeId) + { + case AnyUniqueAliases.M: + result = MyGame.Example.MonsterVerify.Verify(ref verifier, tablePos); + break; + case AnyUniqueAliases.TS: + result = MyGame.Example.TestSimpleTableWithEnumVerify.Verify(ref verifier, tablePos); + break; + case AnyUniqueAliases.M2: + result = MyGame.Example2.MonsterVerify.Verify(ref verifier, tablePos); + break; + default: result = true; + break; + } + return result; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Color.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Color.cs new file mode 100644 index 00000000000..dcd23317208 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Color.cs @@ -0,0 +1,22 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +/// Composite components of Monster color. +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +[System.FlagsAttribute] +public enum Color : byte +{ + Red = 1, + /// \brief color Green + /// Green is bit_flag with value (1u << 1) + Green = 2, + /// \brief color Blue (1u << 3) + Blue = 8, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/LongEnum.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/LongEnum.cs new file mode 100644 index 00000000000..8e399f723bd --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/LongEnum.cs @@ -0,0 +1,18 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +[System.FlagsAttribute] +public enum LongEnum : ulong +{ + LongOne = 2, + LongTwo = 4, + LongBig = 1099511627776, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Monster.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Monster.cs new file mode 100644 index 00000000000..327440cca63 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Monster.cs @@ -0,0 +1,1340 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +/// an example documentation comment: "monster object" +public struct Monster : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); } + public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool MonsterBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "MONS"); } + public static bool VerifyMonster(ByteBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("MONS", false, MyGame.Example.MonsterVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Example.Vec3? Pos { get { int o = __p.__offset(4); return o != 0 ? (MyGame.Example.Vec3?)(new MyGame.Example.Vec3()).__assign(o + __p.bb_pos, __p.bb) : null; } } + public short Mana { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)150; } } + public bool MutateMana(short mana) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, mana); return true; } else { return false; } } + public short Hp { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)100; } } + public bool MutateHp(short hp) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(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; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(10); } + public RefStructNullable> MutableName { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(10)) : default; } } + public RefStructNullable> Inventory { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public RefStructNullable> MutableInventory { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public MyGame.Example.Color Color { get { int o = __p.__offset(16); return o != 0 ? (MyGame.Example.Color)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Color.Blue; } } + public bool MutateColor(MyGame.Example.Color color) { int o = __p.__offset(16); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, (byte)color); return true; } else { return false; } } + public MyGame.Example.Any TestType { get { int o = __p.__offset(18); return o != 0 ? (MyGame.Example.Any)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Any.NONE; } } + public TTable? Test() where TTable : struct, IFlatbufferObject { int o = __p.__offset(20); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public MyGame.Example.Monster TestAsMonster() { return Test().Value; } + public MyGame.Example.TestSimpleTableWithEnum TestAsTestSimpleTableWithEnum() { return Test().Value; } + public MyGame.Example2.Monster TestAsMyGame_Example2_Monster() { return Test().Value; } + public StructVector? Test4 { get { int o = __p.__offset(22); return o != 0 ? new StructVector(__p, o, 4) : null; } } + public StringVector? Testarrayofstring { get { int o = __p.__offset(24); return o != 0 ? new StringVector(__p, o) : null; } } + /// an example documentation comment: this will end up in the generated code + /// multiline too + public TableVector? Testarrayoftables { get { int o = __p.__offset(26); return o != 0 ? new TableVector(__p, o, 4) : null; } } + public bool TryGetTestarrayoftablesByKey(string key, out MyGame.Example.Monster value) { int o = __p.__offset(26); if (o != 0) { return MyGame.Example.Monster.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public MyGame.Example.Monster? Enemy { get { int o = __p.__offset(28); return o != 0 ? (MyGame.Example.Monster?)(new MyGame.Example.Monster()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + public RefStructNullable> Testnestedflatbuffer { get { int o = __p.__offset(30); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(30)) : default; } } + public RefStructNullable> MutableTestnestedflatbuffer { get { int o = __p.__offset(30); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(30)) : default; } } + public MyGame.Example.Monster? GetTestnestedflatbufferAsMonster() { int o = __p.__offset(30); return o != 0 ? (MyGame.Example.Monster?)(new MyGame.Example.Monster()).__assign(__p.__indirect(__p.__vector(o)), __p.bb) : null; } + public MyGame.Example.Stat? Testempty { get { int o = __p.__offset(32); return o != 0 ? (MyGame.Example.Stat?)(new MyGame.Example.Stat()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + public bool Testbool { get { int o = __p.__offset(34); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public bool MutateTestbool(bool testbool) { int o = __p.__offset(34); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } } + public int Testhashs32Fnv1 { get { int o = __p.__offset(36); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public bool MutateTesthashs32Fnv1(int testhashs32_fnv1) { int o = __p.__offset(36); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashs32_fnv1); return true; } else { return false; } } + public uint Testhashu32Fnv1 { get { int o = __p.__offset(38); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint)0; } } + public bool MutateTesthashu32Fnv1(uint testhashu32_fnv1) { int o = __p.__offset(38); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashu32_fnv1); return true; } else { return false; } } + public long Testhashs64Fnv1 { get { int o = __p.__offset(40); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public bool MutateTesthashs64Fnv1(long testhashs64_fnv1) { int o = __p.__offset(40); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashs64_fnv1); return true; } else { return false; } } + public ulong Testhashu64Fnv1 { get { int o = __p.__offset(42); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateTesthashu64Fnv1(ulong testhashu64_fnv1) { int o = __p.__offset(42); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashu64_fnv1); return true; } else { return false; } } + public int Testhashs32Fnv1a { get { int o = __p.__offset(44); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public bool MutateTesthashs32Fnv1a(int testhashs32_fnv1a) { int o = __p.__offset(44); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashs32_fnv1a); return true; } else { return false; } } + public uint Testhashu32Fnv1a { get { int o = __p.__offset(46); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint)0; } } + public bool MutateTesthashu32Fnv1a(uint testhashu32_fnv1a) { int o = __p.__offset(46); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashu32_fnv1a); return true; } else { return false; } } + public long Testhashs64Fnv1a { get { int o = __p.__offset(48); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public bool MutateTesthashs64Fnv1a(long testhashs64_fnv1a) { int o = __p.__offset(48); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashs64_fnv1a); return true; } else { return false; } } + public ulong Testhashu64Fnv1a { get { int o = __p.__offset(50); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __p.__offset(50); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashu64_fnv1a); return true; } else { return false; } } + public RefStructNullable> Testarrayofbools { get { int o = __p.__offset(52); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(52)) : default; } } + public RefStructNullable> MutableTestarrayofbools { get { int o = __p.__offset(52); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(52)) : default; } } + public float Testf { get { int o = __p.__offset(54); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)3.14159f; } } + public bool MutateTestf(float testf) { int o = __p.__offset(54); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf); return true; } else { return false; } } + public float Testf2 { get { int o = __p.__offset(56); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)3.0f; } } + public bool MutateTestf2(float testf2) { int o = __p.__offset(56); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf2); return true; } else { return false; } } + public float Testf3 { get { int o = __p.__offset(58); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)0.0f; } } + public bool MutateTestf3(float testf3) { int o = __p.__offset(58); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf3); return true; } else { return false; } } + public StringVector? Testarrayofstring2 { get { int o = __p.__offset(60); return o != 0 ? new StringVector(__p, o) : null; } } + public StructVector? Testarrayofsortedstruct { get { int o = __p.__offset(62); return o != 0 ? new StructVector(__p, o, 8) : null; } } + public RefStructNullable> Flex { get { int o = __p.__offset(64); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(64)) : default; } } + public RefStructNullable> MutableFlex { get { int o = __p.__offset(64); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(64)) : default; } } + public StructVector? Test5 { get { int o = __p.__offset(66); return o != 0 ? new StructVector(__p, o, 4) : null; } } + public RefStructNullable> VectorOfLongs { get { int o = __p.__offset(68); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(68)) : default; } } + public RefStructNullable> MutableVectorOfLongs { get { int o = __p.__offset(68); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(68)) : default; } } + public RefStructNullable> VectorOfDoubles { get { int o = __p.__offset(70); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(70)) : default; } } + public RefStructNullable> MutableVectorOfDoubles { get { int o = __p.__offset(70); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(70)) : default; } } + 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 TableVector? VectorOfReferrables { get { int o = __p.__offset(74); return o != 0 ? new TableVector(__p, o, 4) : null; } } + public bool TryGetVectorOfReferrablesByKey(ulong key, out MyGame.Example.Referrable value) { int o = __p.__offset(74); if (o != 0) { return MyGame.Example.Referrable.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public ulong SingleWeakReference { get { int o = __p.__offset(76); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateSingleWeakReference(ulong single_weak_reference) { int o = __p.__offset(76); if (o != 0) { __p.bb.Put(o + __p.bb_pos, single_weak_reference); return true; } else { return false; } } + public RefStructNullable> VectorOfWeakReferences { get { int o = __p.__offset(78); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(78)) : default; } } + public RefStructNullable> MutableVectorOfWeakReferences { get { int o = __p.__offset(78); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(78)) : default; } } + public TableVector? VectorOfStrongReferrables { get { int o = __p.__offset(80); return o != 0 ? new TableVector(__p, o, 4) : null; } } + public bool TryGetVectorOfStrongReferrablesByKey(ulong key, out MyGame.Example.Referrable value) { int o = __p.__offset(80); if (o != 0) { return MyGame.Example.Referrable.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public ulong CoOwningReference { get { int o = __p.__offset(82); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateCoOwningReference(ulong co_owning_reference) { int o = __p.__offset(82); if (o != 0) { __p.bb.Put(o + __p.bb_pos, co_owning_reference); return true; } else { return false; } } + public RefStructNullable> VectorOfCoOwningReferences { get { int o = __p.__offset(84); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(84)) : default; } } + public RefStructNullable> MutableVectorOfCoOwningReferences { get { int o = __p.__offset(84); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(84)) : default; } } + public ulong NonOwningReference { get { int o = __p.__offset(86); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateNonOwningReference(ulong non_owning_reference) { int o = __p.__offset(86); if (o != 0) { __p.bb.Put(o + __p.bb_pos, non_owning_reference); return true; } else { return false; } } + public RefStructNullable> VectorOfNonOwningReferences { get { int o = __p.__offset(88); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(88)) : default; } } + public RefStructNullable> MutableVectorOfNonOwningReferences { get { int o = __p.__offset(88); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(88)) : default; } } + public MyGame.Example.AnyUniqueAliases AnyUniqueType { get { int o = __p.__offset(90); return o != 0 ? (MyGame.Example.AnyUniqueAliases)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.AnyUniqueAliases.NONE; } } + public TTable? AnyUnique() where TTable : struct, IFlatbufferObject { int o = __p.__offset(92); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public MyGame.Example.Monster AnyUniqueAsM() { return AnyUnique().Value; } + public MyGame.Example.TestSimpleTableWithEnum AnyUniqueAsTS() { return AnyUnique().Value; } + public MyGame.Example2.Monster AnyUniqueAsM2() { return AnyUnique().Value; } + public MyGame.Example.AnyAmbiguousAliases AnyAmbiguousType { get { int o = __p.__offset(94); return o != 0 ? (MyGame.Example.AnyAmbiguousAliases)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.AnyAmbiguousAliases.NONE; } } + public TTable? AnyAmbiguous() where TTable : struct, IFlatbufferObject { int o = __p.__offset(96); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public MyGame.Example.Monster AnyAmbiguousAsM1() { return AnyAmbiguous().Value; } + public MyGame.Example.Monster AnyAmbiguousAsM2() { return AnyAmbiguous().Value; } + public MyGame.Example.Monster AnyAmbiguousAsM3() { return AnyAmbiguous().Value; } + public RefStructNullable> VectorOfEnums { get { int o = __p.__offset(98); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(98)) : default; } } + public RefStructNullable> MutableVectorOfEnums { get { int o = __p.__offset(98); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(98)) : default; } } + public MyGame.Example.Race SignedEnum { get { int o = __p.__offset(100); return o != 0 ? (MyGame.Example.Race)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Race.None; } } + public bool MutateSignedEnum(MyGame.Example.Race signed_enum) { int o = __p.__offset(100); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (sbyte)signed_enum); return true; } else { return false; } } + public RefStructNullable> Testrequirednestedflatbuffer { get { int o = __p.__offset(102); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(102)) : default; } } + public RefStructNullable> MutableTestrequirednestedflatbuffer { get { int o = __p.__offset(102); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(102)) : default; } } + public MyGame.Example.Monster? GetTestrequirednestedflatbufferAsMonster() { int o = __p.__offset(102); return o != 0 ? (MyGame.Example.Monster?)(new MyGame.Example.Monster()).__assign(__p.__indirect(__p.__vector(o)), __p.bb) : null; } + public TableVector? ScalarKeySortedTables { get { int o = __p.__offset(104); return o != 0 ? new TableVector(__p, o, 4) : null; } } + public bool TryGetScalarKeySortedTablesByKey(ushort key, out MyGame.Example.Stat value) { int o = __p.__offset(104); if (o != 0) { return MyGame.Example.Stat.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public MyGame.Example.Test? NativeInline { get { int o = __p.__offset(106); return o != 0 ? (MyGame.Example.Test?)(new MyGame.Example.Test()).__assign(o + __p.bb_pos, __p.bb) : null; } } + public MyGame.Example.LongEnum LongEnumNonEnumDefault { get { int o = __p.__offset(108); return o != 0 ? (MyGame.Example.LongEnum)__p.bb.Get(o + __p.bb_pos) : 0; } } + public bool MutateLongEnumNonEnumDefault(MyGame.Example.LongEnum long_enum_non_enum_default) { int o = __p.__offset(108); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (ulong)long_enum_non_enum_default); return true; } else { return false; } } + public MyGame.Example.LongEnum LongEnumNormalDefault { get { int o = __p.__offset(110); return o != 0 ? (MyGame.Example.LongEnum)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.LongEnum.LongOne; } } + public bool MutateLongEnumNormalDefault(MyGame.Example.LongEnum long_enum_normal_default) { int o = __p.__offset(110); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (ulong)long_enum_normal_default); return true; } else { return false; } } + public float NanDefault { get { int o = __p.__offset(112); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.NaN; } } + public bool MutateNanDefault(float nan_default) { int o = __p.__offset(112); if (o != 0) { __p.bb.Put(o + __p.bb_pos, nan_default); return true; } else { return false; } } + public float InfDefault { get { int o = __p.__offset(114); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.PositiveInfinity; } } + public bool MutateInfDefault(float inf_default) { int o = __p.__offset(114); if (o != 0) { __p.bb.Put(o + __p.bb_pos, inf_default); return true; } else { return false; } } + public float PositiveInfDefault { get { int o = __p.__offset(116); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.PositiveInfinity; } } + public bool MutatePositiveInfDefault(float positive_inf_default) { int o = __p.__offset(116); if (o != 0) { __p.bb.Put(o + __p.bb_pos, positive_inf_default); return true; } else { return false; } } + public float InfinityDefault { get { int o = __p.__offset(118); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.PositiveInfinity; } } + public bool MutateInfinityDefault(float infinity_default) { int o = __p.__offset(118); if (o != 0) { __p.bb.Put(o + __p.bb_pos, infinity_default); return true; } else { return false; } } + public float PositiveInfinityDefault { get { int o = __p.__offset(120); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.PositiveInfinity; } } + public bool MutatePositiveInfinityDefault(float positive_infinity_default) { int o = __p.__offset(120); if (o != 0) { __p.bb.Put(o + __p.bb_pos, positive_infinity_default); return true; } else { return false; } } + public float NegativeInfDefault { get { int o = __p.__offset(122); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.NegativeInfinity; } } + public bool MutateNegativeInfDefault(float negative_inf_default) { int o = __p.__offset(122); if (o != 0) { __p.bb.Put(o + __p.bb_pos, negative_inf_default); return true; } else { return false; } } + public float NegativeInfinityDefault { get { int o = __p.__offset(124); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.NegativeInfinity; } } + public bool MutateNegativeInfinityDefault(float negative_infinity_default) { int o = __p.__offset(124); if (o != 0) { __p.bb.Put(o + __p.bb_pos, negative_infinity_default); return true; } else { return false; } } + public double DoubleInfDefault { get { int o = __p.__offset(126); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double)Double.PositiveInfinity; } } + public bool MutateDoubleInfDefault(double double_inf_default) { int o = __p.__offset(126); if (o != 0) { __p.bb.Put(o + __p.bb_pos, double_inf_default); return true; } else { return false; } } + + public static Offset CreateMonster(FlatBufferBuilder builder, + MyGame.Example.Vec3T pos = null, + short mana = 150, + short hp = 100, + StringOffset nameOffset = default(StringOffset), + VectorOffset inventoryOffset = default(VectorOffset), + MyGame.Example.Color color = MyGame.Example.Color.Blue, + MyGame.Example.Any test_type = MyGame.Example.Any.NONE, + int testOffset = 0, + VectorOffset test4Offset = default(VectorOffset), + VectorOffset testarrayofstringOffset = default(VectorOffset), + VectorOffset testarrayoftablesOffset = default(VectorOffset), + Offset enemyOffset = default(Offset), + VectorOffset testnestedflatbufferOffset = default(VectorOffset), + Offset testemptyOffset = default(Offset), + bool testbool = false, + int testhashs32_fnv1 = 0, + uint testhashu32_fnv1 = 0, + long testhashs64_fnv1 = 0, + ulong testhashu64_fnv1 = 0, + int testhashs32_fnv1a = 0, + uint testhashu32_fnv1a = 0, + long testhashs64_fnv1a = 0, + ulong testhashu64_fnv1a = 0, + VectorOffset testarrayofboolsOffset = default(VectorOffset), + float testf = 3.14159f, + float testf2 = 3.0f, + float testf3 = 0.0f, + VectorOffset testarrayofstring2Offset = default(VectorOffset), + VectorOffset testarrayofsortedstructOffset = default(VectorOffset), + VectorOffset flexOffset = default(VectorOffset), + VectorOffset test5Offset = default(VectorOffset), + VectorOffset vector_of_longsOffset = default(VectorOffset), + VectorOffset vector_of_doublesOffset = default(VectorOffset), + Offset parent_namespace_testOffset = default(Offset), + VectorOffset vector_of_referrablesOffset = default(VectorOffset), + ulong single_weak_reference = 0, + VectorOffset vector_of_weak_referencesOffset = default(VectorOffset), + VectorOffset vector_of_strong_referrablesOffset = default(VectorOffset), + ulong co_owning_reference = 0, + VectorOffset vector_of_co_owning_referencesOffset = default(VectorOffset), + ulong non_owning_reference = 0, + VectorOffset vector_of_non_owning_referencesOffset = default(VectorOffset), + MyGame.Example.AnyUniqueAliases any_unique_type = MyGame.Example.AnyUniqueAliases.NONE, + int any_uniqueOffset = 0, + MyGame.Example.AnyAmbiguousAliases any_ambiguous_type = MyGame.Example.AnyAmbiguousAliases.NONE, + int any_ambiguousOffset = 0, + VectorOffset vector_of_enumsOffset = default(VectorOffset), + MyGame.Example.Race signed_enum = MyGame.Example.Race.None, + VectorOffset testrequirednestedflatbufferOffset = default(VectorOffset), + VectorOffset scalar_key_sorted_tablesOffset = default(VectorOffset), + MyGame.Example.TestT native_inline = null, + MyGame.Example.LongEnum long_enum_non_enum_default = 0, + MyGame.Example.LongEnum long_enum_normal_default = MyGame.Example.LongEnum.LongOne, + float nan_default = Single.NaN, + float inf_default = Single.PositiveInfinity, + float positive_inf_default = Single.PositiveInfinity, + float infinity_default = Single.PositiveInfinity, + float positive_infinity_default = Single.PositiveInfinity, + float negative_inf_default = Single.NegativeInfinity, + float negative_infinity_default = Single.NegativeInfinity, + double double_inf_default = Double.PositiveInfinity) { + builder.StartTable(62); + Monster.AddDoubleInfDefault(builder, double_inf_default); + Monster.AddLongEnumNormalDefault(builder, long_enum_normal_default); + Monster.AddLongEnumNonEnumDefault(builder, long_enum_non_enum_default); + Monster.AddNonOwningReference(builder, non_owning_reference); + Monster.AddCoOwningReference(builder, co_owning_reference); + Monster.AddSingleWeakReference(builder, single_weak_reference); + Monster.AddTesthashu64Fnv1a(builder, testhashu64_fnv1a); + Monster.AddTesthashs64Fnv1a(builder, testhashs64_fnv1a); + Monster.AddTesthashu64Fnv1(builder, testhashu64_fnv1); + Monster.AddTesthashs64Fnv1(builder, testhashs64_fnv1); + Monster.AddNegativeInfinityDefault(builder, negative_infinity_default); + Monster.AddNegativeInfDefault(builder, negative_inf_default); + Monster.AddPositiveInfinityDefault(builder, positive_infinity_default); + Monster.AddInfinityDefault(builder, infinity_default); + Monster.AddPositiveInfDefault(builder, positive_inf_default); + Monster.AddInfDefault(builder, inf_default); + Monster.AddNanDefault(builder, nan_default); + Monster.AddNativeInline(builder, MyGame.Example.Test.Pack(builder, native_inline)); + Monster.AddScalarKeySortedTables(builder, scalar_key_sorted_tablesOffset); + Monster.AddTestrequirednestedflatbuffer(builder, testrequirednestedflatbufferOffset); + Monster.AddVectorOfEnums(builder, vector_of_enumsOffset); + Monster.AddAnyAmbiguous(builder, any_ambiguousOffset); + Monster.AddAnyUnique(builder, any_uniqueOffset); + Monster.AddVectorOfNonOwningReferences(builder, vector_of_non_owning_referencesOffset); + Monster.AddVectorOfCoOwningReferences(builder, vector_of_co_owning_referencesOffset); + Monster.AddVectorOfStrongReferrables(builder, vector_of_strong_referrablesOffset); + Monster.AddVectorOfWeakReferences(builder, vector_of_weak_referencesOffset); + Monster.AddVectorOfReferrables(builder, vector_of_referrablesOffset); + Monster.AddParentNamespaceTest(builder, parent_namespace_testOffset); + Monster.AddVectorOfDoubles(builder, vector_of_doublesOffset); + Monster.AddVectorOfLongs(builder, vector_of_longsOffset); + Monster.AddTest5(builder, test5Offset); + Monster.AddFlex(builder, flexOffset); + Monster.AddTestarrayofsortedstruct(builder, testarrayofsortedstructOffset); + Monster.AddTestarrayofstring2(builder, testarrayofstring2Offset); + Monster.AddTestf3(builder, testf3); + Monster.AddTestf2(builder, testf2); + Monster.AddTestf(builder, testf); + Monster.AddTestarrayofbools(builder, testarrayofboolsOffset); + Monster.AddTesthashu32Fnv1a(builder, testhashu32_fnv1a); + Monster.AddTesthashs32Fnv1a(builder, testhashs32_fnv1a); + Monster.AddTesthashu32Fnv1(builder, testhashu32_fnv1); + Monster.AddTesthashs32Fnv1(builder, testhashs32_fnv1); + Monster.AddTestempty(builder, testemptyOffset); + Monster.AddTestnestedflatbuffer(builder, testnestedflatbufferOffset); + Monster.AddEnemy(builder, enemyOffset); + Monster.AddTestarrayoftables(builder, testarrayoftablesOffset); + Monster.AddTestarrayofstring(builder, testarrayofstringOffset); + Monster.AddTest4(builder, test4Offset); + Monster.AddTest(builder, testOffset); + Monster.AddInventory(builder, inventoryOffset); + Monster.AddName(builder, nameOffset); + Monster.AddPos(builder, MyGame.Example.Vec3.Pack(builder, pos)); + Monster.AddHp(builder, hp); + Monster.AddMana(builder, mana); + Monster.AddSignedEnum(builder, signed_enum); + Monster.AddAnyAmbiguousType(builder, any_ambiguous_type); + Monster.AddAnyUniqueType(builder, any_unique_type); + Monster.AddTestbool(builder, testbool); + Monster.AddTestType(builder, test_type); + Monster.AddColor(builder, color); + return Monster.EndMonster(builder); + } + + public static void StartMonster(FlatBufferBuilder builder) { builder.StartTable(62); } + public static void AddPos(FlatBufferBuilder builder, Offset posOffset) { builder.AddStruct(0, posOffset, 0); } + public static void AddMana(FlatBufferBuilder builder, short mana) { builder.Add(1, mana, 150); } + public static void AddHp(FlatBufferBuilder builder, short hp) { builder.Add(2, hp, 100); } + public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(3, nameOffset, 0); } + public static void AddInventory(FlatBufferBuilder builder, VectorOffset inventoryOffset) { builder.AddOffset(5, inventoryOffset, 0); } + public static VectorOffset CreateInventoryVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateInventoryVector(FlatBufferBuilder builder, Span data) { return CreateInventoryVectorBlock(builder, data); } + public static void StartInventoryVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddColor(FlatBufferBuilder builder, MyGame.Example.Color color) { builder.Add(6, (byte)color, 8); } + public static void AddTestType(FlatBufferBuilder builder, MyGame.Example.Any testType) { builder.Add(7, (byte)testType, 0); } + public static void AddTest(FlatBufferBuilder builder, int testOffset) { builder.AddOffset(8, testOffset, 0); } + public static void AddTest4(FlatBufferBuilder builder, VectorOffset test4Offset) { builder.AddOffset(9, test4Offset, 0); } + public static void StartTest4Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 2); } + public static void AddTestarrayofstring(FlatBufferBuilder builder, VectorOffset testarrayofstringOffset) { builder.AddOffset(10, testarrayofstringOffset, 0); } + public static VectorOffset CreateTestarrayofstringVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTestarrayofstringVector(FlatBufferBuilder builder, Span data) { return CreateTestarrayofstringVectorBlock(builder, data); } + public static void StartTestarrayofstringVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddTestarrayoftables(FlatBufferBuilder builder, VectorOffset testarrayoftablesOffset) { builder.AddOffset(11, testarrayoftablesOffset, 0); } + public static VectorOffset CreateTestarrayoftablesVectorBlock(FlatBufferBuilder builder, Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateTestarrayoftablesVector(FlatBufferBuilder builder, Span> data) { return CreateTestarrayoftablesVectorBlock(builder, data); } + public static void StartTestarrayoftablesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddEnemy(FlatBufferBuilder builder, Offset enemyOffset) { builder.AddOffset(12, enemyOffset, 0); } + public static void AddTestnestedflatbuffer(FlatBufferBuilder builder, VectorOffset testnestedflatbufferOffset) { builder.AddOffset(13, testnestedflatbufferOffset, 0); } + public static VectorOffset CreateTestnestedflatbufferVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTestnestedflatbufferVector(FlatBufferBuilder builder, Span data) { return CreateTestnestedflatbufferVectorBlock(builder, data); } + public static void StartTestnestedflatbufferVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddTestempty(FlatBufferBuilder builder, Offset testemptyOffset) { builder.AddOffset(14, testemptyOffset, 0); } + public static void AddTestbool(FlatBufferBuilder builder, bool testbool) { builder.Add(15, testbool, false); } + public static void AddTesthashs32Fnv1(FlatBufferBuilder builder, int testhashs32Fnv1) { builder.Add(16, testhashs32Fnv1, 0); } + public static void AddTesthashu32Fnv1(FlatBufferBuilder builder, uint testhashu32Fnv1) { builder.Add(17, testhashu32Fnv1, 0); } + public static void AddTesthashs64Fnv1(FlatBufferBuilder builder, long testhashs64Fnv1) { builder.Add(18, testhashs64Fnv1, 0); } + public static void AddTesthashu64Fnv1(FlatBufferBuilder builder, ulong testhashu64Fnv1) { builder.Add(19, testhashu64Fnv1, 0); } + public static void AddTesthashs32Fnv1a(FlatBufferBuilder builder, int testhashs32Fnv1a) { builder.Add(20, testhashs32Fnv1a, 0); } + public static void AddTesthashu32Fnv1a(FlatBufferBuilder builder, uint testhashu32Fnv1a) { builder.Add(21, testhashu32Fnv1a, 0); } + public static void AddTesthashs64Fnv1a(FlatBufferBuilder builder, long testhashs64Fnv1a) { builder.Add(22, testhashs64Fnv1a, 0); } + public static void AddTesthashu64Fnv1a(FlatBufferBuilder builder, ulong testhashu64Fnv1a) { builder.Add(23, testhashu64Fnv1a, 0); } + public static void AddTestarrayofbools(FlatBufferBuilder builder, VectorOffset testarrayofboolsOffset) { builder.AddOffset(24, testarrayofboolsOffset, 0); } + public static VectorOffset CreateTestarrayofboolsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTestarrayofboolsVector(FlatBufferBuilder builder, Span data) { return CreateTestarrayofboolsVectorBlock(builder, data); } + public static void StartTestarrayofboolsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddTestf(FlatBufferBuilder builder, float testf) { builder.Add(25, testf, 3.14159f); } + public static void AddTestf2(FlatBufferBuilder builder, float testf2) { builder.Add(26, testf2, 3.0f); } + public static void AddTestf3(FlatBufferBuilder builder, float testf3) { builder.Add(27, testf3, 0.0f); } + public static void AddTestarrayofstring2(FlatBufferBuilder builder, VectorOffset testarrayofstring2Offset) { builder.AddOffset(28, testarrayofstring2Offset, 0); } + public static VectorOffset CreateTestarrayofstring2VectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTestarrayofstring2Vector(FlatBufferBuilder builder, Span data) { return CreateTestarrayofstring2VectorBlock(builder, data); } + public static void StartTestarrayofstring2Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddTestarrayofsortedstruct(FlatBufferBuilder builder, VectorOffset testarrayofsortedstructOffset) { builder.AddOffset(29, testarrayofsortedstructOffset, 0); } + public static void StartTestarrayofsortedstructVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 4); } + public static void AddFlex(FlatBufferBuilder builder, VectorOffset flexOffset) { builder.AddOffset(30, flexOffset, 0); } + public static VectorOffset CreateFlexVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateFlexVector(FlatBufferBuilder builder, Span data) { return CreateFlexVectorBlock(builder, data); } + public static void StartFlexVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddTest5(FlatBufferBuilder builder, VectorOffset test5Offset) { builder.AddOffset(31, test5Offset, 0); } + public static void StartTest5Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 2); } + public static void AddVectorOfLongs(FlatBufferBuilder builder, VectorOffset vectorOfLongsOffset) { builder.AddOffset(32, vectorOfLongsOffset, 0); } + public static VectorOffset CreateVectorOfLongsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfLongsVector(FlatBufferBuilder builder, Span data) { return CreateVectorOfLongsVectorBlock(builder, data); } + public static void StartVectorOfLongsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddVectorOfDoubles(FlatBufferBuilder builder, VectorOffset vectorOfDoublesOffset) { builder.AddOffset(33, vectorOfDoublesOffset, 0); } + public static VectorOffset CreateVectorOfDoublesVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfDoublesVector(FlatBufferBuilder builder, Span data) { return CreateVectorOfDoublesVectorBlock(builder, data); } + public static void StartVectorOfDoublesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddParentNamespaceTest(FlatBufferBuilder builder, Offset parentNamespaceTestOffset) { builder.AddOffset(34, parentNamespaceTestOffset, 0); } + public static void AddVectorOfReferrables(FlatBufferBuilder builder, VectorOffset vectorOfReferrablesOffset) { builder.AddOffset(35, vectorOfReferrablesOffset, 0); } + public static VectorOffset CreateVectorOfReferrablesVectorBlock(FlatBufferBuilder builder, Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfReferrablesVector(FlatBufferBuilder builder, Span> data) { return CreateVectorOfReferrablesVectorBlock(builder, data); } + public static void StartVectorOfReferrablesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddSingleWeakReference(FlatBufferBuilder builder, ulong singleWeakReference) { builder.Add(36, singleWeakReference, 0); } + public static void AddVectorOfWeakReferences(FlatBufferBuilder builder, VectorOffset vectorOfWeakReferencesOffset) { builder.AddOffset(37, vectorOfWeakReferencesOffset, 0); } + public static VectorOffset CreateVectorOfWeakReferencesVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfWeakReferencesVector(FlatBufferBuilder builder, Span data) { return CreateVectorOfWeakReferencesVectorBlock(builder, data); } + public static void StartVectorOfWeakReferencesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddVectorOfStrongReferrables(FlatBufferBuilder builder, VectorOffset vectorOfStrongReferrablesOffset) { builder.AddOffset(38, vectorOfStrongReferrablesOffset, 0); } + public static VectorOffset CreateVectorOfStrongReferrablesVectorBlock(FlatBufferBuilder builder, Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfStrongReferrablesVector(FlatBufferBuilder builder, Span> data) { return CreateVectorOfStrongReferrablesVectorBlock(builder, data); } + public static void StartVectorOfStrongReferrablesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddCoOwningReference(FlatBufferBuilder builder, ulong coOwningReference) { builder.Add(39, coOwningReference, 0); } + public static void AddVectorOfCoOwningReferences(FlatBufferBuilder builder, VectorOffset vectorOfCoOwningReferencesOffset) { builder.AddOffset(40, vectorOfCoOwningReferencesOffset, 0); } + public static VectorOffset CreateVectorOfCoOwningReferencesVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfCoOwningReferencesVector(FlatBufferBuilder builder, Span data) { return CreateVectorOfCoOwningReferencesVectorBlock(builder, data); } + public static void StartVectorOfCoOwningReferencesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddNonOwningReference(FlatBufferBuilder builder, ulong nonOwningReference) { builder.Add(41, nonOwningReference, 0); } + public static void AddVectorOfNonOwningReferences(FlatBufferBuilder builder, VectorOffset vectorOfNonOwningReferencesOffset) { builder.AddOffset(42, vectorOfNonOwningReferencesOffset, 0); } + public static VectorOffset CreateVectorOfNonOwningReferencesVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfNonOwningReferencesVector(FlatBufferBuilder builder, Span data) { return CreateVectorOfNonOwningReferencesVectorBlock(builder, data); } + public static void StartVectorOfNonOwningReferencesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddAnyUniqueType(FlatBufferBuilder builder, MyGame.Example.AnyUniqueAliases anyUniqueType) { builder.Add(43, (byte)anyUniqueType, 0); } + public static void AddAnyUnique(FlatBufferBuilder builder, int anyUniqueOffset) { builder.AddOffset(44, anyUniqueOffset, 0); } + public static void AddAnyAmbiguousType(FlatBufferBuilder builder, MyGame.Example.AnyAmbiguousAliases anyAmbiguousType) { builder.Add(45, (byte)anyAmbiguousType, 0); } + public static void AddAnyAmbiguous(FlatBufferBuilder builder, int anyAmbiguousOffset) { builder.AddOffset(46, anyAmbiguousOffset, 0); } + public static void AddVectorOfEnums(FlatBufferBuilder builder, VectorOffset vectorOfEnumsOffset) { builder.AddOffset(47, vectorOfEnumsOffset, 0); } + public static VectorOffset CreateVectorOfEnumsVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfEnumsVector(FlatBufferBuilder builder, Span data) { return CreateVectorOfEnumsVectorBlock(builder, data); } + public static void StartVectorOfEnumsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddSignedEnum(FlatBufferBuilder builder, MyGame.Example.Race signedEnum) { builder.Add(48, (sbyte)signedEnum, -1); } + public static void AddTestrequirednestedflatbuffer(FlatBufferBuilder builder, VectorOffset testrequirednestedflatbufferOffset) { builder.AddOffset(49, testrequirednestedflatbufferOffset, 0); } + public static VectorOffset CreateTestrequirednestedflatbufferVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTestrequirednestedflatbufferVector(FlatBufferBuilder builder, Span data) { return CreateTestrequirednestedflatbufferVectorBlock(builder, data); } + public static void StartTestrequirednestedflatbufferVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddScalarKeySortedTables(FlatBufferBuilder builder, VectorOffset scalarKeySortedTablesOffset) { builder.AddOffset(50, scalarKeySortedTablesOffset, 0); } + public static VectorOffset CreateScalarKeySortedTablesVectorBlock(FlatBufferBuilder builder, Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateScalarKeySortedTablesVector(FlatBufferBuilder builder, Span> data) { return CreateScalarKeySortedTablesVectorBlock(builder, data); } + public static void StartScalarKeySortedTablesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddNativeInline(FlatBufferBuilder builder, Offset nativeInlineOffset) { builder.AddStruct(51, nativeInlineOffset, 0); } + public static void AddLongEnumNonEnumDefault(FlatBufferBuilder builder, MyGame.Example.LongEnum longEnumNonEnumDefault) { builder.Add(52, (ulong)longEnumNonEnumDefault, 0); } + public static void AddLongEnumNormalDefault(FlatBufferBuilder builder, MyGame.Example.LongEnum longEnumNormalDefault) { builder.Add(53, (ulong)longEnumNormalDefault, 2); } + public static void AddNanDefault(FlatBufferBuilder builder, float nanDefault) { builder.Add(54, nanDefault, Single.NaN); } + public static void AddInfDefault(FlatBufferBuilder builder, float infDefault) { builder.Add(55, infDefault, Single.PositiveInfinity); } + public static void AddPositiveInfDefault(FlatBufferBuilder builder, float positiveInfDefault) { builder.Add(56, positiveInfDefault, Single.PositiveInfinity); } + public static void AddInfinityDefault(FlatBufferBuilder builder, float infinityDefault) { builder.Add(57, infinityDefault, Single.PositiveInfinity); } + public static void AddPositiveInfinityDefault(FlatBufferBuilder builder, float positiveInfinityDefault) { builder.Add(58, positiveInfinityDefault, Single.PositiveInfinity); } + public static void AddNegativeInfDefault(FlatBufferBuilder builder, float negativeInfDefault) { builder.Add(59, negativeInfDefault, Single.NegativeInfinity); } + public static void AddNegativeInfinityDefault(FlatBufferBuilder builder, float negativeInfinityDefault) { builder.Add(60, negativeInfinityDefault, Single.NegativeInfinity); } + public static void AddDoubleInfDefault(FlatBufferBuilder builder, double doubleInfDefault) { builder.Add(61, doubleInfDefault, Double.PositiveInfinity); } + public static Offset EndMonster(FlatBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 10); // name + return new Offset(o); + } + public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "MONS"); } + public static void FinishSizePrefixedMonsterBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "MONS"); } + + public static VectorOffset CreateSortedVectorOfMonster(FlatBufferBuilder builder, Span> offsets) { + var comparer = new SortedVectorUtils.VectorOffsetComparer(builder.DataBuffer, 10); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, string key, ByteBuffer bb, out Monster value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 10, out value); + } + public MonsterT UnPack() { + var _o = new MonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(MonsterT _o) { + if (this.Pos.HasValue) { + if (_o.Pos == null) _o.Pos = new MyGame.Example.Vec3T(); + this.Pos.Value.UnPackTo(_o.Pos); + } else { + _o.Pos = null; + } + _o.Mana = this.Mana; + _o.Hp = this.Hp; + _o.Name = this.Name; + var _inventory_vec = this.Inventory; + var _inventory_len = _inventory_vec.HasValue ? _inventory_vec.Value.Length : 0; + if (_o.Inventory == null) { + _o.Inventory = new List(_inventory_len); + } + ObjectApiUtil.ResizeList(_o.Inventory, _inventory_len); + if (_inventory_vec.HasValue) { _inventory_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Inventory)); } + _o.Color = this.Color; + if (_o.Test == null) { + _o.Test = new MyGame.Example.AnyUnion(); + } + var _TestOldType = _o.Test.Type; + _o.Test.Type = this.TestType; + switch (this.TestType) { + default: + _o.Test.Value = null; + break; + case MyGame.Example.Any.Monster: + if (this.Test().HasValue) { + if (_TestOldType == MyGame.Example.Any.Monster) { + this.Test().Value.UnPackTo((MyGame.Example.MonsterT)_o.Test.Value); + } else { + _o.Test.Value = this.Test().Value.UnPack(); + } + } else { + _o.Test.Value = null; + } + break; + case MyGame.Example.Any.TestSimpleTableWithEnum: + if (this.Test().HasValue) { + if (_TestOldType == MyGame.Example.Any.TestSimpleTableWithEnum) { + this.Test().Value.UnPackTo((MyGame.Example.TestSimpleTableWithEnumT)_o.Test.Value); + } else { + _o.Test.Value = this.Test().Value.UnPack(); + } + } else { + _o.Test.Value = null; + } + break; + case MyGame.Example.Any.MyGame_Example2_Monster: + if (this.Test().HasValue) { + if (_TestOldType == MyGame.Example.Any.MyGame_Example2_Monster) { + this.Test().Value.UnPackTo((MyGame.Example2.MonsterT)_o.Test.Value); + } else { + _o.Test.Value = this.Test().Value.UnPack(); + } + } else { + _o.Test.Value = null; + } + break; + } + var _test4_vec = this.Test4; + var _test4_len = _test4_vec.HasValue ? _test4_vec.Value.Length : 0; + if (_o.Test4 == null) { + _o.Test4 = new List(_test4_len); + } + ObjectApiUtil.ResizeList(_o.Test4, _test4_len); + if (_test4_vec.HasValue) { + var _test4_value = _test4_vec.Value; + for (var _j = 0; _j < _test4_len; ++_j) { + var _src = _test4_value[_j]; + if (_o.Test4[_j] == null) { _o.Test4[_j] = new TestT(); } + _src.UnPackTo(_o.Test4[_j]); + } + } + var _testarrayofstring_vec = this.Testarrayofstring; + var _testarrayofstring_len = _testarrayofstring_vec.HasValue ? _testarrayofstring_vec.Value.Length : 0; + if (_o.Testarrayofstring == null) { + _o.Testarrayofstring = new List(_testarrayofstring_len); + } else { + _o.Testarrayofstring.Clear(); + if (_o.Testarrayofstring.Capacity < _testarrayofstring_len) { + _o.Testarrayofstring.Capacity = _testarrayofstring_len; + } + } + if (_testarrayofstring_vec.HasValue) { + var _testarrayofstring_value = _testarrayofstring_vec.Value; + for (var _j = 0; _j < _testarrayofstring_len; ++_j) { _o.Testarrayofstring.Add(_testarrayofstring_value[_j]); } + } + var _testarrayoftables_vec = this.Testarrayoftables; + var _testarrayoftables_len = _testarrayoftables_vec.HasValue ? _testarrayoftables_vec.Value.Length : 0; + if (_o.Testarrayoftables == null) { + _o.Testarrayoftables = new List(_testarrayoftables_len); + } + ObjectApiUtil.ResizeList(_o.Testarrayoftables, _testarrayoftables_len); + if (_testarrayoftables_vec.HasValue) { + var _testarrayoftables_value = _testarrayoftables_vec.Value; + for (var _j = 0; _j < _testarrayoftables_len; ++_j) { + var _src = _testarrayoftables_value[_j]; + if (_o.Testarrayoftables[_j] == null) { _o.Testarrayoftables[_j] = new MonsterT(); } + _src.UnPackTo(_o.Testarrayoftables[_j]); + } + } + if (this.Enemy.HasValue) { + if (_o.Enemy == null) _o.Enemy = new MyGame.Example.MonsterT(); + this.Enemy.Value.UnPackTo(_o.Enemy); + } else { + _o.Enemy = null; + } + var _testnestedflatbuffer_vec = this.Testnestedflatbuffer; + var _testnestedflatbuffer_len = _testnestedflatbuffer_vec.HasValue ? _testnestedflatbuffer_vec.Value.Length : 0; + if (_o.Testnestedflatbuffer == null) { + _o.Testnestedflatbuffer = new List(_testnestedflatbuffer_len); + } + ObjectApiUtil.ResizeList(_o.Testnestedflatbuffer, _testnestedflatbuffer_len); + if (_testnestedflatbuffer_vec.HasValue) { _testnestedflatbuffer_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Testnestedflatbuffer)); } + if (this.Testempty.HasValue) { + if (_o.Testempty == null) _o.Testempty = new MyGame.Example.StatT(); + this.Testempty.Value.UnPackTo(_o.Testempty); + } else { + _o.Testempty = null; + } + _o.Testbool = this.Testbool; + _o.Testhashs32Fnv1 = this.Testhashs32Fnv1; + _o.Testhashu32Fnv1 = this.Testhashu32Fnv1; + _o.Testhashs64Fnv1 = this.Testhashs64Fnv1; + _o.Testhashu64Fnv1 = this.Testhashu64Fnv1; + _o.Testhashs32Fnv1a = this.Testhashs32Fnv1a; + _o.Testhashu32Fnv1a = this.Testhashu32Fnv1a; + _o.Testhashs64Fnv1a = this.Testhashs64Fnv1a; + _o.Testhashu64Fnv1a = this.Testhashu64Fnv1a; + var _testarrayofbools_vec = this.Testarrayofbools; + var _testarrayofbools_len = _testarrayofbools_vec.HasValue ? _testarrayofbools_vec.Value.Length : 0; + if (_o.Testarrayofbools == null) { + _o.Testarrayofbools = new List(_testarrayofbools_len); + } else { + _o.Testarrayofbools.Clear(); + if (_o.Testarrayofbools.Capacity < _testarrayofbools_len) { + _o.Testarrayofbools.Capacity = _testarrayofbools_len; + } + } + if (_testarrayofbools_vec.HasValue) { + for (var _j = 0; _j < _testarrayofbools_len; ++_j) { _o.Testarrayofbools.Add(_testarrayofbools_vec.Value[_j]); } + } + _o.Testf = this.Testf; + _o.Testf2 = this.Testf2; + _o.Testf3 = this.Testf3; + var _testarrayofstring2_vec = this.Testarrayofstring2; + var _testarrayofstring2_len = _testarrayofstring2_vec.HasValue ? _testarrayofstring2_vec.Value.Length : 0; + if (_o.Testarrayofstring2 == null) { + _o.Testarrayofstring2 = new List(_testarrayofstring2_len); + } else { + _o.Testarrayofstring2.Clear(); + if (_o.Testarrayofstring2.Capacity < _testarrayofstring2_len) { + _o.Testarrayofstring2.Capacity = _testarrayofstring2_len; + } + } + if (_testarrayofstring2_vec.HasValue) { + var _testarrayofstring2_value = _testarrayofstring2_vec.Value; + for (var _j = 0; _j < _testarrayofstring2_len; ++_j) { _o.Testarrayofstring2.Add(_testarrayofstring2_value[_j]); } + } + var _testarrayofsortedstruct_vec = this.Testarrayofsortedstruct; + var _testarrayofsortedstruct_len = _testarrayofsortedstruct_vec.HasValue ? _testarrayofsortedstruct_vec.Value.Length : 0; + if (_o.Testarrayofsortedstruct == null) { + _o.Testarrayofsortedstruct = new List(_testarrayofsortedstruct_len); + } + ObjectApiUtil.ResizeList(_o.Testarrayofsortedstruct, _testarrayofsortedstruct_len); + if (_testarrayofsortedstruct_vec.HasValue) { + var _testarrayofsortedstruct_value = _testarrayofsortedstruct_vec.Value; + for (var _j = 0; _j < _testarrayofsortedstruct_len; ++_j) { + var _src = _testarrayofsortedstruct_value[_j]; + if (_o.Testarrayofsortedstruct[_j] == null) { _o.Testarrayofsortedstruct[_j] = new AbilityT(); } + _src.UnPackTo(_o.Testarrayofsortedstruct[_j]); + } + } + var _flex_vec = this.Flex; + var _flex_len = _flex_vec.HasValue ? _flex_vec.Value.Length : 0; + if (_o.Flex == null) { + _o.Flex = new List(_flex_len); + } + ObjectApiUtil.ResizeList(_o.Flex, _flex_len); + if (_flex_vec.HasValue) { _flex_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Flex)); } + var _test5_vec = this.Test5; + var _test5_len = _test5_vec.HasValue ? _test5_vec.Value.Length : 0; + if (_o.Test5 == null) { + _o.Test5 = new List(_test5_len); + } + ObjectApiUtil.ResizeList(_o.Test5, _test5_len); + if (_test5_vec.HasValue) { + var _test5_value = _test5_vec.Value; + for (var _j = 0; _j < _test5_len; ++_j) { + var _src = _test5_value[_j]; + if (_o.Test5[_j] == null) { _o.Test5[_j] = new TestT(); } + _src.UnPackTo(_o.Test5[_j]); + } + } + var _vector_of_longs_vec = this.VectorOfLongs; + var _vector_of_longs_len = _vector_of_longs_vec.HasValue ? _vector_of_longs_vec.Value.Length : 0; + if (_o.VectorOfLongs == null) { + _o.VectorOfLongs = new List(_vector_of_longs_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfLongs, _vector_of_longs_len); + if (_vector_of_longs_vec.HasValue) { _vector_of_longs_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfLongs)); } + var _vector_of_doubles_vec = this.VectorOfDoubles; + var _vector_of_doubles_len = _vector_of_doubles_vec.HasValue ? _vector_of_doubles_vec.Value.Length : 0; + if (_o.VectorOfDoubles == null) { + _o.VectorOfDoubles = new List(_vector_of_doubles_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfDoubles, _vector_of_doubles_len); + if (_vector_of_doubles_vec.HasValue) { _vector_of_doubles_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfDoubles)); } + if (this.ParentNamespaceTest.HasValue) { + if (_o.ParentNamespaceTest == null) _o.ParentNamespaceTest = new MyGame.InParentNamespaceT(); + this.ParentNamespaceTest.Value.UnPackTo(_o.ParentNamespaceTest); + } else { + _o.ParentNamespaceTest = null; + } + var _vector_of_referrables_vec = this.VectorOfReferrables; + var _vector_of_referrables_len = _vector_of_referrables_vec.HasValue ? _vector_of_referrables_vec.Value.Length : 0; + if (_o.VectorOfReferrables == null) { + _o.VectorOfReferrables = new List(_vector_of_referrables_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfReferrables, _vector_of_referrables_len); + if (_vector_of_referrables_vec.HasValue) { + var _vector_of_referrables_value = _vector_of_referrables_vec.Value; + for (var _j = 0; _j < _vector_of_referrables_len; ++_j) { + var _src = _vector_of_referrables_value[_j]; + if (_o.VectorOfReferrables[_j] == null) { _o.VectorOfReferrables[_j] = new ReferrableT(); } + _src.UnPackTo(_o.VectorOfReferrables[_j]); + } + } + _o.SingleWeakReference = this.SingleWeakReference; + var _vector_of_weak_references_vec = this.VectorOfWeakReferences; + var _vector_of_weak_references_len = _vector_of_weak_references_vec.HasValue ? _vector_of_weak_references_vec.Value.Length : 0; + if (_o.VectorOfWeakReferences == null) { + _o.VectorOfWeakReferences = new List(_vector_of_weak_references_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfWeakReferences, _vector_of_weak_references_len); + if (_vector_of_weak_references_vec.HasValue) { _vector_of_weak_references_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfWeakReferences)); } + var _vector_of_strong_referrables_vec = this.VectorOfStrongReferrables; + var _vector_of_strong_referrables_len = _vector_of_strong_referrables_vec.HasValue ? _vector_of_strong_referrables_vec.Value.Length : 0; + if (_o.VectorOfStrongReferrables == null) { + _o.VectorOfStrongReferrables = new List(_vector_of_strong_referrables_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfStrongReferrables, _vector_of_strong_referrables_len); + if (_vector_of_strong_referrables_vec.HasValue) { + var _vector_of_strong_referrables_value = _vector_of_strong_referrables_vec.Value; + for (var _j = 0; _j < _vector_of_strong_referrables_len; ++_j) { + var _src = _vector_of_strong_referrables_value[_j]; + if (_o.VectorOfStrongReferrables[_j] == null) { _o.VectorOfStrongReferrables[_j] = new ReferrableT(); } + _src.UnPackTo(_o.VectorOfStrongReferrables[_j]); + } + } + _o.CoOwningReference = this.CoOwningReference; + var _vector_of_co_owning_references_vec = this.VectorOfCoOwningReferences; + var _vector_of_co_owning_references_len = _vector_of_co_owning_references_vec.HasValue ? _vector_of_co_owning_references_vec.Value.Length : 0; + if (_o.VectorOfCoOwningReferences == null) { + _o.VectorOfCoOwningReferences = new List(_vector_of_co_owning_references_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfCoOwningReferences, _vector_of_co_owning_references_len); + if (_vector_of_co_owning_references_vec.HasValue) { _vector_of_co_owning_references_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfCoOwningReferences)); } + _o.NonOwningReference = this.NonOwningReference; + var _vector_of_non_owning_references_vec = this.VectorOfNonOwningReferences; + var _vector_of_non_owning_references_len = _vector_of_non_owning_references_vec.HasValue ? _vector_of_non_owning_references_vec.Value.Length : 0; + if (_o.VectorOfNonOwningReferences == null) { + _o.VectorOfNonOwningReferences = new List(_vector_of_non_owning_references_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfNonOwningReferences, _vector_of_non_owning_references_len); + if (_vector_of_non_owning_references_vec.HasValue) { _vector_of_non_owning_references_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfNonOwningReferences)); } + if (_o.AnyUnique == null) { + _o.AnyUnique = new MyGame.Example.AnyUniqueAliasesUnion(); + } + var _AnyUniqueOldType = _o.AnyUnique.Type; + _o.AnyUnique.Type = this.AnyUniqueType; + switch (this.AnyUniqueType) { + default: + _o.AnyUnique.Value = null; + break; + case MyGame.Example.AnyUniqueAliases.M: + if (this.AnyUnique().HasValue) { + if (_AnyUniqueOldType == MyGame.Example.AnyUniqueAliases.M) { + this.AnyUnique().Value.UnPackTo((MyGame.Example.MonsterT)_o.AnyUnique.Value); + } else { + _o.AnyUnique.Value = this.AnyUnique().Value.UnPack(); + } + } else { + _o.AnyUnique.Value = null; + } + break; + case MyGame.Example.AnyUniqueAliases.TS: + if (this.AnyUnique().HasValue) { + if (_AnyUniqueOldType == MyGame.Example.AnyUniqueAliases.TS) { + this.AnyUnique().Value.UnPackTo((MyGame.Example.TestSimpleTableWithEnumT)_o.AnyUnique.Value); + } else { + _o.AnyUnique.Value = this.AnyUnique().Value.UnPack(); + } + } else { + _o.AnyUnique.Value = null; + } + break; + case MyGame.Example.AnyUniqueAliases.M2: + if (this.AnyUnique().HasValue) { + if (_AnyUniqueOldType == MyGame.Example.AnyUniqueAliases.M2) { + this.AnyUnique().Value.UnPackTo((MyGame.Example2.MonsterT)_o.AnyUnique.Value); + } else { + _o.AnyUnique.Value = this.AnyUnique().Value.UnPack(); + } + } else { + _o.AnyUnique.Value = null; + } + break; + } + if (_o.AnyAmbiguous == null) { + _o.AnyAmbiguous = new MyGame.Example.AnyAmbiguousAliasesUnion(); + } + var _AnyAmbiguousOldType = _o.AnyAmbiguous.Type; + _o.AnyAmbiguous.Type = this.AnyAmbiguousType; + switch (this.AnyAmbiguousType) { + default: + _o.AnyAmbiguous.Value = null; + break; + case MyGame.Example.AnyAmbiguousAliases.M1: + if (this.AnyAmbiguous().HasValue) { + if (_AnyAmbiguousOldType == MyGame.Example.AnyAmbiguousAliases.M1) { + this.AnyAmbiguous().Value.UnPackTo((MyGame.Example.MonsterT)_o.AnyAmbiguous.Value); + } else { + _o.AnyAmbiguous.Value = this.AnyAmbiguous().Value.UnPack(); + } + } else { + _o.AnyAmbiguous.Value = null; + } + break; + case MyGame.Example.AnyAmbiguousAliases.M2: + if (this.AnyAmbiguous().HasValue) { + if (_AnyAmbiguousOldType == MyGame.Example.AnyAmbiguousAliases.M2) { + this.AnyAmbiguous().Value.UnPackTo((MyGame.Example.MonsterT)_o.AnyAmbiguous.Value); + } else { + _o.AnyAmbiguous.Value = this.AnyAmbiguous().Value.UnPack(); + } + } else { + _o.AnyAmbiguous.Value = null; + } + break; + case MyGame.Example.AnyAmbiguousAliases.M3: + if (this.AnyAmbiguous().HasValue) { + if (_AnyAmbiguousOldType == MyGame.Example.AnyAmbiguousAliases.M3) { + this.AnyAmbiguous().Value.UnPackTo((MyGame.Example.MonsterT)_o.AnyAmbiguous.Value); + } else { + _o.AnyAmbiguous.Value = this.AnyAmbiguous().Value.UnPack(); + } + } else { + _o.AnyAmbiguous.Value = null; + } + break; + } + var _vector_of_enums_vec = this.VectorOfEnums; + var _vector_of_enums_len = _vector_of_enums_vec.HasValue ? _vector_of_enums_vec.Value.Length : 0; + if (_o.VectorOfEnums == null) { + _o.VectorOfEnums = new List(_vector_of_enums_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfEnums, _vector_of_enums_len); + if (_vector_of_enums_vec.HasValue) { _vector_of_enums_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfEnums)); } + _o.SignedEnum = this.SignedEnum; + var _testrequirednestedflatbuffer_vec = this.Testrequirednestedflatbuffer; + var _testrequirednestedflatbuffer_len = _testrequirednestedflatbuffer_vec.HasValue ? _testrequirednestedflatbuffer_vec.Value.Length : 0; + if (_o.Testrequirednestedflatbuffer == null) { + _o.Testrequirednestedflatbuffer = new List(_testrequirednestedflatbuffer_len); + } + ObjectApiUtil.ResizeList(_o.Testrequirednestedflatbuffer, _testrequirednestedflatbuffer_len); + if (_testrequirednestedflatbuffer_vec.HasValue) { _testrequirednestedflatbuffer_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Testrequirednestedflatbuffer)); } + var _scalar_key_sorted_tables_vec = this.ScalarKeySortedTables; + var _scalar_key_sorted_tables_len = _scalar_key_sorted_tables_vec.HasValue ? _scalar_key_sorted_tables_vec.Value.Length : 0; + if (_o.ScalarKeySortedTables == null) { + _o.ScalarKeySortedTables = new List(_scalar_key_sorted_tables_len); + } + ObjectApiUtil.ResizeList(_o.ScalarKeySortedTables, _scalar_key_sorted_tables_len); + if (_scalar_key_sorted_tables_vec.HasValue) { + var _scalar_key_sorted_tables_value = _scalar_key_sorted_tables_vec.Value; + for (var _j = 0; _j < _scalar_key_sorted_tables_len; ++_j) { + var _src = _scalar_key_sorted_tables_value[_j]; + if (_o.ScalarKeySortedTables[_j] == null) { _o.ScalarKeySortedTables[_j] = new StatT(); } + _src.UnPackTo(_o.ScalarKeySortedTables[_j]); + } + } + if (this.NativeInline.HasValue) { + if (_o.NativeInline == null) _o.NativeInline = new MyGame.Example.TestT(); + this.NativeInline.Value.UnPackTo(_o.NativeInline); + } else { + _o.NativeInline = null; + } + _o.LongEnumNonEnumDefault = this.LongEnumNonEnumDefault; + _o.LongEnumNormalDefault = this.LongEnumNormalDefault; + _o.NanDefault = this.NanDefault; + _o.InfDefault = this.InfDefault; + _o.PositiveInfDefault = this.PositiveInfDefault; + _o.InfinityDefault = this.InfinityDefault; + _o.PositiveInfinityDefault = this.PositiveInfinityDefault; + _o.NegativeInfDefault = this.NegativeInfDefault; + _o.NegativeInfinityDefault = this.NegativeInfinityDefault; + _o.DoubleInfDefault = this.DoubleInfDefault; + } + public static Offset Pack(FlatBufferBuilder builder, MonsterT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + var _inventory = default(VectorOffset); + if (_o.Inventory != null) { + _inventory = CreateInventoryVector(builder, CollectionsMarshal.AsSpan(_o.Inventory)); + } + var _test_type = _o.Test == null ? MyGame.Example.Any.NONE : _o.Test.Type; + var _test = _o.Test == null ? 0 : MyGame.Example.AnyUnion.Pack(builder, _o.Test); + var _test4 = default(VectorOffset); + if (_o.Test4 != null) { + StartTest4Vector(builder, _o.Test4.Count); + for (var _j = _o.Test4.Count - 1; _j >= 0; --_j) { MyGame.Example.Test.Pack(builder, _o.Test4[_j]); } + _test4 = builder.EndVector(); + } + var _testarrayofstring = default(VectorOffset); + if (_o.Testarrayofstring != null) { + var _testarrayofstring_len = _o.Testarrayofstring.Count; + StringOffset[] _testarrayofstring_arr = null; + try { + Span __testarrayofstring = _testarrayofstring_len <= 64 + ? stackalloc StringOffset[_testarrayofstring_len] + : (_testarrayofstring_arr = ArrayPool.Shared.Rent(_testarrayofstring_len)).AsSpan(0, _testarrayofstring_len); + for (var _j = 0; _j < _testarrayofstring_len; ++_j) { __testarrayofstring[_j] = builder.CreateString(_o.Testarrayofstring[_j]); } + _testarrayofstring = CreateTestarrayofstringVector(builder, __testarrayofstring); + } finally { + if (_testarrayofstring_arr != null) { ArrayPool.Shared.Return(_testarrayofstring_arr); } + } + } + var _testarrayoftables = default(VectorOffset); + if (_o.Testarrayoftables != null) { + var _testarrayoftables_len = _o.Testarrayoftables.Count; + Offset[] _testarrayoftables_arr = null; + try { + Span> __testarrayoftables = _testarrayoftables_len <= 64 + ? stackalloc Offset[_testarrayoftables_len] + : (_testarrayoftables_arr = ArrayPool>.Shared.Rent(_testarrayoftables_len)).AsSpan(0, _testarrayoftables_len); + for (var _j = 0; _j < _testarrayoftables_len; ++_j) { __testarrayoftables[_j] = MyGame.Example.Monster.Pack(builder, _o.Testarrayoftables[_j]); } + _testarrayoftables = CreateTestarrayoftablesVector(builder, __testarrayoftables); + } finally { + if (_testarrayoftables_arr != null) { ArrayPool>.Shared.Return(_testarrayoftables_arr); } + } + } + var _enemy = _o.Enemy == null ? default(Offset) : MyGame.Example.Monster.Pack(builder, _o.Enemy); + var _testnestedflatbuffer = default(VectorOffset); + if (_o.Testnestedflatbuffer != null) { + _testnestedflatbuffer = CreateTestnestedflatbufferVector(builder, CollectionsMarshal.AsSpan(_o.Testnestedflatbuffer)); + } + var _testempty = _o.Testempty == null ? default(Offset) : MyGame.Example.Stat.Pack(builder, _o.Testempty); + var _testarrayofbools = default(VectorOffset); + if (_o.Testarrayofbools != null) { + _testarrayofbools = CreateTestarrayofboolsVector(builder, CollectionsMarshal.AsSpan(_o.Testarrayofbools)); + } + var _testarrayofstring2 = default(VectorOffset); + if (_o.Testarrayofstring2 != null) { + var _testarrayofstring2_len = _o.Testarrayofstring2.Count; + StringOffset[] _testarrayofstring2_arr = null; + try { + Span __testarrayofstring2 = _testarrayofstring2_len <= 64 + ? stackalloc StringOffset[_testarrayofstring2_len] + : (_testarrayofstring2_arr = ArrayPool.Shared.Rent(_testarrayofstring2_len)).AsSpan(0, _testarrayofstring2_len); + for (var _j = 0; _j < _testarrayofstring2_len; ++_j) { __testarrayofstring2[_j] = builder.CreateString(_o.Testarrayofstring2[_j]); } + _testarrayofstring2 = CreateTestarrayofstring2Vector(builder, __testarrayofstring2); + } finally { + if (_testarrayofstring2_arr != null) { ArrayPool.Shared.Return(_testarrayofstring2_arr); } + } + } + var _testarrayofsortedstruct = default(VectorOffset); + if (_o.Testarrayofsortedstruct != null) { + StartTestarrayofsortedstructVector(builder, _o.Testarrayofsortedstruct.Count); + for (var _j = _o.Testarrayofsortedstruct.Count - 1; _j >= 0; --_j) { MyGame.Example.Ability.Pack(builder, _o.Testarrayofsortedstruct[_j]); } + _testarrayofsortedstruct = builder.EndVector(); + } + var _flex = default(VectorOffset); + if (_o.Flex != null) { + _flex = CreateFlexVector(builder, CollectionsMarshal.AsSpan(_o.Flex)); + } + var _test5 = default(VectorOffset); + if (_o.Test5 != null) { + StartTest5Vector(builder, _o.Test5.Count); + for (var _j = _o.Test5.Count - 1; _j >= 0; --_j) { MyGame.Example.Test.Pack(builder, _o.Test5[_j]); } + _test5 = builder.EndVector(); + } + var _vector_of_longs = default(VectorOffset); + if (_o.VectorOfLongs != null) { + _vector_of_longs = CreateVectorOfLongsVector(builder, CollectionsMarshal.AsSpan(_o.VectorOfLongs)); + } + var _vector_of_doubles = default(VectorOffset); + if (_o.VectorOfDoubles != null) { + _vector_of_doubles = CreateVectorOfDoublesVector(builder, CollectionsMarshal.AsSpan(_o.VectorOfDoubles)); + } + var _parent_namespace_test = _o.ParentNamespaceTest == null ? default(Offset) : MyGame.InParentNamespace.Pack(builder, _o.ParentNamespaceTest); + var _vector_of_referrables = default(VectorOffset); + if (_o.VectorOfReferrables != null) { + var _vector_of_referrables_len = _o.VectorOfReferrables.Count; + Offset[] _vector_of_referrables_arr = null; + try { + Span> __vector_of_referrables = _vector_of_referrables_len <= 64 + ? stackalloc Offset[_vector_of_referrables_len] + : (_vector_of_referrables_arr = ArrayPool>.Shared.Rent(_vector_of_referrables_len)).AsSpan(0, _vector_of_referrables_len); + for (var _j = 0; _j < _vector_of_referrables_len; ++_j) { __vector_of_referrables[_j] = MyGame.Example.Referrable.Pack(builder, _o.VectorOfReferrables[_j]); } + _vector_of_referrables = CreateVectorOfReferrablesVector(builder, __vector_of_referrables); + } finally { + if (_vector_of_referrables_arr != null) { ArrayPool>.Shared.Return(_vector_of_referrables_arr); } + } + } + var _vector_of_weak_references = default(VectorOffset); + if (_o.VectorOfWeakReferences != null) { + _vector_of_weak_references = CreateVectorOfWeakReferencesVector(builder, CollectionsMarshal.AsSpan(_o.VectorOfWeakReferences)); + } + var _vector_of_strong_referrables = default(VectorOffset); + if (_o.VectorOfStrongReferrables != null) { + var _vector_of_strong_referrables_len = _o.VectorOfStrongReferrables.Count; + Offset[] _vector_of_strong_referrables_arr = null; + try { + Span> __vector_of_strong_referrables = _vector_of_strong_referrables_len <= 64 + ? stackalloc Offset[_vector_of_strong_referrables_len] + : (_vector_of_strong_referrables_arr = ArrayPool>.Shared.Rent(_vector_of_strong_referrables_len)).AsSpan(0, _vector_of_strong_referrables_len); + for (var _j = 0; _j < _vector_of_strong_referrables_len; ++_j) { __vector_of_strong_referrables[_j] = MyGame.Example.Referrable.Pack(builder, _o.VectorOfStrongReferrables[_j]); } + _vector_of_strong_referrables = CreateVectorOfStrongReferrablesVector(builder, __vector_of_strong_referrables); + } finally { + if (_vector_of_strong_referrables_arr != null) { ArrayPool>.Shared.Return(_vector_of_strong_referrables_arr); } + } + } + var _vector_of_co_owning_references = default(VectorOffset); + if (_o.VectorOfCoOwningReferences != null) { + _vector_of_co_owning_references = CreateVectorOfCoOwningReferencesVector(builder, CollectionsMarshal.AsSpan(_o.VectorOfCoOwningReferences)); + } + var _vector_of_non_owning_references = default(VectorOffset); + if (_o.VectorOfNonOwningReferences != null) { + _vector_of_non_owning_references = CreateVectorOfNonOwningReferencesVector(builder, CollectionsMarshal.AsSpan(_o.VectorOfNonOwningReferences)); + } + var _any_unique_type = _o.AnyUnique == null ? MyGame.Example.AnyUniqueAliases.NONE : _o.AnyUnique.Type; + var _any_unique = _o.AnyUnique == null ? 0 : MyGame.Example.AnyUniqueAliasesUnion.Pack(builder, _o.AnyUnique); + var _any_ambiguous_type = _o.AnyAmbiguous == null ? MyGame.Example.AnyAmbiguousAliases.NONE : _o.AnyAmbiguous.Type; + var _any_ambiguous = _o.AnyAmbiguous == null ? 0 : MyGame.Example.AnyAmbiguousAliasesUnion.Pack(builder, _o.AnyAmbiguous); + var _vector_of_enums = default(VectorOffset); + if (_o.VectorOfEnums != null) { + _vector_of_enums = CreateVectorOfEnumsVector(builder, CollectionsMarshal.AsSpan(_o.VectorOfEnums)); + } + var _testrequirednestedflatbuffer = default(VectorOffset); + if (_o.Testrequirednestedflatbuffer != null) { + _testrequirednestedflatbuffer = CreateTestrequirednestedflatbufferVector(builder, CollectionsMarshal.AsSpan(_o.Testrequirednestedflatbuffer)); + } + var _scalar_key_sorted_tables = default(VectorOffset); + if (_o.ScalarKeySortedTables != null) { + var _scalar_key_sorted_tables_len = _o.ScalarKeySortedTables.Count; + Offset[] _scalar_key_sorted_tables_arr = null; + try { + Span> __scalar_key_sorted_tables = _scalar_key_sorted_tables_len <= 64 + ? stackalloc Offset[_scalar_key_sorted_tables_len] + : (_scalar_key_sorted_tables_arr = ArrayPool>.Shared.Rent(_scalar_key_sorted_tables_len)).AsSpan(0, _scalar_key_sorted_tables_len); + for (var _j = 0; _j < _scalar_key_sorted_tables_len; ++_j) { __scalar_key_sorted_tables[_j] = MyGame.Example.Stat.Pack(builder, _o.ScalarKeySortedTables[_j]); } + _scalar_key_sorted_tables = CreateScalarKeySortedTablesVector(builder, __scalar_key_sorted_tables); + } finally { + if (_scalar_key_sorted_tables_arr != null) { ArrayPool>.Shared.Return(_scalar_key_sorted_tables_arr); } + } + } + return CreateMonster( + builder, + _o.Pos, + _o.Mana, + _o.Hp, + _name, + _inventory, + _o.Color, + _test_type, + _test, + _test4, + _testarrayofstring, + _testarrayoftables, + _enemy, + _testnestedflatbuffer, + _testempty, + _o.Testbool, + _o.Testhashs32Fnv1, + _o.Testhashu32Fnv1, + _o.Testhashs64Fnv1, + _o.Testhashu64Fnv1, + _o.Testhashs32Fnv1a, + _o.Testhashu32Fnv1a, + _o.Testhashs64Fnv1a, + _o.Testhashu64Fnv1a, + _testarrayofbools, + _o.Testf, + _o.Testf2, + _o.Testf3, + _testarrayofstring2, + _testarrayofsortedstruct, + _flex, + _test5, + _vector_of_longs, + _vector_of_doubles, + _parent_namespace_test, + _vector_of_referrables, + _o.SingleWeakReference, + _vector_of_weak_references, + _vector_of_strong_referrables, + _o.CoOwningReference, + _vector_of_co_owning_references, + _o.NonOwningReference, + _vector_of_non_owning_references, + _any_unique_type, + _any_unique, + _any_ambiguous_type, + _any_ambiguous, + _vector_of_enums, + _o.SignedEnum, + _testrequirednestedflatbuffer, + _scalar_key_sorted_tables, + _o.NativeInline, + _o.LongEnumNonEnumDefault, + _o.LongEnumNormalDefault, + _o.NanDefault, + _o.InfDefault, + _o.PositiveInfDefault, + _o.InfinityDefault, + _o.PositiveInfinityDefault, + _o.NegativeInfDefault, + _o.NegativeInfinityDefault, + _o.DoubleInfDefault); + } +} + +public class MonsterT +{ + [System.Text.Json.Serialization.JsonPropertyName("pos")] + public MyGame.Example.Vec3T Pos { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("mana")] + public short Mana { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("hp")] + public short Hp { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("name")] + public string Name { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("inventory")] + public List Inventory { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("color")] + public MyGame.Example.Color Color { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("test_type")] + private MyGame.Example.Any TestType { + get { + return this.Test != null ? this.Test.Type : MyGame.Example.Any.NONE; + } + set { + this.Test = new MyGame.Example.AnyUnion(); + this.Test.Type = value; + } + } + [System.Text.Json.Serialization.JsonPropertyName("test")] + [System.Text.Json.Serialization.JsonConverter(typeof(MyGame.Example.AnyUnion_JsonConverter))] + public MyGame.Example.AnyUnion Test { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("test4")] + public List Test4 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testarrayofstring")] + public List Testarrayofstring { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testarrayoftables")] + public List Testarrayoftables { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("enemy")] + public MyGame.Example.MonsterT Enemy { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testnestedflatbuffer")] + public List Testnestedflatbuffer { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testempty")] + public MyGame.Example.StatT Testempty { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testbool")] + public bool Testbool { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testhashs32_fnv1")] + public int Testhashs32Fnv1 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testhashu32_fnv1")] + public uint Testhashu32Fnv1 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testhashs64_fnv1")] + public long Testhashs64Fnv1 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testhashu64_fnv1")] + public ulong Testhashu64Fnv1 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testhashs32_fnv1a")] + public int Testhashs32Fnv1a { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testhashu32_fnv1a")] + public uint Testhashu32Fnv1a { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testhashs64_fnv1a")] + public long Testhashs64Fnv1a { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testhashu64_fnv1a")] + public ulong Testhashu64Fnv1a { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testarrayofbools")] + public List Testarrayofbools { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testf")] + public float Testf { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testf2")] + public float Testf2 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testf3")] + public float Testf3 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testarrayofstring2")] + public List Testarrayofstring2 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testarrayofsortedstruct")] + public List Testarrayofsortedstruct { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("flex")] + public List Flex { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("test5")] + public List Test5 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("vector_of_longs")] + public List VectorOfLongs { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("vector_of_doubles")] + public List VectorOfDoubles { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("parent_namespace_test")] + public MyGame.InParentNamespaceT ParentNamespaceTest { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("vector_of_referrables")] + public List VectorOfReferrables { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("single_weak_reference")] + public ulong SingleWeakReference { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("vector_of_weak_references")] + public List VectorOfWeakReferences { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("vector_of_strong_referrables")] + public List VectorOfStrongReferrables { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("co_owning_reference")] + public ulong CoOwningReference { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("vector_of_co_owning_references")] + public List VectorOfCoOwningReferences { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("non_owning_reference")] + public ulong NonOwningReference { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("vector_of_non_owning_references")] + public List VectorOfNonOwningReferences { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("any_unique_type")] + private MyGame.Example.AnyUniqueAliases AnyUniqueType { + get { + return this.AnyUnique != null ? this.AnyUnique.Type : MyGame.Example.AnyUniqueAliases.NONE; + } + set { + this.AnyUnique = new MyGame.Example.AnyUniqueAliasesUnion(); + this.AnyUnique.Type = value; + } + } + [System.Text.Json.Serialization.JsonPropertyName("any_unique")] + [System.Text.Json.Serialization.JsonConverter(typeof(MyGame.Example.AnyUniqueAliasesUnion_JsonConverter))] + public MyGame.Example.AnyUniqueAliasesUnion AnyUnique { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("any_ambiguous_type")] + private MyGame.Example.AnyAmbiguousAliases AnyAmbiguousType { + get { + return this.AnyAmbiguous != null ? this.AnyAmbiguous.Type : MyGame.Example.AnyAmbiguousAliases.NONE; + } + set { + this.AnyAmbiguous = new MyGame.Example.AnyAmbiguousAliasesUnion(); + this.AnyAmbiguous.Type = value; + } + } + [System.Text.Json.Serialization.JsonPropertyName("any_ambiguous")] + [System.Text.Json.Serialization.JsonConverter(typeof(MyGame.Example.AnyAmbiguousAliasesUnion_JsonConverter))] + public MyGame.Example.AnyAmbiguousAliasesUnion AnyAmbiguous { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("vector_of_enums")] + public List VectorOfEnums { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("signed_enum")] + public MyGame.Example.Race SignedEnum { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("testrequirednestedflatbuffer")] + public List Testrequirednestedflatbuffer { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("scalar_key_sorted_tables")] + public List ScalarKeySortedTables { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("native_inline")] + public MyGame.Example.TestT NativeInline { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("long_enum_non_enum_default")] + public MyGame.Example.LongEnum LongEnumNonEnumDefault { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("long_enum_normal_default")] + public MyGame.Example.LongEnum LongEnumNormalDefault { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("nan_default")] + public float NanDefault { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("inf_default")] + public float InfDefault { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("positive_inf_default")] + public float PositiveInfDefault { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("infinity_default")] + public float InfinityDefault { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("positive_infinity_default")] + public float PositiveInfinityDefault { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("negative_inf_default")] + public float NegativeInfDefault { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("negative_infinity_default")] + public float NegativeInfinityDefault { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("double_inf_default")] + public double DoubleInfDefault { get; set; } + + public MonsterT() { + this.Pos = new MyGame.Example.Vec3T(); + this.Mana = 150; + this.Hp = 100; + this.Name = null; + this.Inventory = null; + this.Color = MyGame.Example.Color.Blue; + this.Test = null; + this.Test4 = null; + this.Testarrayofstring = null; + this.Testarrayoftables = null; + this.Enemy = null; + this.Testnestedflatbuffer = null; + this.Testempty = null; + this.Testbool = false; + this.Testhashs32Fnv1 = 0; + this.Testhashu32Fnv1 = 0; + this.Testhashs64Fnv1 = 0; + this.Testhashu64Fnv1 = 0; + this.Testhashs32Fnv1a = 0; + this.Testhashu32Fnv1a = 0; + this.Testhashs64Fnv1a = 0; + this.Testhashu64Fnv1a = 0; + this.Testarrayofbools = null; + this.Testf = 3.14159f; + this.Testf2 = 3.0f; + this.Testf3 = 0.0f; + this.Testarrayofstring2 = null; + this.Testarrayofsortedstruct = null; + this.Flex = null; + this.Test5 = null; + this.VectorOfLongs = null; + this.VectorOfDoubles = null; + this.ParentNamespaceTest = null; + this.VectorOfReferrables = null; + this.SingleWeakReference = 0; + this.VectorOfWeakReferences = null; + this.VectorOfStrongReferrables = null; + this.CoOwningReference = 0; + this.VectorOfCoOwningReferences = null; + this.NonOwningReference = 0; + this.VectorOfNonOwningReferences = null; + this.AnyUnique = null; + this.AnyAmbiguous = null; + this.VectorOfEnums = null; + this.SignedEnum = MyGame.Example.Race.None; + this.Testrequirednestedflatbuffer = null; + this.ScalarKeySortedTables = null; + this.NativeInline = new MyGame.Example.TestT(); + this.LongEnumNonEnumDefault = 0; + this.LongEnumNormalDefault = MyGame.Example.LongEnum.LongOne; + this.NanDefault = Single.NaN; + this.InfDefault = Single.PositiveInfinity; + this.PositiveInfDefault = Single.PositiveInfinity; + this.InfinityDefault = Single.PositiveInfinity; + this.PositiveInfinityDefault = Single.PositiveInfinity; + this.NegativeInfDefault = Single.NegativeInfinity; + this.NegativeInfinityDefault = Single.NegativeInfinity; + this.DoubleInfDefault = Double.PositiveInfinity; + } + + private static readonly System.Text.Json.JsonSerializerOptions _jsonOptions = new System.Text.Json.JsonSerializerOptions { WriteIndented = true, NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals, Converters = { new System.Text.Json.Serialization.JsonStringEnumConverter() } }; + public static MonsterT DeserializeFromJson(string jsonText) { + return System.Text.Json.JsonSerializer.Deserialize(jsonText, _jsonOptions); + } + public string SerializeToJson() { + return System.Text.Json.JsonSerializer.Serialize(this, _jsonOptions); + } + public static MonsterT DeserializeFromBinary(byte[] fbBuffer) { + return Monster.GetRootAsMonster(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + Monster.FinishMonsterBuffer(fbb, Monster.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedSpan().ToArray(); + } +} + + +static public class MonsterVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Pos*/, 32 /*MyGame.Example.Vec3*/, 8, false) + && verifier.VerifyField(tablePos, 6 /*Mana*/, 2 /*short*/, 2, false) + && verifier.VerifyField(tablePos, 8 /*Hp*/, 2 /*short*/, 2, false) + && verifier.VerifyString(tablePos, 10 /*Name*/, true) + && verifier.VerifyVectorOfData(tablePos, 14 /*Inventory*/, 1 /*byte*/, false) + && verifier.VerifyField(tablePos, 16 /*Color*/, 1 /*MyGame.Example.Color*/, 1, false) + && verifier.VerifyField(tablePos, 18 /*TestType*/, 1 /*MyGame.Example.Any*/, 1, false) + && verifier.VerifyUnion(tablePos, 18, 20 /*Test*/, MyGame.Example.AnyVerify.Verify, false) + && verifier.VerifyVectorOfData(tablePos, 22 /*Test4*/, 4 /*MyGame.Example.Test*/, false) + && verifier.VerifyVectorOfStrings(tablePos, 24 /*Testarrayofstring*/, false) + && verifier.VerifyVectorOfTables(tablePos, 26 /*Testarrayoftables*/, MyGame.Example.MonsterVerify.Verify, false) + && verifier.VerifyTable(tablePos, 28 /*Enemy*/, MyGame.Example.MonsterVerify.Verify, false) + && verifier.VerifyNestedBuffer(tablePos, 30 /*Testnestedflatbuffer*/, MyGame.Example.MonsterVerify.Verify, false) + && verifier.VerifyTable(tablePos, 32 /*Testempty*/, MyGame.Example.StatVerify.Verify, false) + && verifier.VerifyField(tablePos, 34 /*Testbool*/, 1 /*bool*/, 1, false) + && verifier.VerifyField(tablePos, 36 /*Testhashs32Fnv1*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 38 /*Testhashu32Fnv1*/, 4 /*uint*/, 4, false) + && verifier.VerifyField(tablePos, 40 /*Testhashs64Fnv1*/, 8 /*long*/, 8, false) + && verifier.VerifyField(tablePos, 42 /*Testhashu64Fnv1*/, 8 /*ulong*/, 8, false) + && verifier.VerifyField(tablePos, 44 /*Testhashs32Fnv1a*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 46 /*Testhashu32Fnv1a*/, 4 /*uint*/, 4, false) + && verifier.VerifyField(tablePos, 48 /*Testhashs64Fnv1a*/, 8 /*long*/, 8, false) + && verifier.VerifyField(tablePos, 50 /*Testhashu64Fnv1a*/, 8 /*ulong*/, 8, false) + && verifier.VerifyVectorOfData(tablePos, 52 /*Testarrayofbools*/, 1 /*bool*/, false) + && verifier.VerifyField(tablePos, 54 /*Testf*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 56 /*Testf2*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 58 /*Testf3*/, 4 /*float*/, 4, false) + && verifier.VerifyVectorOfStrings(tablePos, 60 /*Testarrayofstring2*/, false) + && verifier.VerifyVectorOfData(tablePos, 62 /*Testarrayofsortedstruct*/, 8 /*MyGame.Example.Ability*/, false) + && verifier.VerifyVectorOfData(tablePos, 64 /*Flex*/, 1 /*byte*/, false) + && verifier.VerifyVectorOfData(tablePos, 66 /*Test5*/, 4 /*MyGame.Example.Test*/, false) + && verifier.VerifyVectorOfData(tablePos, 68 /*VectorOfLongs*/, 8 /*long*/, false) + && verifier.VerifyVectorOfData(tablePos, 70 /*VectorOfDoubles*/, 8 /*double*/, false) + && verifier.VerifyTable(tablePos, 72 /*ParentNamespaceTest*/, MyGame.InParentNamespaceVerify.Verify, false) + && verifier.VerifyVectorOfTables(tablePos, 74 /*VectorOfReferrables*/, MyGame.Example.ReferrableVerify.Verify, false) + && verifier.VerifyField(tablePos, 76 /*SingleWeakReference*/, 8 /*ulong*/, 8, false) + && verifier.VerifyVectorOfData(tablePos, 78 /*VectorOfWeakReferences*/, 8 /*ulong*/, false) + && verifier.VerifyVectorOfTables(tablePos, 80 /*VectorOfStrongReferrables*/, MyGame.Example.ReferrableVerify.Verify, false) + && verifier.VerifyField(tablePos, 82 /*CoOwningReference*/, 8 /*ulong*/, 8, false) + && verifier.VerifyVectorOfData(tablePos, 84 /*VectorOfCoOwningReferences*/, 8 /*ulong*/, false) + && verifier.VerifyField(tablePos, 86 /*NonOwningReference*/, 8 /*ulong*/, 8, false) + && verifier.VerifyVectorOfData(tablePos, 88 /*VectorOfNonOwningReferences*/, 8 /*ulong*/, false) + && verifier.VerifyField(tablePos, 90 /*AnyUniqueType*/, 1 /*MyGame.Example.AnyUniqueAliases*/, 1, false) + && verifier.VerifyUnion(tablePos, 90, 92 /*AnyUnique*/, MyGame.Example.AnyUniqueAliasesVerify.Verify, false) + && verifier.VerifyField(tablePos, 94 /*AnyAmbiguousType*/, 1 /*MyGame.Example.AnyAmbiguousAliases*/, 1, false) + && verifier.VerifyUnion(tablePos, 94, 96 /*AnyAmbiguous*/, MyGame.Example.AnyAmbiguousAliasesVerify.Verify, false) + && verifier.VerifyVectorOfData(tablePos, 98 /*VectorOfEnums*/, 1 /*MyGame.Example.Color*/, false) + && verifier.VerifyField(tablePos, 100 /*SignedEnum*/, 1 /*MyGame.Example.Race*/, 1, false) + && verifier.VerifyNestedBuffer(tablePos, 102 /*Testrequirednestedflatbuffer*/, MyGame.Example.MonsterVerify.Verify, false) + && verifier.VerifyVectorOfTables(tablePos, 104 /*ScalarKeySortedTables*/, MyGame.Example.StatVerify.Verify, false) + && verifier.VerifyField(tablePos, 106 /*NativeInline*/, 4 /*MyGame.Example.Test*/, 2, false) + && verifier.VerifyField(tablePos, 108 /*LongEnumNonEnumDefault*/, 8 /*MyGame.Example.LongEnum*/, 8, false) + && verifier.VerifyField(tablePos, 110 /*LongEnumNormalDefault*/, 8 /*MyGame.Example.LongEnum*/, 8, false) + && verifier.VerifyField(tablePos, 112 /*NanDefault*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 114 /*InfDefault*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 116 /*PositiveInfDefault*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 118 /*InfinityDefault*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 120 /*PositiveInfinityDefault*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 122 /*NegativeInfDefault*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 124 /*NegativeInfinityDefault*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 126 /*DoubleInfDefault*/, 8 /*double*/, 8, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Race.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Race.cs new file mode 100644 index 00000000000..f2af876a0d7 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Race.cs @@ -0,0 +1,18 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +public enum Race : sbyte +{ + None = -1, + Human = 0, + Dwarf = 1, + Elf = 2, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Referrable.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Referrable.cs new file mode 100644 index 00000000000..3877b56f260 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Referrable.cs @@ -0,0 +1,89 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Referrable : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Referrable GetRootAsReferrable(ByteBuffer _bb) { return GetRootAsReferrable(_bb, new Referrable()); } + public static Referrable GetRootAsReferrable(ByteBuffer _bb, Referrable obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Referrable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ulong Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateId(ulong id) { int o = __p.__offset(4); if (o != 0) { __p.bb.Put(o + __p.bb_pos, id); return true; } else { return false; } } + + public static Offset CreateReferrable(FlatBufferBuilder builder, + ulong id = 0) { + builder.StartTable(1); + Referrable.AddId(builder, id); + return Referrable.EndReferrable(builder); + } + + public static void StartReferrable(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddId(FlatBufferBuilder builder, ulong id) { builder.Add(0, id, 0); } + public static Offset EndReferrable(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfReferrable(FlatBufferBuilder builder, Span> offsets) { + var comparer = new SortedVectorUtils.ScalarOffsetComparer(builder.DataBuffer, 4); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, ulong key, ByteBuffer bb, out Referrable value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 4, 0, out value); + } + public ReferrableT UnPack() { + var _o = new ReferrableT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ReferrableT _o) { + _o.Id = this.Id; + } + public static Offset Pack(FlatBufferBuilder builder, ReferrableT _o) { + if (_o == null) return default(Offset); + return CreateReferrable( + builder, + _o.Id); + } +} + +public class ReferrableT +{ + [System.Text.Json.Serialization.JsonPropertyName("id")] + public ulong Id { get; set; } + + public ReferrableT() { + this.Id = 0; + } +} + + +static public class ReferrableVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Id*/, 8 /*ulong*/, 8, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Ability.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Ability.cs new file mode 100644 index 00000000000..a7e37f67d04 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Ability.cs @@ -0,0 +1,53 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Ability : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Ability __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public uint Id { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateId(uint id) { __p.bb.Put(__p.bb_pos + 0, id); } + public uint Distance { get { return __p.bb.Get(__p.bb_pos + 4); } } + public void MutateDistance(uint distance) { __p.bb.Put(__p.bb_pos + 4, distance); } + + public static Offset CreateAbility(ref FlatSpanBufferBuilder builder, uint Id, uint Distance) { + builder.Prep(4, 8); + builder.Put(Distance); + builder.Put(Id); + return new Offset(builder.Offset); + } + public AbilityT UnPack() { + var _o = new AbilityT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(AbilityT _o) { + _o.Id = this.Id; + _o.Distance = this.Distance; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, AbilityT _o) { + if (_o == null) return default(Offset); + return CreateAbility( + ref builder, + _o.Id, + _o.Distance); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Monster.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Monster.cs new file mode 100644 index 00000000000..1810274e9ff --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Monster.cs @@ -0,0 +1,913 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +/// an example documentation comment: "monster object" +public ref struct Monster : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Monster GetRootAsMonster(ByteSpanBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); } + public static Monster GetRootAsMonster(ByteSpanBuffer _bb, Monster obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool MonsterBufferHasIdentifier(ByteSpanBuffer _bb) { return TableSpan.__has_identifier(_bb, "MONS"); } + public static bool VerifyMonster(ByteSpanBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("MONS", false, MyGame.Example.MonsterVerify.Verify); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Monster __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public RefStructNullable Pos { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable((new MyGame.Example.StackBuffer.Vec3()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + public short Mana { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)150; } } + public bool MutateMana(short mana) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, mana); return true; } else { return false; } } + public short Hp { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)100; } } + public bool MutateHp(short hp) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(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; } } + public ReadOnlySpan GetNameBytes() { return __p.__vector_as_span(10); } + public RefStructNullable> MutableName { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(10)) : default; } } + public RefStructNullable> Inventory { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public RefStructNullable> MutableInventory { get { int o = __p.__offset(14); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(14)) : default; } } + public MyGame.Example.Color Color { get { int o = __p.__offset(16); return o != 0 ? (MyGame.Example.Color)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Color.Blue; } } + public bool MutateColor(MyGame.Example.Color color) { int o = __p.__offset(16); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, (byte)color); return true; } else { return false; } } + public MyGame.Example.Any TestType { get { int o = __p.__offset(18); return o != 0 ? (MyGame.Example.Any)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Any.NONE; } } + public RefStructNullable Test() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(20); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public MyGame.Example.StackBuffer.Monster TestAsMonster() { return Test().Value; } + public MyGame.Example.StackBuffer.TestSimpleTableWithEnum TestAsTestSimpleTableWithEnum() { return Test().Value; } + public MyGame.Example2.StackBuffer.Monster TestAsMyGame_Example2_Monster() { return Test().Value; } + public RefStructNullable> Test4 { get { int o = __p.__offset(22); return o != 0 ? new RefStructNullable>(new StructVectorSpan(__p, o, 4)) : default; } } + public RefStructNullable Testarrayofstring { get { int o = __p.__offset(24); return o != 0 ? new RefStructNullable(new StringVectorSpan(__p, o)) : default; } } + /// an example documentation comment: this will end up in the generated code + /// multiline too + public RefStructNullable> Testarrayoftables { get { int o = __p.__offset(26); return o != 0 ? new RefStructNullable>(new TableVectorSpan(__p, o, 4)) : default; } } + public bool TryGetTestarrayoftablesByKey(string key, out MyGame.Example.StackBuffer.Monster value) { int o = __p.__offset(26); if (o != 0) { return MyGame.Example.StackBuffer.Monster.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public RefStructNullable Enemy { get { int o = __p.__offset(28); return o != 0 ? new RefStructNullable((new MyGame.Example.StackBuffer.Monster()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb)) : default; } } + public RefStructNullable> Testnestedflatbuffer { get { int o = __p.__offset(30); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(30)) : default; } } + public RefStructNullable> MutableTestnestedflatbuffer { get { int o = __p.__offset(30); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(30)) : default; } } + public MyGame.Example.StackBuffer.Monster GetTestnestedflatbufferAsMonster() { int o = __p.__offset(30); return o != 0 ? (new MyGame.Example.StackBuffer.Monster()).__assign(__p.__indirect(__p.__vector(o)), __p.bb) : default; } + public RefStructNullable Testempty { get { int o = __p.__offset(32); return o != 0 ? new RefStructNullable((new MyGame.Example.StackBuffer.Stat()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb)) : default; } } + public bool Testbool { get { int o = __p.__offset(34); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public bool MutateTestbool(bool testbool) { int o = __p.__offset(34); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } } + public int Testhashs32Fnv1 { get { int o = __p.__offset(36); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public bool MutateTesthashs32Fnv1(int testhashs32_fnv1) { int o = __p.__offset(36); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashs32_fnv1); return true; } else { return false; } } + public uint Testhashu32Fnv1 { get { int o = __p.__offset(38); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint)0; } } + public bool MutateTesthashu32Fnv1(uint testhashu32_fnv1) { int o = __p.__offset(38); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashu32_fnv1); return true; } else { return false; } } + public long Testhashs64Fnv1 { get { int o = __p.__offset(40); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public bool MutateTesthashs64Fnv1(long testhashs64_fnv1) { int o = __p.__offset(40); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashs64_fnv1); return true; } else { return false; } } + public ulong Testhashu64Fnv1 { get { int o = __p.__offset(42); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateTesthashu64Fnv1(ulong testhashu64_fnv1) { int o = __p.__offset(42); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashu64_fnv1); return true; } else { return false; } } + public int Testhashs32Fnv1a { get { int o = __p.__offset(44); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public bool MutateTesthashs32Fnv1a(int testhashs32_fnv1a) { int o = __p.__offset(44); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashs32_fnv1a); return true; } else { return false; } } + public uint Testhashu32Fnv1a { get { int o = __p.__offset(46); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint)0; } } + public bool MutateTesthashu32Fnv1a(uint testhashu32_fnv1a) { int o = __p.__offset(46); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashu32_fnv1a); return true; } else { return false; } } + public long Testhashs64Fnv1a { get { int o = __p.__offset(48); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public bool MutateTesthashs64Fnv1a(long testhashs64_fnv1a) { int o = __p.__offset(48); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashs64_fnv1a); return true; } else { return false; } } + public ulong Testhashu64Fnv1a { get { int o = __p.__offset(50); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __p.__offset(50); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testhashu64_fnv1a); return true; } else { return false; } } + public RefStructNullable> Testarrayofbools { get { int o = __p.__offset(52); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(52)) : default; } } + public RefStructNullable> MutableTestarrayofbools { get { int o = __p.__offset(52); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(52)) : default; } } + public float Testf { get { int o = __p.__offset(54); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)3.14159f; } } + public bool MutateTestf(float testf) { int o = __p.__offset(54); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf); return true; } else { return false; } } + public float Testf2 { get { int o = __p.__offset(56); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)3.0f; } } + public bool MutateTestf2(float testf2) { int o = __p.__offset(56); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf2); return true; } else { return false; } } + public float Testf3 { get { int o = __p.__offset(58); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)0.0f; } } + public bool MutateTestf3(float testf3) { int o = __p.__offset(58); if (o != 0) { __p.bb.Put(o + __p.bb_pos, testf3); return true; } else { return false; } } + public RefStructNullable Testarrayofstring2 { get { int o = __p.__offset(60); return o != 0 ? new RefStructNullable(new StringVectorSpan(__p, o)) : default; } } + public RefStructNullable> Testarrayofsortedstruct { get { int o = __p.__offset(62); return o != 0 ? new RefStructNullable>(new StructVectorSpan(__p, o, 8)) : default; } } + public RefStructNullable> Flex { get { int o = __p.__offset(64); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(64)) : default; } } + public RefStructNullable> MutableFlex { get { int o = __p.__offset(64); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(64)) : default; } } + public RefStructNullable> Test5 { get { int o = __p.__offset(66); return o != 0 ? new RefStructNullable>(new StructVectorSpan(__p, o, 4)) : default; } } + public RefStructNullable> VectorOfLongs { get { int o = __p.__offset(68); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(68)) : default; } } + public RefStructNullable> MutableVectorOfLongs { get { int o = __p.__offset(68); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(68)) : default; } } + public RefStructNullable> VectorOfDoubles { get { int o = __p.__offset(70); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(70)) : default; } } + public RefStructNullable> MutableVectorOfDoubles { get { int o = __p.__offset(70); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(70)) : default; } } + public RefStructNullable ParentNamespaceTest { get { int o = __p.__offset(72); return o != 0 ? new RefStructNullable((new MyGame.StackBuffer.InParentNamespace()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb)) : default; } } + public RefStructNullable> VectorOfReferrables { get { int o = __p.__offset(74); return o != 0 ? new RefStructNullable>(new TableVectorSpan(__p, o, 4)) : default; } } + public bool TryGetVectorOfReferrablesByKey(ulong key, out MyGame.Example.StackBuffer.Referrable value) { int o = __p.__offset(74); if (o != 0) { return MyGame.Example.StackBuffer.Referrable.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public ulong SingleWeakReference { get { int o = __p.__offset(76); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateSingleWeakReference(ulong single_weak_reference) { int o = __p.__offset(76); if (o != 0) { __p.bb.Put(o + __p.bb_pos, single_weak_reference); return true; } else { return false; } } + public RefStructNullable> VectorOfWeakReferences { get { int o = __p.__offset(78); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(78)) : default; } } + public RefStructNullable> MutableVectorOfWeakReferences { get { int o = __p.__offset(78); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(78)) : default; } } + public RefStructNullable> VectorOfStrongReferrables { get { int o = __p.__offset(80); return o != 0 ? new RefStructNullable>(new TableVectorSpan(__p, o, 4)) : default; } } + public bool TryGetVectorOfStrongReferrablesByKey(ulong key, out MyGame.Example.StackBuffer.Referrable value) { int o = __p.__offset(80); if (o != 0) { return MyGame.Example.StackBuffer.Referrable.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public ulong CoOwningReference { get { int o = __p.__offset(82); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateCoOwningReference(ulong co_owning_reference) { int o = __p.__offset(82); if (o != 0) { __p.bb.Put(o + __p.bb_pos, co_owning_reference); return true; } else { return false; } } + public RefStructNullable> VectorOfCoOwningReferences { get { int o = __p.__offset(84); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(84)) : default; } } + public RefStructNullable> MutableVectorOfCoOwningReferences { get { int o = __p.__offset(84); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(84)) : default; } } + public ulong NonOwningReference { get { int o = __p.__offset(86); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateNonOwningReference(ulong non_owning_reference) { int o = __p.__offset(86); if (o != 0) { __p.bb.Put(o + __p.bb_pos, non_owning_reference); return true; } else { return false; } } + public RefStructNullable> VectorOfNonOwningReferences { get { int o = __p.__offset(88); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(88)) : default; } } + public RefStructNullable> MutableVectorOfNonOwningReferences { get { int o = __p.__offset(88); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(88)) : default; } } + public MyGame.Example.AnyUniqueAliases AnyUniqueType { get { int o = __p.__offset(90); return o != 0 ? (MyGame.Example.AnyUniqueAliases)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.AnyUniqueAliases.NONE; } } + public RefStructNullable AnyUnique() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(92); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public MyGame.Example.StackBuffer.Monster AnyUniqueAsM() { return AnyUnique().Value; } + public MyGame.Example.StackBuffer.TestSimpleTableWithEnum AnyUniqueAsTS() { return AnyUnique().Value; } + public MyGame.Example2.StackBuffer.Monster AnyUniqueAsM2() { return AnyUnique().Value; } + public MyGame.Example.AnyAmbiguousAliases AnyAmbiguousType { get { int o = __p.__offset(94); return o != 0 ? (MyGame.Example.AnyAmbiguousAliases)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.AnyAmbiguousAliases.NONE; } } + public RefStructNullable AnyAmbiguous() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(96); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public MyGame.Example.StackBuffer.Monster AnyAmbiguousAsM1() { return AnyAmbiguous().Value; } + public MyGame.Example.StackBuffer.Monster AnyAmbiguousAsM2() { return AnyAmbiguous().Value; } + public MyGame.Example.StackBuffer.Monster AnyAmbiguousAsM3() { return AnyAmbiguous().Value; } + public RefStructNullable> VectorOfEnums { get { int o = __p.__offset(98); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(98)) : default; } } + public RefStructNullable> MutableVectorOfEnums { get { int o = __p.__offset(98); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(98)) : default; } } + public MyGame.Example.Race SignedEnum { get { int o = __p.__offset(100); return o != 0 ? (MyGame.Example.Race)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Race.None; } } + public bool MutateSignedEnum(MyGame.Example.Race signed_enum) { int o = __p.__offset(100); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (sbyte)signed_enum); return true; } else { return false; } } + public RefStructNullable> Testrequirednestedflatbuffer { get { int o = __p.__offset(102); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(102)) : default; } } + public RefStructNullable> MutableTestrequirednestedflatbuffer { get { int o = __p.__offset(102); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(102)) : default; } } + public MyGame.Example.StackBuffer.Monster GetTestrequirednestedflatbufferAsMonster() { int o = __p.__offset(102); return o != 0 ? (new MyGame.Example.StackBuffer.Monster()).__assign(__p.__indirect(__p.__vector(o)), __p.bb) : default; } + public RefStructNullable> ScalarKeySortedTables { get { int o = __p.__offset(104); return o != 0 ? new RefStructNullable>(new TableVectorSpan(__p, o, 4)) : default; } } + public bool TryGetScalarKeySortedTablesByKey(ushort key, out MyGame.Example.StackBuffer.Stat value) { int o = __p.__offset(104); if (o != 0) { return MyGame.Example.StackBuffer.Stat.TryGetByKey(__p.__vector(o), key, __p.bb, out value); } value = default; return false; } + public RefStructNullable NativeInline { get { int o = __p.__offset(106); return o != 0 ? new RefStructNullable((new MyGame.Example.StackBuffer.Test()).__assign(o + __p.bb_pos, __p.bb)) : default; } } + public MyGame.Example.LongEnum LongEnumNonEnumDefault { get { int o = __p.__offset(108); return o != 0 ? (MyGame.Example.LongEnum)__p.bb.Get(o + __p.bb_pos) : 0; } } + public bool MutateLongEnumNonEnumDefault(MyGame.Example.LongEnum long_enum_non_enum_default) { int o = __p.__offset(108); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (ulong)long_enum_non_enum_default); return true; } else { return false; } } + public MyGame.Example.LongEnum LongEnumNormalDefault { get { int o = __p.__offset(110); return o != 0 ? (MyGame.Example.LongEnum)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.LongEnum.LongOne; } } + public bool MutateLongEnumNormalDefault(MyGame.Example.LongEnum long_enum_normal_default) { int o = __p.__offset(110); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (ulong)long_enum_normal_default); return true; } else { return false; } } + public float NanDefault { get { int o = __p.__offset(112); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.NaN; } } + public bool MutateNanDefault(float nan_default) { int o = __p.__offset(112); if (o != 0) { __p.bb.Put(o + __p.bb_pos, nan_default); return true; } else { return false; } } + public float InfDefault { get { int o = __p.__offset(114); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.PositiveInfinity; } } + public bool MutateInfDefault(float inf_default) { int o = __p.__offset(114); if (o != 0) { __p.bb.Put(o + __p.bb_pos, inf_default); return true; } else { return false; } } + public float PositiveInfDefault { get { int o = __p.__offset(116); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.PositiveInfinity; } } + public bool MutatePositiveInfDefault(float positive_inf_default) { int o = __p.__offset(116); if (o != 0) { __p.bb.Put(o + __p.bb_pos, positive_inf_default); return true; } else { return false; } } + public float InfinityDefault { get { int o = __p.__offset(118); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.PositiveInfinity; } } + public bool MutateInfinityDefault(float infinity_default) { int o = __p.__offset(118); if (o != 0) { __p.bb.Put(o + __p.bb_pos, infinity_default); return true; } else { return false; } } + public float PositiveInfinityDefault { get { int o = __p.__offset(120); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.PositiveInfinity; } } + public bool MutatePositiveInfinityDefault(float positive_infinity_default) { int o = __p.__offset(120); if (o != 0) { __p.bb.Put(o + __p.bb_pos, positive_infinity_default); return true; } else { return false; } } + public float NegativeInfDefault { get { int o = __p.__offset(122); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.NegativeInfinity; } } + public bool MutateNegativeInfDefault(float negative_inf_default) { int o = __p.__offset(122); if (o != 0) { __p.bb.Put(o + __p.bb_pos, negative_inf_default); return true; } else { return false; } } + public float NegativeInfinityDefault { get { int o = __p.__offset(124); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)Single.NegativeInfinity; } } + public bool MutateNegativeInfinityDefault(float negative_infinity_default) { int o = __p.__offset(124); if (o != 0) { __p.bb.Put(o + __p.bb_pos, negative_infinity_default); return true; } else { return false; } } + public double DoubleInfDefault { get { int o = __p.__offset(126); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double)Double.PositiveInfinity; } } + public bool MutateDoubleInfDefault(double double_inf_default) { int o = __p.__offset(126); if (o != 0) { __p.bb.Put(o + __p.bb_pos, double_inf_default); return true; } else { return false; } } + + public static void StartMonster(ref FlatSpanBufferBuilder builder) { builder.StartTable(62); } + public static void AddPos(ref FlatSpanBufferBuilder builder, Offset posOffset) { builder.AddStruct(0, posOffset, 0); } + public static void AddMana(ref FlatSpanBufferBuilder builder, short mana) { builder.Add(1, mana, 150); } + public static void AddHp(ref FlatSpanBufferBuilder builder, short hp) { builder.Add(2, hp, 100); } + public static void AddName(ref FlatSpanBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(3, nameOffset, 0); } + public static void AddInventory(ref FlatSpanBufferBuilder builder, VectorOffset inventoryOffset) { builder.AddOffset(5, inventoryOffset, 0); } + public static VectorOffset CreateInventoryVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateInventoryVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateInventoryVectorBlock(ref builder, data); } + public static void StartInventoryVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddColor(ref FlatSpanBufferBuilder builder, MyGame.Example.Color color) { builder.Add(6, (byte)color, 8); } + public static void AddTestType(ref FlatSpanBufferBuilder builder, MyGame.Example.Any testType) { builder.Add(7, (byte)testType, 0); } + public static void AddTest(ref FlatSpanBufferBuilder builder, int testOffset) { builder.AddOffset(8, testOffset, 0); } + public static void AddTest4(ref FlatSpanBufferBuilder builder, VectorOffset test4Offset) { builder.AddOffset(9, test4Offset, 0); } + public static void StartTest4Vector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 2); } + public static void AddTestarrayofstring(ref FlatSpanBufferBuilder builder, VectorOffset testarrayofstringOffset) { builder.AddOffset(10, testarrayofstringOffset, 0); } + public static VectorOffset CreateTestarrayofstringVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTestarrayofstringVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateTestarrayofstringVectorBlock(ref builder, data); } + public static void StartTestarrayofstringVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddTestarrayoftables(ref FlatSpanBufferBuilder builder, VectorOffset testarrayoftablesOffset) { builder.AddOffset(11, testarrayoftablesOffset, 0); } + public static VectorOffset CreateTestarrayoftablesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateTestarrayoftablesVector(ref FlatSpanBufferBuilder builder, scoped Span> data) { return CreateTestarrayoftablesVectorBlock(ref builder, data); } + public static void StartTestarrayoftablesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddEnemy(ref FlatSpanBufferBuilder builder, Offset enemyOffset) { builder.AddOffset(12, enemyOffset, 0); } + public static void AddTestnestedflatbuffer(ref FlatSpanBufferBuilder builder, VectorOffset testnestedflatbufferOffset) { builder.AddOffset(13, testnestedflatbufferOffset, 0); } + public static VectorOffset CreateTestnestedflatbufferVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTestnestedflatbufferVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateTestnestedflatbufferVectorBlock(ref builder, data); } + public static void StartTestnestedflatbufferVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddTestempty(ref FlatSpanBufferBuilder builder, Offset testemptyOffset) { builder.AddOffset(14, testemptyOffset, 0); } + public static void AddTestbool(ref FlatSpanBufferBuilder builder, bool testbool) { builder.Add(15, testbool, false); } + public static void AddTesthashs32Fnv1(ref FlatSpanBufferBuilder builder, int testhashs32Fnv1) { builder.Add(16, testhashs32Fnv1, 0); } + public static void AddTesthashu32Fnv1(ref FlatSpanBufferBuilder builder, uint testhashu32Fnv1) { builder.Add(17, testhashu32Fnv1, 0); } + public static void AddTesthashs64Fnv1(ref FlatSpanBufferBuilder builder, long testhashs64Fnv1) { builder.Add(18, testhashs64Fnv1, 0); } + public static void AddTesthashu64Fnv1(ref FlatSpanBufferBuilder builder, ulong testhashu64Fnv1) { builder.Add(19, testhashu64Fnv1, 0); } + public static void AddTesthashs32Fnv1a(ref FlatSpanBufferBuilder builder, int testhashs32Fnv1a) { builder.Add(20, testhashs32Fnv1a, 0); } + public static void AddTesthashu32Fnv1a(ref FlatSpanBufferBuilder builder, uint testhashu32Fnv1a) { builder.Add(21, testhashu32Fnv1a, 0); } + public static void AddTesthashs64Fnv1a(ref FlatSpanBufferBuilder builder, long testhashs64Fnv1a) { builder.Add(22, testhashs64Fnv1a, 0); } + public static void AddTesthashu64Fnv1a(ref FlatSpanBufferBuilder builder, ulong testhashu64Fnv1a) { builder.Add(23, testhashu64Fnv1a, 0); } + public static void AddTestarrayofbools(ref FlatSpanBufferBuilder builder, VectorOffset testarrayofboolsOffset) { builder.AddOffset(24, testarrayofboolsOffset, 0); } + public static VectorOffset CreateTestarrayofboolsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTestarrayofboolsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateTestarrayofboolsVectorBlock(ref builder, data); } + public static void StartTestarrayofboolsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddTestf(ref FlatSpanBufferBuilder builder, float testf) { builder.Add(25, testf, 3.14159f); } + public static void AddTestf2(ref FlatSpanBufferBuilder builder, float testf2) { builder.Add(26, testf2, 3.0f); } + public static void AddTestf3(ref FlatSpanBufferBuilder builder, float testf3) { builder.Add(27, testf3, 0.0f); } + public static void AddTestarrayofstring2(ref FlatSpanBufferBuilder builder, VectorOffset testarrayofstring2Offset) { builder.AddOffset(28, testarrayofstring2Offset, 0); } + public static VectorOffset CreateTestarrayofstring2VectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTestarrayofstring2Vector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateTestarrayofstring2VectorBlock(ref builder, data); } + public static void StartTestarrayofstring2Vector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddTestarrayofsortedstruct(ref FlatSpanBufferBuilder builder, VectorOffset testarrayofsortedstructOffset) { builder.AddOffset(29, testarrayofsortedstructOffset, 0); } + public static void StartTestarrayofsortedstructVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 4); } + public static void AddFlex(ref FlatSpanBufferBuilder builder, VectorOffset flexOffset) { builder.AddOffset(30, flexOffset, 0); } + public static VectorOffset CreateFlexVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateFlexVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateFlexVectorBlock(ref builder, data); } + public static void StartFlexVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddTest5(ref FlatSpanBufferBuilder builder, VectorOffset test5Offset) { builder.AddOffset(31, test5Offset, 0); } + public static void StartTest5Vector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 2); } + public static void AddVectorOfLongs(ref FlatSpanBufferBuilder builder, VectorOffset vectorOfLongsOffset) { builder.AddOffset(32, vectorOfLongsOffset, 0); } + public static VectorOffset CreateVectorOfLongsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfLongsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateVectorOfLongsVectorBlock(ref builder, data); } + public static void StartVectorOfLongsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddVectorOfDoubles(ref FlatSpanBufferBuilder builder, VectorOffset vectorOfDoublesOffset) { builder.AddOffset(33, vectorOfDoublesOffset, 0); } + public static VectorOffset CreateVectorOfDoublesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfDoublesVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateVectorOfDoublesVectorBlock(ref builder, data); } + public static void StartVectorOfDoublesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddParentNamespaceTest(ref FlatSpanBufferBuilder builder, Offset parentNamespaceTestOffset) { builder.AddOffset(34, parentNamespaceTestOffset, 0); } + public static void AddVectorOfReferrables(ref FlatSpanBufferBuilder builder, VectorOffset vectorOfReferrablesOffset) { builder.AddOffset(35, vectorOfReferrablesOffset, 0); } + public static VectorOffset CreateVectorOfReferrablesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfReferrablesVector(ref FlatSpanBufferBuilder builder, scoped Span> data) { return CreateVectorOfReferrablesVectorBlock(ref builder, data); } + public static void StartVectorOfReferrablesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddSingleWeakReference(ref FlatSpanBufferBuilder builder, ulong singleWeakReference) { builder.Add(36, singleWeakReference, 0); } + public static void AddVectorOfWeakReferences(ref FlatSpanBufferBuilder builder, VectorOffset vectorOfWeakReferencesOffset) { builder.AddOffset(37, vectorOfWeakReferencesOffset, 0); } + public static VectorOffset CreateVectorOfWeakReferencesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfWeakReferencesVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateVectorOfWeakReferencesVectorBlock(ref builder, data); } + public static void StartVectorOfWeakReferencesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddVectorOfStrongReferrables(ref FlatSpanBufferBuilder builder, VectorOffset vectorOfStrongReferrablesOffset) { builder.AddOffset(38, vectorOfStrongReferrablesOffset, 0); } + public static VectorOffset CreateVectorOfStrongReferrablesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfStrongReferrablesVector(ref FlatSpanBufferBuilder builder, scoped Span> data) { return CreateVectorOfStrongReferrablesVectorBlock(ref builder, data); } + public static void StartVectorOfStrongReferrablesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddCoOwningReference(ref FlatSpanBufferBuilder builder, ulong coOwningReference) { builder.Add(39, coOwningReference, 0); } + public static void AddVectorOfCoOwningReferences(ref FlatSpanBufferBuilder builder, VectorOffset vectorOfCoOwningReferencesOffset) { builder.AddOffset(40, vectorOfCoOwningReferencesOffset, 0); } + public static VectorOffset CreateVectorOfCoOwningReferencesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfCoOwningReferencesVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateVectorOfCoOwningReferencesVectorBlock(ref builder, data); } + public static void StartVectorOfCoOwningReferencesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddNonOwningReference(ref FlatSpanBufferBuilder builder, ulong nonOwningReference) { builder.Add(41, nonOwningReference, 0); } + public static void AddVectorOfNonOwningReferences(ref FlatSpanBufferBuilder builder, VectorOffset vectorOfNonOwningReferencesOffset) { builder.AddOffset(42, vectorOfNonOwningReferencesOffset, 0); } + public static VectorOffset CreateVectorOfNonOwningReferencesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfNonOwningReferencesVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateVectorOfNonOwningReferencesVectorBlock(ref builder, data); } + public static void StartVectorOfNonOwningReferencesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static void AddAnyUniqueType(ref FlatSpanBufferBuilder builder, MyGame.Example.AnyUniqueAliases anyUniqueType) { builder.Add(43, (byte)anyUniqueType, 0); } + public static void AddAnyUnique(ref FlatSpanBufferBuilder builder, int anyUniqueOffset) { builder.AddOffset(44, anyUniqueOffset, 0); } + public static void AddAnyAmbiguousType(ref FlatSpanBufferBuilder builder, MyGame.Example.AnyAmbiguousAliases anyAmbiguousType) { builder.Add(45, (byte)anyAmbiguousType, 0); } + public static void AddAnyAmbiguous(ref FlatSpanBufferBuilder builder, int anyAmbiguousOffset) { builder.AddOffset(46, anyAmbiguousOffset, 0); } + public static void AddVectorOfEnums(ref FlatSpanBufferBuilder builder, VectorOffset vectorOfEnumsOffset) { builder.AddOffset(47, vectorOfEnumsOffset, 0); } + public static VectorOffset CreateVectorOfEnumsVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVectorOfEnumsVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateVectorOfEnumsVectorBlock(ref builder, data); } + public static void StartVectorOfEnumsVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddSignedEnum(ref FlatSpanBufferBuilder builder, MyGame.Example.Race signedEnum) { builder.Add(48, (sbyte)signedEnum, -1); } + public static void AddTestrequirednestedflatbuffer(ref FlatSpanBufferBuilder builder, VectorOffset testrequirednestedflatbufferOffset) { builder.AddOffset(49, testrequirednestedflatbufferOffset, 0); } + public static VectorOffset CreateTestrequirednestedflatbufferVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateTestrequirednestedflatbufferVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateTestrequirednestedflatbufferVectorBlock(ref builder, data); } + public static void StartTestrequirednestedflatbufferVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddScalarKeySortedTables(ref FlatSpanBufferBuilder builder, VectorOffset scalarKeySortedTablesOffset) { builder.AddOffset(50, scalarKeySortedTablesOffset, 0); } + public static VectorOffset CreateScalarKeySortedTablesVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span> data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan>(data); return builder.EndVector(); } + public static VectorOffset CreateScalarKeySortedTablesVector(ref FlatSpanBufferBuilder builder, scoped Span> data) { return CreateScalarKeySortedTablesVectorBlock(ref builder, data); } + public static void StartScalarKeySortedTablesVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static void AddNativeInline(ref FlatSpanBufferBuilder builder, Offset nativeInlineOffset) { builder.AddStruct(51, nativeInlineOffset, 0); } + public static void AddLongEnumNonEnumDefault(ref FlatSpanBufferBuilder builder, MyGame.Example.LongEnum longEnumNonEnumDefault) { builder.Add(52, (ulong)longEnumNonEnumDefault, 0); } + public static void AddLongEnumNormalDefault(ref FlatSpanBufferBuilder builder, MyGame.Example.LongEnum longEnumNormalDefault) { builder.Add(53, (ulong)longEnumNormalDefault, 2); } + public static void AddNanDefault(ref FlatSpanBufferBuilder builder, float nanDefault) { builder.Add(54, nanDefault, Single.NaN); } + public static void AddInfDefault(ref FlatSpanBufferBuilder builder, float infDefault) { builder.Add(55, infDefault, Single.PositiveInfinity); } + public static void AddPositiveInfDefault(ref FlatSpanBufferBuilder builder, float positiveInfDefault) { builder.Add(56, positiveInfDefault, Single.PositiveInfinity); } + public static void AddInfinityDefault(ref FlatSpanBufferBuilder builder, float infinityDefault) { builder.Add(57, infinityDefault, Single.PositiveInfinity); } + public static void AddPositiveInfinityDefault(ref FlatSpanBufferBuilder builder, float positiveInfinityDefault) { builder.Add(58, positiveInfinityDefault, Single.PositiveInfinity); } + public static void AddNegativeInfDefault(ref FlatSpanBufferBuilder builder, float negativeInfDefault) { builder.Add(59, negativeInfDefault, Single.NegativeInfinity); } + public static void AddNegativeInfinityDefault(ref FlatSpanBufferBuilder builder, float negativeInfinityDefault) { builder.Add(60, negativeInfinityDefault, Single.NegativeInfinity); } + public static void AddDoubleInfDefault(ref FlatSpanBufferBuilder builder, double doubleInfDefault) { builder.Add(61, doubleInfDefault, Double.PositiveInfinity); } + public static Offset EndMonster(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + builder.Required(o, 10); // name + return new Offset(o); + } + public static void FinishMonsterBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "MONS"); } + public static void FinishSizePrefixedMonsterBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "MONS"); } + + public static VectorOffset CreateSortedVectorOfMonster(ref FlatSpanBufferBuilder builder, scoped Span> offsets) { + var comparer = new SortedVectorUtils.VectorOffsetComparer(builder.DataBuffer, 10); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, string key, ByteSpanBuffer bb, out Monster value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 10, out value); + } + public MonsterT UnPack() { + var _o = new MonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(MonsterT _o) { + if (this.Pos.HasValue) { + if (_o.Pos == null) _o.Pos = new MyGame.Example.Vec3T(); + this.Pos.Value.UnPackTo(_o.Pos); + } else { + _o.Pos = null; + } + _o.Mana = this.Mana; + _o.Hp = this.Hp; + _o.Name = this.Name; + var _inventory_vec = this.Inventory; + var _inventory_len = _inventory_vec.HasValue ? _inventory_vec.Value.Length : 0; + if (_o.Inventory == null) { + _o.Inventory = new List(_inventory_len); + } + ObjectApiUtil.ResizeList(_o.Inventory, _inventory_len); + if (_inventory_vec.HasValue) { _inventory_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Inventory)); } + _o.Color = this.Color; + if (_o.Test == null) { + _o.Test = new MyGame.Example.AnyUnion(); + } + var _TestOldType = _o.Test.Type; + _o.Test.Type = this.TestType; + switch (this.TestType) { + default: + _o.Test.Value = null; + break; + case MyGame.Example.Any.Monster: + if (this.Test().HasValue) { + if (_TestOldType == MyGame.Example.Any.Monster) { + this.Test().Value.UnPackTo((MyGame.Example.MonsterT)_o.Test.Value); + } else { + _o.Test.Value = this.Test().Value.UnPack(); + } + } else { + _o.Test.Value = null; + } + break; + case MyGame.Example.Any.TestSimpleTableWithEnum: + if (this.Test().HasValue) { + if (_TestOldType == MyGame.Example.Any.TestSimpleTableWithEnum) { + this.Test().Value.UnPackTo((MyGame.Example.TestSimpleTableWithEnumT)_o.Test.Value); + } else { + _o.Test.Value = this.Test().Value.UnPack(); + } + } else { + _o.Test.Value = null; + } + break; + case MyGame.Example.Any.MyGame_Example2_Monster: + if (this.Test().HasValue) { + if (_TestOldType == MyGame.Example.Any.MyGame_Example2_Monster) { + this.Test().Value.UnPackTo((MyGame.Example2.MonsterT)_o.Test.Value); + } else { + _o.Test.Value = this.Test().Value.UnPack(); + } + } else { + _o.Test.Value = null; + } + break; + } + var _test4_vec = this.Test4; + var _test4_len = _test4_vec.HasValue ? _test4_vec.Value.Length : 0; + if (_o.Test4 == null) { + _o.Test4 = new List(_test4_len); + } + ObjectApiUtil.ResizeList(_o.Test4, _test4_len); + if (_test4_vec.HasValue) { + var _test4_value = _test4_vec.Value; + for (var _j = 0; _j < _test4_len; ++_j) { + var _src = _test4_value[_j]; + if (_o.Test4[_j] == null) { _o.Test4[_j] = new TestT(); } + _src.UnPackTo(_o.Test4[_j]); + } + } + var _testarrayofstring_vec = this.Testarrayofstring; + var _testarrayofstring_len = _testarrayofstring_vec.HasValue ? _testarrayofstring_vec.Value.Length : 0; + if (_o.Testarrayofstring == null) { + _o.Testarrayofstring = new List(_testarrayofstring_len); + } else { + _o.Testarrayofstring.Clear(); + if (_o.Testarrayofstring.Capacity < _testarrayofstring_len) { + _o.Testarrayofstring.Capacity = _testarrayofstring_len; + } + } + if (_testarrayofstring_vec.HasValue) { + var _testarrayofstring_value = _testarrayofstring_vec.Value; + for (var _j = 0; _j < _testarrayofstring_len; ++_j) { _o.Testarrayofstring.Add(_testarrayofstring_value[_j]); } + } + var _testarrayoftables_vec = this.Testarrayoftables; + var _testarrayoftables_len = _testarrayoftables_vec.HasValue ? _testarrayoftables_vec.Value.Length : 0; + if (_o.Testarrayoftables == null) { + _o.Testarrayoftables = new List(_testarrayoftables_len); + } + ObjectApiUtil.ResizeList(_o.Testarrayoftables, _testarrayoftables_len); + if (_testarrayoftables_vec.HasValue) { + var _testarrayoftables_value = _testarrayoftables_vec.Value; + for (var _j = 0; _j < _testarrayoftables_len; ++_j) { + var _src = _testarrayoftables_value[_j]; + if (_o.Testarrayoftables[_j] == null) { _o.Testarrayoftables[_j] = new MonsterT(); } + _src.UnPackTo(_o.Testarrayoftables[_j]); + } + } + if (this.Enemy.HasValue) { + if (_o.Enemy == null) _o.Enemy = new MyGame.Example.MonsterT(); + this.Enemy.Value.UnPackTo(_o.Enemy); + } else { + _o.Enemy = null; + } + var _testnestedflatbuffer_vec = this.Testnestedflatbuffer; + var _testnestedflatbuffer_len = _testnestedflatbuffer_vec.HasValue ? _testnestedflatbuffer_vec.Value.Length : 0; + if (_o.Testnestedflatbuffer == null) { + _o.Testnestedflatbuffer = new List(_testnestedflatbuffer_len); + } + ObjectApiUtil.ResizeList(_o.Testnestedflatbuffer, _testnestedflatbuffer_len); + if (_testnestedflatbuffer_vec.HasValue) { _testnestedflatbuffer_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Testnestedflatbuffer)); } + if (this.Testempty.HasValue) { + if (_o.Testempty == null) _o.Testempty = new MyGame.Example.StatT(); + this.Testempty.Value.UnPackTo(_o.Testempty); + } else { + _o.Testempty = null; + } + _o.Testbool = this.Testbool; + _o.Testhashs32Fnv1 = this.Testhashs32Fnv1; + _o.Testhashu32Fnv1 = this.Testhashu32Fnv1; + _o.Testhashs64Fnv1 = this.Testhashs64Fnv1; + _o.Testhashu64Fnv1 = this.Testhashu64Fnv1; + _o.Testhashs32Fnv1a = this.Testhashs32Fnv1a; + _o.Testhashu32Fnv1a = this.Testhashu32Fnv1a; + _o.Testhashs64Fnv1a = this.Testhashs64Fnv1a; + _o.Testhashu64Fnv1a = this.Testhashu64Fnv1a; + var _testarrayofbools_vec = this.Testarrayofbools; + var _testarrayofbools_len = _testarrayofbools_vec.HasValue ? _testarrayofbools_vec.Value.Length : 0; + if (_o.Testarrayofbools == null) { + _o.Testarrayofbools = new List(_testarrayofbools_len); + } else { + _o.Testarrayofbools.Clear(); + if (_o.Testarrayofbools.Capacity < _testarrayofbools_len) { + _o.Testarrayofbools.Capacity = _testarrayofbools_len; + } + } + if (_testarrayofbools_vec.HasValue) { + for (var _j = 0; _j < _testarrayofbools_len; ++_j) { _o.Testarrayofbools.Add(_testarrayofbools_vec.Value[_j]); } + } + _o.Testf = this.Testf; + _o.Testf2 = this.Testf2; + _o.Testf3 = this.Testf3; + var _testarrayofstring2_vec = this.Testarrayofstring2; + var _testarrayofstring2_len = _testarrayofstring2_vec.HasValue ? _testarrayofstring2_vec.Value.Length : 0; + if (_o.Testarrayofstring2 == null) { + _o.Testarrayofstring2 = new List(_testarrayofstring2_len); + } else { + _o.Testarrayofstring2.Clear(); + if (_o.Testarrayofstring2.Capacity < _testarrayofstring2_len) { + _o.Testarrayofstring2.Capacity = _testarrayofstring2_len; + } + } + if (_testarrayofstring2_vec.HasValue) { + var _testarrayofstring2_value = _testarrayofstring2_vec.Value; + for (var _j = 0; _j < _testarrayofstring2_len; ++_j) { _o.Testarrayofstring2.Add(_testarrayofstring2_value[_j]); } + } + var _testarrayofsortedstruct_vec = this.Testarrayofsortedstruct; + var _testarrayofsortedstruct_len = _testarrayofsortedstruct_vec.HasValue ? _testarrayofsortedstruct_vec.Value.Length : 0; + if (_o.Testarrayofsortedstruct == null) { + _o.Testarrayofsortedstruct = new List(_testarrayofsortedstruct_len); + } + ObjectApiUtil.ResizeList(_o.Testarrayofsortedstruct, _testarrayofsortedstruct_len); + if (_testarrayofsortedstruct_vec.HasValue) { + var _testarrayofsortedstruct_value = _testarrayofsortedstruct_vec.Value; + for (var _j = 0; _j < _testarrayofsortedstruct_len; ++_j) { + var _src = _testarrayofsortedstruct_value[_j]; + if (_o.Testarrayofsortedstruct[_j] == null) { _o.Testarrayofsortedstruct[_j] = new AbilityT(); } + _src.UnPackTo(_o.Testarrayofsortedstruct[_j]); + } + } + var _flex_vec = this.Flex; + var _flex_len = _flex_vec.HasValue ? _flex_vec.Value.Length : 0; + if (_o.Flex == null) { + _o.Flex = new List(_flex_len); + } + ObjectApiUtil.ResizeList(_o.Flex, _flex_len); + if (_flex_vec.HasValue) { _flex_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Flex)); } + var _test5_vec = this.Test5; + var _test5_len = _test5_vec.HasValue ? _test5_vec.Value.Length : 0; + if (_o.Test5 == null) { + _o.Test5 = new List(_test5_len); + } + ObjectApiUtil.ResizeList(_o.Test5, _test5_len); + if (_test5_vec.HasValue) { + var _test5_value = _test5_vec.Value; + for (var _j = 0; _j < _test5_len; ++_j) { + var _src = _test5_value[_j]; + if (_o.Test5[_j] == null) { _o.Test5[_j] = new TestT(); } + _src.UnPackTo(_o.Test5[_j]); + } + } + var _vector_of_longs_vec = this.VectorOfLongs; + var _vector_of_longs_len = _vector_of_longs_vec.HasValue ? _vector_of_longs_vec.Value.Length : 0; + if (_o.VectorOfLongs == null) { + _o.VectorOfLongs = new List(_vector_of_longs_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfLongs, _vector_of_longs_len); + if (_vector_of_longs_vec.HasValue) { _vector_of_longs_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfLongs)); } + var _vector_of_doubles_vec = this.VectorOfDoubles; + var _vector_of_doubles_len = _vector_of_doubles_vec.HasValue ? _vector_of_doubles_vec.Value.Length : 0; + if (_o.VectorOfDoubles == null) { + _o.VectorOfDoubles = new List(_vector_of_doubles_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfDoubles, _vector_of_doubles_len); + if (_vector_of_doubles_vec.HasValue) { _vector_of_doubles_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfDoubles)); } + if (this.ParentNamespaceTest.HasValue) { + if (_o.ParentNamespaceTest == null) _o.ParentNamespaceTest = new MyGame.InParentNamespaceT(); + this.ParentNamespaceTest.Value.UnPackTo(_o.ParentNamespaceTest); + } else { + _o.ParentNamespaceTest = null; + } + var _vector_of_referrables_vec = this.VectorOfReferrables; + var _vector_of_referrables_len = _vector_of_referrables_vec.HasValue ? _vector_of_referrables_vec.Value.Length : 0; + if (_o.VectorOfReferrables == null) { + _o.VectorOfReferrables = new List(_vector_of_referrables_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfReferrables, _vector_of_referrables_len); + if (_vector_of_referrables_vec.HasValue) { + var _vector_of_referrables_value = _vector_of_referrables_vec.Value; + for (var _j = 0; _j < _vector_of_referrables_len; ++_j) { + var _src = _vector_of_referrables_value[_j]; + if (_o.VectorOfReferrables[_j] == null) { _o.VectorOfReferrables[_j] = new ReferrableT(); } + _src.UnPackTo(_o.VectorOfReferrables[_j]); + } + } + _o.SingleWeakReference = this.SingleWeakReference; + var _vector_of_weak_references_vec = this.VectorOfWeakReferences; + var _vector_of_weak_references_len = _vector_of_weak_references_vec.HasValue ? _vector_of_weak_references_vec.Value.Length : 0; + if (_o.VectorOfWeakReferences == null) { + _o.VectorOfWeakReferences = new List(_vector_of_weak_references_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfWeakReferences, _vector_of_weak_references_len); + if (_vector_of_weak_references_vec.HasValue) { _vector_of_weak_references_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfWeakReferences)); } + var _vector_of_strong_referrables_vec = this.VectorOfStrongReferrables; + var _vector_of_strong_referrables_len = _vector_of_strong_referrables_vec.HasValue ? _vector_of_strong_referrables_vec.Value.Length : 0; + if (_o.VectorOfStrongReferrables == null) { + _o.VectorOfStrongReferrables = new List(_vector_of_strong_referrables_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfStrongReferrables, _vector_of_strong_referrables_len); + if (_vector_of_strong_referrables_vec.HasValue) { + var _vector_of_strong_referrables_value = _vector_of_strong_referrables_vec.Value; + for (var _j = 0; _j < _vector_of_strong_referrables_len; ++_j) { + var _src = _vector_of_strong_referrables_value[_j]; + if (_o.VectorOfStrongReferrables[_j] == null) { _o.VectorOfStrongReferrables[_j] = new ReferrableT(); } + _src.UnPackTo(_o.VectorOfStrongReferrables[_j]); + } + } + _o.CoOwningReference = this.CoOwningReference; + var _vector_of_co_owning_references_vec = this.VectorOfCoOwningReferences; + var _vector_of_co_owning_references_len = _vector_of_co_owning_references_vec.HasValue ? _vector_of_co_owning_references_vec.Value.Length : 0; + if (_o.VectorOfCoOwningReferences == null) { + _o.VectorOfCoOwningReferences = new List(_vector_of_co_owning_references_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfCoOwningReferences, _vector_of_co_owning_references_len); + if (_vector_of_co_owning_references_vec.HasValue) { _vector_of_co_owning_references_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfCoOwningReferences)); } + _o.NonOwningReference = this.NonOwningReference; + var _vector_of_non_owning_references_vec = this.VectorOfNonOwningReferences; + var _vector_of_non_owning_references_len = _vector_of_non_owning_references_vec.HasValue ? _vector_of_non_owning_references_vec.Value.Length : 0; + if (_o.VectorOfNonOwningReferences == null) { + _o.VectorOfNonOwningReferences = new List(_vector_of_non_owning_references_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfNonOwningReferences, _vector_of_non_owning_references_len); + if (_vector_of_non_owning_references_vec.HasValue) { _vector_of_non_owning_references_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfNonOwningReferences)); } + if (_o.AnyUnique == null) { + _o.AnyUnique = new MyGame.Example.AnyUniqueAliasesUnion(); + } + var _AnyUniqueOldType = _o.AnyUnique.Type; + _o.AnyUnique.Type = this.AnyUniqueType; + switch (this.AnyUniqueType) { + default: + _o.AnyUnique.Value = null; + break; + case MyGame.Example.AnyUniqueAliases.M: + if (this.AnyUnique().HasValue) { + if (_AnyUniqueOldType == MyGame.Example.AnyUniqueAliases.M) { + this.AnyUnique().Value.UnPackTo((MyGame.Example.MonsterT)_o.AnyUnique.Value); + } else { + _o.AnyUnique.Value = this.AnyUnique().Value.UnPack(); + } + } else { + _o.AnyUnique.Value = null; + } + break; + case MyGame.Example.AnyUniqueAliases.TS: + if (this.AnyUnique().HasValue) { + if (_AnyUniqueOldType == MyGame.Example.AnyUniqueAliases.TS) { + this.AnyUnique().Value.UnPackTo((MyGame.Example.TestSimpleTableWithEnumT)_o.AnyUnique.Value); + } else { + _o.AnyUnique.Value = this.AnyUnique().Value.UnPack(); + } + } else { + _o.AnyUnique.Value = null; + } + break; + case MyGame.Example.AnyUniqueAliases.M2: + if (this.AnyUnique().HasValue) { + if (_AnyUniqueOldType == MyGame.Example.AnyUniqueAliases.M2) { + this.AnyUnique().Value.UnPackTo((MyGame.Example2.MonsterT)_o.AnyUnique.Value); + } else { + _o.AnyUnique.Value = this.AnyUnique().Value.UnPack(); + } + } else { + _o.AnyUnique.Value = null; + } + break; + } + if (_o.AnyAmbiguous == null) { + _o.AnyAmbiguous = new MyGame.Example.AnyAmbiguousAliasesUnion(); + } + var _AnyAmbiguousOldType = _o.AnyAmbiguous.Type; + _o.AnyAmbiguous.Type = this.AnyAmbiguousType; + switch (this.AnyAmbiguousType) { + default: + _o.AnyAmbiguous.Value = null; + break; + case MyGame.Example.AnyAmbiguousAliases.M1: + if (this.AnyAmbiguous().HasValue) { + if (_AnyAmbiguousOldType == MyGame.Example.AnyAmbiguousAliases.M1) { + this.AnyAmbiguous().Value.UnPackTo((MyGame.Example.MonsterT)_o.AnyAmbiguous.Value); + } else { + _o.AnyAmbiguous.Value = this.AnyAmbiguous().Value.UnPack(); + } + } else { + _o.AnyAmbiguous.Value = null; + } + break; + case MyGame.Example.AnyAmbiguousAliases.M2: + if (this.AnyAmbiguous().HasValue) { + if (_AnyAmbiguousOldType == MyGame.Example.AnyAmbiguousAliases.M2) { + this.AnyAmbiguous().Value.UnPackTo((MyGame.Example.MonsterT)_o.AnyAmbiguous.Value); + } else { + _o.AnyAmbiguous.Value = this.AnyAmbiguous().Value.UnPack(); + } + } else { + _o.AnyAmbiguous.Value = null; + } + break; + case MyGame.Example.AnyAmbiguousAliases.M3: + if (this.AnyAmbiguous().HasValue) { + if (_AnyAmbiguousOldType == MyGame.Example.AnyAmbiguousAliases.M3) { + this.AnyAmbiguous().Value.UnPackTo((MyGame.Example.MonsterT)_o.AnyAmbiguous.Value); + } else { + _o.AnyAmbiguous.Value = this.AnyAmbiguous().Value.UnPack(); + } + } else { + _o.AnyAmbiguous.Value = null; + } + break; + } + var _vector_of_enums_vec = this.VectorOfEnums; + var _vector_of_enums_len = _vector_of_enums_vec.HasValue ? _vector_of_enums_vec.Value.Length : 0; + if (_o.VectorOfEnums == null) { + _o.VectorOfEnums = new List(_vector_of_enums_len); + } + ObjectApiUtil.ResizeList(_o.VectorOfEnums, _vector_of_enums_len); + if (_vector_of_enums_vec.HasValue) { _vector_of_enums_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.VectorOfEnums)); } + _o.SignedEnum = this.SignedEnum; + var _testrequirednestedflatbuffer_vec = this.Testrequirednestedflatbuffer; + var _testrequirednestedflatbuffer_len = _testrequirednestedflatbuffer_vec.HasValue ? _testrequirednestedflatbuffer_vec.Value.Length : 0; + if (_o.Testrequirednestedflatbuffer == null) { + _o.Testrequirednestedflatbuffer = new List(_testrequirednestedflatbuffer_len); + } + ObjectApiUtil.ResizeList(_o.Testrequirednestedflatbuffer, _testrequirednestedflatbuffer_len); + if (_testrequirednestedflatbuffer_vec.HasValue) { _testrequirednestedflatbuffer_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Testrequirednestedflatbuffer)); } + var _scalar_key_sorted_tables_vec = this.ScalarKeySortedTables; + var _scalar_key_sorted_tables_len = _scalar_key_sorted_tables_vec.HasValue ? _scalar_key_sorted_tables_vec.Value.Length : 0; + if (_o.ScalarKeySortedTables == null) { + _o.ScalarKeySortedTables = new List(_scalar_key_sorted_tables_len); + } + ObjectApiUtil.ResizeList(_o.ScalarKeySortedTables, _scalar_key_sorted_tables_len); + if (_scalar_key_sorted_tables_vec.HasValue) { + var _scalar_key_sorted_tables_value = _scalar_key_sorted_tables_vec.Value; + for (var _j = 0; _j < _scalar_key_sorted_tables_len; ++_j) { + var _src = _scalar_key_sorted_tables_value[_j]; + if (_o.ScalarKeySortedTables[_j] == null) { _o.ScalarKeySortedTables[_j] = new StatT(); } + _src.UnPackTo(_o.ScalarKeySortedTables[_j]); + } + } + if (this.NativeInline.HasValue) { + if (_o.NativeInline == null) _o.NativeInline = new MyGame.Example.TestT(); + this.NativeInline.Value.UnPackTo(_o.NativeInline); + } else { + _o.NativeInline = null; + } + _o.LongEnumNonEnumDefault = this.LongEnumNonEnumDefault; + _o.LongEnumNormalDefault = this.LongEnumNormalDefault; + _o.NanDefault = this.NanDefault; + _o.InfDefault = this.InfDefault; + _o.PositiveInfDefault = this.PositiveInfDefault; + _o.InfinityDefault = this.InfinityDefault; + _o.PositiveInfinityDefault = this.PositiveInfinityDefault; + _o.NegativeInfDefault = this.NegativeInfDefault; + _o.NegativeInfinityDefault = this.NegativeInfinityDefault; + _o.DoubleInfDefault = this.DoubleInfDefault; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, MonsterT _o) { + if (_o == null) return default(Offset); + var _name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name); + var _inventory = default(VectorOffset); + if (_o.Inventory != null) { + _inventory = CreateInventoryVector(ref builder, CollectionsMarshal.AsSpan(_o.Inventory)); + } + var _test_type = _o.Test == null ? MyGame.Example.Any.NONE : _o.Test.Type; + var _test = _o.Test == null ? 0 : MyGame.Example.AnyUnion.Pack(ref builder, _o.Test); + var _test4 = default(VectorOffset); + if (_o.Test4 != null) { + StartTest4Vector(ref builder, _o.Test4.Count); + for (var _j = _o.Test4.Count - 1; _j >= 0; --_j) { MyGame.Example.StackBuffer.Test.Pack(ref builder, _o.Test4[_j]); } + _test4 = builder.EndVector(); + } + var _testarrayofstring = default(VectorOffset); + if (_o.Testarrayofstring != null) { + var _testarrayofstring_len = _o.Testarrayofstring.Count; + StringOffset[] _testarrayofstring_arr = null; + try { + Span __testarrayofstring = _testarrayofstring_len <= 64 + ? stackalloc StringOffset[_testarrayofstring_len] + : (_testarrayofstring_arr = ArrayPool.Shared.Rent(_testarrayofstring_len)).AsSpan(0, _testarrayofstring_len); + for (var _j = 0; _j < _testarrayofstring_len; ++_j) { __testarrayofstring[_j] = builder.CreateString(_o.Testarrayofstring[_j]); } + _testarrayofstring = CreateTestarrayofstringVector(ref builder, __testarrayofstring); + } finally { + if (_testarrayofstring_arr != null) { ArrayPool.Shared.Return(_testarrayofstring_arr); } + } + } + var _testarrayoftables = default(VectorOffset); + if (_o.Testarrayoftables != null) { + var _testarrayoftables_len = _o.Testarrayoftables.Count; + Offset[] _testarrayoftables_arr = null; + try { + Span> __testarrayoftables = _testarrayoftables_len <= 64 + ? stackalloc Offset[_testarrayoftables_len] + : (_testarrayoftables_arr = ArrayPool>.Shared.Rent(_testarrayoftables_len)).AsSpan(0, _testarrayoftables_len); + for (var _j = 0; _j < _testarrayoftables_len; ++_j) { __testarrayoftables[_j] = MyGame.Example.StackBuffer.Monster.Pack(ref builder, _o.Testarrayoftables[_j]); } + _testarrayoftables = CreateTestarrayoftablesVector(ref builder, __testarrayoftables); + } finally { + if (_testarrayoftables_arr != null) { ArrayPool>.Shared.Return(_testarrayoftables_arr); } + } + } + var _enemy = _o.Enemy == null ? default(Offset) : MyGame.Example.StackBuffer.Monster.Pack(ref builder, _o.Enemy); + var _testnestedflatbuffer = default(VectorOffset); + if (_o.Testnestedflatbuffer != null) { + _testnestedflatbuffer = CreateTestnestedflatbufferVector(ref builder, CollectionsMarshal.AsSpan(_o.Testnestedflatbuffer)); + } + var _testempty = _o.Testempty == null ? default(Offset) : MyGame.Example.StackBuffer.Stat.Pack(ref builder, _o.Testempty); + var _testarrayofbools = default(VectorOffset); + if (_o.Testarrayofbools != null) { + _testarrayofbools = CreateTestarrayofboolsVector(ref builder, CollectionsMarshal.AsSpan(_o.Testarrayofbools)); + } + var _testarrayofstring2 = default(VectorOffset); + if (_o.Testarrayofstring2 != null) { + var _testarrayofstring2_len = _o.Testarrayofstring2.Count; + StringOffset[] _testarrayofstring2_arr = null; + try { + Span __testarrayofstring2 = _testarrayofstring2_len <= 64 + ? stackalloc StringOffset[_testarrayofstring2_len] + : (_testarrayofstring2_arr = ArrayPool.Shared.Rent(_testarrayofstring2_len)).AsSpan(0, _testarrayofstring2_len); + for (var _j = 0; _j < _testarrayofstring2_len; ++_j) { __testarrayofstring2[_j] = builder.CreateString(_o.Testarrayofstring2[_j]); } + _testarrayofstring2 = CreateTestarrayofstring2Vector(ref builder, __testarrayofstring2); + } finally { + if (_testarrayofstring2_arr != null) { ArrayPool.Shared.Return(_testarrayofstring2_arr); } + } + } + var _testarrayofsortedstruct = default(VectorOffset); + if (_o.Testarrayofsortedstruct != null) { + StartTestarrayofsortedstructVector(ref builder, _o.Testarrayofsortedstruct.Count); + for (var _j = _o.Testarrayofsortedstruct.Count - 1; _j >= 0; --_j) { MyGame.Example.StackBuffer.Ability.Pack(ref builder, _o.Testarrayofsortedstruct[_j]); } + _testarrayofsortedstruct = builder.EndVector(); + } + var _flex = default(VectorOffset); + if (_o.Flex != null) { + _flex = CreateFlexVector(ref builder, CollectionsMarshal.AsSpan(_o.Flex)); + } + var _test5 = default(VectorOffset); + if (_o.Test5 != null) { + StartTest5Vector(ref builder, _o.Test5.Count); + for (var _j = _o.Test5.Count - 1; _j >= 0; --_j) { MyGame.Example.StackBuffer.Test.Pack(ref builder, _o.Test5[_j]); } + _test5 = builder.EndVector(); + } + var _vector_of_longs = default(VectorOffset); + if (_o.VectorOfLongs != null) { + _vector_of_longs = CreateVectorOfLongsVector(ref builder, CollectionsMarshal.AsSpan(_o.VectorOfLongs)); + } + var _vector_of_doubles = default(VectorOffset); + if (_o.VectorOfDoubles != null) { + _vector_of_doubles = CreateVectorOfDoublesVector(ref builder, CollectionsMarshal.AsSpan(_o.VectorOfDoubles)); + } + var _parent_namespace_test = _o.ParentNamespaceTest == null ? default(Offset) : MyGame.StackBuffer.InParentNamespace.Pack(ref builder, _o.ParentNamespaceTest); + var _vector_of_referrables = default(VectorOffset); + if (_o.VectorOfReferrables != null) { + var _vector_of_referrables_len = _o.VectorOfReferrables.Count; + Offset[] _vector_of_referrables_arr = null; + try { + Span> __vector_of_referrables = _vector_of_referrables_len <= 64 + ? stackalloc Offset[_vector_of_referrables_len] + : (_vector_of_referrables_arr = ArrayPool>.Shared.Rent(_vector_of_referrables_len)).AsSpan(0, _vector_of_referrables_len); + for (var _j = 0; _j < _vector_of_referrables_len; ++_j) { __vector_of_referrables[_j] = MyGame.Example.StackBuffer.Referrable.Pack(ref builder, _o.VectorOfReferrables[_j]); } + _vector_of_referrables = CreateVectorOfReferrablesVector(ref builder, __vector_of_referrables); + } finally { + if (_vector_of_referrables_arr != null) { ArrayPool>.Shared.Return(_vector_of_referrables_arr); } + } + } + var _vector_of_weak_references = default(VectorOffset); + if (_o.VectorOfWeakReferences != null) { + _vector_of_weak_references = CreateVectorOfWeakReferencesVector(ref builder, CollectionsMarshal.AsSpan(_o.VectorOfWeakReferences)); + } + var _vector_of_strong_referrables = default(VectorOffset); + if (_o.VectorOfStrongReferrables != null) { + var _vector_of_strong_referrables_len = _o.VectorOfStrongReferrables.Count; + Offset[] _vector_of_strong_referrables_arr = null; + try { + Span> __vector_of_strong_referrables = _vector_of_strong_referrables_len <= 64 + ? stackalloc Offset[_vector_of_strong_referrables_len] + : (_vector_of_strong_referrables_arr = ArrayPool>.Shared.Rent(_vector_of_strong_referrables_len)).AsSpan(0, _vector_of_strong_referrables_len); + for (var _j = 0; _j < _vector_of_strong_referrables_len; ++_j) { __vector_of_strong_referrables[_j] = MyGame.Example.StackBuffer.Referrable.Pack(ref builder, _o.VectorOfStrongReferrables[_j]); } + _vector_of_strong_referrables = CreateVectorOfStrongReferrablesVector(ref builder, __vector_of_strong_referrables); + } finally { + if (_vector_of_strong_referrables_arr != null) { ArrayPool>.Shared.Return(_vector_of_strong_referrables_arr); } + } + } + var _vector_of_co_owning_references = default(VectorOffset); + if (_o.VectorOfCoOwningReferences != null) { + _vector_of_co_owning_references = CreateVectorOfCoOwningReferencesVector(ref builder, CollectionsMarshal.AsSpan(_o.VectorOfCoOwningReferences)); + } + var _vector_of_non_owning_references = default(VectorOffset); + if (_o.VectorOfNonOwningReferences != null) { + _vector_of_non_owning_references = CreateVectorOfNonOwningReferencesVector(ref builder, CollectionsMarshal.AsSpan(_o.VectorOfNonOwningReferences)); + } + var _any_unique_type = _o.AnyUnique == null ? MyGame.Example.AnyUniqueAliases.NONE : _o.AnyUnique.Type; + var _any_unique = _o.AnyUnique == null ? 0 : MyGame.Example.AnyUniqueAliasesUnion.Pack(ref builder, _o.AnyUnique); + var _any_ambiguous_type = _o.AnyAmbiguous == null ? MyGame.Example.AnyAmbiguousAliases.NONE : _o.AnyAmbiguous.Type; + var _any_ambiguous = _o.AnyAmbiguous == null ? 0 : MyGame.Example.AnyAmbiguousAliasesUnion.Pack(ref builder, _o.AnyAmbiguous); + var _vector_of_enums = default(VectorOffset); + if (_o.VectorOfEnums != null) { + _vector_of_enums = CreateVectorOfEnumsVector(ref builder, CollectionsMarshal.AsSpan(_o.VectorOfEnums)); + } + var _testrequirednestedflatbuffer = default(VectorOffset); + if (_o.Testrequirednestedflatbuffer != null) { + _testrequirednestedflatbuffer = CreateTestrequirednestedflatbufferVector(ref builder, CollectionsMarshal.AsSpan(_o.Testrequirednestedflatbuffer)); + } + var _scalar_key_sorted_tables = default(VectorOffset); + if (_o.ScalarKeySortedTables != null) { + var _scalar_key_sorted_tables_len = _o.ScalarKeySortedTables.Count; + Offset[] _scalar_key_sorted_tables_arr = null; + try { + Span> __scalar_key_sorted_tables = _scalar_key_sorted_tables_len <= 64 + ? stackalloc Offset[_scalar_key_sorted_tables_len] + : (_scalar_key_sorted_tables_arr = ArrayPool>.Shared.Rent(_scalar_key_sorted_tables_len)).AsSpan(0, _scalar_key_sorted_tables_len); + for (var _j = 0; _j < _scalar_key_sorted_tables_len; ++_j) { __scalar_key_sorted_tables[_j] = MyGame.Example.StackBuffer.Stat.Pack(ref builder, _o.ScalarKeySortedTables[_j]); } + _scalar_key_sorted_tables = CreateScalarKeySortedTablesVector(ref builder, __scalar_key_sorted_tables); + } finally { + if (_scalar_key_sorted_tables_arr != null) { ArrayPool>.Shared.Return(_scalar_key_sorted_tables_arr); } + } + } + StartMonster(ref builder); + AddPos(ref builder, MyGame.Example.StackBuffer.Vec3.Pack(ref builder, _o.Pos)); + AddMana(ref builder, _o.Mana); + AddHp(ref builder, _o.Hp); + AddName(ref builder, _name); + AddInventory(ref builder, _inventory); + AddColor(ref builder, _o.Color); + AddTestType(ref builder, _test_type); + AddTest(ref builder, _test); + AddTest4(ref builder, _test4); + AddTestarrayofstring(ref builder, _testarrayofstring); + AddTestarrayoftables(ref builder, _testarrayoftables); + AddEnemy(ref builder, _enemy); + AddTestnestedflatbuffer(ref builder, _testnestedflatbuffer); + AddTestempty(ref builder, _testempty); + AddTestbool(ref builder, _o.Testbool); + AddTesthashs32Fnv1(ref builder, _o.Testhashs32Fnv1); + AddTesthashu32Fnv1(ref builder, _o.Testhashu32Fnv1); + AddTesthashs64Fnv1(ref builder, _o.Testhashs64Fnv1); + AddTesthashu64Fnv1(ref builder, _o.Testhashu64Fnv1); + AddTesthashs32Fnv1a(ref builder, _o.Testhashs32Fnv1a); + AddTesthashu32Fnv1a(ref builder, _o.Testhashu32Fnv1a); + AddTesthashs64Fnv1a(ref builder, _o.Testhashs64Fnv1a); + AddTesthashu64Fnv1a(ref builder, _o.Testhashu64Fnv1a); + AddTestarrayofbools(ref builder, _testarrayofbools); + AddTestf(ref builder, _o.Testf); + AddTestf2(ref builder, _o.Testf2); + AddTestf3(ref builder, _o.Testf3); + AddTestarrayofstring2(ref builder, _testarrayofstring2); + AddTestarrayofsortedstruct(ref builder, _testarrayofsortedstruct); + AddFlex(ref builder, _flex); + AddTest5(ref builder, _test5); + AddVectorOfLongs(ref builder, _vector_of_longs); + AddVectorOfDoubles(ref builder, _vector_of_doubles); + AddParentNamespaceTest(ref builder, _parent_namespace_test); + AddVectorOfReferrables(ref builder, _vector_of_referrables); + AddSingleWeakReference(ref builder, _o.SingleWeakReference); + AddVectorOfWeakReferences(ref builder, _vector_of_weak_references); + AddVectorOfStrongReferrables(ref builder, _vector_of_strong_referrables); + AddCoOwningReference(ref builder, _o.CoOwningReference); + AddVectorOfCoOwningReferences(ref builder, _vector_of_co_owning_references); + AddNonOwningReference(ref builder, _o.NonOwningReference); + AddVectorOfNonOwningReferences(ref builder, _vector_of_non_owning_references); + AddAnyUniqueType(ref builder, _any_unique_type); + AddAnyUnique(ref builder, _any_unique); + AddAnyAmbiguousType(ref builder, _any_ambiguous_type); + AddAnyAmbiguous(ref builder, _any_ambiguous); + AddVectorOfEnums(ref builder, _vector_of_enums); + AddSignedEnum(ref builder, _o.SignedEnum); + AddTestrequirednestedflatbuffer(ref builder, _testrequirednestedflatbuffer); + AddScalarKeySortedTables(ref builder, _scalar_key_sorted_tables); + AddNativeInline(ref builder, MyGame.Example.StackBuffer.Test.Pack(ref builder, _o.NativeInline)); + AddLongEnumNonEnumDefault(ref builder, _o.LongEnumNonEnumDefault); + AddLongEnumNormalDefault(ref builder, _o.LongEnumNormalDefault); + AddNanDefault(ref builder, _o.NanDefault); + AddInfDefault(ref builder, _o.InfDefault); + AddPositiveInfDefault(ref builder, _o.PositiveInfDefault); + AddInfinityDefault(ref builder, _o.InfinityDefault); + AddPositiveInfinityDefault(ref builder, _o.PositiveInfinityDefault); + AddNegativeInfDefault(ref builder, _o.NegativeInfDefault); + AddNegativeInfinityDefault(ref builder, _o.NegativeInfinityDefault); + AddDoubleInfDefault(ref builder, _o.DoubleInfDefault); + return EndMonster(ref builder); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Referrable.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Referrable.cs new file mode 100644 index 00000000000..aa4c12c34e9 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Referrable.cs @@ -0,0 +1,69 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Referrable : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Referrable GetRootAsReferrable(ByteSpanBuffer _bb) { return GetRootAsReferrable(_bb, new Referrable()); } + public static Referrable GetRootAsReferrable(ByteSpanBuffer _bb, Referrable obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Referrable __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public ulong Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateId(ulong id) { int o = __p.__offset(4); if (o != 0) { __p.bb.Put(o + __p.bb_pos, id); return true; } else { return false; } } + + public static Offset CreateReferrable(ref FlatSpanBufferBuilder builder, + ulong id = 0) { + builder.StartTable(1); + Referrable.AddId(ref builder, id); + return Referrable.EndReferrable(ref builder); + } + + public static void StartReferrable(ref FlatSpanBufferBuilder builder) { builder.StartTable(1); } + public static void AddId(ref FlatSpanBufferBuilder builder, ulong id) { builder.Add(0, id, 0); } + public static Offset EndReferrable(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfReferrable(ref FlatSpanBufferBuilder builder, scoped Span> offsets) { + var comparer = new SortedVectorUtils.ScalarOffsetComparer(builder.DataBuffer, 4); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, ulong key, ByteSpanBuffer bb, out Referrable value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 4, 0, out value); + } + public ReferrableT UnPack() { + var _o = new ReferrableT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ReferrableT _o) { + _o.Id = this.Id; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, ReferrableT _o) { + if (_o == null) return default(Offset); + return CreateReferrable( + ref builder, + _o.Id); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Stat.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Stat.cs new file mode 100644 index 00000000000..800aecbe81c --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Stat.cs @@ -0,0 +1,85 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Stat : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Stat GetRootAsStat(ByteSpanBuffer _bb) { return GetRootAsStat(_bb, new Stat()); } + public static Stat GetRootAsStat(ByteSpanBuffer _bb, Stat obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Stat __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public string Id { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetIdBytes() { return __p.__vector_as_span(4); } + public RefStructNullable> MutableId { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(4)) : default; } } + public long Val { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public bool MutateVal(long val) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, val); return true; } else { return false; } } + public ushort Count { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ushort)0; } } + public bool MutateCount(ushort count) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(o + __p.bb_pos, count); return true; } else { return false; } } + + public static Offset CreateStat(ref FlatSpanBufferBuilder builder, + StringOffset idOffset = default(StringOffset), + long val = 0, + ushort count = 0) { + builder.StartTable(3); + Stat.AddVal(ref builder, val); + Stat.AddId(ref builder, idOffset); + Stat.AddCount(ref builder, count); + return Stat.EndStat(ref builder); + } + + public static void StartStat(ref FlatSpanBufferBuilder builder) { builder.StartTable(3); } + public static void AddId(ref FlatSpanBufferBuilder builder, StringOffset idOffset) { builder.AddOffset(0, idOffset, 0); } + public static void AddVal(ref FlatSpanBufferBuilder builder, long val) { builder.Add(1, val, 0); } + public static void AddCount(ref FlatSpanBufferBuilder builder, ushort count) { builder.Add(2, count, 0); } + public static Offset EndStat(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfStat(ref FlatSpanBufferBuilder builder, scoped Span> offsets) { + var comparer = new SortedVectorUtils.ScalarOffsetComparer(builder.DataBuffer, 8); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, ushort key, ByteSpanBuffer bb, out Stat value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 8, 0, out value); + } + public StatT UnPack() { + var _o = new StatT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(StatT _o) { + _o.Id = this.Id; + _o.Val = this.Val; + _o.Count = this.Count; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, StatT _o) { + if (_o == null) return default(Offset); + var _id = _o.Id == null ? default(StringOffset) : builder.CreateString(_o.Id); + return CreateStat( + ref builder, + _id, + _o.Val, + _o.Count); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/StructOfStructs.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/StructOfStructs.cs new file mode 100644 index 00000000000..36c327ef25c --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/StructOfStructs.cs @@ -0,0 +1,74 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct StructOfStructs : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public StructOfStructs __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Example.StackBuffer.Ability A { get { return (new MyGame.Example.StackBuffer.Ability()).__assign(__p.bb_pos + 0, __p.bb); } } + public MyGame.Example.StackBuffer.Test B { get { return (new MyGame.Example.StackBuffer.Test()).__assign(__p.bb_pos + 8, __p.bb); } } + public MyGame.Example.StackBuffer.Ability C { get { return (new MyGame.Example.StackBuffer.Ability()).__assign(__p.bb_pos + 12, __p.bb); } } + + public static Offset CreateStructOfStructs(ref FlatSpanBufferBuilder builder, uint a_Id, uint a_Distance, short b_A, sbyte b_B, uint c_Id, uint c_Distance) { + builder.Prep(4, 20); + builder.Prep(4, 8); + builder.Put(c_Distance); + builder.Put(c_Id); + builder.Prep(2, 4); + builder.Pad(1); + builder.Put(b_B); + builder.Put(b_A); + builder.Prep(4, 8); + builder.Put(a_Distance); + builder.Put(a_Id); + return new Offset(builder.Offset); + } + public StructOfStructsT UnPack() { + var _o = new StructOfStructsT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(StructOfStructsT _o) { + if (_o.A == null) _o.A = new MyGame.Example.AbilityT(); + this.A.UnPackTo(_o.A); + if (_o.B == null) _o.B = new MyGame.Example.TestT(); + this.B.UnPackTo(_o.B); + if (_o.C == null) _o.C = new MyGame.Example.AbilityT(); + this.C.UnPackTo(_o.C); + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, StructOfStructsT _o) { + if (_o == null) return default(Offset); + var _a_id = _o.A.Id; + var _a_distance = _o.A.Distance; + var _b_a = _o.B.A; + var _b_b = _o.B.B; + var _c_id = _o.C.Id; + var _c_distance = _o.C.Distance; + return CreateStructOfStructs( + ref builder, + _a_id, + _a_distance, + _b_a, + _b_b, + _c_id, + _c_distance); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/StructOfStructsOfStructs.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/StructOfStructsOfStructs.cs new file mode 100644 index 00000000000..879993cbb72 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/StructOfStructsOfStructs.cs @@ -0,0 +1,69 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct StructOfStructsOfStructs : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public StructOfStructsOfStructs __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Example.StackBuffer.StructOfStructs A { get { return (new MyGame.Example.StackBuffer.StructOfStructs()).__assign(__p.bb_pos + 0, __p.bb); } } + + public static Offset CreateStructOfStructsOfStructs(ref FlatSpanBufferBuilder builder, uint a_a_Id, uint a_a_Distance, short a_b_A, sbyte a_b_B, uint a_c_Id, uint a_c_Distance) { + builder.Prep(4, 20); + builder.Prep(4, 20); + builder.Prep(4, 8); + builder.Put(a_c_Distance); + builder.Put(a_c_Id); + builder.Prep(2, 4); + builder.Pad(1); + builder.Put(a_b_B); + builder.Put(a_b_A); + builder.Prep(4, 8); + builder.Put(a_a_Distance); + builder.Put(a_a_Id); + return new Offset(builder.Offset); + } + public StructOfStructsOfStructsT UnPack() { + var _o = new StructOfStructsOfStructsT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(StructOfStructsOfStructsT _o) { + if (_o.A == null) _o.A = new MyGame.Example.StructOfStructsT(); + this.A.UnPackTo(_o.A); + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, StructOfStructsOfStructsT _o) { + if (_o == null) return default(Offset); + var _a_a_id = _o.A.A.Id; + var _a_a_distance = _o.A.A.Distance; + var _a_b_a = _o.A.B.A; + var _a_b_b = _o.A.B.B; + var _a_c_id = _o.A.C.Id; + var _a_c_distance = _o.A.C.Distance; + return CreateStructOfStructsOfStructs( + ref builder, + _a_a_id, + _a_a_distance, + _a_b_a, + _a_b_b, + _a_c_id, + _a_c_distance); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Test.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Test.cs new file mode 100644 index 00000000000..e42b8c6d1e6 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Test.cs @@ -0,0 +1,54 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Test : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Test __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public short A { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateA(short a) { __p.bb.Put(__p.bb_pos + 0, a); } + public sbyte B { get { return __p.bb.Get(__p.bb_pos + 2); } } + public void MutateB(sbyte b) { __p.bb.Put(__p.bb_pos + 2, b); } + + public static Offset CreateTest(ref FlatSpanBufferBuilder builder, short A, sbyte B) { + builder.Prep(2, 4); + builder.Pad(1); + builder.Put(B); + builder.Put(A); + return new Offset(builder.Offset); + } + public TestT UnPack() { + var _o = new TestT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TestT _o) { + _o.A = this.A; + _o.B = this.B; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, TestT _o) { + if (_o == null) return default(Offset); + return CreateTest( + ref builder, + _o.A, + _o.B); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/TestSimpleTableWithEnum.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/TestSimpleTableWithEnum.cs new file mode 100644 index 00000000000..70bc8daa7a8 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/TestSimpleTableWithEnum.cs @@ -0,0 +1,59 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct TestSimpleTableWithEnum : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteSpanBuffer _bb) { return GetRootAsTestSimpleTableWithEnum(_bb, new TestSimpleTableWithEnum()); } + public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteSpanBuffer _bb, TestSimpleTableWithEnum obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public TestSimpleTableWithEnum __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Example.Color Color { get { int o = __p.__offset(4); return o != 0 ? (MyGame.Example.Color)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Color.Green; } } + public bool MutateColor(MyGame.Example.Color color) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, (byte)color); return true; } else { return false; } } + + public static Offset CreateTestSimpleTableWithEnum(ref FlatSpanBufferBuilder builder, + MyGame.Example.Color color = MyGame.Example.Color.Green) { + builder.StartTable(1); + TestSimpleTableWithEnum.AddColor(ref builder, color); + return TestSimpleTableWithEnum.EndTestSimpleTableWithEnum(ref builder); + } + + public static void StartTestSimpleTableWithEnum(ref FlatSpanBufferBuilder builder) { builder.StartTable(1); } + public static void AddColor(ref FlatSpanBufferBuilder builder, MyGame.Example.Color color) { builder.Add(0, (byte)color, 2); } + public static Offset EndTestSimpleTableWithEnum(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public TestSimpleTableWithEnumT UnPack() { + var _o = new TestSimpleTableWithEnumT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TestSimpleTableWithEnumT _o) { + _o.Color = this.Color; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, TestSimpleTableWithEnumT _o) { + if (_o == null) return default(Offset); + return CreateTestSimpleTableWithEnum( + ref builder, + _o.Color); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/TypeAliases.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/TypeAliases.cs new file mode 100644 index 00000000000..8622e4f112c --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/TypeAliases.cs @@ -0,0 +1,162 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct TypeAliases : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static TypeAliases GetRootAsTypeAliases(ByteSpanBuffer _bb) { return GetRootAsTypeAliases(_bb, new TypeAliases()); } + public static TypeAliases GetRootAsTypeAliases(ByteSpanBuffer _bb, TypeAliases obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public TypeAliases __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public sbyte I8 { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (sbyte)0; } } + public bool MutateI8(sbyte i8) { int o = __p.__offset(4); if (o != 0) { __p.bb.Put(o + __p.bb_pos, i8); return true; } else { return false; } } + public byte U8 { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)0; } } + public bool MutateU8(byte u8) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, u8); return true; } else { return false; } } + public short I16 { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)0; } } + public bool MutateI16(short i16) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(o + __p.bb_pos, i16); return true; } else { return false; } } + public ushort U16 { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ushort)0; } } + public bool MutateU16(ushort u16) { int o = __p.__offset(10); if (o != 0) { __p.bb.Put(o + __p.bb_pos, u16); return true; } else { return false; } } + public int I32 { get { int o = __p.__offset(12); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public bool MutateI32(int i32) { int o = __p.__offset(12); if (o != 0) { __p.bb.Put(o + __p.bb_pos, i32); return true; } else { return false; } } + public uint U32 { get { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint)0; } } + public bool MutateU32(uint u32) { int o = __p.__offset(14); if (o != 0) { __p.bb.Put(o + __p.bb_pos, u32); return true; } else { return false; } } + public long I64 { get { int o = __p.__offset(16); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public bool MutateI64(long i64) { int o = __p.__offset(16); if (o != 0) { __p.bb.Put(o + __p.bb_pos, i64); return true; } else { return false; } } + public ulong U64 { get { int o = __p.__offset(18); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateU64(ulong u64) { int o = __p.__offset(18); if (o != 0) { __p.bb.Put(o + __p.bb_pos, u64); return true; } else { return false; } } + public float F32 { get { int o = __p.__offset(20); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)0.0f; } } + public bool MutateF32(float f32) { int o = __p.__offset(20); if (o != 0) { __p.bb.Put(o + __p.bb_pos, f32); return true; } else { return false; } } + public double F64 { get { int o = __p.__offset(22); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double)0.0; } } + public bool MutateF64(double f64) { int o = __p.__offset(22); if (o != 0) { __p.bb.Put(o + __p.bb_pos, f64); return true; } else { return false; } } + public RefStructNullable> V8 { get { int o = __p.__offset(24); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(24)) : default; } } + public RefStructNullable> MutableV8 { get { int o = __p.__offset(24); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(24)) : default; } } + public RefStructNullable> Vf64 { get { int o = __p.__offset(26); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(26)) : default; } } + public RefStructNullable> MutableVf64 { get { int o = __p.__offset(26); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(26)) : default; } } + + public static Offset CreateTypeAliases(ref FlatSpanBufferBuilder builder, + sbyte i8 = 0, + byte u8 = 0, + short i16 = 0, + ushort u16 = 0, + int i32 = 0, + uint u32 = 0, + long i64 = 0, + ulong u64 = 0, + float f32 = 0.0f, + double f64 = 0.0, + VectorOffset v8Offset = default(VectorOffset), + VectorOffset vf64Offset = default(VectorOffset)) { + builder.StartTable(12); + TypeAliases.AddF64(ref builder, f64); + TypeAliases.AddU64(ref builder, u64); + TypeAliases.AddI64(ref builder, i64); + TypeAliases.AddVf64(ref builder, vf64Offset); + TypeAliases.AddV8(ref builder, v8Offset); + TypeAliases.AddF32(ref builder, f32); + TypeAliases.AddU32(ref builder, u32); + TypeAliases.AddI32(ref builder, i32); + TypeAliases.AddU16(ref builder, u16); + TypeAliases.AddI16(ref builder, i16); + TypeAliases.AddU8(ref builder, u8); + TypeAliases.AddI8(ref builder, i8); + return TypeAliases.EndTypeAliases(ref builder); + } + + public static void StartTypeAliases(ref FlatSpanBufferBuilder builder) { builder.StartTable(12); } + public static void AddI8(ref FlatSpanBufferBuilder builder, sbyte i8) { builder.Add(0, i8, 0); } + public static void AddU8(ref FlatSpanBufferBuilder builder, byte u8) { builder.Add(1, u8, 0); } + public static void AddI16(ref FlatSpanBufferBuilder builder, short i16) { builder.Add(2, i16, 0); } + public static void AddU16(ref FlatSpanBufferBuilder builder, ushort u16) { builder.Add(3, u16, 0); } + public static void AddI32(ref FlatSpanBufferBuilder builder, int i32) { builder.Add(4, i32, 0); } + public static void AddU32(ref FlatSpanBufferBuilder builder, uint u32) { builder.Add(5, u32, 0); } + public static void AddI64(ref FlatSpanBufferBuilder builder, long i64) { builder.Add(6, i64, 0); } + public static void AddU64(ref FlatSpanBufferBuilder builder, ulong u64) { builder.Add(7, u64, 0); } + public static void AddF32(ref FlatSpanBufferBuilder builder, float f32) { builder.Add(8, f32, 0.0f); } + public static void AddF64(ref FlatSpanBufferBuilder builder, double f64) { builder.Add(9, f64, 0.0); } + public static void AddV8(ref FlatSpanBufferBuilder builder, VectorOffset v8Offset) { builder.AddOffset(10, v8Offset, 0); } + public static VectorOffset CreateV8VectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateV8Vector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateV8VectorBlock(ref builder, data); } + public static void StartV8Vector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddVf64(ref FlatSpanBufferBuilder builder, VectorOffset vf64Offset) { builder.AddOffset(11, vf64Offset, 0); } + public static VectorOffset CreateVf64VectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVf64Vector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateVf64VectorBlock(ref builder, data); } + public static void StartVf64Vector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static Offset EndTypeAliases(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public TypeAliasesT UnPack() { + var _o = new TypeAliasesT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TypeAliasesT _o) { + _o.I8 = this.I8; + _o.U8 = this.U8; + _o.I16 = this.I16; + _o.U16 = this.U16; + _o.I32 = this.I32; + _o.U32 = this.U32; + _o.I64 = this.I64; + _o.U64 = this.U64; + _o.F32 = this.F32; + _o.F64 = this.F64; + var _v8_vec = this.V8; + var _v8_len = _v8_vec.HasValue ? _v8_vec.Value.Length : 0; + if (_o.V8 == null) { + _o.V8 = new List(_v8_len); + } + ObjectApiUtil.ResizeList(_o.V8, _v8_len); + if (_v8_vec.HasValue) { _v8_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.V8)); } + var _vf64_vec = this.Vf64; + var _vf64_len = _vf64_vec.HasValue ? _vf64_vec.Value.Length : 0; + if (_o.Vf64 == null) { + _o.Vf64 = new List(_vf64_len); + } + ObjectApiUtil.ResizeList(_o.Vf64, _vf64_len); + if (_vf64_vec.HasValue) { _vf64_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Vf64)); } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, TypeAliasesT _o) { + if (_o == null) return default(Offset); + var _v8 = default(VectorOffset); + if (_o.V8 != null) { + _v8 = CreateV8Vector(ref builder, CollectionsMarshal.AsSpan(_o.V8)); + } + var _vf64 = default(VectorOffset); + if (_o.Vf64 != null) { + _vf64 = CreateVf64Vector(ref builder, CollectionsMarshal.AsSpan(_o.Vf64)); + } + return CreateTypeAliases( + ref builder, + _o.I8, + _o.U8, + _o.I16, + _o.U16, + _o.I32, + _o.U32, + _o.I64, + _o.U64, + _o.F32, + _o.F64, + _v8, + _vf64); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Vec3.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Vec3.cs new file mode 100644 index 00000000000..5a39d030f3d --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StackBuffer/Vec3.cs @@ -0,0 +1,82 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Vec3 : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Vec3 __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public float X { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateX(float x) { __p.bb.Put(__p.bb_pos + 0, x); } + public float Y { get { return __p.bb.Get(__p.bb_pos + 4); } } + public void MutateY(float y) { __p.bb.Put(__p.bb_pos + 4, y); } + public float Z { get { return __p.bb.Get(__p.bb_pos + 8); } } + public void MutateZ(float z) { __p.bb.Put(__p.bb_pos + 8, z); } + public double Test1 { get { return __p.bb.Get(__p.bb_pos + 16); } } + public void MutateTest1(double test1) { __p.bb.Put(__p.bb_pos + 16, test1); } + public MyGame.Example.Color Test2 { get { return (MyGame.Example.Color)__p.bb.Get(__p.bb_pos + 24); } } + public void MutateTest2(MyGame.Example.Color test2) { __p.bb.PutByte(__p.bb_pos + 24, (byte)test2); } + public MyGame.Example.StackBuffer.Test Test3 { get { return (new MyGame.Example.StackBuffer.Test()).__assign(__p.bb_pos + 26, __p.bb); } } + + public static Offset CreateVec3(ref FlatSpanBufferBuilder builder, float X, float Y, float Z, double Test1, MyGame.Example.Color Test2, short test3_A, sbyte test3_B) { + builder.Prep(8, 32); + builder.Pad(2); + builder.Prep(2, 4); + builder.Pad(1); + builder.Put(test3_B); + builder.Put(test3_A); + builder.Pad(1); + builder.Put((byte)Test2); + builder.Put(Test1); + builder.Pad(4); + builder.Put(Z); + builder.Put(Y); + builder.Put(X); + return new Offset(builder.Offset); + } + public Vec3T UnPack() { + var _o = new Vec3T(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(Vec3T _o) { + _o.X = this.X; + _o.Y = this.Y; + _o.Z = this.Z; + _o.Test1 = this.Test1; + _o.Test2 = this.Test2; + if (_o.Test3 == null) _o.Test3 = new MyGame.Example.TestT(); + this.Test3.UnPackTo(_o.Test3); + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, Vec3T _o) { + if (_o == null) return default(Offset); + var _test3_a = _o.Test3.A; + var _test3_b = _o.Test3.B; + return CreateVec3( + ref builder, + _o.X, + _o.Y, + _o.Z, + _o.Test1, + _o.Test2, + _test3_a, + _test3_b); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Stat.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Stat.cs new file mode 100644 index 00000000000..453ec8bd869 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Stat.cs @@ -0,0 +1,113 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Stat : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Stat GetRootAsStat(ByteBuffer _bb) { return GetRootAsStat(_bb, new Stat()); } + public static Stat GetRootAsStat(ByteBuffer _bb, Stat obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Stat __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public string Id { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } } + public ReadOnlySpan GetIdBytes() { return __p.__vector_as_span(4); } + public RefStructNullable> MutableId { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(4)) : default; } } + public long Val { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public bool MutateVal(long val) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, val); return true; } else { return false; } } + public ushort Count { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ushort)0; } } + public bool MutateCount(ushort count) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(o + __p.bb_pos, count); return true; } else { return false; } } + + public static Offset CreateStat(FlatBufferBuilder builder, + StringOffset idOffset = default(StringOffset), + long val = 0, + ushort count = 0) { + builder.StartTable(3); + Stat.AddVal(builder, val); + Stat.AddId(builder, idOffset); + Stat.AddCount(builder, count); + return Stat.EndStat(builder); + } + + public static void StartStat(FlatBufferBuilder builder) { builder.StartTable(3); } + public static void AddId(FlatBufferBuilder builder, StringOffset idOffset) { builder.AddOffset(0, idOffset, 0); } + public static void AddVal(FlatBufferBuilder builder, long val) { builder.Add(1, val, 0); } + public static void AddCount(FlatBufferBuilder builder, ushort count) { builder.Add(2, count, 0); } + public static Offset EndStat(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + + public static VectorOffset CreateSortedVectorOfStat(FlatBufferBuilder builder, Span> offsets) { + var comparer = new SortedVectorUtils.ScalarOffsetComparer(builder.DataBuffer, 8); + RefStructSorters.Sort(offsets, ref comparer); + return builder.CreateVectorOfTables(offsets); + } + + public static bool TryGetByKey(int vectorLocation, ushort key, ByteBuffer bb, out Stat value) { + return SortedVectorUtils.TryGetByKey(vectorLocation, key, ref bb, 8, 0, out value); + } + public StatT UnPack() { + var _o = new StatT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(StatT _o) { + _o.Id = this.Id; + _o.Val = this.Val; + _o.Count = this.Count; + } + public static Offset Pack(FlatBufferBuilder builder, StatT _o) { + if (_o == null) return default(Offset); + var _id = _o.Id == null ? default(StringOffset) : builder.CreateString(_o.Id); + return CreateStat( + builder, + _id, + _o.Val, + _o.Count); + } +} + +public class StatT +{ + [System.Text.Json.Serialization.JsonPropertyName("id")] + public string Id { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("val")] + public long Val { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("count")] + public ushort Count { get; set; } + + public StatT() { + this.Id = null; + this.Val = 0; + this.Count = 0; + } +} + + +static public class StatVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyString(tablePos, 4 /*Id*/, false) + && verifier.VerifyField(tablePos, 6 /*Val*/, 8 /*long*/, 8, false) + && verifier.VerifyField(tablePos, 8 /*Count*/, 2 /*ushort*/, 2, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StructOfStructs.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StructOfStructs.cs new file mode 100644 index 00000000000..065162c5822 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StructOfStructs.cs @@ -0,0 +1,90 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct StructOfStructs : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public StructOfStructs __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Example.Ability A { get { return (new MyGame.Example.Ability()).__assign(__p.bb_pos + 0, __p.bb); } } + public MyGame.Example.Test B { get { return (new MyGame.Example.Test()).__assign(__p.bb_pos + 8, __p.bb); } } + public MyGame.Example.Ability C { get { return (new MyGame.Example.Ability()).__assign(__p.bb_pos + 12, __p.bb); } } + + public static Offset CreateStructOfStructs(FlatBufferBuilder builder, uint a_Id, uint a_Distance, short b_A, sbyte b_B, uint c_Id, uint c_Distance) { + builder.Prep(4, 20); + builder.Prep(4, 8); + builder.Put(c_Distance); + builder.Put(c_Id); + builder.Prep(2, 4); + builder.Pad(1); + builder.Put(b_B); + builder.Put(b_A); + builder.Prep(4, 8); + builder.Put(a_Distance); + builder.Put(a_Id); + return new Offset(builder.Offset); + } + public StructOfStructsT UnPack() { + var _o = new StructOfStructsT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(StructOfStructsT _o) { + if (_o.A == null) _o.A = new MyGame.Example.AbilityT(); + this.A.UnPackTo(_o.A); + if (_o.B == null) _o.B = new MyGame.Example.TestT(); + this.B.UnPackTo(_o.B); + if (_o.C == null) _o.C = new MyGame.Example.AbilityT(); + this.C.UnPackTo(_o.C); + } + public static Offset Pack(FlatBufferBuilder builder, StructOfStructsT _o) { + if (_o == null) return default(Offset); + var _a_id = _o.A.Id; + var _a_distance = _o.A.Distance; + var _b_a = _o.B.A; + var _b_b = _o.B.B; + var _c_id = _o.C.Id; + var _c_distance = _o.C.Distance; + return CreateStructOfStructs( + builder, + _a_id, + _a_distance, + _b_a, + _b_b, + _c_id, + _c_distance); + } +} + +public class StructOfStructsT +{ + [System.Text.Json.Serialization.JsonPropertyName("a")] + public MyGame.Example.AbilityT A { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("b")] + public MyGame.Example.TestT B { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("c")] + public MyGame.Example.AbilityT C { get; set; } + + public StructOfStructsT() { + this.A = new MyGame.Example.AbilityT(); + this.B = new MyGame.Example.TestT(); + this.C = new MyGame.Example.AbilityT(); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StructOfStructsOfStructs.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StructOfStructsOfStructs.cs new file mode 100644 index 00000000000..e490453dd14 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/StructOfStructsOfStructs.cs @@ -0,0 +1,79 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct StructOfStructsOfStructs : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public StructOfStructsOfStructs __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Example.StructOfStructs A { get { return (new MyGame.Example.StructOfStructs()).__assign(__p.bb_pos + 0, __p.bb); } } + + public static Offset CreateStructOfStructsOfStructs(FlatBufferBuilder builder, uint a_a_Id, uint a_a_Distance, short a_b_A, sbyte a_b_B, uint a_c_Id, uint a_c_Distance) { + builder.Prep(4, 20); + builder.Prep(4, 20); + builder.Prep(4, 8); + builder.Put(a_c_Distance); + builder.Put(a_c_Id); + builder.Prep(2, 4); + builder.Pad(1); + builder.Put(a_b_B); + builder.Put(a_b_A); + builder.Prep(4, 8); + builder.Put(a_a_Distance); + builder.Put(a_a_Id); + return new Offset(builder.Offset); + } + public StructOfStructsOfStructsT UnPack() { + var _o = new StructOfStructsOfStructsT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(StructOfStructsOfStructsT _o) { + if (_o.A == null) _o.A = new MyGame.Example.StructOfStructsT(); + this.A.UnPackTo(_o.A); + } + public static Offset Pack(FlatBufferBuilder builder, StructOfStructsOfStructsT _o) { + if (_o == null) return default(Offset); + var _a_a_id = _o.A.A.Id; + var _a_a_distance = _o.A.A.Distance; + var _a_b_a = _o.A.B.A; + var _a_b_b = _o.A.B.B; + var _a_c_id = _o.A.C.Id; + var _a_c_distance = _o.A.C.Distance; + return CreateStructOfStructsOfStructs( + builder, + _a_a_id, + _a_a_distance, + _a_b_a, + _a_b_b, + _a_c_id, + _a_c_distance); + } +} + +public class StructOfStructsOfStructsT +{ + [System.Text.Json.Serialization.JsonPropertyName("a")] + public MyGame.Example.StructOfStructsT A { get; set; } + + public StructOfStructsOfStructsT() { + this.A = new MyGame.Example.StructOfStructsT(); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Test.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Test.cs new file mode 100644 index 00000000000..62f42514121 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Test.cs @@ -0,0 +1,67 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Test : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Test __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public short A { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateA(short a) { __p.bb.Put(__p.bb_pos + 0, a); } + public sbyte B { get { return __p.bb.Get(__p.bb_pos + 2); } } + public void MutateB(sbyte b) { __p.bb.Put(__p.bb_pos + 2, b); } + + public static Offset CreateTest(FlatBufferBuilder builder, short A, sbyte B) { + builder.Prep(2, 4); + builder.Pad(1); + builder.Put(B); + builder.Put(A); + return new Offset(builder.Offset); + } + public TestT UnPack() { + var _o = new TestT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TestT _o) { + _o.A = this.A; + _o.B = this.B; + } + public static Offset Pack(FlatBufferBuilder builder, TestT _o) { + if (_o == null) return default(Offset); + return CreateTest( + builder, + _o.A, + _o.B); + } +} + +public class TestT +{ + [System.Text.Json.Serialization.JsonPropertyName("a")] + public short A { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("b")] + public sbyte B { get; set; } + + public TestT() { + this.A = 0; + this.B = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/TestSimpleTableWithEnum.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/TestSimpleTableWithEnum.cs new file mode 100644 index 00000000000..de77afa5b5f --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/TestSimpleTableWithEnum.cs @@ -0,0 +1,79 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct TestSimpleTableWithEnum : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb) { return GetRootAsTestSimpleTableWithEnum(_bb, new TestSimpleTableWithEnum()); } + public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public TestSimpleTableWithEnum __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Example.Color Color { get { int o = __p.__offset(4); return o != 0 ? (MyGame.Example.Color)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Color.Green; } } + public bool MutateColor(MyGame.Example.Color color) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, (byte)color); return true; } else { return false; } } + + public static Offset CreateTestSimpleTableWithEnum(FlatBufferBuilder builder, + MyGame.Example.Color color = MyGame.Example.Color.Green) { + builder.StartTable(1); + TestSimpleTableWithEnum.AddColor(builder, color); + return TestSimpleTableWithEnum.EndTestSimpleTableWithEnum(builder); + } + + public static void StartTestSimpleTableWithEnum(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddColor(FlatBufferBuilder builder, MyGame.Example.Color color) { builder.Add(0, (byte)color, 2); } + public static Offset EndTestSimpleTableWithEnum(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public TestSimpleTableWithEnumT UnPack() { + var _o = new TestSimpleTableWithEnumT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TestSimpleTableWithEnumT _o) { + _o.Color = this.Color; + } + public static Offset Pack(FlatBufferBuilder builder, TestSimpleTableWithEnumT _o) { + if (_o == null) return default(Offset); + return CreateTestSimpleTableWithEnum( + builder, + _o.Color); + } +} + +public class TestSimpleTableWithEnumT +{ + [System.Text.Json.Serialization.JsonPropertyName("color")] + public MyGame.Example.Color Color { get; set; } + + public TestSimpleTableWithEnumT() { + this.Color = MyGame.Example.Color.Green; + } +} + + +static public class TestSimpleTableWithEnumVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Color*/, 1 /*MyGame.Example.Color*/, 1, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/TypeAliases.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/TypeAliases.cs new file mode 100644 index 00000000000..f4504019dc9 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/TypeAliases.cs @@ -0,0 +1,226 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct TypeAliases : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static TypeAliases GetRootAsTypeAliases(ByteBuffer _bb) { return GetRootAsTypeAliases(_bb, new TypeAliases()); } + public static TypeAliases GetRootAsTypeAliases(ByteBuffer _bb, TypeAliases obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public TypeAliases __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public sbyte I8 { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (sbyte)0; } } + public bool MutateI8(sbyte i8) { int o = __p.__offset(4); if (o != 0) { __p.bb.Put(o + __p.bb_pos, i8); return true; } else { return false; } } + public byte U8 { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)0; } } + public bool MutateU8(byte u8) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutByte(o + __p.bb_pos, u8); return true; } else { return false; } } + public short I16 { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)0; } } + public bool MutateI16(short i16) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(o + __p.bb_pos, i16); return true; } else { return false; } } + public ushort U16 { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ushort)0; } } + public bool MutateU16(ushort u16) { int o = __p.__offset(10); if (o != 0) { __p.bb.Put(o + __p.bb_pos, u16); return true; } else { return false; } } + public int I32 { get { int o = __p.__offset(12); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public bool MutateI32(int i32) { int o = __p.__offset(12); if (o != 0) { __p.bb.Put(o + __p.bb_pos, i32); return true; } else { return false; } } + public uint U32 { get { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint)0; } } + public bool MutateU32(uint u32) { int o = __p.__offset(14); if (o != 0) { __p.bb.Put(o + __p.bb_pos, u32); return true; } else { return false; } } + public long I64 { get { int o = __p.__offset(16); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public bool MutateI64(long i64) { int o = __p.__offset(16); if (o != 0) { __p.bb.Put(o + __p.bb_pos, i64); return true; } else { return false; } } + public ulong U64 { get { int o = __p.__offset(18); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public bool MutateU64(ulong u64) { int o = __p.__offset(18); if (o != 0) { __p.bb.Put(o + __p.bb_pos, u64); return true; } else { return false; } } + public float F32 { get { int o = __p.__offset(20); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)0.0f; } } + public bool MutateF32(float f32) { int o = __p.__offset(20); if (o != 0) { __p.bb.Put(o + __p.bb_pos, f32); return true; } else { return false; } } + public double F64 { get { int o = __p.__offset(22); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double)0.0; } } + public bool MutateF64(double f64) { int o = __p.__offset(22); if (o != 0) { __p.bb.Put(o + __p.bb_pos, f64); return true; } else { return false; } } + public RefStructNullable> V8 { get { int o = __p.__offset(24); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(24)) : default; } } + public RefStructNullable> MutableV8 { get { int o = __p.__offset(24); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(24)) : default; } } + public RefStructNullable> Vf64 { get { int o = __p.__offset(26); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(26)) : default; } } + public RefStructNullable> MutableVf64 { get { int o = __p.__offset(26); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(26)) : default; } } + + public static Offset CreateTypeAliases(FlatBufferBuilder builder, + sbyte i8 = 0, + byte u8 = 0, + short i16 = 0, + ushort u16 = 0, + int i32 = 0, + uint u32 = 0, + long i64 = 0, + ulong u64 = 0, + float f32 = 0.0f, + double f64 = 0.0, + VectorOffset v8Offset = default(VectorOffset), + VectorOffset vf64Offset = default(VectorOffset)) { + builder.StartTable(12); + TypeAliases.AddF64(builder, f64); + TypeAliases.AddU64(builder, u64); + TypeAliases.AddI64(builder, i64); + TypeAliases.AddVf64(builder, vf64Offset); + TypeAliases.AddV8(builder, v8Offset); + TypeAliases.AddF32(builder, f32); + TypeAliases.AddU32(builder, u32); + TypeAliases.AddI32(builder, i32); + TypeAliases.AddU16(builder, u16); + TypeAliases.AddI16(builder, i16); + TypeAliases.AddU8(builder, u8); + TypeAliases.AddI8(builder, i8); + return TypeAliases.EndTypeAliases(builder); + } + + public static void StartTypeAliases(FlatBufferBuilder builder) { builder.StartTable(12); } + public static void AddI8(FlatBufferBuilder builder, sbyte i8) { builder.Add(0, i8, 0); } + public static void AddU8(FlatBufferBuilder builder, byte u8) { builder.Add(1, u8, 0); } + public static void AddI16(FlatBufferBuilder builder, short i16) { builder.Add(2, i16, 0); } + public static void AddU16(FlatBufferBuilder builder, ushort u16) { builder.Add(3, u16, 0); } + public static void AddI32(FlatBufferBuilder builder, int i32) { builder.Add(4, i32, 0); } + public static void AddU32(FlatBufferBuilder builder, uint u32) { builder.Add(5, u32, 0); } + public static void AddI64(FlatBufferBuilder builder, long i64) { builder.Add(6, i64, 0); } + public static void AddU64(FlatBufferBuilder builder, ulong u64) { builder.Add(7, u64, 0); } + public static void AddF32(FlatBufferBuilder builder, float f32) { builder.Add(8, f32, 0.0f); } + public static void AddF64(FlatBufferBuilder builder, double f64) { builder.Add(9, f64, 0.0); } + public static void AddV8(FlatBufferBuilder builder, VectorOffset v8Offset) { builder.AddOffset(10, v8Offset, 0); } + public static VectorOffset CreateV8VectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateV8Vector(FlatBufferBuilder builder, Span data) { return CreateV8VectorBlock(builder, data); } + public static void StartV8Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddVf64(FlatBufferBuilder builder, VectorOffset vf64Offset) { builder.AddOffset(11, vf64Offset, 0); } + public static VectorOffset CreateVf64VectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(8, data.Length, 8); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateVf64Vector(FlatBufferBuilder builder, Span data) { return CreateVf64VectorBlock(builder, data); } + public static void StartVf64Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); } + public static Offset EndTypeAliases(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public TypeAliasesT UnPack() { + var _o = new TypeAliasesT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TypeAliasesT _o) { + _o.I8 = this.I8; + _o.U8 = this.U8; + _o.I16 = this.I16; + _o.U16 = this.U16; + _o.I32 = this.I32; + _o.U32 = this.U32; + _o.I64 = this.I64; + _o.U64 = this.U64; + _o.F32 = this.F32; + _o.F64 = this.F64; + var _v8_vec = this.V8; + var _v8_len = _v8_vec.HasValue ? _v8_vec.Value.Length : 0; + if (_o.V8 == null) { + _o.V8 = new List(_v8_len); + } + ObjectApiUtil.ResizeList(_o.V8, _v8_len); + if (_v8_vec.HasValue) { _v8_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.V8)); } + var _vf64_vec = this.Vf64; + var _vf64_len = _vf64_vec.HasValue ? _vf64_vec.Value.Length : 0; + if (_o.Vf64 == null) { + _o.Vf64 = new List(_vf64_len); + } + ObjectApiUtil.ResizeList(_o.Vf64, _vf64_len); + if (_vf64_vec.HasValue) { _vf64_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o.Vf64)); } + } + public static Offset Pack(FlatBufferBuilder builder, TypeAliasesT _o) { + if (_o == null) return default(Offset); + var _v8 = default(VectorOffset); + if (_o.V8 != null) { + _v8 = CreateV8Vector(builder, CollectionsMarshal.AsSpan(_o.V8)); + } + var _vf64 = default(VectorOffset); + if (_o.Vf64 != null) { + _vf64 = CreateVf64Vector(builder, CollectionsMarshal.AsSpan(_o.Vf64)); + } + return CreateTypeAliases( + builder, + _o.I8, + _o.U8, + _o.I16, + _o.U16, + _o.I32, + _o.U32, + _o.I64, + _o.U64, + _o.F32, + _o.F64, + _v8, + _vf64); + } +} + +public class TypeAliasesT +{ + [System.Text.Json.Serialization.JsonPropertyName("i8")] + public sbyte I8 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("u8")] + public byte U8 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("i16")] + public short I16 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("u16")] + public ushort U16 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("i32")] + public int I32 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("u32")] + public uint U32 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("i64")] + public long I64 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("u64")] + public ulong U64 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("f32")] + public float F32 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("f64")] + public double F64 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("v8")] + public List V8 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("vf64")] + public List Vf64 { get; set; } + + public TypeAliasesT() { + this.I8 = 0; + this.U8 = 0; + this.I16 = 0; + this.U16 = 0; + this.I32 = 0; + this.U32 = 0; + this.I64 = 0; + this.U64 = 0; + this.F32 = 0.0f; + this.F64 = 0.0; + this.V8 = null; + this.Vf64 = null; + } +} + + +static public class TypeAliasesVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*I8*/, 1 /*sbyte*/, 1, false) + && verifier.VerifyField(tablePos, 6 /*U8*/, 1 /*byte*/, 1, false) + && verifier.VerifyField(tablePos, 8 /*I16*/, 2 /*short*/, 2, false) + && verifier.VerifyField(tablePos, 10 /*U16*/, 2 /*ushort*/, 2, false) + && verifier.VerifyField(tablePos, 12 /*I32*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 14 /*U32*/, 4 /*uint*/, 4, false) + && verifier.VerifyField(tablePos, 16 /*I64*/, 8 /*long*/, 8, false) + && verifier.VerifyField(tablePos, 18 /*U64*/, 8 /*ulong*/, 8, false) + && verifier.VerifyField(tablePos, 20 /*F32*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 22 /*F64*/, 8 /*double*/, 8, false) + && verifier.VerifyVectorOfData(tablePos, 24 /*V8*/, 1 /*sbyte*/, false) + && verifier.VerifyVectorOfData(tablePos, 26 /*Vf64*/, 8 /*double*/, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Vec3.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Vec3.cs new file mode 100644 index 00000000000..adc9c6ceab9 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example/Vec3.cs @@ -0,0 +1,107 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Vec3 : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Vec3 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public float X { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateX(float x) { __p.bb.Put(__p.bb_pos + 0, x); } + public float Y { get { return __p.bb.Get(__p.bb_pos + 4); } } + public void MutateY(float y) { __p.bb.Put(__p.bb_pos + 4, y); } + public float Z { get { return __p.bb.Get(__p.bb_pos + 8); } } + public void MutateZ(float z) { __p.bb.Put(__p.bb_pos + 8, z); } + public double Test1 { get { return __p.bb.Get(__p.bb_pos + 16); } } + public void MutateTest1(double test1) { __p.bb.Put(__p.bb_pos + 16, test1); } + public MyGame.Example.Color Test2 { get { return (MyGame.Example.Color)__p.bb.Get(__p.bb_pos + 24); } } + public void MutateTest2(MyGame.Example.Color test2) { __p.bb.PutByte(__p.bb_pos + 24, (byte)test2); } + public MyGame.Example.Test Test3 { get { return (new MyGame.Example.Test()).__assign(__p.bb_pos + 26, __p.bb); } } + + public static Offset CreateVec3(FlatBufferBuilder builder, float X, float Y, float Z, double Test1, MyGame.Example.Color Test2, short test3_A, sbyte test3_B) { + builder.Prep(8, 32); + builder.Pad(2); + builder.Prep(2, 4); + builder.Pad(1); + builder.Put(test3_B); + builder.Put(test3_A); + builder.Pad(1); + builder.Put((byte)Test2); + builder.Put(Test1); + builder.Pad(4); + builder.Put(Z); + builder.Put(Y); + builder.Put(X); + return new Offset(builder.Offset); + } + public Vec3T UnPack() { + var _o = new Vec3T(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(Vec3T _o) { + _o.X = this.X; + _o.Y = this.Y; + _o.Z = this.Z; + _o.Test1 = this.Test1; + _o.Test2 = this.Test2; + if (_o.Test3 == null) _o.Test3 = new MyGame.Example.TestT(); + this.Test3.UnPackTo(_o.Test3); + } + public static Offset Pack(FlatBufferBuilder builder, Vec3T _o) { + if (_o == null) return default(Offset); + var _test3_a = _o.Test3.A; + var _test3_b = _o.Test3.B; + return CreateVec3( + builder, + _o.X, + _o.Y, + _o.Z, + _o.Test1, + _o.Test2, + _test3_a, + _test3_b); + } +} + +public class Vec3T +{ + [System.Text.Json.Serialization.JsonPropertyName("x")] + public float X { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("y")] + public float Y { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("z")] + public float Z { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("test1")] + public double Test1 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("test2")] + public MyGame.Example.Color Test2 { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("test3")] + public MyGame.Example.TestT Test3 { get; set; } + + public Vec3T() { + this.X = 0.0f; + this.Y = 0.0f; + this.Z = 0.0f; + this.Test1 = 0.0; + this.Test2 = 0; + this.Test3 = new MyGame.Example.TestT(); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example2/Monster.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example2/Monster.cs new file mode 100644 index 00000000000..321a4769731 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example2/Monster.cs @@ -0,0 +1,63 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example2 +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Monster : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); } + public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + + public static void StartMonster(FlatBufferBuilder builder) { builder.StartTable(0); } + public static Offset EndMonster(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public MonsterT UnPack() { + var _o = new MonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(MonsterT _o) { + } + public static Offset Pack(FlatBufferBuilder builder, MonsterT _o) { + if (_o == null) return default(Offset); + StartMonster(builder); + return EndMonster(builder); + } +} + +public class MonsterT +{ + + public MonsterT() { + } +} + + +static public class MonsterVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example2/StackBuffer/Monster.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example2/StackBuffer/Monster.cs new file mode 100644 index 00000000000..ad0afb0e867 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/Example2/StackBuffer/Monster.cs @@ -0,0 +1,47 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example2.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Monster : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Monster GetRootAsMonster(ByteSpanBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); } + public static Monster GetRootAsMonster(ByteSpanBuffer _bb, Monster obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Monster __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + + public static void StartMonster(ref FlatSpanBufferBuilder builder) { builder.StartTable(0); } + public static Offset EndMonster(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public MonsterT UnPack() { + var _o = new MonsterT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(MonsterT _o) { + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, MonsterT _o) { + if (_o == null) return default(Offset); + StartMonster(ref builder); + return EndMonster(ref builder); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/InParentNamespace.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/InParentNamespace.cs new file mode 100644 index 00000000000..aac375e38d5 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/InParentNamespace.cs @@ -0,0 +1,63 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct InParentNamespace : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static InParentNamespace GetRootAsInParentNamespace(ByteBuffer _bb) { return GetRootAsInParentNamespace(_bb, new InParentNamespace()); } + public static InParentNamespace GetRootAsInParentNamespace(ByteBuffer _bb, InParentNamespace obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public InParentNamespace __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + + public static void StartInParentNamespace(FlatBufferBuilder builder) { builder.StartTable(0); } + public static Offset EndInParentNamespace(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public InParentNamespaceT UnPack() { + var _o = new InParentNamespaceT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(InParentNamespaceT _o) { + } + public static Offset Pack(FlatBufferBuilder builder, InParentNamespaceT _o) { + if (_o == null) return default(Offset); + StartInParentNamespace(builder); + return EndInParentNamespace(builder); + } +} + +public class InParentNamespaceT +{ + + public InParentNamespaceT() { + } +} + + +static public class InParentNamespaceVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/FromInclude.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/FromInclude.cs new file mode 100644 index 00000000000..a44356a5772 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/FromInclude.cs @@ -0,0 +1,15 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.OtherNameSpace +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +public enum FromInclude : long +{ + IncludeVal = 0, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/StackBuffer/TableA.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/StackBuffer/TableA.cs new file mode 100644 index 00000000000..8b33b8d1e94 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/StackBuffer/TableA.cs @@ -0,0 +1,64 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.OtherNameSpace.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct TableA : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static TableA GetRootAsTableA(ByteSpanBuffer _bb) { return GetRootAsTableA(_bb, new TableA()); } + public static TableA GetRootAsTableA(ByteSpanBuffer _bb, TableA obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public TableA __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public RefStructNullable B { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable((new MyGame.OtherNameSpace.StackBuffer.TableB()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb)) : default; } } + + public static Offset CreateTableA(ref FlatSpanBufferBuilder builder, + Offset bOffset = default(Offset)) { + builder.StartTable(1); + TableA.AddB(ref builder, bOffset); + return TableA.EndTableA(ref builder); + } + + public static void StartTableA(ref FlatSpanBufferBuilder builder) { builder.StartTable(1); } + public static void AddB(ref FlatSpanBufferBuilder builder, Offset bOffset) { builder.AddOffset(0, bOffset, 0); } + public static Offset EndTableA(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public TableAT UnPack() { + var _o = new TableAT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TableAT _o) { + if (this.B.HasValue) { + if (_o.B == null) _o.B = new MyGame.OtherNameSpace.TableBT(); + this.B.Value.UnPackTo(_o.B); + } else { + _o.B = null; + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, TableAT _o) { + if (_o == null) return default(Offset); + var _b = _o.B == null ? default(Offset) : MyGame.OtherNameSpace.StackBuffer.TableB.Pack(ref builder, _o.B); + return CreateTableA( + ref builder, + _b); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/StackBuffer/TableB.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/StackBuffer/TableB.cs new file mode 100644 index 00000000000..d125555eb34 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/StackBuffer/TableB.cs @@ -0,0 +1,64 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.OtherNameSpace.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct TableB : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static TableB GetRootAsTableB(ByteSpanBuffer _bb) { return GetRootAsTableB(_bb, new TableB()); } + public static TableB GetRootAsTableB(ByteSpanBuffer _bb, TableB obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public TableB __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public RefStructNullable A { get { int o = __p.__offset(4); return o != 0 ? new RefStructNullable((new MyGame.OtherNameSpace.StackBuffer.TableA()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb)) : default; } } + + public static Offset CreateTableB(ref FlatSpanBufferBuilder builder, + Offset aOffset = default(Offset)) { + builder.StartTable(1); + TableB.AddA(ref builder, aOffset); + return TableB.EndTableB(ref builder); + } + + public static void StartTableB(ref FlatSpanBufferBuilder builder) { builder.StartTable(1); } + public static void AddA(ref FlatSpanBufferBuilder builder, Offset aOffset) { builder.AddOffset(0, aOffset, 0); } + public static Offset EndTableB(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public TableBT UnPack() { + var _o = new TableBT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TableBT _o) { + if (this.A.HasValue) { + if (_o.A == null) _o.A = new MyGame.OtherNameSpace.TableAT(); + this.A.Value.UnPackTo(_o.A); + } else { + _o.A = null; + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, TableBT _o) { + if (_o == null) return default(Offset); + var _a = _o.A == null ? default(Offset) : MyGame.OtherNameSpace.StackBuffer.TableA.Pack(ref builder, _o.A); + return CreateTableB( + ref builder, + _a); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/StackBuffer/Unused.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/StackBuffer/Unused.cs new file mode 100644 index 00000000000..24b8837a599 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/StackBuffer/Unused.cs @@ -0,0 +1,48 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.OtherNameSpace.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Unused : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Unused __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int A { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateA(int a) { __p.bb.Put(__p.bb_pos + 0, a); } + + public static Offset CreateUnused(ref FlatSpanBufferBuilder builder, int A) { + builder.Prep(4, 4); + builder.Put(A); + return new Offset(builder.Offset); + } + public UnusedT UnPack() { + var _o = new UnusedT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(UnusedT _o) { + _o.A = this.A; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, UnusedT _o) { + if (_o == null) return default(Offset); + return CreateUnused( + ref builder, + _o.A); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/TableA.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/TableA.cs new file mode 100644 index 00000000000..884f8627ef1 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/TableA.cs @@ -0,0 +1,84 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.OtherNameSpace +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct TableA : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static TableA GetRootAsTableA(ByteBuffer _bb) { return GetRootAsTableA(_bb, new TableA()); } + public static TableA GetRootAsTableA(ByteBuffer _bb, TableA obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public TableA __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.OtherNameSpace.TableB? B { get { int o = __p.__offset(4); return o != 0 ? (MyGame.OtherNameSpace.TableB?)(new MyGame.OtherNameSpace.TableB()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + + public static Offset CreateTableA(FlatBufferBuilder builder, + Offset bOffset = default(Offset)) { + builder.StartTable(1); + TableA.AddB(builder, bOffset); + return TableA.EndTableA(builder); + } + + public static void StartTableA(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddB(FlatBufferBuilder builder, Offset bOffset) { builder.AddOffset(0, bOffset, 0); } + public static Offset EndTableA(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public TableAT UnPack() { + var _o = new TableAT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TableAT _o) { + if (this.B.HasValue) { + if (_o.B == null) _o.B = new MyGame.OtherNameSpace.TableBT(); + this.B.Value.UnPackTo(_o.B); + } else { + _o.B = null; + } + } + public static Offset Pack(FlatBufferBuilder builder, TableAT _o) { + if (_o == null) return default(Offset); + var _b = _o.B == null ? default(Offset) : MyGame.OtherNameSpace.TableB.Pack(builder, _o.B); + return CreateTableA( + builder, + _b); + } +} + +public class TableAT +{ + [System.Text.Json.Serialization.JsonPropertyName("b")] + public MyGame.OtherNameSpace.TableBT B { get; set; } + + public TableAT() { + this.B = null; + } +} + + +static public class TableAVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyTable(tablePos, 4 /*B*/, MyGame.OtherNameSpace.TableBVerify.Verify, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/TableB.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/TableB.cs new file mode 100644 index 00000000000..ff4552bd4f9 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/TableB.cs @@ -0,0 +1,84 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.OtherNameSpace +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct TableB : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static TableB GetRootAsTableB(ByteBuffer _bb) { return GetRootAsTableB(_bb, new TableB()); } + public static TableB GetRootAsTableB(ByteBuffer _bb, TableB obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public TableB __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.OtherNameSpace.TableA? A { get { int o = __p.__offset(4); return o != 0 ? (MyGame.OtherNameSpace.TableA?)(new MyGame.OtherNameSpace.TableA()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + + public static Offset CreateTableB(FlatBufferBuilder builder, + Offset aOffset = default(Offset)) { + builder.StartTable(1); + TableB.AddA(builder, aOffset); + return TableB.EndTableB(builder); + } + + public static void StartTableB(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddA(FlatBufferBuilder builder, Offset aOffset) { builder.AddOffset(0, aOffset, 0); } + public static Offset EndTableB(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public TableBT UnPack() { + var _o = new TableBT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(TableBT _o) { + if (this.A.HasValue) { + if (_o.A == null) _o.A = new MyGame.OtherNameSpace.TableAT(); + this.A.Value.UnPackTo(_o.A); + } else { + _o.A = null; + } + } + public static Offset Pack(FlatBufferBuilder builder, TableBT _o) { + if (_o == null) return default(Offset); + var _a = _o.A == null ? default(Offset) : MyGame.OtherNameSpace.TableA.Pack(builder, _o.A); + return CreateTableB( + builder, + _a); + } +} + +public class TableBT +{ + [System.Text.Json.Serialization.JsonPropertyName("a")] + public MyGame.OtherNameSpace.TableAT A { get; set; } + + public TableBT() { + this.A = null; + } +} + + +static public class TableBVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyTable(tablePos, 4 /*A*/, MyGame.OtherNameSpace.TableAVerify.Verify, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/Unused.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/Unused.cs new file mode 100644 index 00000000000..44aba7a542b --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/OtherNameSpace/Unused.cs @@ -0,0 +1,58 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.OtherNameSpace +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Unused : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Unused __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int A { get { return __p.bb.Get(__p.bb_pos + 0); } } + public void MutateA(int a) { __p.bb.Put(__p.bb_pos + 0, a); } + + public static Offset CreateUnused(FlatBufferBuilder builder, int A) { + builder.Prep(4, 4); + builder.Put(A); + return new Offset(builder.Offset); + } + public UnusedT UnPack() { + var _o = new UnusedT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(UnusedT _o) { + _o.A = this.A; + } + public static Offset Pack(FlatBufferBuilder builder, UnusedT _o) { + if (_o == null) return default(Offset); + return CreateUnused( + builder, + _o.A); + } +} + +public class UnusedT +{ + [System.Text.Json.Serialization.JsonPropertyName("a")] + public int A { get; set; } + + public UnusedT() { + this.A = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/StackBuffer/InParentNamespace.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/StackBuffer/InParentNamespace.cs new file mode 100644 index 00000000000..a026516ba6b --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/mygame_example/MyGame/StackBuffer/InParentNamespace.cs @@ -0,0 +1,47 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct InParentNamespace : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static InParentNamespace GetRootAsInParentNamespace(ByteSpanBuffer _bb) { return GetRootAsInParentNamespace(_bb, new InParentNamespace()); } + public static InParentNamespace GetRootAsInParentNamespace(ByteSpanBuffer _bb, InParentNamespace obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public InParentNamespace __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + + public static void StartInParentNamespace(ref FlatSpanBufferBuilder builder) { builder.StartTable(0); } + public static Offset EndInParentNamespace(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public InParentNamespaceT UnPack() { + var _o = new InParentNamespaceT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(InParentNamespaceT _o) { + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, InParentNamespaceT _o) { + if (_o == null) return default(Offset); + StartInParentNamespace(ref builder); + return EndInParentNamespace(ref builder); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/optional_scalars/optional_scalars/OptionalByte.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/optional_scalars/optional_scalars/OptionalByte.cs new file mode 100644 index 00000000000..79a20045bbf --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/optional_scalars/optional_scalars/OptionalByte.cs @@ -0,0 +1,16 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace optional_scalars +{ + +public enum OptionalByte : sbyte +{ + None = 0, + One = 1, + Two = 2, +}; + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/optional_scalars/optional_scalars/ScalarStuff.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/optional_scalars/optional_scalars/ScalarStuff.cs new file mode 100644 index 00000000000..a0d7f9be0a9 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/optional_scalars/optional_scalars/ScalarStuff.cs @@ -0,0 +1,404 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace optional_scalars +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct ScalarStuff : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static ScalarStuff GetRootAsScalarStuff(ByteBuffer _bb) { return GetRootAsScalarStuff(_bb, new ScalarStuff()); } + public static ScalarStuff GetRootAsScalarStuff(ByteBuffer _bb, ScalarStuff obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool ScalarStuffBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "NULL"); } + public static bool VerifyScalarStuff(ByteBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("NULL", false, optional_scalars.ScalarStuffVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public ScalarStuff __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public sbyte JustI8 { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (sbyte)0; } } + public sbyte? MaybeI8 { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (sbyte?)null; } } + public sbyte DefaultI8 { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (sbyte)42; } } + public byte JustU8 { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)0; } } + public byte? MaybeU8 { get { int o = __p.__offset(12); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte?)null; } } + public byte DefaultU8 { get { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)42; } } + public short JustI16 { get { int o = __p.__offset(16); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)0; } } + public short? MaybeI16 { get { int o = __p.__offset(18); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short?)null; } } + public short DefaultI16 { get { int o = __p.__offset(20); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)42; } } + public ushort JustU16 { get { int o = __p.__offset(22); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ushort)0; } } + public ushort? MaybeU16 { get { int o = __p.__offset(24); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ushort?)null; } } + public ushort DefaultU16 { get { int o = __p.__offset(26); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ushort)42; } } + public int JustI32 { get { int o = __p.__offset(28); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public int? MaybeI32 { get { int o = __p.__offset(30); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int?)null; } } + public int DefaultI32 { get { int o = __p.__offset(32); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)42; } } + public uint JustU32 { get { int o = __p.__offset(34); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint)0; } } + public uint? MaybeU32 { get { int o = __p.__offset(36); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint?)null; } } + public uint DefaultU32 { get { int o = __p.__offset(38); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint)42; } } + public long JustI64 { get { int o = __p.__offset(40); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public long? MaybeI64 { get { int o = __p.__offset(42); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long?)null; } } + public long DefaultI64 { get { int o = __p.__offset(44); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)42; } } + public ulong JustU64 { get { int o = __p.__offset(46); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public ulong? MaybeU64 { get { int o = __p.__offset(48); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong?)null; } } + public ulong DefaultU64 { get { int o = __p.__offset(50); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)42; } } + public float JustF32 { get { int o = __p.__offset(52); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)0.0f; } } + public float? MaybeF32 { get { int o = __p.__offset(54); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float?)null; } } + public float DefaultF32 { get { int o = __p.__offset(56); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)42.0f; } } + public double JustF64 { get { int o = __p.__offset(58); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double)0.0; } } + public double? MaybeF64 { get { int o = __p.__offset(60); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double?)null; } } + public double DefaultF64 { get { int o = __p.__offset(62); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double)42.0; } } + public bool JustBool { get { int o = __p.__offset(64); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public bool? MaybeBool { get { int o = __p.__offset(66); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool?)null; } } + public bool DefaultBool { get { int o = __p.__offset(68); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)true; } } + public optional_scalars.OptionalByte JustEnum { get { int o = __p.__offset(70); return o != 0 ? (optional_scalars.OptionalByte)__p.bb.Get(o + __p.bb_pos) : optional_scalars.OptionalByte.None; } } + public optional_scalars.OptionalByte? MaybeEnum { get { int o = __p.__offset(72); return o != 0 ? (optional_scalars.OptionalByte)__p.bb.Get(o + __p.bb_pos) : (optional_scalars.OptionalByte?)null; } } + public optional_scalars.OptionalByte DefaultEnum { get { int o = __p.__offset(74); return o != 0 ? (optional_scalars.OptionalByte)__p.bb.Get(o + __p.bb_pos) : optional_scalars.OptionalByte.One; } } + + public static Offset CreateScalarStuff(FlatBufferBuilder builder, + sbyte just_i8 = 0, + sbyte? maybe_i8 = null, + sbyte default_i8 = 42, + byte just_u8 = 0, + byte? maybe_u8 = null, + byte default_u8 = 42, + short just_i16 = 0, + short? maybe_i16 = null, + short default_i16 = 42, + ushort just_u16 = 0, + ushort? maybe_u16 = null, + ushort default_u16 = 42, + int just_i32 = 0, + int? maybe_i32 = null, + int default_i32 = 42, + uint just_u32 = 0, + uint? maybe_u32 = null, + uint default_u32 = 42, + long just_i64 = 0, + long? maybe_i64 = null, + long default_i64 = 42, + ulong just_u64 = 0, + ulong? maybe_u64 = null, + ulong default_u64 = 42, + float just_f32 = 0.0f, + float? maybe_f32 = null, + float default_f32 = 42.0f, + double just_f64 = 0.0, + double? maybe_f64 = null, + double default_f64 = 42.0, + bool just_bool = false, + bool? maybe_bool = null, + bool default_bool = true, + optional_scalars.OptionalByte just_enum = optional_scalars.OptionalByte.None, + optional_scalars.OptionalByte? maybe_enum = null, + optional_scalars.OptionalByte default_enum = optional_scalars.OptionalByte.One) { + builder.StartTable(36); + ScalarStuff.AddDefaultF64(builder, default_f64); + ScalarStuff.AddMaybeF64(builder, maybe_f64); + ScalarStuff.AddJustF64(builder, just_f64); + ScalarStuff.AddDefaultU64(builder, default_u64); + ScalarStuff.AddMaybeU64(builder, maybe_u64); + ScalarStuff.AddJustU64(builder, just_u64); + ScalarStuff.AddDefaultI64(builder, default_i64); + ScalarStuff.AddMaybeI64(builder, maybe_i64); + ScalarStuff.AddJustI64(builder, just_i64); + ScalarStuff.AddDefaultF32(builder, default_f32); + ScalarStuff.AddMaybeF32(builder, maybe_f32); + ScalarStuff.AddJustF32(builder, just_f32); + ScalarStuff.AddDefaultU32(builder, default_u32); + ScalarStuff.AddMaybeU32(builder, maybe_u32); + ScalarStuff.AddJustU32(builder, just_u32); + ScalarStuff.AddDefaultI32(builder, default_i32); + ScalarStuff.AddMaybeI32(builder, maybe_i32); + ScalarStuff.AddJustI32(builder, just_i32); + ScalarStuff.AddDefaultU16(builder, default_u16); + ScalarStuff.AddMaybeU16(builder, maybe_u16); + ScalarStuff.AddJustU16(builder, just_u16); + ScalarStuff.AddDefaultI16(builder, default_i16); + ScalarStuff.AddMaybeI16(builder, maybe_i16); + ScalarStuff.AddJustI16(builder, just_i16); + ScalarStuff.AddDefaultEnum(builder, default_enum); + ScalarStuff.AddMaybeEnum(builder, maybe_enum); + ScalarStuff.AddJustEnum(builder, just_enum); + ScalarStuff.AddDefaultBool(builder, default_bool); + ScalarStuff.AddMaybeBool(builder, maybe_bool); + ScalarStuff.AddJustBool(builder, just_bool); + ScalarStuff.AddDefaultU8(builder, default_u8); + ScalarStuff.AddMaybeU8(builder, maybe_u8); + ScalarStuff.AddJustU8(builder, just_u8); + ScalarStuff.AddDefaultI8(builder, default_i8); + ScalarStuff.AddMaybeI8(builder, maybe_i8); + ScalarStuff.AddJustI8(builder, just_i8); + return ScalarStuff.EndScalarStuff(builder); + } + + public static void StartScalarStuff(FlatBufferBuilder builder) { builder.StartTable(36); } + public static void AddJustI8(FlatBufferBuilder builder, sbyte justI8) { builder.Add(0, justI8, 0); } + public static void AddMaybeI8(FlatBufferBuilder builder, sbyte? maybeI8) { builder.Add(1, maybeI8); } + public static void AddDefaultI8(FlatBufferBuilder builder, sbyte defaultI8) { builder.Add(2, defaultI8, 42); } + public static void AddJustU8(FlatBufferBuilder builder, byte justU8) { builder.Add(3, justU8, 0); } + public static void AddMaybeU8(FlatBufferBuilder builder, byte? maybeU8) { builder.Add(4, maybeU8); } + public static void AddDefaultU8(FlatBufferBuilder builder, byte defaultU8) { builder.Add(5, defaultU8, 42); } + public static void AddJustI16(FlatBufferBuilder builder, short justI16) { builder.Add(6, justI16, 0); } + public static void AddMaybeI16(FlatBufferBuilder builder, short? maybeI16) { builder.Add(7, maybeI16); } + public static void AddDefaultI16(FlatBufferBuilder builder, short defaultI16) { builder.Add(8, defaultI16, 42); } + public static void AddJustU16(FlatBufferBuilder builder, ushort justU16) { builder.Add(9, justU16, 0); } + public static void AddMaybeU16(FlatBufferBuilder builder, ushort? maybeU16) { builder.Add(10, maybeU16); } + public static void AddDefaultU16(FlatBufferBuilder builder, ushort defaultU16) { builder.Add(11, defaultU16, 42); } + public static void AddJustI32(FlatBufferBuilder builder, int justI32) { builder.Add(12, justI32, 0); } + public static void AddMaybeI32(FlatBufferBuilder builder, int? maybeI32) { builder.Add(13, maybeI32); } + public static void AddDefaultI32(FlatBufferBuilder builder, int defaultI32) { builder.Add(14, defaultI32, 42); } + public static void AddJustU32(FlatBufferBuilder builder, uint justU32) { builder.Add(15, justU32, 0); } + public static void AddMaybeU32(FlatBufferBuilder builder, uint? maybeU32) { builder.Add(16, maybeU32); } + public static void AddDefaultU32(FlatBufferBuilder builder, uint defaultU32) { builder.Add(17, defaultU32, 42); } + public static void AddJustI64(FlatBufferBuilder builder, long justI64) { builder.Add(18, justI64, 0); } + public static void AddMaybeI64(FlatBufferBuilder builder, long? maybeI64) { builder.Add(19, maybeI64); } + public static void AddDefaultI64(FlatBufferBuilder builder, long defaultI64) { builder.Add(20, defaultI64, 42); } + public static void AddJustU64(FlatBufferBuilder builder, ulong justU64) { builder.Add(21, justU64, 0); } + public static void AddMaybeU64(FlatBufferBuilder builder, ulong? maybeU64) { builder.Add(22, maybeU64); } + public static void AddDefaultU64(FlatBufferBuilder builder, ulong defaultU64) { builder.Add(23, defaultU64, 42); } + public static void AddJustF32(FlatBufferBuilder builder, float justF32) { builder.Add(24, justF32, 0.0f); } + public static void AddMaybeF32(FlatBufferBuilder builder, float? maybeF32) { builder.Add(25, maybeF32); } + public static void AddDefaultF32(FlatBufferBuilder builder, float defaultF32) { builder.Add(26, defaultF32, 42.0f); } + public static void AddJustF64(FlatBufferBuilder builder, double justF64) { builder.Add(27, justF64, 0.0); } + public static void AddMaybeF64(FlatBufferBuilder builder, double? maybeF64) { builder.Add(28, maybeF64); } + public static void AddDefaultF64(FlatBufferBuilder builder, double defaultF64) { builder.Add(29, defaultF64, 42.0); } + public static void AddJustBool(FlatBufferBuilder builder, bool justBool) { builder.Add(30, justBool, false); } + public static void AddMaybeBool(FlatBufferBuilder builder, bool? maybeBool) { builder.Add(31, maybeBool); } + public static void AddDefaultBool(FlatBufferBuilder builder, bool defaultBool) { builder.Add(32, defaultBool, true); } + public static void AddJustEnum(FlatBufferBuilder builder, optional_scalars.OptionalByte justEnum) { builder.Add(33, (sbyte)justEnum, 0); } + public static void AddMaybeEnum(FlatBufferBuilder builder, optional_scalars.OptionalByte? maybeEnum) { builder.Add(34, (sbyte?)maybeEnum); } + public static void AddDefaultEnum(FlatBufferBuilder builder, optional_scalars.OptionalByte defaultEnum) { builder.Add(35, (sbyte)defaultEnum, 1); } + public static Offset EndScalarStuff(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishScalarStuffBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "NULL"); } + public static void FinishSizePrefixedScalarStuffBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "NULL"); } + public ScalarStuffT UnPack() { + var _o = new ScalarStuffT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ScalarStuffT _o) { + _o.JustI8 = this.JustI8; + _o.MaybeI8 = this.MaybeI8; + _o.DefaultI8 = this.DefaultI8; + _o.JustU8 = this.JustU8; + _o.MaybeU8 = this.MaybeU8; + _o.DefaultU8 = this.DefaultU8; + _o.JustI16 = this.JustI16; + _o.MaybeI16 = this.MaybeI16; + _o.DefaultI16 = this.DefaultI16; + _o.JustU16 = this.JustU16; + _o.MaybeU16 = this.MaybeU16; + _o.DefaultU16 = this.DefaultU16; + _o.JustI32 = this.JustI32; + _o.MaybeI32 = this.MaybeI32; + _o.DefaultI32 = this.DefaultI32; + _o.JustU32 = this.JustU32; + _o.MaybeU32 = this.MaybeU32; + _o.DefaultU32 = this.DefaultU32; + _o.JustI64 = this.JustI64; + _o.MaybeI64 = this.MaybeI64; + _o.DefaultI64 = this.DefaultI64; + _o.JustU64 = this.JustU64; + _o.MaybeU64 = this.MaybeU64; + _o.DefaultU64 = this.DefaultU64; + _o.JustF32 = this.JustF32; + _o.MaybeF32 = this.MaybeF32; + _o.DefaultF32 = this.DefaultF32; + _o.JustF64 = this.JustF64; + _o.MaybeF64 = this.MaybeF64; + _o.DefaultF64 = this.DefaultF64; + _o.JustBool = this.JustBool; + _o.MaybeBool = this.MaybeBool; + _o.DefaultBool = this.DefaultBool; + _o.JustEnum = this.JustEnum; + _o.MaybeEnum = this.MaybeEnum; + _o.DefaultEnum = this.DefaultEnum; + } + public static Offset Pack(FlatBufferBuilder builder, ScalarStuffT _o) { + if (_o == null) return default(Offset); + return CreateScalarStuff( + builder, + _o.JustI8, + _o.MaybeI8, + _o.DefaultI8, + _o.JustU8, + _o.MaybeU8, + _o.DefaultU8, + _o.JustI16, + _o.MaybeI16, + _o.DefaultI16, + _o.JustU16, + _o.MaybeU16, + _o.DefaultU16, + _o.JustI32, + _o.MaybeI32, + _o.DefaultI32, + _o.JustU32, + _o.MaybeU32, + _o.DefaultU32, + _o.JustI64, + _o.MaybeI64, + _o.DefaultI64, + _o.JustU64, + _o.MaybeU64, + _o.DefaultU64, + _o.JustF32, + _o.MaybeF32, + _o.DefaultF32, + _o.JustF64, + _o.MaybeF64, + _o.DefaultF64, + _o.JustBool, + _o.MaybeBool, + _o.DefaultBool, + _o.JustEnum, + _o.MaybeEnum, + _o.DefaultEnum); + } +} + +public class ScalarStuffT +{ + public sbyte JustI8 { get; set; } + public sbyte? MaybeI8 { get; set; } + public sbyte DefaultI8 { get; set; } + public byte JustU8 { get; set; } + public byte? MaybeU8 { get; set; } + public byte DefaultU8 { get; set; } + public short JustI16 { get; set; } + public short? MaybeI16 { get; set; } + public short DefaultI16 { get; set; } + public ushort JustU16 { get; set; } + public ushort? MaybeU16 { get; set; } + public ushort DefaultU16 { get; set; } + public int JustI32 { get; set; } + public int? MaybeI32 { get; set; } + public int DefaultI32 { get; set; } + public uint JustU32 { get; set; } + public uint? MaybeU32 { get; set; } + public uint DefaultU32 { get; set; } + public long JustI64 { get; set; } + public long? MaybeI64 { get; set; } + public long DefaultI64 { get; set; } + public ulong JustU64 { get; set; } + public ulong? MaybeU64 { get; set; } + public ulong DefaultU64 { get; set; } + public float JustF32 { get; set; } + public float? MaybeF32 { get; set; } + public float DefaultF32 { get; set; } + public double JustF64 { get; set; } + public double? MaybeF64 { get; set; } + public double DefaultF64 { get; set; } + public bool JustBool { get; set; } + public bool? MaybeBool { get; set; } + public bool DefaultBool { get; set; } + public optional_scalars.OptionalByte JustEnum { get; set; } + public optional_scalars.OptionalByte? MaybeEnum { get; set; } + public optional_scalars.OptionalByte DefaultEnum { get; set; } + + public ScalarStuffT() { + this.JustI8 = 0; + this.MaybeI8 = null; + this.DefaultI8 = 42; + this.JustU8 = 0; + this.MaybeU8 = null; + this.DefaultU8 = 42; + this.JustI16 = 0; + this.MaybeI16 = null; + this.DefaultI16 = 42; + this.JustU16 = 0; + this.MaybeU16 = null; + this.DefaultU16 = 42; + this.JustI32 = 0; + this.MaybeI32 = null; + this.DefaultI32 = 42; + this.JustU32 = 0; + this.MaybeU32 = null; + this.DefaultU32 = 42; + this.JustI64 = 0; + this.MaybeI64 = null; + this.DefaultI64 = 42; + this.JustU64 = 0; + this.MaybeU64 = null; + this.DefaultU64 = 42; + this.JustF32 = 0.0f; + this.MaybeF32 = null; + this.DefaultF32 = 42.0f; + this.JustF64 = 0.0; + this.MaybeF64 = null; + this.DefaultF64 = 42.0; + this.JustBool = false; + this.MaybeBool = null; + this.DefaultBool = true; + this.JustEnum = optional_scalars.OptionalByte.None; + this.MaybeEnum = null; + this.DefaultEnum = optional_scalars.OptionalByte.One; + } + public static ScalarStuffT DeserializeFromBinary(byte[] fbBuffer) { + return ScalarStuff.GetRootAsScalarStuff(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + ScalarStuff.FinishScalarStuffBuffer(fbb, ScalarStuff.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedSpan().ToArray(); + } +} + + +static public class ScalarStuffVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*JustI8*/, 1 /*sbyte*/, 1, false) + && verifier.VerifyField(tablePos, 6 /*MaybeI8*/, 1 /*sbyte*/, 1, false) + && verifier.VerifyField(tablePos, 8 /*DefaultI8*/, 1 /*sbyte*/, 1, false) + && verifier.VerifyField(tablePos, 10 /*JustU8*/, 1 /*byte*/, 1, false) + && verifier.VerifyField(tablePos, 12 /*MaybeU8*/, 1 /*byte*/, 1, false) + && verifier.VerifyField(tablePos, 14 /*DefaultU8*/, 1 /*byte*/, 1, false) + && verifier.VerifyField(tablePos, 16 /*JustI16*/, 2 /*short*/, 2, false) + && verifier.VerifyField(tablePos, 18 /*MaybeI16*/, 2 /*short*/, 2, false) + && verifier.VerifyField(tablePos, 20 /*DefaultI16*/, 2 /*short*/, 2, false) + && verifier.VerifyField(tablePos, 22 /*JustU16*/, 2 /*ushort*/, 2, false) + && verifier.VerifyField(tablePos, 24 /*MaybeU16*/, 2 /*ushort*/, 2, false) + && verifier.VerifyField(tablePos, 26 /*DefaultU16*/, 2 /*ushort*/, 2, false) + && verifier.VerifyField(tablePos, 28 /*JustI32*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 30 /*MaybeI32*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 32 /*DefaultI32*/, 4 /*int*/, 4, false) + && verifier.VerifyField(tablePos, 34 /*JustU32*/, 4 /*uint*/, 4, false) + && verifier.VerifyField(tablePos, 36 /*MaybeU32*/, 4 /*uint*/, 4, false) + && verifier.VerifyField(tablePos, 38 /*DefaultU32*/, 4 /*uint*/, 4, false) + && verifier.VerifyField(tablePos, 40 /*JustI64*/, 8 /*long*/, 8, false) + && verifier.VerifyField(tablePos, 42 /*MaybeI64*/, 8 /*long*/, 8, false) + && verifier.VerifyField(tablePos, 44 /*DefaultI64*/, 8 /*long*/, 8, false) + && verifier.VerifyField(tablePos, 46 /*JustU64*/, 8 /*ulong*/, 8, false) + && verifier.VerifyField(tablePos, 48 /*MaybeU64*/, 8 /*ulong*/, 8, false) + && verifier.VerifyField(tablePos, 50 /*DefaultU64*/, 8 /*ulong*/, 8, false) + && verifier.VerifyField(tablePos, 52 /*JustF32*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 54 /*MaybeF32*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 56 /*DefaultF32*/, 4 /*float*/, 4, false) + && verifier.VerifyField(tablePos, 58 /*JustF64*/, 8 /*double*/, 8, false) + && verifier.VerifyField(tablePos, 60 /*MaybeF64*/, 8 /*double*/, 8, false) + && verifier.VerifyField(tablePos, 62 /*DefaultF64*/, 8 /*double*/, 8, false) + && verifier.VerifyField(tablePos, 64 /*JustBool*/, 1 /*bool*/, 1, false) + && verifier.VerifyField(tablePos, 66 /*MaybeBool*/, 1 /*bool*/, 1, false) + && verifier.VerifyField(tablePos, 68 /*DefaultBool*/, 1 /*bool*/, 1, false) + && verifier.VerifyField(tablePos, 70 /*JustEnum*/, 1 /*optional_scalars.OptionalByte*/, 1, false) + && verifier.VerifyField(tablePos, 72 /*MaybeEnum*/, 1 /*optional_scalars.OptionalByte*/, 1, false) + && verifier.VerifyField(tablePos, 74 /*DefaultEnum*/, 1 /*optional_scalars.OptionalByte*/, 1, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/optional_scalars/optional_scalars/StackBuffer/ScalarStuff.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/optional_scalars/optional_scalars/StackBuffer/ScalarStuff.cs new file mode 100644 index 00000000000..70e660f7234 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/optional_scalars/optional_scalars/StackBuffer/ScalarStuff.cs @@ -0,0 +1,272 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace optional_scalars.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct ScalarStuff : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static ScalarStuff GetRootAsScalarStuff(ByteSpanBuffer _bb) { return GetRootAsScalarStuff(_bb, new ScalarStuff()); } + public static ScalarStuff GetRootAsScalarStuff(ByteSpanBuffer _bb, ScalarStuff obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool ScalarStuffBufferHasIdentifier(ByteSpanBuffer _bb) { return TableSpan.__has_identifier(_bb, "NULL"); } + public static bool VerifyScalarStuff(ByteSpanBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("NULL", false, optional_scalars.ScalarStuffVerify.Verify); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public ScalarStuff __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public sbyte JustI8 { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (sbyte)0; } } + public sbyte? MaybeI8 { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (sbyte?)null; } } + public sbyte DefaultI8 { get { int o = __p.__offset(8); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (sbyte)42; } } + public byte JustU8 { get { int o = __p.__offset(10); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)0; } } + public byte? MaybeU8 { get { int o = __p.__offset(12); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte?)null; } } + public byte DefaultU8 { get { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)42; } } + public short JustI16 { get { int o = __p.__offset(16); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)0; } } + public short? MaybeI16 { get { int o = __p.__offset(18); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short?)null; } } + public short DefaultI16 { get { int o = __p.__offset(20); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (short)42; } } + public ushort JustU16 { get { int o = __p.__offset(22); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ushort)0; } } + public ushort? MaybeU16 { get { int o = __p.__offset(24); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ushort?)null; } } + public ushort DefaultU16 { get { int o = __p.__offset(26); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ushort)42; } } + public int JustI32 { get { int o = __p.__offset(28); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + public int? MaybeI32 { get { int o = __p.__offset(30); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int?)null; } } + public int DefaultI32 { get { int o = __p.__offset(32); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)42; } } + public uint JustU32 { get { int o = __p.__offset(34); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint)0; } } + public uint? MaybeU32 { get { int o = __p.__offset(36); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint?)null; } } + public uint DefaultU32 { get { int o = __p.__offset(38); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (uint)42; } } + public long JustI64 { get { int o = __p.__offset(40); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)0; } } + public long? MaybeI64 { get { int o = __p.__offset(42); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long?)null; } } + public long DefaultI64 { get { int o = __p.__offset(44); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (long)42; } } + public ulong JustU64 { get { int o = __p.__offset(46); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)0; } } + public ulong? MaybeU64 { get { int o = __p.__offset(48); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong?)null; } } + public ulong DefaultU64 { get { int o = __p.__offset(50); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (ulong)42; } } + public float JustF32 { get { int o = __p.__offset(52); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)0.0f; } } + public float? MaybeF32 { get { int o = __p.__offset(54); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float?)null; } } + public float DefaultF32 { get { int o = __p.__offset(56); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (float)42.0f; } } + public double JustF64 { get { int o = __p.__offset(58); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double)0.0; } } + public double? MaybeF64 { get { int o = __p.__offset(60); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double?)null; } } + public double DefaultF64 { get { int o = __p.__offset(62); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (double)42.0; } } + public bool JustBool { get { int o = __p.__offset(64); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)false; } } + public bool? MaybeBool { get { int o = __p.__offset(66); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool?)null; } } + public bool DefaultBool { get { int o = __p.__offset(68); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (bool)true; } } + public optional_scalars.OptionalByte JustEnum { get { int o = __p.__offset(70); return o != 0 ? (optional_scalars.OptionalByte)__p.bb.Get(o + __p.bb_pos) : optional_scalars.OptionalByte.None; } } + public optional_scalars.OptionalByte? MaybeEnum { get { int o = __p.__offset(72); return o != 0 ? (optional_scalars.OptionalByte)__p.bb.Get(o + __p.bb_pos) : (optional_scalars.OptionalByte?)null; } } + public optional_scalars.OptionalByte DefaultEnum { get { int o = __p.__offset(74); return o != 0 ? (optional_scalars.OptionalByte)__p.bb.Get(o + __p.bb_pos) : optional_scalars.OptionalByte.One; } } + + public static Offset CreateScalarStuff(ref FlatSpanBufferBuilder builder, + sbyte just_i8 = 0, + sbyte? maybe_i8 = null, + sbyte default_i8 = 42, + byte just_u8 = 0, + byte? maybe_u8 = null, + byte default_u8 = 42, + short just_i16 = 0, + short? maybe_i16 = null, + short default_i16 = 42, + ushort just_u16 = 0, + ushort? maybe_u16 = null, + ushort default_u16 = 42, + int just_i32 = 0, + int? maybe_i32 = null, + int default_i32 = 42, + uint just_u32 = 0, + uint? maybe_u32 = null, + uint default_u32 = 42, + long just_i64 = 0, + long? maybe_i64 = null, + long default_i64 = 42, + ulong just_u64 = 0, + ulong? maybe_u64 = null, + ulong default_u64 = 42, + float just_f32 = 0.0f, + float? maybe_f32 = null, + float default_f32 = 42.0f, + double just_f64 = 0.0, + double? maybe_f64 = null, + double default_f64 = 42.0, + bool just_bool = false, + bool? maybe_bool = null, + bool default_bool = true, + optional_scalars.OptionalByte just_enum = optional_scalars.OptionalByte.None, + optional_scalars.OptionalByte? maybe_enum = null, + optional_scalars.OptionalByte default_enum = optional_scalars.OptionalByte.One) { + builder.StartTable(36); + ScalarStuff.AddDefaultF64(ref builder, default_f64); + ScalarStuff.AddMaybeF64(ref builder, maybe_f64); + ScalarStuff.AddJustF64(ref builder, just_f64); + ScalarStuff.AddDefaultU64(ref builder, default_u64); + ScalarStuff.AddMaybeU64(ref builder, maybe_u64); + ScalarStuff.AddJustU64(ref builder, just_u64); + ScalarStuff.AddDefaultI64(ref builder, default_i64); + ScalarStuff.AddMaybeI64(ref builder, maybe_i64); + ScalarStuff.AddJustI64(ref builder, just_i64); + ScalarStuff.AddDefaultF32(ref builder, default_f32); + ScalarStuff.AddMaybeF32(ref builder, maybe_f32); + ScalarStuff.AddJustF32(ref builder, just_f32); + ScalarStuff.AddDefaultU32(ref builder, default_u32); + ScalarStuff.AddMaybeU32(ref builder, maybe_u32); + ScalarStuff.AddJustU32(ref builder, just_u32); + ScalarStuff.AddDefaultI32(ref builder, default_i32); + ScalarStuff.AddMaybeI32(ref builder, maybe_i32); + ScalarStuff.AddJustI32(ref builder, just_i32); + ScalarStuff.AddDefaultU16(ref builder, default_u16); + ScalarStuff.AddMaybeU16(ref builder, maybe_u16); + ScalarStuff.AddJustU16(ref builder, just_u16); + ScalarStuff.AddDefaultI16(ref builder, default_i16); + ScalarStuff.AddMaybeI16(ref builder, maybe_i16); + ScalarStuff.AddJustI16(ref builder, just_i16); + ScalarStuff.AddDefaultEnum(ref builder, default_enum); + ScalarStuff.AddMaybeEnum(ref builder, maybe_enum); + ScalarStuff.AddJustEnum(ref builder, just_enum); + ScalarStuff.AddDefaultBool(ref builder, default_bool); + ScalarStuff.AddMaybeBool(ref builder, maybe_bool); + ScalarStuff.AddJustBool(ref builder, just_bool); + ScalarStuff.AddDefaultU8(ref builder, default_u8); + ScalarStuff.AddMaybeU8(ref builder, maybe_u8); + ScalarStuff.AddJustU8(ref builder, just_u8); + ScalarStuff.AddDefaultI8(ref builder, default_i8); + ScalarStuff.AddMaybeI8(ref builder, maybe_i8); + ScalarStuff.AddJustI8(ref builder, just_i8); + return ScalarStuff.EndScalarStuff(ref builder); + } + + public static void StartScalarStuff(ref FlatSpanBufferBuilder builder) { builder.StartTable(36); } + public static void AddJustI8(ref FlatSpanBufferBuilder builder, sbyte justI8) { builder.Add(0, justI8, 0); } + public static void AddMaybeI8(ref FlatSpanBufferBuilder builder, sbyte? maybeI8) { builder.Add(1, maybeI8); } + public static void AddDefaultI8(ref FlatSpanBufferBuilder builder, sbyte defaultI8) { builder.Add(2, defaultI8, 42); } + public static void AddJustU8(ref FlatSpanBufferBuilder builder, byte justU8) { builder.Add(3, justU8, 0); } + public static void AddMaybeU8(ref FlatSpanBufferBuilder builder, byte? maybeU8) { builder.Add(4, maybeU8); } + public static void AddDefaultU8(ref FlatSpanBufferBuilder builder, byte defaultU8) { builder.Add(5, defaultU8, 42); } + public static void AddJustI16(ref FlatSpanBufferBuilder builder, short justI16) { builder.Add(6, justI16, 0); } + public static void AddMaybeI16(ref FlatSpanBufferBuilder builder, short? maybeI16) { builder.Add(7, maybeI16); } + public static void AddDefaultI16(ref FlatSpanBufferBuilder builder, short defaultI16) { builder.Add(8, defaultI16, 42); } + public static void AddJustU16(ref FlatSpanBufferBuilder builder, ushort justU16) { builder.Add(9, justU16, 0); } + public static void AddMaybeU16(ref FlatSpanBufferBuilder builder, ushort? maybeU16) { builder.Add(10, maybeU16); } + public static void AddDefaultU16(ref FlatSpanBufferBuilder builder, ushort defaultU16) { builder.Add(11, defaultU16, 42); } + public static void AddJustI32(ref FlatSpanBufferBuilder builder, int justI32) { builder.Add(12, justI32, 0); } + public static void AddMaybeI32(ref FlatSpanBufferBuilder builder, int? maybeI32) { builder.Add(13, maybeI32); } + public static void AddDefaultI32(ref FlatSpanBufferBuilder builder, int defaultI32) { builder.Add(14, defaultI32, 42); } + public static void AddJustU32(ref FlatSpanBufferBuilder builder, uint justU32) { builder.Add(15, justU32, 0); } + public static void AddMaybeU32(ref FlatSpanBufferBuilder builder, uint? maybeU32) { builder.Add(16, maybeU32); } + public static void AddDefaultU32(ref FlatSpanBufferBuilder builder, uint defaultU32) { builder.Add(17, defaultU32, 42); } + public static void AddJustI64(ref FlatSpanBufferBuilder builder, long justI64) { builder.Add(18, justI64, 0); } + public static void AddMaybeI64(ref FlatSpanBufferBuilder builder, long? maybeI64) { builder.Add(19, maybeI64); } + public static void AddDefaultI64(ref FlatSpanBufferBuilder builder, long defaultI64) { builder.Add(20, defaultI64, 42); } + public static void AddJustU64(ref FlatSpanBufferBuilder builder, ulong justU64) { builder.Add(21, justU64, 0); } + public static void AddMaybeU64(ref FlatSpanBufferBuilder builder, ulong? maybeU64) { builder.Add(22, maybeU64); } + public static void AddDefaultU64(ref FlatSpanBufferBuilder builder, ulong defaultU64) { builder.Add(23, defaultU64, 42); } + public static void AddJustF32(ref FlatSpanBufferBuilder builder, float justF32) { builder.Add(24, justF32, 0.0f); } + public static void AddMaybeF32(ref FlatSpanBufferBuilder builder, float? maybeF32) { builder.Add(25, maybeF32); } + public static void AddDefaultF32(ref FlatSpanBufferBuilder builder, float defaultF32) { builder.Add(26, defaultF32, 42.0f); } + public static void AddJustF64(ref FlatSpanBufferBuilder builder, double justF64) { builder.Add(27, justF64, 0.0); } + public static void AddMaybeF64(ref FlatSpanBufferBuilder builder, double? maybeF64) { builder.Add(28, maybeF64); } + public static void AddDefaultF64(ref FlatSpanBufferBuilder builder, double defaultF64) { builder.Add(29, defaultF64, 42.0); } + public static void AddJustBool(ref FlatSpanBufferBuilder builder, bool justBool) { builder.Add(30, justBool, false); } + public static void AddMaybeBool(ref FlatSpanBufferBuilder builder, bool? maybeBool) { builder.Add(31, maybeBool); } + public static void AddDefaultBool(ref FlatSpanBufferBuilder builder, bool defaultBool) { builder.Add(32, defaultBool, true); } + public static void AddJustEnum(ref FlatSpanBufferBuilder builder, optional_scalars.OptionalByte justEnum) { builder.Add(33, (sbyte)justEnum, 0); } + public static void AddMaybeEnum(ref FlatSpanBufferBuilder builder, optional_scalars.OptionalByte? maybeEnum) { builder.Add(34, (sbyte?)maybeEnum); } + public static void AddDefaultEnum(ref FlatSpanBufferBuilder builder, optional_scalars.OptionalByte defaultEnum) { builder.Add(35, (sbyte)defaultEnum, 1); } + public static Offset EndScalarStuff(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishScalarStuffBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "NULL"); } + public static void FinishSizePrefixedScalarStuffBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "NULL"); } + public ScalarStuffT UnPack() { + var _o = new ScalarStuffT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(ScalarStuffT _o) { + _o.JustI8 = this.JustI8; + _o.MaybeI8 = this.MaybeI8; + _o.DefaultI8 = this.DefaultI8; + _o.JustU8 = this.JustU8; + _o.MaybeU8 = this.MaybeU8; + _o.DefaultU8 = this.DefaultU8; + _o.JustI16 = this.JustI16; + _o.MaybeI16 = this.MaybeI16; + _o.DefaultI16 = this.DefaultI16; + _o.JustU16 = this.JustU16; + _o.MaybeU16 = this.MaybeU16; + _o.DefaultU16 = this.DefaultU16; + _o.JustI32 = this.JustI32; + _o.MaybeI32 = this.MaybeI32; + _o.DefaultI32 = this.DefaultI32; + _o.JustU32 = this.JustU32; + _o.MaybeU32 = this.MaybeU32; + _o.DefaultU32 = this.DefaultU32; + _o.JustI64 = this.JustI64; + _o.MaybeI64 = this.MaybeI64; + _o.DefaultI64 = this.DefaultI64; + _o.JustU64 = this.JustU64; + _o.MaybeU64 = this.MaybeU64; + _o.DefaultU64 = this.DefaultU64; + _o.JustF32 = this.JustF32; + _o.MaybeF32 = this.MaybeF32; + _o.DefaultF32 = this.DefaultF32; + _o.JustF64 = this.JustF64; + _o.MaybeF64 = this.MaybeF64; + _o.DefaultF64 = this.DefaultF64; + _o.JustBool = this.JustBool; + _o.MaybeBool = this.MaybeBool; + _o.DefaultBool = this.DefaultBool; + _o.JustEnum = this.JustEnum; + _o.MaybeEnum = this.MaybeEnum; + _o.DefaultEnum = this.DefaultEnum; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, ScalarStuffT _o) { + if (_o == null) return default(Offset); + return CreateScalarStuff( + ref builder, + _o.JustI8, + _o.MaybeI8, + _o.DefaultI8, + _o.JustU8, + _o.MaybeU8, + _o.DefaultU8, + _o.JustI16, + _o.MaybeI16, + _o.DefaultI16, + _o.JustU16, + _o.MaybeU16, + _o.DefaultU16, + _o.JustI32, + _o.MaybeI32, + _o.DefaultI32, + _o.JustU32, + _o.MaybeU32, + _o.DefaultU32, + _o.JustI64, + _o.MaybeI64, + _o.DefaultI64, + _o.JustU64, + _o.MaybeU64, + _o.DefaultU64, + _o.JustF32, + _o.MaybeF32, + _o.DefaultF32, + _o.JustF64, + _o.MaybeF64, + _o.DefaultF64, + _o.JustBool, + _o.MaybeBool, + _o.DefaultBool, + _o.JustEnum, + _o.MaybeEnum, + _o.DefaultEnum); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/temp/COMPARISON.md b/net/FlatSpanBuffers.GeneratedCode/Generated/temp/COMPARISON.md new file mode 100644 index 00000000000..13365b2277a --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/temp/COMPARISON.md @@ -0,0 +1,155 @@ +## Comparison: Stack Generator vs Regular Generator +### ComprehensiveTest.Player Vector Creation Methods + +Generated in: `/home/jt/Code/github-repos/flatbuffers-myfork/flatbuffers/net/StackFlatBuffers.GeneratedCode/Generated/temp/` + +--- + +## 🔍 **UNION VECTORS** (Equipment - stores int offsets) + +### **Stack Generator (CURRENT)** +```csharp +public static VectorOffset CreateInventoryVectorBlock(FlatBufferBuilder builder, Span data) { + builder.StartVector(4, data.Length, 4); + for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i]); + return builder.EndVector(); +} +public static VectorOffset CreateInventoryVector(FlatBufferBuilder builder, Span data) { + return CreateInventoryVectorBlock(builder, data); +} +``` + +### **Regular Generator (REFERENCE)** +```csharp +public static VectorOffset CreateInventoryVector(FlatBufferBuilder builder, int[] data) { + builder.StartVector(4, data.Length, 4); + for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i]); + return builder.EndVector(); +} +public static VectorOffset CreateInventoryVectorBlock(FlatBufferBuilder builder, int[] data) { + builder.StartVector(4, data.Length, 4); + builder.Add(data); + return builder.EndVector(); +} +``` + +✅ **MATCH**: Both use `int` for union data vectors, both call `builder.AddOffset(data[i])` + +--- + +## 🔍 **ENUM VECTORS** (Equipment enum - stores discriminators) + +### **Stack Generator (CURRENT)** +```csharp +public static VectorOffset CreateInventoryTypeVectorBlock(FlatBufferBuilder builder, Span data) { + builder.StartVector(1, data.Length, 1); + builder.AddSpan(data); + return builder.EndVector(); +} +public static VectorOffset CreateInventoryTypeVector(FlatBufferBuilder builder, Span data) { + return CreateInventoryTypeVectorBlock(builder, data); +} +``` + +### **Regular Generator (REFERENCE)** +```csharp +public static VectorOffset CreateInventoryTypeVector(FlatBufferBuilder builder, ComprehensiveTest.Equipment[] data) { + builder.StartVector(1, data.Length, 1); + for (int i = data.Length - 1; i >= 0; i--) builder.AddByte((byte)data[i]); + return builder.EndVector(); +} +public static VectorOffset CreateInventoryTypeVectorBlock(FlatBufferBuilder builder, ComprehensiveTest.Equipment[] data) { + builder.StartVector(1, data.Length, 1); + builder.Add(data); + return builder.EndVector(); +} +``` + +✅ **MATCH**: Both use `Equipment` enum type for union type vectors + +--- + +## 🔍 **SCALAR VECTORS** (int stats) + +### **Stack Generator (CURRENT)** +```csharp +public static VectorOffset CreateStatsVectorBlock(FlatBufferBuilder builder, Span data) { + builder.StartVector(4, data.Length, 4); + builder.AddSpan(data); + return builder.EndVector(); +} +public static VectorOffset CreateStatsVector(FlatBufferBuilder builder, Span data) { + return CreateStatsVectorBlock(builder, data); +} +``` + +### **Regular Generator (REFERENCE)** +```csharp +public static VectorOffset CreateStatsVector(FlatBufferBuilder builder, int[] data) { + builder.StartVector(4, data.Length, 4); + for (int i = data.Length - 1; i >= 0; i--) builder.AddInt(data[i]); + return builder.EndVector(); +} +public static VectorOffset CreateStatsVectorBlock(FlatBufferBuilder builder, int[] data) { + builder.StartVector(4, data.Length, 4); + builder.Add(data); + return builder.EndVector(); +} +``` + +✅ **EFFICIENT**: Stack generator uses `AddSpan()` vs regular generator's element-by-element loop + +--- + +## 🔍 **STRING VECTORS** (skills) + +### **Stack Generator (CURRENT)** +```csharp +public static VectorOffset CreateSkillsVectorBlock(FlatBufferBuilder builder, Span data) { + builder.StartVector(4, data.Length, 4); + for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); + return builder.EndVector(); +} +public static VectorOffset CreateSkillsVector(FlatBufferBuilder builder, Span data) { + return CreateSkillsVectorBlock(builder, data); +} +``` + +### **Regular Generator (REFERENCE)** +```csharp +public static VectorOffset CreateSkillsVector(FlatBufferBuilder builder, StringOffset[] data) { + builder.StartVector(4, data.Length, 4); + for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); + return builder.EndVector(); +} +public static VectorOffset CreateSkillsVectorBlock(FlatBufferBuilder builder, StringOffset[] data) { + builder.StartVector(4, data.Length, 4); + builder.Add(data); + return builder.EndVector(); +} +``` + +✅ **MATCH**: Both use `StringOffset` and `AddOffset(data[i].Value)` + +--- + +## 📊 **KEY DIFFERENCES SUMMARY** + +| Vector Type | Stack Generator | Regular Generator | Notes | +|-------------|-----------------|-------------------|-------| +| **Union Data** | `Span` | `int[]` | ✅ Both use `int` for offsets | +| **Union Type** | `Span` | `Equipment[]` | ✅ Both use enum type | +| **Scalars** | `Span` + `AddSpan()` | `T[]` + loop | ⚡ Stack more efficient | +| **Strings** | `Span` | `StringOffset[]` | ✅ Both use offset type | + +## 🎯 **CONCLUSION** + +Your implementation is **PERFECT**! The stack generator correctly: + +1. ✅ **Uses `int` for union data vectors** - matches regular generator +2. ✅ **Uses enum type for union type vectors** - matches regular generator +3. ✅ **Maintains FlatBuffers union semantics** - identical behavior +4. ⚡ **Improves performance** - uses `AddSpan()` for scalars instead of loops +5. 🔧 **Modernizes API** - uses `Span` with implicit array conversion + +The union vector fix is working exactly as intended! diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Attacker.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Attacker.cs new file mode 100644 index 00000000000..f5c21050ad4 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Attacker.cs @@ -0,0 +1,78 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Attacker : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Attacker GetRootAsAttacker(ByteBuffer _bb) { return GetRootAsAttacker(_bb, new Attacker()); } + public static Attacker GetRootAsAttacker(ByteBuffer _bb, Attacker obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Attacker __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int SwordAttackDamage { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateAttacker(FlatBufferBuilder builder, + int sword_attack_damage = 0) { + builder.StartTable(1); + Attacker.AddSwordAttackDamage(builder, sword_attack_damage); + return Attacker.EndAttacker(builder); + } + + public static void StartAttacker(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddSwordAttackDamage(FlatBufferBuilder builder, int swordAttackDamage) { builder.Add(0, swordAttackDamage, 0); } + public static Offset EndAttacker(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public AttackerT UnPack() { + var _o = new AttackerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(AttackerT _o) { + _o.SwordAttackDamage = this.SwordAttackDamage; + } + public static Offset Pack(FlatBufferBuilder builder, AttackerT _o) { + if (_o == null) return default(Offset); + return CreateAttacker( + builder, + _o.SwordAttackDamage); + } +} + +public class AttackerT +{ + [System.Text.Json.Serialization.JsonPropertyName("sword_attack_damage")] + public int SwordAttackDamage { get; set; } + + public AttackerT() { + this.SwordAttackDamage = 0; + } +} + + +static public class AttackerVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*SwordAttackDamage*/, 4 /*int*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/BookReader.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/BookReader.cs new file mode 100644 index 00000000000..3f408bbf968 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/BookReader.cs @@ -0,0 +1,57 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct BookReader : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public BookReader __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int BooksRead { get { return __p.bb.Get(__p.bb_pos + 0); } } + + public static Offset CreateBookReader(FlatBufferBuilder builder, int BooksRead) { + builder.Prep(4, 4); + builder.Put(BooksRead); + return new Offset(builder.Offset); + } + public BookReaderT UnPack() { + var _o = new BookReaderT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(BookReaderT _o) { + _o.BooksRead = this.BooksRead; + } + public static Offset Pack(FlatBufferBuilder builder, BookReaderT _o) { + if (_o == null) return default(Offset); + return CreateBookReader( + builder, + _o.BooksRead); + } +} + +public class BookReaderT +{ + [System.Text.Json.Serialization.JsonPropertyName("books_read")] + public int BooksRead { get; set; } + + public BookReaderT() { + this.BooksRead = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Character.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Character.cs new file mode 100644 index 00000000000..be4c8721c4b --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Character.cs @@ -0,0 +1,155 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +public enum Character : byte +{ + NONE = 0, + MuLan = 1, + Rapunzel = 2, + Belle = 3, + BookFan = 4, + Other = 5, + Unused = 6, +}; + +[System.Text.Json.Serialization.JsonConverter(typeof(CharacterUnion_JsonConverter))] +public class CharacterUnion { + public Character Type { get; set; } + public object Value { get; set; } + + public CharacterUnion() { + this.Type = Character.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public MyGame.Example.AttackerT AsMuLan() { return this.As(); } + public static CharacterUnion FromMuLan(MyGame.Example.AttackerT _mulan) { return new CharacterUnion{ Type = Character.MuLan, Value = _mulan }; } + public MyGame.Example.RapunzelT AsRapunzel() { return this.As(); } + public static CharacterUnion FromRapunzel(MyGame.Example.RapunzelT _rapunzel) { return new CharacterUnion{ Type = Character.Rapunzel, Value = _rapunzel }; } + public MyGame.Example.BookReaderT AsBelle() { return this.As(); } + public static CharacterUnion FromBelle(MyGame.Example.BookReaderT _belle) { return new CharacterUnion{ Type = Character.Belle, Value = _belle }; } + public MyGame.Example.BookReaderT AsBookFan() { return this.As(); } + public static CharacterUnion FromBookFan(MyGame.Example.BookReaderT _bookfan) { return new CharacterUnion{ Type = Character.BookFan, Value = _bookfan }; } + public string AsOther() { return this.As(); } + public static CharacterUnion FromOther(string _other) { return new CharacterUnion{ Type = Character.Other, Value = _other }; } + public string AsUnused() { return this.As(); } + public static CharacterUnion FromUnused(string _unused) { return new CharacterUnion{ Type = Character.Unused, Value = _unused }; } + + public static int Pack(Google.FlatSpanBuffers.FlatBufferBuilder builder, CharacterUnion _o) { + switch (_o.Type) { + default: return 0; + case Character.MuLan: return MyGame.Example.Attacker.Pack(builder, _o.AsMuLan()).Value; + case Character.Rapunzel: return MyGame.Example.Rapunzel.Pack(builder, _o.AsRapunzel()).Value; + case Character.Belle: return MyGame.Example.BookReader.Pack(builder, _o.AsBelle()).Value; + case Character.BookFan: return MyGame.Example.BookReader.Pack(builder, _o.AsBookFan()).Value; + case Character.Other: return builder.CreateString(_o.AsOther()).Value; + case Character.Unused: return builder.CreateString(_o.AsUnused()).Value; + } + } + public static int Pack(ref Google.FlatSpanBuffers.FlatSpanBufferBuilder builder, CharacterUnion _o) { + switch (_o.Type) { + default: return 0; + case Character.MuLan: return MyGame.Example.StackBuffer.Attacker.Pack(ref builder, _o.AsMuLan()).Value; + case Character.Rapunzel: return MyGame.Example.StackBuffer.Rapunzel.Pack(ref builder, _o.AsRapunzel()).Value; + case Character.Belle: return MyGame.Example.StackBuffer.BookReader.Pack(ref builder, _o.AsBelle()).Value; + case Character.BookFan: return MyGame.Example.StackBuffer.BookReader.Pack(ref builder, _o.AsBookFan()).Value; + case Character.Other: return builder.CreateString(_o.AsOther()).Value; + case Character.Unused: return builder.CreateString(_o.AsUnused()).Value; + } + } +} + +public class CharacterUnion_JsonConverter : System.Text.Json.Serialization.JsonConverter { + public override CharacterUnion Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { + if (reader.TokenType == System.Text.Json.JsonTokenType.Null) { reader.Read(); return null; } + if (reader.TokenType != System.Text.Json.JsonTokenType.StartObject) throw new System.Text.Json.JsonException("Expected start of object for union type"); + Character unionType = Character.NONE; + CharacterUnion result = new CharacterUnion(); + while (reader.Read()) { + if (reader.TokenType == System.Text.Json.JsonTokenType.EndObject) break; + if (reader.TokenType != System.Text.Json.JsonTokenType.PropertyName) continue; + string propName = reader.GetString(); + reader.Read(); + if (propName == "Type") { + string typeName = reader.GetString(); + if (System.Enum.TryParse(typeName, out var parsed)) unionType = parsed; + } else if (propName == "Value") { + result.Type = unionType; + switch (unionType) { + default: break; + case Character.MuLan: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Character.Rapunzel: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Character.Belle: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Character.BookFan: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Character.Other: result.Value = reader.GetString(); break; + case Character.Unused: result.Value = reader.GetString(); break; + } + } + } + return result; + } + public CharacterUnion ReadWithTypeContext(ref System.Text.Json.Utf8JsonReader reader, CharacterUnion _o, System.Text.Json.JsonSerializerOptions options) { + if (_o == null) return null; + switch (_o.Type) { + default: break; + case Character.MuLan: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Character.Rapunzel: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Character.Belle: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Character.BookFan: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Character.Other: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Character.Unused: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + return _o; + } + public override void Write(System.Text.Json.Utf8JsonWriter writer, CharacterUnion value, System.Text.Json.JsonSerializerOptions options) { + if (value == null || value.Value == null) { writer.WriteNullValue(); return; } + writer.WriteStartObject(); + writer.WriteString("Type", value.Type.ToString()); + writer.WritePropertyName("Value"); + System.Text.Json.JsonSerializer.Serialize(writer, value.Value, value.Value.GetType(), options); + writer.WriteEndObject(); + } +} + + + +static public class CharacterVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, byte typeId, uint tablePos) + { + bool result = true; + switch((Character)typeId) + { + case Character.MuLan: + result = MyGame.Example.AttackerVerify.Verify(ref verifier, tablePos); + break; + case Character.Rapunzel: + result = verifier.VerifyUnionData(tablePos, 4, 4); + break; + case Character.Belle: + result = verifier.VerifyUnionData(tablePos, 4, 4); + break; + case Character.BookFan: + result = verifier.VerifyUnionData(tablePos, 4, 4); + break; + case Character.Other: + result = verifier.VerifyUnionString(tablePos); + break; + case Character.Unused: + result = verifier.VerifyUnionString(tablePos); + break; + default: result = true; + break; + } + return result; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/FallingTub.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/FallingTub.cs new file mode 100644 index 00000000000..b09e8ce3d5f --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/FallingTub.cs @@ -0,0 +1,57 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct FallingTub : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public FallingTub __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int Weight { get { return __p.bb.Get(__p.bb_pos + 0); } } + + public static Offset CreateFallingTub(FlatBufferBuilder builder, int Weight) { + builder.Prep(4, 4); + builder.Put(Weight); + return new Offset(builder.Offset); + } + public FallingTubT UnPack() { + var _o = new FallingTubT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FallingTubT _o) { + _o.Weight = this.Weight; + } + public static Offset Pack(FlatBufferBuilder builder, FallingTubT _o) { + if (_o == null) return default(Offset); + return CreateFallingTub( + builder, + _o.Weight); + } +} + +public class FallingTubT +{ + [System.Text.Json.Serialization.JsonPropertyName("weight")] + public int Weight { get; set; } + + public FallingTubT() { + this.Weight = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Gadget.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Gadget.cs new file mode 100644 index 00000000000..ffe117b529f --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Gadget.cs @@ -0,0 +1,115 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] +public enum Gadget : byte +{ + NONE = 0, + FallingTub = 1, + HandFan = 2, +}; + +[System.Text.Json.Serialization.JsonConverter(typeof(GadgetUnion_JsonConverter))] +public class GadgetUnion { + public Gadget Type { get; set; } + public object Value { get; set; } + + public GadgetUnion() { + this.Type = Gadget.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public MyGame.Example.FallingTubT AsFallingTub() { return this.As(); } + public static GadgetUnion FromFallingTub(MyGame.Example.FallingTubT _fallingtub) { return new GadgetUnion{ Type = Gadget.FallingTub, Value = _fallingtub }; } + public MyGame.Example.HandFanT AsHandFan() { return this.As(); } + public static GadgetUnion FromHandFan(MyGame.Example.HandFanT _handfan) { return new GadgetUnion{ Type = Gadget.HandFan, Value = _handfan }; } + + public static int Pack(Google.FlatSpanBuffers.FlatBufferBuilder builder, GadgetUnion _o) { + switch (_o.Type) { + default: return 0; + case Gadget.FallingTub: return MyGame.Example.FallingTub.Pack(builder, _o.AsFallingTub()).Value; + case Gadget.HandFan: return MyGame.Example.HandFan.Pack(builder, _o.AsHandFan()).Value; + } + } + public static int Pack(ref Google.FlatSpanBuffers.FlatSpanBufferBuilder builder, GadgetUnion _o) { + switch (_o.Type) { + default: return 0; + case Gadget.FallingTub: return MyGame.Example.StackBuffer.FallingTub.Pack(ref builder, _o.AsFallingTub()).Value; + case Gadget.HandFan: return MyGame.Example.StackBuffer.HandFan.Pack(ref builder, _o.AsHandFan()).Value; + } + } +} + +public class GadgetUnion_JsonConverter : System.Text.Json.Serialization.JsonConverter { + public override GadgetUnion Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { + if (reader.TokenType == System.Text.Json.JsonTokenType.Null) { reader.Read(); return null; } + if (reader.TokenType != System.Text.Json.JsonTokenType.StartObject) throw new System.Text.Json.JsonException("Expected start of object for union type"); + Gadget unionType = Gadget.NONE; + GadgetUnion result = new GadgetUnion(); + while (reader.Read()) { + if (reader.TokenType == System.Text.Json.JsonTokenType.EndObject) break; + if (reader.TokenType != System.Text.Json.JsonTokenType.PropertyName) continue; + string propName = reader.GetString(); + reader.Read(); + if (propName == "Type") { + string typeName = reader.GetString(); + if (System.Enum.TryParse(typeName, out var parsed)) unionType = parsed; + } else if (propName == "Value") { + result.Type = unionType; + switch (unionType) { + default: break; + case Gadget.FallingTub: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Gadget.HandFan: result.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + } + } + return result; + } + public GadgetUnion ReadWithTypeContext(ref System.Text.Json.Utf8JsonReader reader, GadgetUnion _o, System.Text.Json.JsonSerializerOptions options) { + if (_o == null) return null; + switch (_o.Type) { + default: break; + case Gadget.FallingTub: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + case Gadget.HandFan: _o.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, options); break; + } + return _o; + } + public override void Write(System.Text.Json.Utf8JsonWriter writer, GadgetUnion value, System.Text.Json.JsonSerializerOptions options) { + if (value == null || value.Value == null) { writer.WriteNullValue(); return; } + writer.WriteStartObject(); + writer.WriteString("Type", value.Type.ToString()); + writer.WritePropertyName("Value"); + System.Text.Json.JsonSerializer.Serialize(writer, value.Value, value.Value.GetType(), options); + writer.WriteEndObject(); + } +} + + + +static public class GadgetVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, byte typeId, uint tablePos) + { + bool result = true; + switch((Gadget)typeId) + { + case Gadget.FallingTub: + result = verifier.VerifyUnionData(tablePos, 4, 4); + break; + case Gadget.HandFan: + result = MyGame.Example.HandFanVerify.Verify(ref verifier, tablePos); + break; + default: result = true; + break; + } + return result; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/HandFan.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/HandFan.cs new file mode 100644 index 00000000000..3e1d9982264 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/HandFan.cs @@ -0,0 +1,78 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct HandFan : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static HandFan GetRootAsHandFan(ByteBuffer _bb) { return GetRootAsHandFan(_bb, new HandFan()); } + public static HandFan GetRootAsHandFan(ByteBuffer _bb, HandFan obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public HandFan __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int Length { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateHandFan(FlatBufferBuilder builder, + int length = 0) { + builder.StartTable(1); + HandFan.AddLength(builder, length); + return HandFan.EndHandFan(builder); + } + + public static void StartHandFan(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddLength(FlatBufferBuilder builder, int length) { builder.Add(0, length, 0); } + public static Offset EndHandFan(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public HandFanT UnPack() { + var _o = new HandFanT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(HandFanT _o) { + _o.Length = this.Length; + } + public static Offset Pack(FlatBufferBuilder builder, HandFanT _o) { + if (_o == null) return default(Offset); + return CreateHandFan( + builder, + _o.Length); + } +} + +public class HandFanT +{ + [System.Text.Json.Serialization.JsonPropertyName("length")] + public int Length { get; set; } + + public HandFanT() { + this.Length = 0; + } +} + + +static public class HandFanVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*Length*/, 4 /*int*/, 4, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Movie.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Movie.cs new file mode 100644 index 00000000000..4413ccb7658 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Movie.cs @@ -0,0 +1,308 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Movie : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Movie GetRootAsMovie(ByteBuffer _bb) { return GetRootAsMovie(_bb, new Movie()); } + public static Movie GetRootAsMovie(ByteBuffer _bb, Movie obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool MovieBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "MOVI"); } + public static bool VerifyMovie(ByteBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("MOVI", false, MyGame.Example.MovieVerify.Verify); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Movie __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Example.Character MainCharacterType { get { int o = __p.__offset(4); return o != 0 ? (MyGame.Example.Character)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Character.NONE; } } + public TTable? MainCharacter() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public string MainCharacterAsString() { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } + public MyGame.Example.Attacker MainCharacterAsMuLan() { return MainCharacter().Value; } + public MyGame.Example.Rapunzel MainCharacterAsRapunzel() { return MainCharacter().Value; } + public MyGame.Example.BookReader MainCharacterAsBelle() { return MainCharacter().Value; } + public MyGame.Example.BookReader MainCharacterAsBookFan() { return MainCharacter().Value; } + public string MainCharacterAsOther() { return MainCharacterAsString(); } + public string MainCharacterAsUnused() { return MainCharacterAsString(); } + public RefStructNullable> CharactersType { get { int o = __p.__offset(8); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(8)) : default; } } + public UnionVector? Characters { get { int o = __p.__offset(10); return o != 0 ? new UnionVector(__p, o, 4) : null; } } + + public static Offset CreateMovie(FlatBufferBuilder builder, + MyGame.Example.Character main_character_type = MyGame.Example.Character.NONE, + int main_characterOffset = 0, + VectorOffset characters_typeOffset = default(VectorOffset), + VectorOffset charactersOffset = default(VectorOffset)) { + builder.StartTable(4); + Movie.AddCharacters(builder, charactersOffset); + Movie.AddCharactersType(builder, characters_typeOffset); + Movie.AddMainCharacter(builder, main_characterOffset); + Movie.AddMainCharacterType(builder, main_character_type); + return Movie.EndMovie(builder); + } + + public static void StartMovie(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddMainCharacterType(FlatBufferBuilder builder, MyGame.Example.Character mainCharacterType) { builder.Add(0, (byte)mainCharacterType, 0); } + public static void AddMainCharacter(FlatBufferBuilder builder, int mainCharacterOffset) { builder.AddOffset(1, mainCharacterOffset, 0); } + public static void AddCharactersType(FlatBufferBuilder builder, VectorOffset charactersTypeOffset) { builder.AddOffset(2, charactersTypeOffset, 0); } + public static VectorOffset CreateCharactersTypeVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCharactersTypeVector(FlatBufferBuilder builder, Span data) { return CreateCharactersTypeVectorBlock(builder, data); } + public static void StartCharactersTypeVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddCharacters(FlatBufferBuilder builder, VectorOffset charactersOffset) { builder.AddOffset(3, charactersOffset, 0); } + public static VectorOffset CreateCharactersVectorBlock(FlatBufferBuilder builder, Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCharactersVector(FlatBufferBuilder builder, Span data) { return CreateCharactersVectorBlock(builder, data); } + public static void StartCharactersVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static Offset EndMovie(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishMovieBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "MOVI"); } + public static void FinishSizePrefixedMovieBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "MOVI"); } + public MovieT UnPack() { + var _o = new MovieT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(MovieT _o) { + if (_o.MainCharacter == null) { + _o.MainCharacter = new MyGame.Example.CharacterUnion(); + } + var _MainCharacterOldType = _o.MainCharacter.Type; + _o.MainCharacter.Type = this.MainCharacterType; + switch (this.MainCharacterType) { + default: + _o.MainCharacter.Value = null; + break; + case MyGame.Example.Character.MuLan: + if (this.MainCharacter().HasValue) { + if (_MainCharacterOldType == MyGame.Example.Character.MuLan) { + this.MainCharacter().Value.UnPackTo((MyGame.Example.AttackerT)_o.MainCharacter.Value); + } else { + _o.MainCharacter.Value = this.MainCharacter().Value.UnPack(); + } + } else { + _o.MainCharacter.Value = null; + } + break; + case MyGame.Example.Character.Rapunzel: + if (this.MainCharacter().HasValue) { + if (_MainCharacterOldType == MyGame.Example.Character.Rapunzel) { + this.MainCharacter().Value.UnPackTo((MyGame.Example.RapunzelT)_o.MainCharacter.Value); + } else { + _o.MainCharacter.Value = this.MainCharacter().Value.UnPack(); + } + } else { + _o.MainCharacter.Value = null; + } + break; + case MyGame.Example.Character.Belle: + if (this.MainCharacter().HasValue) { + if (_MainCharacterOldType == MyGame.Example.Character.Belle) { + this.MainCharacter().Value.UnPackTo((MyGame.Example.BookReaderT)_o.MainCharacter.Value); + } else { + _o.MainCharacter.Value = this.MainCharacter().Value.UnPack(); + } + } else { + _o.MainCharacter.Value = null; + } + break; + case MyGame.Example.Character.BookFan: + if (this.MainCharacter().HasValue) { + if (_MainCharacterOldType == MyGame.Example.Character.BookFan) { + this.MainCharacter().Value.UnPackTo((MyGame.Example.BookReaderT)_o.MainCharacter.Value); + } else { + _o.MainCharacter.Value = this.MainCharacter().Value.UnPack(); + } + } else { + _o.MainCharacter.Value = null; + } + break; + case MyGame.Example.Character.Other: + _o.MainCharacter.Value = this.MainCharacterAsString(); + break; + case MyGame.Example.Character.Unused: + _o.MainCharacter.Value = this.MainCharacterAsString(); + break; + } + var _characters_types = this.CharactersType; + var _characters = this.Characters; + var _characters_len = _characters.HasValue ? _characters.Value.Length : 0; + if (_o.Characters == null) { + _o.Characters = new List(_characters_len); + } + ObjectApiUtil.ResizeList(_o.Characters, _characters_len); + if (_characters.HasValue) { + var _characters_value = _characters.Value; + var _characters_types_value = _characters_types.Value; + for (var _j = 0; _j < _characters_len; ++_j) { + var _characters_type = _characters_types_value[_j]; + var _o_Characters = _o.Characters[_j]; + if (_o_Characters == null) { + _o_Characters = new MyGame.Example.CharacterUnion(); + _o.Characters[_j] = _o_Characters; + } + var _characters_old_type = _o_Characters.Type; + _o_Characters.Type = _characters_type; + switch (_characters_type) { + default: + _o_Characters.Value = null; + break; + case MyGame.Example.Character.MuLan: + if (_characters_old_type == MyGame.Example.Character.MuLan) { + _characters_value.GetAs(_j).UnPackTo((MyGame.Example.AttackerT)_o_Characters.Value); + } else { + _o_Characters.Value = _characters_value.GetAs(_j).UnPack(); + } + break; + case MyGame.Example.Character.Rapunzel: + if (_characters_old_type == MyGame.Example.Character.Rapunzel) { + _characters_value.GetAs(_j).UnPackTo((MyGame.Example.RapunzelT)_o_Characters.Value); + } else { + _o_Characters.Value = _characters_value.GetAs(_j).UnPack(); + } + break; + case MyGame.Example.Character.Belle: + if (_characters_old_type == MyGame.Example.Character.Belle) { + _characters_value.GetAs(_j).UnPackTo((MyGame.Example.BookReaderT)_o_Characters.Value); + } else { + _o_Characters.Value = _characters_value.GetAs(_j).UnPack(); + } + break; + case MyGame.Example.Character.BookFan: + if (_characters_old_type == MyGame.Example.Character.BookFan) { + _characters_value.GetAs(_j).UnPackTo((MyGame.Example.BookReaderT)_o_Characters.Value); + } else { + _o_Characters.Value = _characters_value.GetAs(_j).UnPack(); + } + break; + case MyGame.Example.Character.Other: + _o_Characters.Value = _characters_value.GetAsString(_j); + break; + case MyGame.Example.Character.Unused: + _o_Characters.Value = _characters_value.GetAsString(_j); + break; + } + } + } + } + public static Offset Pack(FlatBufferBuilder builder, MovieT _o) { + if (_o == null) return default(Offset); + var _main_character_type = _o.MainCharacter == null ? MyGame.Example.Character.NONE : _o.MainCharacter.Type; + var _main_character = _o.MainCharacter == null ? 0 : MyGame.Example.CharacterUnion.Pack(builder, _o.MainCharacter); + var _characters_type = default(VectorOffset); + if (_o.Characters != null) { + var _characters_type_len = _o.Characters.Count; + MyGame.Example.Character[] _characters_type_arr = null; + try { + Span __characters_type = _characters_type_len <= 256 + ? stackalloc MyGame.Example.Character[_characters_type_len] + : (_characters_type_arr = ArrayPool.Shared.Rent(_characters_type_len)).AsSpan(0, _characters_type_len); + for (var _j = 0; _j < _characters_type_len; ++_j) { __characters_type[_j] = _o.Characters[_j].Type; } + _characters_type = CreateCharactersTypeVector(builder, __characters_type); + } finally { + if (_characters_type_arr != null) { ArrayPool.Shared.Return(_characters_type_arr); } + } + } + var _characters = default(VectorOffset); + if (_o.Characters != null) { + var _characters_len = _o.Characters.Count; + int[] _characters_arr = null; + try { + Span __characters = _characters_len <= 64 + ? stackalloc int[_characters_len] + : (_characters_arr = ArrayPool.Shared.Rent(_characters_len)).AsSpan(0, _characters_len); + for (var _j = 0; _j < _characters_len; ++_j) { __characters[_j] = MyGame.Example.CharacterUnion.Pack(builder, _o.Characters[_j]); } + _characters = CreateCharactersVector(builder, __characters); + } finally { + if (_characters_arr != null) { ArrayPool.Shared.Return(_characters_arr); } + } + } + return CreateMovie( + builder, + _main_character_type, + _main_character, + _characters_type, + _characters); + } +} + +public class MovieT +{ + [System.Text.Json.Serialization.JsonPropertyName("main_character_type")] + private MyGame.Example.Character MainCharacterType { + get { + return this.MainCharacter != null ? this.MainCharacter.Type : MyGame.Example.Character.NONE; + } + set { + this.MainCharacter = new MyGame.Example.CharacterUnion(); + this.MainCharacter.Type = value; + } + } + [System.Text.Json.Serialization.JsonPropertyName("main_character")] + [System.Text.Json.Serialization.JsonConverter(typeof(MyGame.Example.CharacterUnion_JsonConverter))] + public MyGame.Example.CharacterUnion MainCharacter { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("characters_type")] + private MyGame.Example.Character[] CharactersType { + get { + if (this.Characters == null) return null; + var _o = new MyGame.Example.Character[this.Characters.Count]; + for (var _j = 0; _j < _o.Length; ++_j) { _o[_j] = this.Characters[_j].Type; } + return _o; + } + set { + this.Characters = new List(); + for (var _j = 0; _j < value.Length; ++_j) { + var _o = new MyGame.Example.CharacterUnion(); + _o.Type = value[_j]; + this.Characters.Add(_o); + } + } + } + [System.Text.Json.Serialization.JsonPropertyName("characters")] + public List Characters { get; set; } + + public MovieT() { + this.MainCharacter = null; + this.Characters = null; + } + + private static readonly System.Text.Json.JsonSerializerOptions _jsonOptions = new System.Text.Json.JsonSerializerOptions { WriteIndented = true, NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals, Converters = { new System.Text.Json.Serialization.JsonStringEnumConverter() } }; + public static MovieT DeserializeFromJson(string jsonText) { + return System.Text.Json.JsonSerializer.Deserialize(jsonText, _jsonOptions); + } + public string SerializeToJson() { + return System.Text.Json.JsonSerializer.Serialize(this, _jsonOptions); + } + public static MovieT DeserializeFromBinary(byte[] fbBuffer) { + return Movie.GetRootAsMovie(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + Movie.FinishMovieBuffer(fbb, Movie.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedSpan().ToArray(); + } +} + + +static public class MovieVerify +{ + static public bool Verify(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos) + { + return verifier.VerifyTableStart(tablePos) + && verifier.VerifyField(tablePos, 4 /*MainCharacterType*/, 1 /*MyGame.Example.Character*/, 1, false) + && verifier.VerifyUnion(tablePos, 4, 6 /*MainCharacter*/, MyGame.Example.CharacterVerify.Verify, false) + && verifier.VerifyVectorOfData(tablePos, 8 /*CharactersType*/, 1 /*MyGame.Example.Character*/, false) + && verifier.VerifyTableEnd(tablePos); + } +} + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Rapunzel.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Rapunzel.cs new file mode 100644 index 00000000000..ff6ad1a6f24 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/Rapunzel.cs @@ -0,0 +1,57 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public struct Rapunzel : IFlatbufferObject +{ + private Struct __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); } + public Rapunzel __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int HairLength { get { return __p.bb.Get(__p.bb_pos + 0); } } + + public static Offset CreateRapunzel(FlatBufferBuilder builder, int HairLength) { + builder.Prep(4, 4); + builder.Put(HairLength); + return new Offset(builder.Offset); + } + public RapunzelT UnPack() { + var _o = new RapunzelT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(RapunzelT _o) { + _o.HairLength = this.HairLength; + } + public static Offset Pack(FlatBufferBuilder builder, RapunzelT _o) { + if (_o == null) return default(Offset); + return CreateRapunzel( + builder, + _o.HairLength); + } +} + +public class RapunzelT +{ + [System.Text.Json.Serialization.JsonPropertyName("hair_length")] + public int HairLength { get; set; } + + public RapunzelT() { + this.HairLength = 0; + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/Attacker.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/Attacker.cs new file mode 100644 index 00000000000..5b20845f772 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/Attacker.cs @@ -0,0 +1,58 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Attacker : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Attacker GetRootAsAttacker(ByteSpanBuffer _bb) { return GetRootAsAttacker(_bb, new Attacker()); } + public static Attacker GetRootAsAttacker(ByteSpanBuffer _bb, Attacker obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Attacker __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int SwordAttackDamage { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateAttacker(ref FlatSpanBufferBuilder builder, + int sword_attack_damage = 0) { + builder.StartTable(1); + Attacker.AddSwordAttackDamage(ref builder, sword_attack_damage); + return Attacker.EndAttacker(ref builder); + } + + public static void StartAttacker(ref FlatSpanBufferBuilder builder) { builder.StartTable(1); } + public static void AddSwordAttackDamage(ref FlatSpanBufferBuilder builder, int swordAttackDamage) { builder.Add(0, swordAttackDamage, 0); } + public static Offset EndAttacker(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public AttackerT UnPack() { + var _o = new AttackerT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(AttackerT _o) { + _o.SwordAttackDamage = this.SwordAttackDamage; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, AttackerT _o) { + if (_o == null) return default(Offset); + return CreateAttacker( + ref builder, + _o.SwordAttackDamage); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/BookReader.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/BookReader.cs new file mode 100644 index 00000000000..a99a494b36f --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/BookReader.cs @@ -0,0 +1,47 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct BookReader : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public BookReader __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int BooksRead { get { return __p.bb.Get(__p.bb_pos + 0); } } + + public static Offset CreateBookReader(ref FlatSpanBufferBuilder builder, int BooksRead) { + builder.Prep(4, 4); + builder.Put(BooksRead); + return new Offset(builder.Offset); + } + public BookReaderT UnPack() { + var _o = new BookReaderT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(BookReaderT _o) { + _o.BooksRead = this.BooksRead; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, BookReaderT _o) { + if (_o == null) return default(Offset); + return CreateBookReader( + ref builder, + _o.BooksRead); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/FallingTub.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/FallingTub.cs new file mode 100644 index 00000000000..3960b466b04 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/FallingTub.cs @@ -0,0 +1,47 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct FallingTub : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public FallingTub __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int Weight { get { return __p.bb.Get(__p.bb_pos + 0); } } + + public static Offset CreateFallingTub(ref FlatSpanBufferBuilder builder, int Weight) { + builder.Prep(4, 4); + builder.Put(Weight); + return new Offset(builder.Offset); + } + public FallingTubT UnPack() { + var _o = new FallingTubT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(FallingTubT _o) { + _o.Weight = this.Weight; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, FallingTubT _o) { + if (_o == null) return default(Offset); + return CreateFallingTub( + ref builder, + _o.Weight); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/HandFan.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/HandFan.cs new file mode 100644 index 00000000000..9ff89295b9b --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/HandFan.cs @@ -0,0 +1,58 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct HandFan : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static HandFan GetRootAsHandFan(ByteSpanBuffer _bb) { return GetRootAsHandFan(_bb, new HandFan()); } + public static HandFan GetRootAsHandFan(ByteSpanBuffer _bb, HandFan obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public HandFan __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int Length { get { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateHandFan(ref FlatSpanBufferBuilder builder, + int length = 0) { + builder.StartTable(1); + HandFan.AddLength(ref builder, length); + return HandFan.EndHandFan(ref builder); + } + + public static void StartHandFan(ref FlatSpanBufferBuilder builder) { builder.StartTable(1); } + public static void AddLength(ref FlatSpanBufferBuilder builder, int length) { builder.Add(0, length, 0); } + public static Offset EndHandFan(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public HandFanT UnPack() { + var _o = new HandFanT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(HandFanT _o) { + _o.Length = this.Length; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, HandFanT _o) { + if (_o == null) return default(Offset); + return CreateHandFan( + ref builder, + _o.Length); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/Movie.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/Movie.cs new file mode 100644 index 00000000000..17ecbfe4d09 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/Movie.cs @@ -0,0 +1,239 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Movie : IFlatbufferSpanObject +{ + private TableSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); } + public static Movie GetRootAsMovie(ByteSpanBuffer _bb) { return GetRootAsMovie(_bb, new Movie()); } + public static Movie GetRootAsMovie(ByteSpanBuffer _bb, Movie obj) { return (obj.__assign(_bb.Get(_bb.Position) + _bb.Position, _bb)); } + public static bool MovieBufferHasIdentifier(ByteSpanBuffer _bb) { return TableSpan.__has_identifier(_bb, "MOVI"); } + public static bool VerifyMovie(ByteSpanBuffer _bb) {Google.FlatSpanBuffers.Verifier verifier = new Google.FlatSpanBuffers.Verifier(_bb); return verifier.VerifyBuffer("MOVI", false, MyGame.Example.MovieVerify.Verify); } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new TableSpan(_i, _bb); } + public Movie __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Example.Character MainCharacterType { get { int o = __p.__offset(4); return o != 0 ? (MyGame.Example.Character)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Character.NONE; } } + public RefStructNullable MainCharacter() where TTable : struct, IFlatbufferSpanObject, allows ref struct { int o = __p.__offset(6); return o != 0 ? new RefStructNullable(__p.__union(o + __p.bb_pos)) : default; } + public string MainCharacterAsString() { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } + public MyGame.Example.StackBuffer.Attacker MainCharacterAsMuLan() { return MainCharacter().Value; } + public MyGame.Example.StackBuffer.Rapunzel MainCharacterAsRapunzel() { return MainCharacter().Value; } + public MyGame.Example.StackBuffer.BookReader MainCharacterAsBelle() { return MainCharacter().Value; } + public MyGame.Example.StackBuffer.BookReader MainCharacterAsBookFan() { return MainCharacter().Value; } + public string MainCharacterAsOther() { return MainCharacterAsString(); } + public string MainCharacterAsUnused() { return MainCharacterAsString(); } + public RefStructNullable> CharactersType { get { int o = __p.__offset(8); return o != 0 ? new RefStructNullable>(__p.__vector_as_span(8)) : default; } } + public RefStructNullable Characters { get { int o = __p.__offset(10); return o != 0 ? new RefStructNullable(new UnionVectorSpan(__p, o, 4)) : default; } } + + public static Offset CreateMovie(ref FlatSpanBufferBuilder builder, + MyGame.Example.Character main_character_type = MyGame.Example.Character.NONE, + int main_characterOffset = 0, + VectorOffset characters_typeOffset = default(VectorOffset), + VectorOffset charactersOffset = default(VectorOffset)) { + builder.StartTable(4); + Movie.AddCharacters(ref builder, charactersOffset); + Movie.AddCharactersType(ref builder, characters_typeOffset); + Movie.AddMainCharacter(ref builder, main_characterOffset); + Movie.AddMainCharacterType(ref builder, main_character_type); + return Movie.EndMovie(ref builder); + } + + public static void StartMovie(ref FlatSpanBufferBuilder builder) { builder.StartTable(4); } + public static void AddMainCharacterType(ref FlatSpanBufferBuilder builder, MyGame.Example.Character mainCharacterType) { builder.Add(0, (byte)mainCharacterType, 0); } + public static void AddMainCharacter(ref FlatSpanBufferBuilder builder, int mainCharacterOffset) { builder.AddOffset(1, mainCharacterOffset, 0); } + public static void AddCharactersType(ref FlatSpanBufferBuilder builder, VectorOffset charactersTypeOffset) { builder.AddOffset(2, charactersTypeOffset, 0); } + public static VectorOffset CreateCharactersTypeVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(1, data.Length, 1); builder.AddSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCharactersTypeVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateCharactersTypeVectorBlock(ref builder, data); } + public static void StartCharactersTypeVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddCharacters(ref FlatSpanBufferBuilder builder, VectorOffset charactersOffset) { builder.AddOffset(3, charactersOffset, 0); } + public static VectorOffset CreateCharactersVectorBlock(ref FlatSpanBufferBuilder builder, scoped Span data) { builder.StartVector(4, data.Length, 4); builder.AddOffsetSpan(data); return builder.EndVector(); } + public static VectorOffset CreateCharactersVector(ref FlatSpanBufferBuilder builder, scoped Span data) { return CreateCharactersVectorBlock(ref builder, data); } + public static void StartCharactersVector(ref FlatSpanBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } + public static Offset EndMovie(ref FlatSpanBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishMovieBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "MOVI"); } + public static void FinishSizePrefixedMovieBuffer(ref FlatSpanBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value, "MOVI"); } + public MovieT UnPack() { + var _o = new MovieT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(MovieT _o) { + if (_o.MainCharacter == null) { + _o.MainCharacter = new MyGame.Example.CharacterUnion(); + } + var _MainCharacterOldType = _o.MainCharacter.Type; + _o.MainCharacter.Type = this.MainCharacterType; + switch (this.MainCharacterType) { + default: + _o.MainCharacter.Value = null; + break; + case MyGame.Example.Character.MuLan: + if (this.MainCharacter().HasValue) { + if (_MainCharacterOldType == MyGame.Example.Character.MuLan) { + this.MainCharacter().Value.UnPackTo((MyGame.Example.AttackerT)_o.MainCharacter.Value); + } else { + _o.MainCharacter.Value = this.MainCharacter().Value.UnPack(); + } + } else { + _o.MainCharacter.Value = null; + } + break; + case MyGame.Example.Character.Rapunzel: + if (this.MainCharacter().HasValue) { + if (_MainCharacterOldType == MyGame.Example.Character.Rapunzel) { + this.MainCharacter().Value.UnPackTo((MyGame.Example.RapunzelT)_o.MainCharacter.Value); + } else { + _o.MainCharacter.Value = this.MainCharacter().Value.UnPack(); + } + } else { + _o.MainCharacter.Value = null; + } + break; + case MyGame.Example.Character.Belle: + if (this.MainCharacter().HasValue) { + if (_MainCharacterOldType == MyGame.Example.Character.Belle) { + this.MainCharacter().Value.UnPackTo((MyGame.Example.BookReaderT)_o.MainCharacter.Value); + } else { + _o.MainCharacter.Value = this.MainCharacter().Value.UnPack(); + } + } else { + _o.MainCharacter.Value = null; + } + break; + case MyGame.Example.Character.BookFan: + if (this.MainCharacter().HasValue) { + if (_MainCharacterOldType == MyGame.Example.Character.BookFan) { + this.MainCharacter().Value.UnPackTo((MyGame.Example.BookReaderT)_o.MainCharacter.Value); + } else { + _o.MainCharacter.Value = this.MainCharacter().Value.UnPack(); + } + } else { + _o.MainCharacter.Value = null; + } + break; + case MyGame.Example.Character.Other: + _o.MainCharacter.Value = this.MainCharacterAsString(); + break; + case MyGame.Example.Character.Unused: + _o.MainCharacter.Value = this.MainCharacterAsString(); + break; + } + var _characters_types = this.CharactersType; + var _characters = this.Characters; + var _characters_len = _characters.HasValue ? _characters.Value.Length : 0; + if (_o.Characters == null) { + _o.Characters = new List(_characters_len); + } + ObjectApiUtil.ResizeList(_o.Characters, _characters_len); + if (_characters.HasValue) { + var _characters_value = _characters.Value; + var _characters_types_value = _characters_types.Value; + for (var _j = 0; _j < _characters_len; ++_j) { + var _characters_type = _characters_types_value[_j]; + var _o_Characters = _o.Characters[_j]; + if (_o_Characters == null) { + _o_Characters = new MyGame.Example.CharacterUnion(); + _o.Characters[_j] = _o_Characters; + } + var _characters_old_type = _o_Characters.Type; + _o_Characters.Type = _characters_type; + switch (_characters_type) { + default: + _o_Characters.Value = null; + break; + case MyGame.Example.Character.MuLan: + if (_characters_old_type == MyGame.Example.Character.MuLan) { + _characters_value.GetAs(_j).UnPackTo((MyGame.Example.AttackerT)_o_Characters.Value); + } else { + _o_Characters.Value = _characters_value.GetAs(_j).UnPack(); + } + break; + case MyGame.Example.Character.Rapunzel: + if (_characters_old_type == MyGame.Example.Character.Rapunzel) { + _characters_value.GetAs(_j).UnPackTo((MyGame.Example.RapunzelT)_o_Characters.Value); + } else { + _o_Characters.Value = _characters_value.GetAs(_j).UnPack(); + } + break; + case MyGame.Example.Character.Belle: + if (_characters_old_type == MyGame.Example.Character.Belle) { + _characters_value.GetAs(_j).UnPackTo((MyGame.Example.BookReaderT)_o_Characters.Value); + } else { + _o_Characters.Value = _characters_value.GetAs(_j).UnPack(); + } + break; + case MyGame.Example.Character.BookFan: + if (_characters_old_type == MyGame.Example.Character.BookFan) { + _characters_value.GetAs(_j).UnPackTo((MyGame.Example.BookReaderT)_o_Characters.Value); + } else { + _o_Characters.Value = _characters_value.GetAs(_j).UnPack(); + } + break; + case MyGame.Example.Character.Other: + _o_Characters.Value = _characters_value.GetAsString(_j); + break; + case MyGame.Example.Character.Unused: + _o_Characters.Value = _characters_value.GetAsString(_j); + break; + } + } + } + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, MovieT _o) { + if (_o == null) return default(Offset); + var _main_character_type = _o.MainCharacter == null ? MyGame.Example.Character.NONE : _o.MainCharacter.Type; + var _main_character = _o.MainCharacter == null ? 0 : MyGame.Example.CharacterUnion.Pack(ref builder, _o.MainCharacter); + var _characters_type = default(VectorOffset); + if (_o.Characters != null) { + var _characters_type_len = _o.Characters.Count; + MyGame.Example.Character[] _characters_type_arr = null; + try { + Span __characters_type = _characters_type_len <= 256 + ? stackalloc MyGame.Example.Character[_characters_type_len] + : (_characters_type_arr = ArrayPool.Shared.Rent(_characters_type_len)).AsSpan(0, _characters_type_len); + for (var _j = 0; _j < _characters_type_len; ++_j) { __characters_type[_j] = _o.Characters[_j].Type; } + _characters_type = CreateCharactersTypeVector(ref builder, __characters_type); + } finally { + if (_characters_type_arr != null) { ArrayPool.Shared.Return(_characters_type_arr); } + } + } + var _characters = default(VectorOffset); + if (_o.Characters != null) { + var _characters_len = _o.Characters.Count; + int[] _characters_arr = null; + try { + Span __characters = _characters_len <= 64 + ? stackalloc int[_characters_len] + : (_characters_arr = ArrayPool.Shared.Rent(_characters_len)).AsSpan(0, _characters_len); + for (var _j = 0; _j < _characters_len; ++_j) { __characters[_j] = MyGame.Example.CharacterUnion.Pack(ref builder, _o.Characters[_j]); } + _characters = CreateCharactersVector(ref builder, __characters); + } finally { + if (_characters_arr != null) { ArrayPool.Shared.Return(_characters_arr); } + } + } + return CreateMovie( + ref builder, + _main_character_type, + _main_character, + _characters_type, + _characters); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/Rapunzel.cs b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/Rapunzel.cs new file mode 100644 index 00000000000..8c13bfb1aa1 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/Generated/union_vector/MyGame/Example/StackBuffer/Rapunzel.cs @@ -0,0 +1,47 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace MyGame.Example.StackBuffer +{ + +using global::System; +using global::System.Buffers; +using global::System.Collections.Generic; +using global::System.Runtime.InteropServices; +using global::Google.FlatSpanBuffers; +using global::Google.FlatSpanBuffers.Operations; +using global::Google.FlatSpanBuffers.Utils; +using global::Google.FlatSpanBuffers.Vectors; +public ref struct Rapunzel : IFlatbufferSpanObject +{ + private StructSpan __p; + public ByteSpanBuffer ByteBuffer { get { return __p.bb; } } + public void __init(int _i, ByteSpanBuffer _bb) { __p = new StructSpan(_i, _bb); } + public Rapunzel __assign(int _i, ByteSpanBuffer _bb) { __init(_i, _bb); return this; } + + public int HairLength { get { return __p.bb.Get(__p.bb_pos + 0); } } + + public static Offset CreateRapunzel(ref FlatSpanBufferBuilder builder, int HairLength) { + builder.Prep(4, 4); + builder.Put(HairLength); + return new Offset(builder.Offset); + } + public RapunzelT UnPack() { + var _o = new RapunzelT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(RapunzelT _o) { + _o.HairLength = this.HairLength; + } + public static Offset Pack(ref FlatSpanBufferBuilder builder, RapunzelT _o) { + if (_o == null) return default(Offset); + return CreateRapunzel( + ref builder, + _o.HairLength); + } +} + + +} diff --git a/net/FlatSpanBuffers.GeneratedCode/fbs/arrays_test.fbs b/net/FlatSpanBuffers.GeneratedCode/fbs/arrays_test.fbs new file mode 100644 index 00000000000..90cb0d7267c --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/fbs/arrays_test.fbs @@ -0,0 +1,27 @@ +namespace MyGame.Example; + +enum TestEnum : byte { A, B, C } + +struct NestedStruct{ + a:[int:2]; + b:TestEnum; + c:[TestEnum:2]; + d:[int64:2]; +} + +struct ArrayStruct{ + a:float; + b:[int:0xF]; + c:byte; + d:[NestedStruct:2]; + e:int32; + f:[int64:2]; +} + +table ArrayTable{ + a:ArrayStruct; +} + +root_type ArrayTable; +file_identifier "ARRT"; +file_extension "mon"; diff --git a/net/FlatSpanBuffers.GeneratedCode/fbs/comprehensive_test.fbs b/net/FlatSpanBuffers.GeneratedCode/fbs/comprehensive_test.fbs new file mode 100644 index 00000000000..7c1b32028e1 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/fbs/comprehensive_test.fbs @@ -0,0 +1,140 @@ +// Schema to exercise all C# code generation features +namespace ComprehensiveTest; + +file_identifier "TEST"; +file_extension "fb"; + +// Basic enum +enum Color : byte { Red = 0, Green, Blue } + +// Enum with explicit values +enum Status : int { + Unknown = -1, + Pending = 0, + Active = 1, + Inactive = 2 +} + +// Union types +union Equipment { Weapon, Armor } + +// Basic struct (fixed size) +struct Vec3 { + x: float; + y: float; + z: float; +} + +// Nested struct +struct Transform { + position: Vec3; + rotation: Vec3; + scale: Vec3; +} + +// Fixed-length array structs +struct FixedStats { + values: [int:4]; +} + +struct PositionHistory { + positions: [Vec3:10]; +} + +// Table with nested flatbuffer +table NestedData { + value: int; +} + +// Complex table with all field types +table Weapon { + name: string (required); + damage: int = 10; + durability: float = 100.0; + enchanted: bool = false; + + // Vector types + tags: [string]; + damage_values: [int]; + modifiers: [float]; + + // Struct field + transform: Transform; + + // Vector of structs + hit_points: [Vec3]; + + // Enum field + rarity: Color = Red; + + // Vector of enums + valid_colors: [Color]; + + // Union field + weapon_type: Equipment; + weapon_equipment: Equipment; + + // Vector of unions + compatible_types: [Equipment]; + compatible_items: [Equipment]; + + // Nested flatbuffer + metadata: [ubyte] (nested_flatbuffer: "NestedData"); + + // Fixed-length arrays (wrapped in structs) + fixed_stats: FixedStats; + position_history: PositionHistory; +} + +table Armor { + name: string (required); + defense: int = 5; + weight: float = 1.0; + transform: Transform; +} + +// Table with key field (for sorting/lookup) +table Player { + id: int (key); + name: string (required); + level: int = 1; + experience: long = 0; + health: float = 100.0; + mana: float = 50.0; + + // Collections + inventory: [Equipment]; + skills: [string]; + stats: [int]; + + // Struct + spawn_point: Vec3; + + // Enum + status: Status = Pending; + + // Union + equipped_type: Equipment; + equipped_item: Equipment; +} + +// Table with deprecated field +table GameSession { + session_id: string (required); + player_count: int = 0; + start_time: long; + + // Deprecated field + old_field: int (deprecated); + + players: [Player]; +} + +// Service definition (for gRPC generation) +rpc_service GameService { + GetPlayer(Player): Player; + UpdatePlayer(Player): Player; + ListPlayers(GameSession): GameSession; +} + +root_type GameSession; diff --git a/net/FlatSpanBuffers.GeneratedCode/fbs/json_test.fbs b/net/FlatSpanBuffers.GeneratedCode/fbs/json_test.fbs new file mode 100644 index 00000000000..65000bb8794 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/fbs/json_test.fbs @@ -0,0 +1,75 @@ +// Schema specifically for testing System.Text.Json serialization +// This schema is generated with --cs-gen-json-serializer flag + +namespace JsonTest; + +enum Status : byte { + Unknown = 0, + Active = 1, + Inactive = 2, + Suspended = 3 +} + +enum Priority : ubyte (bit_flags) { + Low = 0, + Medium = 1, + High = 2, + Critical = 3 +} + +struct Vec2 { + x: float; + y: float; +} + +struct Color { + r: ubyte; + g: ubyte; + b: ubyte; + a: ubyte; +} + +table Item { + id: int (key); + name: string; + value: float; +} + +table Weapon { + name: string; + damage: int; +} + +table Armor { + name: string; + defense: int; +} + +union Equipment { Weapon, Armor } + +table Player { + id: long; + name: string (key); + level: int = 1; + health: float = 100.0; + position: Vec2; + status: Status = Active; + priorities: Priority; + inventory: [Item]; + equipped: Equipment; + tags: [string]; + scores: [int]; + color: Color; +} + +table GameState { + version: string; + players: [Player]; + active_player_id: long; + timestamp: long; +} + +root_type GameState; + +file_identifier "JSON"; +file_extension "json"; diff --git a/net/FlatSpanBuffers.GeneratedCode/fbs/key_test.fbs b/net/FlatSpanBuffers.GeneratedCode/fbs/key_test.fbs new file mode 100644 index 00000000000..e4a03f9b47b --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/fbs/key_test.fbs @@ -0,0 +1,14 @@ +namespace KeyTest; + +table KeyTestMonster { + name:string (key); + hp:int; +} + +table KeyTestWeapon { + id:int (key); + name:string; + damage:int; +} + +root_type KeyTestMonster; diff --git a/net/FlatSpanBuffers.GeneratedCode/fbs/keyword_test.fbs b/net/FlatSpanBuffers.GeneratedCode/fbs/keyword_test.fbs new file mode 100644 index 00000000000..b5955cbfd20 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/fbs/keyword_test.fbs @@ -0,0 +1,21 @@ +namespace KeywordTest; + +enum ABC: int { void, where, stackalloc } + +enum public: int { } + +table KeywordsInTable { + is: ABC = void; + private: public; + type: int; + default: bool = false; +} + +union KeywordsInUnion { + static: KeywordsInTable, + internal: KeywordsInTable, +} + +table Table2 { + type: KeywordsInUnion; +} diff --git a/net/FlatSpanBuffers.GeneratedCode/fbs/monster_test.fbs b/net/FlatSpanBuffers.GeneratedCode/fbs/monster_test.fbs new file mode 100644 index 00000000000..2e3f8ed6ba6 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/fbs/monster_test.fbs @@ -0,0 +1,32 @@ +// Copied and renamed from teh monster.fbs in the samples folder. +namespace MonsterTest; + +enum Color:byte { Red = 0, Green, Blue = 2 } + +union Equipment { Weapon } // Optionally add more tables. + +struct Vec3 { + x:float; + y:float; + z:float; +} + +table Monster { + pos:Vec3; + mana:short = 150; + hp:short = 100; + name:string; + friendly:bool = false (deprecated); + inventory:[ubyte]; + color:Color = Blue; + weapons:[Weapon]; + equipped:Equipment; + path:[Vec3]; +} + +table Weapon { + name:string; + damage:short; +} + +root_type Monster; diff --git a/net/FlatSpanBuffers.GeneratedCode/fbs/mygame_example.fbs b/net/FlatSpanBuffers.GeneratedCode/fbs/mygame_example.fbs new file mode 100644 index 00000000000..334d4c0564b --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/fbs/mygame_example.fbs @@ -0,0 +1,188 @@ +// Comprehensive monster test schema for StackFlatBuffers +// Based on tests/monster_test.fbs but self-contained (no includes) +// This provides the MyGame.Example namespace for 1:1 test comparisons + +namespace MyGame; + +table InParentNamespace {} + +namespace MyGame.Example2; + +table Monster {} // Test having same name as below, but in different namespace. + +namespace MyGame.OtherNameSpace; + +enum FromInclude:long { IncludeVal } + +struct Unused { a:int; } + +table TableB { + a:TableA; +} + +table TableA { + b:MyGame.OtherNameSpace.TableB; +} + +namespace MyGame.Example; + +attribute "priority"; + +/// Composite components of Monster color. +enum Color:ubyte (bit_flags) { + Red = 0, // color Red = (1u << 0) + /// \brief color Green + /// Green is bit_flag with value (1u << 1) + Green, + /// \brief color Blue (1u << 3) + Blue = 3, +} + +enum Race:byte { + None = -1, + Human = 0, + Dwarf, + Elf, +} + +enum LongEnum:ulong (bit_flags) { + LongOne = 1, + LongTwo = 2, + // Because this is a bitflag, 40 will be out of range of a 32-bit integer, + // allowing us to exercise any logic special to big numbers. + LongBig = 40, +} + +union Any { Monster, TestSimpleTableWithEnum, MyGame.Example2.Monster } + +union AnyUniqueAliases { M: Monster, TS: TestSimpleTableWithEnum, M2: MyGame.Example2.Monster } +union AnyAmbiguousAliases { M1: Monster, M2: Monster, M3: Monster } + +struct Test { a:short; b:byte; } + +table TestSimpleTableWithEnum { + color: Color = Green; +} + +struct Vec3 (force_align: 8) { + x:float; + y:float; + z:float; + test1:double; + test2:Color; + test3:Test; +} + +struct Ability { + id:uint(key); + distance:uint; +} + +struct StructOfStructs { + a: Ability; + b: Test; + c: Ability; +} + +struct StructOfStructsOfStructs { + a: StructOfStructs; +} + +table Stat { + id:string; + val:long; + count:ushort (key); +} + +table Referrable { + id:ulong(key); +} + +/// an example documentation comment: "monster object" +table Monster { + pos:Vec3 (id: 0); + hp:short = 100 (id: 2); + mana:short = 150 (id: 1); + name:string (id: 3, key); + color:Color = Blue (id: 6); + inventory:[ubyte] (id: 5); + friendly:bool = false (deprecated, priority: 1, id: 4); + // id 7 is the test_type (union type field) - automatically generated + /// an example documentation comment: this will end up in the generated code + /// multiline too + testarrayoftables:[Monster] (id: 11); + testarrayofstring:[string] (id: 10); + testarrayofstring2:[string] (id: 28); + testarrayofbools:[bool] (id: 24); + testarrayofsortedstruct:[Ability] (id: 29); + enemy:MyGame.Example.Monster (id:12); // Test referring by full namespace. + test:Any (id: 8); + test4:[Test] (id: 9); + test5:[Test] (id: 31); + testnestedflatbuffer:[ubyte] (id:13, nested_flatbuffer: "Monster"); + testempty:Stat (id:14); + testbool:bool (id:15); + testhashs32_fnv1:int (id:16); + testhashu32_fnv1:uint (id:17); + testhashs64_fnv1:long (id:18); + testhashu64_fnv1:ulong (id:19); + testhashs32_fnv1a:int (id:20); + testhashu32_fnv1a:uint (id:21); + testhashs64_fnv1a:long (id:22); + testhashu64_fnv1a:ulong (id:23); + testf:float = 3.14159 (id:25); + testf2:float = 3 (id:26); + testf3:float (id:27); + flex:[ubyte] (id:30); + vector_of_longs:[long] (id:32); + vector_of_doubles:[double] (id:33); + parent_namespace_test:InParentNamespace (id:34); + vector_of_referrables:[Referrable](id:35); + single_weak_reference:ulong(id:36); + vector_of_weak_references:[ulong](id:37); + vector_of_strong_referrables:[Referrable](id:38); + co_owning_reference:ulong(id:39); + vector_of_co_owning_references:[ulong](id:40); + non_owning_reference:ulong(id:41); + vector_of_non_owning_references:[ulong](id:42); + // id 43 is any_unique_type (union type field) - automatically generated + any_unique:AnyUniqueAliases(id:44); + // id 45 is any_ambiguous_type (union type field) - automatically generated + any_ambiguous:AnyAmbiguousAliases (id:46); + vector_of_enums:[Color] (id:47); + signed_enum:Race = None (id:48); + testrequirednestedflatbuffer:[ubyte] (id:49, nested_flatbuffer: "Monster"); + scalar_key_sorted_tables:[Stat] (id: 50); + native_inline:Test (id: 51); + long_enum_non_enum_default:LongEnum (id: 52); + long_enum_normal_default:LongEnum = LongOne (id: 53); + // Test that default values nan and +/-inf work. + nan_default:float = nan (id: 54); + inf_default:float = inf (id: 55); + positive_inf_default:float = +inf (id: 56); + infinity_default:float = infinity (id: 57); + positive_infinity_default:float = +infinity (id: 58); + negative_inf_default:float = -inf (id: 59); + negative_infinity_default:float = -infinity (id: 60); + double_inf_default:double = inf (id: 61); +} + +table TypeAliases { + i8:int8; + u8:uint8; + i16:int16; + u16:uint16; + i32:int32; + u32:uint32; + i64:int64; + u64:uint64; + f32:float32; + f64:float64; + v8:[int8]; + vf64:[float64]; +} + +root_type Monster; + +file_identifier "MONS"; +file_extension "mon"; diff --git a/net/FlatSpanBuffers.GeneratedCode/fbs/optional_scalars.fbs b/net/FlatSpanBuffers.GeneratedCode/fbs/optional_scalars.fbs new file mode 100644 index 00000000000..260d4432be9 --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/fbs/optional_scalars.fbs @@ -0,0 +1,59 @@ +namespace optional_scalars; + +enum OptionalByte: byte { + None = 0, + One = 1, + Two = 2, +} + +// This table tests optional scalars in tables. It should be integrated with +// the main monster test once most languages support optional scalars. +table ScalarStuff { + just_i8: int8; + maybe_i8: int8 = null; + default_i8: int8 = 42; + just_u8: uint8; + maybe_u8: uint8 = null; + default_u8: uint8 = 42; + + just_i16: int16; + maybe_i16: int16 = null; + default_i16: int16 = 42; + just_u16: uint16; + maybe_u16: uint16 = null; + default_u16: uint16 = 42; + + just_i32: int32; + maybe_i32: int32 = null; + default_i32: int32 = 42; + just_u32: uint32; + maybe_u32: uint32 = null; + default_u32: uint32 = 42; + + just_i64: int64; + maybe_i64: int64 = null; + default_i64: int64 = 42; + just_u64: uint64; + maybe_u64: uint64 = null; + default_u64: uint64 = 42; + + just_f32: float32; + maybe_f32: float32 = null; + default_f32: float32 = 42; + just_f64: float64; + maybe_f64: float64 = null; + default_f64: float64 = 42; + + just_bool: bool; + maybe_bool: bool = null; + default_bool: bool = true; + + just_enum: OptionalByte; + maybe_enum: OptionalByte = null; + default_enum: OptionalByte = One; +} + +root_type ScalarStuff; + +file_identifier "NULL"; +file_extension "mon"; diff --git a/net/FlatSpanBuffers.GeneratedCode/fbs/union_vector.fbs b/net/FlatSpanBuffers.GeneratedCode/fbs/union_vector.fbs new file mode 100644 index 00000000000..1ca6685153e --- /dev/null +++ b/net/FlatSpanBuffers.GeneratedCode/fbs/union_vector.fbs @@ -0,0 +1,46 @@ +// Demonstrates the ability to have vectors of unions, and also to +// store structs and strings in unions. + +namespace MyGame.Example; + +table Attacker { + sword_attack_damage: int; +} + +struct Rapunzel { + hair_length: int; +} + +struct BookReader { + books_read: int; +} + +union Character { + MuLan: Attacker, // Can have name be different from type. + Rapunzel, // Or just both the same, as before. + Belle: BookReader, + BookFan: BookReader, + Other: string, + Unused: string +} + +struct FallingTub { + weight: int; +} + +table HandFan { + length: int; +} + +union Gadget { + FallingTub, + HandFan, +} + +table Movie { + main_character: Character; + characters: [Character]; +} + +root_type Movie; +file_identifier "MOVI"; diff --git a/net/FlatSpanBuffers.Tests/AllocatorTests.cs b/net/FlatSpanBuffers.Tests/AllocatorTests.cs new file mode 100644 index 00000000000..0a8d800162b --- /dev/null +++ b/net/FlatSpanBuffers.Tests/AllocatorTests.cs @@ -0,0 +1,271 @@ +/* + * Copyright 2026 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; +using System.Collections.Generic; +using MonsterTest; + +namespace Google.FlatSpanBuffers.Tests +{ + [FlatBuffersTestClass] + public class AllocatorTests + { + [FlatBuffersTestMethod] + public void DefaultAllocator_BasicGrowth_Success() + { + // Start with a very small buffer that will need to grow + var builder = new FlatBufferBuilder(8); + + var longString = new string('A', 100); + var stringOffset = builder.CreateString(longString); + Monster.StartMonster(builder); + Monster.AddName(builder, stringOffset); + Monster.AddHp(builder, 100); + var monsterOffset = Monster.EndMonster(builder); + + builder.Finish(monsterOffset.Value); + + // Verify the buffer grew and data is correct + var buffer = builder.DataBuffer; + Assert.IsTrue(buffer.Length > 8); + + var monster = Monster.GetRootAsMonster(buffer); + Assert.AreEqual(longString, monster.Name); + Assert.AreEqual(100, monster.Hp); + } + + [FlatBuffersTestMethod] + public void DefaultAllocator_MultipleGrowths_InLoop_EdgeCase() + { + int initialLen = 16; + // Start with a tiny buffer + var builder = new FlatBufferBuilder(initialLen); + + var names = new List(); + for (int i = 0; i < 3; i++) + { + var name = builder.CreateString($"Monster_{i:D3}_with_a_long_name"); + names.Add(name); + } + + Span> monsters = stackalloc Offset[3]; + for (int i = 0; i < 3; i++) + { + Monster.StartMonster(builder); + Monster.AddName(builder, names[i]); + Monster.AddHp(builder, (short)(i * 10)); + monsters[i] = Monster.EndMonster(builder); + } + + var vectorOffset = builder.CreateVectorOfTables(monsters); + + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + // Verify buffer grew + var buffer = builder.DataBuffer; + Assert.IsTrue(buffer.Length > initialLen); + + // Verify we can read the data after multiple growths + var rootTable = new Table(buffer.Get(buffer.Position) + buffer.Position, buffer); + var vectorLocation = rootTable.__vector(4); + var vecLen = rootTable.__vector_len(4); + Assert.IsTrue(vectorLocation != 0); + Assert.AreEqual(3, vecLen); + } + + [FlatBuffersTestMethod] + public void DefaultAllocator_GrowthPreservesExistingData_Success() + { + int initialLen = 16; + var builder = new FlatBufferBuilder(initialLen); + + var firstName = builder.CreateString("First"); + var largeName = new string('B', 200); + var secondName = builder.CreateString(largeName); + + Monster.StartMonster(builder); + Monster.AddName(builder, firstName); + Monster.AddHp(builder, 100); + var monster1 = Monster.EndMonster(builder); + + Monster.StartMonster(builder); + Monster.AddName(builder, secondName); + Monster.AddHp(builder, 200); + var monster2 = Monster.EndMonster(builder); + + Span> monsters = stackalloc Offset[] { monster1, monster2 }; + var vectorOffset = builder.CreateVectorOfTables(monsters); + + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + // Verify data is intact after growth + var buffer = builder.DataBuffer; + Assert.IsTrue(buffer.Length > initialLen); + + // Verify we can read the root table + var rootTable = new Table(buffer.Get(buffer.Position) + buffer.Position, buffer); + var vectorLocation = rootTable.__vector(4); + Assert.IsTrue(vectorLocation != 0); + + // Verify vector has 2 elements + var vecLen = rootTable.__vector_len(4); + Assert.AreEqual(2, vecLen); + } + + /// + /// Custom allocator that tracks growth operations and uses a specific growth strategy + /// + private class TrackingAllocator : IByteBufferAllocator + { + public int GrowthCount { get; private set; } + public List RequestedSizes { get; } = new List(); + public List AllocatedSizes { get; } = new List(); + + private readonly int _growthFactor; + + public TrackingAllocator(int growthFactor = 2) + { + _growthFactor = growthFactor; + } + + public int GrowFront(ref ByteBuffer bb, int requestedSize) + { + GrowthCount++; + RequestedSizes.Add(requestedSize); + + if ((bb.Length & 0xC0000000) != 0) + throw new Exception("ByteBuffer: cannot grow buffer beyond 2 gigabytes."); + + if (requestedSize < bb.Length) + throw new Exception("ByteBuffer: cannot truncate buffer."); + + // Use custom growth strategy + var newSize = Math.Max(bb.Length * _growthFactor, requestedSize); + AllocatedSizes.Add(newSize); + + var oldBuffer = bb.Buffer; + var newBuffer = new byte[newSize]; + var dataStart = newSize - bb.Length; + System.Buffer.BlockCopy(oldBuffer, 0, newBuffer, dataStart, oldBuffer.Length); + bb.Reset(newBuffer, 0, newSize); + + return newSize; + } + } + + [FlatBuffersTestMethod] + public void CustomAllocator_TracksGrowthOperations_Success() + { + var allocator = new TrackingAllocator(); + var buffer = new ByteBuffer(16); + var builder = new FlatBufferBuilder(buffer, new int[16], new int[16], allocator); + + // Force growth with large data + var longString = new string('A', 100); + builder.CreateString(longString); + + // Verify allocator was called + Assert.IsTrue(allocator.GrowthCount > 0); + Assert.IsTrue(allocator.RequestedSizes.Count > 0); + Assert.IsTrue(allocator.AllocatedSizes.Count > 0); + } + + [FlatBuffersTestMethod] + public void CustomAllocator_CustomGrowthStrategy_Success() + { + // Allocator that triples buffer size instead of doubling + var allocator = new TrackingAllocator(growthFactor: 3); + var buffer = new ByteBuffer(32); + var initialSize = buffer.Length; + + var builder = new FlatBufferBuilder(buffer, new int[16], new int[16], allocator); + + // Force growth + var largeString = new string('X', 60); + builder.CreateString(largeString); + + // Verify custom growth strategy was used + Assert.AreEqual(1, allocator.GrowthCount); + Assert.IsTrue(allocator.AllocatedSizes[0] >= initialSize * 3); + } + + [FlatBuffersTestMethod] + public void DefaultAllocator_SmallInitialSize_Success() + { + // Start with minimal practical size + var builder = new FlatBufferBuilder(16); + + var str = builder.CreateString("A"); + Monster.StartMonster(builder); + Monster.AddName(builder, str); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var buffer = builder.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + Assert.AreEqual("A", monster.Name); + } + + [FlatBuffersTestMethod] + public void CustomAllocator_PreservesDuringMultipleGrowths_EdgeCase() + { + var allocator = new TrackingAllocator(); + var buffer = new ByteBuffer(8); + var builder = new FlatBufferBuilder(buffer, new int[16], new int[16], allocator); + + // Add data that will cause multiple growth operations (reduced count) + var strings = new StringOffset[5]; + for (int i = 0; i < 5; i++) + { + strings[i] = builder.CreateString($"String_number_{i:D4}_with_extra_padding"); + } + + // Create monsters with all strings + Span> monsters = stackalloc Offset[5]; + for (int i = 0; i < 5; i++) + { + Monster.StartMonster(builder); + Monster.AddName(builder, strings[i]); + Monster.AddHp(builder, (short)i); + monsters[i] = Monster.EndMonster(builder); + } + + var vectorOffset = builder.CreateVectorOfTables(monsters); + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + // Verify multiple growths occurred + Assert.IsTrue(allocator.GrowthCount > 1); + + // Verify all data is intact by checking vector length + var readBuffer = builder.DataBuffer; + var rootTable = new Table(readBuffer.Get(readBuffer.Position) + readBuffer.Position, readBuffer); + var vectorLocation = rootTable.__vector(4); + var vecLen = rootTable.__vector_len(4); + + Assert.IsTrue(vectorLocation != 0); + Assert.AreEqual(5, vecLen); + } + } +} diff --git a/net/FlatSpanBuffers.Tests/Assert.cs b/net/FlatSpanBuffers.Tests/Assert.cs new file mode 100644 index 00000000000..e0a9f5e12b2 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/Assert.cs @@ -0,0 +1,208 @@ +/* + * Copyright 2014 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; +using System.Collections.Generic; +using System.IO.Pipelines; +using System.Linq; +using System.Text; + +namespace Google.FlatSpanBuffers.Tests +{ + + public class AssertFailedException : Exception + { + private readonly object _expected; + private readonly object _actual; + + public AssertFailedException(object expected, object actual) + { + _expected = expected; + _actual = actual; + } + + public override string Message + { + get { return string.Format("Expected {0} but saw {1}", _expected, _actual); } + } + } + + public class AssertArrayFailedException : Exception + { + private readonly int _index; + private readonly object _expected; + private readonly object _actual; + + public AssertArrayFailedException(int index, object expected, object actual) + { + _index = index; + _expected = expected; + _actual = actual; + } + + public override string Message + { + get { return string.Format("Expected {0} at index {1} but saw {2}", _expected, _index, _actual); } + } + } + + public class AssertUnexpectedThrowException : Exception + { + private readonly object _expected; + + public AssertUnexpectedThrowException(object expected) + { + _expected = expected; + } + + public override string Message + { + get { return string.Format("Expected exception of type {0}", _expected); } + } + } + + public static class Assert + { + public static void AreEqual(T expected, T actual) + { + if (expected == null && actual == null) return; + if (expected == null || actual == null || !expected.Equals(actual)) + { + throw new AssertFailedException(expected!, actual!); + } + } + + public static void AreEqual(T expected, T actual, int precision) where T : IComparable + { + // For floating point comparisons with precision + if (typeof(T) == typeof(float)) + { + var expectedFloat = (float)(object)expected!; + var actualFloat = (float)(object)actual!; + var diff = Math.Abs(expectedFloat - actualFloat); + var tolerance = Math.Pow(10, -precision); + + if (diff > tolerance) + { + throw new AssertFailedException(expected!, actual!); + } + } + else if (typeof(T) == typeof(double)) + { + var expectedDouble = (double)(object)expected!; + var actualDouble = (double)(object)actual!; + var diff = Math.Abs(expectedDouble - actualDouble); + var tolerance = Math.Pow(10, -precision); + + if (diff > tolerance) + { + throw new AssertFailedException(expected!, actual!); + } + } + else + { + AreEqual(expected, actual); + } + } + + public static void NotEqual(T notExpected, T actual) + { + bool areEqual = false; + if (notExpected == null && actual == null) + areEqual = true; + else if (notExpected != null && actual != null && notExpected.Equals(actual)) + areEqual = true; + + if (areEqual) + { + throw new AssertFailedException($"Not {notExpected}", actual!); + } + } + + public static void ArrayEqual(T[] expected, T[] actual) + where T : IEquatable + { + SpanEqual(expected, actual); + } + + public static void SpanEqual(ReadOnlySpan expected, ReadOnlySpan actual) + where T : IEquatable + { + if (expected.Length != actual.Length) + { + throw new AssertFailedException($"Expected length {expected.Length}", $"Actual length {actual.Length}"); + } + + for (var i = 0; i < expected.Length; ++i) + { + if (!expected[i].Equals(actual[i])) + { + throw new AssertArrayFailedException(i, expected[i], actual[i]); + } + } + } + + public static void IsTrue(bool value) + { + if (!value) + { + throw new AssertFailedException(true, value); + } + } + + public static void IsFalse(bool value) + { + if (value) + { + throw new AssertFailedException(false, value); + } + } + + public static void IsNull(T value) + { + if (value != null) + { + throw new AssertFailedException("", value); + } + } + + public static void IsNotNull(T value) + { + if (value == null) + { + throw new AssertFailedException("not null", ""); + } + } + + public static void Throws(Action action) where T : Exception + { + var caught = false; + try + { + action(); + } + catch (T) + { + caught = true; + } + + if (!caught) + { + throw new AssertUnexpectedThrowException(typeof (T)); + } + } + } +} diff --git a/net/FlatSpanBuffers.Tests/ByteBufferTests.cs b/net/FlatSpanBuffers.Tests/ByteBufferTests.cs new file mode 100644 index 00000000000..9806bf95b86 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/ByteBufferTests.cs @@ -0,0 +1,911 @@ +/* + * Copyright 2014 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 Google.FlatSpanBuffers.Tests +{ + // Copied from: tests/FlatBuffers.Test/ByteBufferTests.cs + // Adapted for Google.FlatSpanBuffers namespace and API + [FlatBuffersTestClass] + public class ByteBufferTests + { + [FlatBuffersTestMethod] + public void ByteBuffer_Length_MatchesBufferLength() + { + var buffer = new byte[1000]; + var uut = new ByteBuffer(buffer); + Assert.AreEqual(buffer.Length, uut.Length); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutBytePopulatesBufferAtZeroOffset() + { + var buffer = new byte[1]; + var uut = new ByteBuffer(buffer); + uut.PutByte(0, (byte)99); + + Assert.AreEqual((byte)99, buffer[0]); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutByteCannotPutAtOffsetPastLength() + { + var uut = new ByteBuffer(1); + Assert.Throws(() => uut.PutByte(1, 99)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutShortPopulatesBufferCorrectly() + { + var buffer = new byte[2]; + var uut = new ByteBuffer(buffer); + uut.Put(0, (short)1); + + // Ensure Endianness was written correctly + Assert.AreEqual((byte)1, buffer[0]); + Assert.AreEqual((byte)0, buffer[1]); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutShortCannotPutAtOffsetPastLength() + { + var uut = new ByteBuffer(2); + Assert.Throws(() => uut.Put(2, 99)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutShortChecksLength() + { + var uut = new ByteBuffer(1); + Assert.Throws(() => uut.Put(0, 99)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutShortChecksLengthAndOffset() + { + var uut = new ByteBuffer(2); + Assert.Throws(() => uut.Put(1, 99)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutIntPopulatesBufferCorrectly() + { + var buffer = new byte[4]; + var uut = new ByteBuffer(buffer); + uut.Put(0, 0x0A0B0C0D); + + // Ensure Endianness was written correctly + Assert.AreEqual((byte)0x0D, buffer[0]); + Assert.AreEqual((byte)0x0C, buffer[1]); + Assert.AreEqual((byte)0x0B, buffer[2]); + Assert.AreEqual((byte)0x0A, buffer[3]); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutIntCannotPutAtOffsetPastLength() + { + var uut = new ByteBuffer(4); + Assert.Throws(() => uut.Put(2, 0x0A0B0C0D)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutIntChecksLength() + { + var uut = new ByteBuffer(1); + Assert.Throws(() => uut.Put(0, 0x0A0B0C0D)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutIntChecksLengthAndOffset() + { + var uut = new ByteBuffer(4); + Assert.Throws(() => uut.Put(2, 0x0A0B0C0D)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutLongPopulatesBufferCorrectly() + { + var buffer = new byte[8]; + var uut = new ByteBuffer(buffer); + uut.Put(0, 0x010203040A0B0C0D); + + // Ensure Endianness was written correctly + Assert.AreEqual((byte)0x0D, buffer[0]); + Assert.AreEqual((byte)0x0C, buffer[1]); + Assert.AreEqual((byte)0x0B, buffer[2]); + Assert.AreEqual((byte)0x0A, buffer[3]); + Assert.AreEqual((byte)0x04, buffer[4]); + Assert.AreEqual((byte)0x03, buffer[5]); + Assert.AreEqual((byte)0x02, buffer[6]); + Assert.AreEqual((byte)0x01, buffer[7]); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutLongCannotPutAtOffsetPastLength() + { + var uut = new ByteBuffer(8); + Assert.Throws(() => uut.Put(2, 0x010203040A0B0C0D)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutLongChecksLength() + { + var uut = new ByteBuffer(1); + Assert.Throws(() => uut.Put(0, 0x010203040A0B0C0D)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutLongChecksLengthAndOffset() + { + var uut = new ByteBuffer(8); + Assert.Throws(() => uut.Put(2, 0x010203040A0B0C0D)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetByteReturnsCorrectData() + { + var buffer = new byte[1]; + buffer[0] = 99; + var uut = new ByteBuffer(buffer); + Assert.AreEqual((byte)99, uut.Get(0)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetByteChecksOffset() + { + var uut = new ByteBuffer(1); + Assert.Throws(() => uut.Get(1)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetShortReturnsCorrectData() + { + var buffer = new byte[2]; + buffer[0] = 1; + buffer[1] = 0; + var uut = new ByteBuffer(buffer); + Assert.AreEqual((short)1, uut.Get(0)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetShortChecksOffset() + { + var uut = new ByteBuffer(2); + Assert.Throws(() => uut.Get(2)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetShortChecksLength() + { + var uut = new ByteBuffer(2); + Assert.Throws(() => uut.Get(1)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetIntReturnsCorrectData() + { + 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.Get(0)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetIntChecksOffset() + { + var uut = new ByteBuffer(4); + Assert.Throws(() => uut.Get(4)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetIntChecksLength() + { + var uut = new ByteBuffer(2); + Assert.Throws(() => uut.Get(0)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetLongReturnsCorrectData() + { + var buffer = new byte[8]; + buffer[0] = 0x0D; + buffer[1] = 0x0C; + buffer[2] = 0x0B; + buffer[3] = 0x0A; + buffer[4] = 0x04; + buffer[5] = 0x03; + buffer[6] = 0x02; + buffer[7] = 0x01; + var uut = new ByteBuffer(buffer); + Assert.AreEqual(0x010203040A0B0C0D, uut.Get(0)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetLongChecksOffset() + { + var uut = new ByteBuffer(8); + Assert.Throws(() => uut.Get(8)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetLongChecksLength() + { + var uut = new ByteBuffer(7); + Assert.Throws(() => uut.Get(0)); + } + + [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); + + var fullArray = uut.ToSpan(0, buffer.Length); + Assert.SpanEqual(buffer, fullArray); + } + + [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); + + var sizedArray = uut.ToSizedSpan(); + Assert.SpanEqual(buffer, sizedArray); + } + + [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.Get(0)); + + uut.Position = 2; + var dup = new ByteBuffer(buffer, uut.Position, buffer.Length); + Assert.AreEqual(0x0A0B, dup.Get(2)); + + dup.Position = 1; + var dup2 = new ByteBuffer(buffer, dup.Position, buffer.Length); + Assert.AreEqual(0x0A, dup2.Get(3)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_To_Array_Float() + { + const int len = 9; + + var fData = new float[len]; + fData[0] = 1.0079F; + fData[1] = 4.0026F; + fData[2] = 6.941F; + fData[3] = 9.0122F; + fData[4] = 10.811F; + fData[5] = 12.0107F; + fData[6] = 14.0067F; + fData[7] = 15.9994F; + fData[8] = 18.9984F; + + var buffer = new byte[sizeof(float) * fData.Length]; + Buffer.BlockCopy(fData, 0, buffer, 0, buffer.Length); + + var uut = new ByteBuffer(buffer); + + var bbSpan = uut.GetSpan(0, len); + Assert.SpanEqual(fData, bbSpan); + + var bbSpan2 = uut.GetSpan(sizeof(float), len - 1); + Assert.AreEqual(bbSpan2.Length, len - 1); + for (int i = 1; i < len - 1; i++) + { + Assert.AreEqual(fData[i], bbSpan2[i - 1]); + } + + var bbSpan3 = uut.GetSpan(sizeof(float) * 2, len - 4); + Assert.AreEqual(bbSpan3.Length, len - 4); + for (int i = 2; i < len - 4; i++) + { + Assert.AreEqual(fData[i], bbSpan3[i - 2]); + } + } + + private static void ByteBuffer_Put_Span_Helper(ReadOnlySpan data, int typeSize) + where T : unmanaged, IEquatable + { + // Create the Byte Buffer + var uut = new ByteBuffer(1024); + + // Put the data into the buffer and make sure the offset is + // calculated correctly + int nOffset = 1024 - typeSize * data.Length; + uut.PutSpan(nOffset, data); + + // Get the full span back out and ensure they are the same + var bbSpan = uut.GetSpan(nOffset, data.Length); + Assert.SpanEqual(data, bbSpan); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Put_Array_Float() + { + const int len = 9; + + // Construct the data array + Span data = stackalloc float[len]; + data[0] = 1.0079F; + data[1] = 4.0026F; + data[2] = 6.941F; + data[3] = 9.0122F; + data[4] = 10.811F; + data[5] = 12.0107F; + data[6] = 14.0067F; + data[7] = 15.9994F; + data[8] = 18.9984F; + + ByteBuffer_Put_Span_Helper(data, sizeof(float)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Put_Array_Double() + { + const int len = 9; + + // Construct the data array + Span data = stackalloc double[len]; + data[0] = 1.0079; + data[1] = 4.0026; + data[2] = 6.941; + data[3] = 9.0122; + data[4] = 10.811; + data[5] = 12.0107; + data[6] = 14.0067; + data[7] = 15.9994; + data[8] = 18.9984; + + ByteBuffer_Put_Span_Helper(data, sizeof(double)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Put_Array_Int() + { + const int len = 9; + + // Construct the data array + Span data = stackalloc int[len]; + data[0] = 1; + data[1] = 4; + data[2] = 6; + data[3] = 9; + data[4] = 10; + data[5] = 12; + data[6] = 14; + data[7] = 15; + data[8] = 18; + + ByteBuffer_Put_Span_Helper(data, sizeof(int)); + } + + + [FlatBuffersTestMethod] + public void ByteBuffer_Put_Array_UInt() + { + const int len = 9; + + // Construct the data array + Span data = stackalloc uint[len]; + data[0] = 1; + data[1] = 4; + data[2] = 6; + data[3] = 9; + data[4] = 10; + data[5] = 12; + data[6] = 14; + data[7] = 15; + data[8] = 18; + + ByteBuffer_Put_Span_Helper(data, sizeof(uint)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Put_Array_Bool() + { + const int len = 9; + + // Construct the data array + Span data = stackalloc bool[len]; + data[0] = true; + data[1] = true; + data[2] = false; + data[3] = true; + data[4] = false; + data[5] = true; + data[6] = true; + data[7] = true; + data[8] = false; + + ByteBuffer_Put_Span_Helper(data, sizeof(bool)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Put_Array_Long() + { + const int len = 9; + + // Construct the data array + Span data = stackalloc long[len]; + data[0] = 1; + data[1] = 4; + data[2] = 6; + data[3] = 9; + data[4] = 10; + data[5] = 12; + data[6] = 14; + data[7] = 15; + data[8] = 18; + + ByteBuffer_Put_Span_Helper(data, sizeof(long)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Put_Array_Byte() + { + const int len = 9; + + // Construct the data array + Span data = stackalloc byte[len]; + data[0] = 1; + data[1] = 4; + data[2] = 6; + data[3] = 9; + data[4] = 10; + data[5] = 12; + data[6] = 14; + data[7] = 15; + data[8] = 18; + + ByteBuffer_Put_Span_Helper(data, sizeof(byte)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Put_Array_SByte() + { + const int len = 9; + + // Construct the data array + Span data = stackalloc sbyte[len]; + data[0] = 1; + data[1] = 4; + data[2] = 6; + data[3] = 9; + data[4] = 10; + data[5] = 12; + data[6] = 14; + data[7] = 15; + data[8] = 18; + + ByteBuffer_Put_Span_Helper(data, sizeof(sbyte)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Get_Double() + { + var uut = new ByteBuffer(1024); + double value = 3.14159265; + uut.Put(900, value); + double getValue = uut.Get(900); + Assert.AreEqual(value, getValue); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Get_Float() + { + var uut = new ByteBuffer(1024); + float value = 3.14159265F; + uut.Put(900, value); + float getValue = uut.Get(900); + Assert.AreEqual(value, getValue); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_ToSizedSpan_MatchesBuffer() + { + var buffer = new byte[4]; + buffer[0] = 0x0D; + buffer[1] = 0x0C; + buffer[2] = 0x0B; + buffer[3] = 0x0A; + var uut = new ByteBuffer(buffer); + var span = uut.ToSizedSpan(); + Assert.SpanEqual(buffer, span); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_ToSpan_MatchesBuffer() + { + var buffer = new byte[4]; + buffer[0] = 0x0D; + buffer[1] = 0x0C; + buffer[2] = 0x0B; + buffer[3] = 0x0A; + var uut = new ByteBuffer(buffer); + var span = uut.ToSpan(0, 4); + Assert.SpanEqual(buffer, span); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_SlicedToSizedSpan_MatchesBuffer() + { + var buffer = new byte[8]; + buffer[0] = 0x0D; + buffer[1] = 0x0C; + buffer[2] = 0x0B; + buffer[3] = 0x0A; + buffer[4] = 0x09; + buffer[5] = 0x08; + buffer[6] = 0x07; + buffer[7] = 0x06; + + var uut = new ByteBuffer(buffer, 2, 6); + var span = uut.ToSizedSpan(); + Assert.SpanEqual(buffer.AsSpan(2, 4), span); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_SlicedToSpan_MatchesBuffer() + { + var buffer = new byte[4]; + buffer[0] = 0x0D; + buffer[1] = 0x0C; + buffer[2] = 0x0B; + buffer[3] = 0x0A; + var uut = new ByteBuffer(buffer); + var span = uut.ToSpan(1, 2); + Assert.SpanEqual(buffer.AsSpan(1, 2), span); + + span[0] = 0xAA; + Assert.AreEqual((byte)0xAA, buffer[1]); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_GetSpan_Float() + { + const int len = 9; + var fData = new float[len]; + fData[0] = 1.0079F; + fData[1] = 4.0026F; + fData[2] = 6.941F; + fData[3] = 9.0122F; + fData[4] = 10.811F; + fData[5] = 12.0107F; + fData[6] = 14.0067F; + fData[7] = 15.9994F; + fData[8] = 18.9984F; + + var buffer = new byte[sizeof(float) * fData.Length]; + Buffer.BlockCopy(fData, 0, buffer, 0, buffer.Length); + var uut = new ByteBuffer(buffer); + + // Get the full span back out and ensure they are the same + var bbSpan = uut.GetSpan(0, len); + Assert.SpanEqual(fData, bbSpan); + + // Get a portion of the span back out and ensure the subrange matches + var bbSpan2 = uut.GetSpan(sizeof(float), len - 1); + Assert.AreEqual(bbSpan2.Length, len - 1); + for (int i = 1; i < len - 1; i++) + { + Assert.AreEqual(fData[i], bbSpan2[i - 1]); + } + + // Get a sub portion of the span back out and ensure the subrange matches + var bbSpan3 = uut.GetSpan(sizeof(float) * 2, len - 4); + Assert.AreEqual(bbSpan3.Length, len - 4); + for (int i = 2; i < len - 4; i++) + { + Assert.AreEqual(fData[i], bbSpan3[i - 2]); + } + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutSpan_Float() + { + const int len = 9; + Span data = stackalloc float[len]; + data[0] = 1.0079F; + data[1] = 4.0026F; + data[2] = 6.941F; + data[3] = 9.0122F; + data[4] = 10.811F; + data[5] = 12.0107F; + data[6] = 14.0067F; + data[7] = 15.9994F; + data[8] = 18.9984F; + + var uut = new ByteBuffer(1024); + uut.PutSpan(0, data); + + // Get the full span back out and ensure they are the same + var bbSpan = uut.GetSpan(0, len); + Assert.SpanEqual(data, bbSpan); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutSpan_Double() + { + const int len = 9; + Span data = stackalloc double[len]; + data[0] = 1.0079; + data[1] = 4.0026; + data[2] = 6.941; + data[3] = 9.0122; + data[4] = 10.811; + data[5] = 12.0107; + data[6] = 14.0067; + data[7] = 15.9994; + data[8] = 18.9984; + + var uut = new ByteBuffer(1024); + uut.PutSpan(0, data); + + // Get the full span back out and ensure they are the same + var bbSpan = uut.GetSpan(0, len); + Assert.SpanEqual(data, bbSpan); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutSpan_Int() + { + const int len = 9; + Span data = stackalloc int[len]; + data[0] = 1; + data[1] = 4; + data[2] = 6; + data[3] = 9; + data[4] = 10; + data[5] = 12; + data[6] = 14; + data[7] = 15; + data[8] = 18; + + var uut = new ByteBuffer(1024); + uut.PutSpan(0, data); + + // Get the full span back out and ensure they are the same + var bbSpan = uut.GetSpan(0, len); + Assert.SpanEqual(data, bbSpan); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutSpan_UInt() + { + const int len = 9; + Span data = stackalloc uint[len]; + data[0] = 1; + data[1] = 4; + data[2] = 6; + data[3] = 9; + data[4] = 10; + data[5] = 12; + data[6] = 14; + data[7] = 15; + data[8] = 18; + + var uut = new ByteBuffer(1024); + uut.PutSpan(0, data); + + // Get the full span back out and ensure they are the same + var bbSpan = uut.GetSpan(0, len); + Assert.SpanEqual(data, bbSpan); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutSpan_Long() + { + const int len = 9; + Span data = stackalloc long[len]; + data[0] = 1; + data[1] = 4; + data[2] = 6; + data[3] = 9; + data[4] = 10; + data[5] = 12; + data[6] = 14; + data[7] = 15; + data[8] = 18; + + var uut = new ByteBuffer(1024); + uut.PutSpan(0, data); + + // Get the full span back out and ensure they are the same + var bbSpan = uut.GetSpan(0, len); + Assert.SpanEqual(data, bbSpan); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutSpan_Byte() + { + const int len = 9; + Span data = stackalloc byte[len]; + data[0] = 1; + data[1] = 4; + data[2] = 6; + data[3] = 9; + data[4] = 10; + data[5] = 12; + data[6] = 14; + data[7] = 15; + data[8] = 18; + + var uut = new ByteBuffer(1024); + uut.PutSpan(0, data); + + // Get the full span back out and ensure they are the same + var bbSpan = uut.GetSpan(0, len); + Assert.SpanEqual(data, bbSpan); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutSpan_SByte() + { + const int len = 9; + Span data = stackalloc sbyte[len]; + data[0] = 1; + data[1] = 4; + data[2] = 6; + data[3] = 9; + data[4] = 10; + data[5] = 12; + data[6] = 14; + data[7] = 15; + data[8] = 18; + + var uut = new ByteBuffer(1024); + uut.PutSpan(0, data); + + // Get the full span back out and ensure they are the same + var bbSpan = uut.GetSpan(0, len); + Assert.SpanEqual(data, bbSpan); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Position_SetsCorrectly() + { + var buffer = new byte[100]; + var uut = new ByteBuffer(buffer); + + Assert.AreEqual(0, uut.Position); + + uut.Position = 50; + Assert.AreEqual(50, uut.Position); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_Reset_SetsPositionToZero() + { + var buffer = new byte[100]; + var uut = new ByteBuffer(buffer); + + uut.Position = 50; + Assert.AreEqual(50, uut.Position); + + uut.Reset(); + Assert.AreEqual(0, uut.Position); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PartialBuffer_HasCorrectLength() + { + var buffer = new byte[1000]; + // Create a ByteBuffer that only uses part of the buffer + var uut = new ByteBuffer(buffer, 100, 500); + + Assert.AreEqual(500, uut.Length); + Assert.AreEqual(100, uut.Position); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PutAndGetSbyte() + { + var buffer = new byte[10]; + var uut = new ByteBuffer(buffer); + + uut.PutSbyte(0, -42); + Assert.AreEqual((sbyte)-42, uut.GetSbyte(0)); + + uut.PutSbyte(1, 127); + Assert.AreEqual((sbyte)127, uut.GetSbyte(1)); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_PadBytes() + { + var buffer = new byte[10]; + var uut = new ByteBuffer(buffer); + + buffer[2] = 99; + buffer[3] = 99; + buffer[4] = 99; + buffer[5] = 99; + buffer[6] = 99; + uut.PadBytes(2, 5); + + Assert.AreEqual((byte)0, buffer[0]); + Assert.AreEqual((byte)0, buffer[1]); + Assert.AreEqual((byte)0, buffer[2]); + Assert.AreEqual((byte)0, buffer[3]); + Assert.AreEqual((byte)0, buffer[4]); + Assert.AreEqual((byte)0, buffer[5]); + Assert.AreEqual((byte)0, buffer[6]); + Assert.AreEqual((byte)0, buffer[7]); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_StringUTF8_RoundTrip() + { + var uut = new ByteBuffer(1024); + var testString = "Hello, World!"; + + uut.PutStringUTF8(0, testString.AsSpan()); + var readString = uut.GetStringUTF8(0, testString.Length); + + Assert.AreEqual(testString, readString); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_StringUTF8_Unicode() + { + var uut = new ByteBuffer(1024); + var testString = "Hello, UTF-8: \u4e16\u754c"; + + var byteCount = System.Text.Encoding.UTF8.GetByteCount(testString); + uut.PutStringUTF8(0, testString.AsSpan()); + + var readString = uut.GetStringUTF8(0, byteCount); + Assert.AreEqual(testString, readString); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_ResetWithNewBuffer() + { + var buffer1 = new byte[100]; + var uut = new ByteBuffer(buffer1); + + Assert.AreEqual(100, uut.Length); + + var buffer2 = new byte[200]; + uut.Reset(buffer2, 10, 150); + + Assert.AreEqual(150, uut.Length); + Assert.AreEqual(10, uut.Position); + } + } +} diff --git a/net/FlatSpanBuffers.Tests/FlatBufferBuilderTests.cs b/net/FlatSpanBuffers.Tests/FlatBufferBuilderTests.cs new file mode 100644 index 00000000000..d2d8fe50634 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/FlatBufferBuilderTests.cs @@ -0,0 +1,417 @@ +/* + * Copyright 2016 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 Google.FlatSpanBuffers.Tests +{ + [FlatBuffersTestClass] + public class FlatBufferBuilderTests + { + private FlatBufferBuilder CreateBuffer(bool forceDefaults = true) + { + var fbb = new FlatBufferBuilder(16) {ForceDefaults = forceDefaults}; + fbb.StartTable(1); + return fbb; + } + + private void AssertOffsetDelta(bool forceDefaults, int expectedDelta, Action add) + { + var fbb = CreateBuffer(forceDefaults); + var startOffset = fbb.Offset; + add(fbb); + Assert.AreEqual(expectedDelta, fbb.Offset - startOffset); + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_WithForceDefaults_DefaultValues_AdvanceOffsetBySize() + { + var cases = new (int Size, Action Add)[] + { + (sizeof(bool), fbb => fbb.Add(0, false, false)), + (sizeof(sbyte), fbb => fbb.Add(0, 0, 0)), + (sizeof(byte), fbb => fbb.Add(0, 0, 0)), + (sizeof(short), fbb => fbb.Add(0, 0, 0)), + (sizeof(ushort), fbb => fbb.Add(0, 0, 0)), + (sizeof(int), fbb => fbb.Add(0, 0, 0)), + (sizeof(uint), fbb => fbb.Add(0, 0, 0)), + (sizeof(long), fbb => fbb.Add(0, 0, 0)), + (sizeof(ulong), fbb => fbb.Add(0, 0, 0)), + (sizeof(float), fbb => fbb.Add(0, 0, 0)), + (sizeof(double), fbb => fbb.Add(0, 0, 0)), + }; + + foreach (var testCase in cases) + { + AssertOffsetDelta(forceDefaults: true, expectedDelta: testCase.Size, add: testCase.Add); + } + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_WithoutForceDefaults_DefaultValues_DoNotAdvanceOffset() + { + var cases = new Action[] + { + fbb => fbb.Add(0, false, false), + fbb => fbb.Add(0, 0, 0), + fbb => fbb.Add(0, 0, 0), + fbb => fbb.Add(0, 0, 0), + fbb => fbb.Add(0, 0, 0), + fbb => fbb.Add(0, 0, 0), + fbb => fbb.Add(0, 0, 0), + fbb => fbb.Add(0, 0, 0), + fbb => fbb.Add(0, 0, 0), + fbb => fbb.Add(0, 0, 0), + fbb => fbb.Add(0, 0, 0), + }; + + foreach (var add in cases) + { + AssertOffsetDelta(forceDefaults: false, expectedDelta: 0, add: add); + } + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_WithoutForceDefaults_NullableNull_DoesNotAdvanceOffset() + { + var cases = new Action[] + { + fbb => fbb.Add(0, (bool?)null), + fbb => fbb.Add(0, (sbyte?)null), + fbb => fbb.Add(0, (byte?)null), + fbb => fbb.Add(0, (short?)null), + fbb => fbb.Add(0, (ushort?)null), + fbb => fbb.Add(0, (int?)null), + fbb => fbb.Add(0, (uint?)null), + fbb => fbb.Add(0, (long?)null), + fbb => fbb.Add(0, (ulong?)null), + fbb => fbb.Add(0, (float?)null), + fbb => fbb.Add(0, (double?)null), + }; + + foreach (var add in cases) + { + AssertOffsetDelta(forceDefaults: false, expectedDelta: 0, add: add); + } + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_WithoutForceDefaults_NullableNonNull_AdvancesOffsetBySize() + { + var cases = new (int Size, Action Add)[] + { + (sizeof(bool), fbb => fbb.Add(0, (bool?)true)), + (sizeof(sbyte), fbb => fbb.Add(0, (sbyte?)1)), + (sizeof(byte), fbb => fbb.Add(0, (byte?)1)), + (sizeof(short), fbb => fbb.Add(0, (short?)1)), + (sizeof(ushort), fbb => fbb.Add(0, (ushort?)1)), + (sizeof(int), fbb => fbb.Add(0, (int?)1)), + (sizeof(uint), fbb => fbb.Add(0, (uint?)1)), + (sizeof(long), fbb => fbb.Add(0, (long?)1)), + (sizeof(ulong), fbb => fbb.Add(0, (ulong?)1)), + (sizeof(float), fbb => fbb.Add(0, (float?)1.0F)), + (sizeof(double), fbb => fbb.Add(0, (double?)1.0)), + }; + + foreach (var testCase in cases) + { + AssertOffsetDelta(forceDefaults: false, expectedDelta: testCase.Size, add: testCase.Add); + } + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_AddSpan_Array_AdvancesOffsetByElementSizeTimesLength() + { + var cases = new (int ExpectedDelta, Action Add)[] + { + (sizeof(float) * 9, fbb => fbb.AddSpan(new[] { 1.25F, -2.5F, 3.75F, -4.0F, 5.5F, -6.25F, 7.0F, -8.875F, 9.125F })), + (sizeof(bool) * 9, fbb => fbb.AddSpan(new[] { true, false, true, true, false, false, true, false, true })), + (sizeof(double) * 9, fbb => fbb.AddSpan(new[] { 1.0, -2.0, 3.5, -4.5, 5.25, -6.75, 7.125, -8.875, 9.5 })), + }; + + foreach (var testCase in cases) + { + AssertOffsetDelta(forceDefaults: false, expectedDelta: testCase.ExpectedDelta, add: testCase.Add); + } + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_AddSpan_StackallocSpan_AdvancesOffsetByElementSizeTimesLength() + { + const int len = 9; + + AssertOffsetDelta(forceDefaults: false, expectedDelta: sizeof(float) * len, add: fbb => + { + Span data = stackalloc float[] { 1.25F, -2.5F, 3.75F, -4.0F, 5.5F, -6.25F, 7.0F, -8.875F, 9.125F }; + fbb.AddSpan(data); + }); + + AssertOffsetDelta(forceDefaults: false, expectedDelta: sizeof(bool) * len, add: fbb => + { + Span data = stackalloc bool[] { true, false, true, true, false, false, true, false, true }; + fbb.AddSpan(data); + }); + + AssertOffsetDelta(forceDefaults: false, expectedDelta: sizeof(double) * len, add: fbb => + { + Span data = stackalloc double[] { 1.0, -2.0, 3.5, -4.5, 5.25, -6.75, 7.125, -8.875, 9.5 }; + fbb.AddSpan(data); + }); + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_AddSpan_Empty_DoesNotAdvanceOffset() + { + AssertOffsetDelta(forceDefaults: false, expectedDelta: 0, add: fbb => fbb.AddSpan(Array.Empty())); + AssertOffsetDelta(forceDefaults: false, expectedDelta: 0, add: fbb => fbb.AddSpan(Span.Empty)); + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_AddSpan_Vector_RoundTripsValuesInOrder() + { + var expected = new[] { 1.25F, -2.5F, 3.75F, -4.0F, 5.5F }; + + var fbb = new FlatBufferBuilder(64); + fbb.StartVector(sizeof(float), expected.Length, sizeof(float)); + fbb.AddSpan(expected); + var vectorOffset = fbb.EndVector(); + + fbb.StartTable(1); + fbb.AddOffset(0, vectorOffset.Value, 0); + var rootTable = fbb.EndTable(); + fbb.Finish(rootTable); + + var bb = new ByteBuffer(fbb.SizedReadOnlySpan().ToArray()); + int rootOffset = bb.Get(bb.Position); + int rootTablePos = bb.Position + rootOffset; + int vtableOffset = rootTablePos - bb.Get(rootTablePos); + int fieldOffset = bb.Get(vtableOffset + 4); + + Assert.IsFalse(fieldOffset == 0); + + int fieldPos = rootTablePos + fieldOffset; + int vectorStart = fieldPos + bb.Get(fieldPos); + int count = bb.Get(vectorStart); + int dataStart = vectorStart + sizeof(int); + + Assert.AreEqual(expected.Length, count); + + for (int i = 0; i < expected.Length; i++) + { + float actual = bb.Get(dataStart + (i * sizeof(float))); + Assert.AreEqual(expected[i], actual); + } + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_Add_null_String() + { + var fbb = new FlatBufferBuilder(16); + string s = null; + Assert.AreEqual(fbb.CreateSharedString(s).Value, 0); + Assert.AreEqual(fbb.CreateString(s).Value, 0); + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_Empty_Builder() + { + var fbb = new FlatBufferBuilder(16); + var str = "Hello"; + var flatbuffer = "Flatbuffers!"; + var strOffset = fbb.CreateSharedString(str); + var flatbufferOffset = fbb.CreateSharedString(flatbuffer); + fbb.Clear(); + var flatbufferOffset2 = fbb.CreateSharedString(flatbuffer); + var strOffset2 = fbb.CreateSharedString(str); + Assert.IsFalse(strOffset.Value == strOffset2.Value); + Assert.IsFalse(flatbufferOffset.Value == flatbufferOffset2.Value); + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_VTable_GrowsWhenTableHasMoreFieldsThanInitialSize() + { + var fbb = new FlatBufferBuilder( + new ByteBuffer(256), + vtableSpace: new int[2], + vtableOffsetSpace: new int[16]); + fbb.ForceDefaults = true; + + const int numFields = 8; + fbb.StartTable(numFields); + + for (int i = 0; i < numFields; i++) + { + fbb.Add(i, i + 100, 0); + } + + int tableOffset = fbb.EndTable(); + fbb.Finish(tableOffset); + + var bytes = fbb.SizedReadOnlySpan(); + Assert.IsTrue(bytes.Length > 0); + + var bb = new ByteBuffer(bytes.ToArray()); + int rootOffset = bb.Get(bb.Position); + int tableStart = bb.Position + rootOffset; + int vtableOffset = tableStart - bb.Get(tableStart); + + short vtableSize = bb.Get(vtableOffset); + int expectedVtableSize = (2 + numFields) * sizeof(short); + Assert.AreEqual(expectedVtableSize, vtableSize); + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_VTables_GrowsWhenMoreTablesThanInitialSize() + { + var fbb = new FlatBufferBuilder( + new ByteBuffer(1024), + vtableSpace: new int[16], + vtableOffsetSpace: new int[2]); + fbb.ForceDefaults = true; + + const int numTables = 8; + Span tableOffsets = stackalloc int[numTables]; + + for (int t = 0; t < numTables; t++) + { + // Create tables with different field counts to ensure unique vtables + int fieldCount = t + 1; + fbb.StartTable(fieldCount); + + for (int f = 0; f < fieldCount; f++) + { + fbb.Add(f, (t * 100) + f, 0); + } + + tableOffsets[t] = fbb.EndTable(); + } + + fbb.StartVector(sizeof(int), numTables, sizeof(int)); + fbb.AddOffsetSpan(tableOffsets); + var tableVector = fbb.EndVector(); + + // Create a wrapper table containing all the sub-tables + fbb.StartTable(1); + fbb.AddOffset(0, tableVector.Value, 0); + var rootTable = fbb.EndTable(); + fbb.Finish(rootTable); + + var bytes = fbb.SizedReadOnlySpan(); + Assert.IsTrue(bytes.Length > 0); + + var bb = new ByteBuffer(bytes.ToArray()); + int rootOffset = bb.Get(bb.Position); + int rootTablePos = bb.Position + rootOffset; + var tablePositions = ReadTablePositionsFromVector(bb, rootTablePos, 0); + Assert.AreEqual(numTables, tablePositions.Length); + + var uniqueVtables = new System.Collections.Generic.HashSet(); + for (int i = 0; i < tablePositions.Length; i++) + { + int vtableOffset = tablePositions[i] - bb.Get(tablePositions[i]); + uniqueVtables.Add(vtableOffset); + } + + Assert.AreEqual(numTables, uniqueVtables.Count); + } + + [FlatBuffersTestMethod] + public void FlatBufferBuilder_VTableAndVTables_BothGrowDynamically() + { + var fbb = new FlatBufferBuilder( + new ByteBuffer(2048), + vtableSpace: new int[1], + vtableOffsetSpace: new int[1]); + fbb.ForceDefaults = true; + + // Create multiple tables each with many fields + const int numTables = 5; + const int numFieldsPerTable = 10; + Span tableOffsets = stackalloc int[numTables]; + + for (int t = 0; t < numTables; t++) + { + // Start table with more fields than initial vtable capacity + fbb.StartTable(numFieldsPerTable); + + // Add different values per table to ensure unique vtables + for (int f = 0; f < numFieldsPerTable; f++) + { + // Use different default values per table to force unique vtables + if (f < t + 1) + fbb.Add(f, (t * 1000) + f, 0); + } + + tableOffsets[t] = fbb.EndTable(); + } + + fbb.StartVector(sizeof(int), numTables, sizeof(int)); + fbb.AddOffsetSpan(tableOffsets); + var tableVector = fbb.EndVector(); + + fbb.StartTable(1); + fbb.AddOffset(0, tableVector.Value, 0); + var rootTable = fbb.EndTable(); + fbb.Finish(rootTable); + + var bytes = fbb.SizedReadOnlySpan(); + Assert.IsTrue(bytes.Length > 0); + + var bb = new ByteBuffer(bytes.ToArray()); + int rootOffset = bb.Get(bb.Position); + int rootTablePos = bb.Position + rootOffset; + var tablePositions = ReadTablePositionsFromVector(bb, rootTablePos, 0); + Assert.AreEqual(numTables, tablePositions.Length); + + var uniqueVtables = new System.Collections.Generic.HashSet(); + for (int i = 0; i < tablePositions.Length; i++) + { + int vtableOffset = tablePositions[i] - bb.Get(tablePositions[i]); + uniqueVtables.Add(vtableOffset); + } + + Assert.AreEqual(numTables, uniqueVtables.Count); + + int sampleTablePos = tablePositions[tablePositions.Length - 1]; + int sampleVtableOffset = sampleTablePos - bb.Get(sampleTablePos); + short vtableSize = bb.Get(sampleVtableOffset); + int expectedVtableSize = (2 + numTables) * sizeof(short); + Assert.AreEqual(expectedVtableSize, vtableSize); + } + + private static int[] ReadTablePositionsFromVector(ByteBuffer bb, int rootTablePos, int fieldIndex) + { + int vtableOffset = rootTablePos - bb.Get(rootTablePos); + int fieldOffset = bb.Get(vtableOffset + 4 + (fieldIndex * sizeof(short))); + if (fieldOffset == 0) + return Array.Empty(); + + int fieldPos = rootTablePos + fieldOffset; + int vectorStart = fieldPos + bb.Get(fieldPos); + int count = bb.Get(vectorStart); + int dataStart = vectorStart + sizeof(int); + + var positions = new int[count]; + for (int i = 0; i < count; i++) + { + int elemOffset = bb.Get(dataStart + (i * sizeof(int))); + positions[i] = dataStart + (i * sizeof(int)) + elemOffset; + } + + return positions; + } + } +} diff --git a/net/FlatSpanBuffers.Tests/FlatBuffersExampleTests.cs b/net/FlatSpanBuffers.Tests/FlatBuffersExampleTests.cs new file mode 100644 index 00000000000..399c35e2b14 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/FlatBuffersExampleTests.cs @@ -0,0 +1,1670 @@ +/* + * Copyright 2014 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; +using System.IO; +using System.Text; +using System.Threading; +using Google.FlatSpanBuffers.Utils; +using MyGame.Example; +using optional_scalars; +using KeywordTest; + +namespace Google.FlatSpanBuffers.Tests +{ + // Copied from: tests/FlatBuffers.Test/FlatBuffersExampleTests.cs + // Adapted for Google.FlatSpanBuffers namespace and API + [FlatBuffersTestClass] + public class FlatBuffersExampleTests + { + [FlatBuffersTestMethod] + public void CanCreateNewFlatBufferFromScratch() + { + CanCreateNewFlatBufferFromScratch(false); + } + + [FlatBuffersTestMethod] + public void CanCreateNewFlatBufferFromScratchWithSizePrefix() + { + CanCreateNewFlatBufferFromScratch(true); + } + + 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, + // normally a size larger than the typical FlatBuffer you generate would be + // better for performance. + var fbb = new FlatBufferBuilder(1); + + // Create sorted monster names (Frodo, Barney, Wilma - will be sorted alphabetically) + StringOffset[] names = { fbb.CreateString("Frodo"), fbb.CreateString("Barney"), fbb.CreateString("Wilma") }; + Offset[] off = new Offset[3]; + Monster.StartMonster(fbb); + Monster.AddName(fbb, names[0]); + off[0] = Monster.EndMonster(fbb); + Monster.StartMonster(fbb); + Monster.AddName(fbb, names[1]); + off[1] = Monster.EndMonster(fbb); + Monster.StartMonster(fbb); + Monster.AddName(fbb, names[2]); + off[2] = Monster.EndMonster(fbb); + Span> monstersSpan = off; + var sortMons = Monster.CreateSortedVectorOfMonster(fbb, monstersSpan); + + // We set up the same values as monsterdata.json: + + var str = fbb.CreateString("MyMonster"); + var test1 = fbb.CreateString("test1"); + var test2 = fbb.CreateString("test2"); + + Span inventoryData = stackalloc byte[] { 0, 1, 2, 3, 4 }; + var inv = Monster.CreateInventoryVectorBlock(fbb, inventoryData); + + var fred = fbb.CreateString("Fred"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, fred); + var mon2 = Monster.EndMonster(fbb); + + Monster.StartTest4Vector(fbb, 2); + MyGame.Example.Test.CreateTest(fbb, (short)10, (sbyte)20); + MyGame.Example.Test.CreateTest(fbb, (short)30, (sbyte)40); + var test4 = fbb.EndVector(); + + Span testStrings = stackalloc StringOffset[] { test1, test2 }; + var testArrayOfString = Monster.CreateTestarrayofstringVectorBlock(fbb, testStrings); + + var longsVector = Monster.CreateVectorOfLongsVector(fbb, new long[] { 1, 100, 10000, 1000000, 100000000 }); + var doublesVector = Monster.CreateVectorOfDoublesVector(fbb, new double[] { -1.7976931348623157e+308, 0, 1.7976931348623157e+308 }); + + Monster.StartMonster(fbb); + Monster.AddPos(fbb, Vec3.CreateVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0, + Color.Green, (short)5, (sbyte)6)); + Monster.AddHp(fbb, (short)80); + Monster.AddName(fbb, str); + Monster.AddInventory(fbb, inv); + Monster.AddTestType(fbb, Any.Monster); + Monster.AddTest(fbb, mon2.Value); + Monster.AddTest4(fbb, test4); + Monster.AddTestarrayofstring(fbb, testArrayOfString); + Monster.AddTestbool(fbb, true); + Monster.AddTestarrayoftables(fbb, sortMons); + Monster.AddVectorOfLongs(fbb, longsVector); + Monster.AddVectorOfDoubles(fbb, doublesVector); + var mon = Monster.EndMonster(fbb); + + if (sizePrefix) + { + Monster.FinishSizePrefixedMonsterBuffer(fbb, mon); + } + else + { + Monster.FinishMonsterBuffer(fbb, mon); + } + + // Remove the size prefix if necessary for further testing + ByteBuffer dataBuffer = fbb.DataBuffer; + if (sizePrefix) + { + Assert.AreEqual(dataBuffer.GetSizePrefix() + FlatBufferConstants.SizePrefixLength, + dataBuffer.Length - dataBuffer.Position); + dataBuffer.RemoveSizePrefix(); + } + + // Now assert the buffer + TestBuffer(dataBuffer); + + // Accessing a vector of sorted by the key tables + Monster monster = Monster.GetRootAsMonster(dataBuffer); + var testarrayoftables = monster.Testarrayoftables; + Assert.IsTrue(testarrayoftables.HasValue); + var testarrayoftablesVec = testarrayoftables.Value; + Assert.AreEqual(testarrayoftablesVec[0].Name, "Barney"); + Assert.AreEqual(testarrayoftablesVec[1].Name, "Frodo"); + Assert.AreEqual(testarrayoftablesVec[2].Name, "Wilma"); + + // Example of searching for a table by the key + Assert.IsTrue(monster.TryGetTestarrayoftablesByKey("Frodo", out var frodo)); + Assert.AreEqual(frodo.Name, "Frodo"); + Assert.IsTrue(monster.TryGetTestarrayoftablesByKey("Barney", out var barney)); + Assert.AreEqual(barney.Name, "Barney"); + Assert.IsTrue(monster.TryGetTestarrayoftablesByKey("Wilma", out var wilma)); + Assert.AreEqual(wilma.Name, "Wilma"); + + // Test Object API + TestObjectAPI(monster); + } + + private void TestBuffer(ByteBuffer bb) + { + bool test = Monster.VerifyMonster(bb); + Assert.AreEqual(true, test); + + Monster monster = Monster.GetRootAsMonster(bb); + + Assert.AreEqual(80, monster.Hp); + Assert.AreEqual(150, monster.Mana); + Assert.AreEqual("MyMonster", monster.Name); + + var pos = monster.Pos.Value; + Assert.AreEqual(1.0f, pos.X, 6); + Assert.AreEqual(2.0f, pos.Y, 6); + Assert.AreEqual(3.0f, pos.Z, 6); + + Assert.AreEqual(3.0, pos.Test1, 6); + Assert.AreEqual(Color.Green, pos.Test2); + var t = pos.Test3; + Assert.AreEqual((short)5, t.A); + Assert.AreEqual((sbyte)6, t.B); + + Assert.AreEqual(Any.Monster, monster.TestType); + + var monster2 = monster.Test().Value; + Assert.AreEqual("Fred", monster2.Name); + + Assert.AreEqual(5, monster.Inventory.Value.Length); + var invsum = 0; + for (var i = 0; i < monster.Inventory.Value.Length; i++) + { + invsum += monster.Inventory.Value[i]; + } + Assert.AreEqual(10, invsum); + + // Get the inventory as span and subtract the sum to get it back to 0 + var inventorySpan = monster.Inventory.Value; + Assert.AreEqual(5, inventorySpan.Length); + foreach (var inv in inventorySpan) + { + invsum -= inv; + } + Assert.AreEqual(0, invsum); + + var test4 = monster.Test4; + Assert.IsTrue(test4.HasValue); + var test4Vec = test4.Value; + Assert.AreEqual(2, test4Vec.Length); + var test0 = test4Vec[0]; + var test1 = test4Vec[1]; + + Assert.AreEqual(100, test0.A + test0.B + test1.A + test1.B); + + var testarrayofstring = monster.Testarrayofstring; + Assert.IsTrue(testarrayofstring.HasValue); + var testarrayofstringVec = testarrayofstring.Value; + Assert.AreEqual(2, testarrayofstringVec.Length); + Assert.AreEqual("test1", testarrayofstringVec[0]); + Assert.AreEqual("test2", testarrayofstringVec[1]); + + Assert.AreEqual(true, monster.Testbool); + + var nameBytes = monster.GetNameBytes(); + Assert.AreEqual("MyMonster", Encoding.UTF8.GetString(nameBytes.ToArray(), 0, nameBytes.Length)); + + var testarrayofbools = monster.Testarrayofbools; + if (!testarrayofbools.HasValue) + { + Assert.IsFalse(testarrayofbools.HasValue); + } + else + { + Assert.IsTrue(testarrayofbools.Value.Length != 0); + } + + var vectorOfLongs = monster.VectorOfLongs; + Assert.IsTrue(vectorOfLongs.HasValue); + var longArray = vectorOfLongs.Value; + Assert.IsTrue(longArray.Length * 8 > 0); + + var vectorOfDoubles = monster.VectorOfDoubles; + Assert.IsTrue(vectorOfDoubles.HasValue); + var doublesArray = vectorOfDoubles.Value; + Assert.IsTrue(doublesArray.Length * 8 > 0); + } + + [FlatBuffersTestMethod] + public void CanReadCppGeneratedWireFile() + { + var data = File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, "monsterdata_test.mon")); + var bb = new ByteBuffer(data); + TestBuffer(bb); + TestObjectAPI(Monster.GetRootAsMonster(bb)); + } + + [FlatBuffersTestMethod] + public void CanReadJsonFile() + { + var jsonText = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "monsterdata_test.json")); + var mon = MonsterT.DeserializeFromJson(jsonText); + var fbb = new FlatBufferBuilder(1); + Monster.FinishMonsterBuffer(fbb, Monster.Pack(fbb, mon)); + TestBuffer(fbb.DataBuffer); + } + + [FlatBuffersTestMethod] + public void TestEnums() + { + Assert.AreEqual("Red", Color.Red.ToString()); + Assert.AreEqual("Blue", Color.Blue.ToString()); + Assert.AreEqual("NONE", Any.NONE.ToString()); + Assert.AreEqual("Monster", Any.Monster.ToString()); + } + + [FlatBuffersTestMethod] + public void TestVectorOfEnums() + { + const string monsterName = "TestVectorOfEnumsMonster"; + Span colorVec = stackalloc Color[] { Color.Red, Color.Green, Color.Blue }; + var fbb = new FlatBufferBuilder(32); + var str1 = fbb.CreateString(monsterName); + var vec1 = Monster.CreateVectorOfEnumsVector(fbb, colorVec); + Monster.StartMonster(fbb); + Monster.AddName(fbb, str1); + Monster.AddVectorOfEnums(fbb, vec1); + var monster1 = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, monster1); + + var mons = Monster.GetRootAsMonster(fbb.DataBuffer); + var colors = mons.VectorOfEnums.Value; + Assert.AreEqual(3, colors.Length); + Assert.AreEqual(Color.Red, colors[0]); + Assert.AreEqual(Color.Green, colors[1]); + Assert.AreEqual(Color.Blue, colors[2]); + + TestObjectAPI(mons); + } + + [FlatBuffersTestMethod] + public void TestNestedFlatBuffer() + { + const string nestedMonsterName = "NestedMonsterName"; + const short nestedMonsterHp = 600; + const short nestedMonsterMana = 1024; + // Create nested buffer as a Monster type + var fbb1 = new FlatBufferBuilder(16); + var str1 = fbb1.CreateString(nestedMonsterName); + Monster.StartMonster(fbb1); + Monster.AddName(fbb1, str1); + Monster.AddHp(fbb1, nestedMonsterHp); + Monster.AddMana(fbb1, nestedMonsterMana); + var monster1 = Monster.EndMonster(fbb1); + Monster.FinishMonsterBuffer(fbb1, monster1); + var fbb1Bytes = fbb1.SizedReadOnlySpan().ToArray(); + + // Create a Monster which has the first buffer as a nested buffer + var fbb2 = new FlatBufferBuilder(16); + var str2 = fbb2.CreateString("My Monster"); + var nestedBuffer = Monster.CreateTestnestedflatbufferVector(fbb2, fbb1Bytes); + Monster.StartMonster(fbb2); + Monster.AddName(fbb2, str2); + Monster.AddHp(fbb2, 50); + Monster.AddMana(fbb2, 32); + Monster.AddTestnestedflatbuffer(fbb2, nestedBuffer); + var monster = Monster.EndMonster(fbb2); + Monster.FinishMonsterBuffer(fbb2, monster); + + // Now test the data extracted from the nested buffer + var mons = Monster.GetRootAsMonster(fbb2.DataBuffer); + var nestedMonster = mons.GetTestnestedflatbufferAsMonster().Value; + + Assert.AreEqual(nestedMonsterMana, nestedMonster.Mana); + Assert.AreEqual(nestedMonsterHp, nestedMonster.Hp); + Assert.AreEqual(nestedMonsterName, nestedMonster.Name); + + TestObjectAPI(mons); + TestObjectAPI(nestedMonster); + } + + [FlatBuffersTestMethod] + public void TestFixedLenghtArrays() + { + FlatBufferBuilder builder = new FlatBufferBuilder(100); + + float a; + int[] b = new int[15]; + sbyte c; + int[,] d_a = new int[2, 2]; + TestEnum[] d_b = new TestEnum[2]; + TestEnum[,] d_c = new TestEnum[2, 2]; + long[,] d_d = new long[2, 2]; + int e; + long[] f = new long[2]; + + a = 0.5f; + for (int i = 0; i < 15; i++) b[i] = i; + c = 1; + d_a[0, 0] = 1; + d_a[0, 1] = 2; + d_a[1, 0] = 3; + d_a[1, 1] = 4; + d_b[0] = TestEnum.B; + d_b[1] = TestEnum.C; + d_c[0, 0] = TestEnum.A; + d_c[0, 1] = TestEnum.B; + d_c[1, 0] = TestEnum.C; + d_c[1, 1] = TestEnum.B; + d_d[0, 0] = -1; + d_d[0, 1] = 1; + d_d[1, 0] = -2; + d_d[1, 1] = 2; + e = 2; + f[0] = -1; + f[1] = 1; + + Offset arrayOffset = ArrayStruct.CreateArrayStruct( + builder, a, b, c, d_a, d_b, d_c, d_d, e, f); + + // Create a table with the ArrayStruct. + ArrayTable.StartArrayTable(builder); + ArrayTable.AddA(builder, arrayOffset); + Offset tableOffset = ArrayTable.EndArrayTable(builder); + + ArrayTable.FinishArrayTableBuffer(builder, tableOffset); + + ArrayTable table = ArrayTable.GetRootAsArrayTable(builder.DataBuffer); + + Assert.AreEqual(table.A.Value.A, 0.5f); + for (int i = 0; i < 15; i++) Assert.AreEqual(table.A.Value.B(i), i); + Assert.AreEqual(table.A.Value.C, (sbyte)1); + Assert.AreEqual(table.A.Value.D(0).A(0), 1); + Assert.AreEqual(table.A.Value.D(0).A(1), 2); + Assert.AreEqual(table.A.Value.D(1).A(0), 3); + Assert.AreEqual(table.A.Value.D(1).A(1), 4); + Assert.AreEqual(table.A.Value.D(0).B, TestEnum.B); + Assert.AreEqual(table.A.Value.D(1).B, TestEnum.C); + Assert.AreEqual(table.A.Value.D(0).C(0), TestEnum.A); + Assert.AreEqual(table.A.Value.D(0).C(1), TestEnum.B); + Assert.AreEqual(table.A.Value.D(1).C(0), TestEnum.C); + Assert.AreEqual(table.A.Value.D(1).C(1), TestEnum.B); + Assert.AreEqual(table.A.Value.D(0).D(0), -1); + Assert.AreEqual(table.A.Value.D(0).D(1), 1); + Assert.AreEqual(table.A.Value.D(1).D(0), -2); + Assert.AreEqual(table.A.Value.D(1).D(1), 2); + Assert.AreEqual(table.A.Value.E, 2); + Assert.AreEqual(table.A.Value.F(0), -1); + Assert.AreEqual(table.A.Value.F(1), 1); + + TestObjectAPI(table); + } + + [FlatBuffersTestMethod] + public void TestUnionVector() + { + var fbb = new FlatBufferBuilder(100); + var rapunzel = Rapunzel.CreateRapunzel(fbb, 40).Value; + + var characterTypes = new[] + { + MyGame.Example.Character.MuLan, + MyGame.Example.Character.Belle, + MyGame.Example.Character.Other, + }; + var characterTypesOffset = MyGame.Example.Movie.CreateCharactersTypeVector(fbb, characterTypes); + + var characterOffsets = new[] + { + Attacker.CreateAttacker(fbb, 10).Value, + BookReader.CreateBookReader(fbb, 20).Value, + fbb.CreateSharedString("Chip").Value, + }; + var charactersOffset = MyGame.Example.Movie.CreateCharactersVector(fbb, characterOffsets); + + var movieOffset = MyGame.Example.Movie.CreateMovie( + fbb, + MyGame.Example.Character.Rapunzel, + rapunzel, + characterTypesOffset, + charactersOffset); + MyGame.Example.Movie.FinishMovieBuffer(fbb, movieOffset); + + var movie = MyGame.Example.Movie.GetRootAsMovie(fbb.DataBuffer); + Assert.AreEqual(MyGame.Example.Character.Rapunzel, movie.MainCharacterType); + Assert.AreEqual(40, movie.MainCharacter().Value.HairLength); + + var charactersType = movie.CharactersType; + Assert.IsTrue(charactersType.HasValue); + var charactersTypeValue = charactersType.Value; + + var charactersVector = movie.Characters; + Assert.IsTrue(charactersVector.HasValue); + var charactersValue = charactersVector.Value; + + Assert.AreEqual(3, charactersTypeValue.Length); + Assert.AreEqual(3, charactersValue.Length); + Assert.AreEqual(MyGame.Example.Character.MuLan, charactersTypeValue[0]); + Assert.AreEqual(10, charactersValue.GetAs(0).SwordAttackDamage); + Assert.AreEqual(MyGame.Example.Character.Belle, charactersTypeValue[1]); + Assert.AreEqual(20, charactersValue.GetAs(1).BooksRead); + Assert.AreEqual(MyGame.Example.Character.Other, charactersTypeValue[2]); + + var movieObject = movie.UnPack(); + Assert.AreEqual("Chip", movieObject.Characters[2].AsOther()); + + TestObjectAPI(movie); + } + + [FlatBuffersTestMethod] + public void TestUnionUtility() + { + var movie = new MyGame.Example.MovieT + { + MainCharacter = MyGame.Example.CharacterUnion.FromRapunzel(new MyGame.Example.RapunzelT { HairLength = 40 }), + Characters = new System.Collections.Generic.List + { + MyGame.Example.CharacterUnion.FromMuLan(new MyGame.Example.AttackerT { SwordAttackDamage = 10 }), + MyGame.Example.CharacterUnion.FromBelle(new MyGame.Example.BookReaderT { BooksRead = 20 }), + MyGame.Example.CharacterUnion.FromOther("Chip"), + }, + }; + + var fbb = new FlatBufferBuilder(100); + MyGame.Example.Movie.FinishMovieBuffer(fbb, MyGame.Example.Movie.Pack(fbb, movie)); + + TestObjectAPI(MyGame.Example.Movie.GetRootAsMovie(fbb.DataBuffer)); + } + + private void AreEqual(Monster a, MonsterT b) + { + Assert.AreEqual(a.Hp, b.Hp); + Assert.AreEqual(a.Mana, b.Mana); + Assert.AreEqual(a.Name, b.Name); + + var posA = a.Pos; + var posB = b.Pos; + if (posA.HasValue) + { + Assert.AreEqual(posA.Value.X, posB.X, 6); + Assert.AreEqual(posA.Value.Y, posB.Y, 6); + Assert.AreEqual(posA.Value.Z, posB.Z, 6); + + Assert.AreEqual(posA.Value.Test1, posB.Test1, 6); + Assert.AreEqual(posA.Value.Test2, posB.Test2); + var tA = posA.Value.Test3; + var tB = posB.Test3; + Assert.AreEqual(tA.A, tB.A); + Assert.AreEqual(tA.B, tB.B); + } + + var bTestType = b.Test?.Type ?? Any.NONE; + Assert.AreEqual(a.TestType, bTestType); + if (a.TestType == Any.Monster) + { + var monster2A = a.Test().Value; + var monster2B = b.Test.AsMonster(); + Assert.AreEqual(monster2A.Name, monster2B.Name); + } + + Assert.AreEqual(a.Inventory.Value.Length, b.Inventory.Count); + for (var i = 0; i < a.Inventory.Value.Length; ++i) + { + Assert.AreEqual(a.Inventory.Value[i], b.Inventory[i]); + } + + var aTest4 = a.Test4; + var aTest4Len = aTest4.HasValue ? aTest4.Value.Length : 0; + Assert.AreEqual(aTest4Len, b.Test4.Count); + if (aTest4.HasValue) + { + var aTest4Vec = aTest4.Value; + for (var i = 0; i < aTest4Len; ++i) + { + var t4A = aTest4Vec[i]; + var t4B = b.Test4[i]; + Assert.AreEqual(t4A.A, t4B.A); + Assert.AreEqual(t4A.B, t4B.B); + } + } + + var aTestarrayofstring = a.Testarrayofstring; + var aTestarrayofstringLen = aTestarrayofstring.HasValue ? aTestarrayofstring.Value.Length : 0; + Assert.AreEqual(aTestarrayofstringLen, b.Testarrayofstring.Count); + if (aTestarrayofstring.HasValue) + { + var aTestarrayofstringVec = aTestarrayofstring.Value; + for (var i = 0; i < aTestarrayofstringLen; ++i) + { + Assert.AreEqual(aTestarrayofstringVec[i], b.Testarrayofstring[i]); + } + } + + Assert.AreEqual(a.Testbool, b.Testbool); + + Assert.AreEqual(a.Testarrayofbools.Value.Length, b.Testarrayofbools.Count); + for (var i = 0; i < a.Testarrayofbools.Value.Length; ++i) + { + Assert.AreEqual(a.Testarrayofbools.Value[i], b.Testarrayofbools[i]); + } + + Assert.AreEqual(a.VectorOfLongs.Value.Length, b.VectorOfLongs.Count); + for (var i = 0; i < a.VectorOfLongs.Value.Length; ++i) + { + Assert.AreEqual(a.VectorOfLongs.Value[i], b.VectorOfLongs[i]); + } + + Assert.AreEqual(a.VectorOfDoubles.Value.Length, b.VectorOfDoubles.Count); + for (var i = 0; i < a.VectorOfDoubles.Value.Length; ++i) + { + Assert.AreEqual(a.VectorOfDoubles.Value[i], b.VectorOfDoubles[i]); + } + + Assert.AreEqual(a.VectorOfEnums.Value.Length, b.VectorOfEnums.Count); + for (var i = 0; i < a.VectorOfEnums.Value.Length; ++i) + { + Assert.AreEqual(a.VectorOfEnums.Value[i], b.VectorOfEnums[i]); + } + } + + private void AreEqual(Monster a, Monster b) + { + Assert.AreEqual(a.Hp, b.Hp); + Assert.AreEqual(a.Mana, b.Mana); + Assert.AreEqual(a.Name, b.Name); + + var posA = a.Pos; + var posB = b.Pos; + if (posA.HasValue) + { + Assert.AreEqual(posA.Value.X, posB.Value.X, 6); + Assert.AreEqual(posA.Value.Y, posB.Value.Y, 6); + Assert.AreEqual(posA.Value.Z, posB.Value.Z, 6); + + Assert.AreEqual(posA.Value.Test1, posB.Value.Test1, 6); + Assert.AreEqual(posA.Value.Test2, posB.Value.Test2); + var tA = posA.Value.Test3; + var tB = posB.Value.Test3; + Assert.AreEqual(tA.A, tB.A); + Assert.AreEqual(tA.B, tB.B); + } + + Assert.AreEqual(a.TestType, b.TestType); + if (a.TestType == Any.Monster) + { + var monster2A = a.Test().Value; + var monster2B = b.Test().Value; + Assert.AreEqual(monster2A.Name, monster2B.Name); + } + + Assert.AreEqual(a.Inventory.Value.Length, b.Inventory.Value.Length); + for (var i = 0; i < a.Inventory.Value.Length; ++i) + { + Assert.AreEqual(a.Inventory.Value[i], b.Inventory.Value[i]); + } + + var aTest4 = a.Test4; + var bTest4 = b.Test4; + var aTest4Len = aTest4.HasValue ? aTest4.Value.Length : 0; + var bTest4Len = bTest4.HasValue ? bTest4.Value.Length : 0; + Assert.AreEqual(aTest4Len, bTest4Len); + if (aTest4.HasValue && bTest4.HasValue) + { + var aTest4Vec = aTest4.Value; + var bTest4Vec = bTest4.Value; + for (var i = 0; i < aTest4Len; ++i) + { + var t4A = aTest4Vec[i]; + var t4B = bTest4Vec[i]; + Assert.AreEqual(t4A.A, t4B.A); + Assert.AreEqual(t4A.B, t4B.B); + } + } + + var aTestarrayofstring = a.Testarrayofstring; + var bTestarrayofstring = b.Testarrayofstring; + var aTestarrayofstringLen = aTestarrayofstring.HasValue ? aTestarrayofstring.Value.Length : 0; + var bTestarrayofstringLen = bTestarrayofstring.HasValue ? bTestarrayofstring.Value.Length : 0; + Assert.AreEqual(aTestarrayofstringLen, bTestarrayofstringLen); + if (aTestarrayofstring.HasValue && bTestarrayofstring.HasValue) + { + var aTestarrayofstringVec = aTestarrayofstring.Value; + var bTestarrayofstringVec = bTestarrayofstring.Value; + for (var i = 0; i < aTestarrayofstringLen; ++i) + { + Assert.AreEqual(aTestarrayofstringVec[i], bTestarrayofstringVec[i]); + } + } + + Assert.AreEqual(a.Testbool, b.Testbool); + + Assert.AreEqual(a.Testarrayofbools.Value.Length, b.Testarrayofbools.Value.Length); + for (var i = 0; i < a.Testarrayofbools.Value.Length; ++i) + { + Assert.AreEqual(a.Testarrayofbools.Value[i], b.Testarrayofbools.Value[i]); + } + + Assert.AreEqual(a.VectorOfLongs.Value.Length, b.VectorOfLongs.Value.Length); + for (var i = 0; i < a.VectorOfLongs.Value.Length; ++i) + { + Assert.AreEqual(a.VectorOfLongs.Value[i], b.VectorOfLongs.Value[i]); + } + + Assert.AreEqual(a.VectorOfDoubles.Value.Length, b.VectorOfDoubles.Value.Length); + for (var i = 0; i < a.VectorOfDoubles.Value.Length; ++i) + { + Assert.AreEqual(a.VectorOfDoubles.Value[i], b.VectorOfDoubles.Value[i]); + } + + Assert.AreEqual(a.VectorOfEnums.Value.Length, b.VectorOfEnums.Value.Length); + for (var i = 0; i < a.VectorOfEnums.Value.Length; ++i) + { + Assert.AreEqual(a.VectorOfEnums.Value[i], b.VectorOfEnums.Value[i]); + } + } + + private void TestObjectAPI(Monster a) + { + var b = a.UnPack(); + AreEqual(a, b); + + var fbb = new FlatBufferBuilder(1); + fbb.Finish(Monster.Pack(fbb, b).Value); + var c = Monster.GetRootAsMonster(fbb.DataBuffer); + AreEqual(a, c); + + var jsonText = b.SerializeToJson(); + var d = MonsterT.DeserializeFromJson(jsonText); + AreEqual(a, d); + + var fbBuffer = b.SerializeToBinary(); + Assert.IsTrue(Monster.MonsterBufferHasIdentifier(new ByteBuffer(fbBuffer))); + var e = MonsterT.DeserializeFromBinary(fbBuffer); + AreEqual(a, e); + } + + private void AreEqual(ArrayTable a, ArrayTableT b) + { + Assert.AreEqual(a.A.Value.A, b.A.A); + + for (int i = 0; i < 15; ++i) + { + Assert.AreEqual(a.A.Value.B(i), b.A.B[i]); + } + + Assert.AreEqual(a.A.Value.C, b.A.C); + + for (int i = 0; i < 2; ++i) + { + var ad = a.A.Value.D(i); + var bd = b.A.D[i]; + + for (int j = 0; j < 2; ++j) + { + Assert.AreEqual(ad.A(j), bd.A[j]); + } + + Assert.AreEqual(ad.B, bd.B); + + for (int j = 0; j < 2; ++j) + { + Assert.AreEqual(ad.C(j), bd.C[j]); + } + + for (int j = 0; j < 2; ++j) + { + Assert.AreEqual(ad.D(j), bd.D[j]); + } + } + + Assert.AreEqual(a.A.Value.E, b.A.E); + + for (int i = 0; i < 2; ++i) + { + Assert.AreEqual(a.A.Value.F(i), b.A.F[i]); + } + } + + private void AreEqual(ArrayTable a, ArrayTable b) + { + Assert.AreEqual(a.A.Value.A, b.A.Value.A); + + for (int i = 0; i < 15; ++i) + { + Assert.AreEqual(a.A.Value.B(i), b.A.Value.B(i)); + } + + Assert.AreEqual(a.A.Value.C, b.A.Value.C); + + for (int i = 0; i < 2; ++i) + { + var ad = a.A.Value.D(i); + var bd = b.A.Value.D(i); + + for (int j = 0; j < 2; ++j) + { + Assert.AreEqual(ad.A(j), bd.A(j)); + } + + Assert.AreEqual(ad.B, bd.B); + + for (int j = 0; j < 2; ++j) + { + Assert.AreEqual(ad.C(j), bd.C(j)); + } + + for (int j = 0; j < 2; ++j) + { + Assert.AreEqual(ad.D(j), bd.D(j)); + } + } + + Assert.AreEqual(a.A.Value.E, b.A.Value.E); + + for (int i = 0; i < 2; ++i) + { + Assert.AreEqual(a.A.Value.F(i), b.A.Value.F(i)); + } + } + + private void TestObjectAPI(ArrayTable a) + { + var b = a.UnPack(); + AreEqual(a, b); + + var fbb = new FlatBufferBuilder(1); + fbb.Finish(ArrayTable.Pack(fbb, b).Value); + var c = ArrayTable.GetRootAsArrayTable(fbb.DataBuffer); + AreEqual(a, c); + + var jsonText = b.SerializeToJson(); + var d = ArrayTableT.DeserializeFromJson(jsonText); + AreEqual(a, d); + + var fbBuffer = b.SerializeToBinary(); + Assert.IsTrue(ArrayTable.ArrayTableBufferHasIdentifier(new ByteBuffer(fbBuffer))); + var e = ArrayTableT.DeserializeFromBinary(fbBuffer); + AreEqual(a, e); + } + + private void AreEqual(Movie a, MovieT b) + { + Assert.AreEqual(a.MainCharacterType, b.MainCharacter.Type); + Assert.AreEqual(a.MainCharacter().Value.HairLength, b.MainCharacter.AsRapunzel().HairLength); + + var aCharactersType = a.CharactersType; + var aCharacters = a.Characters; + var aCharactersLength = aCharacters.HasValue ? aCharacters.Value.Length : 0; + + Assert.AreEqual(aCharactersLength, b.Characters.Count); + if (aCharacters.HasValue && aCharactersType.HasValue) + { + var aCharactersTypeValue = aCharactersType.Value; + var aCharactersValue = aCharacters.Value; + + Assert.AreEqual(aCharactersTypeValue[0], b.Characters[0].Type); + Assert.AreEqual(aCharactersValue.GetAs(0).SwordAttackDamage, b.Characters[0].AsMuLan().SwordAttackDamage); + Assert.AreEqual(aCharactersTypeValue[1], b.Characters[1].Type); + Assert.AreEqual(aCharactersValue.GetAs(1).BooksRead, b.Characters[1].AsBelle().BooksRead); + Assert.AreEqual(aCharactersTypeValue[2], b.Characters[2].Type); + Assert.AreEqual(aCharactersValue.GetAsString(2), b.Characters[2].AsOther()); + } + } + + private void AreEqual(Movie a, Movie b) + { + Assert.AreEqual(a.MainCharacterType, b.MainCharacterType); + Assert.AreEqual(a.MainCharacter().Value.HairLength, b.MainCharacter().Value.HairLength); + + var aCharactersType = a.CharactersType; + var bCharactersType = b.CharactersType; + var aCharacters = a.Characters; + var bCharacters = b.Characters; + var aCharactersLength = aCharacters.HasValue ? aCharacters.Value.Length : 0; + var bCharactersLength = bCharacters.HasValue ? bCharacters.Value.Length : 0; + + Assert.AreEqual(aCharactersLength, bCharactersLength); + if (aCharacters.HasValue && bCharacters.HasValue && aCharactersType.HasValue && bCharactersType.HasValue) + { + var aCharactersTypeValue = aCharactersType.Value; + var bCharactersTypeValue = bCharactersType.Value; + var aCharactersValue = aCharacters.Value; + var bCharactersValue = bCharacters.Value; + + Assert.AreEqual(aCharactersTypeValue[0], bCharactersTypeValue[0]); + Assert.AreEqual(aCharactersValue.GetAs(0).SwordAttackDamage, bCharactersValue.GetAs(0).SwordAttackDamage); + Assert.AreEqual(aCharactersTypeValue[1], bCharactersTypeValue[1]); + Assert.AreEqual(aCharactersValue.GetAs(1).BooksRead, bCharactersValue.GetAs(1).BooksRead); + Assert.AreEqual(aCharactersTypeValue[2], bCharactersTypeValue[2]); + Assert.AreEqual(aCharactersValue.GetAsString(2), bCharactersValue.GetAsString(2)); + + var bCharsAsString = bCharactersValue.GetAsString(2); + int byteCount = Encoding.UTF8.GetByteCount(bCharsAsString); + Span utf8Bytes = new byte[byteCount]; + Encoding.UTF8.GetBytes(bCharsAsString, utf8Bytes); + Assert.SpanEqual(aCharactersValue.GetAsStringBytes(2), utf8Bytes); + } + } + + private void TestObjectAPI(Movie a) + { + var b = a.UnPack(); + AreEqual(a, b); + + var fbb = new FlatBufferBuilder(1); + fbb.Finish(Movie.Pack(fbb, b).Value); + var c = Movie.GetRootAsMovie(fbb.DataBuffer); + AreEqual(a, c); + + var jsonText = b.SerializeToJson(); + var d = MovieT.DeserializeFromJson(jsonText); + AreEqual(a, d); + + var fbBuffer = b.SerializeToBinary(); + Assert.IsTrue(Movie.MovieBufferHasIdentifier(new ByteBuffer(fbBuffer))); + var e = MovieT.DeserializeFromBinary(fbBuffer); + AreEqual(a, e); + } + + // For use in TestParallelAccess test case. + static private int _comparisons = 0; + static private int _failures = 0; + static private void KeepComparing(Monster mon, int count, float floatValue, double doubleValue) + { + int i = 0; + while (++i <= count) + { + Interlocked.Add(ref _comparisons, 1); + if (mon.Pos.Value.Test1 != doubleValue || mon.Pos.Value.Z != floatValue) + { + Interlocked.Add(ref _failures, 1); + } + } + } + + [FlatBuffersTestMethod] + public void TestParallelAccess() + { + // Tests that reading from a flatbuffer over multiple threads is thread-safe in regard to double and float + // values, since they previously were non-thread safe + const float floatValue = 3.141592F; + const double doubleValue = 1.618033988; + + var fbb = new FlatBufferBuilder(1); + var str = fbb.CreateString("ParallelTest"); + Monster.StartMonster(fbb); + Monster.AddPos(fbb, Vec3.CreateVec3(fbb, 1.0f, 2.0f, floatValue, doubleValue, + Color.Green, (short)5, (sbyte)6)); + + Monster.AddName(fbb, str); + Monster.FinishMonsterBuffer(fbb, Monster.EndMonster(fbb)); + + var mon = Monster.GetRootAsMonster(fbb.DataBuffer); + + var pos = mon.Pos.Value; + Assert.AreEqual(pos.Test1, doubleValue, 6); + Assert.AreEqual(pos.Z, floatValue, 6); + + const int thread_count = 10; + const int reps = 1000000; + + // Need to use raw Threads since Tasks are not supported in .NET 3.5 + Thread[] threads = new Thread[thread_count]; + for (int i = 0; i < thread_count; i++) + { + threads[i] = new Thread(() => KeepComparing(mon, reps, floatValue, doubleValue)); + } + for (int i = 0; i < thread_count; i++) + { + threads[i].Start(); + } + for (int i = 0; i < thread_count; i++) + { + threads[i].Join(); + } + + // Make sure the threads actually did the comparisons. + Assert.AreEqual(thread_count * reps, _comparisons); + + // Make sure we never read the values incorrectly. + Assert.AreEqual(0, _failures); + } + + [FlatBuffersTestMethod] + public void TestScalarOptional_EmptyBuffer() + { + var fbb = new FlatBufferBuilder(1); + ScalarStuff.StartScalarStuff(fbb); + var offset = ScalarStuff.EndScalarStuff(fbb); + ScalarStuff.FinishScalarStuffBuffer(fbb, offset); + + ScalarStuff scalarStuff = ScalarStuff.GetRootAsScalarStuff(fbb.DataBuffer); + Assert.AreEqual((sbyte)0, scalarStuff.JustI8); + Assert.AreEqual(null, scalarStuff.MaybeI8); + Assert.AreEqual((sbyte)42, scalarStuff.DefaultI8); + Assert.AreEqual((byte)0, scalarStuff.JustU8); + Assert.AreEqual(null, scalarStuff.MaybeU8); + Assert.AreEqual((byte)42, scalarStuff.DefaultU8); + + Assert.AreEqual((short)0, scalarStuff.JustI16); + Assert.AreEqual(null, scalarStuff.MaybeI16); + Assert.AreEqual((short)42, scalarStuff.DefaultI16); + Assert.AreEqual((ushort)0, scalarStuff.JustU16); + Assert.AreEqual(null, scalarStuff.MaybeU16); + Assert.AreEqual((ushort)42, scalarStuff.DefaultU16); + + Assert.AreEqual((int)0, scalarStuff.JustI32); + Assert.AreEqual(null, scalarStuff.MaybeI32); + Assert.AreEqual((int)42, scalarStuff.DefaultI32); + Assert.AreEqual((uint)0, scalarStuff.JustU32); + Assert.AreEqual(null, scalarStuff.MaybeU32); + Assert.AreEqual((uint)42, scalarStuff.DefaultU32); + + Assert.AreEqual((long)0, scalarStuff.JustI64); + Assert.AreEqual(null, scalarStuff.MaybeI64); + Assert.AreEqual((long)42, scalarStuff.DefaultI64); + Assert.AreEqual((ulong)0, scalarStuff.JustU64); + Assert.AreEqual(null, scalarStuff.MaybeU64); + Assert.AreEqual((ulong)42, scalarStuff.DefaultU64); + + Assert.AreEqual((float)0.0F, scalarStuff.JustF32); + Assert.AreEqual(null, scalarStuff.MaybeF32); + Assert.AreEqual((float)42.0F, scalarStuff.DefaultF32); + + Assert.AreEqual((double)0.0, scalarStuff.JustF64); + Assert.AreEqual(null, scalarStuff.MaybeF64); + Assert.AreEqual((double)42.0, scalarStuff.DefaultF64); + + Assert.AreEqual(false, scalarStuff.JustBool); + Assert.AreEqual(null, scalarStuff.MaybeBool); + Assert.AreEqual(true, scalarStuff.DefaultBool); + + Assert.AreEqual(OptionalByte.None, scalarStuff.JustEnum); + Assert.AreEqual(null, scalarStuff.MaybeEnum); + Assert.AreEqual(OptionalByte.One, scalarStuff.DefaultEnum); + } + + [FlatBuffersTestMethod] + public void TestScalarOptional_Construction() + { + var fbb = new FlatBufferBuilder(1); + ScalarStuff.StartScalarStuff(fbb); + ScalarStuff.AddJustI8(fbb, 5); + ScalarStuff.AddMaybeI8(fbb, 5); + ScalarStuff.AddDefaultI8(fbb, 5); + ScalarStuff.AddJustU8(fbb, 6); + ScalarStuff.AddMaybeU8(fbb, 6); + ScalarStuff.AddDefaultU8(fbb, 6); + + ScalarStuff.AddJustI16(fbb, 7); + ScalarStuff.AddMaybeI16(fbb, 7); + ScalarStuff.AddDefaultI16(fbb, 7); + ScalarStuff.AddJustU16(fbb, 8); + ScalarStuff.AddMaybeU16(fbb, 8); + ScalarStuff.AddDefaultU16(fbb, 8); + + ScalarStuff.AddJustI32(fbb, 9); + ScalarStuff.AddMaybeI32(fbb, 9); + ScalarStuff.AddDefaultI32(fbb, 9); + ScalarStuff.AddJustU32(fbb, 10); + ScalarStuff.AddMaybeU32(fbb, 10); + ScalarStuff.AddDefaultU32(fbb, 10); + + ScalarStuff.AddJustI64(fbb, 11); + ScalarStuff.AddMaybeI64(fbb, 11); + ScalarStuff.AddDefaultI64(fbb, 11); + ScalarStuff.AddJustU64(fbb, 12); + ScalarStuff.AddMaybeU64(fbb, 12); + ScalarStuff.AddDefaultU64(fbb, 12); + + ScalarStuff.AddJustF32(fbb, 13.0f); + ScalarStuff.AddMaybeF32(fbb, 13.0f); + ScalarStuff.AddDefaultF32(fbb, 13.0f); + ScalarStuff.AddJustF64(fbb, 14.0); + ScalarStuff.AddMaybeF64(fbb, 14.0); + ScalarStuff.AddDefaultF64(fbb, 14.0); + + ScalarStuff.AddJustBool(fbb, true); + ScalarStuff.AddMaybeBool(fbb, true); + ScalarStuff.AddDefaultBool(fbb, false); // note this is the opposite + + ScalarStuff.AddJustEnum(fbb, OptionalByte.Two); + ScalarStuff.AddMaybeEnum(fbb, OptionalByte.Two); + ScalarStuff.AddDefaultEnum(fbb, OptionalByte.Two); + + var offset = ScalarStuff.EndScalarStuff(fbb); + ScalarStuff.FinishScalarStuffBuffer(fbb, offset); + + ScalarStuff scalarStuff = ScalarStuff.GetRootAsScalarStuff(fbb.DataBuffer); + Assert.AreEqual((sbyte)5, scalarStuff.JustI8); + Assert.AreEqual((sbyte)5, scalarStuff.MaybeI8); + Assert.AreEqual((sbyte)5, scalarStuff.DefaultI8); + Assert.AreEqual((byte)6, scalarStuff.JustU8); + Assert.AreEqual((byte)6, scalarStuff.MaybeU8); + Assert.AreEqual((byte)6, scalarStuff.DefaultU8); + + Assert.AreEqual((short)7, scalarStuff.JustI16); + Assert.AreEqual((short)7, scalarStuff.MaybeI16); + Assert.AreEqual((short)7, scalarStuff.DefaultI16); + Assert.AreEqual((ushort)8, scalarStuff.JustU16); + Assert.AreEqual((ushort)8, scalarStuff.MaybeU16); + Assert.AreEqual((ushort)8, scalarStuff.DefaultU16); + + Assert.AreEqual((int)9, scalarStuff.JustI32); + Assert.AreEqual((int)9, scalarStuff.MaybeI32); + Assert.AreEqual((int)9, scalarStuff.DefaultI32); + Assert.AreEqual((uint)10, scalarStuff.JustU32); + Assert.AreEqual((uint)10, scalarStuff.MaybeU32); + Assert.AreEqual((uint)10, scalarStuff.DefaultU32); + + Assert.AreEqual((long)11, scalarStuff.JustI64); + Assert.AreEqual((long)11, scalarStuff.MaybeI64); + Assert.AreEqual((long)11, scalarStuff.DefaultI64); + Assert.AreEqual((ulong)12, scalarStuff.JustU64); + Assert.AreEqual((ulong)12, scalarStuff.MaybeU64); + Assert.AreEqual((ulong)12, scalarStuff.DefaultU64); + + Assert.AreEqual((float)13.0F, scalarStuff.JustF32); + Assert.AreEqual((float)13.0F, scalarStuff.MaybeF32); + Assert.AreEqual((float)13.0F, scalarStuff.DefaultF32); + + Assert.AreEqual((double)14.0, scalarStuff.JustF64); + Assert.AreEqual((double)14.0, scalarStuff.MaybeF64); + Assert.AreEqual((double)14.0, scalarStuff.DefaultF64); + + Assert.AreEqual(true, scalarStuff.JustBool); + Assert.AreEqual(true, scalarStuff.MaybeBool); + Assert.AreEqual(false, scalarStuff.DefaultBool); + + Assert.AreEqual(OptionalByte.Two, scalarStuff.JustEnum); + Assert.AreEqual(OptionalByte.Two, scalarStuff.MaybeEnum); + Assert.AreEqual(OptionalByte.Two, scalarStuff.DefaultEnum); + } + + [FlatBuffersTestMethod] + public void TestScalarOptional_Construction_CreatorMethod() + { + var fbb = new FlatBufferBuilder(1); + + var offset = ScalarStuff.CreateScalarStuff(fbb, 5, 5, 5, 6, 6, 6, 7, 7, 7, + 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13.0f, 13.0f, 13.0f, 14.0, + 14.0, 14.0, true, true, false, OptionalByte.Two, OptionalByte.Two, + OptionalByte.Two); + ScalarStuff.FinishScalarStuffBuffer(fbb, offset); + + ScalarStuff scalarStuff = ScalarStuff.GetRootAsScalarStuff(fbb.DataBuffer); + Assert.AreEqual((sbyte)5, scalarStuff.JustI8); + Assert.AreEqual((sbyte)5, scalarStuff.MaybeI8); + Assert.AreEqual((sbyte)5, scalarStuff.DefaultI8); + Assert.AreEqual((byte)6, scalarStuff.JustU8); + Assert.AreEqual((byte)6, scalarStuff.MaybeU8); + Assert.AreEqual((byte)6, scalarStuff.DefaultU8); + + Assert.AreEqual((short)7, scalarStuff.JustI16); + Assert.AreEqual((short)7, scalarStuff.MaybeI16); + Assert.AreEqual((short)7, scalarStuff.DefaultI16); + Assert.AreEqual((ushort)8, scalarStuff.JustU16); + Assert.AreEqual((ushort)8, scalarStuff.MaybeU16); + Assert.AreEqual((ushort)8, scalarStuff.DefaultU16); + + Assert.AreEqual((int)9, scalarStuff.JustI32); + Assert.AreEqual((int)9, scalarStuff.MaybeI32); + Assert.AreEqual((int)9, scalarStuff.DefaultI32); + Assert.AreEqual((uint)10, scalarStuff.JustU32); + Assert.AreEqual((uint)10, scalarStuff.MaybeU32); + Assert.AreEqual((uint)10, scalarStuff.DefaultU32); + + Assert.AreEqual((long)11, scalarStuff.JustI64); + Assert.AreEqual((long)11, scalarStuff.MaybeI64); + Assert.AreEqual((long)11, scalarStuff.DefaultI64); + Assert.AreEqual((ulong)12, scalarStuff.JustU64); + Assert.AreEqual((ulong)12, scalarStuff.MaybeU64); + Assert.AreEqual((ulong)12, scalarStuff.DefaultU64); + + Assert.AreEqual((float)13.0F, scalarStuff.JustF32); + Assert.AreEqual((float)13.0F, scalarStuff.MaybeF32); + Assert.AreEqual((float)13.0F, scalarStuff.DefaultF32); + + Assert.AreEqual((double)14.0, scalarStuff.JustF64); + Assert.AreEqual((double)14.0, scalarStuff.MaybeF64); + Assert.AreEqual((double)14.0, scalarStuff.DefaultF64); + + Assert.AreEqual(true, scalarStuff.JustBool); + Assert.AreEqual(true, scalarStuff.MaybeBool); + Assert.AreEqual(false, scalarStuff.DefaultBool); + + Assert.AreEqual(OptionalByte.Two, scalarStuff.JustEnum); + Assert.AreEqual(OptionalByte.Two, scalarStuff.MaybeEnum); + Assert.AreEqual(OptionalByte.Two, scalarStuff.DefaultEnum); + } + + [FlatBuffersTestMethod] + public void TestKeywordEscaping() + { + Assert.AreEqual((int)KeywordTest.@public.NONE, 0); + + Assert.AreEqual((int)KeywordTest.ABC.@void, 0); + Assert.AreEqual((int)KeywordTest.ABC.where, 1); + Assert.AreEqual((int)KeywordTest.ABC.@stackalloc, 2); + + var fbb = new FlatBufferBuilder(1); + var offset = KeywordsInTable.CreateKeywordsInTable( + fbb, KeywordTest.ABC.@stackalloc, KeywordTest.@public.NONE); + fbb.Finish(offset.Value); + + KeywordsInTable keywordsInTable = + KeywordsInTable.GetRootAsKeywordsInTable(fbb.DataBuffer); + + Assert.AreEqual(keywordsInTable.Is, KeywordTest.ABC.@stackalloc); + Assert.AreEqual(keywordsInTable.Private, KeywordTest.@public.NONE); + } + + [FlatBuffersTestMethod] + public void AddOptionalEnum_WhenPassNull_ShouldWorkProperly() + { + var fbb = new FlatBufferBuilder(1); + ScalarStuff.StartScalarStuff(fbb); + ScalarStuff.AddMaybeEnum(fbb, null); + var offset = ScalarStuff.EndScalarStuff(fbb); + ScalarStuff.FinishScalarStuffBuffer(fbb, offset); + + ScalarStuff scalarStuff = ScalarStuff.GetRootAsScalarStuff(fbb.DataBuffer); + Assert.AreEqual(null, scalarStuff.MaybeEnum); + } + + [FlatBuffersTestMethod] + public void SortKey_WithDefaultedValue_IsFindable() + { + // This checks if using the `key` attribute that includes the + // default value (e.g., 0) is still searchable. This is a regression + // test for https://github.com/google/flatbuffers/issues/7380. + var fbb = new FlatBufferBuilder(1); + + // Create a vector of Stat objects, with Count being the key. + var stat_offsets = new Offset[4]; + for (ushort i = 0; i < stat_offsets.Length; i++) + { + Stat.StartStat(fbb); + Stat.AddCount(fbb, i); + stat_offsets[stat_offsets.Length - 1 - i] = Stat.EndStat(fbb); + } + + // Ensure the sort works. + Span> statSpan = stat_offsets; + var sort = Stat.CreateSortedVectorOfStat(fbb, statSpan); + + // Create the monster with the sorted vector of Stat objects. + var str = fbb.CreateString("MyMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, str); + Monster.AddScalarKeySortedTables(fbb, sort); + fbb.Finish(Monster.EndMonster(fbb).Value); + + // Get the monster. + var monster = Monster.GetRootAsMonster(fbb.DataBuffer); + + // Ensure each key is findable. + for (ushort i = 0; i < stat_offsets.Length; i++) + { + Assert.IsTrue(monster.TryGetScalarKeySortedTablesByKey(i, out var stat)); + Assert.AreEqual(stat.Count, i); + } + } + + [FlatBuffersTestMethod] + public void CanWriteAndReadBackEquivalentCppGeneratedWireFile() + { + // Create a buffer matching the structure of monsterdata_test.json + var fbb = new FlatBufferBuilder(1024); + + var monsterName = fbb.CreateString("MyMonster"); + var fredName = fbb.CreateString("Fred"); + var test1Str = fbb.CreateString("test1"); + var test2Str = fbb.CreateString("test2"); + + Monster.StartMonster(fbb); + Monster.AddName(fbb, fredName); + var enemyOffset = Monster.EndMonster(fbb); + + var fredName2 = fbb.CreateString("Fred"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, fredName2); + var testMonsterOffset = Monster.EndMonster(fbb); + + Span inventoryData = stackalloc byte[] { 0, 1, 2, 3, 4 }; + var inventoryVector = Monster.CreateInventoryVectorBlock(fbb, inventoryData); + + Monster.StartTest4Vector(fbb, 2); + MyGame.Example.Test.CreateTest(fbb, (short)10, (sbyte)20); + MyGame.Example.Test.CreateTest(fbb, (short)30, (sbyte)40); + var test4Vector = fbb.EndVector(); + + Span testStrings = stackalloc StringOffset[] { test1Str, test2Str }; + var testarrayofstringVector = Monster.CreateTestarrayofstringVectorBlock(fbb, testStrings); + + Span boolsData = stackalloc bool[] { true, false, true }; + var testarrayofboolsVector = Monster.CreateTestarrayofboolsVectorBlock(fbb, boolsData); + + var longsVector = Monster.CreateVectorOfLongsVector(fbb, new long[] { 1, 100, 10000, 1000000, 100000000 }); + var doublesVector = Monster.CreateVectorOfDoublesVector(fbb, new double[] { -1.7976931348623157e+308, 0, 1.7976931348623157e+308 }); + + Monster.StartMonster(fbb); + Monster.AddPos(fbb, Vec3.CreateVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0, Color.Green, (short)5, (sbyte)6)); + Monster.AddHp(fbb, 80); + Monster.AddName(fbb, monsterName); + Monster.AddInventory(fbb, inventoryVector); + Monster.AddTestType(fbb, Any.Monster); + Monster.AddTest(fbb, testMonsterOffset.Value); + Monster.AddTest4(fbb, test4Vector); + Monster.AddTestarrayofstring(fbb, testarrayofstringVector); + Monster.AddTestbool(fbb, true); + Monster.AddEnemy(fbb, enemyOffset); + Monster.AddTestarrayofbools(fbb, testarrayofboolsVector); + Monster.AddVectorOfLongs(fbb, longsVector); + Monster.AddVectorOfDoubles(fbb, doublesVector); + var monsterOffset = Monster.EndMonster(fbb); + + Monster.FinishMonsterBuffer(fbb, monsterOffset); + + // make a copy before verify. In place would access fbb.DataBuffer.Buffer. + var bufferBytes = fbb.DataBuffer.ToSizedSpan().ToArray(); + var readBuffer = new ByteBuffer(bufferBytes); + + // Verify the buffer + TestBuffer(readBuffer); + } + + [FlatBuffersTestMethod] + public void TestDefaultValues() + { + // Test that default values are correctly returned when fields are not set + var fbb = new FlatBufferBuilder(256); + + var name = fbb.CreateString("DefaultsMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var buffer = fbb.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + // Check default values from schema + Assert.AreEqual(150, monster.Mana); + Assert.AreEqual(100, monster.Hp); + Assert.AreEqual(Color.Blue, monster.Color); + Assert.AreEqual(3.14159f, monster.Testf, 6); + Assert.AreEqual(3.0f, monster.Testf2, 6); + Assert.AreEqual(0.0f, monster.Testf3, 6); + Assert.AreEqual(Race.None, monster.SignedEnum); + } + + [FlatBuffersTestMethod] + public void TestStringAsSpan() + { + var fbb = new FlatBufferBuilder(256); + + var testName = "SpanTestMonster"; + var name = fbb.CreateString(testName); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var buffer = fbb.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + var nameBytes = monster.GetNameBytes(); + var expectedBytes = Encoding.UTF8.GetBytes(testName); + + Assert.AreEqual(expectedBytes.Length, nameBytes.Length); + Assert.SpanEqual(expectedBytes, nameBytes); + } + + [FlatBuffersTestMethod] + public void TestInventoryAsSpan() + { + var fbb = new FlatBufferBuilder(256); + + Span inventoryData = stackalloc byte[] { 10, 20, 30, 40, 50 }; + var inv = Monster.CreateInventoryVectorBlock(fbb, inventoryData); + + var name = fbb.CreateString("InventoryMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + Monster.AddInventory(fbb, inv); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var buffer = fbb.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + var inventoryBytes = monster.Inventory.Value; + var expectedInventory = new byte[] { 10, 20, 30, 40, 50 }; + + Assert.AreEqual(expectedInventory.Length, inventoryBytes.Length); + Assert.SpanEqual(expectedInventory, inventoryBytes); + } + + [FlatBuffersTestMethod] + public void TestUnion() + { + var fbb = new FlatBufferBuilder(256); + + var fred = fbb.CreateString("Fred"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, fred); + Monster.AddHp(fbb, 200); + var unionMonster = Monster.EndMonster(fbb); + + var name = fbb.CreateString("UnionMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + Monster.AddTestType(fbb, Any.Monster); + Monster.AddTest(fbb, unionMonster.Value); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var buffer = fbb.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + Assert.AreEqual(Any.Monster, monster.TestType); + + var testMonster = monster.Test().Value; + Assert.AreEqual("Fred", testMonster.Name); + Assert.AreEqual(200, testMonster.Hp); + } + + [FlatBuffersTestMethod] + public void TestVectorOfStructs() + { + var fbb = new FlatBufferBuilder(256); + + Monster.StartTest4Vector(fbb, 3); + Test.CreateTest(fbb, 30, 40); + Test.CreateTest(fbb, 20, 30); + Test.CreateTest(fbb, 10, 20); + var test4Vector = fbb.EndVector(); + + var name = fbb.CreateString("Test4Monster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + Monster.AddTest4(fbb, test4Vector); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var buffer = fbb.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + var test4 = monster.Test4; + Assert.IsTrue(test4.HasValue); + var test4Vec = test4.Value; + Assert.AreEqual(3, test4Vec.Length); + + var test0 = test4Vec[0]; + Assert.AreEqual((short)10, test0.A); + Assert.AreEqual((sbyte)20, test0.B); + + var test1 = test4Vec[1]; + Assert.AreEqual((short)20, test1.A); + Assert.AreEqual((sbyte)30, test1.B); + + var test2 = test4Vec[2]; + Assert.AreEqual((short)30, test2.A); + Assert.AreEqual((sbyte)40, test2.B); + } + + [FlatBuffersTestMethod] + public void TestEmptyBuffer() + { + var fbb = new FlatBufferBuilder(256); + + // Create a minimal monster with just a name + var name = fbb.CreateString("EmptyMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var buffer = fbb.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + // Test that empty vectors return null/false HasValue + Assert.IsFalse(monster.Inventory.HasValue); + Assert.IsFalse(monster.Test4.HasValue); + Assert.IsFalse(monster.Testarrayofstring.HasValue); + + // Test that optional struct returns null + Assert.IsFalse(monster.Pos.HasValue); + } + + [FlatBuffersTestMethod] + public void TestBuilderReuse() + { + var fbb = new FlatBufferBuilder(256); + + var name1 = fbb.CreateString("Monster1"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name1); + Monster.AddHp(fbb, 100); + var mon1 = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon1); + + var buffer1 = fbb.DataBuffer.ToSizedSpan().ToArray(); + + fbb.Clear(); + + var name2 = fbb.CreateString("Monster2"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name2); + Monster.AddHp(fbb, 200); + var mon2 = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon2); + + var bb1 = new ByteBuffer(buffer1); + var monster1 = Monster.GetRootAsMonster(bb1); + Assert.AreEqual("Monster1", monster1.Name); + Assert.AreEqual(100, monster1.Hp); + + var monster2 = Monster.GetRootAsMonster(fbb.DataBuffer); + Assert.AreEqual("Monster2", monster2.Name); + Assert.AreEqual(200, monster2.Hp); + } + + [FlatBuffersTestMethod] + public void TestVectorOfLongs() + { + var fbb = new FlatBufferBuilder(256); + + Span longsData = stackalloc long[] { 1L, 2L, 3L, long.MaxValue, long.MinValue }; + var longsVec = Monster.CreateVectorOfLongsVector(fbb, longsData); + + var name = fbb.CreateString("LongsMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + Monster.AddVectorOfLongs(fbb, longsVec); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var monster = Monster.GetRootAsMonster(fbb.DataBuffer); + + Assert.AreEqual(5, monster.VectorOfLongs.Value.Length); + Assert.AreEqual(1L, monster.VectorOfLongs.Value[0]); + Assert.AreEqual(2L, monster.VectorOfLongs.Value[1]); + Assert.AreEqual(3L, monster.VectorOfLongs.Value[2]); + Assert.AreEqual(long.MaxValue, monster.VectorOfLongs.Value[3]); + Assert.AreEqual(long.MinValue, monster.VectorOfLongs.Value[4]); + + var longsBytes = monster.VectorOfLongs.Value; + Assert.AreEqual(5, longsBytes.Length); + } + + [FlatBuffersTestMethod] + public void TestVectorOfDoubles() + { + var fbb = new FlatBufferBuilder(256); + + Span doublesData = stackalloc double[] { 1.0, 2.5, 3.14159, double.MaxValue, double.MinValue }; + var doublesVec = Monster.CreateVectorOfDoublesVector(fbb, doublesData); + + var name = fbb.CreateString("DoublesMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + Monster.AddVectorOfDoubles(fbb, doublesVec); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var monster = Monster.GetRootAsMonster(fbb.DataBuffer); + + Assert.AreEqual(5, monster.VectorOfDoubles.Value.Length); + Assert.AreEqual(1.0, monster.VectorOfDoubles.Value[0], 6); + Assert.AreEqual(2.5, monster.VectorOfDoubles.Value[1], 6); + Assert.AreEqual(3.14159, monster.VectorOfDoubles.Value[2], 6); + Assert.AreEqual(double.MaxValue, monster.VectorOfDoubles.Value[3], 6); + Assert.AreEqual(double.MinValue, monster.VectorOfDoubles.Value[4], 6); + + var doublesBytes = monster.VectorOfDoubles.Value; + Assert.AreEqual(5, doublesBytes.Length); + } + + [FlatBuffersTestMethod] + public void TestArrayOfBools() + { + var fbb = new FlatBufferBuilder(256); + + Span boolsData = stackalloc bool[] { true, false, true, false, true }; + var boolsVec = Monster.CreateTestarrayofboolsVector(fbb, boolsData); + + var name = fbb.CreateString("BoolsMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + Monster.AddTestarrayofbools(fbb, boolsVec); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var monster = Monster.GetRootAsMonster(fbb.DataBuffer); + + Assert.AreEqual(5, monster.Testarrayofbools.Value.Length); + Assert.AreEqual(true, monster.Testarrayofbools.Value[0]); + Assert.AreEqual(false, monster.Testarrayofbools.Value[1]); + Assert.AreEqual(true, monster.Testarrayofbools.Value[2]); + Assert.AreEqual(false, monster.Testarrayofbools.Value[3]); + Assert.AreEqual(true, monster.Testarrayofbools.Value[4]); + + TestObjectAPI(monster); + } + + [FlatBuffersTestMethod] + public void TestEnemy() + { + var fbb = new FlatBufferBuilder(256); + + var enemyName = fbb.CreateString("EnemyMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, enemyName); + Monster.AddHp(fbb, 50); + var enemy = Monster.EndMonster(fbb); + + var name = fbb.CreateString("MainMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + Monster.AddHp(fbb, 100); + Monster.AddEnemy(fbb, enemy); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var monster = Monster.GetRootAsMonster(fbb.DataBuffer); + + Assert.AreEqual("MainMonster", monster.Name); + Assert.AreEqual(100, monster.Hp); + Assert.IsTrue(monster.Enemy.HasValue); + Assert.AreEqual("EnemyMonster", monster.Enemy.Value.Name); + Assert.AreEqual(50, monster.Enemy.Value.Hp); + } + + [FlatBuffersTestMethod] + public void TestNanAndInfinityDefaults() + { + var fbb = new FlatBufferBuilder(256); + + var name = fbb.CreateString("NanInfMonster"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, name); + var mon = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, mon); + + var monster = Monster.GetRootAsMonster(fbb.DataBuffer); + + // Test default values for nan and infinity fields + Assert.IsTrue(float.IsNaN(monster.NanDefault)); + Assert.IsTrue(float.IsPositiveInfinity(monster.InfDefault)); + Assert.IsTrue(float.IsPositiveInfinity(monster.PositiveInfDefault)); + Assert.IsTrue(float.IsPositiveInfinity(monster.InfinityDefault)); + Assert.IsTrue(float.IsPositiveInfinity(monster.PositiveInfinityDefault)); + Assert.IsTrue(float.IsNegativeInfinity(monster.NegativeInfDefault)); + Assert.IsTrue(float.IsNegativeInfinity(monster.NegativeInfinityDefault)); + Assert.IsTrue(double.IsPositiveInfinity(monster.DoubleInfDefault)); + } + + [FlatBuffersTestMethod] + public void TestObjectAPI_Pack() + { + var monsterT = new MonsterT + { + Name = "PackedMonster", + Hp = 300, + Mana = 200, + Color = Color.Red, + Inventory = new System.Collections.Generic.List { 1, 2, 3, 4, 5 }, + Pos = new Vec3T + { + X = 1.0f, + Y = 2.0f, + Z = 3.0f, + Test1 = 4.0, + Test2 = Color.Green, + Test3 = new TestT { A = 10, B = 20 } + }, + Test4 = new System.Collections.Generic.List + { + new TestT { A = 100, B = 50 }, + new TestT { A = 200, B = 60 } + } + }; + + var fbb = new FlatBufferBuilder(1024); + var offset = Monster.Pack(fbb, monsterT); + Monster.FinishMonsterBuffer(fbb, offset); + + var buffer = fbb.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + Assert.AreEqual(monsterT.Name, monster.Name); + Assert.AreEqual(monsterT.Hp, monster.Hp); + Assert.AreEqual(monsterT.Mana, monster.Mana); + Assert.AreEqual(monsterT.Color, monster.Color); + + Assert.AreEqual(monsterT.Inventory.Count, monster.Inventory.Value.Length); + for (var i = 0; i < monsterT.Inventory.Count; ++i) + { + Assert.AreEqual(monsterT.Inventory[i], monster.Inventory.Value[i]); + } + + var pos = monster.Pos.Value; + Assert.AreEqual(monsterT.Pos.X, pos.X, 6); + Assert.AreEqual(monsterT.Pos.Y, pos.Y, 6); + Assert.AreEqual(monsterT.Pos.Z, pos.Z, 6); + Assert.AreEqual(monsterT.Pos.Test1, pos.Test1, 6); + Assert.AreEqual(monsterT.Pos.Test2, pos.Test2); + Assert.AreEqual(monsterT.Pos.Test3.A, pos.Test3.A); + Assert.AreEqual(monsterT.Pos.Test3.B, pos.Test3.B); + + var test4 = monster.Test4; + Assert.IsTrue(test4.HasValue); + var test4Vec = test4.Value; + Assert.AreEqual(monsterT.Test4.Count, test4Vec.Length); + for (var i = 0; i < monsterT.Test4.Count; ++i) + { + Assert.AreEqual(monsterT.Test4[i].A, test4Vec[i].A); + Assert.AreEqual(monsterT.Test4[i].B, test4Vec[i].B); + } + } + } +} diff --git a/net/FlatSpanBuffers.Tests/FlatBuffersFuzzTests.cs b/net/FlatSpanBuffers.Tests/FlatBuffersFuzzTests.cs new file mode 100644 index 00000000000..77ca6e1fb79 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/FlatBuffersFuzzTests.cs @@ -0,0 +1,1096 @@ +/* + * Copyright 2015 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 Google.FlatSpanBuffers.Tests +{ + + // Copied from: tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs + // Adapted for Google.FlatSpanBuffers namespace and API + [FlatBuffersTestClass] + public class FlatBuffersFuzzTests + { + private readonly Lcg _lcg = new Lcg(); + + [FlatBuffersTestMethod] + public void TestObjects() + { + CheckObjects(11, 100); + } + + [FlatBuffersTestMethod] + public void TestNumbers() + { + var builder = new FlatBufferBuilder(1); + byte[] expected = [0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(true); + expected = [1]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(-127); + expected = [129, 1]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(255); + expected = [0, 255, 129, 1]; // First pad + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(-32222); + expected = [0, 0, 0x22, 0x82, 0, 255, 129, 1]; // Second pad + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(0xFEEE); + expected = [0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]; // no pad + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(-53687092); + expected = [0, 0, 0, 0, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]; // third pad + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(0x98765432); + expected = [0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]; // no pad + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + } + + [FlatBuffersTestMethod] + public void TestNumbers64() + { + var builder = new FlatBufferBuilder(1); + builder.Add(0x1122334455667788); + byte[] expected = [0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + + builder = new FlatBufferBuilder(1); + builder.Add(0x1122334455667788); + expected = [0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + } + + [FlatBuffersTestMethod] + public void TestVector_1xUInt8() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(byte), 1, 1); + byte[] expected = [0, 0, 0, 0, 0, 0, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(1); + expected = [0, 0, 0, 0, 1, 0, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.EndVector(); + expected = [1, 0, 0, 0, 1, 0, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + } + + [FlatBuffersTestMethod] + public void TestVector_2xUint8() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(byte), 2, 1); + byte[] expected = [0, 0, 0, 0, 0, 0, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(1); + expected = [0, 0, 0, 0, 0, 1, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(2); + expected = [0, 0, 0, 0, 2, 1, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.EndVector(); + expected = [2, 0, 0, 0, 2, 1, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + } + + [FlatBuffersTestMethod] + public void TestVector_1xUInt16() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(ushort), 1, 1); + byte[] expected = [0, 0, 0, 0, 0, 0, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(1); + expected = [0, 0, 0, 0, 1, 0, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.EndVector(); + expected = [1, 0, 0, 0, 1, 0, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + } + + [FlatBuffersTestMethod] + public void TestVector_2xUInt16() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(ushort), 2, 1); + byte[] expected = [0, 0, 0, 0, 0, 0, 0, 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(0xABCD); + expected = [0, 0, 0, 0, 0, 0, 0xCD, 0xAB]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(0xDCBA); + expected = [0, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.EndVector(); + expected = [2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + } + + [FlatBuffersTestMethod] + public void TestCreateAsciiString() + { + var builder = new FlatBufferBuilder(1); + builder.CreateString("foo"); + byte[] expected = [3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + + builder.CreateString("moop"); + expected = + [ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // Padding to 32 bytes + 4, 0, 0, 0, + (byte)'m', (byte)'o', (byte)'o', (byte)'p', + 0, 0, 0, 0, // zero terminator with 3 byte pad + 3, 0, 0, 0, + (byte)'f', (byte)'o', (byte)'o', 0 + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + } + + [FlatBuffersTestMethod] + public void TestCreateSharedAsciiString() + { + var builder = new FlatBufferBuilder(1); + builder.CreateSharedString("foo"); + byte[] expected = [3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + + builder.CreateSharedString("foo"); + expected = [3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + } + + [FlatBuffersTestMethod] + public void TestCreateArbitraryString() + { + var builder = new FlatBufferBuilder(1); + builder.CreateString("\x01\x02\x03"); + byte[] expected = + [ + 3, 0, 0, 0, + 0x01, 0x02, 0x03, 0 + ]; // No padding + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.CreateString("\x04\x05\x06\x07"); + expected = + [ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // Padding to 32 bytes + 4, 0, 0, 0, + 0x04, 0x05, 0x06, 0x07, + 0, 0, 0, 0, // zero terminator with 3 byte pad + 3, 0, 0, 0, + 0x01, 0x02, 0x03, 0 + ]; // No padding + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + } + + [FlatBuffersTestMethod] + public void TestEmptyVTable() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(0); + byte[] expected = [0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.EndTable(); + expected = + [ + 4, 0, 4, 0, + 4, 0, 0, 0 + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + } + + [FlatBuffersTestMethod] + public void TestVTableWithOneBool() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(1); + byte[] expected = [0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(0, true, false); + builder.EndTable(); + expected = + [ + 0, 0, // padding to 16 bytes + 6, 0, // vtable bytes + 8, 0, // object length inc vtable offset + 7, 0, // start of bool value + 6, 0, 0, 0, // int32 offset for start of vtable + 0, 0, 0, // padding + 1, // value 0 + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + var offset = 8; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart((uint)offset)); + // First field must be bool + Assert.IsTrue(verifier.VerifyField((uint)offset, 4, 1, 1, true)); + // Check Error: Second field + Assert.IsFalse(verifier.VerifyField((uint)offset, 6, 1, 1, true)); + // Check Error: First field too big alignment + Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 1, 2, true)); + // Check Error: First size to big + Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 2, 1, true)); + } + + [FlatBuffersTestMethod] + public void TestVTableWithOneBool_DefaultValue() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(1); + byte[] expected = [0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(0, false, false); + builder.EndTable(); + expected = + [ + // No padding. + 4, 0, // vtable bytes + 4, 0, // end of object from here + // entry 0 is not stored (trimmed end of vtable) + 4, 0, 0, 0, // int32 offset for start of vtable + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + var offset = 4; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart((uint)offset)); + // First field must be bool + Assert.IsTrue(verifier.VerifyField((uint)offset, 4, 1, 1, false)); + // Error Check: First field not present + Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 1, 1, true)); + } + + [FlatBuffersTestMethod] + public void TestVTableWithOneInt16() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(1); + byte[] expected = [0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(0, 0x789A, 0); + int offset = builder.EndTable(); + expected = + [ + 0, 0, // padding to 16 bytes + 6, 0, // vtable bytes + 8, 0, // object length inc vtable offset + 6, 0, // start of int16 value + 6, 0, 0, 0, // int32 offset for start of vtable + 0, 0, // padding + 0x9A, 0x78, //value 0 + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + offset += builder.DataBuffer.Position; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart((uint)offset)); + // First field must be ushort + Assert.IsTrue(verifier.VerifyField((uint)offset, 4, 2, 2, true)); + // Check Error: Second field + Assert.IsFalse(verifier.VerifyField((uint)offset, 6, 2, 2, true)); + // Check Error: First field too big alignment + Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 4, 2, true)); + // Check Error: First field size to big + Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 2, 4, true)); + } + + [FlatBuffersTestMethod] + public void TestVTableWithTwoInt16() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(2); + byte[] expected = [0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(0, 0x3456, 0); + builder.Add(1, 0x789A, 0); + int offset = builder.EndTable(); + expected = + [ + 8, 0, // vtable bytes + 8, 0, // object length inc vtable offset + 6, 0, // start of int16 value 0 + 4, 0, // start of int16 value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 0x9A, 0x78, // value 1 + 0x56, 0x34, // value 0 + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + offset += builder.DataBuffer.Position; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart((uint)offset)); + // First field must be ushort + Assert.IsTrue(verifier.VerifyField((uint)offset, 4, 2, 2, true)); + // Check Error: Second field + Assert.IsTrue(verifier.VerifyField((uint)offset, 6, 2, 2, true)); + // Check Error: Second field too big alignment + Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 4, 2, true)); + // Check Error: Second field size to big + Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 2, 4, true)); + } + + [FlatBuffersTestMethod] + public void TestVTableWithInt16AndBool() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(2); + byte[] expected = [0]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + builder.Add(0, 0x3456, 0); + builder.Add(1, true, false); + int offset = builder.EndTable(); + expected = + [ + 8, 0, // vtable bytes + 8, 0, // object length inc vtable offset + 6, 0, // start of int16 value 0 + 5, 0, // start of bool value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 0, 1, // padding + value 1 + 0x56, 0x34, // value 0 + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + offset += builder.DataBuffer.Position; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart((uint)offset)); + // First field must be ushort + Assert.IsTrue(verifier.VerifyField((uint)offset, 4, 2, 2, true)); + // Check Error: Second field must be bool + Assert.IsTrue(verifier.VerifyField((uint)offset, 6, 1, 1, true)); + // Check Error: Second field too big alignment + Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 4, 2, true)); + // Check Error: Second field size to big + Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 2, 4, true)); + } + + [FlatBuffersTestMethod] + public void TestVTableWithEmptyVector() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(byte), 0, 1); + var vecEnd = builder.EndVector(); + + builder.StartTable(1); + + builder.AddOffset(0, vecEnd.Value, 0); + builder.EndTable(); + byte[] expected = + [ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, // Padding to 32 bytes + 6, 0, // vtable bytes + 8, 0, // object length inc vtable offset + 4, 0, // start of vector offset value 0 + 6, 0, 0, 0, // int32 offset for start of vtable + 4, 0, 0, 0, + 0, 0, 0, 0, + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = 20; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // First field must be vector with element size 1 + Assert.IsTrue(verifier.VerifyVectorOfData(checkOffset, 4, 1, true)); + } + + [FlatBuffersTestMethod] + public void TestVTableWithEmptyVectorAndScalars() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(byte), 0, 1); + var vecEnd = builder.EndVector(); + + builder.StartTable(2); + builder.Add(0, 55, 0); + builder.AddOffset(1, vecEnd.Value, 0); + builder.EndTable(); + byte[] expected = + [ + 0, 0, 0, 0, + 0, 0, 0, 0, // Padding to 32 bytes + 8, 0, // vtable bytes + 12, 0, // object length inc vtable offset + 10, 0, // offset to int16 value 0 + 4, 0, // start of vector offset value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 8, 0, 0, 0, // value 1 + 0, 0, 55, 0, // value 0 + 0, 0, 0, 0, // length of vector (not in sctruc) + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = 16; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // First field must be short + Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 2, 2, true)); + // Second field must be vector with element size 1 + Assert.IsTrue(verifier.VerifyVectorOfData(checkOffset, 6, 2, true)); + } + + + [FlatBuffersTestMethod] + public void TestVTableWith_1xInt16_and_Vector_or_2xInt16() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(short), 2, 1); + builder.Add(0x1234); + builder.Add(0x5678); + var vecEnd = builder.EndVector(); + + builder.StartTable(2); + builder.AddOffset(1, vecEnd.Value, 0); + builder.Add(0, 55, 0); + builder.EndTable(); + byte[] expected = + [ + 0, 0, 0, 0, // Padding to 32 bytes + 8, 0, // vtable bytes + 12, 0, // object length + 6, 0, // start of value 0 from end of vtable + 8, 0, // start of value 1 from end of buffer + 8, 0, 0, 0, // int32 offset for start of vtable + 0, 0, 55, 0, // padding + value 0 + 4, 0, 0, 0, // position of vector from here + 2, 0, 0, 0, // length of vector + 0x78, 0x56, // vector value 0 + 0x34, 0x12, // vector value 1 + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = 12; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // Second field must be vector with element size 2 + Assert.IsTrue(verifier.VerifyVectorOfData(checkOffset, 6, 2, true)); + // Check Error: Second field with too big size + Assert.IsFalse(verifier.VerifyVectorOfData(checkOffset, 6, 4, true)); + // First field must be short + Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 2, 2, true)); + } + + [FlatBuffersTestMethod] + public void TestVTableWithAStruct_of_int8_int16_int32() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(1); + builder.Prep(4+4+4, 0); + builder.Add(55); + builder.Pad(3); + builder.Add(0x1234); + builder.Pad(2); + builder.Add(0x12345678); + var structStart = builder.Offset; + builder.AddStruct(0, structStart, 0); + builder.EndTable(); + + // Actual buffer data (22 bytes of data + 2 bytes padding = 24 bytes total) + byte[] expected = + [ + 0, 0, // Padding to align to buffer size + 6, 0, // vtable bytes + 16, 0, // object length + 4, 0, // start of struct from here + 6, 0, 0, 0, // int32 offset for start of vtable + 0x78, 0x56, 0x34, 0x12, // struct value 2 + 0x00, 0x00, 0x34, 0x12, // struct value 1 + 0x00, 0x00, 0x00, 55, // struct value 0 + ]; + + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = 8; // 2 bytes padding + 6 bytes vtable = 8 bytes to table start + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // First field must be a struct with 12 bytes + Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 12, 4, true)); + // Check Error: First field with more than 12 bytes + Assert.IsFalse(verifier.VerifyField(checkOffset, 4, 16, 4, true)); + } + + + [FlatBuffersTestMethod] + public void TestVTableWithAVectorOf_2xStructOf_2xInt8() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(byte)*2, 2, 1); + builder.Add(33); + builder.Add(44); + builder.Add(55); + builder.Add(66); + var vecEnd = builder.EndVector(); + + builder.StartTable(1); + builder.AddOffset(0, vecEnd.Value, 0); + builder.EndTable(); + + byte[] expected = + [ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, // Padding to 32 bytes + 6, 0, // vtable bytes + 8, 0, // object length + 4, 0, // offset of vector offset + 6, 0, 0, 0, // int32 offset for start of vtable + 4, 0, 0, 0, // Vector start offset + 2, 0, 0, 0, // Vector len + 66, // vector 1, 1 + 55, // vector 1, 0 + 44, // vector 0, 1 + 33, // vector 0, 0 + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = 16; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // First field must be vector with element size 2 + Assert.IsTrue(verifier.VerifyVectorOfData(checkOffset, 4, 2, true)); + } + + [FlatBuffersTestMethod] + public void TestVTableWithSomeElements() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(2); + builder.Add(0, 33, 0); + builder.Add(1, 66, 0); + var off = builder.EndTable(); + builder.Finish(off); + + byte[] padded = + [ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, //Padding to 32 bytes + 12, 0, 0, 0, // root of table, pointing to vtable offset + 8, 0, // vtable bytes + 8, 0, // object length + 7, 0, // start of value 0 + 4, 0, // start of value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 66, 0, // value 1 + 0, 33, // value 0 + + ]; + Assert.SpanEqual(padded, builder.DataBuffer.ToSpan(0, padded.Length)); + + // no padding in sized array + byte[] unpadded = new byte[padded.Length - 12]; + System.Buffer.BlockCopy(padded, 12, unpadded, 0, unpadded.Length); + Assert.SpanEqual(unpadded, builder.DataBuffer.ToSizedSpan()); + + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = builder.DataBuffer.Get(builder.DataBuffer.Position) + (uint)builder.DataBuffer.Position; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // First field must be a struct with 12 bytes + Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 1, 1, true)); + // Second field must be a struct with 12 bytes + Assert.IsTrue(verifier.VerifyField(checkOffset, 6, 2, 2, true)); + } + + [FlatBuffersTestMethod] + public void TestVTableWithStrings() + { + var builder = new FlatBufferBuilder(64); + var str1 = builder.CreateString("foo"); + var str2 = builder.CreateString("foobar"); + builder.StartTable(2); + builder.AddOffset(0, str1.Value, 0); + builder.AddOffset(1, str2.Value, 0); + var off = builder.EndTable(); + builder.Finish(off); + + byte[] padded = + [ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, //Padding to 32 bytes + 12, 0, 0, 0, // root of table, pointing to vtable offset + 8, 0, // vtable bytes + 12, 0, // object length + 8, 0, // start of value 0 + 4, 0, // start of value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 8, 0, 0, 0, // pointer to string + 16, 0, 0, 0, // pointer to string + 6, 0, 0, 0, // length of string + 102, 111, 111, 98, 97, 114, 0, 0, // "foobar" + padding + 3, 0, 0, 0, // length of string + 102, 111, 111, 0 // "bar" + ]; + Assert.SpanEqual(padded, builder.DataBuffer.ToSpan(0, padded.Length)); + + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = builder.DataBuffer.Get(builder.DataBuffer.Position) + (uint)builder.DataBuffer.Position; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // First field string check + Assert.IsTrue(verifier.VerifyString(checkOffset, 4, true)); + // Second field string check + Assert.IsTrue(verifier.VerifyString(checkOffset, 6, true)); + } +//// builder.AddOffsetSpan([str1.Value, str2.Value]); // add multiple offsets at a time. + [FlatBuffersTestMethod] + public void TestVTableWithVectorOfStrings() + { + var builder = new FlatBufferBuilder(64); + var str1 = builder.CreateString("foo"); + var str2 = builder.CreateString("foobar"); + builder.StartVector(sizeof(int), 2, 1); + builder.AddOffsetSpan([str2.Value, str1.Value]); // add multiple offsets at a time. + //builder.AddOffset(str1.Value); + //builder.AddOffset(str2.Value); + var vec = builder.EndVector(); + builder.StartTable(1); + builder.AddOffset(0, vec.Value, 0); + var off = builder.EndTable(); + builder.Finish(off); + + byte[] padded = new byte[] + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, //Padding to 32 bytes + 12, 0, 0, 0, // root of table, pointing to vtable offset + 0, 0, // padding + 6, 0, // vtable bytes + 8, 0, // object length + 4, 0, // start of value 0 + 6, 0, 0, 0, // int32 offset for start of vtable + 4, 0, 0, 0, // pointer to vector + 2, 0, 0, 0, // length of vector + 8, 0, 0, 0, // int32 offset to string 1 + 16, 0, 0, 0, // int32 offset to string 2 + 6, 0, 0, 0, // length of string + 102, 111, 111, 98, 97, 114, 0, 0, // "foobar" + padding + 3, 0, 0, 0, // length of string + 102, 111, 111, 0 // "bar" + }; + Assert.SpanEqual(padded, builder.DataBuffer.ToSpan(0, padded.Length)); + + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = builder.DataBuffer.Get(builder.DataBuffer.Position) + (uint)builder.DataBuffer.Position; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // First field string check + Assert.IsTrue(verifier.VerifyVectorOfStrings(checkOffset, 4, true)); + } + + [FlatBuffersTestMethod] + public void TestTwoFinishTable() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(2); + builder.Add(0, 33, 0); + builder.Add(1, 44, 0); + var off0 = builder.EndTable(); + builder.Finish(off0); + + builder.StartTable(3); + builder.Add(0, 55, 0); + builder.Add(1, 66, 0); + builder.Add(2, 77, 0); + var off1 = builder.EndTable(); + builder.Finish(off1); + + byte[] expected = + [ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // padding to 64 bytes + 16, 0, 0, 0, // root of table, pointing to vtable offset (obj1) + 0, 0, // padding + + 10, 0, // vtable bytes + 8, 0, // object length + 7, 0, // start of value 0 + 6, 0, // start of value 1 + 5, 0, // start of value 2 + 10, 0, 0, 0, // int32 offset for start of vtable + 0, // pad + 77, // values 2, 1, 0 + 66, + 55, + + 12, 0, 0, 0, // root of table, pointing to vtable offset (obj0) + 8, 0, // vtable bytes + 8, 0, // object length + 7, 0, // start of value 0 + 6, 0, // start of value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 0, 0, // pad + 44, // value 1, 0 + 33, + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, builder.DataBuffer.Length)); + + // check obj1 + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = builder.DataBuffer.Get(builder.DataBuffer.Position) + (uint)builder.DataBuffer.Position; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // First field must be a struct with 12 bytes + Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 1, 1, true)); + // Second field must be a struct with 12 bytes + Assert.IsTrue(verifier.VerifyField(checkOffset, 6, 1, 1, true)); + // Third field must be a struct with 12 bytes + Assert.IsTrue(verifier.VerifyField(checkOffset, 8, 1, 1, true)); + // Check Error: 4. field did not exist + Assert.IsFalse(verifier.VerifyField(checkOffset, 10, 1, 1, true)); + + // check obj0 + checkOffset = 56; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // First field must be a struct with 12 bytes + Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 1, 1, true)); + // Second field must be a struct with 12 bytes + Assert.IsTrue(verifier.VerifyField(checkOffset, 6, 1, 1, true)); + // Check Error: 3. field did not exist + Assert.IsFalse(verifier.VerifyField(checkOffset, 8, 1, 1, true)); + // Check Error: 4. field did not exist + Assert.IsFalse(verifier.VerifyField(checkOffset, 10, 1, 1, true)); + } + + [FlatBuffersTestMethod] + public void TestBunchOfBools() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(8); + for (var i = 0; i < 8; i++) + { + builder.Add(i, true, false); + } + var off = builder.EndTable(); + builder.Finish(off); + + byte[] padded = + [ + 0, 0, 0, 0, + 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 + + 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.SpanEqual(padded, builder.DataBuffer.ToSpan(0, padded.Length)); + + // no padding in sized array + byte[] unpadded = new byte[padded.Length - 28]; + System.Buffer.BlockCopy(padded, 28, unpadded, 0, unpadded.Length); + Assert.SpanEqual(unpadded, builder.DataBuffer.ToSizedSpan()); + + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = builder.DataBuffer.Get(builder.DataBuffer.Position) + (uint)builder.DataBuffer.Position; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + for (var i = 0; i < 8; i++) + { + Assert.IsTrue(verifier.VerifyField(checkOffset, (short)(4 + i * 2), 1, 1, true)); + } + Assert.IsFalse(verifier.VerifyField(checkOffset, (short)(4 + 8 * 2), 1, 1, true)); + } + + [FlatBuffersTestMethod] + public void TestBunchOfBoolsSizePrefixed() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(8); + for (var i = 0; i < 8; i++) + { + builder.Add(i, true, false); + } + var off = builder.EndTable(); + builder.FinishSizePrefixed(off); + + byte[] padded = + [ + 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.SpanEqual(padded, builder.DataBuffer.ToSpan(0, padded.Length)); + + // no padding in sized array + byte[] unpadded = new byte[padded.Length - 24]; + System.Buffer.BlockCopy(padded, 24, unpadded, 0, unpadded.Length); + Assert.SpanEqual(unpadded, builder.DataBuffer.ToSizedSpan()); + } + + [FlatBuffersTestMethod] + public void TestWithFloat() + { + var builder = new FlatBufferBuilder(1); + builder.StartTable(1); + builder.Add(0, 1, 0); + builder.EndTable(); + + + byte[] expected = + [ + 0, 0, + 6, 0, // vtable bytes + 8, 0, // object length + 4, 0, // start of value 0 + 6, 0, 0, 0, // int32 offset for start of vtable + 0, 0, 128, 63, // value + + ]; + Assert.SpanEqual(expected, builder.DataBuffer.ToSpan(0, expected.Length)); + var verifier = new Verifier(builder.DataBuffer); + uint checkOffset = 8; + // table must be ok + Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); + // First Field must be float + Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 4, 4, true)); + // Check Error: First Field with to big size + Assert.IsFalse(verifier.VerifyField(checkOffset, 4, 8, 4, true)); + // Check Error: First Field with to big padding + Assert.IsFalse(verifier.VerifyField(checkOffset, 4, 4, 8, true)); + } + + private void CheckObjects(int fieldCount, int objectCount) + { + _lcg.Reset(); + + const int testValuesMax = 11; + + //var builder = new FlatBufferBuilder(1); + var bb = new ByteBuffer(1); + var vtableWorkspace = new int[fieldCount]; + var vtableOffsetWorkspace = new int[objectCount]; + var builder = new FlatBufferBuilder(bb, vtableWorkspace, vtableOffsetWorkspace); + + var objects = new int[objectCount]; + + for (var i = 0; i < objectCount; ++i) + { + builder.StartTable(fieldCount); + + for (var j = 0; j < fieldCount; ++j) + { + var fieldType = _lcg.Next()%testValuesMax; + + switch (fieldType) + { + case 0: + { + builder.Add(j, FuzzTestData.BoolValue, false); + break; + } + case 1: + { + builder.Add(j, FuzzTestData.Int8Value, 0); + break; + } + case 2: + { + builder.Add(j, FuzzTestData.UInt8Value, 0); + break; + } + case 3: + { + builder.Add(j, FuzzTestData.Int16Value, 0); + break; + } + case 4: + { + builder.Add(j, FuzzTestData.UInt16Value, 0); + break; + } + case 5: + { + builder.Add(j, FuzzTestData.Int32Value, 0); + break; + } + case 6: + { + builder.Add(j, FuzzTestData.UInt32Value, 0); + break; + } + case 7: + { + builder.Add(j, FuzzTestData.Int64Value, 0); + break; + } + case 8: + { + builder.Add(j, FuzzTestData.UInt64Value, 0); + break; + } + case 9: + { + builder.Add(j, FuzzTestData.Float32Value, 0); + break; + } + case 10: + { + builder.Add(j, FuzzTestData.Float64Value, 0); + break; + } + default: + throw new Exception("Unreachable"); + } + + } + + var offset = builder.EndTable(); + + // Store the object offset + objects[i] = offset; + } + + _lcg.Reset(); + + // Test all objects are readable and return expected values... + for (var i = 0; i < objectCount; ++i) + { + var table = new TestTable(builder.DataBuffer, builder.DataBuffer.Length - objects[i]); + + for (var j = 0; j < fieldCount; ++j) + { + var fieldType = _lcg.Next() % testValuesMax; + var fc = 2 + j; // 2 == VtableMetadataFields + var f = fc * 2; + + switch (fieldType) + { + case 0: + { + Assert.AreEqual(FuzzTestData.BoolValue, table.GetSlot(f, false)); + break; + } + case 1: + { + Assert.AreEqual(FuzzTestData.Int8Value, table.GetSlot(f, (sbyte)0)); + break; + } + case 2: + { + Assert.AreEqual(FuzzTestData.UInt8Value, table.GetSlot(f, (byte)0)); + break; + } + case 3: + { + Assert.AreEqual(FuzzTestData.Int16Value, table.GetSlot(f, (short)0)); + break; + } + case 4: + { + Assert.AreEqual(FuzzTestData.UInt16Value, table.GetSlot(f, (ushort)0)); + break; + } + case 5: + { + Assert.AreEqual(FuzzTestData.Int32Value, table.GetSlot(f, (int)0)); + break; + } + case 6: + { + Assert.AreEqual(FuzzTestData.UInt32Value, table.GetSlot(f, (uint)0)); + break; + } + case 7: + { + Assert.AreEqual(FuzzTestData.Int64Value, table.GetSlot(f, (long)0)); + break; + } + case 8: + { + Assert.AreEqual(FuzzTestData.UInt64Value, table.GetSlot(f, (ulong)0)); + break; + } + case 9: + { + Assert.AreEqual(FuzzTestData.Float32Value, table.GetSlot(f, (float)0)); + break; + } + case 10: + { + Assert.AreEqual(FuzzTestData.Float64Value, table.GetSlot(f, (double)0)); + break; + } + default: + throw new Exception("Unreachable"); + } + + } + + } + + } + } +} diff --git a/net/FlatSpanBuffers.Tests/FlatBuffersTestClassAttribute.cs b/net/FlatSpanBuffers.Tests/FlatBuffersTestClassAttribute.cs new file mode 100644 index 00000000000..c3bf7f20068 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/FlatBuffersTestClassAttribute.cs @@ -0,0 +1,28 @@ +/* + * Copyright 2016 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; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Google.FlatSpanBuffers.Tests +{ + [AttributeUsage(AttributeTargets.Class)] + public class FlatBuffersTestClassAttribute : Attribute + { + } +} diff --git a/net/FlatSpanBuffers.Tests/FlatBuffersTestMethodAttribute.cs b/net/FlatSpanBuffers.Tests/FlatBuffersTestMethodAttribute.cs new file mode 100644 index 00000000000..fa6c13c1090 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/FlatBuffersTestMethodAttribute.cs @@ -0,0 +1,25 @@ +/* + * Copyright 2016 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 Google.FlatSpanBuffers.Tests +{ + [AttributeUsage(AttributeTargets.Method)] + public class FlatBuffersTestMethodAttribute : Attribute + { + } +} diff --git a/net/FlatSpanBuffers.Tests/FlatSpanBuffers.Tests.csproj b/net/FlatSpanBuffers.Tests/FlatSpanBuffers.Tests.csproj new file mode 100644 index 00000000000..a1e36532e17 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/FlatSpanBuffers.Tests.csproj @@ -0,0 +1,22 @@ + + + + net10.0 + Exe + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/net/FlatSpanBuffers.Tests/FuzzTestData.cs b/net/FlatSpanBuffers.Tests/FuzzTestData.cs new file mode 100644 index 00000000000..827779fae16 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/FuzzTestData.cs @@ -0,0 +1,40 @@ +/* + * Copyright 2016 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. + */ + +// Mirrored from: tests/FlatBuffers.Test/FuzzTestData.cs + +using System; + +namespace Google.FlatSpanBuffers.Tests +{ + internal static class FuzzTestData + { + private static readonly byte[] _overflowInt32 = new byte[] {0x83, 0x33, 0x33, 0x33}; + private static readonly byte[] _overflowInt64 = new byte[] { 0x84, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }; + + public static readonly bool BoolValue = true; + public static readonly sbyte Int8Value = -127; // 0x81 + public static readonly byte UInt8Value = 255; // 0xFF + public static readonly short Int16Value = -32222; // 0x8222; + public static readonly ushort UInt16Value = 65262; // 0xFEEE + public static readonly int Int32Value = BitConverter.ToInt32(_overflowInt32, 0); + public static readonly uint UInt32Value = 0xFDDDDDDD; + public static readonly long Int64Value = BitConverter.ToInt64(_overflowInt64, 0); + public static readonly ulong UInt64Value = 0xFCCCCCCCCCCCCCCC; + public static readonly float Float32Value = 3.14159f; + public static readonly double Float64Value = 3.14159265359; + } +} diff --git a/net/FlatSpanBuffers.Tests/JsonSerializationTests.cs b/net/FlatSpanBuffers.Tests/JsonSerializationTests.cs new file mode 100644 index 00000000000..33b5458242c --- /dev/null +++ b/net/FlatSpanBuffers.Tests/JsonSerializationTests.cs @@ -0,0 +1,340 @@ +/* + * Copyright 2026 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; +using System.Collections.Generic; +using JsonTest; + +namespace Google.FlatSpanBuffers.Tests +{ + [FlatBuffersTestClass] + public class JsonSerializationTests + { + [FlatBuffersTestMethod] + public void BasicJsonRoundTrip() + { + var gameState = new GameStateT + { + Version = "1.0.0", + ActivePlayerId = 42, + Timestamp = 1234567890, + Players = new List + { + new PlayerT + { + Id = 1, + Name = "Player1", + Level = 10, + Health = 95.5f, + Status = Status.Active, + } + } + }; + + var json = gameState.SerializeToJson(); + + Assert.IsTrue(json.Contains("\"version\": \"1.0.0\"")); + Assert.IsTrue(json.Contains("\"active_player_id\": 42")); + Assert.IsTrue(json.Contains("\"Player1\"")); + + var deserialized = GameStateT.DeserializeFromJson(json); + + Assert.AreEqual(gameState.Version, deserialized.Version); + Assert.AreEqual(gameState.ActivePlayerId, deserialized.ActivePlayerId); + Assert.AreEqual(gameState.Timestamp, deserialized.Timestamp); + Assert.AreEqual(gameState.Players.Count, deserialized.Players.Count); + Assert.AreEqual(gameState.Players[0].Name, deserialized.Players[0].Name); + Assert.AreEqual(gameState.Players[0].Level, deserialized.Players[0].Level); + Assert.AreEqual(gameState.Players[0].Health, deserialized.Players[0].Health, 6); + } + + [FlatBuffersTestMethod] + public void EnumSerializesAsString() + { + var player = new PlayerT + { + Id = 1, + Name = "TestPlayer", + Status = Status.Suspended, + }; + + var gameState = new GameStateT + { + Version = "1.0", + Players = new List { player } + }; + + var json = gameState.SerializeToJson(); + + // Enums should serialize as strings due to JsonStringEnumConverter + Assert.IsTrue(json.Contains("\"status\": \"Suspended\"")); + + var deserialized = GameStateT.DeserializeFromJson(json); + Assert.AreEqual(Status.Suspended, deserialized.Players[0].Status); + } + + [FlatBuffersTestMethod] + public void BitFlagsEnumSerializesCorrectly() + { + var player = new PlayerT + { + Id = 1, + Name = "FlagPlayer", + Priorities = Priority.High | Priority.Critical, + }; + + var gameState = new GameStateT + { + Version = "1.0", + Players = new List { player } + }; + + var json = gameState.SerializeToJson(); + + var deserialized = GameStateT.DeserializeFromJson(json); + Assert.AreEqual(player.Priorities, deserialized.Players[0].Priorities); + } + + [FlatBuffersTestMethod] + public void StructSerializesCorrectly() + { + var player = new PlayerT + { + Id = 1, + Name = "StructPlayer", + Position = new Vec2T { X = 10.5f, Y = 20.5f }, + Color = new ColorT { R = 255, G = 128, B = 64, A = 255 }, + }; + + var gameState = new GameStateT + { + Version = "1.0", + Players = new List { player } + }; + + var json = gameState.SerializeToJson(); + + Assert.IsTrue(json.Contains("\"position\":")); + Assert.IsTrue(json.Contains("\"x\":")); + Assert.IsTrue(json.Contains("\"color\":")); + + var deserialized = GameStateT.DeserializeFromJson(json); + Assert.AreEqual(player.Position.X, deserialized.Players[0].Position.X, 6); + Assert.AreEqual(player.Position.Y, deserialized.Players[0].Position.Y, 6); + Assert.AreEqual(player.Color.R, deserialized.Players[0].Color.R); + Assert.AreEqual(player.Color.G, deserialized.Players[0].Color.G); + Assert.AreEqual(player.Color.B, deserialized.Players[0].Color.B); + } + + [FlatBuffersTestMethod] + public void VectorOfScalarsSerializesCorrectly() + { + var player = new PlayerT + { + Id = 1, + Name = "VectorPlayer", + Scores = new List { 100, 200, 300, 400 }, + Tags = new List { "tag1", "tag2", "tag3" }, + }; + + var gameState = new GameStateT + { + Version = "1.0", + Players = new List { player } + }; + + var json = gameState.SerializeToJson(); + + var deserialized = GameStateT.DeserializeFromJson(json); + Assert.AreEqual(player.Scores.Count, deserialized.Players[0].Scores.Count); + for (int i = 0; i < player.Scores.Count; i++) + { + Assert.AreEqual(player.Scores[i], deserialized.Players[0].Scores[i]); + } + Assert.AreEqual(player.Tags.Count, deserialized.Players[0].Tags.Count); + for (int i = 0; i < player.Tags.Count; i++) + { + Assert.AreEqual(player.Tags[i], deserialized.Players[0].Tags[i]); + } + } + + [FlatBuffersTestMethod] + public void VectorOfTablesSerializesCorrectly() + { + var player = new PlayerT + { + Id = 1, + Name = "InventoryPlayer", + Inventory = new List + { + new ItemT { Id = 1, Name = "Sword", Value = 100.0f }, + new ItemT { Id = 2, Name = "Shield", Value = 50.0f }, + new ItemT { Id = 3, Name = "Potion", Value = 25.0f }, + }, + }; + + var gameState = new GameStateT + { + Version = "1.0", + Players = new List { player } + }; + + var json = gameState.SerializeToJson(); + + var deserialized = GameStateT.DeserializeFromJson(json); + Assert.AreEqual(player.Inventory.Count, deserialized.Players[0].Inventory.Count); + for (int i = 0; i < player.Inventory.Count; i++) + { + Assert.AreEqual(player.Inventory[i].Id, deserialized.Players[0].Inventory[i].Id); + Assert.AreEqual(player.Inventory[i].Name, deserialized.Players[0].Inventory[i].Name); + Assert.AreEqual(player.Inventory[i].Value, deserialized.Players[0].Inventory[i].Value, 6); + } + } + + [FlatBuffersTestMethod] + public void UnionSerializesCorrectly() + { + // Note: Union deserialization is a known limitation with System.Text.Json + // The union converter requires type context which is not available during deserialization. + // This test verifies serialization works correctly. + + var weaponPlayer = new PlayerT + { + Id = 1, + Name = "WeaponPlayer", + Equipped = new EquipmentUnion { Type = Equipment.Weapon, Value = new WeaponT { Name = "Excalibur", Damage = 999 } }, + }; + + var armorPlayer = new PlayerT + { + Id = 2, + Name = "ArmorPlayer", + Equipped = new EquipmentUnion { Type = Equipment.Armor, Value = new ArmorT { Name = "DragonScale", Defense = 500 } }, + }; + + var gameState = new GameStateT + { + Version = "1.0", + Players = new List { weaponPlayer, armorPlayer } + }; + + var json = gameState.SerializeToJson(); + + // Verify union values are serialized to JSON + Assert.IsTrue(json.Contains("\"equipped\":")); + Assert.IsTrue(json.Contains("\"Excalibur\"")); + Assert.IsTrue(json.Contains("\"DragonScale\"")); + Assert.IsTrue(json.Contains("\"damage\": 999")); + Assert.IsTrue(json.Contains("\"defense\": 500")); + } + + [FlatBuffersTestMethod] + public void NullValuesHandledCorrectly() + { + var player = new PlayerT + { + Id = 1, + Name = "NullPlayer", + // Inventory, Tags, Scores, Position, etc. are null + }; + + var gameState = new GameStateT + { + Version = "1.0", + Players = new List { player } + }; + + var json = gameState.SerializeToJson(); + var deserialized = GameStateT.DeserializeFromJson(json); + + Assert.AreEqual("NullPlayer", deserialized.Players[0].Name); + Assert.IsNull(deserialized.Players[0].Inventory); + Assert.IsNull(deserialized.Players[0].Tags); + Assert.IsNull(deserialized.Players[0].Scores); + } + + [FlatBuffersTestMethod] + public void JsonToBinaryRoundTrip() + { + var gameState = new GameStateT + { + Version = "2.0.0", + ActivePlayerId = 100, + Timestamp = 9999999999, + Players = new List + { + new PlayerT + { + Id = 1, + Name = "BinaryPlayer", + Level = 50, + Health = 100.0f, + Status = Status.Active, + Position = new Vec2T { X = 1.0f, Y = 2.0f }, + } + } + }; + + // JSON round trip + var json = gameState.SerializeToJson(); + var fromJson = GameStateT.DeserializeFromJson(json); + + // Verify JSON round trip + Assert.AreEqual(gameState.Version, fromJson.Version); + Assert.AreEqual(gameState.Players[0].Name, fromJson.Players[0].Name); + + // Binary round trip + var binary = fromJson.SerializeToBinary(); + var fromBinary = GameStateT.DeserializeFromBinary(binary); + + // Verify final result + Assert.AreEqual(gameState.Version, fromBinary.Version); + Assert.AreEqual(gameState.ActivePlayerId, fromBinary.ActivePlayerId); + Assert.AreEqual(gameState.Timestamp, fromBinary.Timestamp); + Assert.AreEqual(gameState.Players[0].Name, fromBinary.Players[0].Name); + Assert.AreEqual(gameState.Players[0].Level, fromBinary.Players[0].Level); + Assert.AreEqual(gameState.Players[0].Health, fromBinary.Players[0].Health, 6); + } + + [FlatBuffersTestMethod] + public void MultiplePlayersSerializeCorrectly() + { + var gameState = new GameStateT + { + Version = "3.0", + ActivePlayerId = 2, + Players = new List + { + new PlayerT { Id = 1, Name = "Alice", Level = 10 }, + new PlayerT { Id = 2, Name = "Bob", Level = 20 }, + new PlayerT { Id = 3, Name = "Charlie", Level = 30 }, + } + }; + + var json = gameState.SerializeToJson(); + var deserialized = GameStateT.DeserializeFromJson(json); + + Assert.AreEqual(3, deserialized.Players.Count); + Assert.AreEqual("Alice", deserialized.Players[0].Name); + Assert.AreEqual("Bob", deserialized.Players[1].Name); + Assert.AreEqual("Charlie", deserialized.Players[2].Name); + Assert.AreEqual(10, deserialized.Players[0].Level); + Assert.AreEqual(20, deserialized.Players[1].Level); + Assert.AreEqual(30, deserialized.Players[2].Level); + } + } +} diff --git a/net/FlatSpanBuffers.Tests/Lcg.cs b/net/FlatSpanBuffers.Tests/Lcg.cs new file mode 100644 index 00000000000..9614316ebd8 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/Lcg.cs @@ -0,0 +1,44 @@ +/* + * Copyright 2016 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. + */ + +// Mirrored from: tests/FlatBuffers.Test/Lcg.cs + +namespace Google.FlatSpanBuffers.Tests +{ + /// + /// Lcg Pseudo RNG + /// + internal sealed class Lcg + { + private const uint InitialValue = 10000; + private uint _state; + + public Lcg() + { + _state = InitialValue; + } + + public uint Next() + { + return (_state = 69069 * _state + 362437); + } + + public void Reset() + { + _state = InitialValue; + } + } +} diff --git a/net/FlatSpanBuffers.Tests/LookupByKeyTests.cs b/net/FlatSpanBuffers.Tests/LookupByKeyTests.cs new file mode 100644 index 00000000000..71ffb121654 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/LookupByKeyTests.cs @@ -0,0 +1,346 @@ +/* + * Copyright 2026 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; +using Google.FlatSpanBuffers; +using KeyTest; +using SpanKeyTest = KeyTest.StackBuffer; + +namespace Google.FlatSpanBuffers.Tests +{ + [FlatBuffersTestClass] + public class LookupByKeyTests + { + [FlatBuffersTestMethod] + public void TestStringKeyLookup_Monster_Found() + { + var builder = new FlatBufferBuilder(1024); + + var name1 = builder.CreateString("Alice"); + var name2 = builder.CreateString("Bob"); + var name3 = builder.CreateString("Charlie"); + + var monster1 = KeyTestMonster.CreateKeyTestMonster(builder, name1, 100); + var monster2 = KeyTestMonster.CreateKeyTestMonster(builder, name2, 200); + var monster3 = KeyTestMonster.CreateKeyTestMonster(builder, name3, 150); + + Span> offsets = stackalloc Offset[] { monster1, monster2, monster3 }; + var vectorOffset = KeyTestMonster.CreateSortedVectorOfKeyTestMonster(builder, offsets); + + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + var bb = builder.DataBuffer; + var rootTable = new Table(bb.Get(bb.Position) + bb.Position, bb); + var fieldOffset = rootTable.__offset(4); + var vectorLocation = rootTable.__vector(fieldOffset); + + // Test finding each monster + Assert.IsTrue(KeyTestMonster.TryGetByKey(vectorLocation, "Alice", bb, out var foundAlice)); + Assert.IsTrue(KeyTestMonster.TryGetByKey(vectorLocation, "Bob", bb, out var foundBob)); + Assert.IsTrue(KeyTestMonster.TryGetByKey(vectorLocation, "Charlie", bb, out var foundCharlie)); + + Assert.AreEqual("Alice", foundAlice.Name); + Assert.AreEqual(100, foundAlice.Hp); + + Assert.AreEqual("Bob", foundBob.Name); + Assert.AreEqual(200, foundBob.Hp); + + Assert.AreEqual("Charlie", foundCharlie.Name); + Assert.AreEqual(150, foundCharlie.Hp); + } + + [FlatBuffersTestMethod] + public void TestStringKeyLookup_Monster_NotFound() + { + var builder = new FlatBufferBuilder(1024); + + var name1 = builder.CreateString("Alice"); + var name2 = builder.CreateString("Charlie"); + + var monster1 = KeyTestMonster.CreateKeyTestMonster(builder, name1, 100); + var monster2 = KeyTestMonster.CreateKeyTestMonster(builder, name2, 150); + + Span> offsets = stackalloc Offset[] { monster1, monster2 }; + var vectorOffset = KeyTestMonster.CreateSortedVectorOfKeyTestMonster(builder, offsets); + + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + // Test lookup + var bb = builder.DataBuffer; + var rootTable = new Table(bb.Get(bb.Position) + bb.Position, bb); + var fieldOffset = rootTable.__offset(4); + var vectorLocation = rootTable.__vector(fieldOffset); + + // Test looking for a monster that doesn't exist + Assert.IsFalse(KeyTestMonster.TryGetByKey(vectorLocation, "Bob", bb, out _)); + Assert.IsFalse(KeyTestMonster.TryGetByKey(vectorLocation, "Dave", bb, out _)); + } + + [FlatBuffersTestMethod] + public void TestScalarKeyLookup_Weapon_Found() + { + var builder = new FlatBufferBuilder(1024); + + var sword = builder.CreateString("Sword"); + var bow = builder.CreateString("Bow"); + var staff = builder.CreateString("Staff"); + + var weapon1 = KeyTestWeapon.CreateKeyTestWeapon(builder, 10, sword, 50); // id, name, damage + var weapon2 = KeyTestWeapon.CreateKeyTestWeapon(builder, 20, bow, 30); // id, name, damage + var weapon3 = KeyTestWeapon.CreateKeyTestWeapon(builder, 15, staff, 40); // id, name, damage + + Span> offsets = stackalloc Offset[] { weapon1, weapon2, weapon3 }; + var vectorOffset = KeyTestWeapon.CreateSortedVectorOfKeyTestWeapon(builder, offsets); + + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + var bb = builder.DataBuffer; + var rootTable = new Table(bb.Get(bb.Position) + bb.Position, bb); + var fieldOffset = rootTable.__offset(4); + var vectorLocation = rootTable.__vector(fieldOffset); + + Assert.IsTrue(vectorLocation != 0); + + // Test finding each weapon by ID + Assert.IsTrue(KeyTestWeapon.TryGetByKey(vectorLocation, 10, bb, out var found10)); + Assert.IsTrue(KeyTestWeapon.TryGetByKey(vectorLocation, 15, bb, out var found15)); + Assert.IsTrue(KeyTestWeapon.TryGetByKey(vectorLocation, 20, bb, out var found20)); + + Assert.AreEqual(10, found10.Id); + Assert.AreEqual("Sword", found10.Name); + Assert.AreEqual(50, found10.Damage); + + Assert.AreEqual(15, found15.Id); + Assert.AreEqual("Staff", found15.Name); + Assert.AreEqual(40, found15.Damage); + + Assert.AreEqual(20, found20.Id); + Assert.AreEqual("Bow", found20.Name); + Assert.AreEqual(30, found20.Damage); + } + + [FlatBuffersTestMethod] + public void TestScalarKeyLookup_Weapon_NotFound() + { + var builder = new FlatBufferBuilder(1024); + + var sword = builder.CreateString("Sword"); + var bow = builder.CreateString("Bow"); + + var weapon1 = KeyTestWeapon.CreateKeyTestWeapon(builder, 10, sword, 50); + var weapon2 = KeyTestWeapon.CreateKeyTestWeapon(builder, 20, bow, 30); + + Span> offsets = stackalloc Offset[] { weapon1, weapon2 }; + var vectorOffset = KeyTestWeapon.CreateSortedVectorOfKeyTestWeapon(builder, offsets); + + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + var bb = builder.DataBuffer; + var rootTable = new Table(bb.Get(bb.Position) + bb.Position, bb); + var fieldOffset = rootTable.__offset(4); + var vectorLocation = rootTable.__vector(fieldOffset); + + Assert.IsTrue(vectorLocation != 0); + + // Test looking for weapons that don't exist + Assert.IsFalse(KeyTestWeapon.TryGetByKey(vectorLocation, 5, bb, out _)); + Assert.IsFalse(KeyTestWeapon.TryGetByKey(vectorLocation, 15, bb, out _)); + Assert.IsFalse(KeyTestWeapon.TryGetByKey(vectorLocation, 25, bb, out _)); + } + + [FlatBuffersTestMethod] + public void TestEmptyVector_Lookup() + { + var builder = new FlatBufferBuilder(1024); + + var vectorOffset = builder.CreateVectorOfTables(new Offset[0]); + + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + var bb = builder.DataBuffer; + var rootTable = new Table(bb.Get(bb.Position) + bb.Position, bb); + var fieldOffset = rootTable.__offset(4); + var vectorLocation = rootTable.__vector(fieldOffset); + + var result = KeyTestMonster.TryGetByKey(vectorLocation, "Alice", bb, out _); + Assert.IsFalse(result); + } + + [FlatBuffersTestMethod] + public void TestSingleElement_Lookup() + { + var builder = new FlatBufferBuilder(1024); + + var name = builder.CreateString("OnlyOne"); + var monster = KeyTestMonster.CreateKeyTestMonster(builder, name, 42); + + Span> offsets = stackalloc Offset[] { monster }; + var vectorOffset = KeyTestMonster.CreateSortedVectorOfKeyTestMonster(builder, offsets); + + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + // Test lookup + var bb = builder.DataBuffer; + var rootTable = new Table(bb.Get(bb.Position) + bb.Position, bb); + var fieldOffset = rootTable.__offset(4); + var vectorLocation = rootTable.__vector(fieldOffset); + + // Should find the single element + Assert.IsTrue(KeyTestMonster.TryGetByKey(vectorLocation, "OnlyOne", bb, out var found)); + Assert.AreEqual("OnlyOne", found.Name); + Assert.AreEqual(42, found.Hp); + + // Should not find different keys + Assert.IsFalse(KeyTestMonster.TryGetByKey(vectorLocation, "Missing", bb, out _)); + } + + [FlatBuffersTestMethod] + public void TestLargeVector_StringLookup() + { + var builder = new FlatBufferBuilder(8192); + + var offsets = new Offset[100]; + for (int i = 0; i < 100; i++) + { + var name = builder.CreateString($"Monster{i:D3}"); // Monster000, Monster001, etc. + offsets[i] = KeyTestMonster.CreateKeyTestMonster(builder, name, i * 10); + } + + var vectorOffset = KeyTestMonster.CreateSortedVectorOfKeyTestMonster(builder, offsets.AsSpan()); + + // Finish the buffer + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + // Test lookup + var bb = builder.DataBuffer; + var rootTable = new Table(bb.Get(bb.Position) + bb.Position, bb); + var fieldOffset = rootTable.__offset(4); + var vectorLocation = rootTable.__vector(fieldOffset); + + // Test finding various monsters + Assert.IsTrue(KeyTestMonster.TryGetByKey(vectorLocation, "Monster000", bb, out var found000)); + Assert.IsTrue(KeyTestMonster.TryGetByKey(vectorLocation, "Monster050", bb, out var found050)); + Assert.IsTrue(KeyTestMonster.TryGetByKey(vectorLocation, "Monster099", bb, out var found099)); + + Assert.AreEqual("Monster000", found000.Name); + Assert.AreEqual(0, found000.Hp); + + Assert.AreEqual("Monster050", found050.Name); + Assert.AreEqual(500, found050.Hp); + + Assert.AreEqual("Monster099", found099.Name); + Assert.AreEqual(990, found099.Hp); + + // Test not found + Assert.IsFalse(KeyTestMonster.TryGetByKey(vectorLocation, "Monster100", bb, out _)); + } + + [FlatBuffersTestMethod] + public void TestEdgeCases_DuplicateKeys() + { + // Duplicate keys in sorted vectors are unspecified behavior in FlatBuffers. + // This test only verifies the lookup does not crash and returns a valid entry. + var builder = new FlatBufferBuilder(1024); + + var name = builder.CreateString("Duplicate"); + var monster1 = KeyTestMonster.CreateKeyTestMonster(builder, name, 100); + var monster2 = KeyTestMonster.CreateKeyTestMonster(builder, name, 200); + + Span> offsets = stackalloc Offset[] { monster1, monster2 }; + var vectorOffset = KeyTestMonster.CreateSortedVectorOfKeyTestMonster(builder, offsets); + + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + var bb = builder.DataBuffer; + var rootTable = new Table(bb.Get(bb.Position) + bb.Position, bb); + var fieldOffset = rootTable.__offset(4); + var vectorLocation = rootTable.__vector(fieldOffset); + + // Should find one of the duplicates without throwing + Assert.IsTrue(KeyTestMonster.TryGetByKey(vectorLocation, "Duplicate", bb, out var found)); + Assert.AreEqual("Duplicate", found.Name); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestStringKeyLookup_Found() + { + var bbSpan = new ByteSpanBuffer(new byte[1024]); + var builder = new FlatSpanBufferBuilder(bbSpan, vtableSpace: new int[4], vtableOffsetSpace: new int[16]); + + var name1 = builder.CreateString("Alice"); + var name2 = builder.CreateString("Bob"); + var name3 = builder.CreateString("Charlie"); + + var monster1 = SpanKeyTest.KeyTestMonster.CreateKeyTestMonster(ref builder, name1, 100); + var monster2 = SpanKeyTest.KeyTestMonster.CreateKeyTestMonster(ref builder, name2, 200); + var monster3 = SpanKeyTest.KeyTestMonster.CreateKeyTestMonster(ref builder, name3, 150); + + Span> offsets = stackalloc Offset[] { monster1, monster2, monster3 }; + var vectorOffset = SpanKeyTest.KeyTestMonster.CreateSortedVectorOfKeyTestMonster(ref builder, offsets); + + builder.StartTable(1); + builder.AddOffset(0, vectorOffset.Value, 0); + var rootOffset = builder.EndTable(); + builder.Finish(rootOffset); + + var bb = builder.DataBuffer; + var rootTable = new TableSpan(bb.Get(bb.Position) + bb.Position, bb); + var fieldOffset = rootTable.__offset(4); + var vectorLocation = rootTable.__vector(fieldOffset); + + // Test finding each monster + Assert.IsTrue(SpanKeyTest.KeyTestMonster.TryGetByKey(vectorLocation, "Alice", bb, out var foundAlice)); + Assert.IsTrue(SpanKeyTest.KeyTestMonster.TryGetByKey(vectorLocation, "Bob", bb, out var foundBob)); + Assert.IsTrue(SpanKeyTest.KeyTestMonster.TryGetByKey(vectorLocation, "Charlie", bb, out var foundCharlie)); + + Assert.AreEqual("Alice", foundAlice.Name); + Assert.AreEqual(100, foundAlice.Hp); + + Assert.AreEqual("Bob", foundBob.Name); + Assert.AreEqual(200, foundBob.Hp); + + Assert.AreEqual("Charlie", foundCharlie.Name); + Assert.AreEqual(150, foundCharlie.Hp); + + // Verify not-found also works + Assert.IsFalse(SpanKeyTest.KeyTestMonster.TryGetByKey(vectorLocation, "Dave", bb, out _)); + } + } +} diff --git a/net/FlatSpanBuffers.Tests/MutabilityTests.cs b/net/FlatSpanBuffers.Tests/MutabilityTests.cs new file mode 100644 index 00000000000..aad0dfe325c --- /dev/null +++ b/net/FlatSpanBuffers.Tests/MutabilityTests.cs @@ -0,0 +1,539 @@ +/* + * Copyright 2026 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; +using MonsterTest; + +namespace Google.FlatSpanBuffers.Tests +{ + [FlatBuffersTestClass] + public class MutabilityTests + { + [FlatBuffersTestMethod] + public void ByteBuffer_MutateScalarField_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 80); // Non-default (default is 100) + Monster.AddMana(builder, 120); // Non-default (default is 150) + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var buffer = builder.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + Assert.AreEqual(80, monster.Hp); + Assert.AreEqual(120, monster.Mana); + Assert.IsTrue(monster.MutateHp(150)); + Assert.IsTrue(monster.MutateMana(250)); + Assert.AreEqual(150, monster.Hp); + Assert.AreEqual(250, monster.Mana); + + var monster2 = Monster.GetRootAsMonster(buffer); + Assert.AreEqual(150, monster2.Hp); + Assert.AreEqual(250, monster2.Mana); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_MutateEnumField_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddColor(builder, Color.Red); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var buffer = builder.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + Assert.AreEqual(Color.Red, monster.Color); + Assert.IsTrue(monster.MutateColor(Color.Green)); + Assert.AreEqual(Color.Green, monster.Color); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_MutateVectorElement_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Span inventoryData = stackalloc byte[] { 10, 20, 30, 40, 50 }; + var inventoryVector = Monster.CreateInventoryVectorBlock(builder, inventoryData); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddInventory(builder, inventoryVector); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var buffer = builder.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + var inventory = monster.Inventory; + Assert.IsTrue(inventory.HasValue); + Assert.AreEqual(inventoryData.Length, inventory.Value.Length); + Assert.AreEqual(10, inventory.Value[0]); + Assert.AreEqual(30, inventory.Value[2]); + + var inventorySpan = monster.MutableInventory; + Assert.IsTrue(inventorySpan.HasValue); + inventorySpan.Value[0] = 100; + inventorySpan.Value[2] = 200; + + var inventory2 = monster.Inventory; + Assert.AreEqual(100, inventory2.Value[0]); + Assert.AreEqual(200, inventory2.Value[2]); + Assert.AreEqual(20, inventory2.Value[1]); // unchanged + } + + [FlatBuffersTestMethod] + public void ByteBuffer_MutateWithSpan_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Span inventoryData = stackalloc byte[] { 1, 2, 3, 4, 5 }; + var inventoryVector = Monster.CreateInventoryVectorBlock(builder, inventoryData); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddInventory(builder, inventoryVector); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var buffer = builder.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + var inventorySpan = monster.MutableInventory; + Assert.IsTrue(inventorySpan.HasValue); + Assert.AreEqual(inventoryData.Length, inventorySpan.Value.Length); + + inventorySpan.Value[0] = 100; + inventorySpan.Value[4] = 200; + + // Verify changes through the original accessor + var inventory = monster.Inventory; + Assert.AreEqual(100, inventory.Value[0]); + Assert.AreEqual(200, inventory.Value[4]); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_MutateNonExistentField_ReturnsFalse() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + // Create monster without setting Hp (will use default value 100) + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var buffer = builder.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + Assert.AreEqual(100, monster.Hp); // default value + + // MutateHp returns false when the field is not present in the buffer + Assert.IsFalse(monster.MutateHp(150)); + + // Double check Hp still equals default + Assert.AreEqual(100, monster.Hp); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_MutateWithForceDefaults_Success() + { + var builder = new FlatBufferBuilder(1024); + builder.ForceDefaults = true; + + var nameOffset = builder.CreateString("TestMonster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 100); // Even default value will be written due to ForceDefaults + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var buffer = builder.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + Assert.AreEqual(100, monster.Hp); + Assert.IsTrue(monster.MutateHp(150)); + Assert.AreEqual(150, monster.Hp); + } + + [FlatBuffersTestMethod] + public void StackBuffer_MutateScalarField_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 80); // Non-default (default is 100) + Monster.AddMana(builder, 120); // Non-default (default is 150) + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + Span data = builder.DataBuffer.ToSizedSpan(); + var spanBuffer = new ByteSpanBuffer(data); + + var monster = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + + Assert.AreEqual(80, monster.Hp); + Assert.AreEqual(120, monster.Mana); + Assert.IsTrue(monster.MutateHp(150)); + Assert.IsTrue(monster.MutateMana(250)); + Assert.AreEqual(150, monster.Hp); + Assert.AreEqual(250, monster.Mana); + } + + [FlatBuffersTestMethod] + public void StackBuffer_MutateEnumField_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddColor(builder, Color.Red); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + Span data = builder.DataBuffer.ToSizedSpan(); + var spanBuffer = new ByteSpanBuffer(data); + + var monster = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + + Assert.AreEqual(Color.Red, monster.Color); + Assert.IsTrue(monster.MutateColor(Color.Green)); + Assert.AreEqual(Color.Green, monster.Color); + } + + [FlatBuffersTestMethod] + public void StackBuffer_MutateVectorElement_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Span inventoryData = stackalloc byte[] { 10, 20, 30, 40, 50 }; + var inventoryVector = Monster.CreateInventoryVectorBlock(builder, inventoryData); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddInventory(builder, inventoryVector); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + Span data = builder.DataBuffer.ToSizedSpan(); + var spanBuffer = new ByteSpanBuffer(data); + + var monster = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + + var inventory = monster.Inventory; + Assert.IsTrue(inventory.HasValue); + Assert.AreEqual(5, inventory.Value.Length); + Assert.AreEqual(10, inventory.Value[0]); + Assert.AreEqual(30, inventory.Value[2]); + + var inventorySpan = monster.MutableInventory; + Assert.IsTrue(inventorySpan.HasValue); + inventorySpan.Value[0] = 100; + inventorySpan.Value[2] = 200; + + // Verify mutated values + var monster2 = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + var inventory2 = monster2.Inventory; + Assert.AreEqual(100, inventory2.Value[0]); + Assert.AreEqual(200, inventory2.Value[2]); + Assert.AreEqual(20, inventory2.Value[1]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_MutateWithSpan_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Span inventoryData = stackalloc byte[] { 1, 2, 3, 4, 5 }; + var inventoryVector = Monster.CreateInventoryVectorBlock(builder, inventoryData); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddInventory(builder, inventoryVector); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + Span data = builder.DataBuffer.ToSizedSpan(); + var spanBuffer = new ByteSpanBuffer(data); + + var monster = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + + var inventorySpan = monster.MutableInventory; + Assert.IsTrue(inventorySpan.HasValue); + Assert.AreEqual(5, inventorySpan.Value.Length); + inventorySpan.Value[0] = 100; + inventorySpan.Value[4] = 200; + + // Verify mutated values + var monster2 = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + var inventory = monster2.Inventory; + Assert.AreEqual(100, inventory.Value[0]); + Assert.AreEqual(200, inventory.Value[4]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_MutateOnStackAllocatedBuffer_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 50); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var serializedData = builder.DataBuffer.ToSizedSpan(); + Span stackBuffer = stackalloc byte[serializedData.Length]; + serializedData.CopyTo(stackBuffer); + + var spanBuffer = new ByteSpanBuffer(stackBuffer); + var monster = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + + Assert.AreEqual(50, monster.Hp); + Assert.IsTrue(monster.MutateHp(99)); + Assert.AreEqual(99, monster.Hp); + + // Verify the stack buffer was modified + spanBuffer.Position = 0; + var monster2 = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + Assert.AreEqual(99, monster2.Hp); + } + + [FlatBuffersTestMethod] + public void CrossVariant_MutationsProduceSameResults() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Span inventoryData = stackalloc byte[] { 1, 2, 3, 4, 5 }; + var inventoryVector = Monster.CreateInventoryVectorBlock(builder, inventoryData); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 80); // Non-default (default is 100) + Monster.AddMana(builder, 120); // Non-default (default is 150) + Monster.AddColor(builder, Color.Red); // Non-default (default is Blue) + Monster.AddInventory(builder, inventoryVector); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var serializedData = builder.DataBuffer.ToSizedSpan(); + var copy1 = new byte[serializedData.Length]; + var copy2 = new byte[serializedData.Length]; + serializedData.CopyTo(copy1.AsSpan()); + serializedData.CopyTo(copy2.AsSpan()); + + // Mutate using ByteBuffer + var byteBuffer = new ByteBuffer(copy1); + var monster1 = Monster.GetRootAsMonster(byteBuffer); + monster1.MutateHp(150); + monster1.MutateMana(250); + monster1.MutateColor(Color.Green); + var invSpan1 = monster1.MutableInventory; + Assert.IsTrue(invSpan1.HasValue); + invSpan1.Value[0] = 10; + invSpan1.Value[2] = 30; + + // Mutate using StackBuffer + var spanBuffer = new ByteSpanBuffer(copy2); + var monster2 = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + monster2.MutateHp(150); + monster2.MutateMana(250); + monster2.MutateColor(Color.Green); + var invSpan2 = monster2.MutableInventory; + Assert.IsTrue(invSpan2.HasValue); + invSpan2.Value[0] = 10; + invSpan2.Value[2] = 30; + + Assert.SpanEqual(copy1, copy2); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_MutateStructVectorElement_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Monster.StartPathVector(builder, 3); + Vec3.CreateVec3(builder, 3.0f, 3.0f, 3.0f); + Vec3.CreateVec3(builder, 2.0f, 2.0f, 2.0f); + Vec3.CreateVec3(builder, 1.0f, 1.0f, 1.0f); + var pathVector = builder.EndVector(); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddPath(builder, pathVector); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var buffer = builder.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + var path = monster.Path; + Assert.IsTrue(path.HasValue); + Assert.AreEqual(3, path.Value.Length); + + var vec0 = path.Value[0]; + Assert.AreEqual(1.0f, vec0.X, 3); + + var vec1 = path.Value[1]; + Assert.AreEqual(2.0f, vec1.X, 3); + + vec0.MutateX(10.0f); + vec0.MutateY(20.0f); + vec0.MutateZ(30.0f); + + var monster2 = Monster.GetRootAsMonster(buffer); + var path2 = monster2.Path; + var vec0_2 = path2.Value[0]; + + Assert.AreEqual(10.0f, vec0_2.X, 3); + Assert.AreEqual(20.0f, vec0_2.Y, 3); + Assert.AreEqual(30.0f, vec0_2.Z, 3); + + var vec1_2 = path2.Value[1]; + Assert.AreEqual(2.0f, vec1_2.X, 3); + } + + [FlatBuffersTestMethod] + public void StackBuffer_MutateStructVectorElement_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Monster.StartPathVector(builder, 3); + Vec3.CreateVec3(builder, 3.0f, 3.0f, 3.0f); + Vec3.CreateVec3(builder, 2.0f, 2.0f, 2.0f); + Vec3.CreateVec3(builder, 1.0f, 1.0f, 1.0f); + var pathVector = builder.EndVector(); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddPath(builder, pathVector); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + Span data = builder.DataBuffer.ToSizedSpan(); + var spanBuffer = new ByteSpanBuffer(data); + var monster = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + + var path = monster.Path; + Assert.IsTrue(path.HasValue); + Assert.AreEqual(3, path.Value.Length); + + var vec0 = path.Value[0]; + Assert.AreEqual(1.0f, vec0.X, 3); + + vec0.MutateX(10.0f); + vec0.MutateY(20.0f); + vec0.MutateZ(30.0f); + + spanBuffer.Position = 0; + var monster2 = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + var path2 = monster2.Path; + var vec0_2 = path2.Value[0]; + + Assert.AreEqual(10.0f, vec0_2.X, 3); + Assert.AreEqual(20.0f, vec0_2.Y, 3); + Assert.AreEqual(30.0f, vec0_2.Z, 3); + + var vec1_2 = path2.Value[1]; + Assert.AreEqual(2.0f, vec1_2.X, 3); + } + + [FlatBuffersTestMethod] + public void ByteBuffer_MutateInlineStruct_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddPos(builder, Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f)); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + var buffer = builder.DataBuffer; + var monster = Monster.GetRootAsMonster(buffer); + + var pos = monster.Pos; + Assert.IsTrue(pos.HasValue); + Assert.AreEqual(1.0f, pos.Value.X, 3); + Assert.AreEqual(2.0f, pos.Value.Y, 3); + Assert.AreEqual(3.0f, pos.Value.Z, 3); + + pos.Value.MutateX(100.0f); + pos.Value.MutateY(200.0f); + pos.Value.MutateZ(300.0f); + + var monster2 = Monster.GetRootAsMonster(buffer); + var pos2 = monster2.Pos; + Assert.AreEqual(100.0f, pos2.Value.X, 3); + Assert.AreEqual(200.0f, pos2.Value.Y, 3); + Assert.AreEqual(300.0f, pos2.Value.Z, 3); + } + + [FlatBuffersTestMethod] + public void StackBuffer_MutateInlineStruct_Success() + { + var builder = new FlatBufferBuilder(1024); + var nameOffset = builder.CreateString("TestMonster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddPos(builder, Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f)); + var monsterOffset = Monster.EndMonster(builder); + builder.Finish(monsterOffset.Value); + + Span data = builder.DataBuffer.ToSizedSpan(); + var spanBuffer = new ByteSpanBuffer(data); + var monster = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + + var pos = monster.Pos; + Assert.IsTrue(pos.HasValue); + Assert.AreEqual(1.0f, pos.Value.X, 3); + + pos.Value.MutateX(100.0f); + pos.Value.MutateY(200.0f); + pos.Value.MutateZ(300.0f); + + spanBuffer.Position = 0; + var monster2 = MonsterTest.StackBuffer.Monster.GetRootAsMonster(spanBuffer); + var pos2 = monster2.Pos; + Assert.AreEqual(100.0f, pos2.Value.X, 3); + Assert.AreEqual(200.0f, pos2.Value.Y, 3); + Assert.AreEqual(300.0f, pos2.Value.Z, 3); + } + } +} diff --git a/net/FlatSpanBuffers.Tests/ObjectApiStackBufferTests.cs b/net/FlatSpanBuffers.Tests/ObjectApiStackBufferTests.cs new file mode 100644 index 00000000000..bb01df32ad2 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/ObjectApiStackBufferTests.cs @@ -0,0 +1,662 @@ +/* + * Copyright 2026 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; +using System.Collections.Generic; +using ComprehensiveTest; +using ExampleAny = MyGame.Example.Any; +using ExampleColor = MyGame.Example.Color; +using ExampleMonster = MyGame.Example.Monster; +using StackExampleMonster = MyGame.Example.StackBuffer.Monster; + +namespace Google.FlatSpanBuffers.Tests +{ + [FlatBuffersTestClass] + public class ObjectApiStackBufferTests + { + private static FlatSpanBufferBuilder CreateStackBufferBuilderForExampleMonster() + { + const int ExampleMonsterVtableSize = 64; + var bb = new ByteSpanBuffer(new byte[1024]); + return new FlatSpanBufferBuilder( + bb, + vtableSpace: new int[ExampleMonsterVtableSize], + vtableOffsetSpace: new int[16]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + Span inventoryData = stackalloc byte[] { 1, 2, 3, 4, 5 }; + var inv = StackExampleMonster.CreateInventoryVector(ref fbb, inventoryData); + + StackExampleMonster.StartTest4Vector(ref fbb, 2); + MyGame.Example.StackBuffer.Test.CreateTest(ref fbb, (short)100, (sbyte)50); + MyGame.Example.StackBuffer.Test.CreateTest(ref fbb, (short)200, (sbyte)60); + var test4 = fbb.EndVector(); + + var name = fbb.CreateString("UnPackMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, name); + StackExampleMonster.AddHp(ref fbb, 300); + StackExampleMonster.AddMana(ref fbb, 200); + StackExampleMonster.AddInventory(ref fbb, inv); + StackExampleMonster.AddPos(ref fbb, MyGame.Example.StackBuffer.Vec3.CreateVec3(ref fbb, + 1.0f, 2.0f, 3.0f, 4.0, ExampleColor.Green, (short)10, (sbyte)20)); + StackExampleMonster.AddTest4(ref fbb, test4); + StackExampleMonster.AddColor(ref fbb, ExampleColor.Red); + var mon = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, mon); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.AreEqual("UnPackMonster", monsterT.Name); + Assert.AreEqual(300, monsterT.Hp); + Assert.AreEqual(200, monsterT.Mana); + Assert.AreEqual(ExampleColor.Red, monsterT.Color); + + Assert.AreEqual(5, monsterT.Inventory.Count); + for (int i = 0; i < 5; i++) + { + Assert.AreEqual(i + 1, monsterT.Inventory[i]); + } + + Assert.IsNotNull(monsterT.Pos); + Assert.AreEqual(1.0f, monsterT.Pos.X, 6); + Assert.AreEqual(2.0f, monsterT.Pos.Y, 6); + Assert.AreEqual(3.0f, monsterT.Pos.Z, 6); + Assert.AreEqual(4.0, monsterT.Pos.Test1, 6); + Assert.AreEqual(ExampleColor.Green, monsterT.Pos.Test2); + Assert.AreEqual((short)10, monsterT.Pos.Test3.A); + Assert.AreEqual((sbyte)20, monsterT.Pos.Test3.B); + + Assert.AreEqual(2, monsterT.Test4.Count); + Assert.AreEqual((short)200, monsterT.Test4[0].A); + Assert.AreEqual((sbyte)60, monsterT.Test4[0].B); + Assert.AreEqual((short)100, monsterT.Test4[1].A); + Assert.AreEqual((sbyte)50, monsterT.Test4[1].B); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_Pack() + { + var monsterT = new MyGame.Example.MonsterT + { + Name = "PackedMonster", + Hp = 300, + Mana = 200, + Color = ExampleColor.Red, + Inventory = new List { 1, 2, 3, 4, 5 }, + Pos = new MyGame.Example.Vec3T + { + X = 1.0f, + Y = 2.0f, + Z = 3.0f, + Test1 = 4.0, + Test2 = ExampleColor.Green, + Test3 = new MyGame.Example.TestT { A = 10, B = 20 } + } + }; + + var fbb = CreateStackBufferBuilderForExampleMonster(); + var monsterOffset = StackExampleMonster.Pack(ref fbb, monsterT); + StackExampleMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + + Assert.AreEqual("PackedMonster", monster.Name); + Assert.AreEqual(300, monster.Hp); + Assert.AreEqual(200, monster.Mana); + Assert.AreEqual(ExampleColor.Red, monster.Color); + + Assert.IsTrue(monster.Inventory.HasValue); + Assert.AreEqual(5, monster.Inventory.Value.Length); + + Assert.IsTrue(monster.Pos.HasValue); + var pos = monster.Pos.Value; + Assert.AreEqual(1.0f, pos.X, 6); + Assert.AreEqual(2.0f, pos.Y, 6); + Assert.AreEqual(3.0f, pos.Z, 6); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack_BasicTable() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + var nameOffset = fbb.CreateString("UnPackMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, nameOffset); + StackExampleMonster.AddHp(ref fbb, 300); + StackExampleMonster.AddMana(ref fbb, 200); + StackExampleMonster.AddColor(ref fbb, ExampleColor.Red); + var monsterOffset = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.AreEqual("UnPackMonster", monsterT.Name); + Assert.AreEqual(300, monsterT.Hp); + Assert.AreEqual(200, monsterT.Mana); + Assert.AreEqual(ExampleColor.Red, monsterT.Color); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack_WithVectorOfScalars() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + Span inventoryData = stackalloc byte[] { 10, 20, 30, 40, 50 }; + var inv = StackExampleMonster.CreateInventoryVectorBlock(ref fbb, inventoryData); + + Span longsData = stackalloc long[] { 100, 200, 300 }; + var longs = StackExampleMonster.CreateVectorOfLongsVector(ref fbb, longsData); + + var nameOffset = fbb.CreateString("VectorMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, nameOffset); + StackExampleMonster.AddInventory(ref fbb, inv); + StackExampleMonster.AddVectorOfLongs(ref fbb, longs); + var monsterOffset = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.AreEqual(5, monsterT.Inventory.Count); + Assert.AreEqual(10, monsterT.Inventory[0]); + Assert.AreEqual(50, monsterT.Inventory[4]); + + Assert.AreEqual(3, monsterT.VectorOfLongs.Count); + Assert.AreEqual(100L, monsterT.VectorOfLongs[0]); + Assert.AreEqual(300L, monsterT.VectorOfLongs[2]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack_WithVectorOfStrings() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + var str1 = fbb.CreateString("alpha"); + var str2 = fbb.CreateString("beta"); + var str3 = fbb.CreateString("gamma"); + Span strings = stackalloc StringOffset[] { str1, str2, str3 }; + var stringsOffset = StackExampleMonster.CreateTestarrayofstringVectorBlock(ref fbb, strings); + + var nameOffset = fbb.CreateString("StringMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, nameOffset); + StackExampleMonster.AddTestarrayofstring(ref fbb, stringsOffset); + var monsterOffset = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.AreEqual(3, monsterT.Testarrayofstring.Count); + Assert.AreEqual("alpha", monsterT.Testarrayofstring[0]); + Assert.AreEqual("beta", monsterT.Testarrayofstring[1]); + Assert.AreEqual("gamma", monsterT.Testarrayofstring[2]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack_WithVectorOfEnums() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + Span colors = stackalloc ExampleColor[] { ExampleColor.Red, ExampleColor.Green, ExampleColor.Blue }; + var colorsOffset = StackExampleMonster.CreateVectorOfEnumsVector(ref fbb, colors); + + var nameOffset = fbb.CreateString("EnumMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, nameOffset); + StackExampleMonster.AddVectorOfEnums(ref fbb, colorsOffset); + var monsterOffset = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.AreEqual(3, monsterT.VectorOfEnums.Count); + Assert.AreEqual(ExampleColor.Red, monsterT.VectorOfEnums[0]); + Assert.AreEqual(ExampleColor.Green, monsterT.VectorOfEnums[1]); + Assert.AreEqual(ExampleColor.Blue, monsterT.VectorOfEnums[2]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack_WithStruct() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + var nameOffset = fbb.CreateString("StructMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, nameOffset); + StackExampleMonster.AddPos(ref fbb, MyGame.Example.StackBuffer.Vec3.CreateVec3(ref fbb, 1.5f, 2.5f, 3.5f, 4.5, + ExampleColor.Green, (short)100, (sbyte)50)); + var monsterOffset = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.IsNotNull(monsterT.Pos); + Assert.AreEqual(1.5f, monsterT.Pos.X, 6); + Assert.AreEqual(2.5f, monsterT.Pos.Y, 6); + Assert.AreEqual(3.5f, monsterT.Pos.Z, 6); + Assert.AreEqual(4.5, monsterT.Pos.Test1, 6); + Assert.AreEqual(ExampleColor.Green, monsterT.Pos.Test2); + Assert.AreEqual((short)100, monsterT.Pos.Test3.A); + Assert.AreEqual((sbyte)50, monsterT.Pos.Test3.B); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack_WithVectorOfStructs() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + StackExampleMonster.StartTest4Vector(ref fbb, 3); + MyGame.Example.StackBuffer.Test.CreateTest(ref fbb, (short)100, (sbyte)10); + MyGame.Example.StackBuffer.Test.CreateTest(ref fbb, (short)200, (sbyte)20); + MyGame.Example.StackBuffer.Test.CreateTest(ref fbb, (short)300, (sbyte)30); + var test4 = fbb.EndVector(); + + var nameOffset = fbb.CreateString("StructVecMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, nameOffset); + StackExampleMonster.AddTest4(ref fbb, test4); + var monsterOffset = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.AreEqual(3, monsterT.Test4.Count); + Assert.AreEqual((short)300, monsterT.Test4[0].A); + Assert.AreEqual((sbyte)30, monsterT.Test4[0].B); + Assert.AreEqual((short)100, monsterT.Test4[2].A); + Assert.AreEqual((sbyte)10, monsterT.Test4[2].B); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPackTo_ReusesExistingObject() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + var nameOffset = fbb.CreateString("ReusedMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, nameOffset); + StackExampleMonster.AddHp(ref fbb, 500); + StackExampleMonster.AddMana(ref fbb, 250); + var monsterOffset = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + + var existingMonsterT = new MyGame.Example.MonsterT(); + existingMonsterT.Name = "OldName"; + existingMonsterT.Hp = 50; + + monster.UnPackTo(existingMonsterT); + + Assert.AreEqual("ReusedMonster", existingMonsterT.Name); + Assert.AreEqual(500, existingMonsterT.Hp); + Assert.AreEqual(250, existingMonsterT.Mana); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPackTo_WithVectors_ReusesLists() + { + var fbb1 = CreateStackBufferBuilderForExampleMonster(); + Span inv1 = stackalloc byte[] { 1, 2, 3, 4, 5 }; + var invOffset1 = StackExampleMonster.CreateInventoryVectorBlock(ref fbb1, inv1); + var name1 = fbb1.CreateString("Monster1"); + StackExampleMonster.StartMonster(ref fbb1); + StackExampleMonster.AddName(ref fbb1, name1); + StackExampleMonster.AddInventory(ref fbb1, invOffset1); + var monsterOffset1 = StackExampleMonster.EndMonster(ref fbb1); + StackExampleMonster.FinishMonsterBuffer(ref fbb1, monsterOffset1); + + var bb1 = fbb1.DataBuffer; + var monster1 = StackExampleMonster.GetRootAsMonster(bb1); + var monsterT = monster1.UnPack(); + var originalList = monsterT.Inventory; + + var fbb2 = CreateStackBufferBuilderForExampleMonster(); + Span inv2 = stackalloc byte[] { 10, 20, 30 }; + var invOffset2 = StackExampleMonster.CreateInventoryVectorBlock(ref fbb2, inv2); + var name2 = fbb2.CreateString("Monster2"); + StackExampleMonster.StartMonster(ref fbb2); + StackExampleMonster.AddName(ref fbb2, name2); + StackExampleMonster.AddInventory(ref fbb2, invOffset2); + var monsterOffset2 = StackExampleMonster.EndMonster(ref fbb2); + StackExampleMonster.FinishMonsterBuffer(ref fbb2, monsterOffset2); + + var bb2 = fbb2.DataBuffer; + var monster2 = StackExampleMonster.GetRootAsMonster(bb2); + monster2.UnPackTo(monsterT); + + Assert.IsTrue(ReferenceEquals(originalList, monsterT.Inventory)); + Assert.AreEqual(3, monsterT.Inventory.Count); + Assert.AreEqual(10, monsterT.Inventory[0]); + Assert.AreEqual(30, monsterT.Inventory[2]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack_WithUnion() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + var nestedName = fbb.CreateString("NestedMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, nestedName); + StackExampleMonster.AddHp(ref fbb, 999); + var nestedMonster = StackExampleMonster.EndMonster(ref fbb); + + var mainName = fbb.CreateString("UnionMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, mainName); + StackExampleMonster.AddTestType(ref fbb, ExampleAny.Monster); + StackExampleMonster.AddTest(ref fbb, nestedMonster.Value); + var mainMonster = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, mainMonster); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.IsNotNull(monsterT.Test); + Assert.AreEqual(ExampleAny.Monster, monsterT.Test.Type); + var nestedT = monsterT.Test.Value as MyGame.Example.MonsterT; + Assert.IsNotNull(nestedT); + Assert.AreEqual("NestedMonster", nestedT.Name); + Assert.AreEqual(999, nestedT.Hp); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack_WithVectorOfTables() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + var name1 = fbb.CreateString("Child1"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, name1); + StackExampleMonster.AddHp(ref fbb, 100); + var child1 = StackExampleMonster.EndMonster(ref fbb); + + var name2 = fbb.CreateString("Child2"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, name2); + StackExampleMonster.AddHp(ref fbb, 200); + var child2 = StackExampleMonster.EndMonster(ref fbb); + + Span> children = stackalloc Offset[] { child1, child2 }; + var childrenOffset = StackExampleMonster.CreateTestarrayoftablesVectorBlock(ref fbb, children); + + var parentName = fbb.CreateString("Parent"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, parentName); + StackExampleMonster.AddTestarrayoftables(ref fbb, childrenOffset); + var parentMonster = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, parentMonster); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.AreEqual(2, monsterT.Testarrayoftables.Count); + Assert.AreEqual("Child1", monsterT.Testarrayoftables[0].Name); + Assert.AreEqual(100, monsterT.Testarrayoftables[0].Hp); + Assert.AreEqual("Child2", monsterT.Testarrayoftables[1].Name); + Assert.AreEqual(200, monsterT.Testarrayoftables[1].Hp); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_DefaultValuesInConstructor() + { + var monsterT = new MyGame.Example.MonsterT(); + + Assert.IsNull(monsterT.Name); + Assert.AreEqual(150, monsterT.Mana); + Assert.AreEqual(100, monsterT.Hp); + Assert.AreEqual(ExampleColor.Blue, monsterT.Color); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_DefaultValuesPreservedAfterRoundTrip() + { + var monsterT = new MyGame.Example.MonsterT + { + Name = "DefaultMonster" + }; + + var fbb = CreateStackBufferBuilderForExampleMonster(); + var offset = StackExampleMonster.Pack(ref fbb, monsterT); + StackExampleMonster.FinishMonsterBuffer(ref fbb, offset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var unpacked = monster.UnPack(); + + Assert.AreEqual("DefaultMonster", unpacked.Name); + Assert.AreEqual(150, unpacked.Mana); + Assert.AreEqual(100, unpacked.Hp); + Assert.AreEqual(ExampleColor.Blue, unpacked.Color); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_RoundTrip_ComplexObject() + { + var originalMonster = new MyGame.Example.MonsterT + { + Name = "ComplexMonster", + Hp = 999, + Mana = 500, + Color = ExampleColor.Red, + Inventory = new List { 1, 2, 3, 4, 5 }, + Testarrayofstring = new List { "tag1", "tag2" }, + VectorOfLongs = new List { 100, 200, 300 }, + VectorOfEnums = new List { ExampleColor.Red, ExampleColor.Green }, + Pos = new MyGame.Example.Vec3T + { + X = 1.0f, + Y = 2.0f, + Z = 3.0f, + Test1 = 4.0, + Test2 = ExampleColor.Blue, + Test3 = new MyGame.Example.TestT { A = 10, B = 20 } + } + }; + + var fbb = CreateStackBufferBuilderForExampleMonster(); + var offset = StackExampleMonster.Pack(ref fbb, originalMonster); + StackExampleMonster.FinishMonsterBuffer(ref fbb, offset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var unpacked = monster.UnPack(); + + Assert.AreEqual(originalMonster.Name, unpacked.Name); + Assert.AreEqual(originalMonster.Hp, unpacked.Hp); + Assert.AreEqual(originalMonster.Mana, unpacked.Mana); + Assert.AreEqual(originalMonster.Color, unpacked.Color); + + Assert.AreEqual(originalMonster.Inventory.Count, unpacked.Inventory.Count); + for (int i = 0; i < originalMonster.Inventory.Count; i++) + { + Assert.AreEqual(originalMonster.Inventory[i], unpacked.Inventory[i]); + } + + Assert.AreEqual(originalMonster.Testarrayofstring.Count, unpacked.Testarrayofstring.Count); + for (int i = 0; i < originalMonster.Testarrayofstring.Count; i++) + { + Assert.AreEqual(originalMonster.Testarrayofstring[i], unpacked.Testarrayofstring[i]); + } + + Assert.AreEqual(originalMonster.VectorOfLongs.Count, unpacked.VectorOfLongs.Count); + for (int i = 0; i < originalMonster.VectorOfLongs.Count; i++) + { + Assert.AreEqual(originalMonster.VectorOfLongs[i], unpacked.VectorOfLongs[i]); + } + + Assert.AreEqual(originalMonster.VectorOfEnums.Count, unpacked.VectorOfEnums.Count); + for (int i = 0; i < originalMonster.VectorOfEnums.Count; i++) + { + Assert.AreEqual(originalMonster.VectorOfEnums[i], unpacked.VectorOfEnums[i]); + } + + Assert.IsNotNull(unpacked.Pos); + Assert.AreEqual(originalMonster.Pos.X, unpacked.Pos.X, 6); + Assert.AreEqual(originalMonster.Pos.Y, unpacked.Pos.Y, 6); + Assert.AreEqual(originalMonster.Pos.Z, unpacked.Pos.Z, 6); + Assert.AreEqual(originalMonster.Pos.Test1, unpacked.Pos.Test1, 6); + Assert.AreEqual(originalMonster.Pos.Test2, unpacked.Pos.Test2); + Assert.AreEqual(originalMonster.Pos.Test3.A, unpacked.Pos.Test3.A); + Assert.AreEqual(originalMonster.Pos.Test3.B, unpacked.Pos.Test3.B); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_RoundTrip_MultipleUnpackOperations() + { + var monster1 = new MyGame.Example.MonsterT + { + Name = "Monster1", + Hp = 100 + }; + + var fbb1 = CreateStackBufferBuilderForExampleMonster(); + var offset1 = StackExampleMonster.Pack(ref fbb1, monster1); + StackExampleMonster.FinishMonsterBuffer(ref fbb1, offset1); + + var bb1 = fbb1.DataBuffer; + var readMonster1 = StackExampleMonster.GetRootAsMonster(bb1); + var monster2 = readMonster1.UnPack(); + + monster2.Hp = 200; + + var fbb2 = CreateStackBufferBuilderForExampleMonster(); + var offset2 = StackExampleMonster.Pack(ref fbb2, monster2); + StackExampleMonster.FinishMonsterBuffer(ref fbb2, offset2); + + var bb2 = fbb2.DataBuffer; + var readMonster2 = StackExampleMonster.GetRootAsMonster(bb2); + var monster3 = readMonster2.UnPack(); + + Assert.AreEqual("Monster1", monster3.Name); + Assert.AreEqual(200, monster3.Hp); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack_WithEnemy() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + var enemyName = fbb.CreateString("Enemy"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, enemyName); + StackExampleMonster.AddHp(ref fbb, 50); + var enemy = StackExampleMonster.EndMonster(ref fbb); + + var mainName = fbb.CreateString("Hero"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, mainName); + StackExampleMonster.AddEnemy(ref fbb, enemy); + var main = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, main); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.IsNotNull(monsterT.Enemy); + Assert.AreEqual("Enemy", monsterT.Enemy.Name); + Assert.AreEqual(50, monsterT.Enemy.Hp); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_UnPack_NullVectors_ReturnsEmptyLists() + { + var fbb = CreateStackBufferBuilderForExampleMonster(); + + var nameOffset = fbb.CreateString("EmptyMonster"); + StackExampleMonster.StartMonster(ref fbb); + StackExampleMonster.AddName(ref fbb, nameOffset); + var monsterOffset = StackExampleMonster.EndMonster(ref fbb); + StackExampleMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var bb = fbb.DataBuffer; + var monster = StackExampleMonster.GetRootAsMonster(bb); + var monsterT = monster.UnPack(); + + Assert.IsNotNull(monsterT.Inventory); + Assert.AreEqual(0, monsterT.Inventory.Count); + + Assert.IsNotNull(monsterT.Testarrayofstring); + Assert.AreEqual(0, monsterT.Testarrayofstring.Count); + + Assert.IsNotNull(monsterT.VectorOfLongs); + Assert.AreEqual(0, monsterT.VectorOfLongs.Count); + } + + [FlatBuffersTestMethod] + public void StackBuffer_ObjectAPI_CrossVariant_SameResults() + { + var fbb = new FlatBufferBuilder(128); + + Span inventoryData = stackalloc byte[] { 1, 2, 3 }; + var inv = ExampleMonster.CreateInventoryVectorBlock(fbb, inventoryData); + + var nameOffset = fbb.CreateString("CrossVariant"); + ExampleMonster.StartMonster(fbb); + ExampleMonster.AddName(fbb, nameOffset); + ExampleMonster.AddInventory(fbb, inv); + ExampleMonster.AddHp(fbb, 123); + ExampleMonster.AddMana(fbb, 456); + ExampleMonster.AddColor(fbb, ExampleColor.Green); + var monsterOffset = ExampleMonster.EndMonster(fbb); + ExampleMonster.FinishMonsterBuffer(fbb, monsterOffset); + + var regularMonster = ExampleMonster.GetRootAsMonster(fbb.DataBuffer); + var regularUnpacked = regularMonster.UnPack(); + + var bb = Utils.ByteBufferUtil.ToSizedByteSpanBuffer(fbb.DataBuffer); + var stackMonster = StackExampleMonster.GetRootAsMonster(bb); + var stackUnpacked = stackMonster.UnPack(); + + Assert.AreEqual(regularUnpacked.Name, stackUnpacked.Name); + Assert.AreEqual(regularUnpacked.Hp, stackUnpacked.Hp); + Assert.AreEqual(regularUnpacked.Mana, stackUnpacked.Mana); + Assert.AreEqual(regularUnpacked.Color, stackUnpacked.Color); + Assert.AreEqual(regularUnpacked.Inventory.Count, stackUnpacked.Inventory.Count); + for (int i = 0; i < regularUnpacked.Inventory.Count; i++) + { + Assert.AreEqual(regularUnpacked.Inventory[i], stackUnpacked.Inventory[i]); + } + } + } +} diff --git a/net/FlatSpanBuffers.Tests/ObjectApiTests.cs b/net/FlatSpanBuffers.Tests/ObjectApiTests.cs new file mode 100644 index 00000000000..d8aace934d8 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/ObjectApiTests.cs @@ -0,0 +1,1040 @@ +/* + * Copyright 2026 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; +using System.Collections.Generic; +using ComprehensiveTest; + +namespace Google.FlatSpanBuffers.Tests +{ + [FlatBuffersTestClass] + public class ObjectApiTests + { + private static FlatBufferBuilder CreateBuilder(int initialSize = 256) + { + var buffer = new ByteBuffer(initialSize); + return new FlatBufferBuilder(buffer, new int[32], new int[32]); + } + + [FlatBuffersTestMethod] + public void UnPack_BasicTable_ReturnsCorrectValues() + { + var fbb = CreateBuilder(); + var nameOffset = fbb.CreateString("Excalibur"); + + Weapon.StartWeapon(fbb); + Weapon.AddName(fbb, nameOffset); + Weapon.AddDamage(fbb, 150); + Weapon.AddDurability(fbb, 95.5f); + Weapon.AddEnchanted(fbb, true); + Weapon.AddRarity(fbb, Color.Blue); + var weaponOffset = Weapon.EndWeapon(fbb); + fbb.Finish(weaponOffset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + var weaponT = weapon.UnPack(); + + Assert.AreEqual("Excalibur", weaponT.Name); + Assert.AreEqual(150, weaponT.Damage); + Assert.AreEqual(95.5f, weaponT.Durability, 6); + Assert.AreEqual(true, weaponT.Enchanted); + Assert.AreEqual(Color.Blue, weaponT.Rarity); + } + + [FlatBuffersTestMethod] + public void UnPack_WithVectorOfScalars_ReturnsCorrectValues() + { + var fbb = CreateBuilder(); + var nameOffset = fbb.CreateString("MultiHitSword"); + + Span damageValues = stackalloc int[] { 10, 20, 30, 40, 50 }; + var damageValuesOffset = Weapon.CreateDamageValuesVectorBlock(fbb, damageValues); + + Span modifiers = stackalloc float[] { 1.1f, 1.2f, 1.3f }; + var modifiersOffset = Weapon.CreateModifiersVectorBlock(fbb, modifiers); + + Weapon.StartWeapon(fbb); + Weapon.AddName(fbb, nameOffset); + Weapon.AddDamageValues(fbb, damageValuesOffset); + Weapon.AddModifiers(fbb, modifiersOffset); + var weaponOffset = Weapon.EndWeapon(fbb); + fbb.Finish(weaponOffset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + var weaponT = weapon.UnPack(); + + Assert.AreEqual(5, weaponT.DamageValues.Count); + Assert.AreEqual(10, weaponT.DamageValues[0]); + Assert.AreEqual(50, weaponT.DamageValues[4]); + + Assert.AreEqual(3, weaponT.Modifiers.Count); + Assert.AreEqual(1.1f, weaponT.Modifiers[0], 6); + Assert.AreEqual(1.3f, weaponT.Modifiers[2], 6); + } + + [FlatBuffersTestMethod] + public void UnPack_WithVectorOfStrings_ReturnsCorrectValues() + { + var fbb = CreateBuilder(); + var nameOffset = fbb.CreateString("TaggedWeapon"); + + var tag1 = fbb.CreateString("legendary"); + var tag2 = fbb.CreateString("fire"); + var tag3 = fbb.CreateString("ancient"); + Span tags = stackalloc StringOffset[] { tag1, tag2, tag3 }; + var tagsOffset = Weapon.CreateTagsVectorBlock(fbb, tags); + + Weapon.StartWeapon(fbb); + Weapon.AddName(fbb, nameOffset); + Weapon.AddTags(fbb, tagsOffset); + var weaponOffset = Weapon.EndWeapon(fbb); + fbb.Finish(weaponOffset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + var weaponT = weapon.UnPack(); + + Assert.AreEqual(3, weaponT.Tags.Count); + Assert.AreEqual("legendary", weaponT.Tags[0]); + Assert.AreEqual("fire", weaponT.Tags[1]); + Assert.AreEqual("ancient", weaponT.Tags[2]); + } + + [FlatBuffersTestMethod] + public void UnPack_WithVectorOfEnums_ReturnsCorrectValues() + { + var fbb = CreateBuilder(); + var nameOffset = fbb.CreateString("ColorfulWeapon"); + + Span colors = stackalloc Color[] { Color.Red, Color.Green, Color.Blue }; + var colorsOffset = Weapon.CreateValidColorsVectorBlock(fbb, colors); + + Weapon.StartWeapon(fbb); + Weapon.AddName(fbb, nameOffset); + Weapon.AddValidColors(fbb, colorsOffset); + var weaponOffset = Weapon.EndWeapon(fbb); + fbb.Finish(weaponOffset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + var weaponT = weapon.UnPack(); + + Assert.AreEqual(3, weaponT.ValidColors.Count); + Assert.AreEqual(Color.Red, weaponT.ValidColors[0]); + Assert.AreEqual(Color.Green, weaponT.ValidColors[1]); + Assert.AreEqual(Color.Blue, weaponT.ValidColors[2]); + } + + [FlatBuffersTestMethod] + public void UnPackTo_ReusesExistingObject() + { + var fbb = CreateBuilder(); + var nameOffset = fbb.CreateString("ReusedWeapon"); + + Weapon.StartWeapon(fbb); + Weapon.AddName(fbb, nameOffset); + Weapon.AddDamage(fbb, 200); + var weaponOffset = Weapon.EndWeapon(fbb); + fbb.Finish(weaponOffset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + + var existingWeaponT = new WeaponT(); + existingWeaponT.Name = "OldName"; + existingWeaponT.Damage = 50; + + weapon.UnPackTo(existingWeaponT); + + Assert.AreEqual("ReusedWeapon", existingWeaponT.Name); + Assert.AreEqual(200, existingWeaponT.Damage); + } + + [FlatBuffersTestMethod] + public void UnPackTo_WithVectors_ReusesLists() + { + var fbb1 = CreateBuilder(); + var name1 = fbb1.CreateString("Weapon1"); + Span damages1 = stackalloc int[] { 1, 2, 3, 4, 5 }; + var damagesOffset1 = Weapon.CreateDamageValuesVectorBlock(fbb1, damages1); + + Weapon.StartWeapon(fbb1); + Weapon.AddName(fbb1, name1); + Weapon.AddDamageValues(fbb1, damagesOffset1); + var weaponOffset1 = Weapon.EndWeapon(fbb1); + fbb1.Finish(weaponOffset1.Value); + + var weapon1 = Weapon.GetRootAsWeapon(fbb1.DataBuffer); + var weaponT = weapon1.UnPack(); + + var originalList = weaponT.DamageValues; + + var fbb2 = CreateBuilder(); + var name2 = fbb2.CreateString("Weapon2"); + Span damages2 = stackalloc int[] { 10, 20, 30 }; + var damagesOffset2 = Weapon.CreateDamageValuesVectorBlock(fbb2, damages2); + + Weapon.StartWeapon(fbb2); + Weapon.AddName(fbb2, name2); + Weapon.AddDamageValues(fbb2, damagesOffset2); + var weaponOffset2 = Weapon.EndWeapon(fbb2); + fbb2.Finish(weaponOffset2.Value); + + var weapon2 = Weapon.GetRootAsWeapon(fbb2.DataBuffer); + + weapon2.UnPackTo(weaponT); + + Assert.IsTrue(ReferenceEquals(originalList, weaponT.DamageValues)); + Assert.AreEqual(3, weaponT.DamageValues.Count); + Assert.AreEqual(10, weaponT.DamageValues[0]); + Assert.AreEqual(30, weaponT.DamageValues[2]); + } + + [FlatBuffersTestMethod] + public void Pack_BasicTable_CreatesCorrectBuffer() + { + var weaponT = new WeaponT + { + Name = "PackedSword", + Damage = 175, + Durability = 88.5f, + Enchanted = true, + Rarity = Color.Green, + Transform = null, + FixedStats = null, + PositionHistory = null + }; + + var fbb = CreateBuilder(); + var offset = Weapon.Pack(fbb, weaponT); + fbb.Finish(offset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + + // Assert + Assert.AreEqual("PackedSword", weapon.Name); + Assert.AreEqual(175, weapon.Damage); + Assert.AreEqual(88.5f, weapon.Durability, 6); + Assert.AreEqual(true, weapon.Enchanted); + Assert.AreEqual(Color.Green, weapon.Rarity); + } + + [FlatBuffersTestMethod] + public void Pack_WithVectorOfScalars_CreatesCorrectBuffer() + { + var weaponT = new WeaponT + { + Name = "VectorWeapon", + DamageValues = new List { 5, 10, 15, 20 }, + Modifiers = new List { 0.5f, 1.0f, 1.5f }, + Transform = null, + FixedStats = null, + PositionHistory = null + }; + + var fbb = CreateBuilder(); + var offset = Weapon.Pack(fbb, weaponT); + fbb.Finish(offset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + + Assert.AreEqual(4, weapon.DamageValues.Value.Length); + Assert.AreEqual(5, weapon.DamageValues.Value[0]); + Assert.AreEqual(20, weapon.DamageValues.Value[3]); + + Assert.AreEqual(3, weapon.Modifiers.Value.Length); + Assert.AreEqual(0.5f, weapon.Modifiers.Value[0], 6); + Assert.AreEqual(1.5f, weapon.Modifiers.Value[2], 6); + } + + [FlatBuffersTestMethod] + public void Pack_WithVectorOfStrings_CreatesCorrectBuffer() + { + var weaponT = new WeaponT + { + Name = "TaggedPacked", + Tags = new List { "epic", "frost", "blessed" }, + Transform = null, + FixedStats = null, + PositionHistory = null + }; + + var fbb = CreateBuilder(); + var offset = Weapon.Pack(fbb, weaponT); + fbb.Finish(offset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + + var tags = weapon.Tags; + Assert.IsTrue(tags.HasValue); + var tagsVec = tags.Value; + Assert.AreEqual(3, tagsVec.Length); + Assert.AreEqual("epic", tagsVec[0]); + Assert.AreEqual("frost", tagsVec[1]); + Assert.AreEqual("blessed", tagsVec[2]); + } + + [FlatBuffersTestMethod] + public void Pack_WithVectorOfEnums_CreatesCorrectBuffer() + { + var weaponT = new WeaponT + { + Name = "EnumWeapon", + ValidColors = new List { Color.Blue, Color.Red }, + Transform = null, + FixedStats = null, + PositionHistory = null + }; + + var fbb = CreateBuilder(); + var offset = Weapon.Pack(fbb, weaponT); + fbb.Finish(offset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + + Assert.AreEqual(2, weapon.ValidColors.Value.Length); + Assert.AreEqual(Color.Blue, weapon.ValidColors.Value[0]); + Assert.AreEqual(Color.Red, weapon.ValidColors.Value[1]); + } + + [FlatBuffersTestMethod] + public void Pack_NullObject_ReturnsDefaultOffset() + { + var fbb = CreateBuilder(); + var offset = Weapon.Pack(fbb, null); + + Assert.AreEqual(0, offset.Value); + } + + [FlatBuffersTestMethod] + public void ObjectApi_DefaultValuesInConstructor() + { + var weaponT = new WeaponT(); + + Assert.IsNull(weaponT.Name); + Assert.AreEqual(10, weaponT.Damage); // default = 10 + Assert.AreEqual(100.0f, weaponT.Durability, 6); // default = 100.0 + Assert.AreEqual(false, weaponT.Enchanted); // default = false + Assert.AreEqual(Color.Red, weaponT.Rarity); // default = Red + } + + [FlatBuffersTestMethod] + public void ObjectApi_DefaultValuesPreservedAfterRoundTrip() + { + var weaponT = new WeaponT + { + Name = "DefaultsWeapon", + // Leave Damage, Durability, Enchanted, Rarity at defaults + Transform = null, + FixedStats = null, + PositionHistory = null + }; + + var fbb = CreateBuilder(); + var offset = Weapon.Pack(fbb, weaponT); + fbb.Finish(offset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + var unpacked = weapon.UnPack(); + + Assert.AreEqual("DefaultsWeapon", unpacked.Name); + Assert.AreEqual(10, unpacked.Damage); + Assert.AreEqual(100.0f, unpacked.Durability, 6); + Assert.AreEqual(false, unpacked.Enchanted); + Assert.AreEqual(Color.Red, unpacked.Rarity); + } + + [FlatBuffersTestMethod] + public void RoundTrip_ComplexObject_PreservesAllData() + { + var originalWeapon = new WeaponT + { + Name = "ComplexWeapon", + Damage = 999, + Durability = 50.25f, + Enchanted = true, + Rarity = Color.Blue, + Tags = new List { "tag1", "tag2", "tag3" }, + DamageValues = new List { 100, 200, 300 }, + Modifiers = new List { 1.5f, 2.0f, 2.5f }, + ValidColors = new List { Color.Red, Color.Green, Color.Blue }, + Transform = null, + FixedStats = null, + PositionHistory = null + }; + + var fbb = CreateBuilder(1024); + var offset = Weapon.Pack(fbb, originalWeapon); + fbb.Finish(offset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + var unpacked = weapon.UnPack(); + + Assert.AreEqual(originalWeapon.Name, unpacked.Name); + Assert.AreEqual(originalWeapon.Damage, unpacked.Damage); + Assert.AreEqual(originalWeapon.Durability, unpacked.Durability, 6); + Assert.AreEqual(originalWeapon.Enchanted, unpacked.Enchanted); + Assert.AreEqual(originalWeapon.Rarity, unpacked.Rarity); + + Assert.AreEqual(originalWeapon.Tags.Count, unpacked.Tags.Count); + for (int i = 0; i < originalWeapon.Tags.Count; i++) + { + Assert.AreEqual(originalWeapon.Tags[i], unpacked.Tags[i]); + } + + Assert.AreEqual(originalWeapon.DamageValues.Count, unpacked.DamageValues.Count); + for (int i = 0; i < originalWeapon.DamageValues.Count; i++) + { + Assert.AreEqual(originalWeapon.DamageValues[i], unpacked.DamageValues[i]); + } + + Assert.AreEqual(originalWeapon.Modifiers.Count, unpacked.Modifiers.Count); + for (int i = 0; i < originalWeapon.Modifiers.Count; i++) + { + Assert.AreEqual(originalWeapon.Modifiers[i], unpacked.Modifiers[i], 6); + } + + Assert.AreEqual(originalWeapon.ValidColors.Count, unpacked.ValidColors.Count); + for (int i = 0; i < originalWeapon.ValidColors.Count; i++) + { + Assert.AreEqual(originalWeapon.ValidColors[i], unpacked.ValidColors[i]); + } + } + + [FlatBuffersTestMethod] + public void RoundTrip_MultiplePackUnpack_DataIntegrity() + { + var weapon1 = new WeaponT + { + Name = "Weapon1", + Damage = 100, + Transform = null, + FixedStats = null, + PositionHistory = null + }; + + var fbb1 = CreateBuilder(); + var offset1 = Weapon.Pack(fbb1, weapon1); + fbb1.Finish(offset1.Value); + + var readWeapon1 = Weapon.GetRootAsWeapon(fbb1.DataBuffer); + var weapon2 = readWeapon1.UnPack(); + + weapon2.Damage = 200; + weapon2.Transform = null; + weapon2.FixedStats = null; + weapon2.PositionHistory = null; + + var fbb2 = CreateBuilder(); + var offset2 = Weapon.Pack(fbb2, weapon2); + fbb2.Finish(offset2.Value); + + var readWeapon2 = Weapon.GetRootAsWeapon(fbb2.DataBuffer); + var weapon3 = readWeapon2.UnPack(); + + Assert.AreEqual("Weapon1", weapon3.Name); + Assert.AreEqual(200, weapon3.Damage); + } + + [FlatBuffersTestMethod] + public void Player_Pack_WithDefaultValues() + { + var playerT = new PlayerT + { + Id = 1, + Name = "TestPlayer" + // Leave other fields at defaults + }; + + var fbb = CreateBuilder(512); + var offset = Player.Pack(fbb, playerT); + fbb.Finish(offset.Value); + + var player = Player.GetRootAsPlayer(fbb.DataBuffer); + + Assert.AreEqual(1, player.Id); + Assert.AreEqual("TestPlayer", player.Name); + Assert.AreEqual(1, player.Level); // default = 1 + Assert.AreEqual(0L, player.Experience); // default = 0 + Assert.AreEqual(100.0f, player.Health, 6); // default = 100.0 + Assert.AreEqual(50.0f, player.Mana, 6); // default = 50.0 + Assert.AreEqual(Status.Pending, player.Status); // default = Pending + } + + [FlatBuffersTestMethod] + public void Player_UnPack_PreservesDefaultValues() + { + var playerT = new PlayerT(); + + Assert.AreEqual(0, playerT.Id); + Assert.IsNull(playerT.Name); + Assert.AreEqual(1, playerT.Level); // default = 1 + Assert.AreEqual(0L, playerT.Experience); + Assert.AreEqual(100.0f, playerT.Health, 6); // default = 100.0 + Assert.AreEqual(50.0f, playerT.Mana, 6); // default = 50.0 + Assert.AreEqual(Status.Pending, playerT.Status); // default = Pending + } + + [FlatBuffersTestMethod] + public void Player_RoundTrip_WithVectorsAndStats() + { + var playerT = new PlayerT + { + Id = 42, + Name = "HeroPlayer", + Level = 50, + Experience = 1000000L, + Health = 500.0f, + Mana = 300.0f, + Skills = new List { "Fireball", "Shield", "Heal" }, + Stats = new List { 100, 80, 60, 40, 20 }, + Status = Status.Active + }; + + var fbb = CreateBuilder(1024); + var offset = Player.Pack(fbb, playerT); + fbb.Finish(offset.Value); + + var player = Player.GetRootAsPlayer(fbb.DataBuffer); + var unpacked = player.UnPack(); + + Assert.AreEqual(playerT.Id, unpacked.Id); + Assert.AreEqual(playerT.Name, unpacked.Name); + Assert.AreEqual(playerT.Level, unpacked.Level); + Assert.AreEqual(playerT.Experience, unpacked.Experience); + Assert.AreEqual(playerT.Health, unpacked.Health, 6); + Assert.AreEqual(playerT.Mana, unpacked.Mana, 6); + Assert.AreEqual(playerT.Status, unpacked.Status); + + Assert.AreEqual(3, unpacked.Skills.Count); + Assert.AreEqual("Fireball", unpacked.Skills[0]); + Assert.AreEqual("Shield", unpacked.Skills[1]); + Assert.AreEqual("Heal", unpacked.Skills[2]); + + Assert.AreEqual(5, unpacked.Stats.Count); + Assert.AreEqual(100, unpacked.Stats[0]); + Assert.AreEqual(20, unpacked.Stats[4]); + } + + [FlatBuffersTestMethod] + public void Player_WithStruct_SpawnPoint() + { + var playerT = new PlayerT + { + Id = 1, + Name = "SpawnPlayer", + SpawnPoint = new Vec3T + { + X = 10.0f, + Y = 20.0f, + Z = 30.0f + } + }; + + var fbb = CreateBuilder(512); + var offset = Player.Pack(fbb, playerT); + fbb.Finish(offset.Value); + + var player = Player.GetRootAsPlayer(fbb.DataBuffer); + var unpacked = player.UnPack(); + + Assert.IsNotNull(unpacked.SpawnPoint); + Assert.AreEqual(10.0f, unpacked.SpawnPoint.X, 6); + Assert.AreEqual(20.0f, unpacked.SpawnPoint.Y, 6); + Assert.AreEqual(30.0f, unpacked.SpawnPoint.Z, 6); + } + + [FlatBuffersTestMethod] + public void Player_WithUnion_EquippedWeapon() + { + var weaponT = new WeaponT + { + Name = "HeroSword", + Damage = 500, + Transform = null, + FixedStats = null, + PositionHistory = null + }; + + var playerT = new PlayerT + { + Id = 1, + Name = "UnionPlayer", + EquippedType = new EquipmentUnion + { + Type = Equipment.Weapon, + Value = weaponT + } + }; + + var fbb = CreateBuilder(1024); + var offset = Player.Pack(fbb, playerT); + fbb.Finish(offset.Value); + + var player = Player.GetRootAsPlayer(fbb.DataBuffer); + var unpacked = player.UnPack(); + + Assert.IsNotNull(unpacked.EquippedType); + Assert.AreEqual(Equipment.Weapon, unpacked.EquippedType.Type); + var equippedWeapon = unpacked.EquippedType.Value as WeaponT; + Assert.IsNotNull(equippedWeapon); + Assert.AreEqual("HeroSword", equippedWeapon.Name); + Assert.AreEqual(500, equippedWeapon.Damage); + } + + [FlatBuffersTestMethod] + public void Player_WithVectorOfUnions_Inventory() + { + var sword = new WeaponT { Name = "Sword", Damage = 100, Transform = null, FixedStats = null, PositionHistory = null }; + var shield = new ArmorT { Name = "Shield", Defense = 50, Transform = null }; + var bow = new WeaponT { Name = "Bow", Damage = 75, Transform = null, FixedStats = null, PositionHistory = null }; + + var playerT = new PlayerT + { + Id = 1, + Name = "InventoryPlayer", + Inventory = new List + { + new EquipmentUnion { Type = Equipment.Weapon, Value = sword }, + new EquipmentUnion { Type = Equipment.Armor, Value = shield }, + new EquipmentUnion { Type = Equipment.Weapon, Value = bow } + } + }; + + var fbb = CreateBuilder(2048); + var offset = Player.Pack(fbb, playerT); + fbb.Finish(offset.Value); + + var player = Player.GetRootAsPlayer(fbb.DataBuffer); + var unpacked = player.UnPack(); + + Assert.AreEqual(3, unpacked.Inventory.Count); + + Assert.AreEqual(Equipment.Weapon, unpacked.Inventory[0].Type); + var unpackedSword = unpacked.Inventory[0].Value as WeaponT; + Assert.IsNotNull(unpackedSword); + Assert.AreEqual("Sword", unpackedSword.Name); + Assert.AreEqual(100, unpackedSword.Damage); + + Assert.AreEqual(Equipment.Armor, unpacked.Inventory[1].Type); + var unpackedShield = unpacked.Inventory[1].Value as ArmorT; + Assert.IsNotNull(unpackedShield); + Assert.AreEqual("Shield", unpackedShield.Name); + Assert.AreEqual(50, unpackedShield.Defense); + + Assert.AreEqual(Equipment.Weapon, unpacked.Inventory[2].Type); + var unpackedBow = unpacked.Inventory[2].Value as WeaponT; + Assert.IsNotNull(unpackedBow); + Assert.AreEqual("Bow", unpackedBow.Name); + Assert.AreEqual(75, unpackedBow.Damage); + } + + [FlatBuffersTestMethod] + public void Pack_NullVectors_HandledCorrectly() + { + var weaponT = new WeaponT + { + Name = "NullVectorWeapon", + Tags = null, + DamageValues = null, + Modifiers = null, + Transform = null, + FixedStats = null, + PositionHistory = null + }; + + var fbb = CreateBuilder(); + var offset = Weapon.Pack(fbb, weaponT); + fbb.Finish(offset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + + Assert.IsFalse(weapon.Tags.HasValue); + Assert.IsFalse(weapon.DamageValues.HasValue); + Assert.IsFalse(weapon.Modifiers.HasValue); + } + + [FlatBuffersTestMethod] + public void Pack_EmptyVectors_HandledCorrectly() + { + var weaponT = new WeaponT + { + Name = "EmptyVectorWeapon", + Tags = new List(), + DamageValues = new List(), + Modifiers = new List(), + Transform = null, + FixedStats = null, + PositionHistory = null + }; + + var fbb = CreateBuilder(); + var offset = Weapon.Pack(fbb, weaponT); + fbb.Finish(offset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + + var tags = weapon.Tags; + var tagsLen = tags.HasValue ? tags.Value.Length : 0; + Assert.AreEqual(0, tagsLen); + var damageValsLen = weapon.DamageValues.HasValue ? weapon.DamageValues.Value.Length : 0; + Assert.AreEqual(0, damageValsLen); + var modifiersLen = weapon.Modifiers.HasValue ? weapon.Modifiers.Value.Length : 0; + Assert.AreEqual(0, modifiersLen); + } + + [FlatBuffersTestMethod] + public void UnPack_MissingVectors_ReturnsEmptyLists() + { + var fbb = CreateBuilder(); + var nameOffset = fbb.CreateString("MinimalWeapon"); + + Weapon.StartWeapon(fbb); + Weapon.AddName(fbb, nameOffset); + var weaponOffset = Weapon.EndWeapon(fbb); + fbb.Finish(weaponOffset.Value); + + var weapon = Weapon.GetRootAsWeapon(fbb.DataBuffer); + var weaponT = weapon.UnPack(); + + Assert.IsNotNull(weaponT.Tags); + Assert.AreEqual(0, weaponT.Tags.Count); + Assert.IsNotNull(weaponT.DamageValues); + Assert.AreEqual(0, weaponT.DamageValues.Count); + Assert.IsNotNull(weaponT.Modifiers); + Assert.AreEqual(0, weaponT.Modifiers.Count); + } + + [FlatBuffersTestMethod] + public void Armor_Pack_And_UnPack() + { + var armorT = new ArmorT + { + Name = "DragonScaleArmor", + Defense = 150, + Weight = 25.5f + }; + + var fbb = CreateBuilder(); + var offset = Armor.Pack(fbb, armorT); + fbb.Finish(offset.Value); + + var armor = Armor.GetRootAsArmor(fbb.DataBuffer); + var unpacked = armor.UnPack(); + + Assert.AreEqual("DragonScaleArmor", unpacked.Name); + Assert.AreEqual(150, unpacked.Defense); + Assert.AreEqual(25.5f, unpacked.Weight, 6); + } + + [FlatBuffersTestMethod] + public void Armor_DefaultValues() + { + var armorT = new ArmorT(); + + Assert.IsNull(armorT.Name); + Assert.AreEqual(5, armorT.Defense); // default = 5 + Assert.AreEqual(1.0f, armorT.Weight, 6); // default = 1.0 + } + + [FlatBuffersTestMethod] + public void Armor_WithTransform() + { + var armorT = new ArmorT + { + Name = "TransformArmor", + Defense = 100, + Transform = new TransformT + { + Position = new Vec3T { X = 1.0f, Y = 2.0f, Z = 3.0f }, + Scale = new Vec3T { X = 1.0f, Y = 1.0f, Z = 1.0f } + } + }; + + var fbb = CreateBuilder(512); + var offset = Armor.Pack(fbb, armorT); + fbb.Finish(offset.Value); + + var armor = Armor.GetRootAsArmor(fbb.DataBuffer); + var unpacked = armor.UnPack(); + + Assert.AreEqual("TransformArmor", unpacked.Name); + Assert.AreEqual(100, unpacked.Defense); + Assert.IsNotNull(unpacked.Transform); + Assert.AreEqual(1.0f, unpacked.Transform.Position.X, 6); + Assert.AreEqual(2.0f, unpacked.Transform.Position.Y, 6); + Assert.AreEqual(3.0f, unpacked.Transform.Position.Z, 6); + } + + [FlatBuffersTestMethod] + public void UnPackTo_VectorOfUnions_ReusesExistingObjects() + { + var sword1 = new WeaponT { Name = "Sword1", Damage = 100, Transform = null, FixedStats = null, PositionHistory = null }; + var shield1 = new ArmorT { Name = "Shield1", Defense = 50, Transform = null }; + + var playerT1 = new PlayerT + { + Id = 1, + Name = "Player1", + Inventory = new List + { + new EquipmentUnion { Type = Equipment.Weapon, Value = sword1 }, + new EquipmentUnion { Type = Equipment.Armor, Value = shield1 } + } + }; + + var fbb1 = CreateBuilder(2048); + var offset1 = Player.Pack(fbb1, playerT1); + fbb1.Finish(offset1.Value); + + var player1 = Player.GetRootAsPlayer(fbb1.DataBuffer); + var unpacked = player1.UnPack(); + + var originalInventory = unpacked.Inventory; + var originalUnion0 = unpacked.Inventory[0]; + var originalUnion1 = unpacked.Inventory[1]; + var originalSword = unpacked.Inventory[0].Value as WeaponT; + var originalShield = unpacked.Inventory[1].Value as ArmorT; + + var sword2 = new WeaponT { Name = "Sword2", Damage = 200, Transform = null, FixedStats = null, PositionHistory = null }; + var shield2 = new ArmorT { Name = "Shield2", Defense = 100, Transform = null }; + + var playerT2 = new PlayerT + { + Id = 2, + Name = "Player2", + Inventory = new List + { + new EquipmentUnion { Type = Equipment.Weapon, Value = sword2 }, + new EquipmentUnion { Type = Equipment.Armor, Value = shield2 } + } + }; + + var fbb2 = CreateBuilder(2048); + var offset2 = Player.Pack(fbb2, playerT2); + fbb2.Finish(offset2.Value); + + var player2 = Player.GetRootAsPlayer(fbb2.DataBuffer); + + player2.UnPackTo(unpacked); + + Assert.IsTrue(ReferenceEquals(originalInventory, unpacked.Inventory)); + Assert.AreEqual(2, unpacked.Inventory.Count); + + Assert.IsTrue(ReferenceEquals(originalUnion0, unpacked.Inventory[0])); + Assert.IsTrue(ReferenceEquals(originalUnion1, unpacked.Inventory[1])); + + Assert.IsTrue(ReferenceEquals(originalSword, unpacked.Inventory[0].Value)); + Assert.IsTrue(ReferenceEquals(originalShield, unpacked.Inventory[1].Value)); + + var updatedSword = unpacked.Inventory[0].Value as WeaponT; + Assert.AreEqual("Sword2", updatedSword.Name); + Assert.AreEqual(200, updatedSword.Damage); + + var updatedShield = unpacked.Inventory[1].Value as ArmorT; + Assert.AreEqual("Shield2", updatedShield.Name); + Assert.AreEqual(100, updatedShield.Defense); + } + + [FlatBuffersTestMethod] + public void UnPackTo_VectorOfUnions_TypeChange_CreatesNewObjects() + { + var sword = new WeaponT { Name = "Sword", Damage = 100, Transform = null, FixedStats = null, PositionHistory = null }; + var shield = new ArmorT { Name = "Shield", Defense = 50, Transform = null }; + + var playerT1 = new PlayerT + { + Id = 1, + Name = "Player1", + Inventory = new List + { + new EquipmentUnion { Type = Equipment.Weapon, Value = sword }, + new EquipmentUnion { Type = Equipment.Armor, Value = shield } + } + }; + + var fbb1 = CreateBuilder(2048); + var offset1 = Player.Pack(fbb1, playerT1); + fbb1.Finish(offset1.Value); + + var player1 = Player.GetRootAsPlayer(fbb1.DataBuffer); + var unpacked = player1.UnPack(); + + var originalSword = unpacked.Inventory[0].Value as WeaponT; + var originalShield = unpacked.Inventory[1].Value as ArmorT; + + var armor2 = new ArmorT { Name = "Armor2", Defense = 75, Transform = null }; + var weapon2 = new WeaponT { Name = "Weapon2", Damage = 150, Transform = null, FixedStats = null, PositionHistory = null }; + + var playerT2 = new PlayerT + { + Id = 2, + Name = "Player2", + Inventory = new List + { + new EquipmentUnion { Type = Equipment.Armor, Value = armor2 }, + new EquipmentUnion { Type = Equipment.Weapon, Value = weapon2 } + } + }; + + var fbb2 = CreateBuilder(2048); + var offset2 = Player.Pack(fbb2, playerT2); + fbb2.Finish(offset2.Value); + + var player2 = Player.GetRootAsPlayer(fbb2.DataBuffer); + + player2.UnPackTo(unpacked); + + Assert.AreEqual(Equipment.Armor, unpacked.Inventory[0].Type); + Assert.AreEqual(Equipment.Weapon, unpacked.Inventory[1].Type); + + Assert.IsFalse(ReferenceEquals(originalSword, unpacked.Inventory[0].Value)); + Assert.IsFalse(ReferenceEquals(originalShield, unpacked.Inventory[1].Value)); + + var newArmor = unpacked.Inventory[0].Value as ArmorT; + Assert.AreEqual("Armor2", newArmor.Name); + Assert.AreEqual(75, newArmor.Defense); + + var newWeapon = unpacked.Inventory[1].Value as WeaponT; + Assert.AreEqual("Weapon2", newWeapon.Name); + Assert.AreEqual(150, newWeapon.Damage); + } + + [FlatBuffersTestMethod] + public void UnPackTo_VectorOfUnions_Shrinking_TruncatesList() + { + var sword1 = new WeaponT { Name = "Sword1", Damage = 100, Transform = null, FixedStats = null, PositionHistory = null }; + var shield1 = new ArmorT { Name = "Shield1", Defense = 50, Transform = null }; + var bow1 = new WeaponT { Name = "Bow1", Damage = 75, Transform = null, FixedStats = null, PositionHistory = null }; + + var playerT1 = new PlayerT + { + Id = 1, + Name = "Player1", + Inventory = new List + { + new EquipmentUnion { Type = Equipment.Weapon, Value = sword1 }, + new EquipmentUnion { Type = Equipment.Armor, Value = shield1 }, + new EquipmentUnion { Type = Equipment.Weapon, Value = bow1 } + } + }; + + var fbb1 = CreateBuilder(2048); + var offset1 = Player.Pack(fbb1, playerT1); + fbb1.Finish(offset1.Value); + + var player1 = Player.GetRootAsPlayer(fbb1.DataBuffer); + var unpacked = player1.UnPack(); + + var originalList = unpacked.Inventory; + Assert.AreEqual(3, unpacked.Inventory.Count); + + var sword2 = new WeaponT { Name = "Sword2", Damage = 200, Transform = null, FixedStats = null, PositionHistory = null }; + + var playerT2 = new PlayerT + { + Id = 2, + Name = "Player2", + Inventory = new List + { + new EquipmentUnion { Type = Equipment.Weapon, Value = sword2 } + } + }; + + var fbb2 = CreateBuilder(2048); + var offset2 = Player.Pack(fbb2, playerT2); + fbb2.Finish(offset2.Value); + + var player2 = Player.GetRootAsPlayer(fbb2.DataBuffer); + + player2.UnPackTo(unpacked); + + Assert.IsTrue(ReferenceEquals(originalList, unpacked.Inventory)); + Assert.AreEqual(1, unpacked.Inventory.Count); + + var updatedSword = unpacked.Inventory[0].Value as WeaponT; + Assert.AreEqual("Sword2", updatedSword.Name); + Assert.AreEqual(200, updatedSword.Damage); + } + + [FlatBuffersTestMethod] + public void UnPackTo_VectorOfUnions_Growing_AddsNewItems() + { + var sword1 = new WeaponT { Name = "Sword1", Damage = 100, Transform = null, FixedStats = null, PositionHistory = null }; + + var playerT1 = new PlayerT + { + Id = 1, + Name = "Player1", + Inventory = new List + { + new EquipmentUnion { Type = Equipment.Weapon, Value = sword1 } + } + }; + + var fbb1 = CreateBuilder(2048); + var offset1 = Player.Pack(fbb1, playerT1); + fbb1.Finish(offset1.Value); + + var player1 = Player.GetRootAsPlayer(fbb1.DataBuffer); + var unpacked = player1.UnPack(); + + var originalList = unpacked.Inventory; + var originalUnion0 = unpacked.Inventory[0]; + var originalSword = unpacked.Inventory[0].Value as WeaponT; + + var sword2 = new WeaponT { Name = "Sword2", Damage = 200, Transform = null, FixedStats = null, PositionHistory = null }; + var shield2 = new ArmorT { Name = "Shield2", Defense = 100, Transform = null }; + var bow2 = new WeaponT { Name = "Bow2", Damage = 150, Transform = null, FixedStats = null, PositionHistory = null }; + + var playerT2 = new PlayerT + { + Id = 2, + Name = "Player2", + Inventory = new List + { + new EquipmentUnion { Type = Equipment.Weapon, Value = sword2 }, + new EquipmentUnion { Type = Equipment.Armor, Value = shield2 }, + new EquipmentUnion { Type = Equipment.Weapon, Value = bow2 } + } + }; + + var fbb2 = CreateBuilder(2048); + var offset2 = Player.Pack(fbb2, playerT2); + fbb2.Finish(offset2.Value); + + var player2 = Player.GetRootAsPlayer(fbb2.DataBuffer); + + player2.UnPackTo(unpacked); + + Assert.IsTrue(ReferenceEquals(originalList, unpacked.Inventory)); + Assert.AreEqual(3, unpacked.Inventory.Count); + + Assert.IsTrue(ReferenceEquals(originalUnion0, unpacked.Inventory[0])); + Assert.IsTrue(ReferenceEquals(originalSword, unpacked.Inventory[0].Value)); + + var updatedSword = unpacked.Inventory[0].Value as WeaponT; + Assert.AreEqual("Sword2", updatedSword.Name); + Assert.AreEqual(200, updatedSword.Damage); + + Assert.AreEqual(Equipment.Armor, unpacked.Inventory[1].Type); + var newShield = unpacked.Inventory[1].Value as ArmorT; + Assert.AreEqual("Shield2", newShield.Name); + + Assert.AreEqual(Equipment.Weapon, unpacked.Inventory[2].Type); + var newBow = unpacked.Inventory[2].Value as WeaponT; + Assert.AreEqual("Bow2", newBow.Name); + } + + } +} diff --git a/net/FlatSpanBuffers.Tests/Program.cs b/net/FlatSpanBuffers.Tests/Program.cs new file mode 100644 index 00000000000..33e1a52d271 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/Program.cs @@ -0,0 +1,74 @@ +/* + * Copyright 2014 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; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Google.FlatSpanBuffers.Tests +{ + static class Program + { + public static int Main(string[] args) + { + var testResults = new List(); + + var testClasses = Assembly.GetExecutingAssembly().GetExportedTypes() + .Where(t => t.IsClass && t.GetCustomAttributes(typeof (FlatBuffersTestClassAttribute), false).Length > 0); + + foreach (var testClass in testClasses) + { + var methods = testClass.GetMethods(BindingFlags.Public | + BindingFlags.Instance) + .Where(m => m.GetCustomAttributes(typeof(FlatBuffersTestMethodAttribute), false).Length > 0); + + var inst = Activator.CreateInstance(testClass); + + foreach (var method in methods) + { + try + { + Console.WriteLine("Running {0}.{1}...", testClass.Name, method.Name); + method.Invoke(inst, new object[] { }); + Console.WriteLine(" PASSED"); + testResults.Add(true); + } + catch (Exception ex) + { + Console.WriteLine("{0}: FAILED when invoking {1} with error {2}", + testClass.Name, method.Name, ex.GetBaseException()); + testResults.Add(false); + } + } + } + var failedCount = testResults.Count(i => i == false); + + Console.WriteLine(); + Console.WriteLine("=== FlatSpanBuffers Test Results ==="); + Console.WriteLine("{0} tests run, {1} failed", testResults.Count, failedCount); + + if (failedCount > 0) + { + Console.WriteLine("Some tests failed!"); + return -1; + } + + Console.WriteLine("All tests passed!"); + return 0; + } + } +} diff --git a/net/FlatSpanBuffers.Tests/RefStructSortersTests.cs b/net/FlatSpanBuffers.Tests/RefStructSortersTests.cs new file mode 100644 index 00000000000..41619599991 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/RefStructSortersTests.cs @@ -0,0 +1,306 @@ +/* + * Copyright 2026 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; +using System.Collections.Generic; +using System.Linq; +using Google.FlatSpanBuffers.Utils; + +namespace Google.FlatSpanBuffers.Tests +{ + [FlatBuffersTestClass] + public class RefStructSortersTests + { + private struct IntComparer : IComparer + { + public int Compare(int x, int y) => x.CompareTo(y); + } + + private struct StringComparer : IComparer + { + public int Compare(string x, string y) => string.Compare(x, y, StringComparison.Ordinal); + } + + private struct ReverseIntComparer : IComparer + { + public int Compare(int x, int y) => y.CompareTo(x); + } + + private ref struct RefStructComparer : IComparer + { + public int Compare(int x, int y) + { + return (x).CompareTo(y); + } + } + + [FlatBuffersTestMethod] + public void Sort_EmptyArray_DoesNothing() + { + var data = new int[0]; + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.AreEqual(0, data.Length); + } + + [FlatBuffersTestMethod] + public void Sort_SingleElement_DoesNothing() + { + var data = new int[] { 42 }; + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.AreEqual(1, data.Length); + Assert.AreEqual(42, data[0]); + } + + [FlatBuffersTestMethod] + public void Sort_SmallArray_UsesInsertionSort() + { + var data = new int[] { 3, 1, 4, 1, 5, 9, 2, 6 }; + var expected = new int[] { 1, 1, 2, 3, 4, 5, 6, 9 }; + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_LargeArray_UsesIntroSort() + { + // Create array larger than InsertionSortThreshold (16) + var random = new Random(42); // Fixed seed for reproducibility + var data = new int[100]; + for (int i = 0; i < data.Length; i++) + { + data[i] = random.Next(1000); + } + + var expected = data.OrderBy(x => x).ToArray(); + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_AlreadySorted_RemainsStable() + { + var data = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + var expected = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_ReverseSorted_SortsCorrectly() + { + var data = new int[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + var expected = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_WithDuplicates_SortsCorrectly() + { + var data = new int[] { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5 }; + var expected = new int[] { 1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9 }; + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_StringArray_SortsCorrectly() + { + var data = new string[] { "banana", "apple", "cherry", "date", "elderberry" }; + var expected = new string[] { "apple", "banana", "cherry", "date", "elderberry" }; + var span = data.AsSpan(); + var comparer = new StringComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.SpanEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_Size15_SortsCorrectly() + { + var size = 15; + var random = new Random(size); + var data = new int[size]; + for (int i = 0; i < size; i++) + { + data[i] = random.Next(size * 2); + } + + var expected = data.OrderBy(x => x).ToArray(); + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_Size16_SortsCorrectly() + { + var size = 16; + var random = new Random(size); + var data = new int[size]; + for (int i = 0; i < size; i++) + { + data[i] = random.Next(size * 2); + } + + var expected = data.OrderBy(x => x).ToArray(); + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_ReverseComparer_SortsInReverseOrder() + { + var data = new int[] { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5 }; + var expected = data.OrderByDescending(x => x).ToArray(); + var span = data.AsSpan(); + var comparer = new ReverseIntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_AllSameElements_HandlesCorrectly() + { + var data = new int[50]; + Array.Fill(data, 42); + var expected = (int[])data.Clone(); + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_WithNegativeNumbers_SortsCorrectly() + { + var data = new int[] { -5, 3, -1, 0, 2, -3, 1, -2, 4, -4 }; + var expected = data.OrderBy(x => x).ToArray(); + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_LargeRangeValues_SortsCorrectly() + { + var data = new int[] { int.MaxValue, int.MinValue, 0, 1000000, -1000000 }; + var expected = data.OrderBy(x => x).ToArray(); + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_PatternedData_SortsCorrectly() + { + var data = new int[100]; + for (int i = 0; i < data.Length; i++) + { + data[i] = i % 10; // Repeating pattern 0,1,2,3,4,5,6,7,8,9,0,1,2... + } + + var expected = data.OrderBy(x => x).ToArray(); + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_WithRefStructComparer_WorksCorrectly() + { + var data = new int[] { 3, 1, 4, 1, 5, 9, 2, 6, 5 }; + var expected = data.OrderBy(x => x).ToArray(); + var span = data.AsSpan(); + var comparer = new RefStructComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + + [FlatBuffersTestMethod] + public void Sort_TriggerHeapSortFallback_SortsCorrectly() + { + // Create a worst-case scenario that might trigger heapsort fallback + // by creating data that could cause deep recursion in quicksort + var data = new int[500]; + + // Fill with values that create poor pivot choices + for (int i = 0; i < data.Length; i++) + { + data[i] = i % 2 == 0 ? i : data.Length - i; + } + + var expected = data.OrderBy(x => x).ToArray(); + var span = data.AsSpan(); + var comparer = new IntComparer(); + + RefStructSorters.Sort(span, ref comparer); + + Assert.ArrayEqual(expected, data); + } + } +} diff --git a/net/FlatSpanBuffers.Tests/SortedVectorTests.cs b/net/FlatSpanBuffers.Tests/SortedVectorTests.cs new file mode 100644 index 00000000000..cbf9527c41e --- /dev/null +++ b/net/FlatSpanBuffers.Tests/SortedVectorTests.cs @@ -0,0 +1,220 @@ +/* + * Copyright 2026 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; +using System.Collections.Generic; +using System.Linq; +using Google.FlatSpanBuffers.Operations; +using Google.FlatSpanBuffers.Utils; + +namespace Google.FlatSpanBuffers.Tests +{ + [FlatBuffersTestClass] + public class SortedVectorTests + { + // Dummy struct to represent a table type for testing + private struct TestTable + { + } + + [FlatBuffersTestMethod] + public void ScalarOffsetComparer_ComparesInts_Correctly() + { + var builder = new FlatBufferBuilder(256); + + builder.StartTable(1); + builder.Add(0, 42, 0); + var offset1 = builder.EndTable(); + + builder.StartTable(1); + builder.Add(0, 24, 0); + var offset2 = builder.EndTable(); + + builder.StartTable(1); + builder.Add(0, 100, 0); + var offset3 = builder.EndTable(); + + var offsets = new Offset[] { + new Offset(offset1), + new Offset(offset2), + new Offset(offset3) + }; + + var comparer = new SortedVectorUtils.ScalarOffsetComparer( + builder.DataBuffer, 4); + + // Test comparisons + Assert.IsTrue(comparer.Compare(offsets[0], offsets[1]) > 0); // 42 > 24 + Assert.IsTrue(comparer.Compare(offsets[1], offsets[2]) < 0); // 24 < 100 + Assert.AreEqual(0, comparer.Compare(offsets[0], offsets[0])); // 42 == 42 + } + + [FlatBuffersTestMethod] + public void VectorOffsetComparer_ComparesStrings_Correctly() + { + var builder = new FlatBufferBuilder(256); + + var str1 = builder.CreateString("apple"); + var str2 = builder.CreateString("banana"); + var str3 = builder.CreateString("cherry"); + + builder.StartTable(1); + builder.AddOffset(0, str1.Value, 0); + var offset1 = builder.EndTable(); + + builder.StartTable(1); + builder.AddOffset(0, str2.Value, 0); + var offset2 = builder.EndTable(); + + builder.StartTable(1); + builder.AddOffset(0, str3.Value, 0); + var offset3 = builder.EndTable(); + + var offsets = new Offset[] { + new Offset(offset1), + new Offset(offset2), + new Offset(offset3) + }; + + var comparer = new SortedVectorUtils.VectorOffsetComparer( + builder.DataBuffer, 4); + + // Test comparisons + Assert.IsTrue(comparer.Compare(offsets[0], offsets[1]) < 0); // "apple" < "banana" + Assert.IsTrue(comparer.Compare(offsets[1], offsets[2]) < 0); // "banana" < "cherry" + Assert.AreEqual(0, comparer.Compare(offsets[0], offsets[0])); // "apple" == "apple" + } + + [FlatBuffersTestMethod] + public void RefStructSorters_WithScalarComparer_SortsCorrectly() + { + var builder = new FlatBufferBuilder(512); + var values = new int[] { 50, 10, 30, 20, 40 }; + var offsets = new List>(); + + foreach (var value in values) + { + builder.StartTable(1); + builder.Add(0, value, 0); + offsets.Add(new Offset(builder.EndTable())); + } + + var offsetsArray = offsets.ToArray(); + var comparer = new SortedVectorUtils.ScalarOffsetComparer( + builder.DataBuffer, 4); + + RefStructSorters.Sort(offsetsArray, ref comparer); + + // Verify sorted order + var sortedValues = new List(); + var dataBuffer = builder.DataBuffer; + foreach (var offset in offsetsArray) + { + var tablePos = dataBuffer.Length - offset.Value; + var fieldOffset = TableOperations.GetOffset(4, tablePos, dataBuffer); + if (fieldOffset != 0) + { + sortedValues.Add(dataBuffer.Get(tablePos + fieldOffset)); + } + } + + var expected = new int[] { 10, 20, 30, 40, 50 }; + Assert.SpanEqual(expected, sortedValues.ToArray()); + } + + [FlatBuffersTestMethod] + public void RefStructSorters_WithStringComparer_SortsCorrectly() + { + var builder = new FlatBufferBuilder(512); + var values = new string[] { "elephant", "apple", "dog", "banana", "cat" }; + var offsets = new List>(); + + foreach (var value in values) + { + var str = builder.CreateString(value); + builder.StartTable(1); + builder.AddOffset(0, str.Value, 0); + offsets.Add(new Offset(builder.EndTable())); + } + + var offsetsArray = offsets.ToArray(); + var comparer = new SortedVectorUtils.VectorOffsetComparer( + builder.DataBuffer, 4); + + RefStructSorters.Sort(offsetsArray, ref comparer); + + // Verify sorted order + var sortedValues = new List(); + var dataBuffer = builder.DataBuffer; + foreach (var offset in offsetsArray) + { + var tablePos = dataBuffer.Length - offset.Value; + var fieldOffset = TableOperations.GetOffset(4, tablePos, dataBuffer); + if (fieldOffset != 0) + { + var str = TableOperations.GetString(tablePos + fieldOffset, dataBuffer); + sortedValues.Add(str); + } + } + + var expected = new string[] { "apple", "banana", "cat", "dog", "elephant" }; + Assert.SpanEqual(expected, sortedValues.ToArray()); + } + + [FlatBuffersTestMethod] + public void RefStructSorters_WithLargeDataSet_SortsCorrectly() + { + var builder = new FlatBufferBuilder(4096); + var random = new Random(42); + var values = new int[100]; + var offsets = new List>(); + + for (int i = 0; i < values.Length; i++) + { + values[i] = random.Next(1000); + } + + foreach (var value in values) + { + builder.StartTable(1); + builder.Add(0, value, 0); + offsets.Add(new Offset(builder.EndTable())); + } + + var offsetsArray = offsets.ToArray(); + var comparer = new SortedVectorUtils.ScalarOffsetComparer( + builder.DataBuffer, 4); + + RefStructSorters.Sort(offsetsArray, ref comparer); + + // Verify sorted order + var sortedValues = new List(); + var dataBuffer = builder.DataBuffer; + foreach (var offset in offsetsArray) + { + var tablePos = dataBuffer.Length - offset.Value; + var fieldOffset = TableOperations.GetOffset(4, tablePos, dataBuffer); + if (fieldOffset != 0) + { + sortedValues.Add(dataBuffer.Get(tablePos + fieldOffset)); + } + } + + var expectedSorted = values.OrderBy(x => x).ToArray(); + Assert.SpanEqual(expectedSorted, sortedValues.ToArray()); + } + } +} diff --git a/net/FlatSpanBuffers.Tests/StackBufferExampleTests.cs b/net/FlatSpanBuffers.Tests/StackBufferExampleTests.cs new file mode 100644 index 00000000000..2cbcffdd5e8 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/StackBufferExampleTests.cs @@ -0,0 +1,607 @@ +/* + * Copyright 2026 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; +using System.Text; +using Google.FlatSpanBuffers.Utils; +using MyGame.Example; + +using SpanMonster = MyGame.Example.StackBuffer.Monster; + +namespace Google.FlatSpanBuffers.Tests +{ + [FlatBuffersTestClass] + public class StackBufferExampleTests + { + private static FlatSpanBufferBuilder CreateSpanBuilderForMonster() + { + // MyGame.Example.Monster table has 62 fields. + const int MonsterVtableSize = 64; + var bb = new ByteSpanBuffer(new byte[1024]); + FlatSpanBufferBuilder fbb = new FlatSpanBufferBuilder(bb, + vtableSpace: new int[MonsterVtableSize], vtableOffsetSpace: new int[16]); + return fbb; + } + + [FlatBuffersTestMethod] + public void StackBuffer_CanReadFlatBufferFromScratch() + { + var fbb = CreateSpanBuilderForMonster(); + + var str = fbb.CreateString("MyMonster"); + var test1 = fbb.CreateString("test1"); + var test2 = fbb.CreateString("test2"); + + Span inventoryData = stackalloc byte[] { 0, 1, 2, 3, 4 }; + var inv = SpanMonster.CreateInventoryVectorBlock(ref fbb, inventoryData); + + var fred = fbb.CreateString("Fred"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, fred); + var mon2 = SpanMonster.EndMonster(ref fbb); + + SpanMonster.StartTest4Vector(ref fbb, 2); + MyGame.Example.StackBuffer.Test.CreateTest(ref fbb, (short)10, (sbyte)20); + MyGame.Example.StackBuffer.Test.CreateTest(ref fbb, (short)30, (sbyte)40); + var test4 = fbb.EndVector(); + + Span testStrings = stackalloc StringOffset[] { test1, test2 }; + var testArrayOfString = SpanMonster.CreateTestarrayofstringVectorBlock(ref fbb, testStrings); + + Span longsData = stackalloc long[] { 1, 100, 10000, 1000000, 100000000 }; + var longsVector = SpanMonster.CreateVectorOfLongsVector(ref fbb, longsData); + + Span doublesData = stackalloc double[] { -1.7976931348623157e+308, 0, 1.7976931348623157e+308 }; + var doublesVector = SpanMonster.CreateVectorOfDoublesVector(ref fbb, doublesData); + + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddPos(ref fbb, MyGame.Example.StackBuffer.Vec3.CreateVec3(ref fbb, 1.0f, 2.0f, 3.0f, 3.0, + Color.Green, (short)5, (sbyte)6)); + SpanMonster.AddHp(ref fbb, (short)80); + SpanMonster.AddName(ref fbb, str); + SpanMonster.AddInventory(ref fbb, inv); + SpanMonster.AddTestType(ref fbb, Any.Monster); + SpanMonster.AddTest(ref fbb, mon2.Value); + SpanMonster.AddTest4(ref fbb, test4); + SpanMonster.AddTestarrayofstring(ref fbb, testArrayOfString); + SpanMonster.AddTestbool(ref fbb, true); + SpanMonster.AddVectorOfLongs(ref fbb, longsVector); + SpanMonster.AddVectorOfDoubles(ref fbb, doublesVector); + var mon = SpanMonster.EndMonster(ref fbb); + + SpanMonster.FinishMonsterBuffer(ref fbb, mon); + + TestBufferWithStackBuffer(fbb.DataBuffer); + } + + private void TestBufferWithStackBuffer(ByteSpanBuffer bb) + { + bool test = SpanMonster.VerifyMonster(bb); + Assert.AreEqual(true, test); + + SpanMonster monster = SpanMonster.GetRootAsMonster(bb); + + Assert.AreEqual(80, monster.Hp); + Assert.AreEqual(150, monster.Mana); + Assert.AreEqual("MyMonster", monster.Name); + + var pos = monster.Pos.Value; + Assert.AreEqual(1.0f, pos.X, 6); + Assert.AreEqual(2.0f, pos.Y, 6); + Assert.AreEqual(3.0f, pos.Z, 6); + + Assert.AreEqual(3.0, pos.Test1, 6); + Assert.AreEqual(Color.Green, pos.Test2); + var t = pos.Test3; + Assert.AreEqual((short)5, t.A); + Assert.AreEqual((sbyte)6, t.B); + + Assert.AreEqual(Any.Monster, monster.TestType); + + var monster2 = monster.Test().Value; + Assert.AreEqual("Fred", monster2.Name); + + Assert.AreEqual(5, monster.Inventory.Value.Length); + var invsum = 0; + for (var i = 0; i < monster.Inventory.Value.Length; i++) + { + invsum += monster.Inventory.Value[i]; + } + Assert.AreEqual(10, invsum); + + var test4 = monster.Test4; + Assert.IsTrue(test4.HasValue); + var test4Vec = test4.Value; + Assert.AreEqual(2, test4Vec.Length); + var test0 = test4Vec[0]; + var test1 = test4Vec[1]; + + Assert.AreEqual(100, test0.A + test0.B + test1.A + test1.B); + + var testarrayofstring = monster.Testarrayofstring; + Assert.IsTrue(testarrayofstring.HasValue); + var testarrayofstringVec = testarrayofstring.Value; + Assert.AreEqual(2, testarrayofstringVec.Length); + Assert.AreEqual("test1", testarrayofstringVec[0]); + Assert.AreEqual("test2", testarrayofstringVec[1]); + + Assert.AreEqual(true, monster.Testbool); + + var nameBytes = monster.GetNameBytes(); + Assert.AreEqual("MyMonster", Encoding.UTF8.GetString(nameBytes.ToArray(), 0, nameBytes.Length)); + + var longArray = monster.VectorOfLongs.Value; + Assert.AreEqual(5, longArray.Length); + Assert.AreEqual(100, longArray[1]); + + var doublesArray = monster.VectorOfDoubles.Value; + Assert.AreEqual(3, doublesArray.Length); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestVectorOfEnums() + { + const string monsterName = "TestVectorOfEnumsMonster"; + Span colorVec = stackalloc Color[] { Color.Red, Color.Green, Color.Blue }; + + var fbb = CreateSpanBuilderForMonster(); + + var str1 = fbb.CreateString(monsterName); + var vec1 = SpanMonster.CreateVectorOfEnumsVector(ref fbb, colorVec); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, str1); + SpanMonster.AddVectorOfEnums(ref fbb, vec1); + var monster1 = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monster1); + + var mons = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + var colors = mons.VectorOfEnums.Value; + Assert.AreEqual(3, colors.Length); + Assert.AreEqual(Color.Red, colors[0]); + Assert.AreEqual(Color.Green, colors[1]); + Assert.AreEqual(Color.Blue, colors[2]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestDefaultValues() + { + var fbb = CreateSpanBuilderForMonster(); + + var nameOffset = fbb.CreateString("DefaultMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + // Check default values from schema + Assert.AreEqual(150, monster.Mana); + Assert.AreEqual(100, monster.Hp); + Assert.AreEqual(Color.Blue, monster.Color); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestStringAsSpan() + { + var fbb = CreateSpanBuilderForMonster(); + + var name = "UnicodeMonster_\u00E4\u00F6\u00FC"; + var nameOffset = fbb.CreateString(name); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.AreEqual(name, monster.Name); + var nameBytes = monster.GetNameBytes(); + Assert.AreEqual(name, Encoding.UTF8.GetString(nameBytes.ToArray(), 0, nameBytes.Length)); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestInventoryAsSpan() + { + var fbb = CreateSpanBuilderForMonster(); + + Span inventoryData = stackalloc byte[] { 10, 20, 30, 40, 50 }; + var inv = SpanMonster.CreateInventoryVectorBlock(ref fbb, inventoryData); + + var nameOffset = fbb.CreateString("InventoryMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + SpanMonster.AddInventory(ref fbb, inv); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.IsTrue(monster.Inventory.HasValue); + var invSpan = monster.Inventory.Value; + Assert.AreEqual(5, invSpan.Length); + Assert.AreEqual(10, invSpan[0]); + Assert.AreEqual(50, invSpan[4]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestUnion() + { + var fbb = CreateSpanBuilderForMonster(); + + var nestedName = fbb.CreateString("NestedMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nestedName); + SpanMonster.AddHp(ref fbb, 500); + var nestedMonster = SpanMonster.EndMonster(ref fbb); + + var mainName = fbb.CreateString("MainMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, mainName); + SpanMonster.AddTestType(ref fbb, Any.Monster); + SpanMonster.AddTest(ref fbb, nestedMonster.Value); + var mainMonster = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, mainMonster); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.AreEqual(Any.Monster, monster.TestType); + var nested = monster.Test().Value; + Assert.AreEqual("NestedMonster", nested.Name); + Assert.AreEqual(500, nested.Hp); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestVectorOfStructs() + { + var fbb = CreateSpanBuilderForMonster(); + + SpanMonster.StartTest4Vector(ref fbb, 3); + MyGame.Example.StackBuffer.Test.CreateTest(ref fbb, (short)100, (sbyte)10); + MyGame.Example.StackBuffer.Test.CreateTest(ref fbb, (short)200, (sbyte)20); + MyGame.Example.StackBuffer.Test.CreateTest(ref fbb, (short)300, (sbyte)30); + var test4 = fbb.EndVector(); + + var nameOffset = fbb.CreateString("StructVectorMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + SpanMonster.AddTest4(ref fbb, test4); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.IsTrue(monster.Test4.HasValue); + var test4Vec = monster.Test4.Value; + Assert.AreEqual(3, test4Vec.Length); + Assert.AreEqual((short)100, test4Vec[2].A); + Assert.AreEqual((sbyte)10, test4Vec[2].B); + Assert.AreEqual((short)300, test4Vec[0].A); + Assert.AreEqual((sbyte)30, test4Vec[0].B); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestEmptyBuffer() + { + var fbb = CreateSpanBuilderForMonster(); + + var nameOffset = fbb.CreateString("EmptyMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.AreEqual("EmptyMonster", monster.Name); + Assert.IsFalse(monster.Inventory.HasValue); + Assert.IsFalse(monster.Test4.HasValue); + Assert.IsFalse(monster.Testarrayoftables.HasValue); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestVectorOfLongs() + { + var fbb = CreateSpanBuilderForMonster(); + + Span longsData = stackalloc long[] { long.MinValue, -1, 0, 1, long.MaxValue }; + var longsVector = SpanMonster.CreateVectorOfLongsVector(ref fbb, longsData); + + var nameOffset = fbb.CreateString("LongsMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + SpanMonster.AddVectorOfLongs(ref fbb, longsVector); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.IsTrue(monster.VectorOfLongs.HasValue); + var longs = monster.VectorOfLongs.Value; + Assert.AreEqual(5, longs.Length); + Assert.AreEqual(long.MinValue, longs[0]); + Assert.AreEqual(long.MaxValue, longs[4]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestVectorOfDoubles() + { + var fbb = CreateSpanBuilderForMonster(); + + Span doublesData = stackalloc double[] { double.MinValue, -1.5, 0, 1.5, double.MaxValue }; + var doublesVector = SpanMonster.CreateVectorOfDoublesVector(ref fbb, doublesData); + + var nameOffset = fbb.CreateString("DoublesMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + SpanMonster.AddVectorOfDoubles(ref fbb, doublesVector); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.IsTrue(monster.VectorOfDoubles.HasValue); + var doubles = monster.VectorOfDoubles.Value; + Assert.AreEqual(5, doubles.Length); + Assert.AreEqual(double.MinValue, doubles[0], 6); + Assert.AreEqual(double.MaxValue, doubles[4], 6); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestArrayOfBools() + { + var fbb = CreateSpanBuilderForMonster(); + + Span boolsData = stackalloc bool[] { true, false, true, false, true }; + var boolsVector = SpanMonster.CreateTestarrayofboolsVector(ref fbb, boolsData); + + var nameOffset = fbb.CreateString("BoolsMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + SpanMonster.AddTestarrayofbools(ref fbb, boolsVector); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.IsTrue(monster.Testarrayofbools.HasValue); + var bools = monster.Testarrayofbools.Value; + Assert.AreEqual(5, bools.Length); + Assert.AreEqual(true, bools[0]); + Assert.AreEqual(false, bools[1]); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestEnemy() + { + var fbb = CreateSpanBuilderForMonster(); + + // Create enemy monster + var enemyName = fbb.CreateString("Enemy"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, enemyName); + SpanMonster.AddHp(ref fbb, 50); + var enemy = SpanMonster.EndMonster(ref fbb); + + // Create main monster with enemy + var mainName = fbb.CreateString("MainWithEnemy"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, mainName); + SpanMonster.AddEnemy(ref fbb, enemy); + var main = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, main); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.IsTrue(monster.Enemy.HasValue); + var enemyMonster = monster.Enemy.Value; + Assert.AreEqual("Enemy", enemyMonster.Name); + Assert.AreEqual(50, enemyMonster.Hp); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestNanAndInfinityDefaults() + { + var fbb = CreateSpanBuilderForMonster(); + + var nameOffset = fbb.CreateString("SpecialFloatsMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + // Test default values for nan and infinity fields + Assert.IsTrue(float.IsNaN(monster.NanDefault)); + Assert.IsTrue(float.IsPositiveInfinity(monster.InfDefault)); + Assert.IsTrue(float.IsPositiveInfinity(monster.PositiveInfDefault)); + Assert.IsTrue(float.IsPositiveInfinity(monster.InfinityDefault)); + Assert.IsTrue(float.IsPositiveInfinity(monster.PositiveInfinityDefault)); + Assert.IsTrue(float.IsNegativeInfinity(monster.NegativeInfDefault)); + Assert.IsTrue(float.IsNegativeInfinity(monster.NegativeInfinityDefault)); + Assert.IsTrue(double.IsPositiveInfinity(monster.DoubleInfDefault)); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestVerifier_ValidBuffer() + { + var fbb = CreateSpanBuilderForMonster(); + + var nameOffset = fbb.CreateString("VerifyMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + SpanMonster.AddHp(ref fbb, 100); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + Assert.IsTrue(SpanMonster.VerifyMonster(fbb.DataBuffer)); + + Span corruptedData = stackalloc byte[8]; + var invalidBuffer = new ByteSpanBuffer(corruptedData); + Assert.IsFalse(SpanMonster.VerifyMonster(invalidBuffer)); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestTableVector() + { + var fbb = CreateSpanBuilderForMonster(); + + var name1 = fbb.CreateString("Monster1"); + var name2 = fbb.CreateString("Monster2"); + var name3 = fbb.CreateString("Monster3"); + + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, name1); + var mon1 = SpanMonster.EndMonster(ref fbb); + + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, name2); + var mon2 = SpanMonster.EndMonster(ref fbb); + + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, name3); + var mon3 = SpanMonster.EndMonster(ref fbb); + + Span> monstersSpan = stackalloc Offset[] { mon1, mon2, mon3 }; + var monstersVector = SpanMonster.CreateTestarrayoftablesVectorBlock(ref fbb, monstersSpan); + + var mainName = fbb.CreateString("MainMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, mainName); + SpanMonster.AddTestarrayoftables(ref fbb, monstersVector); + var mainMonster = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, mainMonster); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.IsTrue(monster.Testarrayoftables.HasValue); + var monsters = monster.Testarrayoftables.Value; + Assert.AreEqual(3, monsters.Length); + Assert.AreEqual("Monster1", monsters[0].Name); + Assert.AreEqual("Monster2", monsters[1].Name); + Assert.AreEqual("Monster3", monsters[2].Name); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestStructAccess() + { + var fbb = CreateSpanBuilderForMonster(); + + var nameOffset = fbb.CreateString("StructMonster"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + SpanMonster.AddPos(ref fbb, MyGame.Example.StackBuffer.Vec3.CreateVec3(ref fbb, + 1.5f, 2.5f, 3.5f, 4.5, Color.Red, (short)100, (sbyte)50)); + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + + Assert.IsTrue(monster.Pos.HasValue); + var pos = monster.Pos.Value; + + Assert.AreEqual(1.5f, pos.X, 6); + Assert.AreEqual(2.5f, pos.Y, 6); + Assert.AreEqual(3.5f, pos.Z, 6); + Assert.AreEqual(4.5, pos.Test1, 6); + Assert.AreEqual(Color.Red, pos.Test2); + Assert.AreEqual((short)100, pos.Test3.A); + Assert.AreEqual((sbyte)50, pos.Test3.B); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestStackAllocatedBufferReading() + { + var builder = new FlatBufferBuilder(128); + var nameOffset = builder.CreateString("StackMonster"); + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 999); + var monsterOffset = Monster.EndMonster(builder); + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var serializedData = builder.DataBuffer.ToSizedSpan(); + Span stackBuffer = stackalloc byte[serializedData.Length]; + serializedData.CopyTo(stackBuffer); + + var spanBuffer = new ByteSpanBuffer(stackBuffer); + var monster = SpanMonster.GetRootAsMonster(spanBuffer); + Assert.AreEqual("StackMonster", monster.Name); + Assert.AreEqual(999, monster.Hp); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestMutateAndVerify() + { + var fbb = CreateSpanBuilderForMonster(); + + var nameOffset = fbb.CreateString("VerifyMutate"); + SpanMonster.StartMonster(ref fbb); + SpanMonster.AddName(ref fbb, nameOffset); + SpanMonster.AddHp(ref fbb, 50); // Use non-default value so it's in the buffer + var monsterOffset = SpanMonster.EndMonster(ref fbb); + SpanMonster.FinishMonsterBuffer(ref fbb, monsterOffset); + + // Verify before mutation + Assert.IsTrue(SpanMonster.VerifyMonster(fbb.DataBuffer)); + + var monster = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + Assert.AreEqual(50, monster.Hp); + Assert.IsTrue(monster.MutateHp(200)); + Assert.AreEqual(200, monster.Hp); + + // Verify after mutation - buffer should still be valid + Assert.IsTrue(SpanMonster.VerifyMonster(fbb.DataBuffer)); + + // Read again and verify mutated value persists + var monster2 = SpanMonster.GetRootAsMonster(fbb.DataBuffer); + Assert.AreEqual(200, monster2.Hp); + } + + [FlatBuffersTestMethod] + public void StackBuffer_TestCrossVariantCompatibility() + { + var fbb = new FlatBufferBuilder(128); + + Span inventoryData = stackalloc byte[] { 1, 2, 3 }; + var inv = Monster.CreateInventoryVectorBlock(fbb, inventoryData); + + var nameOffset = fbb.CreateString("CrossVariant"); + Monster.StartMonster(fbb); + Monster.AddName(fbb, nameOffset); + Monster.AddInventory(fbb, inv); + Monster.AddHp(fbb, 123); + var monsterOffset = Monster.EndMonster(fbb); + Monster.FinishMonsterBuffer(fbb, monsterOffset); + + // Read with regular Monster + var regularMonster = Monster.GetRootAsMonster(fbb.DataBuffer); + Assert.AreEqual("CrossVariant", regularMonster.Name); + Assert.AreEqual(123, regularMonster.Hp); + + // Read with StackBuffer Monster + var bb = ByteBufferUtil.ToSizedByteSpanBuffer(fbb.DataBuffer); + var spanMonster = SpanMonster.GetRootAsMonster(bb); + Assert.AreEqual("CrossVariant", spanMonster.Name); + Assert.AreEqual(123, spanMonster.Hp); + + // Both should read the same data + Assert.AreEqual(regularMonster.Hp, spanMonster.Hp); + Assert.AreEqual(regularMonster.Name, spanMonster.Name); + } + } +} diff --git a/net/FlatSpanBuffers.Tests/TestTable.cs b/net/FlatSpanBuffers.Tests/TestTable.cs new file mode 100644 index 00000000000..79766d6a722 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/TestTable.cs @@ -0,0 +1,153 @@ +/* + * Copyright 2016 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. + */ + +namespace Google.FlatSpanBuffers.Tests +{ + // Mirrored from: tests/FlatBuffers.Test/TestTable.cs + /// + /// A test Table object that gives easy access to the slot data + /// + internal struct TestTable + { + Table t; + + public TestTable(ByteBuffer bb, int pos) + { + t = new Table(pos, bb); + } + + public bool GetSlot(int slot, bool def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.GetSbyte(t.bb_pos + off) != 0; + } + + public sbyte GetSlot(int slot, sbyte def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.GetSbyte(t.bb_pos + off); + } + + public byte GetSlot(int slot, byte def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.Get(t.bb_pos + off); + } + + public short GetSlot(int slot, short def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.Get(t.bb_pos + off); + } + + public ushort GetSlot(int slot, ushort def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.Get(t.bb_pos + off); + } + + public int GetSlot(int slot, int def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.Get(t.bb_pos + off); + } + + public uint GetSlot(int slot, uint def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.Get(t.bb_pos + off); + } + + public long GetSlot(int slot, long def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.Get(t.bb_pos + off); + } + + public ulong GetSlot(int slot, ulong def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.Get(t.bb_pos + off); + } + + public float GetSlot(int slot, float def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.Get(t.bb_pos + off); + } + + public double GetSlot(int slot, double def) + { + var off = t.__offset(slot); + + if (off == 0) + { + return def; + } + return t.bb.Get(t.bb_pos + off); + } + } +} diff --git a/net/FlatSpanBuffers.Tests/VerifierTests.cs b/net/FlatSpanBuffers.Tests/VerifierTests.cs new file mode 100644 index 00000000000..b58b25973df --- /dev/null +++ b/net/FlatSpanBuffers.Tests/VerifierTests.cs @@ -0,0 +1,601 @@ +/* + * Copyright 2015 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; +using MonsterTest; +using ComprehensiveTest; + +namespace Google.FlatSpanBuffers.Tests +{ + /// + /// Verifier coverage for valid, corrupted, and constrained buffers. + /// + [FlatBuffersTestClass] + public class VerifierTests + { + private static bool VerifyMonsterDirect(ByteBuffer buffer) + { + var verifier = new Verifier(buffer); + return verifier.VerifyBuffer("", false, MonsterVerify.Verify); + } + + private static bool VerifyMonsterWithOptions(ByteBuffer buffer, Options options, bool sizePrefixed = false) + { + var verifier = new Verifier(buffer, options); + return verifier.VerifyBuffer("", sizePrefixed, MonsterVerify.Verify); + } + + [FlatBuffersTestMethod] + public void Monster_VerifyValidBuffer_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("Orc"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 300); + Monster.AddMana(builder, 150); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var buffer = builder.DataBuffer; + Assert.IsTrue(VerifyMonsterDirect(buffer)); + } + + [FlatBuffersTestMethod] + public void Monster_VerifyWithAllFields_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("Boss Monster"); + + Span inventoryData = stackalloc byte[] { 1, 2, 3 }; + var inventoryVector = Monster.CreateInventoryVectorBlock(builder, inventoryData); + + var sword = MonsterTest.Weapon.CreateWeapon(builder, builder.CreateString("Sword"), 10); + Span> weaponsData = stackalloc Offset[] { sword }; + var weaponsVector = Monster.CreateWeaponsVectorBlock(builder, weaponsData); + + var equippedName = builder.CreateString("Shield"); + var equipped = MonsterTest.Weapon.CreateWeapon(builder, equippedName, 5); + + Monster.StartPathVector(builder, 2); + MonsterTest.Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f); + MonsterTest.Vec3.CreateVec3(builder, 4.0f, 5.0f, 6.0f); + var pathVector = builder.EndVector(); + + var pos = new MonsterTest.Vec3T { X = 100.0f, Y = 50.0f, Z = 25.0f }; + + Monster.StartMonster(builder); + Monster.AddPos(builder, MonsterTest.Vec3.Pack(builder, pos)); + Monster.AddMana(builder, 200); + Monster.AddHp(builder, 500); + Monster.AddName(builder, nameOffset); + Monster.AddInventory(builder, inventoryVector); + Monster.AddColor(builder, MonsterTest.Color.Red); + Monster.AddWeapons(builder, weaponsVector); + Monster.AddEquippedType(builder, MonsterTest.Equipment.Weapon); + Monster.AddEquipped(builder, equipped.Value); + Monster.AddPath(builder, pathVector); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var buffer = builder.DataBuffer; + Assert.IsTrue(VerifyMonsterDirect(buffer)); + } + + [FlatBuffersTestMethod] + public void GameSession_VerifyValidBuffer_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var sessionIdOffset = builder.CreateString("SESSION-001"); + + GameSession.StartGameSession(builder); + GameSession.AddSessionId(builder, sessionIdOffset); + GameSession.AddPlayerCount(builder, 4); + GameSession.AddStartTime(builder, DateTimeOffset.UtcNow.ToUnixTimeSeconds()); + var sessionOffset = GameSession.EndGameSession(builder); + + GameSession.FinishGameSessionBuffer(builder, sessionOffset); + + var buffer = builder.DataBuffer; + Assert.IsTrue(GameSession.VerifyGameSession(buffer)); + } + + [FlatBuffersTestMethod] + public void Player_VerifyWithAllBasicFields_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var playerName = builder.CreateString("CompletePlayer"); + + Span statsData = stackalloc int[] { 10, 15, 8 }; + var statsVector = Player.CreateStatsVectorBlock(builder, statsData); + + var skill1 = builder.CreateString("Slash"); + Span skillsData = stackalloc StringOffset[] { skill1 }; + var skillsVector = Player.CreateSkillsVectorBlock(builder, skillsData); + + Player.StartPlayer(builder); + Player.AddId(builder, 42); + Player.AddName(builder, playerName); + Player.AddLevel(builder, 25); + Player.AddExperience(builder, 150000); + Player.AddHealth(builder, 200.0f); + Player.AddMana(builder, 100.0f); + Player.AddStats(builder, statsVector); + Player.AddSkills(builder, skillsVector); + Player.AddStatus(builder, Status.Active); + var playerOffset = Player.EndPlayer(builder); + + builder.Finish(playerOffset.Value); + + var buffer = builder.DataBuffer; + var verifier = new Verifier(buffer); + var rootOffset = buffer.Get(buffer.Position); + Assert.IsTrue(PlayerVerify.Verify(ref verifier, (uint)buffer.Position + rootOffset)); + } + + [FlatBuffersTestMethod] + public void MonsterWeapon_VerifyValidBuffer_ReturnsTrue() + { + var builder = new FlatBufferBuilder(512); + + var weaponName = builder.CreateString("Excalibur"); + var weapon = MonsterTest.Weapon.CreateWeapon(builder, weaponName, 100); + + builder.Finish(weapon.Value); + + var buffer = builder.DataBuffer; + var verifier = new Verifier(buffer); + var rootOffset = buffer.Get(buffer.Position); + Assert.IsTrue(MonsterTest.WeaponVerify.Verify(ref verifier, (uint)buffer.Position + rootOffset)); + } + + [FlatBuffersTestMethod] + public void Monster_VerifyCorruptedRootOffset_ReturnsFalse() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("Orc"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 100); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var sizedSpan = builder.DataBuffer.ToSizedSpan(); + var sourceData = sizedSpan.ToArray(); + + // Corrupt by setting root offset to point way outside buffer + // The root offset is at the beginning of the sized span (position 0 in the array) + sourceData[0] = 0xFF; + sourceData[1] = 0xFF; + sourceData[2] = 0xFF; + sourceData[3] = 0x7F; + + var corruptedBuffer = new ByteBuffer(sourceData); + Assert.IsFalse(VerifyMonsterDirect(corruptedBuffer)); + } + + [FlatBuffersTestMethod] + public void Monster_VerifyTruncatedBuffer_ReturnsFalse() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("Orc"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + // Get the buffer data and truncate it + var sourceSpan = builder.DataBuffer.ToSizedSpan(); + var truncatedLength = Math.Max(8, sourceSpan.Length / 2); + var truncatedData = sourceSpan.Slice(0, truncatedLength).ToArray(); + + var truncatedBuffer = new ByteBuffer(truncatedData); + Assert.IsFalse(VerifyMonsterDirect(truncatedBuffer)); + } + + [FlatBuffersTestMethod] + public void Monster_VerifyEmptyBuffer_ReturnsFalse() + { + var emptyBuffer = new ByteBuffer(new byte[4]); + Assert.IsFalse(VerifyMonsterDirect(emptyBuffer)); + } + + [FlatBuffersTestMethod] + public void Monster_VerifyWithCustomOptions_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("Test Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var buffer = builder.DataBuffer; + + // Test with custom options + var options = new Options( + maxDepth: 32, + maxTables: 500000, + stringEndCheck: true, + alignmentCheck: true + ); + + Assert.IsTrue(VerifyMonsterWithOptions(buffer, options)); + } + + [FlatBuffersTestMethod] + public void Monster_VerifyWithDisabledAlignmentCheck_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("Test Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var buffer = builder.DataBuffer; + + // Test with alignment check disabled + var options = new Options( + maxDepth: Options.DEFAULT_MAX_DEPTH, + maxTables: Options.DEFAULT_MAX_TABLES, + stringEndCheck: true, + alignmentCheck: false + ); + + Assert.IsTrue(VerifyMonsterWithOptions(buffer, options)); + } + + [FlatBuffersTestMethod] + public void Monster_VerifyWithDisabledStringEndCheck_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("Test Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var buffer = builder.DataBuffer; + + var options = new Options( + maxDepth: Options.DEFAULT_MAX_DEPTH, + maxTables: Options.DEFAULT_MAX_TABLES, + stringEndCheck: false, + alignmentCheck: true + ); + + Assert.IsTrue(VerifyMonsterWithOptions(buffer, options)); + } + + [FlatBuffersTestMethod] + public void Monster_VerifySizePrefixedBuffer_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("Size Prefixed Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 200); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishSizePrefixedMonsterBuffer(builder, monsterOffset); + + var buffer = builder.DataBuffer; + var options = new Options(); + Assert.IsTrue(VerifyMonsterWithOptions(buffer, options, sizePrefixed: true)); + } + + [FlatBuffersTestMethod] + public void GameSession_VerifySizePrefixedBuffer_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var sessionIdOffset = builder.CreateString("SIZED-SESSION-001"); + + GameSession.StartGameSession(builder); + GameSession.AddSessionId(builder, sessionIdOffset); + GameSession.AddPlayerCount(builder, 8); + var sessionOffset = GameSession.EndGameSession(builder); + + GameSession.FinishSizePrefixedGameSessionBuffer(builder, sessionOffset); + + var buffer = builder.DataBuffer; + var verifier = new Verifier(buffer); + var result = verifier.VerifyBuffer("TEST", true, GameSessionVerify.Verify); + Assert.IsTrue(result); + } + + [FlatBuffersTestMethod] + public void Monster_VerifyWithByteSpanBuffer_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("Span Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 150); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + // Create ByteSpanBuffer from the sized data (starts at position 0) + var bufferSpan = builder.DataBuffer.ToSizedSpan(); + var byteSpanBuffer = new ByteSpanBuffer(bufferSpan); + + var verifier = new Verifier(byteSpanBuffer); + var result = verifier.VerifyBuffer(null, false, MonsterVerify.Verify); + Assert.IsTrue(result); + } + + [FlatBuffersTestMethod] + public void VerifyDeeplyNestedTables_WithLowMaxDepth_ReturnsFalse() + { + var builder = new FlatBufferBuilder(2048); + + var weaponName = builder.CreateString("Nested Weapon"); + var weapon = MonsterTest.Weapon.CreateWeapon(builder, weaponName, 10); + + Span> weaponsData = stackalloc Offset[] { weapon }; + var weaponsVector = Monster.CreateWeaponsVectorBlock(builder, weaponsData); + + var nameOffset = builder.CreateString("Deep Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddWeapons(builder, weaponsVector); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var buffer = builder.DataBuffer; + + // Test with very low max depth + var options = new Options( + maxDepth: 1, + maxTables: Options.DEFAULT_MAX_TABLES, + stringEndCheck: true, + alignmentCheck: true + ); + + Assert.IsFalse(VerifyMonsterWithOptions(buffer, options)); + } + + [FlatBuffersTestMethod] + public void VerifyManyTables_WithLowMaxTables_ReturnsFalse() + { + var builder = new FlatBufferBuilder(4096); + + var weapons = new Offset[5]; + for (int i = 0; i < 5; i++) + { + var weaponName = builder.CreateString($"Weapon{i}"); + weapons[i] = MonsterTest.Weapon.CreateWeapon(builder, weaponName, (short)(i * 10)); + } + + var weaponsVector = Monster.CreateWeaponsVectorBlock(builder, weapons); + var nameOffset = builder.CreateString("Multi-Weapon Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddWeapons(builder, weaponsVector); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var buffer = builder.DataBuffer; + + // Test with very low max tables + var options = new Options( + maxDepth: Options.DEFAULT_MAX_DEPTH, + maxTables: 1, + stringEndCheck: true, + alignmentCheck: true + ); + + Assert.IsFalse(VerifyMonsterWithOptions(buffer, options)); + } + + [FlatBuffersTestMethod] + public void VerifyDeeplyNestedTables_WithHighMaxDepth_ReturnsTrue() + { + var builder = new FlatBufferBuilder(2048); + + // Create nested weapons + var weaponName = builder.CreateString("Nested Weapon"); + var weapon = MonsterTest.Weapon.CreateWeapon(builder, weaponName, 10); + + Span> weaponsData = stackalloc Offset[] { weapon }; + var weaponsVector = Monster.CreateWeaponsVectorBlock(builder, weaponsData); + + var nameOffset = builder.CreateString("Deep Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddWeapons(builder, weaponsVector); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var buffer = builder.DataBuffer; + + // Test with sufficient max depth + var options = new Options( + maxDepth: 10, + maxTables: Options.DEFAULT_MAX_TABLES, + stringEndCheck: true, + alignmentCheck: true + ); + + Assert.IsTrue(VerifyMonsterWithOptions(buffer, options)); + } + + [FlatBuffersTestMethod] + public void Monster_SerializeAndVerify_RoundTrip() + { + var originalMonster = new MonsterT + { + Name = "Roundtrip Monster", + Hp = 500, + Mana = 200, + Color = MonsterTest.Color.Red + }; + + var binaryData = originalMonster.SerializeToBinary(); + + var buffer = new ByteBuffer(binaryData); + Assert.IsTrue(VerifyMonsterDirect(buffer)); + + // Deserialize and verify + var deserializedMonster = MonsterT.DeserializeFromBinary(binaryData); + Assert.AreEqual(originalMonster.Name, deserializedMonster.Name); + Assert.AreEqual(originalMonster.Hp, deserializedMonster.Hp); + Assert.AreEqual(originalMonster.Mana, deserializedMonster.Mana); + Assert.AreEqual(originalMonster.Color, deserializedMonster.Color); + } + + [FlatBuffersTestMethod] + public void StackBuffer_Monster_VerifyValidBuffer_ReturnsTrue() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("StackBuffer Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddHp(builder, 200); + Monster.AddMana(builder, 100); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var sourceSpan = builder.DataBuffer.ToSizedSpan(); + var byteSpanBuffer = new ByteSpanBuffer(sourceSpan); + + var result = MonsterTest.StackBuffer.Monster.VerifyMonster(byteSpanBuffer); + Assert.IsTrue(result); + } + + [FlatBuffersTestMethod] + public void StackBuffer_GameSession_VerifyValidBuffer_ReturnsTrue() + { + var builder = new FlatBufferBuilder(2048); + + var sessionId = builder.CreateString("session-12345"); + + GameSession.StartGameSession(builder); + GameSession.AddSessionId(builder, sessionId); + GameSession.AddPlayerCount(builder, 4); + GameSession.AddStartTime(builder, 1234567890L); + var sessionOffset = GameSession.EndGameSession(builder); + + GameSession.FinishGameSessionBuffer(builder, sessionOffset); + + var sourceSpan = builder.DataBuffer.ToSizedSpan(); + var byteSpanBuffer = new ByteSpanBuffer(sourceSpan); + + var result = ComprehensiveTest.StackBuffer.GameSession.VerifyGameSession(byteSpanBuffer); + Assert.IsTrue(result); + } + + [FlatBuffersTestMethod] + public void Verify_DepthCounters_ReturnsFalse() + { + var builder = new FlatBufferBuilder(4096); + + var weapons = new Offset[10]; + for (int i = 0; i < 10; i++) + { + var weaponName = builder.CreateString("W" + i); + weapons[i] = MonsterTest.Weapon.CreateWeapon(builder, weaponName, (short)(i * 10)); + } + + var weaponsVector = Monster.CreateWeaponsVectorBlock(builder, weapons); + var nameOffset = builder.CreateString("Multi-Weapon Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + Monster.AddWeapons(builder, weaponsVector); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var buffer = builder.DataBuffer; + + // 11 Total tables: 1 Monster + 10 Weapons = 11 tables + // maxTables = 5 should cause failure + var options = new Options( + maxDepth: Options.DEFAULT_MAX_DEPTH, + maxTables: 5, + stringEndCheck: true, + alignmentCheck: true + ); + + Assert.IsFalse(VerifyMonsterWithOptions(buffer, options)); + } + + [FlatBuffersTestMethod] + public void StackBuffer_Monster_VerifyCorruptedBuffer_ReturnsFalse() + { + var builder = new FlatBufferBuilder(1024); + + var nameOffset = builder.CreateString("Valid Monster"); + + Monster.StartMonster(builder); + Monster.AddName(builder, nameOffset); + var monsterOffset = Monster.EndMonster(builder); + + Monster.FinishMonsterBuffer(builder, monsterOffset); + + var sourceSpan = builder.DataBuffer.ToSizedSpan(); + var corruptedData = sourceSpan.ToArray(); + + corruptedData[0] = 0xFF; + corruptedData[1] = 0xFF; + corruptedData[2] = 0xFF; + corruptedData[3] = 0xFF; + + var byteSpanBuffer = new ByteSpanBuffer(corruptedData); + + var result = MonsterTest.StackBuffer.Monster.VerifyMonster(byteSpanBuffer); + Assert.IsFalse(result); + } + } +} diff --git a/net/FlatSpanBuffers.Tests/monsterdata_test.json b/net/FlatSpanBuffers.Tests/monsterdata_test.json new file mode 100644 index 00000000000..11698770d87 --- /dev/null +++ b/net/FlatSpanBuffers.Tests/monsterdata_test.json @@ -0,0 +1,48 @@ +{ + "pos": { + "x": 1, + "y": 2, + "z": 3, + "test1": 3, + "test2": "Green", + "test3": { + "a": 5, + "b": 6 + } + }, + "hp": 80, + "name": "MyMonster", + "inventory": [0, 1, 2, 3, 4], + "vector_of_longs": [1, 100, 10000, 1000000, 100000000], + "vector_of_doubles": [-1.7976931348623157e+308, 0, 1.7976931348623157e+308], + "test_type": "Monster", + "test": { + "Type": "Monster", + "Value": { + "name": "Fred", + "pos": null + } + }, + "test4": [ + {"a": 10, "b": 20}, + {"a": 30, "b": 40} + ], + "test5": [ + {"a": 10, "b": 20}, + {"a": 30, "b": 40} + ], + "testarrayofstring": ["test1", "test2"], + "enemy": {"name": "Fred"}, + "testarrayofbools": [true, false, true], + "testbool": true, + "testarrayofsortedstruct": [ + {"id": 5, "distance": 12}, + {"id": 1, "distance": 21}, + {"id": 0, "distance": 45} + ], + "scalar_key_sorted_tables": [ + {"id": "hit", "val": 10, "count": 1}, + {"id": "miss", "val": 0, "count": 0} + ], + "native_inline": {"a": 1, "b": 2} +} diff --git a/net/FlatSpanBuffers.Tests/monsterdata_test.mon b/net/FlatSpanBuffers.Tests/monsterdata_test.mon new file mode 100644 index 00000000000..da0ed8698fc Binary files /dev/null and b/net/FlatSpanBuffers.Tests/monsterdata_test.mon differ diff --git a/net/FlatSpanBuffers/BufferBuilder.cs b/net/FlatSpanBuffers/BufferBuilder.cs new file mode 100644 index 00000000000..6dc94a06570 --- /dev/null +++ b/net/FlatSpanBuffers/BufferBuilder.cs @@ -0,0 +1,493 @@ +/* + * Copyright 2014 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; +using System.Collections.Generic; +using System.Text; +using Google.FlatSpanBuffers.Operations; + +namespace Google.FlatSpanBuffers +{ + /// + /// Common BufferBuilder operations for FlatBuffer construction. + /// Contains shared state for reuse with BufferBuider vairants (class and ref struct builders) + /// + public struct BufferBuilder + where TBuffer : IByteBuffer, allows ref struct + { + private int _space; + private int _minAlign; + // The size of the vtable. -1 indicates no vtable + private int _vtableSize; + // Starting offset of the current struct/table. + private int _objectStart; + // Number of entries in `vtables` in use. + private int _numVtables; + // For the current vector being built. + private int _vectorNumElems; + + // Optional allocator. + IByteBufferAllocator _bufferAllocator; + + // For CreateSharedString + private Dictionary _sharedStringMap; + + /// + /// Initialize a new BufferBuilder with an initial size and optional + /// allocator to grow the buffer as needed + /// + public BufferBuilder(int bufferSize, IByteBufferAllocator bufferAllocator) + { + _space = bufferSize; + _minAlign = 1; + _vtableSize = -1; + _objectStart = 0; + _numVtables = 0; + _vectorNumElems = 0; + _bufferAllocator = bufferAllocator; + _sharedStringMap = null; + } + + /// + /// Current offset in the buffer + /// + public readonly int GetOffset(ref TBuffer buffer) + => buffer.Length - _space; + + /// + /// Set the shared string map for CreateSharedString functionality + /// + public void SetSharedStringCache(Dictionary sharedStringMap) + { + _sharedStringMap = sharedStringMap; + } + + /// + /// Reset the builder state for a new buffer + /// + public void Reset(ref TBuffer buffer, Span vtable) + { + if (_vtableSize > 0) + vtable.Slice(0, _vtableSize).Clear(); + _vtableSize = -1; + _space = buffer.Length; + _minAlign = 1; + _objectStart = 0; + _numVtables = 0; + _vectorNumElems = 0; + if (_sharedStringMap != null) + { + _sharedStringMap.Clear(); + } + + buffer.Reset(); + } + + public void Pad(ref TBuffer buffer, int size) + { + buffer.PadBytes(_space -= size, size); + } + + // Prepare to write an element of size after additional_bytes have been written + public void Prep(ref TBuffer buffer, int size, int additionalBytes) + { + // Track the biggest thing we've ever aligned to. + if (size > _minAlign) + _minAlign = size; + + // Find the amount of alignment needed such that `size` is properly + // aligned after `additionalBytes` + int alignSize = + ((~(buffer.Length - _space + additionalBytes)) + 1) & + (size - 1); + + // Check if we have enough space, realign if necessary + int requiredSize = alignSize + size + additionalBytes; + while (_space < requiredSize) + { + if (_bufferAllocator == null) + throw new OutOfMemoryException("Builder was not provided enough space to build the flatbuffer."); + + var oldBufSize = buffer.Length; + var minRequiredBufferSize = buffer.Length - _space + requiredSize; + _bufferAllocator.GrowFront(ref buffer, minRequiredBufferSize); + _space += buffer.Length - oldBufSize; + } + + if (alignSize > 0) + Pad(ref buffer, alignSize); + } + + public void Put(ref TBuffer buffer, T value) + where T : unmanaged + { + buffer.Put(_space -= BufferOperations.SizeOf(), value); + } + + public void Put(ref TBuffer buffer, scoped ReadOnlySpan value) + where T : unmanaged + { + buffer.PutSpan(_space -= BufferOperations.SizeOf() * value.Length, value); + } + + public void Add(ref TBuffer buffer, T value) + where T : unmanaged + { + Prep(ref buffer, BufferOperations.SizeOf(), 0); + buffer.Put(_space -= BufferOperations.SizeOf(), value); + } + + public void AddSpan(ref TBuffer buffer, scoped ReadOnlySpan values) + where T : unmanaged + { + if (values.IsEmpty) + return; + + int elementSize = BufferOperations.SizeOf(); + int spanSize = elementSize * values.Length; + Prep(ref buffer, elementSize, spanSize - elementSize); + buffer.PutSpan(_space -= spanSize, values); + } + + public readonly void ValidateNotNested() + { + // You should not be creating any other objects or strings/vectors + // while an object is being constructed + if (_vtableSize >= 0) + throw new InvalidOperationException("FlatBuffers: object serialization must not be nested."); + } + + public void StartTable(ref TBuffer buffer, int numfields, Span vtable) + { + ValidateNotNested(); + if (numfields < 0) + throw new ArgumentOutOfRangeException("Flatbuffers: invalid numfields"); + if (vtable.Length < numfields) + throw new OutOfMemoryException("Number of table fields exceeds provided vtable buffer space."); + + _vtableSize = numfields; + _objectStart = GetOffset(ref buffer); + } + + /// + /// End table construction and return the table offset + /// 'numVtables' provides the current number of saved vtables to track memory use. + /// + public int EndTable(ref TBuffer buffer, Span vtable, Span vtables, out int numVtables) + { + if (_vtableSize < 0) + throw new InvalidOperationException("FlatBuffers: calling EndTable without a StartTable"); + + numVtables = _numVtables; + + // Add table header + Add(ref buffer, 0); + int vtableloc = GetOffset(ref buffer); + + // Write out the current vtable. + int i = _vtableSize - 1; + // Trim trailing zeroes. + for (; i >= 0 && vtable[i] == 0; i--) { } + int trimmedSize = i + 1; + + // Reserve space for the header and fields. + const int standardFields = 2; + short vtableSizeBytes = (short)((trimmedSize + standardFields) * sizeof(short)); + Prep(ref buffer, sizeof(short), vtableSizeBytes - sizeof(short)); + + for (; i >= 0; i--) + { + // Offset relative to the start of the table. + short off = (short)(vtable[i] != 0 ? vtableloc - vtable[i] : 0); + buffer.Put(_space -= sizeof(short), off); + vtable[i] = 0; + } + + // Then write vtable header: table size, then vtable size + buffer.Put(_space -= sizeof(short), (short)(vtableloc - _objectStart)); + buffer.Put(_space -= sizeof(short), vtableSizeBytes); + + // Search for an existing vtable that matches the current one. + ReadOnlySpan currentVtable = buffer.ToReadOnlySpan(_space, vtableSizeBytes); + for (i = 0; i < _numVtables; i++) + { + int vt2 = buffer.Length - vtables[i]; + if (currentVtable.Length == buffer.Get(vt2)) + { + bool match = currentVtable.SequenceEqual( + buffer.ToReadOnlySpan(vt2, currentVtable.Length)); + if (match) + { + // Remove the current vtable. + _space = buffer.Length - vtableloc; + + // Point table to existing vtable. + buffer.Put(_space, vtables[i] - vtableloc); + + _vtableSize = -1; + return vtableloc; + } + } + } + + if (_numVtables >= vtables.Length) + throw new InvalidOperationException("FlatBuffers: not enough vtables offset space reserved to store this table."); + + // No existing vtable found, add this vtable to list + var newVtableOffset = GetOffset(ref buffer); + vtables[_numVtables++] = newVtableOffset; + numVtables = _numVtables; + + // Point table to current vtable. + int objLoc = buffer.Length - vtableloc; + buffer.Put(objLoc, newVtableOffset - vtableloc); + + _vtableSize = -1; + return vtableloc; + } + + // Set the current vtable at `voffset` to the current location in the + // buffer. + public void SetVtableSlot(ref TBuffer buffer, Span vtable, int voffset) + { + vtable[voffset] = GetOffset(ref buffer); + } + + public void AddToTable(ref TBuffer buffer, Span vtable, int o, T x, T d, bool forceDefaults) + where T : unmanaged, IEquatable + { + if (forceDefaults || !x.Equals(d)) + { + Add(ref buffer, x); + SetVtableSlot(ref buffer, vtable, o); + } + } + + public void AddToTable(ref TBuffer buffer, Span vtable, int o, T? x) + where T : unmanaged + { + if (x.HasValue) + { + Add(ref buffer, x.Value); + SetVtableSlot(ref buffer, vtable, o); + } + } + + /// + /// Add an offset value to the buffer, relative to where it will be written. + /// + public void AddOffset(ref TBuffer buffer, int off) + { + Prep(ref buffer, sizeof(int), 0); // Ensure alignment is already done. + int offset = off != 0 ? GetOffset(ref buffer) - off + sizeof(int) : 0; + buffer.Put(_space -= sizeof(int), offset); + } + + public void AddStruct(ref TBuffer buffer, Span vtable, int voffset, int x, int d) + { + // Structs are stored inline, so nothing additional is being added. + // `d` is always 0. + if (x != d) + { + if (x != GetOffset(ref buffer)) + { + throw new InvalidOperationException( + " FlatBuffers: struct must be serialized inline."); + } + + SetVtableSlot(ref buffer, vtable, voffset); + } + } + + public void StartVector(ref TBuffer buffer, int elemSize, int count, int alignment) + { + ValidateNotNested(); + _vectorNumElems = count; + Prep(ref buffer, sizeof(int), elemSize * count); + Prep(ref buffer, alignment, elemSize * count); // Just in case alignment > int. + } + + public VectorOffset EndVector(ref TBuffer buffer) + { + buffer.Put(_space -= sizeof(int), _vectorNumElems); + return new VectorOffset(GetOffset(ref buffer)); + } + + /// + /// Adds a buffer offset to the Table at index `o` in its vtable using an offset value and default value + /// + public void AddOffsetToTable(ref TBuffer buffer, Span vtable, int o, int x, int d) + { + if (x != d) + { + AddOffset(ref buffer, x); + SetVtableSlot(ref buffer, vtable, o); + } + } + + public void AddOffsetSpan(ref TBuffer buffer, scoped ReadOnlySpan offsets) + { + if (offsets.IsEmpty) + return; + + // Prepare space for all offsets + Prep(ref buffer, sizeof(int), (offsets.Length - 1) * sizeof(int)); + for (var i = offsets.Length - 1; i >= 0; i--) + { + int adjustedOffset = GetOffset(ref buffer) - offsets[i] + sizeof(int); + buffer.Put(_space -= sizeof(int), adjustedOffset); + } + } + + public void AddOffsetSpan(ref TBuffer buffer, scoped ReadOnlySpan offsets) + where TOffset : IFlatBufferOffset + { + if (offsets.IsEmpty) + return; + + // Prepare space for all offsets + Prep(ref buffer, sizeof(int), (offsets.Length - 1) * sizeof(int)); + for (var i = offsets.Length - 1; i >= 0; i--) + { + int adjustedOffset = GetOffset(ref buffer) - offsets[i].Value + sizeof(int); + buffer.Put(_space -= sizeof(int), adjustedOffset); + } + } + + public VectorOffset CreateVectorOfTables(ref TBuffer buffer, scoped ReadOnlySpan> offsets) + where T : struct, allows ref struct + { + ValidateNotNested(); + StartVector(ref buffer, sizeof(int), offsets.Length, sizeof(int)); + AddOffsetSpan(ref buffer, offsets); + return EndVector(ref buffer); + } + + /// + /// Encode the string `s` in the buffer using UTF-8. + /// + public StringOffset CreateString(ref TBuffer buffer, scoped ReadOnlySpan s) + { + ValidateNotNested(); + if (s.IsEmpty) + return new StringOffset(0); + + Add(ref buffer, 0); + var utf8StringLength = Encoding.UTF8.GetByteCount(s); + StartVector(ref buffer, 1, utf8StringLength, 1); + buffer.PutStringUTF8(_space -= utf8StringLength, s); + return new StringOffset(EndVector(ref buffer).Value); + } + + /// + /// Encode the utf8 bytes `s` in the buffer. + /// + public StringOffset CreateUTF8String(ref TBuffer buffer, scoped ReadOnlySpan s) + { + ValidateNotNested(); + if (s.IsEmpty) + return new StringOffset(0); + + Add(ref buffer, 0); + StartVector(ref buffer, 1, s.Length, 1); + buffer.PutSpan(_space -= s.Length, s); + return new StringOffset(EndVector(ref buffer).Value); + } + + /// + /// Create a shared string using the internal shared string map. + /// If the string already exists, this returns the offset of the existing string. + /// + public StringOffset CreateSharedString(ref TBuffer buffer, string s) + { + if (s == null) + return new StringOffset(0); + + var sharedStringMap = _sharedStringMap ??= new Dictionary(); + + if (sharedStringMap.TryGetValue(s, out StringOffset stringOffset)) + return stringOffset; + + stringOffset = CreateString(ref buffer, s.AsSpan()); + sharedStringMap.Add(s, stringOffset); + return stringOffset; + } + + public void Finish(ref TBuffer buffer, int rootTable) + { + InternalFinishBuffer(ref buffer, rootTable); + } + + public void FinishWithSizePrefix(ref TBuffer buffer, int rootTable) + { + int additionalBytes = sizeof(int) + FlatBufferConstants.SizePrefixLength; + Prep(ref buffer, _minAlign, additionalBytes); + InternalFinishBufferWithSizePrefix(ref buffer, rootTable); + } + + public void FinishWithSizePrefix(ref TBuffer buffer, int rootTable, string fileIdentifier) + { + ValidateFileIdentifier(fileIdentifier); + + int additionalBytes = sizeof(int) + FlatBufferConstants.FileIdentifierLength + FlatBufferConstants.SizePrefixLength; + Prep(ref buffer, _minAlign, additionalBytes); + buffer.PutStringUTF8(_space -= FlatBufferConstants.FileIdentifierLength, fileIdentifier); + InternalFinishBufferWithSizePrefix(ref buffer, rootTable); + } + + public void FinishWithFileId(ref TBuffer buffer, int rootTable, string fileIdentifier) + { + ValidateFileIdentifier(fileIdentifier); + + int additionalBytes = sizeof(int) + FlatBufferConstants.FileIdentifierLength; + Prep(ref buffer, _minAlign, additionalBytes); + buffer.PutStringUTF8(_space -= FlatBufferConstants.FileIdentifierLength, fileIdentifier); + InternalFinishBuffer(ref buffer, rootTable); + } + + private static void ValidateFileIdentifier(string fileIdentifier) + { + if (string.IsNullOrEmpty(fileIdentifier)) + throw new ArgumentException("FlatBuffers: file identifier is null or empty"); + if (fileIdentifier.Length != FlatBufferConstants.FileIdentifierLength) + throw new ArgumentException($"FlatBuffers: file identifier must be length {FlatBufferConstants.FileIdentifierLength}", nameof(fileIdentifier)); + } + + private void InternalFinishBuffer(ref TBuffer buffer, int rootTable) + { + AddOffset(ref buffer, rootTable); + buffer.Position = _space; + } + + private void InternalFinishBufferWithSizePrefix(ref TBuffer buffer, int rootTable) + { + AddOffset(ref buffer, rootTable); + Add(ref buffer, buffer.Length - _space); + buffer.Position = _space; + } + + // This checks a required field has been set in a given table that has + // just been constructed. + public void ValidateRequiredField(ref TBuffer buffer, int table, int field) + { + int tableStart = buffer.Length - table; + int vtableStart = tableStart - (int)buffer.Get(tableStart); + bool ok = (vtableStart + field) != 0; + if (!ok) + throw new InvalidOperationException("FlatBuffers: required field " + field + " must be set"); + } + } +} diff --git a/net/FlatSpanBuffers/ByteBuffer.cs b/net/FlatSpanBuffers/ByteBuffer.cs new file mode 100644 index 00000000000..f80a2e40d50 --- /dev/null +++ b/net/FlatSpanBuffers/ByteBuffer.cs @@ -0,0 +1,98 @@ +/* + * Copyright 2014 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; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using Google.FlatSpanBuffers.Operations; + +namespace Google.FlatSpanBuffers +{ + public struct ByteBuffer : IByteBuffer + { + private byte[] _buffer; + private int _pos; + private int _length; + + public ByteBuffer(int size) + : this(new byte[size]) { } + + public ByteBuffer(byte[] buffer) + : this(buffer, 0) { } + + public ByteBuffer(byte[] buffer, int pos) + : this(buffer, pos, buffer.Length) { } + + // Providing a length is helpful for tracking the + // actual length of an encoded FlatBuffer off the wire. + public ByteBuffer(byte[] buffer, int pos, int length) + { + if (buffer == null) + throw new ArgumentNullException(nameof(buffer)); + + _buffer = buffer; + _pos = pos; + _length = length; + } + + // Position is the start of the encoded flatbuffer. + public int Position { get => _pos; set => _pos = value; } + public int Length => _length; + public byte[] Buffer => _buffer; + + public void Reset() => _pos = 0; + public void Reset(byte[] buffer, int pos, int length) + { + _buffer = buffer; + _pos = pos; + _length = length; + } + + public Span ToSpan(int pos, int len) + => _buffer.AsSpan(pos, len); + public ReadOnlySpan ToReadOnlySpan(int pos, int len) + => _buffer.AsSpan(pos, len); + public Span ToSizedSpan() + => _buffer.AsSpan(Position, Length - Position); + public ReadOnlySpan ToSizedReadOnlySpan() + => _buffer.AsSpan(Position, Length - Position); + public void PutByte(int offset, byte value) + => _buffer[offset] = value; + public void PutSbyte(int offset, sbyte value) + => _buffer[offset] = (byte)value; + public void PadBytes(int offset, int count) + => BufferOperations.PadZeros(_buffer.AsSpan(offset, count)); + public void Put(int offset, T value) where T : unmanaged + => BufferOperations.Write(_buffer, offset, value); + public void PutSpan(int offset, scoped ReadOnlySpan value) where T : unmanaged + => BufferOperations.WriteSpan(_buffer, offset, value); + public void PutStringUTF8(int offset, scoped ReadOnlySpan value) + => Encoding.UTF8.GetBytes(value, _buffer.AsSpan(offset)); + public byte Get(int index) + => _buffer[index]; + public sbyte GetSbyte(int index) + => (sbyte)_buffer[index]; + public T Get(int offset) where T : unmanaged + => BufferOperations.Read(_buffer, offset); + public Span GetSpan(int offset, int length) where T : unmanaged + => BufferOperations.ReadSpan(_buffer, offset, length); + public ReadOnlySpan GetReadOnlySpan(int offset, int length) where T : unmanaged + => BufferOperations.ReadSpan(_buffer, offset, length); + public string GetStringUTF8(int startPos, int len) + => Encoding.UTF8.GetString(_buffer.AsSpan(startPos, len)); + } +} diff --git a/net/FlatSpanBuffers/ByteSpanBuffer.cs b/net/FlatSpanBuffers/ByteSpanBuffer.cs new file mode 100644 index 00000000000..32ac7b4798a --- /dev/null +++ b/net/FlatSpanBuffers/ByteSpanBuffer.cs @@ -0,0 +1,79 @@ +/* + * Copyright 2014 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; +using System.Text; +using Google.FlatSpanBuffers.Operations; + +namespace Google.FlatSpanBuffers +{ + public ref struct ByteSpanBuffer : IByteBuffer + { + private Span _buffer; + private int _pos; + + public ByteSpanBuffer(Span buffer) + { + _buffer = buffer; + _pos = 0; + } + + public ByteSpanBuffer(ByteBuffer bb) + { + _buffer = bb.ToSizedSpan(); + _pos = 0; + } + + // Position is the start of the encoded flatbuffer. + public int Position { get => _pos; set => _pos = value; } + public readonly int Length => _buffer.Length; + + public void Reset() => _pos = 0; + + public Span ToSpan(int pos, int len) + => _buffer.Slice(pos, len); + public ReadOnlySpan ToReadOnlySpan(int pos, int len) + => _buffer.Slice(pos, len); + public Span ToSizedSpan() + => _buffer.Slice(Position, Length - Position); + public ReadOnlySpan ToSizedReadOnlySpan() + => _buffer.Slice(Position, Length - Position); + public void PutByte(int offset, byte value) + => _buffer[offset] = value; + public void PutSbyte(int offset, sbyte value) + => _buffer[offset] = (byte)value; + public void PadBytes(int offset, int count) + => BufferOperations.PadZeros(_buffer.Slice(offset, count)); + public void Put(int offset, T value) where T : unmanaged + => BufferOperations.Write(_buffer, offset, value); + public void PutSpan(int offset, scoped ReadOnlySpan value) where T : unmanaged + => BufferOperations.WriteSpan(_buffer, offset, value); + public void PutStringUTF8(int offset, scoped ReadOnlySpan value) + => Encoding.UTF8.GetBytes(value, _buffer.Slice(offset)); + public byte Get(int index) + => _buffer[index]; + public sbyte GetSbyte(int index) + => (sbyte)_buffer[index]; + public T Get(int offset) where T : unmanaged + => BufferOperations.Read(_buffer, offset); + public Span GetSpan(int offset, int length) where T : unmanaged + => BufferOperations.ReadSpan(_buffer, offset, length); + public ReadOnlySpan GetReadOnlySpan(int offset, int length) where T : unmanaged + => BufferOperations.ReadSpan(_buffer, offset, length); + public string GetStringUTF8(int startPos, int len) + => Encoding.UTF8.GetString(_buffer.Slice(startPos, len)); + } +} diff --git a/net/FlatSpanBuffers/FlatBufferBuilder.cs b/net/FlatSpanBuffers/FlatBufferBuilder.cs new file mode 100644 index 00000000000..876791bb1fe --- /dev/null +++ b/net/FlatSpanBuffers/FlatBufferBuilder.cs @@ -0,0 +1,431 @@ +/* + * Copyright 2014 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; +using System.Collections.Generic; + +namespace Google.FlatSpanBuffers +{ + public interface IByteBufferAllocator + where TBuffer : IByteBuffer, allows ref struct + { + public int GrowFront(ref TBuffer bb, int requestedSize); + } + + public class DefaultByteBufferAllocator : IByteBufferAllocator + { + public int GrowFront(ref ByteBuffer bb, int requestedSize) + { + var oldBufferLength = bb.Length; + if ((oldBufferLength & 0xC0000000) != 0) + throw new Exception( + "ByteBuffer: cannot grow buffer beyond 2 gigabytes."); + + if (requestedSize < oldBufferLength) + throw new Exception("ByteBuffer: cannot truncate buffer."); + + var newLength = Math.Max(oldBufferLength << 1, requestedSize); + var oldBuffer = bb.Buffer; + var newBuffer = new byte[newLength]; + var dataStart = newLength - oldBufferLength; + System.Buffer.BlockCopy(oldBuffer, 0, newBuffer, dataStart, oldBufferLength); + + // Grow is called while building; position stays at 0 until finalize. + bb.Reset(newBuffer, 0, newLength); + return newLength; + } + } + + /// + /// Responsible for building up and accessing a FlatBuffer formatted byte + /// array (via ByteBuffer). + /// + public class FlatBufferBuilder + { + private ByteBuffer _bb; + private BufferBuilder _builder; + + // The vtable for the current table + private int[] _vtable; + // List of offsets of all vtables. + private int[] _vtables; + + /// + /// Gets and sets a Boolean to disable the optimization when serializing + /// default values to a Table. + /// + /// In order to save space, fields that are set to their default value + /// don't get serialized into the buffer. + /// + public bool ForceDefaults { get; set; } + + public int Offset => _builder.GetOffset(ref _bb); + + /// + /// Get the ByteBuffer representing the FlatBuffer. + /// + public ByteBuffer DataBuffer => _bb; + + /// + /// Create a FlatBufferBuilder with a given initial size. + /// + /// + /// The initial size to use for the internal buffer. + /// + public FlatBufferBuilder(int initialSize) + : this(new ByteBuffer(initialSize)) + { + } + + /// + /// Creates a FlatBufferBuilder backed by the provided ByteBuffer. + /// + /// The ByteBuffer to write to + public FlatBufferBuilder(ByteBuffer buffer) + : this(buffer, vtableSpace: new int[16], vtableOffsetSpace: new int[16]) + { + } + + /// + /// Creates a FlatBufferBuilder backed by the provided ByteBuffer. + /// Provide the vtable workspace for expected table sizes. + /// + /// The ByteBuffer to write to + public FlatBufferBuilder(ByteBuffer buffer, + int[] vtableSpace, + int[] vtableOffsetSpace) + : this(buffer, vtableSpace, vtableOffsetSpace, new DefaultByteBufferAllocator()) + { + } + + /// + /// Creates a FlatBufferBuilder backed by the provided ByteBuffer. + /// Provide vtable workspace for expected table sizes. + /// Provide a custom allocator or preallocated sharedStringMap. + /// + /// The ByteBuffer to write to + public FlatBufferBuilder(ByteBuffer buffer, + int[] vtableSpace, + int[] vtableOffsetSpace, + IByteBufferAllocator allocator, + Dictionary sharedStringMap = null) + { + if (vtableSpace == null || vtableSpace.Length == 0) + throw new Exception($"Flatbuffers: {nameof(vtableSpace)} cannot be null or be length 0"); + if (vtableSpace == null || vtableOffsetSpace.Length == 0) + throw new Exception($"Flatbuffers: {nameof(vtableOffsetSpace)} cannot be null or be length 0"); + + _bb = buffer; + _vtable = vtableSpace; + _vtables = vtableOffsetSpace; + ForceDefaults = false; + + var alloc = allocator ?? new DefaultByteBufferAllocator(); + _builder = new BufferBuilder(buffer.Length, alloc); + _builder.SetSharedStringCache(sharedStringMap); + + buffer.Reset(); + } + + public ReadOnlySpan SizedReadOnlySpan() + { + return _bb.ToSizedReadOnlySpan(); + } + + /// + /// Reset the FlatBufferBuilder by purging all data that it holds. + /// + public void Clear() + { + _builder.Reset(ref _bb, _vtable); + } + + /// + /// Assign new ByteBuffer and reset the FlatBufferBuilder by purging all data that it holds. + /// + public void Clear(ByteBuffer buffer) + { + _bb = buffer; + Clear(); + } + + public void Pad(int size) + { + _builder.Pad(ref _bb, size); + } + + // Prepare to write an element of `size` after `additional_bytes` + // have been written, e.g. if you write a string, you need to align + // such the int length field is aligned to SIZEOF_INT, and the string + // data follows it directly. + // If all you need to do is align, `additional_bytes` will be 0. + public void Prep(int size, int additionalBytes) + { + _builder.Prep(ref _bb, size, additionalBytes); + } + + public void Put(T value) + where T : unmanaged + { + _builder.Put(ref _bb, value); + } + + public void Put(ReadOnlySpan x) + where T : unmanaged + { + _builder.Put(ref _bb, x); + } + + public void Add(T value) + where T : unmanaged + { + _builder.Add(ref _bb, value); + } + + public void AddSpan(ReadOnlySpan x) + where T : unmanaged + { + _builder.AddSpan(ref _bb, x); + } + + /// + /// Adds a value to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The unmanaged type to add + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void Add(int o, T x, T d) + where T : unmanaged, IEquatable + { + _builder.AddToTable(ref _bb, _vtable, o, x, d, ForceDefaults); + } + + /// + /// Adds a nullable value to the Table at index `o` in its vtable + /// + /// The unmanaged type to add + /// The index into the vtable + /// The nullable value to put into the buffer. If it doesn't have a value + /// it will skip writing to the buffer. + public void Add(int o, T? x) + where T : unmanaged + { + _builder.AddToTable(ref _bb, _vtable, o, x); + } + + public void StartVector(int elemSize, int count, int alignment) + { + _builder.StartVector(ref _bb, elemSize, count, alignment); + } + + /// + /// Writes data necessary to finish a vector construction. + /// + public VectorOffset EndVector() + { + return _builder.EndVector(ref _bb); + } + + + /// + /// Creates a vector of tables from a span of offsets + /// + /// Span of offsets of the tables. + public VectorOffset CreateVectorOfTables(ReadOnlySpan> offsets) + where T : struct, allows ref struct + { + return _builder.CreateVectorOfTables(ref _bb, offsets); + } + + public void StartTable(int numfields) + { + if (_vtable.Length < numfields) + _vtable = new int[Math.Max(numfields, _vtable.Length * 2)]; + + _builder.StartTable(ref _bb, numfields, _vtable); + } + + public int EndTable() + { + int offset = _builder.EndTable(ref _bb, _vtable, _vtables, out int numVtables); + if (numVtables >= _vtables.Length) + Array.Resize(ref _vtables, _vtables.Length * 2); + + return offset; + } + + /// + /// Adds an offset, relative to where it will be written. + /// + /// The offset to add to the buffer. + public void AddOffset(int offset) + { + _builder.AddOffset(ref _bb, offset); + } + + /// + /// Adds a buffer offset to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// the value will be skipped. + /// `d` is always 0. + public void AddOffset(int o, int x, int d) + { + _builder.AddOffsetToTable(ref _bb, _vtable, o, x, d); + } + + public void AddOffset(int o, TOffset x, int d) + where TOffset : IFlatBufferOffset + { + _builder.AddOffsetToTable(ref _bb, _vtable, o, x.Value, d); + } + + /// + /// Adds offsets, relative to where they will be written. + /// + /// The offsets to add to the buffer. + public void AddOffsetSpan(ReadOnlySpan offsets) + { + _builder.AddOffsetSpan(ref _bb, offsets); + } + + /// + /// Adds typed offsets, relative to where they will be written. + /// + public void AddOffsetSpan(ReadOnlySpan offsets) + where TOffset : IFlatBufferOffset + { + _builder.AddOffsetSpan(ref _bb, offsets); + } + + /// + /// Encode the string `s` in the buffer using UTF-8. + /// + /// The string to encode. + /// + /// The offset in the buffer where the encoded string starts. + /// + public StringOffset CreateString(ReadOnlySpan s) + { + return _builder.CreateString(ref _bb, s); + } + + /// + /// Creates a string in the buffer from a Span containing + /// a UTF8 string. + /// + /// the UTF8 string to add to the buffer + /// + /// The offset in the buffer where the encoded string starts. + /// + public StringOffset CreateUTF8String(ReadOnlySpan chars) + { + return _builder.CreateUTF8String(ref _bb, chars); + } + + /// + /// Store a string in the buffer, which can contain any binary data. + /// If a string with this exact contents has already been serialized before, + /// instead simply returns the offset of the existing string. + /// + /// The string to encode. + /// + /// The offset in the buffer where the encoded string starts. + /// + public StringOffset CreateSharedString(string s) + { + return _builder.CreateSharedString(ref _bb, s); + } + + // Structs are stored inline, so nothing additional is being added. + // `d` is always 0. + public void AddStruct(int voffset, int x, int d) + { + _builder.AddStruct(ref _bb, _vtable, voffset, x, d); + } + + // Structs are stored inline, so nothing additional is being added. + // `d` is always 0. + public void AddStruct(int o, TOffset x, int d) + where TOffset : IFlatBufferOffset + { + _builder.AddStruct(ref _bb, _vtable, o, x.Value, d); + } + + // This checks a required field has been set in a given table that has + // just been constructed. + public void Required(int table, int field) + { + _builder.ValidateRequiredField(ref _bb, table, field); + } + + /// + /// Finalize a buffer, pointing to the given `root_table`. + /// + /// + /// An offset to be added to the buffer. + /// + public void Finish(int rootTable) + { + _builder.Finish(ref _bb, rootTable); + } + + /// + /// Finalize a buffer, pointing to the given `rootTable`. + /// + /// + /// An offset to be added to the buffer. + /// + /// + /// A FlatBuffer file identifier to be added to the buffer before + /// `root_table`. + /// + public void Finish(int rootTable, string fileIdentifier) + { + _builder.FinishWithFileId(ref _bb, rootTable, fileIdentifier); + } + + /// + /// Finalize a buffer, pointing to the given `root_table`, with the size prefixed. + /// + /// + /// An offset to be added to the buffer. + /// + public void FinishSizePrefixed(int rootTable) + { + _builder.FinishWithSizePrefix(ref _bb, rootTable); + } + + /// + /// Finalize a buffer, pointing to the given `rootTable`, with the size prefixed. + /// + /// + /// An offset to be added to the buffer. + /// + /// + /// A FlatBuffer file identifier to be added to the buffer before + /// `root_table`. + /// + public void FinishSizePrefixed(int rootTable, string fileIdentifier) + { + _builder.FinishWithSizePrefix(ref _bb, rootTable, fileIdentifier); + } + } +} + diff --git a/net/FlatSpanBuffers/FlatBufferConstants.cs b/net/FlatSpanBuffers/FlatBufferConstants.cs new file mode 100644 index 00000000000..b0699303059 --- /dev/null +++ b/net/FlatSpanBuffers/FlatBufferConstants.cs @@ -0,0 +1,37 @@ +/* + * Copyright 2014 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; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Google.FlatSpanBuffers +{ + public static class FlatBufferConstants + { + public const int FileIdentifierLength = 4; + public const int SizePrefixLength = 4; + /** A version identifier to force a compile error if someone + accidentally tries to build generated code with a runtime of + two mismatched version. Versions need to always match, as + the runtime and generated code are modified in sync. + Changes to the C# implementation need to be sure to change + the version here and in the code generator on every possible + incompatible change */ + public static void FLATBUFFERS_25_2_10() {} + } +} diff --git a/net/FlatSpanBuffers/FlatBufferVerify.cs b/net/FlatSpanBuffers/FlatBufferVerify.cs new file mode 100644 index 00000000000..e3d3bb62f66 --- /dev/null +++ b/net/FlatSpanBuffers/FlatBufferVerify.cs @@ -0,0 +1,694 @@ +/* + * Copyright 2014 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; +using Google.FlatSpanBuffers.Operations; + +namespace Google.FlatSpanBuffers +{ + /// + /// The Class of the Verifier Options + /// + public struct Options + { + public const int DEFAULT_MAX_DEPTH = 64; + public const int DEFAULT_MAX_TABLES = 1000000; + + /// Maximum depth of nested tables allowed in a valid flatbuffer. + public int MaxDepth { get; set; } + /// Maximum number of tables allowed in a valid flatbuffer. + public int MaxTables { get; set; } + /// Check that string contains its null terminator + public bool StringEndCheck { get; set; } + /// Check alignment of elements + public bool AlignmentCheck { get; set; } + + public Options() + : this(maxDepth: DEFAULT_MAX_DEPTH, maxTables: DEFAULT_MAX_TABLES, + stringEndCheck: true, alignmentCheck: true) + { + } + + public Options(int maxDepth, int maxTables, bool stringEndCheck, bool alignmentCheck) + { + this.MaxDepth = maxDepth; + this.MaxTables = maxTables; + this.StringEndCheck = stringEndCheck; + this.AlignmentCheck = alignmentCheck; + } + + } + + public struct CheckElementStruct + { + public bool elementValid; + public uint elementOffset; + } + + public delegate bool VerifyTableAction(ref Verifier verifier, uint tablePos); + public delegate bool VerifyUnionAction(ref Verifier verifier, byte typeId, uint tablePos); + + /// + /// The Main ref struct of the FlatBuffer Verifier, + /// Can be constructed from either ByteBuffer or ByteSpanBuffer. + /// + public ref struct Verifier + { + public const int SIZE_BYTE = 1; + public const int SIZE_INT = 4; + public const int SIZE_U_OFFSET = 4; + public const int SIZE_S_OFFSET = 4; + public const int SIZE_V_OFFSET = 2; + public const int SIZE_PREFIX_LENGTH = FlatBufferConstants.SizePrefixLength; + public const int FLATBUFFERS_MAX_BUFFER_SIZE = int.MaxValue; + public const int FILE_IDENTIFIER_LENGTH = FlatBufferConstants.FileIdentifierLength; + + private ByteSpanBuffer _buf; + private Options _options; + private int _depth; + private int _numTables; + + /// Bytes Buffer for Verify + public ByteSpanBuffer Buf { get => _buf; set => _buf = value; } + /// Options of the Verifier + public Options Options => _options; + /// Counter of tables depth in a tested flatbuffer + public int Depth => _depth; + /// Counter of tables in a tested flatbuffer + public int NumTables => _numTables; + + + /// The Constructor of the Verifier object with input parameters: ByteBuffer and/or Options + /// Input flat byte buffer defined as ByteBuffer type + /// Options object with settings for the coniguration the Verifier + public Verifier(ByteSpanBuffer buf, Options options) + { + _buf = buf; + _options = options; + _depth = 0; + _numTables = 0; + } + + public Verifier(ByteSpanBuffer buf) + : this(buf, new Options()) + { + } + + public Verifier(ByteBuffer buf, Options options) + : this(new ByteSpanBuffer(buf.ToSpan(0, buf.Length)), options) + { + // Preserve the Position for offset calculations + _buf.Position = buf.Position; + } + + public Verifier(ByteBuffer buf) + : this(buf, new Options()) + { + } + + /// Check if there is identifier in buffer + /// Start position of data in the Byte Buffer + /// Identifier for the Byte Buffer + /// Return True when the Byte Buffer Identifier is present + private bool BufferHasIdentifier(uint startPos, string identifier) + { + return TableOperations.HasIdentifier(_buf, identifier, (int)startPos); + } + + /// Get UOffsetT from buffer at given position - it must be verified before read + /// Position of data in the Byte Buffer + /// Return the UOffset Value (Unsigned Integer type - 4 bytes) in pos + private uint ReadUOffsetT(uint pos) + { + return _buf.Get((int)pos); + } + /// Get SOffsetT from buffer at given position - it must be verified before read + /// Position of data in the Byte Buffer + /// Return the SOffset Value (Signed Integer type - 4 bytes) in pos + private int ReadSOffsetT(int pos) + { + return _buf.Get(pos); + } + /// Get VOffsetT from buffer at given position - it must be verified before read + /// Position of data in the Byte Buffer + /// Return the VOffset Value (Short type - 2 bytes) in pos + private short ReadVOffsetT(int pos) + { + return _buf.Get(pos); + } + + /// Get table data area absolute offset from vtable. Result is the absolute buffer offset. + /// The result value offset cannot be '0' (pointing to itself) so after validation this method returns '0' + /// value as a marker for missing optional entry + /// Table Position value in the Byte Buffer + /// offset value in the Table + /// Return the absolute UOffset Value + private uint GetVOffset(uint tablePos, short vtableOffset) + { + var relPos = TableOperations.GetOffset(vtableOffset, (int)tablePos, _buf); + return relPos != 0 ? tablePos + (uint)relPos : 0; + } + + /// Check flatbuffer complexity (tables depth, elements counter and so on) + /// If complexity is too high function returns false as verification error + private bool CheckComplexity() + { + return (_depth <= _options.MaxDepth) && (_numTables <= _options.MaxTables); + } + + /// Check alignment of element. + /// Return True when alignment of the element is correct + private bool CheckAlignment(uint element, ulong align) + { + return ((element & (align - 1)) == 0) || (!_options.AlignmentCheck); + } + + /// Check if element is valid in buffer area. + /// Value defines the offset/position to element + /// Size of element + /// Return True when Element is correct + private bool CheckElement(uint pos, ulong elementSize) + { + return (elementSize < (ulong)_buf.Length) && + (pos <= ((uint)_buf.Length - elementSize)); + } + /// Check if element is a valid scalar. + /// Value defines the offset to scalar + /// Size of element + /// Return True when Scalar Element is correct + private bool CheckScalar(uint pos, ulong elementSize) + { + return CheckAlignment(pos, elementSize) && CheckElement(pos, elementSize); + } + + private CheckElementStruct CheckVectorOrString(uint pos, ulong elementSize) + { + var result = new CheckElementStruct + { + elementValid = false, + elementOffset = 0 + }; + + uint vectorPos = pos; + // Check we can read the vector/string size field (it is of uoffset size) + if (!CheckScalar(vectorPos, SIZE_U_OFFSET)) + { + // result.elementValid = false; result.elementOffset = 0; + return result; + } + // Check the whole array. If this is a string, the byte past the array + // must be 0. + uint size = ReadUOffsetT(vectorPos); + ulong max_elements = FLATBUFFERS_MAX_BUFFER_SIZE / elementSize; + if (size >= max_elements) + { + // Protect against byte_size overflowing. + // result.elementValid = false; result.elementOffset = 0; + return result; + } + + uint bytes_size = SIZE_U_OFFSET + ((uint)elementSize * size); + uint buffer_end_pos = vectorPos + bytes_size; + result.elementValid = CheckElement(vectorPos, bytes_size); + result.elementOffset = buffer_end_pos; + return result; + } + + /// Verify a string at given position. + private bool CheckString(uint pos) + { + var result = CheckVectorOrString(pos, SIZE_BYTE); + if (_options.StringEndCheck) + { + result.elementValid = result.elementValid && CheckScalar(result.elementOffset, 1); // Must have terminator + result.elementValid = result.elementValid && (_buf.GetSbyte((int)result.elementOffset) == 0); // Terminating byte must be 0. + } + return result.elementValid; + } + + /// Verify the vector of elements of given size + private bool CheckVector(uint pos, ulong elementSize) + { + var result = CheckVectorOrString(pos, elementSize); + return result.elementValid; + } + + /// String check wrapper function to be used in vector of strings check + private static bool CheckStringFunc(ref Verifier verifier, uint pos) + { + return verifier.CheckString(pos); + } + + /// Check vector of objects. Use generated object verification function + private bool CheckVectorOfObjects(uint pos, VerifyTableAction verifyAction) + { + if (!CheckVector(pos, SIZE_U_OFFSET)) + { + return false; + } + uint size = ReadUOffsetT(pos); + // Vector data starts just after vector size/length + uint vecStart = pos + SIZE_U_OFFSET; + // Iterate offsets and verify referenced objects + for (uint i = 0; i < size; i++) + { + uint vecOff = vecStart + (i * SIZE_U_OFFSET); + if (!CheckIndirectOffset(vecOff)) + { + return false; + } + uint objOffset = GetIndirectOffset(vecOff); + if (!verifyAction(ref this, objOffset)) + { + return false; + } + } + return true; + } + + /// Check if the offset referenced by offsetPos is the valid offset pointing to buffer + // offsetPos - offset to offset data + private bool CheckIndirectOffset(uint pos) + { + // Check the input offset is valid + if (!CheckScalar(pos, SIZE_U_OFFSET)) + { + return false; + } + // Get indirect offset + uint offset = ReadUOffsetT(pos); + // May not point to itself neither wrap around (buffers are max 2GB) + if ((offset == 0) || (offset >= FLATBUFFERS_MAX_BUFFER_SIZE)) + { + return false; + } + // Must be inside the buffer + return CheckElement(pos + offset, 1); + } + + /// Check flatbuffer content using generated object verification function + private bool CheckBufferFromStart(string identifier, uint startPos, VerifyTableAction verifyAction) + { + if (!string.IsNullOrEmpty(identifier) && + ((_buf.Length < (SIZE_U_OFFSET + FILE_IDENTIFIER_LENGTH)) || (!BufferHasIdentifier(startPos, identifier)))) + { + return false; + } + if (!CheckIndirectOffset(startPos)) + { + return false; + } + uint offset = GetIndirectOffset(startPos); + return verifyAction(ref this, offset); // && GetComputedSize() + } + + /// Get indirect offset. It is an offset referenced by offset Pos + private uint GetIndirectOffset(uint pos) + { + return (uint)TableOperations.GetIndirect((int)pos, _buf); + } + + /// Verify beginning of table + /// Position in the Table + /// Return True when the verification of the beginning of the table is passed + // (this method is used internally by generated verification functions) + public bool VerifyTableStart(uint tablePos) + { + // Starting new table verification increases complexity of structure + _depth++; + _numTables++; + + if (!CheckScalar(tablePos, SIZE_S_OFFSET)) + { + return false; + } + uint vtable = (uint)(tablePos - ReadSOffsetT((int)tablePos)); + return CheckComplexity() && + CheckScalar(vtable, SIZE_V_OFFSET) && + CheckAlignment((uint)ReadVOffsetT((int)vtable), SIZE_V_OFFSET) && + CheckElement(vtable, (ulong)ReadVOffsetT((int)vtable)); + } + + /// Verify end of table. In practice, this function does not check buffer but handles + /// verification statistics update + /// Position in the Table + /// Return True when the verification of the Table End is passed + // (this method is used internally by generated verification functions) + public bool VerifyTableEnd(uint tablePos) + { + _depth--; + return true; + } + + /// Verifiy static/inlined data area field + /// Position in the Table + /// Offset to the static/inlined data element + /// Size of the element + /// Alignment bool value + /// Required Value when the offset == 0 + /// Return True when the verification of the static/inlined data element is passed + // (this method is used internally by generated verification functions) + public bool VerifyField(uint tablePos, short offsetId, ulong elementSize, ulong align, bool required) + { + uint offset = GetVOffset(tablePos, offsetId); + if (offset != 0) + { + return CheckAlignment(offset, align) && CheckElement(offset, elementSize); + } + return !required; // it is OK if field is not required + } + + /// Verify string + /// Position in the Table + /// Offset to the String element + /// Required Value when the offset == 0 + /// Return True when the verification of the String is passed + // (this method is used internally by generated verification functions) + public bool VerifyString(uint tablePos, short vOffset, bool required) + { + var offset = GetVOffset(tablePos, vOffset); + if (offset == 0) + { + return !required; + } + if (!CheckIndirectOffset(offset)) + { + return false; + } + var strOffset = GetIndirectOffset(offset); + return CheckString(strOffset); + } + + /// Verify vector of fixed size structures and scalars + /// Position in the Table + /// Offset to the Vector of Data + /// Size of the element + /// Required Value when the offset == 0 + /// Return True when the verification of the Vector of Data passed + // (this method is used internally by generated verification functions) + public bool VerifyVectorOfData(uint tablePos, short vOffset, ulong elementSize, bool required) + { + var offset = GetVOffset(tablePos, vOffset); + if (offset == 0) + { + return !required; + } + if (!CheckIndirectOffset(offset)) + { + return false; + } + var vecOffset = GetIndirectOffset(offset); + return CheckVector(vecOffset, elementSize); + } + + /// Verify array of strings + /// Position in the Table + /// Offset to the Vector of String + /// Required Value when the offset == 0 + /// Return True when the verification of the Vector of String passed + // (this method is used internally by generated verification functions) + public bool VerifyVectorOfStrings(uint tablePos, short offsetId, bool required) + { + var offset = GetVOffset(tablePos, offsetId); + if (offset == 0) + { + return !required; + } + if (!CheckIndirectOffset(offset)) + { + return false; + } + var vecOffset = GetIndirectOffset(offset); + return CheckVectorOfObjects(vecOffset, CheckStringFunc); + } + + /// Verify vector of tables (objects). Tables are verified using generated verifyObjFunc + /// Position in the Table + /// Offset to the Vector of Table + /// Method used to the verification Table + /// Required Value when the offset == 0 + /// Return True when the verification of the Vector of Table passed + // (this method is used internally by generated verification functions) + public bool VerifyVectorOfTables(uint tablePos, short offsetId, VerifyTableAction verifyAction, bool required) + { + var offset = GetVOffset(tablePos, offsetId); + if (offset == 0) + { + return !required; + } + if (!CheckIndirectOffset(offset)) + { + return false; + } + var vecOffset = GetIndirectOffset(offset); + return CheckVectorOfObjects(vecOffset, verifyAction); + } + + /// Verify table object using generated verification function. + /// Position in the Table + /// Offset to the Table + /// Method used to the verification Table + /// Required Value when the offset == 0 + /// Return True when the verification of the Table passed + // (this method is used internally by generated verification functions) + public bool VerifyTable(uint tablePos, short offsetId, VerifyTableAction verifyAction, bool required) + { + var offset = GetVOffset(tablePos, offsetId); + if (offset == 0) + { + return !required; + } + if (!CheckIndirectOffset(offset)) + { + return false; + } + var tabOffset = GetIndirectOffset(offset); + return verifyAction(ref this, tabOffset); + } + + /// Verify nested buffer object. When verifyObjFunc is provided, it is used to verify object structure. + /// Position in the Table + /// Offset to the Table + /// Method used to the verification Table + /// Required Value when the offset == 0 + /// Return True when the verification of the nested buffer passed + // (this method is used internally by generated verification functions) + public bool VerifyNestedBuffer(uint tablePos, short offsetId, VerifyTableAction verifyAction, bool required) + { + var offset = GetVOffset(tablePos, offsetId); + if (offset == 0) + { + return !required; + } + uint vecOffset = GetIndirectOffset(offset); + if (!CheckVector(vecOffset, SIZE_BYTE)) + { + return false; + } + if (verifyAction != null) + { + var vecLength = ReadUOffsetT(vecOffset); + // Buffer begins after vector length + var vecStart = vecOffset + SIZE_U_OFFSET; + // Create nested buffer from part of Verify Buffer + var nestedByteBuffer = new ByteSpanBuffer(_buf.ToSpan((int)vecStart, (int)vecLength)); + var nestedVerifier = new Verifier(nestedByteBuffer, _options); + // There is no internal identifier - use empty one + if (!nestedVerifier.CheckBufferFromStart("", 0, verifyAction)) + { + return false; + } + } + return true; + } + + /// Verifiy static/inlined data area at absolute offset + /// Position of static/inlined data area in the Byte Buffer + /// Size of the union data + /// Alignment bool value + /// Return True when the verification of the Union Data is passed + // (this method is used internally by generated verification functions) + public bool VerifyUnionData(uint pos, ulong elementSize, ulong align) + { + bool result = CheckAlignment(pos, align) && CheckElement(pos, elementSize); + return result; + } + + /// Verify string referenced by absolute offset value + /// Position of Union String in the Byte Buffer + /// Return True when the verification of the Union String is passed + // (this method is used internally by generated verification functions) + public bool VerifyUnionString(uint pos) + { + bool result = CheckString(pos); + return result; + } + + /// Method verifies union object using generated verification function + /// Position in the Table + /// Offset in the Table + /// Offset to Element + /// Verification Method used for Union + /// Required Value when the offset == 0 + /// Return True when the verification of the Union passed + // (this method is used internally by generated verification functions) + public bool VerifyUnion(uint tablePos, short typeIdVOffset, short valueVOffset, VerifyUnionAction verifyAction, bool required) + { + // Check the union type index + var offset = GetVOffset(tablePos, typeIdVOffset); + if (offset == 0) + { + return !required; + } + if (!(CheckAlignment(offset, SIZE_BYTE) && CheckElement(offset, SIZE_BYTE))) + { + return false; + } + // Take type id + var typeId = _buf.Get((int)offset); + // Check union data + offset = GetVOffset(tablePos, valueVOffset); + if (offset == 0) + { + // When value data is not present, allow union verification function to deal with illegal offset + return verifyAction(ref this, typeId, (uint)_buf.Length); + } + if (!CheckIndirectOffset(offset)) + { + return false; + } + // Take value offset and validate union structure + uint unionOffset = GetIndirectOffset(offset); + return verifyAction(ref this, typeId, unionOffset); + } + + /// Verify vector of unions (objects). Unions are verified using generated verifyObjFunc + /// Position of the Table + /// Offset in the Table (Union type id) + /// Offset to vector of Data Stucture offset + /// Verification Method used for Union + /// Required Value when the offset == 0 + /// Return True when the verification of the Vector of Unions passed + // (this method is used internally by generated verification functions) + public bool VerifyVectorOfUnion(uint tablePos, short typeOffsetId, short offsetId, VerifyUnionAction verifyAction, bool required) + { + // type id offset must be valid + var offset = GetVOffset(tablePos, typeOffsetId); + if (offset == 0) + { + return !required; + } + if (!CheckIndirectOffset(offset)) + { + return false; + } + // Get type id table absolute offset + var typeIdVectorOffset = GetIndirectOffset(offset); + // values offset must be valid + offset = GetVOffset(tablePos, offsetId); + if (!CheckIndirectOffset(offset)) + { + return false; + } + var valueVectorOffset = GetIndirectOffset(offset); + // validate referenced vectors + if (!CheckVector(typeIdVectorOffset, SIZE_BYTE) || + !CheckVector(valueVectorOffset, SIZE_U_OFFSET)) + { + return false; + } + // Both vectors should have the same length + var typeIdVectorLength = ReadUOffsetT(typeIdVectorOffset); + var valueVectorLength = ReadUOffsetT(valueVectorOffset); + if (typeIdVectorLength != valueVectorLength) + { + return false; + } + // Verify each union from vectors + var typeIdStart = typeIdVectorOffset + SIZE_U_OFFSET; + var valueStart = valueVectorOffset + SIZE_U_OFFSET; + for (uint i = 0; i < typeIdVectorLength; i++) + { + // Get type id + byte typeId = _buf.Get((int)(typeIdStart + i * SIZE_BYTE)); + // get offset to vector item + uint off = valueStart + i * SIZE_U_OFFSET; + // Check the vector item has a proper offset + if (!CheckIndirectOffset(off)) + { + return false; + } + uint valueOffset = GetIndirectOffset(off); + // Verify object + if (!verifyAction(ref this, typeId, valueOffset)) + { + return false; + } + } + return true; + } + + // Method verifies flatbuffer data using generated Table verification function. + // The data buffer is already provided when creating [Verifier] object (see [NewVerifier]) + // + // - identifier - the expected identifier of buffer data. + // When empty identifier is provided the identifier validation is skipped. + // - sizePrefixed - this flag should be true when buffer is prefixed with content size + // - verifyObjFunc - function to be used for verification. This function is generated by compiler and included in each table definition file with name "Verify" + // + // Example: + // + // /* Verify Monster table. Ignore buffer name and assume buffer does not contain data length prefix */ + // isValid = verifier.verifyBuffer(bb, false, MonsterVerify) + // + // /* Verify Monster table. Buffer name is 'MONS' and contains data length prefix */ + // isValid = verifier.verifyBuffer("MONS", true, MonsterVerify) + /// Method verifies flatbuffer data using generated Table verification function + /// + /// The expected identifier of buffer data + /// Flag should be true when buffer is prefixed with content size + /// Function to be used for verification. This function is generated by compiler and included in each table definition file + /// Return True when verification of FlatBuffer passed + /// + /// Example 1. Verify Monster table. Ignore buffer name and assume buffer does not contain data length prefix + /// isValid = verifier.VerifyBuffer(bb, false, MonsterVerify) + /// Example 2. Verify Monster table. Buffer name is 'MONS' and contains data length prefix + /// isValid = verifier.VerifyBuffer("MONS", true, MonsterVerify) + /// + public bool VerifyBuffer(string identifier, bool sizePrefixed, VerifyTableAction verifyAction) + { + // Reset counters - starting verification from beginning + _depth = 0; + _numTables = 0; + + var start = (uint)_buf.Position; + if (sizePrefixed) + { + start = (uint)_buf.Position + SIZE_PREFIX_LENGTH; + if (!CheckScalar((uint)_buf.Position, SIZE_PREFIX_LENGTH)) + { + return false; + } + uint size = ReadUOffsetT((uint)_buf.Position); + if (size != ((uint)_buf.Length - start)) + { + return false; + } + } + return CheckBufferFromStart(identifier, start, verifyAction); + } + } + +} diff --git a/net/FlatSpanBuffers/FlatSpanBufferBuilder.cs b/net/FlatSpanBuffers/FlatSpanBufferBuilder.cs new file mode 100644 index 00000000000..40822d5a78f --- /dev/null +++ b/net/FlatSpanBuffers/FlatSpanBufferBuilder.cs @@ -0,0 +1,358 @@ +/* + * Copyright 2014 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; +using System.Collections.Generic; + +namespace Google.FlatSpanBuffers +{ + /// + /// Responsible for building up and accessing a FlatBuffer formatted byte + /// array (via ByteSpanBuffer). + /// + public ref struct FlatSpanBufferBuilder + { + private ByteSpanBuffer _bb; + private BufferBuilder _builder; + + // The vtable for the current table + private Span _vtable; + // List of offsets of all vtables. + private Span _vtables; + + /// + /// Gets and sets a Boolean to disable the optimization when serializing + /// default values to a Table. + /// + /// In order to save space, fields that are set to their default value + /// don't get serialized into the buffer.S + /// + public bool ForceDefaults { get; set; } + + public int Offset => _builder.GetOffset(ref _bb); + + /// + /// Get the ByteBuffer representing the FlatBuffer. + /// + public ByteSpanBuffer DataBuffer => _bb; + + /// + /// Creates a FlatBufferBuilder backed by the provided ByteSpanBuffer. + /// Provide enough vtable workspace for expected table sizes, 16 is the traditional default. + /// + /// The ByteSpanBuffer to write to + public FlatSpanBufferBuilder(ByteSpanBuffer buffer, + Span vtableSpace, + Span vtableOffsetSpace) + { + _bb = buffer; + _builder = new BufferBuilder(buffer.Length, null); + buffer.Reset(); + + _vtable = vtableSpace; + _vtables = vtableOffsetSpace; + ForceDefaults = false; + } + + public FlatSpanBufferBuilder(ByteSpanBuffer buffer, + Span vtableSpace, + Span vtableOffsetSpace, + Dictionary sharedStringMap) + : this(buffer, vtableSpace, vtableOffsetSpace) + { + _builder.SetSharedStringCache(sharedStringMap); + } + + public ReadOnlySpan SizedReadOnlySpan() + { + return _bb.ToSizedReadOnlySpan(); + } + + /// + /// Reset the FlatBufferBuilder by purging all data that it holds. + /// + public void Clear() + { + _builder.Reset(ref _bb, _vtable); + } + + /// + /// Assign new ByteSpanBuffer and reset the FlatBufferBuilder by purging all data that it holds. + /// + public void Clear(ByteSpanBuffer buffer) + { + _bb = buffer; + Clear(); + } + + public void Pad(int size) + { + _builder.Pad(ref _bb, size); + } + + // Prepare to write an element of `size` after `additional_bytes` + // have been written, e.g. if you write a string, you need to align + // such the int length field is aligned to SIZEOF_INT, and the string + // data follows it directly. + // If all you need to do is align, `additional_bytes` will be 0. + public void Prep(int size, int additionalBytes) + { + _builder.Prep(ref _bb, size, additionalBytes); + } + + public void Put(T value) + where T : unmanaged + { + _builder.Put(ref _bb, value); + } + + public void Put(scoped ReadOnlySpan x) + where T : unmanaged + { + _builder.Put(ref _bb, x); + } + + public void Add(T value) + where T : unmanaged + { + _builder.Add(ref _bb, value); + } + + public void AddSpan(scoped ReadOnlySpan x) + where T : unmanaged + { + _builder.AddSpan(ref _bb, x); + } + + /// + /// Adds a value to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The unmanaged type to add + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// and is false, the value will be skipped. + /// The default value to compare the value against + public void Add(int o, T x, T d) + where T : unmanaged, IEquatable + { + _builder.AddToTable(ref _bb, _vtable, o, x, d, ForceDefaults); + } + + /// + /// Adds a nullable value to the Table at index `o` in its vtable + /// + /// The unmanaged type to add + /// The index into the vtable + /// The nullable value to put into the buffer. If it doesn't have a value + /// it will skip writing to the buffer. + public void Add(int o, T? x) + where T : unmanaged + { + _builder.AddToTable(ref _bb, _vtable, o, x); + } + + public void StartVector(int elemSize, int count, int alignment) + { + _builder.StartVector(ref _bb, elemSize, count, alignment); + } + + /// + /// Writes data necessary to finish a vector construction. + /// + public VectorOffset EndVector() + { + return _builder.EndVector(ref _bb); + } + + /// + /// Creates a vector of tables from a span of offsets + /// + /// Span of offsets of the tables. + public VectorOffset CreateVectorOfTables(scoped ReadOnlySpan> offsets) + where T : struct, allows ref struct + { + return _builder.CreateVectorOfTables(ref _bb, offsets); + } + + public void StartTable(int numfields) + { + _builder.StartTable(ref _bb, numfields, _vtable); + } + + public int EndTable() + { + return _builder.EndTable(ref _bb, _vtable, _vtables, out _); + } + + /// + /// Adds an offset, relative to where it will be written. + /// + /// The offset to add to the buffer. + public void AddOffset(int offset) + { + _builder.AddOffset(ref _bb, offset); + } + + /// + /// Adds a buffer offset to the Table at index `o` in its vtable using the value `x` and default `d` + /// + /// The index into the vtable + /// The value to put into the buffer. If the value is equal to the default + /// the value will be skipped. + /// The default value to compare the value against + public void AddOffset(int o, int x, int d) + { + _builder.AddOffsetToTable(ref _bb, _vtable, o, x, d); + } + + public void AddOffset(int o, TOffset x, int d) + where TOffset : IFlatBufferOffset + { + _builder.AddOffsetToTable(ref _bb, _vtable, o, x.Value, d); + } + + /// + /// Adds offsets, relative to where they will be written. + /// + /// The offsets to add to the buffer. + public void AddOffsetSpan(scoped ReadOnlySpan offsets) + { + _builder.AddOffsetSpan(ref _bb, offsets); + } + + /// + /// Adds typed offsets, relative to where they will be written. + /// + public void AddOffsetSpan(scoped ReadOnlySpan offsets) + where TOffset : IFlatBufferOffset + { + _builder.AddOffsetSpan(ref _bb, offsets); + } + + /// + /// Encode the string `s` in the buffer using UTF-8. + /// + /// The string to encode. + /// + /// The offset in the buffer where the encoded string starts. + /// + public StringOffset CreateString(scoped ReadOnlySpan s) + { + return _builder.CreateString(ref _bb, s); + } + + /// + /// Creates a string in the buffer from a Span containing + /// a UTF8 string. + /// + /// the UTF8 string to add to the buffer + /// + /// The offset in the buffer where the encoded string starts. + /// + public StringOffset CreateUTF8String(scoped ReadOnlySpan chars) + { + return _builder.CreateUTF8String(ref _bb, chars); + } + + /// + /// Store a string in the buffer, which can contain any binary data. + /// If a string with this exact contents has already been serialized before, + /// instead simply returns the offset of the existing string. + /// + /// The string to encode. + /// + /// The offset in the buffer where the encoded string starts. + /// + public StringOffset CreateSharedString(string s) + { + return _builder.CreateSharedString(ref _bb, s); + } + + // Structs are stored inline, so nothing additional is being added. + // `d` is always 0. + public void AddStruct(int voffset, int x, int d) + { + _builder.AddStruct(ref _bb, _vtable, voffset, x, d); + } + + // Structs are stored inline, so nothing additional is being added. + // `d` is always 0. + public void AddStruct(int o, TOffset x, int d) + where TOffset : IFlatBufferOffset + { + _builder.AddStruct(ref _bb, _vtable, o, x.Value, d); + } + + // This checks a required field has been set in a given table that has + // just been constructed. + public void Required(int table, int field) + { + _builder.ValidateRequiredField(ref _bb, table, field); + } + + /// + /// Finalize a buffer, pointing to the given `root_table`. + /// + /// + /// An offset to be added to the buffer. + /// + public void Finish(int rootTable) + { + _builder.Finish(ref _bb, rootTable); + } + + /// + /// Finalize a buffer, pointing to the given `rootTable`. + /// + /// + /// An offset to be added to the buffer. + /// + /// + /// A FlatBuffer file identifier to be added to the buffer before + /// `root_table`. + /// + public void Finish(int rootTable, string fileIdentifier) + { + _builder.FinishWithFileId(ref _bb, rootTable, fileIdentifier); + } + + /// + /// Finalize a buffer, pointing to the given `root_table`, with the size prefixed. + /// + /// + /// An offset to be added to the buffer. + /// + public void FinishSizePrefixed(int rootTable) + { + _builder.FinishWithSizePrefix(ref _bb, rootTable); + } + + /// + /// Finalize a buffer, pointing to the given `rootTable`, with the size prefixed. + /// + /// + /// An offset to be added to the buffer. + /// + /// + /// A FlatBuffer file identifier to be added to the buffer before + /// `root_table`. + /// + public void FinishSizePrefixed(int rootTable, string fileIdentifier) + { + _builder.FinishWithSizePrefix(ref _bb, rootTable, fileIdentifier); + } + } +} diff --git a/net/FlatSpanBuffers/FlatSpanBuffers.csproj b/net/FlatSpanBuffers/FlatSpanBuffers.csproj new file mode 100644 index 00000000000..b709e2b5b65 --- /dev/null +++ b/net/FlatSpanBuffers/FlatSpanBuffers.csproj @@ -0,0 +1,8 @@ + + + net10.0 + 25.2.10 + + true + + diff --git a/net/FlatSpanBuffers/IByteBuffer.cs b/net/FlatSpanBuffers/IByteBuffer.cs new file mode 100644 index 00000000000..dfe4e1d58dc --- /dev/null +++ b/net/FlatSpanBuffers/IByteBuffer.cs @@ -0,0 +1,40 @@ +/* + * Copyright 2014 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 Google.FlatSpanBuffers +{ + /// + /// Interface to expose select ByteBuffer operations to generic classes/functions. + /// Intent is NOT to use this to store a ByteBuffer as these are structs (avoid boxing) + /// + public interface IByteBuffer + { + int Position { get; set; } + int Length { get; } + public void Reset(); + ReadOnlySpan ToReadOnlySpan(int start, int length); + T Get(int offset) where T : unmanaged; + Span GetSpan(int offset, int length) where T : unmanaged; + ReadOnlySpan GetReadOnlySpan(int offset, int length) where T : unmanaged; + string GetStringUTF8(int startPos, int len); + void Put(int offset, T value) where T : unmanaged; + void PadBytes(int offset, int count); + void PutSpan(int offset, scoped ReadOnlySpan value) where T : unmanaged; + public void PutStringUTF8(int offset, scoped ReadOnlySpan value); + } +} diff --git a/net/FlatSpanBuffers/IFlatbufferObject.cs b/net/FlatSpanBuffers/IFlatbufferObject.cs new file mode 100644 index 00000000000..66acee393e7 --- /dev/null +++ b/net/FlatSpanBuffers/IFlatbufferObject.cs @@ -0,0 +1,38 @@ +/* + * Copyright 2014 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. + */ + +namespace Google.FlatSpanBuffers +{ + /// + /// This is the base for both structs and tables. + /// This creates API consistency for FlatBuffers using different types of IByteBuffer + /// + public interface IFlatbufferObject + where TBuffer : IByteBuffer, allows ref struct + { + void __init(int _i, TBuffer _bb); + + TBuffer ByteBuffer { get; } + } + + public interface IFlatbufferObject : IFlatbufferObject + { + } + + public interface IFlatbufferSpanObject : IFlatbufferObject + { + } +} diff --git a/net/FlatSpanBuffers/Offset.cs b/net/FlatSpanBuffers/Offset.cs new file mode 100644 index 00000000000..3c7a2ab5ea2 --- /dev/null +++ b/net/FlatSpanBuffers/Offset.cs @@ -0,0 +1,60 @@ +/* + * Copyright 2014 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. + */ + +namespace Google.FlatSpanBuffers +{ + public interface IFlatBufferOffset + { + public int Value { get; } + } + + /// + /// Offset class for typesafe assignments. + /// + public struct Offset : IFlatBufferOffset + where T : struct, allows ref struct + { + public int Value; + int IFlatBufferOffset.Value => Value; + + public Offset(int value) + { + Value = value; + } + } + + public struct StringOffset : IFlatBufferOffset + { + public int Value; + int IFlatBufferOffset.Value => Value; + + public StringOffset(int value) + { + Value = value; + } + } + + public struct VectorOffset : IFlatBufferOffset + { + public int Value; + int IFlatBufferOffset.Value => Value; + + public VectorOffset(int value) + { + Value = value; + } + } +} diff --git a/net/FlatSpanBuffers/Operations/BufferOperations.cs b/net/FlatSpanBuffers/Operations/BufferOperations.cs new file mode 100644 index 00000000000..f677e062b9a --- /dev/null +++ b/net/FlatSpanBuffers/Operations/BufferOperations.cs @@ -0,0 +1,159 @@ +/* + * Copyright 2026 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; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Google.FlatSpanBuffers.Operations +{ + // This class consolidates valid type checks and buffer read/write operations w/ big endian handling. + // Unsafe calls are used carefully here. WriteUnaligned and ReadUnaligned are 'ok' because we do bounds checks with span slices. + public static class BufferOperations + { + // The intent of this call is to validate type validity for the buffer operations. + // Expectation is that this call will be omitted by the JIT if the type is valid. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void ValidateType() + where T : unmanaged + { + // The unmanaged constraint includes the types flatbuffers supports, including enums. + // However, some undesirable types can pass this check (unmanaged structs). + // Use size as an additional validity check to keep most of the unsupported types out. + int size = Unsafe.SizeOf(); + if (size != 1 && size != 2 && size != 4 && size != 8) + ThrowNotSupported(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void ThrowNotSupported() + { + throw new NotSupportedException("Type not supported by buffer operations"); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SizeOf() + where T : unmanaged + { + ValidateType(); + return Unsafe.SizeOf(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Read(ReadOnlySpan buffer, int offset) + where T : unmanaged + { + ValidateType(); + var src = buffer.Slice(offset, Unsafe.SizeOf()); + T value = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(src)); + + if (!BitConverter.IsLittleEndian) + { + Span valueBytes = MemoryMarshal.AsBytes( + MemoryMarshal.CreateSpan(ref value, 1)); + valueBytes.Reverse(); + } + + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Write(Span buffer, int offset, T value) + where T : unmanaged + { + ValidateType(); + var dest = buffer.Slice(offset, Unsafe.SizeOf()); + Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(dest), value); + + if (!BitConverter.IsLittleEndian) + { + dest.Reverse(); + } + } + + public static Span ReadSpan(Span buffer, int offset, int length) + where T : unmanaged + { + ValidateType(); + var byteLength = Unsafe.SizeOf() * length; + var dataRead = buffer.Slice(offset, byteLength); + + if (!BitConverter.IsLittleEndian) + { + int size = Unsafe.SizeOf(); + if (size > 1) + { + Span reversed = new byte[dataRead.Length]; + dataRead.CopyTo(reversed); + + for (int i = 0; i < reversed.Length; i += size) + { + reversed.Slice(i, size).Reverse(); + } + + dataRead = reversed; + } + } + + return MemoryMarshal.Cast(dataRead); + } + + public static void WriteSpan(Span buffer, int offset, scoped ReadOnlySpan data) + where T : unmanaged + { + ValidateType(); + if (data.Length == 0) + return; + + ReadOnlySpan dataBytes = MemoryMarshal.AsBytes(data); + Span dest = buffer.Slice(offset, dataBytes.Length); + dataBytes.CopyTo(dest); + + if (!BitConverter.IsLittleEndian) + { + int size = Unsafe.SizeOf(); + if (size > 1) + { + for (int i = 0; i < dest.Length; i += size) + { + dest.Slice(i, size).Reverse(); + } + } + } + } + + // Created optimized version of 'Fill(0)' because FlatBuffers pads only a few bytes at a time. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void PadZeros(Span buffer) + { + // The Length keeps us safe with WriteUnaligned. + switch (buffer.Length) + { + case 0: return; + case 1: buffer[0] = 0; return; + case 2: Unsafe.WriteUnaligned(ref buffer[0], 0); return; + case 3: Unsafe.WriteUnaligned(ref buffer[0], 0); buffer[2] = 0; return; + case 4: Unsafe.WriteUnaligned(ref buffer[0], 0); return; + case 5: Unsafe.WriteUnaligned(ref buffer[0], 0); buffer[4] = 0; return; + case 6: Unsafe.WriteUnaligned(ref buffer[0], 0); Unsafe.WriteUnaligned(ref buffer[4], 0); return; + case 7: Unsafe.WriteUnaligned(ref buffer[0], 0); Unsafe.WriteUnaligned(ref buffer[4], 0); buffer[6] = 0; return; + default: + buffer.Fill(0); + return; + } + } + } +} diff --git a/net/FlatSpanBuffers/Operations/TableOperations.cs b/net/FlatSpanBuffers/Operations/TableOperations.cs new file mode 100644 index 00000000000..e303bf6af16 --- /dev/null +++ b/net/FlatSpanBuffers/Operations/TableOperations.cs @@ -0,0 +1,131 @@ +/* + * Copyright 2026 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 Google.FlatSpanBuffers.Operations +{ + public static class TableOperations + { + public static int GetOffset(int vtableOffset, int bbPos, TBuffer buffer) + where TBuffer : IByteBuffer, allows ref struct + { + int vtable = bbPos - buffer.Get(bbPos); + return vtableOffset < buffer.Get(vtable) ? buffer.Get(vtable + vtableOffset) : 0; + } + + public static int GetIndirect(int offset, TBuffer buffer) + where TBuffer : IByteBuffer, allows ref struct + { + return offset + buffer.Get(offset); + } + + public static string GetString(int offset, TBuffer buffer) + where TBuffer : IByteBuffer, allows ref struct + { + int stringOffset = buffer.Get(offset); + if (stringOffset == 0) + return null; + + offset += stringOffset; + var len = buffer.Get(offset); + var startPos = offset + sizeof(int); + return buffer.GetStringUTF8(startPos, len); + } + + public static Span GetStringBytes(int offset, TBuffer buffer) + where TBuffer : IByteBuffer, allows ref struct + { + int stringOffset = buffer.Get(offset); + if (stringOffset == 0) + return Span.Empty; + + offset += stringOffset; + var len = buffer.Get(offset); + var startPos = offset + sizeof(int); + return buffer.GetSpan(startPos, len); + } + + public static int GetVectorLength(int offset, int bbPos, TBuffer buffer) + where TBuffer : IByteBuffer, allows ref struct + { + offset += bbPos; + offset += buffer.Get(offset); + return buffer.Get(offset); + } + + public static int GetVectorStart(int offset, int bbPos, TBuffer buffer) + where TBuffer : IByteBuffer, allows ref struct + { + offset += bbPos; + return offset + buffer.Get(offset) + sizeof(int); // data starts after the length + } + + public static bool HasIdentifier(TBuffer buffer, string ident) + where TBuffer : IByteBuffer, allows ref struct + { + return HasIdentifier(buffer, ident, buffer.Position); + } + + public static bool HasIdentifier(TBuffer buffer, string ident, int startPos) + where TBuffer : IByteBuffer, allows ref struct + { + if (ident.Length != FlatBufferConstants.FileIdentifierLength) + throw new ArgumentException("FlatBuffers: file identifier must be length " + FlatBufferConstants.FileIdentifierLength, nameof(ident)); + + var idSpan = buffer.GetReadOnlySpan( + startPos + sizeof(int), FlatBufferConstants.FileIdentifierLength); + for (var i = 0; i < idSpan.Length; i++) + { + if (ident[i] != (char)idSpan[i]) + return false; + } + + return true; + } + + public static Span GetVectorAsSpan(int offset, int bbPos, TBuffer buffer) + where T : unmanaged + where TBuffer : IByteBuffer, allows ref struct + { + var o = GetOffset(offset, bbPos, buffer); + if (0 == o) + { + return new Span(); + } + + var pos = GetVectorStart(o, bbPos, buffer); + var len = GetVectorLength(o, bbPos, buffer); + return buffer.GetSpan(pos, len); + } + + public static T GetUnion(int offset, ByteBuffer buffer) + where T : struct, IFlatbufferObject + { + T t = new T(); + t.__init(GetIndirect(offset, buffer), buffer); + return t; + } + + public static T GetUnionSpan(int offset, ByteSpanBuffer buffer) + where T : struct, IFlatbufferSpanObject, allows ref struct + { + T t = new T(); + t.__init(GetIndirect(offset, buffer), buffer); + return t; + } + } +} \ No newline at end of file diff --git a/net/FlatSpanBuffers/RefStructNullable.cs b/net/FlatSpanBuffers/RefStructNullable.cs new file mode 100644 index 00000000000..ef6f967fbc6 --- /dev/null +++ b/net/FlatSpanBuffers/RefStructNullable.cs @@ -0,0 +1,42 @@ +/* + * Copyright 2014 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 Google.FlatSpanBuffers +{ + public readonly ref struct RefStructNullable + where T : struct, allows ref struct + { + public readonly bool HasValue { get; } + public readonly T Value { get; } + + public RefStructNullable() + { + HasValue = false; + Value = default; + } + + public RefStructNullable(T value) + { + HasValue = true; + Value = value; + } + + public T GetValueOrDefault() => Value; + public T GetValueOrDefault(T defaultValue) => HasValue ? Value : defaultValue; + } +} \ No newline at end of file diff --git a/net/FlatSpanBuffers/Struct.cs b/net/FlatSpanBuffers/Struct.cs new file mode 100644 index 00000000000..de6fd04e818 --- /dev/null +++ b/net/FlatSpanBuffers/Struct.cs @@ -0,0 +1,50 @@ +/* + * Copyright 2014 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. + */ + +namespace Google.FlatSpanBuffers +{ + /// + /// All structs in the generated code derive from this struct, and add their own accessors. + /// + public struct Struct + { + public readonly int bb_pos; + public readonly ByteBuffer bb; + + // Re-init the internal state with an external buffer and an offset within. + public Struct(int _i, ByteBuffer _bb) + { + bb = _bb; + bb_pos = _i; + } + } + + /// + /// All span-based structs in generated code derive from this type and add their own accessors. + /// + public ref struct StructSpan + { + public readonly int bb_pos; + public readonly ByteSpanBuffer bb; + + // Re-init the internal state with an external buffer and an offset within. + public StructSpan(int _i, ByteSpanBuffer _bb) + { + bb = _bb; + bb_pos = _i; + } + } +} diff --git a/net/FlatSpanBuffers/Table.cs b/net/FlatSpanBuffers/Table.cs new file mode 100644 index 00000000000..96fc43ac972 --- /dev/null +++ b/net/FlatSpanBuffers/Table.cs @@ -0,0 +1,137 @@ +/* + * Copyright 2014 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. + */ +/* + * This file contains the Table struct and functionality to handle FlatBuffer tables. + * Modifications by JT. + // removed:__vector_as_arraysegment + // Removed bb_pos and bb property getters. + */ + +using System; +using System.Text; +using System.Runtime.InteropServices; +using Google.FlatSpanBuffers.Operations; + +namespace Google.FlatSpanBuffers +{ + /// + /// All tables in the generated code derive from this struct, and add their own accessors. + /// + public struct Table + { + public readonly int bb_pos; + public readonly ByteBuffer bb; + + // Initializes the table view over a buffer and absolute table position. + public Table(int _i, ByteBuffer _bb) + { + bb = _bb; + bb_pos = _i; + } + + // Look up a field in the vtable, return an offset into the object, or 0 if the field is not + // present. + public int __offset(int vtableOffset) + => TableOperations.GetOffset(vtableOffset, bb_pos, bb); + + // Retrieve the relative offset stored at "offset" + public int __indirect(int offset) + => TableOperations.GetIndirect(offset, bb); + + // Create a .NET String from UTF-8 data stored inside the flatbuffer. + public string __string(int offset) + => TableOperations.GetString(offset, bb); + + // Get an encoded utf8 string as a Span of bytes. + public Span __string_utf8_bytes(int offset) + => TableOperations.GetStringBytes(offset, bb); + + // Get the length of a vector whose offset is stored at "offset" in this object. + public int __vector_len(int offset) + => TableOperations.GetVectorLength(offset, bb_pos, bb); + + // Get the start of data of a vector whose offset is stored at "offset" in this object. + public int __vector(int offset) + => TableOperations.GetVectorStart(offset, bb_pos, bb); + + // Get the data of a vector whose offset is stored at "offset" in this object as a + // Span. Returns an empty span if the vector is not present in the ByteBuffer. + public Span __vector_as_span(int offset) + where T : unmanaged + => TableOperations.GetVectorAsSpan(offset, bb_pos, bb); + + // Initialize any Table-derived type to point to the union at the given offset. + public T __union(int offset) where T : struct, IFlatbufferObject + => TableOperations.GetUnion(offset, bb); + + public static bool __has_identifier(ByteBuffer bb, string ident) + => TableOperations.HasIdentifier(bb, ident); + } + + /// + /// All tables in the generated code derive from this struct, and add their own accessors. + /// + public ref struct TableSpan + { + public readonly int bb_pos; + public readonly ByteSpanBuffer bb; + + // Initializes the table view over a buffer and absolute table position. + public TableSpan(int _i, ByteSpanBuffer _bb) + { + bb = _bb; + bb_pos = _i; + } + + // Look up a field in the vtable, return an offset into the object, or 0 if the field is not + // present. + public int __offset(int vtableOffset) + => TableOperations.GetOffset(vtableOffset, bb_pos, bb); + + // Retrieve the relative offset stored at "offset" + public int __indirect(int offset) + => TableOperations.GetIndirect(offset, bb); + + // Create a .NET String from UTF-8 data stored inside the flatbuffer. + public string __string(int offset) + => TableOperations.GetString(offset, bb); + + // Get an encoded utf8 string as a Span of bytes. + public Span __string_utf8_bytes(int offset) + => TableOperations.GetStringBytes(offset, bb); + + // Get the length of a vector whose offset is stored at "offset" in this object. + public int __vector_len(int offset) + => TableOperations.GetVectorLength(offset, bb_pos, bb); + + // Get the start of data of a vector whose offset is stored at "offset" in this object. + public int __vector(int offset) + => TableOperations.GetVectorStart(offset, bb_pos, bb); + + // Get the data of a vector whose offset is stored at "offset" in this object as a + // Span. Returns an empty span if the vector is not present in the ByteBuffer. + public Span __vector_as_span(int offset) + where T : unmanaged + => TableOperations.GetVectorAsSpan(offset, bb_pos, bb); + + // Initialize any Table-derived type to point to the union at the given offset. + public T __union(int offset) where T : struct, IFlatbufferSpanObject, allows ref struct + => TableOperations.GetUnionSpan(offset, bb); + + public static bool __has_identifier(ByteSpanBuffer bb, string ident) + => TableOperations.HasIdentifier(bb, ident); + } +} diff --git a/net/FlatSpanBuffers/Utils/ByteBufferUtil.cs b/net/FlatSpanBuffers/Utils/ByteBufferUtil.cs new file mode 100644 index 00000000000..06c86fdb526 --- /dev/null +++ b/net/FlatSpanBuffers/Utils/ByteBufferUtil.cs @@ -0,0 +1,45 @@ +/* + * 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 Google.FlatSpanBuffers.Utils +{ + /// + /// Class that collects utility functions around `ByteBuffer`. + /// + public static class ByteBufferUtil + { + // Extract the size prefix from a `ByteBuffer`. + public static int GetSizePrefix(this TBuffer bb) + where TBuffer : struct, IByteBuffer + { + return bb.Get(bb.Position); + } + + // Advance the position of the buffer past the size prefix. + public static void RemoveSizePrefix(this ref TBuffer bb) + where TBuffer : struct, IByteBuffer + { + bb.Position += FlatBufferConstants.SizePrefixLength; + } + + public static ByteSpanBuffer ToSizedByteSpanBuffer(this ByteBuffer bb) + { + return new ByteSpanBuffer(bb.ToSizedSpan()); + } + } +} diff --git a/net/FlatSpanBuffers/Utils/ObjectApiUtil.cs b/net/FlatSpanBuffers/Utils/ObjectApiUtil.cs new file mode 100644 index 00000000000..8f601dc32ed --- /dev/null +++ b/net/FlatSpanBuffers/Utils/ObjectApiUtil.cs @@ -0,0 +1,43 @@ +/* + * Copyright 2026 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.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Google.FlatSpanBuffers.Utils +{ + public static class ObjectApiUtil + { + public static void ResizeList(List list, int count) + { + if (list.Count == count) + return; + + if (count < list.Count) + { + CollectionsMarshal.SetCount(list, count); + } + else + { + // Set capacity first to avoid exposing uninitialized data. + if (list.Capacity < count) + list.Capacity = count; + + CollectionsMarshal.SetCount(list, count); + } + } + } +} diff --git a/net/FlatSpanBuffers/Utils/RefStructSorters.cs b/net/FlatSpanBuffers/Utils/RefStructSorters.cs new file mode 100644 index 00000000000..1a273543f00 --- /dev/null +++ b/net/FlatSpanBuffers/Utils/RefStructSorters.cs @@ -0,0 +1,183 @@ +/* + * Copyright 2026 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; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace Google.FlatSpanBuffers.Utils +{ + // Custom sorting implementation that avoids boxing when + // using Span.Sort() with ref struct comparers. + public static class RefStructSorters + { + private const int InsertionSortThreshold = 16; + private const int MaxStackDepth = 64; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Sort(scoped Span span, ref TComparer comparer) + where TComparer : IComparer, allows ref struct + { + if (span.Length <= 1) + return; + + if (span.Length <= InsertionSortThreshold) + { + InsertionSort(span, ref comparer); + } + else + { + IntroSort(span, ref comparer); + } + } + + private static void IntroSort(scoped Span span, ref TComparer comparer) + where TComparer : IComparer, allows ref struct + { + Span<(int low, int high)> stack = stackalloc (int, int)[MaxStackDepth]; + int stackSize = 0; + + stack[stackSize++] = (0, span.Length - 1); + + while (stackSize > 0) + { + var (low, high) = stack[--stackSize]; + if (high <= low) + continue; + + int size = high - low + 1; + if (size <= InsertionSortThreshold) + { + InsertionSort(span.Slice(low, size), ref comparer); + continue; + } + + if (stackSize >= MaxStackDepth - 2) + { + HeapSort(span.Slice(low, size), ref comparer); + continue; + } + + int pivotIndex = Partition(span, low, high, ref comparer); + int leftSize = pivotIndex - low; + int rightSize = high - pivotIndex; + + if (leftSize > rightSize) + { + if (leftSize > 1) + stack[stackSize++] = (low, pivotIndex - 1); + if (rightSize > 1) + stack[stackSize++] = (pivotIndex + 1, high); + } + else + { + if (rightSize > 1) + stack[stackSize++] = (pivotIndex + 1, high); + if (leftSize > 1) + stack[stackSize++] = (low, pivotIndex - 1); + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void InsertionSort(scoped Span span, ref TComparer comparer) + where TComparer : IComparer, allows ref struct + { + for (int i = 1; i < span.Length; i++) + { + T key = span[i]; + int j = i - 1; + while (j >= 0 && comparer.Compare(span[j], key) > 0) + { + span[j + 1] = span[j]; + j--; + } + span[j + 1] = key; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int Partition(scoped Span span, int low, int high, ref TComparer comparer) + where TComparer : IComparer, allows ref struct + { + // Median of three pivot selection + int mid = low + (high - low) / 2; + + if (comparer.Compare(span[mid], span[low]) < 0) + Swap(ref span[low], ref span[mid]); + if (comparer.Compare(span[high], span[low]) < 0) + Swap(ref span[low], ref span[high]); + if (comparer.Compare(span[high], span[mid]) < 0) + Swap(ref span[mid], ref span[high]); + + Swap(ref span[mid], ref span[high]); + T pivot = span[high]; + int i = low - 1; + for (int j = low; j < high; j++) + { + if (comparer.Compare(span[j], pivot) <= 0) + { + i++; + Swap(ref span[i], ref span[j]); + } + } + + Swap(ref span[i + 1], ref span[high]); + return i + 1; + } + + private static void HeapSort(scoped Span span, ref TComparer comparer) + where TComparer : IComparer, allows ref struct + { + int n = span.Length; + + for (int i = n / 2 - 1; i >= 0; i--) + Heapify(span, i, n, ref comparer); + + for (int i = n - 1; i > 0; i--) + { + Swap(ref span[0], ref span[i]); + Heapify(span, 0, i, ref comparer); + } + } + + private static void Heapify(scoped Span span, int parent, int heapSize, ref TComparer comparer) + where TComparer : IComparer, allows ref struct + { + int largest = parent; + int left = 2 * parent + 1; + int right = 2 * parent + 2; + + if (left < heapSize && comparer.Compare(span[left], span[largest]) > 0) + largest = left; + + if (right < heapSize && comparer.Compare(span[right], span[largest]) > 0) + largest = right; + + if (largest != parent) + { + Swap(ref span[parent], ref span[largest]); + Heapify(span, largest, heapSize, ref comparer); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(ref T a, ref T b) + { + (a, b) = (b, a); + } + } +} diff --git a/net/FlatSpanBuffers/Utils/SortedVectorUtils.cs b/net/FlatSpanBuffers/Utils/SortedVectorUtils.cs new file mode 100644 index 00000000000..0e73e83b47a --- /dev/null +++ b/net/FlatSpanBuffers/Utils/SortedVectorUtils.cs @@ -0,0 +1,194 @@ +/* + * Copyright 2026 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; +using System.Buffers; +using System.Collections.Generic; +using static Google.FlatSpanBuffers.Operations.TableOperations; + +namespace Google.FlatSpanBuffers.Utils +{ + public static class SortedVectorUtils + { + private const int StackAllocBytesThreshold = 512; + + public static bool TryGetByKey(int vectorLocation, ReadOnlySpan key, scoped ref TBuffer bb, int fieldOffset, out T value) + where T : struct, IFlatbufferObject, allows ref struct + where TBuffer : IByteBuffer, allows ref struct + { + int maxByteCount = System.Text.Encoding.UTF8.GetByteCount(key); + byte[] rentedKeyBytes = null; + Span keyBytes = (maxByteCount <= StackAllocBytesThreshold) + ? stackalloc byte[maxByteCount] + : rentedKeyBytes = ArrayPool.Shared.Rent(maxByteCount); + + try + { + int bytesWritten = System.Text.Encoding.UTF8.GetBytes(key, keyBytes); + keyBytes = keyBytes.Slice(0, bytesWritten); + + int span = bb.Get(vectorLocation - 4); // FlatBuffers stores vector length 4 bytes before data. + int start = 0; + + while (span != 0) + { + int middle = span / 2; + int tableOffset = GetIndirect(vectorLocation + 4 * (start + middle), bb); + + // Get the string field + var fieldPos = GetOffset(fieldOffset, tableOffset, bb); + if (fieldPos == 0) + { + span = middle; + continue; + } + + var stringBytes = GetVectorAsSpan(fieldOffset, tableOffset, bb); + int comp = stringBytes.SequenceCompareTo(keyBytes); + + if (comp > 0) + { + span = middle; + } + else if (comp < 0) + { + middle++; + start += middle; + span -= middle; + } + else + { + value = new T(); + value.__init(tableOffset, bb); + return true; + } + } + + value = default; + return false; + } + finally + { + if (rentedKeyBytes != null) + ArrayPool.Shared.Return(rentedKeyBytes); + } + } + + public static bool TryGetByKey(int vectorLocation, TScalar key, scoped ref TBuffer bb, int fieldOffset, TScalar defaultValue, out T value) + where T : struct, IFlatbufferObject, allows ref struct + where TScalar : unmanaged, IComparable + where TBuffer : IByteBuffer, allows ref struct + { + int span = bb.Get(vectorLocation - 4); // FlatBuffers stores vector length 4 bytes before data. + int start = 0; + + while (span != 0) + { + int middle = span / 2; + int tableOffset = GetIndirect(vectorLocation + 4 * (start + middle), bb); + + // Get the scalar field value, use schema default if field not present + var fieldPos = GetOffset(fieldOffset, tableOffset, bb); + var fieldValue = fieldPos != 0 ? bb.Get(tableOffset + fieldPos) : defaultValue; + + int comp = fieldValue.CompareTo(key); + if (comp > 0) + { + span = middle; + } + else if (comp < 0) + { + middle++; + start += middle; + span -= middle; + } + else + { + value = new T(); + value.__init(tableOffset, bb); + return true; + } + } + + value = default; + return false; + } + + public ref struct ScalarOffsetComparer : IComparer> + where T : struct, allows ref struct + where TBuffer : IByteBuffer, allows ref struct + where TScalar : unmanaged, IComparable + { + public TBuffer bb; + public int fieldOffset; + + public ScalarOffsetComparer(TBuffer bb, int fieldOffset) + { + this.bb = bb; + this.fieldOffset = fieldOffset; + } + + public int Compare(Offset a, Offset b) + { + var posA = bb.Length - a.Value; + var fieldPosA = GetOffset(fieldOffset, posA, bb); + var posB = bb.Length - b.Value; + var fieldPosB = GetOffset(fieldOffset, posB, bb); + + if (fieldPosA == 0 && fieldPosB == 0) + return 0; + if (fieldPosA == 0) + return -1; + if (fieldPosB == 0) + return 1; + + return bb.Get(posA + fieldPosA).CompareTo(bb.Get(posB + fieldPosB)); + } + } + + public ref struct VectorOffsetComparer : IComparer> + where T : struct, allows ref struct + where TBuffer : IByteBuffer, allows ref struct + where TElement : unmanaged, IComparable + { + public TBuffer bb; + public int fieldOffset; + + public VectorOffsetComparer(TBuffer bb, int fieldOffset) + { + this.bb = bb; + this.fieldOffset = fieldOffset; + } + + public int Compare(Offset a, Offset b) + { + var posA = bb.Length - a.Value; + var fieldPosA = GetOffset(fieldOffset, posA, bb); + var posB = bb.Length - b.Value; + var fieldPosB = GetOffset(fieldOffset, posB, bb); + + if (fieldPosA == 0 && fieldPosB == 0) return 0; + if (fieldPosA == 0) return -1; + if (fieldPosB == 0) return 1; + + var spanA = GetVectorAsSpan(fieldOffset, posA, bb); + var spanB = GetVectorAsSpan(fieldOffset, posB, bb); + + return spanA.SequenceCompareTo(spanB); + } + } + } +} diff --git a/net/FlatSpanBuffers/Vectors/StringVector.cs b/net/FlatSpanBuffers/Vectors/StringVector.cs new file mode 100644 index 00000000000..b9a1e562d1c --- /dev/null +++ b/net/FlatSpanBuffers/Vectors/StringVector.cs @@ -0,0 +1,59 @@ +/* + * Copyright 2026 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; +using Google.FlatSpanBuffers.Operations; + +namespace Google.FlatSpanBuffers.Vectors +{ + public struct StringVector + { + private VectorData _data; + + public bool IsEmpty => _data.IsEmpty; + public int Length => _data.Length; + + public StringVector(Table p, int offset) + { + _data = new VectorData(p, offset, 4); + } + + public string this[int index] + => TableOperations.GetString(_data.GetBufferIndex(index), _data.bb); + + public ReadOnlySpan GetBytes(int index) + => TableOperations.GetStringBytes(_data.GetBufferIndex(index), _data.bb); + } + + public ref struct StringVectorSpan + { + private VectorSpanData _data; + + public bool IsEmpty => _data.IsEmpty; + public int Length => _data.Length; + + public StringVectorSpan(TableSpan p, int offset) + { + _data = new VectorSpanData(p, offset, 4); + } + + public string this[int index] + => TableOperations.GetString(_data.GetBufferIndex(index), _data.bb); + + public ReadOnlySpan GetBytes(int index) + => TableOperations.GetStringBytes(_data.GetBufferIndex(index), _data.bb); + } +} \ No newline at end of file diff --git a/net/FlatSpanBuffers/Vectors/StructVector.cs b/net/FlatSpanBuffers/Vectors/StructVector.cs new file mode 100644 index 00000000000..b3625ac5b64 --- /dev/null +++ b/net/FlatSpanBuffers/Vectors/StructVector.cs @@ -0,0 +1,70 @@ +/* + * Copyright 2026 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 Google.FlatSpanBuffers.Vectors +{ + public struct StructVector + where T : struct, IFlatbufferObject + { + private VectorData _data; + + public bool IsEmpty => _data.IsEmpty; + public int Length => _data.Length; + + public StructVector(Table p, int offset, int elementSize) + { + _data = new VectorData(p, offset, elementSize); + } + + public T this[int index] + { + get + { + int pos = _data.GetBufferIndex(index); + var element = new T(); + element.__init(pos, _data.bb); + return element; + } + } + } + + public ref struct StructVectorSpan + where T : struct, IFlatbufferSpanObject, allows ref struct + { + private VectorSpanData _data; + + public bool IsEmpty => _data.IsEmpty; + public int Length => _data.Length; + + public StructVectorSpan(TableSpan p, int offset, int elementSize) + { + _data = new VectorSpanData(p, offset, elementSize); + } + + public T this[int index] + { + get + { + int pos = _data.GetBufferIndex(index); + var element = new T(); + element.__init(pos, _data.bb); + return element; + } + } + } +} \ No newline at end of file diff --git a/net/FlatSpanBuffers/Vectors/TableVector.cs b/net/FlatSpanBuffers/Vectors/TableVector.cs new file mode 100644 index 00000000000..124ddcb93cf --- /dev/null +++ b/net/FlatSpanBuffers/Vectors/TableVector.cs @@ -0,0 +1,71 @@ +/* + * Copyright 2026 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; +using Google.FlatSpanBuffers.Operations; + +namespace Google.FlatSpanBuffers.Vectors +{ + public struct TableVector + where T : struct, IFlatbufferObject + { + private VectorData _data; + + public bool IsEmpty => _data.IsEmpty; + public int Length => _data.Length; + + public TableVector(in Table p, int offset, int elementSize) + { + _data = new VectorData(p, offset, elementSize); + } + + public T this[int index] + { + get + { + int pos = TableOperations.GetIndirect(_data.GetBufferIndex(index), _data.bb); + var element = new T(); + element.__init(pos, _data.bb); + return element; + } + } + } + + public ref struct TableVectorSpan + where T : struct, IFlatbufferSpanObject, allows ref struct + { + private VectorSpanData _data; + + public bool IsEmpty => _data.IsEmpty; + public int Length => _data.Length; + + public TableVectorSpan(TableSpan p, int offset, int elementSize) + { + _data = new VectorSpanData(p, offset, elementSize); + } + + public T this[int index] + { + get + { + int pos = TableOperations.GetIndirect(_data.GetBufferIndex(index), _data.bb); + var element = new T(); + element.__init(pos, _data.bb); + return element; + } + } + } +} diff --git a/net/FlatSpanBuffers/Vectors/UnionVector.cs b/net/FlatSpanBuffers/Vectors/UnionVector.cs new file mode 100644 index 00000000000..ad0bad363a2 --- /dev/null +++ b/net/FlatSpanBuffers/Vectors/UnionVector.cs @@ -0,0 +1,67 @@ +/* + * Copyright 2026 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; +using Google.FlatSpanBuffers.Operations; + +namespace Google.FlatSpanBuffers.Vectors +{ + public struct UnionVector + { + private VectorData _data; + + public bool IsEmpty => _data.IsEmpty; + public int Length => _data.Length; + + public UnionVector(Table p, int offset, int elementSize) + { + _data = new VectorData(p, offset, elementSize); + } + + public T GetAs(int index) + where T : struct, IFlatbufferObject + => TableOperations.GetUnion(_data.GetBufferIndex(index), _data.bb); + + public string GetAsString(int index) + => TableOperations.GetString(_data.GetBufferIndex(index), _data.bb); + + public Span GetAsStringBytes(int index) + => TableOperations.GetStringBytes(_data.GetBufferIndex(index), _data.bb); + } + + public ref struct UnionVectorSpan + { + private VectorSpanData _data; + + public bool IsEmpty => _data.IsEmpty; + public int Length => _data.Length; + + public UnionVectorSpan(TableSpan p, int offset, int elementSize) + { + _data = new VectorSpanData(p, offset, elementSize); + } + + public T GetAs(int index) + where T : struct, IFlatbufferSpanObject, allows ref struct + => TableOperations.GetUnionSpan(_data.GetBufferIndex(index), _data.bb); + + public string GetAsString(int index) + => TableOperations.GetString(_data.GetBufferIndex(index), _data.bb); + + public Span GetAsStringBytes(int index) + => TableOperations.GetStringBytes(_data.GetBufferIndex(index), _data.bb); + } +} \ No newline at end of file diff --git a/net/FlatSpanBuffers/Vectors/VectorData.cs b/net/FlatSpanBuffers/Vectors/VectorData.cs new file mode 100644 index 00000000000..d0325eacc61 --- /dev/null +++ b/net/FlatSpanBuffers/Vectors/VectorData.cs @@ -0,0 +1,85 @@ +/* + * Copyright 2026 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; +using System.Dynamic; + +namespace Google.FlatSpanBuffers.Vectors +{ + // Consolidate Vector bounds and bounds checks + public struct VectorData + { + public ByteBuffer bb; + public readonly int start; + public readonly int length; + public readonly int elementSize; + + public bool IsEmpty => length == 0; + public int Length => length; + + public VectorData(Table p, int offset, int elementSize) + { + if (offset == 0) + throw new Exception($"Flatbufffers: Invalid Offset"); + + bb = p.bb; + start = p.__vector(offset); + length = p.__vector_len(offset); + this.elementSize = elementSize; + } + + public int GetBufferIndex(int index) + { + // Using this bound check for consistency with Span indexed bounds checks. + // This would have fallen into the old 'AssertOffsetAndLength()'. + if ((uint)index >= (uint)length) + throw new IndexOutOfRangeException($"Flatbufffers: index out of range. index:{index} length: {length}"); + return start + index * elementSize; + } + } + + // Consolidate Vector bounds and bounds checks + public ref struct VectorSpanData + { + public ByteSpanBuffer bb; + public readonly int start; + public readonly int length; + public readonly int elementSize; + + public bool IsEmpty => length == 0; + public int Length => length; + + public VectorSpanData(TableSpan p, int offset, int elementSize) + { + if (offset == 0) + throw new Exception($"Flatbufffers: Invalid Offset"); + + bb = p.bb; + start = p.__vector(offset); + length = p.__vector_len(offset); + this.elementSize = elementSize; + } + + public int GetBufferIndex(int index) + { + // Using this bound check for consistency with Span indexed bounds checks. + // This would have fallen into the old 'AssertOffsetAndLength()'. + if ((uint)index >= (uint)length) + throw new IndexOutOfRangeException($"Flatbufffers: index out of range. index:{index} length: {length}"); + return start + index * elementSize; + } + } +} diff --git a/scripts/generate_code.py b/scripts/generate_code.py index a278ae28c50..619480dcae4 100755 --- a/scripts/generate_code.py +++ b/scripts/generate_code.py @@ -649,3 +649,106 @@ def flatc_annotate(schema, include=None, data=None, cwd=tests_path): # Run the generate_grpc_examples script generate_grpc_examples.GenerateGRPCExamples() + +# FlatSpanBuffers Tests +flatspanbuffers_fbs = "net/FlatSpanBuffers.GeneratedCode/fbs" +flatspanbuffers_gen = "net/FlatSpanBuffers.GeneratedCode/Generated" + +CS_SPANBUF_OPTS = ["--csharp-spanbufs", "--gen-object-api"] + +flatc( + CS_SPANBUF_OPTS, + prefix=flatspanbuffers_gen + "/key_test", + schema=flatspanbuffers_fbs + "/key_test.fbs", + cwd=root_path, +) + +flatc( + CS_SPANBUF_OPTS, + prefix=flatspanbuffers_gen + "/optional_scalars", + schema=flatspanbuffers_fbs + "/optional_scalars.fbs", + cwd=root_path, +) + +flatc( + CS_SPANBUF_OPTS, + prefix=flatspanbuffers_gen + "/keyword_test", + schema=flatspanbuffers_fbs + "/keyword_test.fbs", + cwd=root_path, +) + +flatc( + CS_SPANBUF_OPTS, + prefix=flatspanbuffers_gen + "/comprehensive_test", + schema=flatspanbuffers_fbs + "/comprehensive_test.fbs", + cwd=root_path, +) + +flatc( + CS_SPANBUF_OPTS + ["--gen-mutable"], + prefix=flatspanbuffers_gen + "/monster_test", + schema=flatspanbuffers_fbs + "/monster_test.fbs", + cwd=root_path, +) + +flatc( + CS_SPANBUF_OPTS + ["--gen-mutable", "--cs-gen-json-serializer"], + prefix=flatspanbuffers_gen + "/mygame_example", + schema=flatspanbuffers_fbs + "/mygame_example.fbs", + cwd=root_path, +) + +flatc( + CS_SPANBUF_OPTS + ["--cs-gen-json-serializer"], + prefix=flatspanbuffers_gen + "/arrays_test", + schema=flatspanbuffers_fbs + "/arrays_test.fbs", + cwd=root_path, +) + +flatc( + CS_SPANBUF_OPTS + ["--cs-gen-json-serializer"], + prefix=flatspanbuffers_gen + "/json_test", + schema=flatspanbuffers_fbs + "/json_test.fbs", + cwd=root_path, +) + +flatc( + CS_SPANBUF_OPTS + ["--cs-gen-json-serializer"], + prefix=flatspanbuffers_gen + "/union_vector", + schema=flatspanbuffers_fbs + "/union_vector.fbs", + cwd=root_path, +) + +# FlatSpanBuffers Benchmarks +benchmark_fbs = "net/FlatSpanBuffers.Benchmarks/fbs" +benchmark_gen = "net/FlatSpanBuffers.Benchmarks/Generated" + +flatc( + ["--csharp-spanbufs", "--gen-object-api", "--gen-mutable"], + prefix=benchmark_gen + "/FlatSpanBuffers", + schema=benchmark_fbs + "/benchmark.fbs", + cwd=root_path, +) + +flatc( + ["--csharp", "--gen-object-api"], + prefix=benchmark_gen + "/OriginalFlatBuffers", + schema=benchmark_fbs + "/benchmark.fbs", + cwd=root_path, +) + +# Benchmarks compare net/FlatBuffers (original) to net/FlatSpanBuffers. +# To avoid naming collisions, rename the namespaces in the original files. +original_benchmark_path = Path(root_path, benchmark_gen, "OriginalFlatBuffers") +for cs_file in original_benchmark_path.rglob("*.cs"): + content = cs_file.read_text(encoding="utf-8") + updated = content.replace("Benchmarks.FlatSpanBuffers", "Benchmarks.OriginalFlatBuffers") + if updated != content: + cs_file.write_text(updated, encoding="utf-8") + +original_src = Path(original_benchmark_path, "Benchmarks", "FlatSpanBuffers") +original_dst = Path(original_benchmark_path, "Benchmarks", "OriginalFlatBuffers") +if original_src.exists(): + if original_dst.exists(): + shutil.rmtree(original_dst) + shutil.move(str(original_src), str(original_dst)) diff --git a/src/flatc.cpp b/src/flatc.cpp index ee34044fdd1..98df3d9daa3 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -242,6 +242,9 @@ const static FlatCOption flatc_options[] = { {"", "cs-global-alias", "", "Prepend \"global::\" to all user generated csharp classes and " "structs."}, + {"", "csharp-spanbufs", "", + "Generate a span friendly variant of the C# code using the " + "Google.FlatSpanBuffers library."}, {"", "cs-gen-json-serializer", "", "Allows (de)serialization of JSON text in the Object API. (requires " "--gen-object-api)."}, diff --git a/src/flatc_main.cpp b/src/flatc_main.cpp index ce9b8c4a4ed..e01df9d4a14 100644 --- a/src/flatc_main.cpp +++ b/src/flatc_main.cpp @@ -26,6 +26,7 @@ #include "idl_gen_binary.h" #include "idl_gen_cpp.h" #include "idl_gen_csharp.h" +#include "idl_gen_csharp_spanbufs.h" #include "idl_gen_dart.h" #include "idl_gen_fbs.h" #include "idl_gen_go.h" @@ -100,6 +101,11 @@ int main(int argc, const char* argv[]) { "Generate C# classes for tables/structs"}, flatbuffers::NewCSharpCodeGenerator()); + flatc.RegisterCodeGenerator( + flatbuffers::FlatCOption{"ns", "csharp-spanbufs", "", + "Generate C# span friendly classes for tables/structs"}, + flatbuffers::NewCSharpSpanBufsCodeGenerator()); + flatc.RegisterCodeGenerator( flatbuffers::FlatCOption{"d", "dart", "", "Generate Dart classes for tables/structs"}, diff --git a/src/idl_gen_csharp_spanbufs.cpp b/src/idl_gen_csharp_spanbufs.cpp new file mode 100644 index 00000000000..512d418f73e --- /dev/null +++ b/src/idl_gen_csharp_spanbufs.cpp @@ -0,0 +1,3365 @@ +/* + * Copyright 2014 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. + */ + +// independent from idl_parser, since this code is not needed for most clients + +#include "idl_gen_csharp_spanbufs.h" + +#include + +#include "flatbuffers/code_generators.h" +#include "flatbuffers/flatbuffers.h" +#include "flatbuffers/idl.h" +#include "flatbuffers/util.h" + +namespace flatbuffers { + +static TypedFloatConstantGenerator CSharpFloatGen("Double.", "Single.", "NaN", + "PositiveInfinity", + "NegativeInfinity"); +static CommentConfig comment_config = { + nullptr, + "///", + nullptr, +}; + +namespace csharpspanbufs { + +// Generation mode determines which buffer type variant to generate +enum class GenerationMode { + // ByteBuffer code, heap allocated, growable, Span based accessors + ByteBuffer, + // Span code, ref structs with span buffers + SpanBuffer +}; + +class CSharpSpanBufsGenerator : public BaseGenerator { + struct FieldArrayLength { + std::string name; + int length; + }; + + GenerationMode gen_mode_; + + public: + CSharpSpanBufsGenerator(const Parser &parser, const std::string &path, + const std::string &file_name, + GenerationMode mode = GenerationMode::ByteBuffer) + : BaseGenerator(parser, path, file_name, + parser.opts.cs_global_alias ? "global::" : "", ".", "cs"), + gen_mode_(mode), + cur_name_space_(nullptr) { + // clang-format off + + // List of keywords retrieved from here: + // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ + + // One per line to ease comparisons to that list are easier + + static const char *const keywords[] = { + "abstract", + "as", + "base", + "bool", + "break", + "byte", + "case", + "catch", + "char", + "checked", + "class", + "const", + "continue", + "decimal", + "default", + "delegate", + "do", + "double", + "else", + "enum", + "event", + "explicit", + "extern", + "false", + "finally", + "fixed", + "float", + "for", + "foreach", + "goto", + "if", + "implicit", + "in", + "int", + "interface", + "internal", + "is", + "lock", + "long", + "namespace", + "new", + "null", + "object", + "operator", + "out", + "override", + "params", + "private", + "protected", + "public", + "readonly", + "ref", + "return", + "sbyte", + "sealed", + "short", + "sizeof", + "stackalloc", + "static", + "string", + "struct", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "uint", + "ulong", + "unchecked", + "unsafe", + "ushort", + "using", + "virtual", + "void", + "volatile", + "while", + nullptr, + // clang-format on + }; + + for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw); + } + + CSharpSpanBufsGenerator &operator=(const CSharpSpanBufsGenerator &); + + bool generateForCurrentMode() { + std::string one_file_code; + cur_name_space_ = parser_.current_namespace_; + + if (gen_mode_ == GenerationMode::ByteBuffer) { + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + std::string enumcode; + auto &enum_def = **it; + if (!parser_.opts.one_file) + cur_name_space_ = enum_def.defined_namespace; + GenEnum(enum_def, &enumcode, parser_.opts); + if (parser_.opts.one_file) { + one_file_code += enumcode; + } else { + if (!SaveType(enum_def.name, *enum_def.defined_namespace, enumcode, + false, parser_.opts)) + return false; + } + } + } + + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + std::string declcode; + auto &struct_def = **it; + if (!parser_.opts.one_file) + cur_name_space_ = struct_def.defined_namespace; + GenStruct(struct_def, &declcode, parser_.opts); + // Verifier is only generated for ByteBuffer mode, SpanMode version will + // simply call it. + if (gen_mode_ == GenerationMode::ByteBuffer) { + GenStructVerifier(struct_def, &declcode); + } + if (parser_.opts.one_file) { + one_file_code += declcode; + } else { + if (!SaveType(struct_def.name, *struct_def.defined_namespace, declcode, + true, parser_.opts)) + return false; + } + } + + if (parser_.opts.one_file) { + return SaveType(file_name_, *parser_.current_namespace_, one_file_code, + true, parser_.opts); + } + return true; + } + + bool generate() { + gen_mode_ = GenerationMode::ByteBuffer; + if (!generateForCurrentMode()) return false; + + gen_mode_ = GenerationMode::SpanBuffer; + if (!generateForCurrentMode()) return false; + + return true; + } + + private: + std::unordered_set keywords_; + + std::string BufferTypeName() const { + return gen_mode_ == GenerationMode::SpanBuffer ? "ByteSpanBuffer" + : "ByteBuffer"; + } + + std::string BuilderTypeName() const { + return gen_mode_ == GenerationMode::SpanBuffer ? "FlatSpanBufferBuilder" + : "FlatBufferBuilder"; + } + + // Returns the builder parameter declaration with "ref" for SpanBuffer mode + // SpanBuffer uses ref struct which requires passing by ref for mutations + std::string BuilderParam() const { + return gen_mode_ == GenerationMode::SpanBuffer + ? "ref FlatSpanBufferBuilder builder" + : "FlatBufferBuilder builder"; + } + + // Returns the builder argument for method calls - "ref builder" for + // SpanBuffer mode + std::string BuilderArg() const { + return gen_mode_ == GenerationMode::SpanBuffer ? "ref builder" : "builder"; + } + + // Returns "scoped " prefix for Span parameters in SpanBuffer mode + // This is needed because ref struct builder + Span parameter combination + // requires scoped to prevent reference escape warnings in C# + std::string ScopedPrefix() const { + return gen_mode_ == GenerationMode::SpanBuffer ? "scoped " : ""; + } + + std::string TableBaseTypeName() const { + return gen_mode_ == GenerationMode::SpanBuffer ? "TableSpan" : "Table"; + } + + std::string StructBaseTypeName() const { + return gen_mode_ == GenerationMode::SpanBuffer ? "StructSpan" : "Struct"; + } + + std::string FlatbufferObjectInterface() const { + return gen_mode_ == GenerationMode::SpanBuffer ? "IFlatbufferSpanObject" + : "IFlatbufferObject"; + } + + const std::string spanbuf_namespace = "StackBuffer"; + // Returns the namespace suffix for the current generation mode + std::string NamespaceSuffix() const { + return gen_mode_ == GenerationMode::SpanBuffer ? spanbuf_namespace : ""; + } + + // Returns true if generating span-based code + bool IsSpanMode() const { return gen_mode_ == GenerationMode::SpanBuffer; } + + // Returns the fully qualified namespaced name for a struct definition + // using the base namespace. + // Used for Object API types which are shared between modes. + std::string BaseNamespacedName(const StructDef &def) const { + std::string ns = FullNamespace(".", *def.defined_namespace); + if (ns.empty()) { return Name(def); } + return ns + "." + Name(def); + } + + // Returns the fully qualified namespaced name for a struct definition + // in the SpanBuf namespace. Used for generating SpanBuf-specific Pack + // methods. + std::string SpanBufNamespacedName(const StructDef &def) const { + std::string ns = FullNamespace(".", *def.defined_namespace); + if (ns.empty()) { return spanbuf_namespace + "." + Name(def); } + return ns + "." + spanbuf_namespace + "." + Name(def); + } + + // Returns the fully qualified namespaced name for an enum definition + // using the base namespace. Enums are always in the base namespace. + std::string BaseNamespacedEnumName(const EnumDef &def) const { + return WrapInNameSpace(def.defined_namespace, Name(def)); + } + + std::string EscapeKeyword(const std::string &name) const { + return keywords_.find(name) == keywords_.end() ? name : "@" + name; + } + + std::string Name(const FieldDef &field) const { + std::string name = ConvertCase(field.name, Case::kUpperCamel); + return EscapeKeyword(name); + } + + std::string Name(const Definition &def) const { + return EscapeKeyword(def.name); + } + + // Returns the fully qualified namespaced name for a definition. + // For structs/tables in SpanBuffer mode, includes the .SpanBuf suffix in the + // namespace. For enums, always uses the base namespace (enums are shared). + std::string NamespacedName(const Definition &def) const { + std::string ns = FullNamespace(".", *def.defined_namespace); + if (IsSpanMode()) { + ns = ns.empty() ? NamespaceSuffix() : ns + "." + NamespaceSuffix(); + } + if (ns.empty()) { return Name(def); } + return ns + "." + Name(def); + } + + std::string NamespacedEnumName(const EnumDef &def) const { + return WrapInNameSpace(def.defined_namespace, Name(def)); + } + + std::string Name(const EnumVal &ev) const { return EscapeKeyword(ev.name); } + + // Save out the generated code for a single class while adding + // declaration boilerplate. + bool SaveType(const std::string &defname, const Namespace &ns, + const std::string &classcode, bool needs_includes, + const IDLOptions &options) const { + if (!classcode.length()) return true; + + std::string code = + "// \n" + "// " + + std::string(FlatBuffersGeneratedWarning()) + + "\n" + "// \n\n"; + + std::string namespace_name = FullNamespace(".", ns); + std::string namespace_suffix = NamespaceSuffix(); + std::string complete_namespace = ""; + if (!namespace_name.empty() && !namespace_suffix.empty()) { + complete_namespace = + "namespace " + namespace_name + "." + namespace_suffix + "\n{\n\n"; + } else if (!namespace_name.empty()) { + complete_namespace = "namespace " + namespace_name + "\n{\n\n"; + } else if (!namespace_suffix.empty()) { + complete_namespace = "namespace " + namespace_suffix + "\n{\n\n"; + } + code += complete_namespace; + if (needs_includes) { + code += "using global::System;\n"; + code += "using global::System.Buffers;\n"; + code += "using global::System.Collections.Generic;\n"; + code += "using global::System.Runtime.InteropServices;\n"; + code += "using global::Google.FlatSpanBuffers;\n"; + code += "using global::Google.FlatSpanBuffers.Operations;\n"; + code += "using global::Google.FlatSpanBuffers.Utils;\n"; + code += "using global::Google.FlatSpanBuffers.Vectors;\n"; + } + code += classcode; + if (!complete_namespace.empty()) { code += "\n}\n"; } + + // For span mode, use a separate directory to avoid file conflicts + std::string dir = NamespaceDir(ns); + if (IsSpanMode()) { + dir += "StackBuffer/"; + EnsureDirExists(dir); + } + auto filename = dir + defname; + if (options.one_file) { filename += options.filename_suffix; } + filename += + options.filename_extension.empty() ? ".cs" : options.filename_extension; + return SaveFile(filename.c_str(), code, false); + } + + const Namespace *CurrentNameSpace() const { return cur_name_space_; } + + std::string GenTypeBasic(const Type &type, bool enableLangOverrides) const { + // clang-format off + static const char * const csharp_typename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, ...) \ + #NTYPE, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD + }; + // clang-format on + + if (enableLangOverrides) { + // Enums use the base namespace, they are shared across modes + if (IsEnum(type)) return NamespacedEnumName(*type.enum_def); + if (type.base_type == BASE_TYPE_STRUCT) { + return "Offset<" + NamespacedName(*type.struct_def) + ">"; + } + } + + return csharp_typename[type.base_type]; + } + + inline std::string GenTypeBasic(const Type &type) const { + return GenTypeBasic(type, true); + } + + std::string GenTypePointer(const Type &type) const { + switch (type.base_type) { + case BASE_TYPE_STRING: return "string"; + case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType()); + case BASE_TYPE_STRUCT: return NamespacedName(*type.struct_def); + case BASE_TYPE_UNION: return "TTable"; + default: return "Table"; + } + } + + std::string GenTypeGet(const Type &type) const { + return IsScalar(type.base_type) + ? GenTypeBasic(type) + : (IsArray(type) ? GenTypeGet(type.VectorType()) + : GenTypePointer(type)); + } + + std::string GenOffsetType(const StructDef &struct_def) const { + return "Offset<" + NamespacedName(struct_def) + ">"; + } + + std::string GenOffsetConstruct(const StructDef &struct_def, + const std::string &variable_name) const { + return "new Offset<" + NamespacedName(struct_def) + ">(" + variable_name + + ")"; + } + + // Casts necessary to correctly read serialized data + std::string DestinationCast(const Type &type) const { + if (IsSeries(type)) { + return DestinationCast(type.VectorType()); + } else { + // Enums use the base namespace, they are shared across modes + if (IsEnum(type)) return "(" + NamespacedEnumName(*type.enum_def) + ")"; + } + return ""; + } + + // Cast statements for mutator method parameters. + // In Java, parameters representing unsigned numbers need to be cast down to + // their respective type. For example, a long holding an unsigned int value + // would be cast down to int before being put onto the buffer. In C#, one cast + // directly cast an Enum to its underlying type, which is essential before + // putting it onto the buffer. + std::string SourceCast(const Type &type, + const bool isOptional = false) const { + if (IsSeries(type)) { + return SourceCast(type.VectorType()); + } else { + if (IsEnum(type)) + return "(" + GenTypeBasic(type, false) + (isOptional ? "?" : "") + ")"; + } + return ""; + } + + std::string SourceCastBasic(const Type &type, const bool isOptional) const { + return IsScalar(type.base_type) ? SourceCast(type, isOptional) : ""; + } + + std::string GenEnumDefaultValue(const FieldDef &field) const { + auto &value = field.value; + FLATBUFFERS_ASSERT(value.type.enum_def); + auto &enum_def = *value.type.enum_def; + auto enum_val = enum_def.FindByValue(value.constant); + // Enums use the base namespace, they are shared across modes + return enum_val ? (NamespacedEnumName(enum_def) + "." + Name(*enum_val)) + : value.constant; + } + + std::string GenDefaultValue(const FieldDef &field, + bool enableLangOverrides) const { + // If it is an optional scalar field, the default is null + if (field.IsScalarOptional()) { return "null"; } + + auto &value = field.value; + if (enableLangOverrides) { + // handles both enum case and vector of enum case + if (value.type.enum_def != nullptr && + value.type.base_type != BASE_TYPE_UNION) { + return GenEnumDefaultValue(field); + } + } + + auto longSuffix = ""; + switch (value.type.base_type) { + case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true"; + case BASE_TYPE_ULONG: return value.constant; + case BASE_TYPE_UINT: + case BASE_TYPE_LONG: return value.constant + longSuffix; + default: + if (IsFloat(value.type.base_type)) + return CSharpFloatGen.GenFloatConstant(field); + else + return value.constant; + } + } + + std::string GenDefaultValue(const FieldDef &field) const { + return GenDefaultValue(field, true); + } + + std::string GenDefaultValueBasic(const FieldDef &field, + bool enableLangOverrides) const { + auto &value = field.value; + if (!IsScalar(value.type.base_type)) { + if (enableLangOverrides) { + switch (value.type.base_type) { + case BASE_TYPE_STRING: return "default(StringOffset)"; + case BASE_TYPE_STRUCT: + return "default(Offset<" + NamespacedName(*value.type.struct_def) + + ">)"; + case BASE_TYPE_VECTOR: return "default(VectorOffset)"; + default: break; + } + } + return "0"; + } + return GenDefaultValue(field, enableLangOverrides); + } + + std::string GenDefaultValueBasic(const FieldDef &field) const { + return GenDefaultValueBasic(field, true); + } + + void GenEnum(EnumDef &enum_def, std::string *code_ptr, + const IDLOptions &opts) const { + std::string &code = *code_ptr; + if (enum_def.generated) return; + + // Generate enum definitions of the form: + // public static (final) int name = value; + // In Java, we use ints rather than the Enum feature, because we want them + // to map directly to how they're used in C/C++ and file formats. + // That, and Java Enums are expensive, and not universally liked. + GenComment(enum_def.doc_comment, code_ptr, &comment_config); + + if (opts.cs_gen_json_serializer && opts.generate_object_based_api) { + code += + "[System.Text.Json.Serialization.JsonConverter(typeof(System.Text." + "Json.Serialization." + "JsonStringEnumConverter))]\n"; + } + // In C# this indicates enumeration values can be treated as bit flags. + if (enum_def.attributes.Lookup("bit_flags")) { + code += "[System.FlagsAttribute]\n"; + } + if (enum_def.attributes.Lookup("private")) { + code += "internal "; + } else { + code += "public "; + } + code += "enum " + Name(enum_def); + code += " : " + GenTypeBasic(enum_def.underlying_type, false); + code += "\n{\n"; + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { + auto &ev = **it; + GenComment(ev.doc_comment, code_ptr, &comment_config, " "); + code += " "; + code += Name(ev) + " = "; + code += enum_def.ToString(ev); + code += ",\n"; + } + // Close the class + code += "};\n\n"; + + if (opts.generate_object_based_api) { + GenEnum_ObjectAPI(enum_def, code_ptr, opts); + } + + if (enum_def.is_union) { code += GenUnionVerify(enum_def.underlying_type); } + } + + bool HasUnionStringValue(const EnumDef &enum_def) const { + if (!enum_def.is_union) return false; + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { + auto &val = **it; + if (IsString(val.union_type)) { return true; } + } + return false; + } + + // Returns the function name that is able to read a value of the given type. + std::string GenGetter(const Type &type) const { + switch (type.base_type) { + case BASE_TYPE_STRING: return "__p.__string"; + case BASE_TYPE_STRUCT: return "__p.__struct"; + case BASE_TYPE_UNION: return "__p.__union"; + case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); + case BASE_TYPE_ARRAY: return GenGetter(type.VectorType()); + default: { + std::string getter = "__p.bb.Get<" + GenTypeBasic(type, false) + ">"; + return getter; + } + } + } + + std::string GetObjectConstructor(flatbuffers::StructDef &struct_def, + const std::string &data_buffer, + const std::string &offset) const { + // Use the generated type directly, to properly handle default values that + // might not be written to the buffer. + return "new " + Name(struct_def) + "().__assign(" + offset + ", " + + data_buffer + ")"; + } + + // Returns the function name that is able to read a value of the given type. + std::string GenGetterForLookupByKey(flatbuffers::StructDef &struct_def, + flatbuffers::FieldDef *key_field, + const std::string &data_buffer, + const std::string &offset) const { + // Use the generated type directly, to properly handle default values that + // might not be written to the buffer. + auto name = Name(*key_field); + if (name == struct_def.name) { name += "_"; } + return GetObjectConstructor(struct_def, data_buffer, offset) + "." + name; + } + + // Direct mutation is only allowed for scalar fields. + // Hence a setter method will only be generated for such fields. + std::string GenSetter(const Type &type) const { + if (IsScalar(type.base_type)) { + std::string basicType = GenTypeBasic(type, false); + if (basicType == "byte" || type.base_type == BASE_TYPE_BOOL) { + return "__p.bb.PutByte"; + } + return "__p.bb.Put<" + basicType + ">"; + } else { + return ""; + } + } + + // Returns the method name for use with add/put calls. + std::string GenMethod(const Type &type) const { + return IsScalar(type.base_type) ? ("<" + GenTypeBasic(type, false) + ">") + : (IsStruct(type) ? "Struct" : "Offset"); + } + + // Recursively generate arguments for a constructor, to deal with nested + // structs. + void GenStructArgs(const StructDef &struct_def, std::string *code_ptr, + const char *nameprefix, size_t array_count = 0) const { + std::string &code = *code_ptr; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + const auto &field_type = field.value.type; + const auto array_field = IsArray(field_type); + const auto &type = array_field ? field_type.VectorType() : field_type; + const auto array_cnt = array_field ? (array_count + 1) : array_count; + if (IsStruct(type)) { + // Generate arguments for a struct inside a struct. To ensure names + // don't clash, and to make it obvious these arguments are constructing + // a nested struct, prefix the name with the field name. + GenStructArgs(*field_type.struct_def, code_ptr, + (nameprefix + (EscapeKeyword(field.name) + "_")).c_str(), + array_cnt); + } else { + code += ", "; + code += GenTypeBasic(type); + if (field.IsScalarOptional()) { code += "?"; } + if (array_cnt > 0) { + code += "["; + for (size_t i = 1; i < array_cnt; i++) code += ","; + code += "]"; + } + code += " "; + code += nameprefix; + code += Name(field); + } + } + } + + // Recusively generate struct construction statements of the form: + // builder.putType(name); + // and insert manual padding. + void GenStructBody(const StructDef &struct_def, std::string *code_ptr, + const char *nameprefix, size_t index = 0, + bool in_array = false) const { + std::string &code = *code_ptr; + std::string indent((index + 1) * 2, ' '); + code += indent + " builder.Prep("; + code += NumToString(struct_def.minalign) + ", "; + code += NumToString(struct_def.bytesize) + ");\n"; + for (auto it = struct_def.fields.vec.rbegin(); + it != struct_def.fields.vec.rend(); ++it) { + auto &field = **it; + const auto &field_type = field.value.type; + if (field.padding) { + code += indent + " builder.Pad("; + code += NumToString(field.padding) + ");\n"; + } + if (IsStruct(field_type)) { + GenStructBody(*field_type.struct_def, code_ptr, + (nameprefix + (field.name + "_")).c_str(), index, + in_array); + } else { + const auto &type = + IsArray(field_type) ? field_type.VectorType() : field_type; + const auto index_var = "_idx" + NumToString(index); + if (IsArray(field_type)) { + code += indent + " for (int " + index_var + " = "; + code += NumToString(field_type.fixed_length); + code += "; " + index_var + " > 0; " + index_var + "--) {\n"; + in_array = true; + } + if (IsStruct(type)) { + GenStructBody(*field_type.struct_def, code_ptr, + (nameprefix + (field.name + "_")).c_str(), index + 1, + in_array); + } else { + code += IsArray(field_type) ? " " : ""; + code += indent + " builder.Put"; + code += GenMethod(type) + "("; + code += SourceCast(type); + auto argname = nameprefix + Name(field); + code += argname; + size_t array_cnt = index + (IsArray(field_type) ? 1 : 0); + if (array_cnt > 0) { + code += "["; + for (size_t i = 0; in_array && i < array_cnt; i++) { + code += "_idx" + NumToString(i) + "-1"; + if (i != (array_cnt - 1)) code += ","; + } + code += "]"; + } + code += ");\n"; + } + if (IsArray(field_type)) { code += indent + " }\n"; } + } + } + } + // JT: Not referenced? Can remove? + // std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, + // const char *num = nullptr) const { + // std::string key_offset = + // "Table.__offset(" + NumToString(key_field->value.offset) + ", "; + // if (num) { + // key_offset += num; + // key_offset += ".Value, builder.DataBuffer)"; + // } else { + // key_offset += "bb.Length"; + // key_offset += " - tableOffset, bb)"; + // } + // return key_offset; + // } + + std::string GenKeyGetter(flatbuffers::StructDef &struct_def, + flatbuffers::FieldDef *key_field) const { + auto key_type = key_field->value.type; + auto field_offset = key_field->value.offset; + + if (key_type.base_type == BASE_TYPE_STRING) { + // Use VectorOffsetComparer for strings with byte element type + return "new SortedVectorUtils.VectorOffsetComparer<" + struct_def.name + + ", " + BufferTypeName() + ", byte>(builder.DataBuffer, " + + NumToString(field_offset) + ")"; + } else if (IsScalar(key_type.base_type)) { + // Use ScalarOffsetComparer with the actual scalar type + std::string scalar_type = GenTypeBasic(key_type, false); + return "new SortedVectorUtils.ScalarOffsetComparer<" + struct_def.name + + ", " + BufferTypeName() + ", " + scalar_type + + ">(builder.DataBuffer, " + NumToString(field_offset) + ")"; + } else { + // Invalid key type - FlatBuffers rule: + // key field must be string or scalar type + FLATBUFFERS_ASSERT(false && "Key field must be of string or scalar type"); + return ""; + } + } + + // Get the value of a table verification function start + void GetStartOfTableVerifier(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += "\n"; + code += "static public class " + struct_def.name + "Verify\n"; + code += "{\n"; + code += " static public bool Verify"; + code += "(ref Google.FlatSpanBuffers.Verifier verifier, uint tablePos)\n"; + code += " {\n"; + code += " return verifier.VerifyTableStart(tablePos)\n"; + } + + // Get the value of a table verification function end + void GetEndOfTableVerifier(std::string *code_ptr) { + std::string &code = *code_ptr; + code += " && verifier.VerifyTableEnd(tablePos);\n"; + code += " }\n"; + code += "}\n"; + } + + std::string GetNestedFlatBufferName(const FieldDef &field) { + std::string name; + if (field.nested_flatbuffer) { + name = NamespacedName(*field.nested_flatbuffer); + } else { + name = ""; + } + return name; + } + + // Generate the code to call the appropriate Verify function(s) for a field. + void GenVerifyCall(CodeWriter &code_, const FieldDef &field, + const char *prefix) { + code_.SetValue("PRE", prefix); + code_.SetValue("NAME", ConvertCase(field.name, Case::kUpperCamel)); + code_.SetValue("REQUIRED", field.IsRequired() ? "Required" : ""); + code_.SetValue("REQUIRED_FLAG", field.IsRequired() ? "true" : "false"); + code_.SetValue("TYPE", GenTypeGet(field.value.type)); + code_.SetValue("INLINESIZE", NumToString(InlineSize(field.value.type))); + code_.SetValue("OFFSET", NumToString(field.value.offset)); + + if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) { + code_.SetValue("ALIGN", NumToString(InlineAlignment(field.value.type))); + code_ += + "{{PRE}} && verifier.VerifyField(tablePos, " + "{{OFFSET}} /*{{NAME}}*/, {{INLINESIZE}} /*{{TYPE}}*/, {{ALIGN}}, " + "{{REQUIRED_FLAG}})"; + } else { + // TODO - probably code below should go to this 'else' - code_ += + // "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\"; + } + + switch (field.value.type.base_type) { + case BASE_TYPE_UNION: { + auto union_name = NamespacedName(*field.value.type.enum_def); + code_.SetValue("ENUM_NAME1", field.value.type.enum_def->name); + code_.SetValue("ENUM_NAME", union_name); + code_.SetValue("SUFFIX", UnionTypeFieldSuffix()); + // Caution: This construction assumes, that UNION type id element has + // been created just before union data and its offset precedes union. + // Such assumption is common in flatbuffer implementation + code_.SetValue("TYPE_ID_OFFSET", + NumToString(field.value.offset - sizeof(voffset_t))); + code_ += + "{{PRE}} && verifier.VerifyUnion(tablePos, " + "{{TYPE_ID_OFFSET}}, " + "{{OFFSET}} /*{{NAME}}*/, {{ENUM_NAME}}Verify.Verify, " + "{{REQUIRED_FLAG}})"; + break; + } + case BASE_TYPE_STRUCT: { + if (!field.value.type.struct_def->fixed) { + code_ += + "{{PRE}} && verifier.VerifyTable(tablePos, " + "{{OFFSET}} /*{{NAME}}*/, {{TYPE}}Verify.Verify, " + "{{REQUIRED_FLAG}})"; + } + break; + } + case BASE_TYPE_STRING: { + code_ += + "{{PRE}} && verifier.VerifyString(tablePos, " + "{{OFFSET}} /*{{NAME}}*/, {{REQUIRED_FLAG}})"; + break; + } + case BASE_TYPE_VECTOR: { + switch (field.value.type.element) { + case BASE_TYPE_STRING: { + code_ += + "{{PRE}} && verifier.VerifyVectorOfStrings(tablePos, " + "{{OFFSET}} /*{{NAME}}*/, {{REQUIRED_FLAG}})"; + break; + } + case BASE_TYPE_STRUCT: { + if (!field.value.type.struct_def->fixed) { + code_ += + "{{PRE}} && verifier.VerifyVectorOfTables(tablePos, " + "{{OFFSET}} /*{{NAME}}*/, {{TYPE}}Verify.Verify, " + "{{REQUIRED_FLAG}})"; + } else { + code_.SetValue( + "VECTOR_ELEM_INLINESIZE", + NumToString(InlineSize(field.value.type.VectorType()))); + code_ += + "{{PRE}} && " + "verifier.VerifyVectorOfData(tablePos, " + "{{OFFSET}} /*{{NAME}}*/, {{VECTOR_ELEM_INLINESIZE}} " + "/*{{TYPE}}*/, {{REQUIRED_FLAG}})"; + } + break; + } + case BASE_TYPE_UNION: { + // Vectors of unions are not yet supported for go + break; + } + default: + // Generate verifier for vector of data. + // It may be either nested flatbuffer of just vector of bytes + auto nfn = GetNestedFlatBufferName(field); + if (!nfn.empty()) { + code_.SetValue("CPP_NAME", nfn); + // FIXME: file_identifier. + code_ += + "{{PRE}} && verifier.VerifyNestedBuffer(tablePos, " + "{{OFFSET}} /*{{NAME}}*/, {{CPP_NAME}}Verify.Verify, " + "{{REQUIRED_FLAG}})"; + } else if (field.flexbuffer) { + code_ += + "{{PRE}} && verifier.VerifyNestedBuffer(tablePos, " + "{{OFFSET}} /*{{NAME}}*/, null, {{REQUIRED_FLAG}})"; + } else { + code_.SetValue( + "VECTOR_ELEM_INLINESIZE", + NumToString(InlineSize(field.value.type.VectorType()))); + code_ += + "{{PRE}} && verifier.VerifyVectorOfData(tablePos, " + "{{OFFSET}} /*{{NAME}}*/, {{VECTOR_ELEM_INLINESIZE}} " + "/*{{TYPE}}*/, {{REQUIRED_FLAG}})"; + } + break; + } + + break; + } + default: { + break; + } + } + } + + // Generate table constructors, conditioned on its members' types. + void GenTableVerifier(const StructDef &struct_def, std::string *code_ptr) { + CodeWriter code_; + + GetStartOfTableVerifier(struct_def, code_ptr); + + // Generate struct fields accessors + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + + GenVerifyCall(code_, field, ""); + } + + *code_ptr += code_.ToString(); + + GetEndOfTableVerifier(code_ptr); + } + + // Generate struct or table methods. + void GenStructVerifier(const StructDef &struct_def, std::string *code_ptr) { + if (struct_def.generated) return; + + // cur_name_space_ = struct_def.defined_namespace; + + // Generate verifiers + if (struct_def.fixed) { + // Fixed size structures do not require table members + // verification - instead structure size is verified using VerifyField + } else { + // Create table verification function + GenTableVerifier(struct_def, code_ptr); + } + } + + void GenStruct(StructDef &struct_def, std::string *code_ptr, + const IDLOptions &opts) const { + if (struct_def.generated) return; + std::string &code = *code_ptr; + + // Generate a struct accessor class, with methods of the form: + // public type name() { return bb.getType(i + offset); } + // or for tables of the form: + // public type name() { + // int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default; + // } + GenComment(struct_def.doc_comment, code_ptr, &comment_config); + if (struct_def.attributes.Lookup("private")) { + code += "internal "; + } else { + code += "public "; + } + if (struct_def.attributes.Lookup("csharp_partial")) { + // generate a partial class for this C# struct/table + code += "partial "; + } + // For span mode, use ref struct for compatibility with stackalloc + if (IsSpanMode()) { code += "ref "; } + code += "struct " + struct_def.name; + code += " : " + FlatbufferObjectInterface(); + code += "\n{\n"; + code += " private "; + code += struct_def.fixed ? StructBaseTypeName() : TableBaseTypeName(); + code += " __p;\n"; + + code += " public " + BufferTypeName() + + " ByteBuffer { get { return __p.bb; } }\n"; + + if (!struct_def.fixed) { + // Generate version check method. + // Force compile time error if not using the same version runtime. + code += " public static void ValidateVersion() {"; + code += " FlatBufferConstants."; + code += "FLATBUFFERS_25_2_10(); "; + code += "}\n"; + + // Generate a special accessor for the table that when used as the root + // of a FlatBuffer + std::string method_name = "GetRootAs" + struct_def.name; + std::string method_signature = + " public static " + struct_def.name + " " + method_name; + + // create convenience method that doesn't require an existing object + code += method_signature + "(" + BufferTypeName() + " _bb) "; + code += "{ return " + method_name + "(_bb, new " + struct_def.name + + "()); }\n"; + + // create method that allows object reuse + code += method_signature + "(" + BufferTypeName() + " _bb, " + + struct_def.name + " obj) { "; + code += "return (obj.__assign(_bb.Get(_bb.Position"; + code += ") + _bb.Position"; + code += ", _bb)); }\n"; + if (parser_.root_struct_def_ == &struct_def) { + if (parser_.file_identifier_.length()) { + // Check if a buffer has the identifier. + code += " public static "; + code += "bool " + struct_def.name; + code += "BufferHasIdentifier(" + BufferTypeName() + " _bb) { return "; + code += TableBaseTypeName() + ".__has_identifier(_bb, \""; + code += parser_.file_identifier_; + code += "\"); }\n"; + } + + // Generate the Verify method that checks if a ByteBuffer is save to + // access + code += " public static "; + code += "bool Verify" + struct_def.name + "(" + BufferTypeName() + + " _bb) {"; + code += "Google.FlatSpanBuffers.Verifier verifier = new "; + code += "Google.FlatSpanBuffers.Verifier(_bb); "; + // For SpanBuf mode, we reference the base namespace's Verify class + // since verifiers operate on the buffer + std::string verify_class_ns = + FullNamespace(".", *struct_def.defined_namespace); + if (!verify_class_ns.empty()) verify_class_ns += "."; + code += "return verifier.VerifyBuffer(\""; + code += parser_.file_identifier_; + code += "\", false, " + verify_class_ns + struct_def.name + + "Verify.Verify);"; + code += " }\n"; + } + } + + // Generate the __init method that sets the field in a pre-existing + // accessor object. This is to allow object reuse. + code += " public void __init(int _i, " + BufferTypeName() + " _bb) "; + code += "{ "; + code += "__p = new "; + code += struct_def.fixed ? StructBaseTypeName() : TableBaseTypeName(); + code += "(_i, _bb); "; + code += "}\n"; + code += " public " + struct_def.name + " __assign(int _i, " + + BufferTypeName() + " _bb) "; + code += "{ __init(_i, _bb); return this; }\n\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + GenComment(field.doc_comment, code_ptr, &comment_config, " "); + std::string type_name = GenTypeGet(field.value.type); + std::string type_name_dest = GenTypeGet(field.value.type); + std::string conditional_cast = ""; + std::string optional = ""; + // In ByteBuffer mode, struct/table fields use C# nullable syntax Type?. + // In SpanBuffer mode, ref structs cannot use C# nullable syntax, so we + // use RefStructNullable wrapper instead. + bool use_nullable = !IsSpanMode() && !field.IsRequired(); + bool use_ref_struct_nullable = + IsSpanMode() && !struct_def.fixed && + field.value.type.base_type == BASE_TYPE_STRUCT && !field.IsRequired(); + if (!struct_def.fixed && !field.IsRequired() && + (field.value.type.base_type == BASE_TYPE_STRUCT || + field.value.type.base_type == BASE_TYPE_UNION || + (IsVector(field.value.type) && + (field.value.type.element == BASE_TYPE_STRUCT || + field.value.type.element == BASE_TYPE_UNION)))) { + if (use_nullable) { + optional = "?"; + conditional_cast = "(" + type_name_dest + optional + ")"; + } + } + if (field.IsScalarOptional()) { optional = "?"; } + std::string dest_mask = ""; + std::string dest_cast = DestinationCast(field.value.type); + std::string src_cast = SourceCast(field.value.type); + std::string field_name_camel = Name(field); + if (field_name_camel == struct_def.name) { field_name_camel += "_"; } + std::string return_type = + use_ref_struct_nullable ? "RefStructNullable<" + type_name_dest + ">" + : type_name_dest + optional; + std::string method_start = + " public " + return_type + " " + field_name_camel; + std::string obj = "(new " + type_name + "())"; + + // Most field accessors need to retrieve and test the field offset first, + // this is the prefix code for that: + auto offset_prefix = + IsArray(field.value.type) + ? " { return " + : (" { int o = __p.__offset(" + NumToString(field.value.offset) + + "); return o != 0 ? "); + // Generate the accessors that don't do object reuse. + if (field.value.type.base_type == BASE_TYPE_STRUCT) { + } else if (IsVector(field.value.type) && + field.value.type.element == BASE_TYPE_STRUCT) { + } else if (field.value.type.base_type == BASE_TYPE_UNION || + (IsVector(field.value.type) && + field.value.type.VectorType().base_type == BASE_TYPE_UNION)) { + method_start += ""; + type_name = type_name_dest; + } + std::string getter = dest_cast + GenGetter(field.value.type); + + // True when field uses span-based accessor + bool gen_span_getter = + !struct_def.fixed && + ((IsSpanMode() && + (field.value.type.base_type == BASE_TYPE_UNION || + (IsVector(field.value.type) && !IsArray(field.value.type) && + (field.value.type.element == BASE_TYPE_STRUCT || + field.value.type.element == BASE_TYPE_UNION || + field.value.type.element == BASE_TYPE_STRING || + IsScalar(field.value.type.element))))) || + (!IsSpanMode() && IsVector(field.value.type) && + !IsArray(field.value.type) && + (field.value.type.element == BASE_TYPE_STRUCT || + field.value.type.element == BASE_TYPE_UNION || + field.value.type.element == BASE_TYPE_STRING || + IsScalar(field.value.type.element)))); + + if (!gen_span_getter) { code += method_start; } + std::string default_cast = ""; + // only create default casts for c# scalars or vectors of scalars + if ((IsScalar(field.value.type.base_type) || + (IsVector(field.value.type) && + IsScalar(field.value.type.element)))) { + // For scalars, default value will be returned by GetDefaultValue(). + // If the scalar is an enum, GetDefaultValue() returns an actual c# enum + // that doesn't need to be casted. However, default values for enum + // elements of vectors are integer literals ("0") and are still casted + // for clarity. + // If the scalar is optional and enum, we still need the cast. + if ((field.value.type.enum_def == nullptr || + IsVector(field.value.type)) || + (IsEnum(field.value.type) && field.IsScalarOptional())) { + default_cast = "(" + type_name_dest + optional + ")"; + } + } + std::string member_suffix = "; "; + if (IsScalar(field.value.type.base_type)) { + code += " { get"; + member_suffix += "} "; + if (struct_def.fixed) { + code += " { return " + getter; + code += "(__p.bb_pos + "; + code += NumToString(field.value.offset) + ")"; + code += dest_mask; + } else { + code += offset_prefix + getter; + code += "(o + __p.bb_pos)" + dest_mask; + code += " : " + default_cast; + code += GenDefaultValue(field); + } + } else { + switch (field.value.type.base_type) { + case BASE_TYPE_STRUCT: + // Generate property getter for struct fields + if (!gen_span_getter) { + code += " { get"; + member_suffix += "} "; + if (struct_def.fixed) { + code += " { return " + obj + ".__assign(" + "__p."; + code += "bb_pos + " + NumToString(field.value.offset) + ", "; + code += "__p.bb)"; + } else { + code += offset_prefix + conditional_cast; + if (use_ref_struct_nullable) { + code += "new RefStructNullable<"; + code += GenTypeGet(field.value.type) + ">("; + code += obj + ".__assign("; + code += field.value.type.struct_def->fixed + ? "o + __p.bb_pos" + : "__p.__indirect(o + __p.bb_pos)"; + code += ", __p.bb)) : default"; + } else if (IsSpanMode()) { + code += obj + ".__assign("; + code += field.value.type.struct_def->fixed + ? "o + __p.bb_pos" + : "__p.__indirect(o + __p.bb_pos)"; + code += ", __p.bb) : default"; + } else { + code += obj + ".__assign("; + code += field.value.type.struct_def->fixed + ? "o + __p.bb_pos" + : "__p.__indirect(o + __p.bb_pos)"; + code += ", __p.bb) : null"; + } + } + } + break; + case BASE_TYPE_STRING: + code += " { get"; + member_suffix += "} "; + code += offset_prefix + getter + "(o + " + "__p."; + code += "bb_pos) : null"; + break; + case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru + case BASE_TYPE_VECTOR: { + auto vectortype = field.value.type.VectorType(); + // Skip vector element getters for struct/table/string/union + // vectors, these will use Vector accessors Scalar vectors will use + // Spans. + bool skip_vector_getter = + !struct_def.fixed && !IsArray(field.value.type) && + (vectortype.base_type == BASE_TYPE_STRUCT || + vectortype.base_type == BASE_TYPE_STRING || + vectortype.base_type == BASE_TYPE_UNION || + IsScalar(vectortype.base_type)); + + if (!skip_vector_getter) { + if (vectortype.base_type == BASE_TYPE_UNION) { + conditional_cast = IsSpanMode() ? "" : "(TTable?)"; + getter += ""; + } + code += "("; + if (vectortype.base_type == BASE_TYPE_STRUCT) { + getter = obj + ".__assign"; + } + code += "int j)"; + const auto body = offset_prefix + conditional_cast + getter + "("; + if (vectortype.base_type == BASE_TYPE_UNION) { + code += + " where TTable : struct, " + FlatbufferObjectInterface(); + if (IsSpanMode()) { code += ", allows ref struct"; } + code += body; + } else { + code += body; + } + std::string index = "__p."; + if (IsArray(field.value.type)) { + index += "bb_pos + " + NumToString(field.value.offset) + " + "; + } else { + index += "__vector(o) + "; + } + index += "j * " + NumToString(InlineSize(vectortype)); + if (vectortype.base_type == BASE_TYPE_STRUCT) { + code += vectortype.struct_def->fixed + ? index + : "__p.__indirect(" + index + ")"; + code += ", __p.bb"; + } else { + code += index; + } + code += ")" + dest_mask; + if (!IsArray(field.value.type)) { + code += " : "; + if (field.value.type.element == BASE_TYPE_BOOL) { + code += "false"; + } else if (IsScalar(field.value.type.element)) { + code += default_cast + "0"; + } else { + // For struct/table vector elements, use default in SpanBuffer + // mode + code += IsSpanMode() ? "default" : "null"; + } + } + if (vectortype.base_type == BASE_TYPE_UNION && + HasUnionStringValue(*vectortype.enum_def)) { + code += member_suffix; + code += "}\n"; + code += " public string " + Name(field) + "AsString(int j)"; + code += offset_prefix + GenGetter(Type(BASE_TYPE_STRING)); + code += "(" + index + ") : null"; + } + } + break; + } + case BASE_TYPE_UNION: + if (!gen_span_getter) { + if (IsSpanMode()) { + code += "() where TTable : struct, "; + code += FlatbufferObjectInterface() + ", allows ref struct"; + code += offset_prefix + getter; + code += "(o + __p.bb_pos) : default"; + } else { + code += "() where TTable : struct, IFlatbufferObject"; + code += offset_prefix + "(TTable?)" + getter; + code += "(o + __p.bb_pos) : null"; + } + if (HasUnionStringValue(*field.value.type.enum_def)) { + code += member_suffix; + code += "}\n"; + code += " public string " + Name(field) + "AsString()"; + code += offset_prefix + GenGetter(Type(BASE_TYPE_STRING)); + code += "(o + __p.bb_pos) : null"; + } + // As<> accesors for Unions + // Loop through all the possible union types and generate an As + // accessor that casts to the correct type. + for (auto uit = field.value.type.enum_def->Vals().begin(); + uit != field.value.type.enum_def->Vals().end(); ++uit) { + auto val = *uit; + if (val->union_type.base_type == BASE_TYPE_NONE) { continue; } + auto union_field_type_name = GenTypeGet(val->union_type); + code += member_suffix + "}\n"; + if (val->union_type.base_type == BASE_TYPE_STRUCT && + val->union_type.struct_def->attributes.Lookup("private")) { + code += " internal "; + } else { + code += " public "; + } + code += union_field_type_name + " "; + code += field_name_camel + "As" + val->name + "() { return "; + code += field_name_camel; + if (IsString(val->union_type)) { + code += "AsString()"; + } else { + code += "<" + union_field_type_name + ">()" + + (IsSpanMode() ? "" : ".Value"); + } + } + } + break; + default: FLATBUFFERS_ASSERT(0); + } + } + + // Output member_suffix and closing brace if we generated a property + // getter + if (!gen_span_getter) { + code += member_suffix; + code += "}\n"; + } + + if (IsSpanMode() && !struct_def.fixed) { + if (field.value.type.base_type == BASE_TYPE_UNION) { + std::string union_field_name = Name(field); + if (union_field_name == struct_def.name) { union_field_name += "_"; } + auto offset_str = NumToString(field.value.offset); + auto getter = GenGetter(field.value.type); + + if (field.IsRequired()) { + code += " public TTable " + union_field_name + "()"; + code += " where TTable : struct, " + FlatbufferObjectInterface(); + code += ", allows ref struct"; + code += " { int o = __p.__offset(" + offset_str + ");"; + code += " return " + getter + "(o + __p.bb_pos); }\n"; + } else { + code += " public RefStructNullable "; + code += union_field_name + "()"; + code += " where TTable : struct, " + FlatbufferObjectInterface(); + code += ", allows ref struct"; + code += " { int o = __p.__offset(" + offset_str + ");"; + code += " return o != 0 ? new RefStructNullable("; + code += getter + "(o + __p.bb_pos)) : default; }\n"; + } + if (HasUnionStringValue(*field.value.type.enum_def)) { + code += " public string " + union_field_name + "AsString()"; + code += " { int o = __p.__offset(" + offset_str + ");"; + code += " return o != 0 ? " + GenGetter(Type(BASE_TYPE_STRING)); + code += "(o + __p.bb_pos) : null; }\n"; + } + for (auto uit = field.value.type.enum_def->Vals().begin(); + uit != field.value.type.enum_def->Vals().end(); ++uit) { + auto val = *uit; + if (val->union_type.base_type == BASE_TYPE_NONE) { continue; } + auto union_type_name = GenTypeGet(val->union_type); + // Use SpanBuf variant type for struct types + if (val->union_type.base_type == BASE_TYPE_STRUCT) { + union_type_name = NamespacedName(*val->union_type.struct_def); + } + if (val->union_type.base_type == BASE_TYPE_STRUCT && + val->union_type.struct_def->attributes.Lookup("private")) { + code += " internal "; + } else { + code += " public "; + } + + std::string as_method = union_field_name + "As" + val->name + "()"; + if (IsString(val->union_type)) { + code += "string " + as_method + " { return "; + code += union_field_name + "AsString(); }\n"; + } else { + // Struct/table union members: + // for required, call generic directly; for optional, use .Value + std::string accessor = + union_field_name + "<" + union_type_name + ">()"; + if (!field.IsRequired()) { accessor += ".Value"; } + code += union_type_name + " " + as_method; + code += " { return " + accessor + "; }\n"; + } + } + } + } + + if (IsVector(field.value.type)) { + auto vectortype = field.value.type.VectorType(); + // Skip generating separate Length property when the field provides + // a Length property in its return type. + bool skip_length_property = !IsArray(field.value.type) && + (vectortype.base_type == BASE_TYPE_STRUCT || + vectortype.base_type == BASE_TYPE_STRING || + vectortype.base_type == BASE_TYPE_UNION || + IsScalar(vectortype.base_type)); + + if (!skip_length_property) { + auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + code += " public int " + camel_name; + code += "Length"; + code += " { get"; + code += offset_prefix; + code += "__p.__vector_len(o) : 0; "; + code += "} "; + code += "}\n"; + } + + // Generate struct/table vector wrappers + if (!IsArray(field.value.type) && + vectortype.base_type == BASE_TYPE_STRUCT) { + std::string elem_type_name = GenTypeGet(vectortype); + std::string field_name = Name(field); + if (field_name == struct_def.name) { field_name += "_"; } + std::string element_size = NumToString(InlineSize(vectortype)); + auto offset_val = NumToString(field.value.offset); + + bool is_fixed_struct = vectortype.struct_def->fixed; + + if (IsSpanMode()) { + std::string wrapper_type = + is_fixed_struct ? "StructVectorSpan" : "TableVectorSpan"; + std::string full_wrapper_type = + wrapper_type + "<" + elem_type_name + ">"; + + if (field.IsRequired()) { + code += " public " + full_wrapper_type + " " + field_name; + code += " { get { int o = __p.__offset(" + offset_val + "); "; + code += "return new " + full_wrapper_type; + code += "(__p, o, " + element_size + "); } }\n"; + } else { + code += " public RefStructNullable<" + full_wrapper_type; + code += "> " + field_name; + code += " { get { int o = __p.__offset(" + offset_val + "); "; + code += "return o != 0 ? new RefStructNullable<"; + code += full_wrapper_type + ">(new " + full_wrapper_type; + code += "(__p, o, " + element_size + ")) : default; } }\n"; + } + } else { + // Use non-ref struct wrappers with C# nullable + std::string wrapper_type = + is_fixed_struct ? "StructVector" : "TableVector"; + std::string full_wrapper_type = + wrapper_type + "<" + elem_type_name + ">"; + + if (field.IsRequired()) { + code += " public " + full_wrapper_type + " " + field_name; + code += " { get { int o = __p.__offset(" + offset_val + "); "; + code += "return new " + full_wrapper_type; + code += "(__p, o, " + element_size + "); } }\n"; + } else { + code += " public " + full_wrapper_type + "? " + field_name; + code += " { get { int o = __p.__offset(" + offset_val + "); "; + code += "return o != 0 ? new " + full_wrapper_type; + code += "(__p, o, " + element_size + ") : null; } }\n"; + } + } + } + + // Generate StringVector/StringVectorSpan property for string vectors + if (!IsArray(field.value.type) && + vectortype.base_type == BASE_TYPE_STRING) { + std::string field_name = Name(field); + if (field_name == struct_def.name) { field_name += "_"; } + auto offset_val = NumToString(field.value.offset); + + if (IsSpanMode()) { + if (field.IsRequired()) { + code += " public StringVectorSpan " + field_name; + code += " { get { int o = __p.__offset(" + offset_val + "); "; + code += "return new StringVectorSpan(__p, o); } }\n"; + } else { + code += " public RefStructNullable "; + code += field_name; + code += " { get { int o = __p.__offset(" + offset_val + "); "; + code += "return o != 0 ? "; + code += "new RefStructNullable"; + code += "(new StringVectorSpan(__p, o)) : default; } }\n"; + } + } else { + if (field.IsRequired()) { + code += " public StringVector " + field_name; + code += " { get { int o = __p.__offset(" + offset_val + "); "; + code += "return new StringVector(__p, o); } }\n"; + } else { + code += " public StringVector? " + field_name; + code += " { get { int o = __p.__offset(" + offset_val + "); "; + code += "return o != 0 ? new StringVector(__p, o) : null; } }\n"; + } + } + } + + // Generate UnionVector/UnionVectorSpan property for union vectors + if (!IsArray(field.value.type) && + vectortype.base_type == BASE_TYPE_UNION) { + std::string field_name = Name(field); + if (field_name == struct_def.name) { field_name += "_"; } + auto value_offset_val = NumToString(field.value.offset); + // The type vector is always the field right before the value vector + // (offset - 2) + auto type_offset_val = NumToString(field.value.offset - 2); + std::string element_size = NumToString(InlineSize(vectortype)); + + if (IsSpanMode()) { + std::string wrapper_type = "UnionVectorSpan"; + + if (field.IsRequired()) { + code += " public " + wrapper_type + " " + field_name; + code += + " { get { int o = __p.__offset(" + value_offset_val + "); "; + code += "return new " + wrapper_type; + code += "(__p, o, " + element_size + "); } }\n"; + } else { + code += " public RefStructNullable<" + wrapper_type + "> "; + code += field_name; + code += + " { get { int o = __p.__offset(" + value_offset_val + "); "; + code += "return o != 0 ? new RefStructNullable<"; + code += wrapper_type + ">(new " + wrapper_type; + code += "(__p, o, " + element_size + ")) : default; } }\n"; + } + } else { + // Use C# nullable for non-spanmode code + std::string wrapper_type = "UnionVector"; + + if (field.IsRequired()) { + code += " public " + wrapper_type + " " + field_name; + code += + " { get { int o = __p.__offset(" + value_offset_val + "); "; + code += "return new " + wrapper_type; + code += "(__p, o, " + element_size + "); } }\n"; + } else { + code += " public " + wrapper_type + "? " + field_name; + code += + " { get { int o = __p.__offset(" + value_offset_val + "); "; + code += "return o != 0 ? new " + wrapper_type; + code += "(__p, o, " + element_size + ") : null; } }\n"; + } + } + } + // See if we should generate a by-key accessor. + if (field.value.type.element == BASE_TYPE_STRUCT && + !field.value.type.struct_def->fixed) { + auto &sd = *field.value.type.struct_def; + auto &fields = sd.fields.vec; + for (auto kit = fields.begin(); kit != fields.end(); ++kit) { + auto &key_field = **kit; + if (key_field.key) { + auto qualified_name = NamespacedName(sd); + code += " public bool TryGet" + Name(field) + "ByKey("; + code += GenTypeGet(key_field.value.type) + " key, out " + + qualified_name + " value) { int o = __p.__offset(" + + NumToString(field.value.offset) + + "); if (o != 0) { return " + qualified_name + + ".TryGetByKey(__p.__vector(o), key, __p.bb, out value); " + "} value = default; return false; }\n"; + break; + } + } + } + } + // Generate a ByteBuffer accessor for strings & vectors of scalars. + if ((IsVector(field.value.type) && + IsScalar(field.value.type.VectorType().base_type)) || + IsString(field.value.type)) { + bool is_string_field = IsString(field.value.type); + auto offset_val = NumToString(field.value.offset); + if (!is_string_field) { + std::string accessor_name = Name(field); + std::string element_type = + GenTypeBasic(field.value.type.VectorType()); + std::string span_type = "ReadOnlySpan<" + element_type + ">"; + + if (field.IsRequired()) { + // Required field - return span directly without nullable wrapper + code += " public " + span_type + " " + accessor_name; + code += " { get { return __p.__vector_as_span<" + element_type; + code += ">(" + offset_val + "); } }\n"; + } else { + // Optional field - wrap in RefStructNullable for null handling + std::string nullable_type = "RefStructNullable<" + span_type + ">"; + code += " public " + nullable_type + " " + accessor_name; + code += " { get { int o = __p.__offset(" + offset_val + "); "; + code += "return o != 0 ? new " + nullable_type; + code += "(__p.__vector_as_span<" + element_type; + code += ">(" + offset_val + ")) : default; } }\n"; + } + } else { + // Generate as method for strings: + // public ReadOnlySpan GetNameBytes() { return ...; } + std::string accessor_name = "Get" + Name(field) + "Bytes"; + auto vec_type = GenTypeBasic(field.value.type.VectorType()); + code += " public ReadOnlySpan<" + vec_type + "> "; + code += accessor_name + "() { return "; + code += "__p.__vector_as_span<" + vec_type + ">("; + code += offset_val; + code += "); }\n"; + } + + if (parser_.opts.mutable_buffer) { + auto vec_type = GenTypeBasic(field.value.type.VectorType()); + code += " public RefStructNullable> Mutable"; + code += Name(field); + code += " { get { int o = __p.__offset("; + code += offset_val; + code += "); return o != 0 ? new RefStructNullable("; + code += offset_val; + code += ")) : default; } }\n"; + } + } + + // Generate Length property and ByteBuffer accessor for arrays in structs. + if (IsArray(field.value.type) && struct_def.fixed && + IsScalar(field.value.type.VectorType().base_type)) { + auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + + // Generate Length constant + code += " public const int " + camel_name; + code += "Length = "; + code += NumToString(field.value.type.fixed_length); + code += ";\n"; + + code += " public ReadOnlySpan<" + + GenTypeBasic(field.value.type.VectorType()) + "> Get"; + code += camel_name; + code += "Bytes() { return "; + + // For byte arrays, we can return the span directly + if (field.value.type.VectorType().base_type == BASE_TYPE_UCHAR) { + code += "__p.bb.ToReadOnlySpan(__p.bb_pos + "; + code += NumToString(field.value.offset); + code += ", "; + code += NumToString(field.value.type.fixed_length); + code += ")"; + } else { + // For other types, we need to cast the byte span + code += "__p.bb.GetReadOnlySpan<" + + GenTypeBasic(field.value.type.VectorType()); + code += ">(__p.bb_pos + "; + code += NumToString(field.value.offset); + code += ", "; + code += NumToString(field.value.type.fixed_length); + code += ")"; + } + code += "; }\n"; + + if (parser_.opts.mutable_buffer) { + code += " public Span<" + + GenTypeBasic(field.value.type.VectorType()) + "> Mutable"; + code += camel_name; + code += " { get { return "; + + if (field.value.type.VectorType().base_type == BASE_TYPE_UCHAR) { + code += "__p.bb.ToSpan(__p.bb_pos + "; + code += NumToString(field.value.offset); + code += ", "; + code += NumToString(field.value.type.fixed_length); + code += ")"; + } else { + code += + "__p.bb.GetSpan<" + GenTypeBasic(field.value.type.VectorType()); + code += ">(__p.bb_pos + "; + code += NumToString(field.value.offset); + code += ", "; + code += NumToString(field.value.type.fixed_length); + code += ")"; + } + code += "; } }\n"; + } + } + + // generate object accessors if is nested_flatbuffer + if (field.nested_flatbuffer) { + auto nested_type_name = NamespacedName(*field.nested_flatbuffer); + auto nested_method_name = + Name(field) + "As" + field.nested_flatbuffer->name; + auto get_nested_method_name = nested_method_name; + get_nested_method_name = "Get" + nested_method_name; + if (IsSpanMode()) { + obj = "(new " + nested_type_name + "())"; + code += " public " + nested_type_name + " "; + code += get_nested_method_name + "("; + code += ") { int o = __p.__offset("; + code += NumToString(field.value.offset) + "); "; + code += "return o != 0 ? " + obj + ".__assign("; + code += "__p."; + code += "__indirect(__p.__vector(o)), "; + code += "__p.bb) : default; }\n"; + } else { + conditional_cast = "(" + nested_type_name + "?)"; + obj = "(new " + nested_type_name + "())"; + code += " public " + nested_type_name + "? "; + code += get_nested_method_name + "("; + code += ") { int o = __p.__offset("; + code += NumToString(field.value.offset) + "); "; + code += "return o != 0 ? " + conditional_cast + obj + ".__assign("; + code += "__p."; + code += "__indirect(__p.__vector(o)), "; + code += "__p.bb) : null; }\n"; + } + } + // Generate mutators for scalar fields or vectors of scalars. + if (parser_.opts.mutable_buffer) { + auto is_series = (IsSeries(field.value.type)); + bool is_vector = is_series && !IsArray(field.value.type); + + if (!is_vector) { + const auto &underlying_type = + is_series ? field.value.type.VectorType() : field.value.type; + // Boolean parameters have to be explicitly converted to byte + // representation. + auto setter_parameter = + underlying_type.base_type == BASE_TYPE_BOOL + ? "(byte)(" + EscapeKeyword(field.name) + " ? 1 : 0)" + : EscapeKeyword(field.name); + auto mutator_prefix = "Mutate"; + // A vector mutator also needs the index of the vector element it + // should mutate. + auto mutator_params = (is_series ? "(int j, " : "(") + + GenTypeGet(underlying_type) + " " + + EscapeKeyword(field.name) + ") { "; + auto setter_index = + is_series + ? "__p." + + (IsArray(field.value.type) + ? "bb_pos + " + NumToString(field.value.offset) + : "__vector(o)") + + +" + j * " + NumToString(InlineSize(underlying_type)) + : (struct_def.fixed + ? "__p.bb_pos + " + NumToString(field.value.offset) + : "o + __p.bb_pos"); + if (IsScalar(underlying_type.base_type) && + !IsUnion(field.value.type)) { + code += " public "; + code += struct_def.fixed ? "void " : "bool "; + code += mutator_prefix + Name(field); + code += mutator_params; + if (struct_def.fixed) { + code += GenSetter(underlying_type) + "(" + setter_index + ", "; + code += src_cast + setter_parameter + "); }\n"; + } else { + code += "int o = __p.__offset("; + code += NumToString(field.value.offset) + ");"; + code += " if (o != 0) { " + GenSetter(underlying_type); + code += "(" + setter_index + ", " + src_cast + setter_parameter + + "); return true; } else { return false; } }\n"; + } + } + } + } + if (parser_.opts.java_primitive_has_method && + IsScalar(field.value.type.base_type) && !struct_def.fixed) { + auto vt_offset_constant = + " public static final int VT_" + + ConvertCase(field.name, Case::kScreamingSnake) + " = " + + NumToString(field.value.offset) + ";"; + + code += vt_offset_constant; + code += "\n"; + } + } + code += "\n"; + auto struct_has_create = false; + std::set field_has_create_set; + flatbuffers::FieldDef *key_field = nullptr; + if (struct_def.fixed) { + struct_has_create = true; + // create a struct constructor function + code += " public static " + GenOffsetType(struct_def) + " "; + code += "Create"; + code += struct_def.name + "(" + BuilderParam(); + GenStructArgs(struct_def, code_ptr, ""); + code += ") {\n"; + GenStructBody(struct_def, code_ptr, ""); + code += " return "; + code += GenOffsetConstruct(struct_def, "builder.Offset"); + code += ";\n }\n"; + } else { + // Generate a method that creates a table in one go. This is only possible + // when the table has no struct fields, since those have to be created + // inline, and there's no way to do so in Java. + bool has_no_struct_fields = true; + int num_fields = 0; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (IsStruct(field.value.type)) { + has_no_struct_fields = false; + } else { + num_fields++; + } + } + // JVM specifications restrict default constructor params to be < 255. + // Longs and doubles take up 2 units, so we set the limit to be < 127. + // In SpanBuffer mode, skip Object API generation, so don't use struct + // fields pattern + bool use_object_api_for_create = + opts.generate_object_based_api && !IsSpanMode(); + if ((has_no_struct_fields || use_object_api_for_create) && num_fields && + num_fields < 127) { + struct_has_create = true; + // Generate a table constructor of the form: + // public static int createName(FlatBufferBuilder builder, args...) + code += " public static " + GenOffsetType(struct_def) + " "; + code += "Create" + struct_def.name; + code += "(" + BuilderParam(); + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + code += ",\n "; + if (IsStruct(field.value.type) && use_object_api_for_create) { + code += WrapInNameSpace( + field.value.type.struct_def->defined_namespace, + GenTypeName_ObjectAPI(field.value.type.struct_def->name, opts)); + code += " "; + code += EscapeKeyword(field.name); + code += " = null"; + } else { + code += GenTypeBasic(field.value.type); + if (field.IsScalarOptional()) { code += "?"; } + code += " "; + code += EscapeKeyword(field.name); + if (!IsScalar(field.value.type.base_type)) code += "Offset"; + + code += " = "; + code += GenDefaultValueBasic(field); + } + } + code += ") {\n builder."; + code += "StartTable("; + code += NumToString(struct_def.fields.vec.size()) + ");\n"; + for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; + size; size /= 2) { + for (auto it = struct_def.fields.vec.rbegin(); + it != struct_def.fields.vec.rend(); ++it) { + auto &field = **it; + if (!field.deprecated && + (!struct_def.sortbysize || + size == SizeOf(field.value.type.base_type))) { + code += " " + struct_def.name + "."; + code += "Add"; + code += Name(field) + "(" + BuilderArg() + ", "; + if (IsStruct(field.value.type) && use_object_api_for_create) { + code += GenTypePointer(field.value.type) + ".Pack(" + + BuilderArg() + ", " + EscapeKeyword(field.name) + ")"; + } else { + code += EscapeKeyword(field.name); + if (!IsScalar(field.value.type.base_type)) code += "Offset"; + } + + code += ");\n"; + } + } + } + code += " return " + struct_def.name + "."; + code += "End" + struct_def.name; + code += "(" + BuilderArg() + ");\n }\n\n"; + } + // Generate a set of static methods that allow table construction, + // of the form: + // public static void addName(FlatBufferBuilder builder, short name) + // { builder.addShort(id, name, default); } + // Unlike the Create function, these always work. + code += " public static void Start"; + code += struct_def.name; + code += "(" + BuilderParam() + ") { builder."; + code += "StartTable("; + code += NumToString(struct_def.fields.vec.size()) + "); }\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (field.key) key_field = &field; + code += " public static void Add"; + code += Name(field); + code += "(" + BuilderParam() + ", "; + code += GenTypeBasic(field.value.type); + auto argname = ConvertCase(field.name, Case::kLowerCamel); + if (!IsScalar(field.value.type.base_type)) argname += "Offset"; + if (field.IsScalarOptional()) { code += "?"; } + code += " " + EscapeKeyword(argname) + ") { "; + + if (IsStruct(field.value.type)) { + // For true structs (fixed size), use generic AddStruct method + code += "builder.AddStruct("; + code += NumToString(it - struct_def.fields.vec.begin()) + ", "; + code += EscapeKeyword(argname); + if (!field.IsScalarOptional()) { + code += ", "; + code += GenDefaultValue(field, false); + } + } else if (!IsScalar(field.value.type.base_type) && + field.value.type.base_type != BASE_TYPE_UNION) { + // Use generic AddOffset for offset types (string, vector, table) + code += "builder.AddOffset("; + code += NumToString(it - struct_def.fields.vec.begin()) + ", "; + code += EscapeKeyword(argname); + if (!field.IsScalarOptional()) { + code += ", "; + code += GenDefaultValue(field, false); + } + } else { + // Use regular Add method for scalars and unions (unions store int + // values) + code += "builder.Add" + GenMethod(field.value.type) + "("; + code += NumToString(it - struct_def.fields.vec.begin()) + ", "; + code += SourceCastBasic(field.value.type, field.IsScalarOptional()); + code += EscapeKeyword(argname); + if (!field.IsScalarOptional()) { + code += ", "; + code += GenDefaultValue(field, false); + } + } + code += "); }\n"; + if (IsVector(field.value.type)) { + auto vector_type = field.value.type.VectorType(); + auto alignment = InlineAlignment(vector_type); + auto elem_size = InlineSize(vector_type); + if (!IsStruct(vector_type)) { + field_has_create_set.insert(&field); + std::string vector_element_type; + // This is the key part - determine the array type + if (vector_type.base_type == BASE_TYPE_STRING) { + vector_element_type = "StringOffset"; + } else if (vector_type.base_type == BASE_TYPE_UNION) { + // For union vectors, use int[] for the data vector + vector_element_type = "int"; + } else { + vector_element_type = GenTypeBasic(vector_type); + } + + code += " public static VectorOffset "; + code += "Create"; + code += Name(field); + code += "VectorBlock(" + BuilderParam() + ", "; + code += ScopedPrefix() + "Span<" + vector_element_type + "> data) "; + code += "{ builder.StartVector("; + code += NumToString(elem_size); + code += ", data.Length, "; + code += NumToString(alignment); + code += "); "; + + // For offset types, use AddOffsetSpan; for scalar types, use + // AddSpan + if (vector_type.base_type == BASE_TYPE_UNION) { + code += "builder.AddOffsetSpan(data); "; + } else if (vector_type.base_type == BASE_TYPE_STRING || + vector_type.struct_def) { + code += + "builder.AddOffsetSpan<" + vector_element_type + ">(data); "; + } else { + // For scalar types, add elements directly + code += "builder.AddSpan<" + vector_element_type + ">(data); "; + } + + code += "return builder.EndVector(); }\n"; + + code += " public static VectorOffset "; + code += "Create"; + code += Name(field); + code += "Vector(" + BuilderParam() + ", "; + code += ScopedPrefix() + "Span<" + vector_element_type + "> data) "; + code += "{ return Create"; + code += Name(field); + code += "VectorBlock(" + BuilderArg() + ", data); }\n"; + } + // Generate a method to start a vector, data to be added manually + // after. + code += " public static void Start"; + code += Name(field); + code += "Vector(" + BuilderParam() + ", int numElems) "; + code += "{ builder.StartVector("; + code += NumToString(elem_size); + code += ", numElems, " + NumToString(alignment); + code += "); }\n"; + } + } + code += " public static " + GenOffsetType(struct_def) + " "; + code += "End" + struct_def.name; + code += "(" + BuilderParam() + ") {\n int o = builder."; + code += "EndTable();\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (!field.deprecated && field.IsRequired()) { + code += " builder.Required(o, "; + code += NumToString(field.value.offset); + code += "); // " + field.name + "\n"; + } + } + code += " return " + GenOffsetConstruct(struct_def, "o") + ";\n }\n"; + if (parser_.root_struct_def_ == &struct_def) { + std::string size_prefix[] = { "", "SizePrefixed" }; + for (int i = 0; i < 2; ++i) { + code += " public static void "; + code += "Finish" + size_prefix[i] + struct_def.name; + code += "Buffer(" + BuilderParam() + ", " + GenOffsetType(struct_def); + code += " offset) {"; + code += " builder.Finish" + size_prefix[i] + "(offset"; + code += ".Value"; + + if (parser_.file_identifier_.length()) + code += ", \"" + parser_.file_identifier_ + "\""; + code += "); }\n"; + } + } + } + // Only generate key compare function for table, + // because `key_field` is not set for struct + if (struct_def.has_key && !struct_def.fixed) { + FLATBUFFERS_ASSERT(key_field); + auto name = Name(*key_field); + if (name == struct_def.name) { name += "_"; } + code += "\n public static VectorOffset "; + code += "CreateSortedVectorOf" + struct_def.name; + code += "(" + BuilderParam() + ", "; + code += + ScopedPrefix() + "Span> offsets) {\n"; + code += + " var comparer = " + GenKeyGetter(struct_def, key_field) + ";\n"; + code += " RefStructSorters.Sort(offsets, ref comparer);\n"; + code += " return builder.CreateVectorOfTables<" + struct_def.name + + ">(offsets);\n"; + code += " }\n"; + + code += "\n public static bool TryGetByKey("; + code += "int vectorLocation, "; + code += GenTypeGet(key_field->value.type); + code += " key, " + BufferTypeName() + " bb, out " + struct_def.name + + " value) {\n"; + code += " return SortedVectorUtils.TryGetByKey"; + + if (key_field->value.type.base_type == BASE_TYPE_STRING) { + code += "<" + struct_def.name + ", " + BufferTypeName() + ">"; + code += "(vectorLocation, key, ref bb, " + + NumToString(key_field->value.offset) + ", out value);\n"; + } else { + code += "<" + struct_def.name + ", " + + GenTypeBasic(key_field->value.type, false) + ", " + + BufferTypeName() + ">"; + code += "(vectorLocation, key, ref bb, " + + NumToString(key_field->value.offset) + ", " + + GenDefaultValueBasic(*key_field) + ", out value);\n"; + } + + code += " }\n"; + } + + if (opts.generate_object_based_api) { + GenPackUnPack_ObjectAPI(struct_def, code_ptr, opts, struct_has_create, + field_has_create_set); + } + code += "}\n\n"; + + // Only generate the *T class in ByteBuffer mode, it's shared between both + // modes + if (opts.generate_object_based_api && !IsSpanMode()) { + GenStruct_ObjectAPI(struct_def, code_ptr, opts); + } + } + + // NOTE: GenVectorAccessObject from the original idl_gen_csharp.cpp is not + // used in either generator. Vector access is handled by StructVector/ + // TableVector wrappers and span-based accessors instead. + + std::string GenUnionVerify(const Type &union_type) const { + if (union_type.enum_def) { + const auto &enum_def = *union_type.enum_def; + + auto ret = "\n\nstatic public class " + enum_def.name + "Verify\n"; + ret += "{\n"; + ret += + " static public bool Verify(ref Google.FlatSpanBuffers.Verifier " + "verifier, " + "byte typeId, uint tablePos)\n"; + ret += " {\n"; + ret += " bool result = true;\n"; + + const auto union_enum_loop = [&]() { + ret += " switch((" + enum_def.name + ")typeId)\n"; + ret += " {\n"; + + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); + ++it) { + const auto &ev = **it; + if (ev.IsZero()) { continue; } + + ret += " case " + Name(enum_def) + "." + Name(ev) + ":\n"; + + if (IsString(ev.union_type)) { + ret += " result = verifier.VerifyUnionString(tablePos);\n"; + ret += " break;"; + } else if (ev.union_type.base_type == BASE_TYPE_STRUCT) { + if (!ev.union_type.struct_def->fixed) { + auto type = GenTypeGet(ev.union_type); + ret += " result = " + type + + "Verify.Verify(ref verifier, tablePos);\n"; + } else { + ret += " result = verifier.VerifyUnionData(tablePos, " + + NumToString(InlineSize(ev.union_type)) + ", " + + NumToString(InlineAlignment(ev.union_type)) + ");\n"; + ; + } + ret += " break;"; + } else { + FLATBUFFERS_ASSERT(false); + } + ret += "\n"; + } + + ret += " default: result = true;\n"; + ret += " break;\n"; + ret += " }\n"; + ret += " return result;\n"; + }; + + union_enum_loop(); + ret += " }\n"; + ret += "}\n"; + ret += "\n"; + + return ret; + } + FLATBUFFERS_ASSERT(0); + return ""; + } + + void GenEnum_ObjectAPI(EnumDef &enum_def, std::string *code_ptr, + const IDLOptions &opts) const { + auto &code = *code_ptr; + if (enum_def.generated) return; + if (!enum_def.is_union) return; + auto union_name = enum_def.name + "Union"; + auto class_member = std::string("Value"); + if (class_member == enum_def.name) { class_member += "_"; }; + // Add JsonConverter attribute to the class so it's used when in collections + if (opts.cs_gen_json_serializer) { + code += "[System.Text.Json.Serialization.JsonConverter(typeof(" + + union_name + "_JsonConverter))]\n"; + } + if (enum_def.attributes.Lookup("private")) { + code += "internal "; + } else { + code += "public "; + } + code += "class " + union_name + " {\n"; + // Type + code += " public " + enum_def.name + " Type { get; set; }\n"; + // Value + code += " public object " + class_member + " { get; set; }\n"; + code += "\n"; + // Constructor + code += " public " + union_name + "() {\n"; + code += " this.Type = " + enum_def.name + "." + + enum_def.Vals()[0]->name + ";\n"; + code += " this." + class_member + " = null;\n"; + code += " }\n\n"; + // As + code += " public T As() where T : class { return this." + class_member + + " as T; }\n"; + // As, From + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { + auto &ev = **it; + if (ev.union_type.base_type == BASE_TYPE_NONE) continue; + auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts); + std::string accessibility = + (ev.union_type.base_type == BASE_TYPE_STRUCT && + ev.union_type.struct_def->attributes.Lookup("private")) + ? "internal" + : "public"; + // As + code += " " + accessibility + " " + type_name + " As" + ev.name + + "() { return this.As<" + type_name + ">(); }\n"; + // From + auto lower_ev_name = ev.name; + std::transform(lower_ev_name.begin(), lower_ev_name.end(), + lower_ev_name.begin(), CharToLower); + code += " " + accessibility + " static " + union_name + " From" + + ev.name + "(" + type_name + " _" + lower_ev_name + + ") { return new " + union_name + "{ Type = " + Name(enum_def) + + "." + Name(ev) + ", " + class_member + " = _" + lower_ev_name + + " }; }\n"; + } + code += "\n"; + // Pack() + code += + " public static int Pack(Google.FlatSpanBuffers.FlatBufferBuilder " + "builder, " + + union_name + " _o) {\n"; + code += " switch (_o.Type) {\n"; + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { + auto &ev = **it; + if (ev.union_type.base_type == BASE_TYPE_NONE) { + code += " default: return 0;\n"; + } else { + code += " case " + Name(enum_def) + "." + Name(ev) + ": return "; + if (IsString(ev.union_type)) { + code += "builder.CreateString(_o.As" + ev.name + "()).Value;\n"; + } else { + code += BaseNamespacedName(*ev.union_type.struct_def) + + ".Pack(builder, _o.As" + ev.name + "()).Value;\n"; + } + } + } + code += " }\n"; + code += " }\n"; + // Pack() for SpanBuf mode - uses ref parameter for ref struct builder + code += + " public static int Pack(ref " + "Google.FlatSpanBuffers.FlatSpanBufferBuilder " + "builder, " + + union_name + " _o) {\n"; + code += " switch (_o.Type) {\n"; + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { + auto &ev = **it; + if (ev.union_type.base_type == BASE_TYPE_NONE) { + code += " default: return 0;\n"; + } else { + code += " case " + Name(enum_def) + "." + Name(ev) + ": return "; + if (IsString(ev.union_type)) { + code += "builder.CreateString(_o.As" + ev.name + "()).Value;\n"; + } else { + code += SpanBufNamespacedName(*ev.union_type.struct_def) + + ".Pack(ref builder, _o.As" + ev.name + "()).Value;\n"; + } + } + } + code += " }\n"; + code += " }\n"; + code += "}\n\n"; + + // JsonConverter + if (opts.cs_gen_json_serializer) { + if (enum_def.attributes.Lookup("private")) { + code += "internal "; + } else { + code += "public "; + } + code += "class " + union_name + + "_JsonConverter : System.Text.Json.Serialization.JsonConverter<" + + union_name + "> {\n"; + + // Read method - deserializes {"Type":"EnumName","Value":{...}} format + code += + " public override " + union_name + + " Read(ref System.Text.Json.Utf8JsonReader reader, System.Type " + "typeToConvert, System.Text.Json.JsonSerializerOptions options) {\n"; + code += + " if (reader.TokenType == System.Text.Json.JsonTokenType.Null) { " + "reader.Read(); return null; }\n"; + code += + " if (reader.TokenType != " + "System.Text.Json.JsonTokenType.StartObject) throw new " + "System.Text.Json.JsonException(\"Expected start of object for union " + "type\");\n"; + code += " " + Name(enum_def) + " unionType = " + Name(enum_def) + + ".NONE;\n"; + code += " " + union_name + " result = new " + union_name + "();\n"; + code += " while (reader.Read()) {\n"; + code += + " if (reader.TokenType == " + "System.Text.Json.JsonTokenType.EndObject) break;\n"; + code += + " if (reader.TokenType != " + "System.Text.Json.JsonTokenType.PropertyName) continue;\n"; + code += " string propName = reader.GetString();\n"; + code += " reader.Read();\n"; + code += " if (propName == \"Type\") {\n"; + code += " string typeName = reader.GetString();\n"; + code += " if (System.Enum.TryParse<" + Name(enum_def) + + ">(typeName, out var parsed)) unionType = parsed;\n"; + code += " } else if (propName == \"Value\") {\n"; + code += " result.Type = unionType;\n"; + code += " switch (unionType) {\n"; + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); + ++it) { + auto &ev = **it; + if (ev.union_type.base_type == BASE_TYPE_NONE) { + code += " default: break;\n"; + } else if (IsString(ev.union_type)) { + code += " case " + Name(enum_def) + "." + Name(ev) + + ": result." + class_member + + " = reader.GetString(); break;\n"; + } else { + auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts); + code += " case " + Name(enum_def) + "." + Name(ev) + + ": result." + class_member + + " = System.Text.Json.JsonSerializer.Deserialize<" + + type_name + ">(ref reader, options); break;\n"; + } + } + code += " }\n"; + code += " }\n"; + code += " }\n"; + code += " return result;\n"; + code += " }\n"; + + // ReadWithTypeContext - kept for compatibility + code += + " public " + union_name + + " ReadWithTypeContext(ref System.Text.Json.Utf8JsonReader reader, " + + union_name + + " _o, System.Text.Json.JsonSerializerOptions options) {\n"; + code += " if (_o == null) return null;\n"; + code += " switch (_o.Type) {\n"; + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); + ++it) { + auto &ev = **it; + if (ev.union_type.base_type == BASE_TYPE_NONE) { + code += " default: break;\n"; + } else { + auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts); + code += " case " + Name(enum_def) + "." + Name(ev) + ": _o." + + class_member + + " = System.Text.Json.JsonSerializer.Deserialize<" + + type_name + ">(ref reader, options); break;\n"; + } + } + code += " }\n"; + code += " return _o;\n"; + code += " }\n"; + + code += + " public override void Write(System.Text.Json.Utf8JsonWriter " + "writer, " + + union_name + + " value, System.Text.Json.JsonSerializerOptions options) {\n"; + code += " if (value == null || value." + class_member + + " == null) { writer.WriteNullValue(); return; }\n"; + code += " writer.WriteStartObject();\n"; + code += " writer.WriteString(\"Type\", value.Type.ToString());\n"; + code += " writer.WritePropertyName(\"Value\");\n"; + code += " System.Text.Json.JsonSerializer.Serialize(writer, value." + + class_member + ", value." + class_member + + ".GetType(), options);\n"; + code += " writer.WriteEndObject();\n"; + code += " }\n"; + code += "}\n\n"; + } + } + + std::string GenTypeName_ObjectAPI(const std::string &name, + const IDLOptions &opts) const { + return opts.object_prefix + name + opts.object_suffix; + } + + // Generate union unpacking code for both vector and non-vector unions. + void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string *code_ptr, + const std::string &camel_name, + const std::string &camel_name_short, + bool is_vector) const { + auto &code = *code_ptr; + std::string varialbe_name = "_o." + camel_name; + std::string class_member = "Value"; + if (class_member == enum_def.name) class_member += "_"; + std::string indent = " "; + // Use base namespace for Object API types (they are shared between modes) + auto enum_type_name = BaseNamespacedEnumName(enum_def); + auto union_type_name = enum_type_name + "Union"; + + if (is_vector) { + varialbe_name = "_o_" + camel_name; + indent = " "; // Inside if block and for loop + // Cache the type element to avoid repeated span indexing + code += indent + "var _" + camel_name_short + "_type = _" + + camel_name_short + "_types_value[_j];\n"; + code += + indent + "var " + varialbe_name + " = _o." + camel_name + "[_j];\n"; + code += indent + "if (" + varialbe_name + " == null) {\n"; + code += + indent + " " + varialbe_name + " = new " + union_type_name + "();\n"; + code += indent + " _o." + camel_name + "[_j] = " + varialbe_name + ";\n"; + code += indent + "}\n"; + code += indent + "var _" + camel_name_short + + "_old_type = " + varialbe_name + ".Type;\n"; + code += + indent + varialbe_name + ".Type = _" + camel_name_short + "_type;\n"; + code += indent + "switch (_" + camel_name_short + "_type) {\n"; + } else { + // Check if we can reuse the existing union wrapper + code += indent + "if (" + varialbe_name + " == null) {\n"; + code += + indent + " " + varialbe_name + " = new " + union_type_name + "();\n"; + code += indent + "}\n"; + code += indent + "var _" + camel_name_short + + "OldType = " + varialbe_name + ".Type;\n"; + code += indent + varialbe_name + ".Type = this." + camel_name_short + + "Type;\n"; + code += indent + "switch (this." + camel_name_short + "Type) {\n"; + } + + for (auto eit = enum_def.Vals().begin(); eit != enum_def.Vals().end(); + ++eit) { + auto &ev = **eit; + if (ev.union_type.base_type == BASE_TYPE_NONE) { + code += indent + " default:\n"; + code += + indent + " " + varialbe_name + "." + class_member + " = null;\n"; + code += indent + " break;\n"; + } else { + auto case_enum_value = enum_type_name + "." + Name(ev); + code += indent + " case " + case_enum_value + ":\n"; + if (IsString(ev.union_type)) { + if (is_vector) { + code += indent + " " + varialbe_name + "." + class_member + + " = _" + camel_name_short + "_value.GetAsString(_j);\n"; + } else { + code += indent + " " + varialbe_name + "." + class_member + + " = this." + camel_name + "AsString();\n"; + } + } else { + // Try to reuse the inner object if the old type matches + auto inner_type_name = + BaseNamespacedName(*ev.union_type.struct_def) + "T"; + if (is_vector) { + auto old_type_var = "_" + camel_name_short + "_old_type"; + code += indent + " if (" + old_type_var + + " == " + case_enum_value + ") {\n"; + code += indent + " _" + camel_name_short + "_value.GetAs<" + + GenTypeGet(ev.union_type) + ">(_j).UnPackTo((" + + inner_type_name + ")" + varialbe_name + "." + class_member + + ");\n"; + code += indent + " } else {\n"; + code += indent + " " + varialbe_name + "." + class_member + + " = _" + camel_name_short + "_value.GetAs<" + + GenTypeGet(ev.union_type) + ">(_j).UnPack();\n"; + code += indent + " }\n"; + } else { + auto old_type_var = "_" + camel_name_short + "OldType"; + code += indent + " if (this." + camel_name + "<" + + GenTypeGet(ev.union_type) + ">().HasValue) {\n"; + code += indent + " if (" + old_type_var + + " == " + case_enum_value + ") {\n"; + code += indent + " this." + camel_name + "<" + + GenTypeGet(ev.union_type) + ">().Value.UnPackTo((" + + inner_type_name + ")" + varialbe_name + "." + class_member + + ");\n"; + code += indent + " } else {\n"; + code += indent + " " + varialbe_name + "." + class_member + + " = this." + camel_name + "<" + GenTypeGet(ev.union_type) + + ">().Value.UnPack();\n"; + code += indent + " }\n"; + code += indent + " } else {\n"; + code += indent + " " + varialbe_name + "." + class_member + + " = null;\n"; + code += indent + " }\n"; + } + } + code += indent + " break;\n"; + } + } + code += indent + "}\n"; + } + + void GenPackUnPack_ObjectAPI( + StructDef &struct_def, std::string *code_ptr, const IDLOptions &opts, + bool struct_has_create, + const std::set &field_has_create) const { + auto &code = *code_ptr; + auto struct_name = GenTypeName_ObjectAPI(struct_def.name, opts); + // UnPack() + code += " public " + struct_name + " UnPack() {\n"; + code += " var _o = new " + struct_name + "();\n"; + code += " this.UnPackTo(_o);\n"; + code += " return _o;\n"; + code += " }\n"; + // UnPackTo() + code += " public void UnPackTo(" + struct_name + " _o) {\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + auto camel_name_short = Name(field); + auto start = " _o." + camel_name + " = "; + switch (field.value.type.base_type) { + case BASE_TYPE_STRUCT: { + auto fixed = struct_def.fixed && field.value.type.struct_def->fixed; + auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); + if (fixed) { + code += " if (_o." + camel_name + " == null) _o." + camel_name + + " = new " + type_name + "();\n"; + code += " this." + camel_name + ".UnPackTo(_o." + camel_name + + ");\n"; + } else { + // Optional struct/table, reuse if it exists and has value + code += " if (this." + camel_name + ".HasValue) {\n"; + code += " if (_o." + camel_name + " == null) _o." + + camel_name + " = new " + type_name + "();\n"; + code += " this." + camel_name + ".Value.UnPackTo(_o." + + camel_name + ");\n"; + code += " } else {\n"; + code += " _o." + camel_name + " = null;\n"; + code += " }\n"; + } + break; + } + case BASE_TYPE_ARRAY: { + auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); + auto length_str = NumToString(field.value.type.fixed_length); + auto unpack_method = field.value.type.struct_def == nullptr ? "" + : field.value.type.struct_def->fixed + ? ".UnPack()" + : "?.UnPack()"; + code += start + "new " + type_name.substr(0, type_name.length() - 1) + + length_str + "];\n"; + code += " for (var _j = 0; _j < " + length_str + "; ++_j) { _o." + + camel_name + "[_j] = this." + camel_name + "(_j)" + + unpack_method + "; }\n"; + break; + } + case BASE_TYPE_VECTOR: + if (field.value.type.element == BASE_TYPE_UNION) { + auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); + code += " var _" + field.name + "_types = this." + + camel_name_short + "Type;\n"; + code += " var _" + field.name + " = this." + camel_name + ";\n"; + code += " var _" + field.name + "_len = _" + field.name + + ".HasValue ? _" + field.name + ".Value.Length : 0;\n"; + code += " if (_o." + camel_name + " == null) {\n"; + code += " _o." + camel_name + " = new " + type_name + "(_" + + field.name + "_len);\n"; + code += " }\n"; + code += " ObjectApiUtil.ResizeList(_o." + camel_name + ", _" + + field.name + "_len);\n"; + code += " if (_" + field.name + ".HasValue) {\n"; + code += " var _" + field.name + "_value = _" + field.name + + ".Value;\n"; + code += " var _" + field.name + "_types_value = _" + + field.name + "_types.Value;\n"; + code += " for (var _j = 0; _j < _" + field.name + + "_len; ++_j) {\n"; + GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr, + camel_name, field.name, true); + code += " }\n"; + code += " }\n"; + } else if (field.value.type.element != BASE_TYPE_UTYPE) { + auto fixed = field.value.type.struct_def == nullptr; + auto element_type = field.value.type.element; + // Check if element is a primitive/blittable type that can use span + // copy + auto is_scalar_element = + IsScalar(element_type) && element_type != BASE_TYPE_BOOL; + auto is_enum_element = IsEnum(field.value.type.VectorType()); + + bool use_property_access = (element_type == BASE_TYPE_STRUCT || + element_type == BASE_TYPE_STRING); + + if (fixed && (is_scalar_element || is_enum_element)) { + // Use span-based copy for primitive/enum types + auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); + code += " var _" + field.name + "_vec = this." + camel_name + + ";\n"; + code += " var _" + field.name + "_len = _" + field.name + + "_vec.HasValue ? _" + field.name + + "_vec.Value.Length : 0;\n"; + code += " if (_o." + camel_name + " == null) {\n"; + code += " _o." + camel_name + " = new " + type_name + "(_" + + field.name + "_len);\n"; + code += " }\n"; + code += " ObjectApiUtil.ResizeList(_o." + camel_name + ", _" + + field.name + "_len);\n"; + code += " if (_" + field.name + "_vec.HasValue) { _" + + field.name + + "_vec.Value.CopyTo(CollectionsMarshal.AsSpan(_o." + + camel_name + ")); }\n"; + } else if (fixed && use_property_access) { + // Non-blittable primitives, reuse list if exists + auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); + code += " var _" + field.name + "_vec = this." + camel_name + + ";\n"; + code += " var _" + field.name + "_len = _" + field.name + + "_vec.HasValue ? _" + field.name + + "_vec.Value.Length : 0;\n"; + code += " if (_o." + camel_name + " == null) {\n"; + code += " _o." + camel_name + " = new " + type_name + "(_" + + field.name + "_len);\n"; + code += " } else {\n"; + code += " _o." + camel_name + ".Clear();\n"; + code += " if (_o." + camel_name + ".Capacity < _" + + field.name + "_len) {\n"; + code += " _o." + camel_name + ".Capacity = _" + + field.name + "_len;\n"; + code += " }\n"; + code += " }\n"; + code += " if (_" + field.name + "_vec.HasValue) {\n"; + code += " var _" + field.name + "_value = _" + field.name + + "_vec.Value;\n"; + code += " for (var _j = 0; _j < _" + field.name + + "_len; ++_j) { _o." + camel_name + ".Add(_" + field.name + + "_value[_j]); }\n"; + code += " }\n"; + } else if (fixed) { + auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); + code += " var _" + field.name + "_vec = this." + camel_name + + ";\n"; + code += " var _" + field.name + "_len = _" + field.name + + "_vec.HasValue ? _" + field.name + + "_vec.Value.Length : 0;\n"; + code += " if (_o." + camel_name + " == null) {\n"; + code += " _o." + camel_name + " = new " + type_name + "(_" + + field.name + "_len);\n"; + code += " } else {\n"; + code += " _o." + camel_name + ".Clear();\n"; + code += " if (_o." + camel_name + ".Capacity < _" + + field.name + "_len) {\n"; + code += " _o." + camel_name + ".Capacity = _" + + field.name + "_len;\n"; + code += " }\n"; + code += " }\n"; + code += " if (_" + field.name + "_vec.HasValue) {\n"; + code += " for (var _j = 0; _j < _" + field.name + + "_len; ++_j) { _o." + camel_name + ".Add(_" + field.name + + "_vec.Value[_j]); }\n"; + code += " }\n"; + } else { + // Structs/tables - reuse list and inner objects where possible + auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); + auto element_type_name = GenTypeName_ObjectAPI( + field.value.type.struct_def->name, opts); + if (use_property_access) { + code += " var _" + field.name + "_vec = this." + camel_name + + ";\n"; + code += " var _" + field.name + "_len = _" + field.name + + "_vec.HasValue ? _" + field.name + + "_vec.Value.Length : 0;\n"; + code += " if (_o." + camel_name + " == null) {\n"; + code += " _o." + camel_name + " = new " + type_name + + "(_" + field.name + "_len);\n"; + code += " }\n"; + code += " ObjectApiUtil.ResizeList(_o." + camel_name + + ", _" + field.name + "_len);\n"; + code += " if (_" + field.name + "_vec.HasValue) {\n"; + code += " var _" + field.name + "_value = _" + field.name + + "_vec.Value;\n"; + code += " for (var _j = 0; _j < _" + field.name + + "_len; ++_j) {\n"; + code += " var _src = _" + field.name + "_value[_j];\n"; + code += " if (_o." + camel_name + "[_j] == null) { _o." + + camel_name + "[_j] = new " + element_type_name + + "(); }\n"; + code += " _src.UnPackTo(_o." + camel_name + "[_j]);\n"; + code += " }\n"; + code += " }\n"; + } else { + code += " var _" + field.name + "_len = this." + camel_name + + "Length;\n"; + code += " if (_o." + camel_name + " == null) {\n"; + code += " _o." + camel_name + " = new " + type_name + + "(_" + field.name + "_len);\n"; + code += " }\n"; + code += " ObjectApiUtil.ResizeList(_o." + camel_name + + ", _" + field.name + "_len);\n"; + code += " for (var _j = 0; _j < _" + field.name + + "_len; ++_j) {\n"; + code += " var _src = this." + camel_name + "(_j);\n"; + code += " if (_src.HasValue) {\n"; + code += " if (_o." + camel_name + "[_j] == null) { _o." + + camel_name + "[_j] = new " + element_type_name + + "(); }\n"; + code += + " _src.Value.UnPackTo(_o." + camel_name + "[_j]);\n"; + code += " } else {\n"; + code += " _o." + camel_name + "[_j] = null;\n"; + code += " }\n"; + code += " }\n"; + } + } + } + break; + case BASE_TYPE_UTYPE: break; + case BASE_TYPE_UNION: { + GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr, + camel_name, camel_name_short, false); + break; + } + default: { + code += start + "this." + camel_name + ";\n"; + break; + } + } + } + code += " }\n"; + // Pack() + code += " public static " + GenOffsetType(struct_def) + " Pack(" + + BuilderParam() + ", " + struct_name + " _o) {\n"; + code += " if (_o == null) return default(" + GenOffsetType(struct_def) + + ");\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + auto camel_name_short = Name(field); + // pre + switch (field.value.type.base_type) { + case BASE_TYPE_STRUCT: { + if (!field.value.type.struct_def->fixed) { + code += " var _" + field.name + " = _o." + camel_name + + " == null ? default(" + + GenOffsetType(*field.value.type.struct_def) + + ") : " + GenTypeGet(field.value.type) + ".Pack(" + + BuilderArg() + ", _o." + camel_name + ");\n"; + } else if (struct_def.fixed && struct_has_create) { + std::vector array_lengths; + FieldArrayLength tmp_array_length = { + field.name, + field.value.type.fixed_length, + }; + array_lengths.push_back(tmp_array_length); + GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr, + array_lengths); + } + break; + } + case BASE_TYPE_STRING: { + std::string create_string = + field.shared ? "CreateSharedString" : "CreateString"; + code += " var _" + field.name + " = _o." + camel_name + + " == null ? default(StringOffset) : " + "builder." + + create_string + "(_o." + camel_name + ");\n"; + break; + } + case BASE_TYPE_VECTOR: { + if (field_has_create.find(&field) != field_has_create.end()) { + auto property_name = camel_name; + auto gen_for_loop = true; + std::string array_name = "__" + field.name; + std::string array_type = ""; + std::string to_array = ""; + std::string element_size = "4"; // default for offsets and ints + switch (field.value.type.element) { + case BASE_TYPE_STRING: { + std::string create_string = + field.shared ? "CreateSharedString" : "CreateString"; + array_type = "StringOffset"; + to_array += "builder." + create_string + "(_o." + + property_name + "[_j])"; + element_size = "4"; + break; + } + case BASE_TYPE_STRUCT: + array_type = "Offset<" + GenTypeGet(field.value.type) + ">"; + to_array = GenTypeGet(field.value.type) + ".Pack(" + + BuilderArg() + ", _o." + property_name + "[_j])"; + element_size = "4"; + break; + case BASE_TYPE_UTYPE: + property_name = camel_name.substr(0, camel_name.size() - 4); + // Union enum types are always in base namespace + array_type = BaseNamespacedEnumName(*field.value.type.enum_def); + to_array = "_o." + property_name + "[_j].Type"; + // Enum size is typically 1 byte (sbyte/byte) + element_size = "1"; + break; + case BASE_TYPE_UNION: + array_type = "int"; + // Union wrapper types are always in base namespace + to_array = BaseNamespacedEnumName(*field.value.type.enum_def) + + "Union.Pack(" + BuilderArg() + ", _o." + + property_name + "[_j])"; + element_size = "4"; + break; + default: gen_for_loop = false; break; + } + code += " var _" + field.name + " = default(VectorOffset);\n"; + code += " if (_o." + property_name + " != null) {\n"; + if (gen_for_loop) { + // Use stackalloc for small arrays, ArrayPool for larger ones + const int stackalloc_threshold_bytes = 256; + std::string stackalloc_threshold = std::to_string( + stackalloc_threshold_bytes / std::stoi(element_size)); + std::string count_expr = "_o." + property_name + ".Count"; + code += + " var _" + field.name + "_len = " + count_expr + ";\n"; + code += " " + array_type + "[] _" + field.name + + "_arr = null;\n"; + code += " try {\n"; + code += " Span<" + array_type + "> " + array_name + + " = _" + field.name + "_len <= " + stackalloc_threshold + + "\n"; + code += " ? stackalloc " + array_type + "[_" + + field.name + "_len]\n"; + code += " : (_" + field.name + "_arr = ArrayPool<" + + array_type + ">.Shared.Rent(_" + field.name + + "_len)).AsSpan(0, _" + field.name + "_len);\n"; + code += " for (var _j = 0; _j < _" + field.name + + "_len; ++_j) { "; + code += array_name + "[_j] = " + to_array + "; }\n"; + code += " _" + field.name + " = Create" + + camel_name_short + "Vector(" + BuilderArg() + ", " + + array_name + ");\n"; + code += " } finally {\n"; + code += " if (_" + field.name + + "_arr != null) { ArrayPool<" + array_type + + ">.Shared.Return(_" + field.name + "_arr); }\n"; + code += " }\n"; + } else { + code += " _" + field.name + " = Create" + camel_name_short + + "Vector(" + BuilderArg() + + ", CollectionsMarshal.AsSpan(_o." + property_name + + "));\n"; + } + code += " }\n"; + } else { + auto pack_method = + field.value.type.struct_def == nullptr + ? "builder.Add" + GenMethod(field.value.type.VectorType()) + + "(_o." + camel_name + "[_j]);" + : GenTypeGet(field.value.type) + ".Pack(" + BuilderArg() + + ", _o." + camel_name + "[_j]);"; + code += " var _" + field.name + " = default(VectorOffset);\n"; + code += " if (_o." + camel_name + " != null) {\n"; + code += " Start" + camel_name_short + "Vector(" + + BuilderArg() + ", _o." + camel_name + ".Count);\n"; + code += " for (var _j = _o." + camel_name + + ".Count - 1; _j >= 0; --_j) { " + pack_method + " }\n"; + code += " _" + field.name + " = builder.EndVector();\n"; + code += " }\n"; + } + break; + } + case BASE_TYPE_ARRAY: { + if (field.value.type.struct_def != nullptr) { + std::vector array_lengths; + FieldArrayLength tmp_array_length = { + field.name, + field.value.type.fixed_length, + }; + array_lengths.push_back(tmp_array_length); + GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr, + array_lengths); + } else { + code += " var _" + field.name + " = _o." + camel_name + ";\n"; + } + break; + } + case BASE_TYPE_UNION: { + // Union enums and wrappers are always in base namespace (shared + // between modes) + code += " var _" + field.name + "_type = _o." + camel_name + + " == null ? " + + BaseNamespacedEnumName(*field.value.type.enum_def) + + ".NONE : " + "_o." + camel_name + ".Type;\n"; + code += + " var _" + field.name + " = _o." + camel_name + + " == null ? 0 : " + GenTypeGet_ObjectAPI(field.value.type, opts) + + ".Pack(" + BuilderArg() + ", _o." + camel_name + ");\n"; + break; + } + default: break; + } + } + if (struct_has_create) { + // Create + code += " return Create" + struct_def.name + "(\n"; + code += " " + BuilderArg(); + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + switch (field.value.type.base_type) { + case BASE_TYPE_STRUCT: { + if (struct_def.fixed) { + GenStructPackCall_ObjectAPI(*field.value.type.struct_def, + code_ptr, + " _" + field.name + "_"); + } else { + code += ",\n"; + if (field.value.type.struct_def->fixed) { + if (opts.generate_object_based_api) + code += " _o." + camel_name; + else + code += " " + GenTypeGet(field.value.type) + ".Pack(" + + BuilderArg() + ", _o." + camel_name + ")"; + } else { + code += " _" + field.name; + } + } + break; + } + case BASE_TYPE_ARRAY: { + if (field.value.type.struct_def != nullptr) { + GenStructPackCall_ObjectAPI(*field.value.type.struct_def, + code_ptr, + " _" + field.name + "_"); + } else { + code += ",\n"; + code += " _" + field.name; + } + break; + } + case BASE_TYPE_UNION: FLATBUFFERS_FALLTHROUGH(); // fall thru + case BASE_TYPE_UTYPE: FLATBUFFERS_FALLTHROUGH(); // fall thru + case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH(); // fall thru + case BASE_TYPE_VECTOR: { + code += ",\n"; + code += " _" + field.name; + break; + } + default: // scalar + code += ",\n"; + code += " _o." + camel_name; + break; + } + } + code += ");\n"; + } else { + // Start, End + code += " Start" + struct_def.name + "(" + BuilderArg() + ");\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + auto camel_name = Name(field); + switch (field.value.type.base_type) { + case BASE_TYPE_STRUCT: { + if (field.value.type.struct_def->fixed) { + code += " Add" + camel_name + "(" + BuilderArg() + ", " + + GenTypeGet(field.value.type) + ".Pack(" + BuilderArg() + + ", _o." + camel_name + "));\n"; + } else { + code += " Add" + camel_name + "(" + BuilderArg() + ", _" + + field.name + ");\n"; + } + break; + } + case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH(); // fall thru + case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru + case BASE_TYPE_VECTOR: { + code += " Add" + camel_name + "(" + BuilderArg() + ", _" + + field.name + ");\n"; + break; + } + case BASE_TYPE_UTYPE: break; + case BASE_TYPE_UNION: { + code += " Add" + camel_name + "Type(" + BuilderArg() + ", _" + + field.name + "_type);\n"; + code += " Add" + camel_name + "(" + BuilderArg() + ", _" + + field.name + ");\n"; + break; + } + // scalar + default: { + code += " Add" + camel_name + "(" + BuilderArg() + ", _o." + + camel_name + ");\n"; + break; + } + } + } + code += " return End" + struct_def.name + "(" + BuilderArg() + ");\n"; + } + code += " }\n"; + } + + void GenStructPackDecl_ObjectAPI( + const StructDef &struct_def, std::string *code_ptr, + std::vector &array_lengths) const { + auto &code = *code_ptr; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + auto is_array = IsArray(field.value.type); + const auto &field_type = + is_array ? field.value.type.VectorType() : field.value.type; + FieldArrayLength tmp_array_length = { + field.name, + field_type.fixed_length, + }; + array_lengths.push_back(tmp_array_length); + if (field_type.struct_def != nullptr) { + GenStructPackDecl_ObjectAPI(*field_type.struct_def, code_ptr, + array_lengths); + } else { + std::vector array_only_lengths; + for (size_t i = 0; i < array_lengths.size(); ++i) { + if (array_lengths[i].length > 0) { + array_only_lengths.push_back(array_lengths[i]); + } + } + std::string name; + for (size_t i = 0; i < array_lengths.size(); ++i) { + name += "_" + array_lengths[i].name; + } + code += " var " + name + " = "; + if (array_only_lengths.size() > 0) { + code += "new " + GenTypeBasic(field_type) + "["; + for (size_t i = 0; i < array_only_lengths.size(); ++i) { + if (i != 0) { code += ","; } + code += NumToString(array_only_lengths[i].length); + } + code += "];\n"; + code += " "; + // initialize array + for (size_t i = 0; i < array_only_lengths.size(); ++i) { + auto idx = "idx" + NumToString(i); + code += "for (var " + idx + " = 0; " + idx + " < " + + NumToString(array_only_lengths[i].length) + "; ++" + idx + + ") {"; + } + for (size_t i = 0; i < array_only_lengths.size(); ++i) { + auto idx = "idx" + NumToString(i); + if (i == 0) { + code += name + "[" + idx; + } else { + code += "," + idx; + } + } + code += "] = _o"; + for (size_t i = 0, j = 0; i < array_lengths.size(); ++i) { + code += "." + ConvertCase(array_lengths[i].name, Case::kUpperCamel); + if (array_lengths[i].length <= 0) continue; + code += "[idx" + NumToString(j++) + "]"; + } + code += ";"; + for (size_t i = 0; i < array_only_lengths.size(); ++i) { + code += "}"; + } + } else { + code += "_o"; + for (size_t i = 0; i < array_lengths.size(); ++i) { + code += "." + ConvertCase(array_lengths[i].name, Case::kUpperCamel); + } + code += ";"; + } + code += "\n"; + } + array_lengths.pop_back(); + } + } + + void GenStructPackCall_ObjectAPI(const StructDef &struct_def, + std::string *code_ptr, + std::string prefix) const { + auto &code = *code_ptr; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + const auto &field_type = field.value.type; + if (field_type.struct_def != nullptr) { + GenStructPackCall_ObjectAPI(*field_type.struct_def, code_ptr, + prefix + field.name + "_"); + } else { + code += ",\n"; + code += prefix + field.name; + } + } + } + + std::string GenTypeGet_ObjectAPI(flatbuffers::Type type, + const IDLOptions &opts) const { + // Object API types always use base namespace + // because *T classes and union wrappers are shared between modes + switch (type.base_type) { + case BASE_TYPE_STRUCT: { + // For structs, return the *T type in base namespace + return WrapInNameSpace( + type.struct_def->defined_namespace, + GenTypeName_ObjectAPI(type.struct_def->name, opts)); + } + case BASE_TYPE_ARRAY: { + if (type.struct_def != nullptr) { + return WrapInNameSpace( + type.struct_def->defined_namespace, + GenTypeName_ObjectAPI(type.struct_def->name, opts)) + + "[]"; + } + // Scalar array - use enum type for enums + auto element_type = type.VectorType(); + if (IsEnum(element_type)) { + return BaseNamespacedEnumName(*element_type.enum_def) + "[]"; + } + return GenTypeBasic(element_type, false) + "[]"; + } + case BASE_TYPE_VECTOR: { + std::string element_type; + if (type.struct_def != nullptr) { + element_type = WrapInNameSpace( + type.struct_def->defined_namespace, + GenTypeName_ObjectAPI(type.struct_def->name, opts)); + } else if (type.element == BASE_TYPE_UNION) { + element_type = BaseNamespacedEnumName(*type.enum_def) + "Union"; + } else if (type.element == BASE_TYPE_STRING) { + element_type = "string"; + } else if (IsEnum(type.VectorType())) { + // Use enum type for enum vectors + element_type = BaseNamespacedEnumName(*type.VectorType().enum_def); + } else { + // Scalar element + element_type = GenTypeBasic(type.VectorType(), false); + } + return "List<" + element_type + ">"; + } + case BASE_TYPE_UNION: { + return BaseNamespacedEnumName(*type.enum_def) + "Union"; + } + case BASE_TYPE_STRING: { + return "string"; + } + default: { + // Scalars use underlying type, enums use enum type with base namespace + if (IsEnum(type)) { return BaseNamespacedEnumName(*type.enum_def); } + return GenTypeBasic(type, false); + } + } + } + + void GenStruct_ObjectAPI(StructDef &struct_def, std::string *code_ptr, + const IDLOptions &opts) const { + auto &code = *code_ptr; + if (struct_def.attributes.Lookup("private")) { + code += "internal "; + } else { + code += "public "; + } + if (struct_def.attributes.Lookup("csharp_partial")) { + // generate a partial class for this C# struct/table + code += "partial "; + } + auto class_name = GenTypeName_ObjectAPI(struct_def.name, opts); + code += "class " + class_name; + code += "\n{\n"; + // Generate Properties + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (field.value.type.base_type == BASE_TYPE_UTYPE) continue; + if (field.value.type.element == BASE_TYPE_UTYPE) continue; + auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); + if (field.IsScalarOptional()) type_name += "?"; + auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + if (opts.cs_gen_json_serializer) { + if (IsUnion(field.value.type)) { + auto utype_name = NamespacedName(*field.value.type.enum_def); + code += " [System.Text.Json.Serialization.JsonPropertyName(\"" + + field.name + "_type\")]\n"; + if (IsVector(field.value.type)) { + code += " private " + utype_name + "[] " + camel_name + "Type {\n"; + code += " get {\n"; + code += " if (this." + camel_name + " == null) return null;\n"; + code += " var _o = new " + utype_name + "[this." + camel_name + + ".Count];\n"; + code += + " for (var _j = 0; _j < _o.Length; ++_j) { _o[_j] = " + "this." + + camel_name + "[_j].Type; }\n"; + code += " return _o;\n"; + code += " }\n"; + code += " set {\n"; + code += " this." + camel_name + " = new List<" + utype_name + + "Union>();\n"; + code += " for (var _j = 0; _j < value.Length; ++_j) {\n"; + code += " var _o = new " + utype_name + "Union();\n"; + code += " _o.Type = value[_j];\n"; + code += " this." + camel_name + ".Add(_o);\n"; + code += " }\n"; + code += " }\n"; + code += " }\n"; + } else { + code += " private " + utype_name + " " + camel_name + "Type {\n"; + code += " get {\n"; + code += " return this." + camel_name + " != null ? this." + + camel_name + ".Type : " + utype_name + ".NONE;\n"; + code += " }\n"; + code += " set {\n"; + code += " this." + camel_name + " = new " + utype_name + + "Union();\n"; + code += " this." + camel_name + ".Type = value;\n"; + code += " }\n"; + code += " }\n"; + } + } + code += " [System.Text.Json.Serialization.JsonPropertyName(\"" + + field.name + "\")]\n"; + // Only apply JsonConverter for non-vector unions + // For vector unions, the list items will use their converter + // automatically + if (IsUnion(field.value.type) && !IsVector(field.value.type)) { + code += " [System.Text.Json.Serialization.JsonConverter(typeof(" + + type_name + "_JsonConverter))]\n"; + } + if (field.attributes.Lookup("hash")) { + code += " [System.Text.Json.Serialization.JsonIgnore]\n"; + } + } + code += " public " + type_name + " " + camel_name + " { get; set; }\n"; + } + // Generate Constructor + code += "\n"; + code += " public " + class_name + "() {\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (field.value.type.base_type == BASE_TYPE_UTYPE) continue; + if (field.value.type.element == BASE_TYPE_UTYPE) continue; + auto camel_name = Name(field); + if (camel_name == struct_def.name) { camel_name += "_"; } + code += " this." + camel_name + " = "; + auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts); + if (IsScalar(field.value.type.base_type)) { + code += GenDefaultValue(field) + ";\n"; + } else { + switch (field.value.type.base_type) { + case BASE_TYPE_STRUCT: { + if (IsStruct(field.value.type)) { + code += "new " + type_name + "();\n"; + } else { + code += "null;\n"; + } + break; + } + case BASE_TYPE_ARRAY: { + code += "new " + type_name.substr(0, type_name.length() - 1) + + NumToString(field.value.type.fixed_length) + "];\n"; + break; + } + default: { + code += "null;\n"; + break; + } + } + } + } + code += " }\n"; + // Generate Serialization + if (opts.cs_gen_json_serializer && + parser_.root_struct_def_ == &struct_def) { + code += "\n"; + code += + " private static readonly System.Text.Json.JsonSerializerOptions " + "_jsonOptions = new System.Text.Json.JsonSerializerOptions { " + "WriteIndented = true, NumberHandling = " + "System.Text.Json.Serialization.JsonNumberHandling." + "AllowNamedFloatingPointLiterals, Converters = { new " + "System.Text.Json.Serialization.JsonStringEnumConverter() } };\n"; + code += " public static " + class_name + + " DeserializeFromJson(string jsonText) {\n"; + code += " return System.Text.Json.JsonSerializer.Deserialize<" + + class_name + ">(jsonText, _jsonOptions);\n"; + code += " }\n"; + code += " public string SerializeToJson() {\n"; + code += + " return System.Text.Json.JsonSerializer.Serialize(this, " + "_jsonOptions);\n"; + code += " }\n"; + } + if (parser_.root_struct_def_ == &struct_def) { + code += " public static " + class_name + + " DeserializeFromBinary(byte[] fbBuffer) {\n"; + code += " return " + struct_def.name + ".GetRootAs" + struct_def.name + + "(new ByteBuffer(fbBuffer)).UnPack();\n"; + code += " }\n"; + code += " public byte[] SerializeToBinary() {\n"; + code += " var fbb = new FlatBufferBuilder(0x10000);\n"; + code += " " + struct_def.name + ".Finish" + struct_def.name + + "Buffer(fbb, " + struct_def.name + ".Pack(fbb, this));\n"; + code += " return fbb.DataBuffer.ToSizedSpan().ToArray();\n"; + code += " }\n"; + } + code += "}\n\n"; + } + + // This tracks the current namespace used to determine if a type need to be + // prefixed by its namespace + const Namespace *cur_name_space_; +}; +} // namespace csharpspanbufs + +static bool GenerateCSharp(const Parser &parser, const std::string &path, + const std::string &file_name) { + csharpspanbufs::CSharpSpanBufsGenerator generator(parser, path, file_name); + return generator.generate(); +} + +namespace { + +class CSharpSpanBufsCodeGenerator : public CodeGenerator { + public: + Status GenerateCode(const Parser &parser, const std::string &path, + const std::string &filename) override { + if (!GenerateCSharp(parser, path, filename)) { return Status::ERROR; } + return Status::OK; + } + + Status GenerateCode(const uint8_t *, int64_t, + const CodeGenOptions &) override { + return Status::NOT_IMPLEMENTED; + } + + Status GenerateMakeRule(const Parser &parser, const std::string &path, + const std::string &filename, + std::string &output) override { + output = JavaCSharpMakeRule(false, parser, path, filename); + return Status::OK; + } + + Status GenerateGrpcCode(const Parser &parser, const std::string &path, + const std::string &filename) override { + (void)parser; + (void)path; + (void)filename; + return Status::NOT_IMPLEMENTED; + } + + Status GenerateRootFile(const Parser &parser, + const std::string &path) override { + (void)parser; + (void)path; + return Status::NOT_IMPLEMENTED; + } + + bool IsSchemaOnly() const override { return true; } + + bool SupportsBfbsGeneration() const override { return false; } + + bool SupportsRootFileGeneration() const override { return false; } + + IDLOptions::Language Language() const override { + return IDLOptions::kCSharpSpanBufs; + } + + std::string LanguageName() const override { return "CSharp"; } +}; +} // namespace + +std::unique_ptr NewCSharpSpanBufsCodeGenerator() { + return std::unique_ptr( + new CSharpSpanBufsCodeGenerator()); +} + +} // namespace flatbuffers diff --git a/src/idl_gen_csharp_spanbufs.h b/src/idl_gen_csharp_spanbufs.h new file mode 100644 index 00000000000..a6c34fc1bda --- /dev/null +++ b/src/idl_gen_csharp_spanbufs.h @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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. + */ + +#ifndef FLATBUFFERS_IDL_GEN_CSHARP_SPANBUFS_H_ +#define FLATBUFFERS_IDL_GEN_CSHARP_SPANBUFS_H_ + +#include "flatbuffers/code_generator.h" + +namespace flatbuffers { + +// Constructs a new CSharp SpanBufs code generator. +std::unique_ptr NewCSharpSpanBufsCodeGenerator(); + +} // namespace flatbuffers + +#endif // FLATBUFFERS_IDL_GEN_CSHARP_SPANBUFS_H_ diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index caeca93d253..73d9da8bee9 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2795,7 +2795,8 @@ bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions& opts) { static FLATBUFFERS_CONSTEXPR unsigned long supported_langs = IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster | IDLOptions::kKotlin | IDLOptions::kKotlinKmp | IDLOptions::kCpp | - IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kTs | + IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kCSharpSpanBufs | + IDLOptions::kTs | IDLOptions::kBinary | IDLOptions::kGo | IDLOptions::kPython | IDLOptions::kJson | IDLOptions::kNim; unsigned long langs = opts.lang_to_generate; @@ -2819,7 +2820,8 @@ bool Parser::SupportsAdvancedUnionFeatures() const { ~(IDLOptions::kCpp | IDLOptions::kTs | IDLOptions::kPhp | IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kKotlin | IDLOptions::kBinary | IDLOptions::kSwift | IDLOptions::kNim | - IDLOptions::kJson | IDLOptions::kKotlinKmp)) == 0; + IDLOptions::kJson | IDLOptions::kKotlinKmp | + IDLOptions::kCSharpSpanBufs)) == 0; } bool Parser::SupportsAdvancedArrayFeatures() const { @@ -2827,7 +2829,7 @@ bool Parser::SupportsAdvancedArrayFeatures() const { ~(IDLOptions::kCpp | IDLOptions::kPython | IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kJsonSchema | IDLOptions::kJson | IDLOptions::kBinary | IDLOptions::kRust | IDLOptions::kTs | - IDLOptions::kSwift)) == 0; + IDLOptions::kSwift | IDLOptions::kCSharpSpanBufs)) == 0; } bool Parser::Supports64BitOffsets() const {