diff --git a/src/Tests/FlatSharpEndToEndTests/ClassLib/FlatBufferVectorOfUnionTests.cs b/src/Tests/FlatSharpEndToEndTests/ClassLib/FlatBufferVectorOfUnionTests.cs
index a448f62c..ce0cb059 100644
--- a/src/Tests/FlatSharpEndToEndTests/ClassLib/FlatBufferVectorOfUnionTests.cs
+++ b/src/Tests/FlatSharpEndToEndTests/ClassLib/FlatBufferVectorOfUnionTests.cs
@@ -17,7 +17,7 @@
namespace FlatSharpEndToEndTests.ClassLib.FlatBufferVectorOfUnionTests;
///
-/// Tests for the FlatBufferVector class that implements IList.
+/// Tests for FlatSharp's IList of Union.
///
public class FlatBufferVectorOfUnionTests
diff --git a/src/Tests/FlatSharpEndToEndTests/ClassLib/FlatBufferVectorTests.cs b/src/Tests/FlatSharpEndToEndTests/ClassLib/FlatBufferVectorTests.cs
index 23cab33f..428881e2 100644
--- a/src/Tests/FlatSharpEndToEndTests/ClassLib/FlatBufferVectorTests.cs
+++ b/src/Tests/FlatSharpEndToEndTests/ClassLib/FlatBufferVectorTests.cs
@@ -19,7 +19,7 @@
namespace FlatSharpEndToEndTests.ClassLib.FlatBufferVectorTests;
///
-/// Tests for the FlatBufferVector class that implements IList.
+/// Tests for FlatSharp's IList implementations.
///
public class FlatBufferVectorTests
{
diff --git a/src/Tests/FlatSharpEndToEndTests/ClassLib/SerializerConfigurationTests.cs b/src/Tests/FlatSharpEndToEndTests/ClassLib/SerializerConfigurationTests.cs
new file mode 100644
index 00000000..290ca3b4
--- /dev/null
+++ b/src/Tests/FlatSharpEndToEndTests/ClassLib/SerializerConfigurationTests.cs
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2018 James Courtney
+ *
+ * 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 FlatSharp.Internal;
+using System.IO;
+
+namespace FlatSharpEndToEndTests.ClassLib.SerializerConfigurationTests;
+
+public class SerializerConfigurationTests
+{
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void UseDeserializationMode(FlatBufferDeserializationOption option)
+ {
+ var item = new Root { StringVector = new string[] { "a", "b", "c" } };
+
+ ISerializer serializer = Root.Serializer.WithSettings(opt => opt.UseDeserializationMode(option));
+
+ Root parsed = item.SerializeAndParse(serializer);
+ IFlatBufferDeserializedObject obj = parsed as IFlatBufferDeserializedObject;
+ Assert.Equal(option, obj.DeserializationContext.DeserializationOption);
+ }
+
+ [Fact]
+ public void UseLazyDeserialization()
+ {
+ var item = new Root { StringVector = new string[] { "a", "b", "c" } };
+
+ ISerializer serializer = Root.Serializer.WithSettings(opt => opt.UseLazyDeserialization());
+
+ Root parsed = item.SerializeAndParse(serializer);
+ IFlatBufferDeserializedObject obj = parsed as IFlatBufferDeserializedObject;
+ Assert.Equal(FlatBufferDeserializationOption.Lazy, obj.DeserializationContext.DeserializationOption);
+ }
+
+ [Fact]
+ public void UseProgressiveDeserialization()
+ {
+ var item = new Root { StringVector = new string[] { "a", "b", "c" } };
+
+ ISerializer serializer = Root.Serializer.WithSettings(opt => opt.UseProgressiveDeserialization());
+
+ Root parsed = item.SerializeAndParse(serializer);
+ IFlatBufferDeserializedObject obj = parsed as IFlatBufferDeserializedObject;
+ Assert.Equal(FlatBufferDeserializationOption.Progressive, obj.DeserializationContext.DeserializationOption);
+ }
+
+ [Fact]
+ public void UseGreedyDeserialization()
+ {
+ var item = new Root { StringVector = new string[] { "a", "b", "c" } };
+
+ ISerializer serializer = Root.Serializer.WithSettings(opt => opt.UseGreedyDeserialization());
+
+ Root parsed = item.SerializeAndParse(serializer);
+ IFlatBufferDeserializedObject obj = parsed as IFlatBufferDeserializedObject;
+ Assert.Equal(FlatBufferDeserializationOption.Greedy, obj.DeserializationContext.DeserializationOption);
+ }
+
+ [Fact]
+ public void UseGreedyMutableDeserialization()
+ {
+ var item = new Root { StringVector = new string[] { "a", "b", "c" } };
+
+ ISerializer serializer = Root.Serializer.WithSettings(opt => opt.UseGreedyMutableDeserialization());
+
+ Root parsed = item.SerializeAndParse(serializer);
+ IFlatBufferDeserializedObject obj = parsed as IFlatBufferDeserializedObject;
+ Assert.Equal(FlatBufferDeserializationOption.GreedyMutable, obj.DeserializationContext.DeserializationOption);
+ }
+
+ [Theory]
+ [InlineData(FlatBufferDeserializationOption.Lazy, false, false)]
+ [InlineData(FlatBufferDeserializationOption.Lazy, true, true)]
+ [InlineData(FlatBufferDeserializationOption.Progressive, false, false)]
+ [InlineData(FlatBufferDeserializationOption.Progressive, true, true)]
+ [InlineData(FlatBufferDeserializationOption.Greedy, false, false)]
+ [InlineData(FlatBufferDeserializationOption.Greedy, true, false)]
+ [InlineData(FlatBufferDeserializationOption.GreedyMutable, false, false)]
+ [InlineData(FlatBufferDeserializationOption.GreedyMutable, true, false)]
+ public void UseMemoryCopySerialization(FlatBufferDeserializationOption option, bool enableMemCopy, bool expectMemCopy)
+ {
+ Root t = new() { StringVector = new[] { "A", "b", "c", } };
+
+ var compiled = Root.Serializer.WithSettings(s => s.UseMemoryCopySerialization(enableMemCopy).UseDeserializationMode(option));
+
+ // overallocate
+ byte[] data = new byte[1024];
+
+ int maxBytes = compiled.GetMaxSize(t);
+ Assert.Equal(88, maxBytes);
+ int actualBytes = compiled.Write(data, t);
+ Assert.Equal(58, actualBytes);
+
+ // First test: Parse the array but don't trim the buffer. This causes the underlying
+ // buffer to be much larger than the actual data.
+ var parsed = compiled.Parse(data);
+ byte[] data2 = new byte[2048];
+ int bytesWritten = compiled.Write(data2, parsed);
+
+ if (expectMemCopy)
+ {
+ Assert.Equal(1024, bytesWritten); // We use mem copy serialization here, and we gave it 1024 bytes when we parsed. So we get 1024 bytes back out.
+ Assert.Equal(1024, compiled.GetMaxSize(parsed));
+ Assert.Throws(() => compiled.Write(new byte[maxBytes], parsed));
+
+ // Repeat, but now using the trimmed array.
+ parsed = compiled.Parse(data.AsMemory().Slice(0, actualBytes));
+ bytesWritten = compiled.Write(data2, parsed);
+ Assert.Equal(58, bytesWritten);
+ Assert.Equal(58, compiled.GetMaxSize(parsed));
+
+ // Default still returns 88.
+ Assert.Equal(88, Root.Serializer.GetMaxSize(parsed));
+ }
+ else
+ {
+ Assert.Equal(58, bytesWritten);
+ Assert.Equal(88, compiled.GetMaxSize(parsed));
+ compiled.Write(new byte[maxBytes], parsed);
+ }
+ }
+
+ [Fact]
+ public void SharedStringWriters()
+ {
+ ISerializer noSharedStrings = Root.Serializer.WithSettings(opt => opt.DisableSharedStrings());
+ ISerializer smallHashSharedStrings = Root.Serializer.WithSettings(opt => opt.UseDefaultSharedStringWriter(1));
+ ISerializer largeHashSharedStrings = Root.Serializer.WithSettings(opt => opt.UseDefaultSharedStringWriter());
+ ISerializer perfectSharedStrings = Root.Serializer.WithSettings(opt => opt.UseSharedStringWriter());
+
+ {
+ Root root = new Root { StringVector = new[] { "a", "b", "a", "b", "a", "b", "a", } };
+
+ byte[] notShared = root.AllocateAndSerialize(noSharedStrings);
+ byte[] smallShared = root.AllocateAndSerialize(smallHashSharedStrings);
+ byte[] largeShared = root.AllocateAndSerialize(largeHashSharedStrings);
+ byte[] perfectShared = root.AllocateAndSerialize(perfectSharedStrings);
+
+ // Small shared doesn't accomplish anything since it alternates.
+ Assert.Equal(notShared.Length, smallShared.Length);
+ Assert.True(largeShared.Length < smallShared.Length);
+ Assert.Equal(largeShared.Length, perfectShared.Length);
+ }
+
+ {
+ Root root = new Root { StringVector = new[] { "a", "a", "a", "a", "b", "b", "b", "b" } };
+
+ byte[] notShared = root.AllocateAndSerialize(noSharedStrings);
+ byte[] smallShared = root.AllocateAndSerialize(smallHashSharedStrings);
+ byte[] largeShared = root.AllocateAndSerialize(largeHashSharedStrings);
+ byte[] perfectShared = root.AllocateAndSerialize(perfectSharedStrings);
+
+ // Small shared doesn't accomplish anything since it alternates.
+ Assert.True(smallShared.Length < notShared.Length);
+ Assert.Equal(largeShared.Length, smallShared.Length);
+ Assert.Equal(largeShared.Length, perfectShared.Length);
+ }
+ }
+
+ private class PerfectSharedStringWriter : ISharedStringWriter
+ {
+ private readonly Dictionary> offsets = new();
+
+ public PerfectSharedStringWriter()
+ {
+ }
+
+ public bool IsDirty => this.offsets.Count > 0;
+
+ public void FlushWrites(TSpanWriter writer, Span data, SerializationContext context) where TSpanWriter : ISpanWriter
+ {
+ foreach (var kvp in this.offsets)
+ {
+ string value = kvp.Key;
+
+ int stringOffset = writer.WriteAndProvisionString(data, value, context);
+
+ for (int i = 0; i < kvp.Value.Count; ++i)
+ {
+ writer.WriteUOffset(data, kvp.Value[i], stringOffset);
+ }
+ }
+
+ this.offsets.Clear();
+ }
+
+ public void Reset()
+ {
+ this.offsets.Clear();
+ }
+
+ public void WriteSharedString(
+ TSpanWriter spanWriter,
+ Span data,
+ int offset,
+ string value,
+ SerializationContext context) where TSpanWriter : ISpanWriter
+ {
+ if (!this.offsets.TryGetValue(value, out var list))
+ {
+ list = new();
+ this.offsets[value] = list;
+ }
+
+ list.Add(offset);
+ }
+ }
+}
diff --git a/src/Tests/FlatSharpEndToEndTests/ClassLib/SerializerConfigurationTests.fbs b/src/Tests/FlatSharpEndToEndTests/ClassLib/SerializerConfigurationTests.fbs
new file mode 100644
index 00000000..d2b7bbe9
--- /dev/null
+++ b/src/Tests/FlatSharpEndToEndTests/ClassLib/SerializerConfigurationTests.fbs
@@ -0,0 +1,14 @@
+
+attribute "fs_serializer";
+attribute "fs_unsafeStructVector";
+attribute "fs_valueStruct";
+attribute "fs_writeThrough";
+attribute "fs_vector";
+attribute "fs_sharedString";
+
+namespace FlatSharpEndToEndTests.ClassLib.SerializerConfigurationTests;
+
+table Root (fs_serializer)
+{
+ StringVector : [ string ] (fs_sharedString);
+}
\ No newline at end of file
diff --git a/src/Tests/FlatSharpEndToEndTests/ClassLib/VTableTests.cs b/src/Tests/FlatSharpEndToEndTests/ClassLib/VTableTests.cs
index a67495a8..42936fb7 100644
--- a/src/Tests/FlatSharpEndToEndTests/ClassLib/VTableTests.cs
+++ b/src/Tests/FlatSharpEndToEndTests/ClassLib/VTableTests.cs
@@ -15,8 +15,9 @@
*/
using FlatSharp.Internal;
+using System.IO;
-namespace FlatSharpEndToEndTests.VTables;
+namespace FlatSharpEndToEndTests.ClassLib.VTables;
public class VTableTests
{
@@ -43,6 +44,83 @@ public class VTableTests
[Fact]
public void Test_VTableGeneric() => this.RunTests(255, VTableGeneric.Create);
+ [Fact]
+ public void InitializeVTable_NormalTable()
+ {
+ byte[] buffer =
+ {
+ 8, 0, // vtable length
+ 12, 0, // table length
+ 4, 0, // index 0 offset
+ 8, 0, // index 1 offset
+ 8, 0, 0, 0, // soffset to vtable.
+ 1, 0, 0, 0,
+ 2, 0, 0, 0,
+ };
+
+ new ArrayInputBuffer(buffer).InitializeVTable(
+ 8,
+ out int vtableOffset,
+ out nuint fieldCount,
+ out ReadOnlySpan fieldData);
+
+ Assert.Equal(0, vtableOffset);
+ Assert.Equal((nuint)2, fieldCount);
+ Assert.Equal(4, fieldData.Length);
+ }
+
+ [Fact]
+ public void InitializeVTable_EmptyTable()
+ {
+ byte[] buffer =
+ {
+ 4, 0, // vtable length
+ 4, 0, // table length
+ 4, 0, 0, 0 // soffset to vtable.
+ };
+
+ new ArrayInputBuffer(buffer).InitializeVTable(
+ 4,
+ out int vtableOffset,
+ out nuint fieldCount,
+ out ReadOnlySpan fieldData);
+
+ Assert.Equal(0, vtableOffset);
+ Assert.Equal((nuint)0, fieldCount);
+ Assert.Equal(0, fieldData.Length);
+ }
+
+ [Fact]
+ public void InitializeVTable_InvalidLength()
+ {
+ byte[] buffer =
+ {
+ 3, 0, // vtable length
+ 4, 0, // table length
+ 4, 0, 0, 0 // soffset to vtable.
+ };
+
+ var ex = Assert.Throws(() =>
+ new ArrayInputBuffer(buffer).InitializeVTable(4, out _, out _, out _));
+
+ Assert.Equal(
+ "FlatBuffer was in an invalid format: VTable was not long enough to be valid.",
+ ex.Message);
+ }
+
+ [Fact]
+ public void ReadUOffset()
+ {
+ byte[] buffer = { 4, 0, 0, 0 };
+ Assert.Equal(4, new ArrayInputBuffer(buffer).ReadUOffset(0));
+
+ buffer = new byte[] { 3, 0, 0, 0 };
+ var ex = Assert.Throws(() => new ArrayInputBuffer(buffer).ReadUOffset(0));
+ Assert.Equal(
+ "FlatBuffer was in an invalid format: Decoded uoffset_t had value less than 4. Value = 3",
+ ex.Message);
+ }
+
private void RunTests(int expectedMaxIndex, CreateCallback callback)
where TVTable : struct, IVTable
{
diff --git a/src/Tests/FlatSharpEndToEndTests/Helpers.cs b/src/Tests/FlatSharpEndToEndTests/Helpers.cs
index 737c29a6..e4aef176 100644
--- a/src/Tests/FlatSharpEndToEndTests/Helpers.cs
+++ b/src/Tests/FlatSharpEndToEndTests/Helpers.cs
@@ -31,17 +31,37 @@ public static IEnumerable AllOptions
public static byte[] AllocateAndSerialize(this T item) where T : class, IFlatBufferSerializable
{
- byte[] data = new byte[item.Serializer.GetMaxSize(item)];
- int bytesWritten = item.Serializer.Write(data, item);
+ return item.AllocateAndSerialize(item.Serializer);
+ }
+
+ public static byte[] AllocateAndSerialize(this T item, ISerializer serializer) where T : class, IFlatBufferSerializable
+ {
+ byte[] data = new byte[serializer.GetMaxSize(item)];
+ int bytesWritten = serializer.Write(data, item);
return data.AsMemory().Slice(0, bytesWritten).ToArray();
}
+ public static T SerializeAndParse(this T item) where T : class, IFlatBufferSerializable
+ {
+ return SerializeAndParse(item, item.Serializer);
+ }
+
public static T SerializeAndParse(
this T item,
- FlatBufferDeserializationOption? option = null) where T : class, IFlatBufferSerializable
+ FlatBufferDeserializationOption? option) where T : class, IFlatBufferSerializable
{
byte[] buffer = item.AllocateAndSerialize();
return item.Serializer.Parse(buffer, option);
}
+
+ public static T SerializeAndParse(
+ this T item,
+ ISerializer? serializer) where T : class, IFlatBufferSerializable
+ {
+ serializer ??= item.Serializer;
+
+ byte[] buffer = item.AllocateAndSerialize();
+ return serializer.Parse(buffer);
+ }
}
diff --git a/src/Tests/FlatSharpEndToEndTests/IO/InputBufferTests.cs b/src/Tests/FlatSharpEndToEndTests/IO/InputBufferTests.cs
index 021902a8..a84fa153 100644
--- a/src/Tests/FlatSharpEndToEndTests/IO/InputBufferTests.cs
+++ b/src/Tests/FlatSharpEndToEndTests/IO/InputBufferTests.cs
@@ -130,83 +130,6 @@ public void ArraySegmentInputBuffer()
(s, b) => s.Parse(new ArraySegment(b)));
}
- [Fact]
- public void InitializeVTable_EmptyTable()
- {
- byte[] buffer =
- {
- 4, 0, // vtable length
- 4, 0, // table length
- 4, 0, 0, 0 // soffset to vtable.
- };
-
- new ArrayInputBuffer(buffer).InitializeVTable(
- 4,
- out int vtableOffset,
- out nuint fieldCount,
- out ReadOnlySpan fieldData);
-
- Assert.Equal(0, vtableOffset);
- Assert.Equal((nuint)0, fieldCount);
- Assert.Equal(0, fieldData.Length);
- }
-
- [Fact]
- public void InitializeVTable_InvalidLength()
- {
- byte[] buffer =
- {
- 3, 0, // vtable length
- 4, 0, // table length
- 4, 0, 0, 0 // soffset to vtable.
- };
-
- var ex = Assert.Throws(() =>
- new ArrayInputBuffer(buffer).InitializeVTable(4, out _, out _, out _));
-
- Assert.Equal(
- "FlatBuffer was in an invalid format: VTable was not long enough to be valid.",
- ex.Message);
- }
-
- [Fact]
- public void InitializeVTable_NormalTable()
- {
- byte[] buffer =
- {
- 8, 0, // vtable length
- 12, 0, // table length
- 4, 0, // index 0 offset
- 8, 0, // index 1 offset
- 8, 0, 0, 0, // soffset to vtable.
- 1, 0, 0, 0,
- 2, 0, 0, 0,
- };
-
- new ArrayInputBuffer(buffer).InitializeVTable(
- 8,
- out int vtableOffset,
- out nuint fieldCount,
- out ReadOnlySpan fieldData);
-
- Assert.Equal(0, vtableOffset);
- Assert.Equal((nuint)2, fieldCount);
- Assert.Equal(4, fieldData.Length);
- }
-
- [Fact]
- public void ReadUOffset()
- {
- byte[] buffer = { 4, 0, 0, 0 };
- Assert.Equal(4, new ArrayInputBuffer(buffer).ReadUOffset(0));
-
- buffer = new byte[] { 3, 0, 0, 0 };
- var ex = Assert.Throws(() => new ArrayInputBuffer(buffer).ReadUOffset(0));
- Assert.Equal(
- "FlatBuffer was in an invalid format: Decoded uoffset_t had value less than 4. Value = 3",
- ex.Message);
- }
-
private void TableSerializationTest(
ISpanWriter writer,
Func, byte[], PrimitiveTypesTable> parse)
diff --git a/src/Tests/FlatSharpEndToEndTests/RawData/RawData.fbs b/src/Tests/FlatSharpEndToEndTests/RawData/RawData.fbs
new file mode 100644
index 00000000..1e69a712
--- /dev/null
+++ b/src/Tests/FlatSharpEndToEndTests/RawData/RawData.fbs
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 James Courtney
+ *
+ * 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.
+ */
+
+attribute "fs_vector";
+attribute "fs_serializer";
+attribute "fs_sortedVector";
+attribute "fs_sharedString";
+
+namespace FlatSharpEndToEndTests.RawData;
+
+table SharedStringTable (fs_serializer)
+{
+ a : string (fs_sharedString);
+ b : string (fs_sharedString);
+ c : string (fs_sharedString);
+ vector : [ string ] (fs_sharedString);
+}
+
+table EmptyTable (fs_serializer) { }
+
+struct SimpleStruct
+{
+ Long : long;
+ Byte : ubyte;
+ Uint : uint;
+}
+
+table SimpleTable (fs_serializer)
+{
+ String : string;
+ struct : SimpleStruct;
+ struct_vector : [ SimpleStruct ];
+ inner_table : SimpleTable;
+}
\ No newline at end of file
diff --git a/src/Tests/FlatSharpEndToEndTests/RawData/RawDataSharedStringTests.cs b/src/Tests/FlatSharpEndToEndTests/RawData/RawDataSharedStringTests.cs
new file mode 100644
index 00000000..659db80d
--- /dev/null
+++ b/src/Tests/FlatSharpEndToEndTests/RawData/RawDataSharedStringTests.cs
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2018 James Courtney
+ *
+ * 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 FlatSharpEndToEndTests.RawData;
+
+public class RawDataSharedStringTests
+{
+ [Fact]
+ public void SharedStrings_Vector_Disabled()
+ {
+ var t = new SharedStringTable
+ {
+ Vector = new List { "string", "string", "string" },
+ };
+
+ var noSharedStrings = SharedStringTable.Serializer.WithSettings(opt => opt.DisableSharedStrings());
+
+ byte[] buffer = t.AllocateAndSerialize(noSharedStrings);
+
+ byte[] expectedBytes = new byte[]
+ {
+ 4, 0, 0, 0, // offset to table start
+ 248, 255, 255, 255, // soffset to vtable.
+ 16, 0, 0, 0, // uoffset to vector
+ 12, 0, 8, 0, // vtable length, table length
+ 0, 0, // vtable[0]
+ 0, 0, // vtable[1]
+ 0, 0, // vtable[2]
+ 4, 0, // vtable[3]
+ 3, 0, 0, 0, // vector length
+ 12, 0, 0, 0, // uffset to first item
+ 20, 0, 0, 0, // uoffset to second item
+ 28, 0, 0, 0, // uoffset to third item
+ 6, 0, 0, 0, // string length
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0, 0, // null terminator + padding
+ 6, 0, 0, 0,
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0, 0, // null terminator + padding
+ 6, 0, 0, 0,
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0, // null terminator
+ };
+
+ Assert.True(expectedBytes.AsSpan().SequenceEqual(buffer));
+ }
+
+ [Fact]
+ public void SharedStrings_Table_Disabled()
+ {
+ var t = new SharedStringTable
+ {
+ A = "string",
+ B = "string",
+ C = "string",
+ };
+
+ var noSharedStrings = SharedStringTable.Serializer.WithSettings(opt => opt.DisableSharedStrings());
+ byte[] buffer = t.AllocateAndSerialize(noSharedStrings);
+
+ byte[] expectedBytes = new byte[]
+ {
+ 4, 0, 0, 0, // offset to table start
+ 240, 255, 255, 255, // soffset to vtable.
+ 24, 0, 0, 0, // uoffset to string 1
+ 32, 0, 0 ,0, // uoffset to string 2
+ 40, 0, 0, 0, // uoffset to string 3
+ 10, 0, 16, 0, // vtable length, table length
+ 12, 0, 8, 0, // vtable(2), vtable(1)
+ 4, 0, 0, 0, // vtable(1), padding
+ 6, 0, 0, 0, // string length
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0, 0, // null terminator.
+ 6, 0, 0, 0,
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0, 0, // null terminator.
+ 6, 0, 0, 0,
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0, // null terminator.
+ };
+
+ Assert.True(expectedBytes.AsSpan().SequenceEqual(buffer));
+ }
+
+ [Fact]
+ public void SharedStrings_Table()
+ {
+ var t = new SharedStringTable
+ {
+ A = "string",
+ B = "string",
+ C = "string",
+ };
+
+ byte[] buffer = t.AllocateAndSerialize();
+
+ byte[] expectedBytes = new byte[]
+ {
+ 4, 0, 0, 0, // offset to table start
+ 240, 255, 255, 255, // soffset to vtable.
+ 24, 0, 0, 0, // uoffset to string 1
+ 20, 0, 0 ,0, // uoffset to string 2
+ 16, 0, 0, 0, // uoffset to string 3
+ 10, 0, 16, 0, // vtable length, table length
+ 12, 0, 8, 0, // vtable(2), vtable(1)
+ 4, 0, 0, 0, // vtable(1), padding
+ 6, 0, 0, 0, // string length
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0, // null terminator.
+ };
+
+ Assert.True(expectedBytes.AsSpan().SequenceEqual(buffer));
+ }
+
+ [Fact]
+ public void SharedStrings_Table_WithNull()
+ {
+ var t = new SharedStringTable
+ {
+ A = null,
+ B = "string",
+ C = null,
+ };
+
+ byte[] buffer = t.AllocateAndSerialize();
+
+ byte[] expectedBytes = new byte[]
+ {
+ 4, 0, 0, 0, // offset to table start
+ 248, 255, 255, 255, // soffset to vtable.
+ 12, 0, 0 ,0, // uoffset to string
+ 8, 0, 8, 0, // vtable length, table length
+ 0, 0, 4, 0, // vtable(0), vtable(1)
+ 6, 0, 0, 0, // string length
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0 // null terminator.
+ };
+
+ Assert.True(expectedBytes.AsSpan().SequenceEqual(buffer));
+ }
+
+ [Fact]
+ public void SharedStrings_Table_WithEviction()
+ {
+ var t = new SharedStringTable
+ {
+ A = "string",
+ B = "foo",
+ C = "string",
+ };
+
+ var serializer = SharedStringTable.Serializer.WithSettings(s => s.UseDefaultSharedStringWriter(1));
+ byte[] buffer = t.AllocateAndSerialize(serializer);
+
+ byte[] expectedBytes = new byte[]
+ {
+ 4, 0, 0, 0, // offset to table start
+ 240, 255, 255, 255, // soffset to vtable.
+ 24, 0, 0, 0, // uoffset to string 1
+ 32, 0, 0 ,0, // uoffset to string 2
+ 36, 0, 0, 0, // uoffset to string 3
+ 10, 0, 16, 0, // vtable length, table length
+ 12, 0, 8, 0, // vtable(0), vtable(1)
+ 4, 0, 0, 0, // vtable(2), padding
+ 6, 0, 0, 0, // string0 length
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0, 0, // null terminator + 1 byte padding
+ 3, 0, 0, 0, // string1 length
+ (byte)'f', (byte)'o', (byte)'o', 0, // string1 + null terminator
+ 6, 0, 0, 0,
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0 // null terminator
+ };
+
+ Assert.True(expectedBytes.AsSpan().SequenceEqual(buffer));
+ }
+
+ [Fact]
+ public void SharedStrings_Vector()
+ {
+ var t = new SharedStringTable
+ {
+ Vector = new List { "string", "string", "string" },
+ };
+
+ byte[] buffer = t.AllocateAndSerialize();
+
+ byte[] expectedBytes = new byte[]
+ {
+ 4, 0, 0, 0, // offset to table start
+ 248, 255, 255, 255, // soffset to vtable.
+ 16, 0, 0, 0, // uoffset to vector
+ 12, 0, 8, 0, // vtable length, table length
+ 0, 0, // vtable[0]
+ 0, 0, // vtable[1]
+ 0, 0, // vtable[2]
+ 4, 0, // vtable[3]
+ 3, 0, 0, 0, // vector length
+ 12, 0, 0, 0, // uffset to first item
+ 8, 0, 0, 0, // uoffset to second item
+ 4, 0, 0, 0, // uoffset to third item
+ 6, 0, 0, 0, // string length
+ (byte)'s', (byte)'t', (byte)'r', (byte)'i',
+ (byte)'n', (byte)'g', 0,
+ };
+
+ Assert.True(expectedBytes.AsSpan().SequenceEqual(buffer));
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/FlatSharpEndToEndTests/RawData/RawDataStringTests.cs b/src/Tests/FlatSharpEndToEndTests/RawData/RawDataStringTests.cs
new file mode 100644
index 00000000..3ddd7a06
--- /dev/null
+++ b/src/Tests/FlatSharpEndToEndTests/RawData/RawDataStringTests.cs
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2018 James Courtney
+ *
+ * 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 FlatSharpEndToEndTests.RawData;
+
+using StringTable = FlatSharpEndToEndTests.TableMembers.StringTable;
+
+public class RawDataStringTests
+{
+ [Fact]
+ public void EmptyString()
+ {
+ var root = new StringTable
+ {
+ ItemStandard = string.Empty,
+ };
+
+ byte[] data = root.AllocateAndSerialize();
+
+ byte[] expectedResult =
+ {
+ 4, 0, 0, 0, // offset to table start
+ 248, 255, 255, 255, // soffset to vtable (-8)
+ 12, 0, 0, 0, // uoffset_t to string
+ 6, 0, // vtable length
+ 8, 0, // table length
+ 4, 0, // offset of index 0 field
+ 0, 0, // padding to 4-byte alignment
+ 0, 0, 0, 0, // vector length
+ 0, // null terminator (special case for strings).
+ };
+
+ Assert.True(expectedResult.AsSpan().SequenceEqual(data));
+ }
+
+ [Fact]
+ public void DeprecatedString()
+ {
+ var root = new StringTable
+ {
+ ItemDeprecated = string.Empty,
+ };
+
+ byte[] data = root.AllocateAndSerialize();
+
+ byte[] expectedResult =
+ {
+ 4, 0, 0, 0, // offset to table start
+ 252, 255, 255, 255, // soffset to vtable (-4)
+ 4, 0, // vtable length
+ 4, 0, // table length
+ };
+
+ Assert.True(expectedResult.AsSpan().SequenceEqual(data));
+ }
+
+ [Fact]
+ public void SimpleString()
+ {
+ var root = new StringTable
+ {
+ ItemStandard = new string(new char[] { (char)1, (char)2, (char)3 }),
+ };
+
+ byte[] target = root.AllocateAndSerialize();
+
+ byte[] expectedResult =
+ {
+ 4, 0, 0, 0, // offset to table start
+ 248, 255, 255, 255, // soffset to vtable (-8)
+ 12, 0, 0, 0, // uoffset_t to vector
+ 6, 0, // vtable length
+ 8, 0, // table length
+ 4, 0, // offset of index 0 field
+ 0, 0, // padding to 4-byte alignment
+ 3, 0, 0, 0, // vector length
+ 1, 2, 3, 0, // data + null terminator (special case for string vectors).
+ };
+
+ Assert.True(expectedResult.AsSpan().SequenceEqual(target));
+ }
+
+ [Fact]
+ public void StringVector()
+ {
+ var root = new StringTable
+ {
+ ItemDeprecated = "notnull",
+ ItemVectorImplicit = new[] { "abc_", "def", "ghi" }
+ };
+
+ byte[] data = root.AllocateAndSerialize();
+
+ byte[] expectedResult =
+ {
+ 4, 0, 0, 0, // offset to table start
+ 248, 255, 255, 255, // soffset to vtable (-8)
+ 16, 0, 0, 0, // uoffset_t to vector
+ 10, 0, // vtable length
+ 8, 0, // table length
+ 0, 0, // offset of index 0 field
+ 0, 0, // offset to index 1 field (deprecated)
+ 4, 0, // offset to index 2 field (the vector)
+ 0, 0, // padding to 4-byte alignment
+ 3, 0, 0, 0, // vector length
+ 12, 0, 0, 0, // offset to index 0
+ 20, 0, 0, 0, // offset to index 1
+ 24, 0, 0, 0, // offset to index 2
+ 4, 0, 0 ,0, // length of string 0
+ (byte)'a', (byte)'b', (byte)'c', (byte)'_', 0, // string 0
+ 0, 0, 0, // padding
+ 3, 0, 0 ,0, // length of string 1
+ (byte)'d', (byte)'e', (byte)'f', 0, // string 1
+ 3, 0, 0 ,0, // length of string 1
+ (byte)'g', (byte)'h', (byte)'i', 0, // string 2
+ };
+
+ Assert.True(expectedResult.AsSpan().SequenceEqual(data));
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/FlatSharpEndToEndTests/RawData/RawDataTableTests.cs b/src/Tests/FlatSharpEndToEndTests/RawData/RawDataTableTests.cs
new file mode 100644
index 00000000..ad8bf60f
--- /dev/null
+++ b/src/Tests/FlatSharpEndToEndTests/RawData/RawDataTableTests.cs
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2018 James Courtney
+ *
+ * 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 FlatSharpEndToEndTests.RawData;
+
+public class RawDataTableTests
+{
+ [Fact]
+ public void AllMembersNull()
+ {
+ SimpleTable table = new SimpleTable();
+ byte[] buffer = table.AllocateAndSerialize();
+
+ byte[] expectedData =
+ {
+ 4, 0, 0, 0,
+ 252, 255, 255, 255,
+ 4, 0,
+ 4, 0,
+ };
+
+ Assert.True(expectedData.AsSpan().SequenceEqual(buffer));
+ }
+
+ [Fact]
+ public void TableWithStruct()
+ {
+ SimpleTable table = new SimpleTable
+ {
+ Struct = new SimpleStruct { Byte = 1, Long = 2, Uint = 3 }
+ };
+
+ byte[] buffer = table.AllocateAndSerialize();
+
+ byte[] expectedData =
+ {
+ 4, 0, 0, 0, // uoffset to table start
+ 236, 255, 255, 255, // soffet to vtable (4 - x = 24 => x = -20)
+ 2, 0, 0, 0, 0, 0, 0, 0, // struct.long
+ 1, // struct.byte
+ 0, 0, 0, // padding
+ 3, 0, 0, 0, // struct.uint
+ 8, 0, // vtable length
+ 20, 0, // table length
+ 0, 0, // index 0 offset
+ 4, 0, // Index 1 offset
+ };
+
+ Assert.True(expectedData.AsSpan().SequenceEqual(buffer));
+ }
+
+ [Fact]
+ public void TableWithStructAndString()
+ {
+ SimpleTable table = new SimpleTable
+ {
+ String = "hi",
+ Struct = new SimpleStruct { Byte = 1, Long = 2, Uint = 3 }
+ };
+
+ byte[] buffer = table.AllocateAndSerialize();
+
+ byte[] expectedData =
+ {
+ 4, 0, 0, 0, // uoffset to table start
+ 232, 255, 255, 255, // soffet to vtable (4 - x = 24 => x = -20)
+ 2, 0, 0, 0, 0, 0, 0, 0, // struct.long
+ 1, 0, 0, 0, // struct.byte + padding
+ 3, 0, 0, 0, // struct.uint
+ 12, 0, 0, 0, // uoffset to string
+ 8, 0, // vtable length
+ 24, 0, // table length
+ 20, 0, // index 0 offset
+ 4, 0, // Index 1 offset
+ 2, 0, 0, 0, // string length
+ 104, 105, 0, // hi + null terminator
+ };
+
+ Assert.True(expectedData.AsSpan().SequenceEqual(buffer));
+ }
+
+ [Fact]
+ public void EmptyTable_Serialize_MaxSize()
+ {
+ EmptyTable table = new EmptyTable();
+
+ byte[] buffer = table.AllocateAndSerialize();
+
+ byte[] expectedData =
+ {
+ 4, 0, 0, 0,
+ 252, 255, 255, 255,
+ 4, 0,
+ 4, 0,
+ };
+
+ Assert.True(expectedData.AsSpan().SequenceEqual(buffer));
+
+ int maxSize = EmptyTable.Serializer.GetMaxSize(table);
+ Assert.Equal(23, maxSize);
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/FlatSharpEndToEndTests/TableMembers/TableMembers.fbs b/src/Tests/FlatSharpEndToEndTests/TableMembers/TableMembers.fbs
index 6116fda9..56ee4981 100644
--- a/src/Tests/FlatSharpEndToEndTests/TableMembers/TableMembers.fbs
+++ b/src/Tests/FlatSharpEndToEndTests/TableMembers/TableMembers.fbs
@@ -143,6 +143,14 @@ table DoubleTable (fs_serializer)
item_readonly_list : [ double ] (fs_vector:"IReadOnlyList");
}
+table StringTable (fs_serializer)
+{
+ item_standard : string;
+ item_deprecated : string (deprecated);
+ item_vector_implicit : [ string ];
+ item_vector_readonly : [ string ] (fs_vector:"IReadOnlyList");
+}
+
table EmptyTable (fs_serializer)
{
}
\ No newline at end of file
diff --git a/src/Tests/FlatSharpEndToEndTests/TableMembers/TableMembersTests.cs b/src/Tests/FlatSharpEndToEndTests/TableMembers/TableMembersTests.cs
index 76c363b7..dd9e352b 100644
--- a/src/Tests/FlatSharpEndToEndTests/TableMembers/TableMembersTests.cs
+++ b/src/Tests/FlatSharpEndToEndTests/TableMembers/TableMembersTests.cs
@@ -83,6 +83,47 @@ public void Byte(FlatBufferDeserializationOption option)
[ClassData(typeof(DeserializationOptionClassData))]
public void Double(FlatBufferDeserializationOption option) => this.RunTest(3.14, option);
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void String(FlatBufferDeserializationOption option)
+ {
+ {
+ byte[] emptyTable = new EmptyTable().AllocateAndSerialize();
+ StringTable parsed = StringTable.Serializer.Parse(emptyTable, option);
+
+ Assert.Null(parsed.ItemDeprecated);
+ Assert.Null(parsed.ItemStandard);
+ Assert.Null(parsed.ItemVectorImplicit);
+ Assert.Null(parsed.ItemVectorReadonly);
+ }
+
+ {
+ StringTable template = new()
+ {
+ ItemDeprecated = "deprecated",
+ ItemStandard = "standard",
+ ItemVectorImplicit = new[] { "a", "b", },
+ ItemVectorReadonly = new[] { "c", "d", "e" },
+ };
+
+ StringTable parsed = template.SerializeAndParse(option);
+
+ Assert.Null(parsed.ItemDeprecated);
+ Assert.Equal("standard", parsed.ItemStandard);
+
+ IList @implicit = parsed.ItemVectorImplicit;
+ Assert.Equal(2, @implicit.Count);
+ Assert.Equal("a", @implicit[0]);
+ Assert.Equal("b", @implicit[1]);
+
+ IReadOnlyList rolist = parsed.ItemVectorReadonly;
+ Assert.Equal(3, rolist.Count);
+ Assert.Equal("c", rolist[0]);
+ Assert.Equal("d", rolist[1]);
+ Assert.Equal("e", rolist[2]);
+ }
+ }
+
private void RunTest(T expectedDefault, FlatBufferDeserializationOption option)
where T : struct
where TTable : class, ITypedTable, IFlatBufferSerializable, new()
diff --git a/src/Tests/FlatSharpEndToEndTests/ValueStructs/ValueStructTests.cs b/src/Tests/FlatSharpEndToEndTests/ValueStructs/ValueStructTests.cs
index 1c121e05..e0f0fd85 100644
--- a/src/Tests/FlatSharpEndToEndTests/ValueStructs/ValueStructTests.cs
+++ b/src/Tests/FlatSharpEndToEndTests/ValueStructs/ValueStructTests.cs
@@ -74,7 +74,7 @@ public void WriteThrough_ValueStruct_InTable()
[Fact]
public void Basics()
{
- Assert.Equal(148, Unsafe.SizeOf());
+ Assert.Equal(36, Unsafe.SizeOf());
}
[Fact]
@@ -82,7 +82,7 @@ public void ExtensionMethod_WorksForVectors()
{
ValueStruct v = default;
- Assert.Equal(128, v.D_Length);
+ Assert.Equal(16, v.D_Length);
for (int i = 0; i < v.D_Length; ++i)
{
diff --git a/src/Tests/FlatSharpEndToEndTests/ValueStructs/ValueStructs.fbs b/src/Tests/FlatSharpEndToEndTests/ValueStructs/ValueStructs.fbs
index ef068d59..771e58e4 100644
--- a/src/Tests/FlatSharpEndToEndTests/ValueStructs/ValueStructs.fbs
+++ b/src/Tests/FlatSharpEndToEndTests/ValueStructs/ValueStructs.fbs
@@ -39,7 +39,7 @@ struct ValueStruct (fs_valueStruct) {
A : ubyte;
B : int;
C : long;
- D : [ubyte : 128];
+ D : [ ubyte : 16 ];
Inner : InnerValueStruct;
}
@@ -50,36 +50,36 @@ struct RefStruct {
struct ValueUnsafeStructVector_Byte (fs_valueStruct) {
GuardLower : ulong;
- Vector : [ubyte : 128] (fs_unsafeStructVector);
+ Vector : [ubyte : 16] (fs_unsafeStructVector);
GuardHigher : ulong;
}
struct ValueUnsafeStructVector_UShort (fs_valueStruct) {
GuardLower : ulong;
- Vector : [ushort : 128] (fs_unsafeStructVector);
+ Vector : [ushort : 16] (fs_unsafeStructVector);
GuardHigher : ulong;
}
struct ValueUnsafeStructVector_UInt (fs_valueStruct) {
GuardLower : ulong;
- Vector : [uint : 128] (fs_unsafeStructVector);
+ Vector : [uint : 16] (fs_unsafeStructVector);
GuardHigher : ulong;
}
struct ValueUnsafeStructVector_ULong (fs_valueStruct) {
GuardLower : ulong;
- Vector : [ulong : 128] (fs_unsafeStructVector);
+ Vector : [ulong : 16] (fs_unsafeStructVector);
GuardHigher : ulong;
}
struct ValueUnsafeStructVector_Float (fs_valueStruct) {
GuardLower : ulong;
- Vector : [float : 128] (fs_unsafeStructVector);
+ Vector : [float : 16] (fs_unsafeStructVector);
GuardHigher : ulong;
}
struct ValueUnsafeStructVector_Double (fs_valueStruct) {
GuardLower : ulong;
- Vector : [double : 128] (fs_unsafeStructVector);
+ Vector : [double : 16] (fs_unsafeStructVector);
GuardHigher : ulong;
}
\ No newline at end of file
diff --git a/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/IndexedVectorTests.cs b/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/IndexedVectorTests.cs
new file mode 100644
index 00000000..ffebf2ff
--- /dev/null
+++ b/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/IndexedVectorTests.cs
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2021 James Courtney
+ *
+ * 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 FlatSharp.Internal;
+using System.Runtime.InteropServices;
+
+namespace FlatSharpEndToEndTests.Vectors.Sorted;
+
+public class IndexedVectorTests
+{
+ private static readonly Random Rng = new();
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Bool(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfBool,
+ (x, v) => x.IndexedVectorOfBool = v,
+ () => new BoolKey { Key = Rng.Next() % 2 == 0 },
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Byte(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfByte,
+ (x, v) => x.IndexedVectorOfByte = v,
+ GetValueFactory((k, v) => k.Key = v),
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void SByte(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfSbyte,
+ (x, v) => x.IndexedVectorOfSbyte = v,
+ GetValueFactory((k, v) => k.Key = v),
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Short(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfShort,
+ (x, v) => x.IndexedVectorOfShort = v,
+ GetValueFactory((k, v) => k.Key = v),
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void UShort(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfUshort,
+ (x, v) => x.IndexedVectorOfUshort = v,
+ GetValueFactory((k, v) => k.Key = v),
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Int(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfInt,
+ (x, v) => x.IndexedVectorOfInt = v,
+ GetValueFactory((k, v) => k.Key = v),
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void UInt(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfUint,
+ (x, v) => x.IndexedVectorOfUint = v,
+ GetValueFactory((k, v) => k.Key = v),
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Long(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfLong,
+ (x, v) => x.IndexedVectorOfLong = v,
+ GetValueFactory((k, v) => k.Key = v),
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void ULong(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfUlong,
+ (x, v) => x.IndexedVectorOfUlong = v,
+ GetValueFactory((k, v) => k.Key = v),
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Float(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfFloat,
+ (x, v) => x.IndexedVectorOfFloat = v,
+ GetValueFactory((k, v) => k.Key = v),
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Double(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfDouble,
+ (x, v) => x.IndexedVectorOfDouble = v,
+ GetValueFactory((k, v) => k.Key = v),
+ k => k.Key);
+
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void String(FlatBufferDeserializationOption opt) => this.IndexedVectorTest(
+ opt,
+ x => x.IndexedVectorOfString,
+ (x, v) => x.IndexedVectorOfString = v,
+ () =>
+ {
+ int length = Rng.Next(0, 2048);
+ byte[] data = new byte[length];
+ Rng.NextBytes(data);
+ return new StringKey { Key = Convert.ToBase64String(data) };
+ },
+ k => k.Key);
+
+ private static Func GetValueFactory(Action setKey)
+ where TKey : struct
+ where TValue : class, ISortableTable, new()
+ {
+ return () =>
+ {
+ byte[] data = new byte[8];
+ Rng.NextBytes(data);
+ TKey key = MemoryMarshal.Cast(data.AsSpan())[0];
+ var val = new TValue();
+ setKey(val, key);
+ return val;
+ };
+ }
+
+ private void IndexedVectorTest(
+ FlatBufferDeserializationOption option,
+ Func> getVector,
+ Action> setVector,
+ Func createValue,
+ Func getKey)
+ where TValue : class, ISortableTable
+ {
+ RootTableIndexed root = new();
+
+ HashSet knownKeys = new();
+
+ IIndexedVector originalVector = new IndexedVector();
+ for (int i = 0; i < 100; ++i)
+ {
+ var toAdd = createValue();
+
+ // Some key types may have a small range of values
+ // such as bool and byte.
+ if (knownKeys.Add(getKey(toAdd)))
+ {
+ originalVector.Add(toAdd);
+ }
+ }
+
+ setVector(root, originalVector);
+
+ byte[] data = root.AllocateAndSerialize();
+ var parsed = RootTableIndexed.Serializer.Parse(data, option);
+
+ IIndexedVector vector = getVector(parsed);
+
+ Assert.Equal(knownKeys.Count, vector.Count);
+
+ foreach (var key in knownKeys)
+ {
+ Assert.True(vector.TryGetValue(key, out TValue value));
+ Assert.True(vector.ContainsKey(key));
+ Assert.NotNull(vector[key]);
+ Assert.NotNull(value);
+ Assert.Equal(key, getKey(value));
+ }
+
+ for (int i = 0; i < 100; ++i)
+ {
+ TKey key = getKey(createValue());
+ if (!knownKeys.Contains(key))
+ {
+ Assert.False(vector.TryGetValue(key, out TValue value));
+ Assert.Null(value);
+ Assert.False(vector.ContainsKey(key));
+ Assert.Throws(() => vector[key]);
+ }
+ }
+ }
+}
diff --git a/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/SortedVectorTests.cs b/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/SortedVectorTests.cs
index 57649c5b..c7412dd5 100644
--- a/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/SortedVectorTests.cs
+++ b/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/SortedVectorTests.cs
@@ -21,8 +21,10 @@ namespace FlatSharpEndToEndTests.Vectors.Sorted;
public class SortedVectorTests
{
- [Fact]
- public void Bool() => this.SortedVectorTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Bool(FlatBufferDeserializationOption opt) => this.SortedVectorTest(
+ opt,
rng => rng.Next() % 2 == 0,
rt => rt.ListVectorOfBool,
(rt, l) => rt.ListVectorOfBool = l,
@@ -31,78 +33,100 @@ public void Bool() => this.SortedVectorTest(
(k, v) => k.Key = v,
Comparer.Default);
- [Fact]
- public void Byte() => this.SortedVectorStructTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Byte(FlatBufferDeserializationOption opt) => this.SortedVectorStructTest(
+ opt,
rt => rt.ListVectorOfByte,
(rt, l) => rt.ListVectorOfByte = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void SByte() => this.SortedVectorStructTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void SByte(FlatBufferDeserializationOption opt) => this.SortedVectorStructTest(
+ opt,
rt => rt.ListVectorOfSbyte,
(rt, l) => rt.ListVectorOfSbyte = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void Short() => this.SortedVectorStructTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Short(FlatBufferDeserializationOption opt) => this.SortedVectorStructTest(
+ opt,
rt => rt.ListVectorOfShort,
(rt, l) => rt.ListVectorOfShort = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void UShort() => this.SortedVectorStructTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void UShort(FlatBufferDeserializationOption opt) => this.SortedVectorStructTest(
+ opt,
rt => rt.ListVectorOfUshort,
(rt, l) => rt.ListVectorOfUshort = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void Int() => this.SortedVectorStructTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Int(FlatBufferDeserializationOption opt) => this.SortedVectorStructTest(
+ opt,
rt => rt.ListVectorOfInt,
(rt, l) => rt.ListVectorOfInt = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void UInt() => this.SortedVectorStructTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void UInt(FlatBufferDeserializationOption opt) => this.SortedVectorStructTest(
+ opt,
rt => rt.ListVectorOfUint,
(rt, l) => rt.ListVectorOfUint = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void Long() => this.SortedVectorStructTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Long(FlatBufferDeserializationOption opt) => this.SortedVectorStructTest(
+ opt,
rt => rt.ListVectorOfLong,
(rt, l) => rt.ListVectorOfLong = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void ULong() => this.SortedVectorStructTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void ULong(FlatBufferDeserializationOption opt) => this.SortedVectorStructTest(
+ opt,
rt => rt.ListVectorOfUlong,
(rt, l) => rt.ListVectorOfUlong = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void Float() => this.SortedVectorStructTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Float(FlatBufferDeserializationOption opt) => this.SortedVectorStructTest(
+ opt,
rt => rt.ListVectorOfFloat,
(rt, l) => rt.ListVectorOfFloat = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void Double() => this.SortedVectorStructTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Double(FlatBufferDeserializationOption opt) => this.SortedVectorStructTest(
+ opt,
rt => rt.ListVectorOfDouble,
(rt, l) => rt.ListVectorOfDouble = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void String_Base64() => this.SortedVectorTest(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void String_Base64(FlatBufferDeserializationOption opt) => this.SortedVectorTest(
+ opt,
rng =>
{
int length = rng.Next(0, 2048);
@@ -117,8 +141,10 @@ public void String_Base64() => this.SortedVectorTest(
(k, v) => k.Key = v,
new Utf8StringComparer());
- [Fact]
- public void Bool_ReadOnly() => this.SortedVectorTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Bool_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorTestReadOnly(
+ opt,
rng => rng.Next() % 2 == 0,
rt => rt.ListVectorOfBool,
(rt, l) => rt.ListVectorOfBool = l,
@@ -127,78 +153,100 @@ public void Bool_ReadOnly() => this.SortedVectorTestReadOnly(
(k, v) => k.Key = v,
Comparer.Default);
- [Fact]
- public void Byte_ReadOnly() => this.SortedVectorStructTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Byte_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorStructTestReadOnly(
+ opt,
rt => rt.ListVectorOfByte,
(rt, l) => rt.ListVectorOfByte = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void SByte_ReadOnly() => this.SortedVectorStructTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void SByte_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorStructTestReadOnly(
+ opt,
rt => rt.ListVectorOfSbyte,
(rt, l) => rt.ListVectorOfSbyte = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void Short_ReadOnly() => this.SortedVectorStructTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Short_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorStructTestReadOnly(
+ opt,
rt => rt.ListVectorOfShort,
(rt, l) => rt.ListVectorOfShort = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void UShort_ReadOnly() => this.SortedVectorStructTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void UShort_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorStructTestReadOnly(
+ opt,
rt => rt.ListVectorOfUshort,
(rt, l) => rt.ListVectorOfUshort = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void Int_ReadOnly() => this.SortedVectorStructTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Int_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorStructTestReadOnly(
+ opt,
rt => rt.ListVectorOfInt,
(rt, l) => rt.ListVectorOfInt = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void UInt_ReadOnly() => this.SortedVectorStructTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void UInt_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorStructTestReadOnly(
+ opt,
rt => rt.ListVectorOfUint,
(rt, l) => rt.ListVectorOfUint = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void Long_ReadOnly() => this.SortedVectorStructTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Long_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorStructTestReadOnly(
+ opt,
rt => rt.ListVectorOfLong,
(rt, l) => rt.ListVectorOfLong = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void ULong_ReadOnly() => this.SortedVectorStructTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void ULong_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorStructTestReadOnly(
+ opt,
rt => rt.ListVectorOfUlong,
(rt, l) => rt.ListVectorOfUlong = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void Float_ReadOnly() => this.SortedVectorStructTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Float_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorStructTestReadOnly(
+ opt,
rt => rt.ListVectorOfFloat,
(rt, l) => rt.ListVectorOfFloat = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void Double_ReadOnly() => this.SortedVectorStructTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void Double_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorStructTestReadOnly(
+ opt,
rt => rt.ListVectorOfDouble,
(rt, l) => rt.ListVectorOfDouble = l,
k => k.Key,
(k, v) => k.Key = v);
- [Fact]
- public void String_Base64_ReadOnly() => this.SortedVectorTestReadOnly(
+ [Theory]
+ [ClassData(typeof(DeserializationOptionClassData))]
+ public void String_Base64_ReadOnly(FlatBufferDeserializationOption opt) => this.SortedVectorTestReadOnly(
+ opt,
rng =>
{
int length = rng.Next(0, 2048);
@@ -214,6 +262,7 @@ public void String_Base64_ReadOnly() => this.SortedVectorTestReadOnly(
+ FlatBufferDeserializationOption option,
Func> getList,
Action> setList,
Func getKey,
@@ -223,6 +272,7 @@ private void SortedVectorStructTestReadOnly(
where TKey : struct
{
this.SortedVectorTestReadOnly(
+ option,
rng =>
{
byte[] data = new byte[8];
@@ -239,6 +289,7 @@ private void SortedVectorStructTestReadOnly(
}
private void SortedVectorStructTest(
+ FlatBufferDeserializationOption option,
Func> getList,
Action> setList,
Func getKey,
@@ -248,6 +299,7 @@ private void SortedVectorStructTest(
where TKey : struct
{
this.SortedVectorTest(
+ option,
rng =>
{
byte[] data = new byte[8];
@@ -264,6 +316,7 @@ private void SortedVectorStructTest(
}
private void SortedVectorTestReadOnly(
+ FlatBufferDeserializationOption opt,
Func createKey,
Func> getList,
Action> setList,
@@ -290,11 +343,12 @@ private void SortedVectorTestReadOnly(
list.Add(value);
}
- this.SortedVectorTestReadOnly(table, getList, getKey, comparer);
+ this.SortedVectorTestReadOnly(opt, table, getList, getKey, comparer);
}
}
private void SortedVectorTest(
+ FlatBufferDeserializationOption option,
Func createKey,
Func> getList,
Action> setList,
@@ -321,11 +375,12 @@ private void SortedVectorTest(
list.Add(value);
}
- this.SortedVectorTest(table, getList, getKey, comparer);
+ this.SortedVectorTest(option, table, getList, getKey, comparer);
}
}
private void SortedVectorTestReadOnly(
+ FlatBufferDeserializationOption option,
RootTableReadOnly root,
Func> getList,
Func getKey,
@@ -335,42 +390,34 @@ private void SortedVectorTestReadOnly(
IReadOnlyList rootList = getList(root);
byte[] data = root.AllocateAndSerialize();
- void RunTest(
- FlatBufferDeserializationOption option)
- {
- var parsed = RootTableReadOnly.Serializer.Parse(data, option);
+ var parsed = RootTableReadOnly.Serializer.Parse(data, option);
+
+ IReadOnlyList vector = getList(parsed);
- IReadOnlyList vector = getList(parsed);
+ Assert.Equal(rootList.Count, vector.Count);
- Assert.Equal(rootList.Count, vector.Count);
+ if (rootList.Count > 0)
+ {
+ TValue previous = vector[0];
- if (rootList.Count > 0)
+ for (int i = 0; i < rootList.Count; ++i)
{
- TValue previous = vector[0];
-
- for (int i = 0; i < rootList.Count; ++i)
- {
- var item = vector[i];
- Assert.True(comparer.Compare(getKey(previous), getKey(item)) <= 0);
- previous = item;
- }
-
- foreach (var originalItem in rootList)
- {
- var item = vector.BinarySearchByFlatBufferKey(getKey(originalItem));
- Assert.NotNull(item);
- Assert.Equal(getKey(originalItem).ToString(), getKey(item).ToString());
- }
+ var item = vector[i];
+ Assert.True(comparer.Compare(getKey(previous), getKey(item)) <= 0);
+ previous = item;
}
- }
- foreach (FlatBufferDeserializationOption mode in Enum.GetValues(typeof(FlatBufferDeserializationOption)))
- {
- RunTest(mode);
+ foreach (var originalItem in rootList)
+ {
+ var item = vector.BinarySearchByFlatBufferKey(getKey(originalItem));
+ Assert.NotNull(item);
+ Assert.Equal(getKey(originalItem).ToString(), getKey(item).ToString());
+ }
}
}
private void SortedVectorTest(
+ FlatBufferDeserializationOption option,
RootTable root,
Func> getList,
Func getKey,
@@ -380,38 +427,29 @@ private void SortedVectorTest(
IList rootList = getList(root);
byte[] data = root.AllocateAndSerialize();
- void RunTest(
- FlatBufferDeserializationOption option)
- {
- var parsed = RootTable.Serializer.Parse(data, option);
+ var parsed = RootTable.Serializer.Parse(data, option);
+
+ IList vector = getList(parsed);
- IList vector = getList(parsed);
+ Assert.Equal(rootList.Count, vector.Count);
- Assert.Equal(rootList.Count, vector.Count);
+ if (rootList.Count > 0)
+ {
+ TValue previous = vector[0];
- if (rootList.Count > 0)
+ for (int i = 0; i < rootList.Count; ++i)
{
- TValue previous = vector[0];
-
- for (int i = 0; i < rootList.Count; ++i)
- {
- var item = vector[i];
- Assert.True(comparer.Compare(getKey(previous), getKey(item)) <= 0);
- previous = item;
- }
-
- foreach (var originalItem in rootList)
- {
- var item = vector.BinarySearchByFlatBufferKey(getKey(originalItem));
- Assert.NotNull(item);
- Assert.Equal(getKey(originalItem).ToString(), getKey(item).ToString());
- }
+ var item = vector[i];
+ Assert.True(comparer.Compare(getKey(previous), getKey(item)) <= 0);
+ previous = item;
}
- }
- foreach (FlatBufferDeserializationOption mode in Enum.GetValues(typeof(FlatBufferDeserializationOption)))
- {
- RunTest(mode);
+ foreach (var originalItem in rootList)
+ {
+ var item = vector.BinarySearchByFlatBufferKey(getKey(originalItem));
+ Assert.NotNull(item);
+ Assert.Equal(getKey(originalItem).ToString(), getKey(item).ToString());
+ }
}
}
}
diff --git a/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/SortedVectors.fbs b/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/SortedVectors.fbs
index 957aa3ae..e1cd1c59 100644
--- a/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/SortedVectors.fbs
+++ b/src/Tests/FlatSharpEndToEndTests/Vectors/Sorted/SortedVectors.fbs
@@ -52,6 +52,28 @@ table RootTableReadOnly (fs_serializer)
list_vector_of_string : [ StringKey ] (fs_sortedVector, fs_vector:"IReadOnlyList");
}
+table RootTableIndexed (fs_serializer)
+{
+ indexed_vector_of_bool : [ BoolKey ] (fs_vector:"IIndexedVector");
+
+ indexed_vector_of_byte : [ ByteKey ] (fs_vector:"IIndexedVector");
+ indexed_vector_of_sbyte : [ SByteKey ] (fs_vector:"IIndexedVector");
+
+ indexed_vector_of_short : [ ShortKey ] (fs_vector:"IIndexedVector");
+ indexed_vector_of_ushort : [ UShortKey ] (fs_vector:"IIndexedVector");
+
+ indexed_vector_of_int : [ IntKey ] (fs_vector:"IIndexedVector");
+ indexed_vector_of_uint : [ UIntKey ] (fs_vector:"IIndexedVector");
+
+ indexed_vector_of_long : [ LongKey ] (fs_vector:"IIndexedVector");
+ indexed_vector_of_ulong : [ ULongKey ] (fs_vector:"IIndexedVector");
+
+ indexed_vector_of_float : [ FloatKey ] (fs_vector:"IIndexedVector");
+ indexed_vector_of_double : [ DoubleKey ] (fs_vector:"IIndexedVector");
+
+ indexed_vector_of_string : [ StringKey ] (fs_vector:"IIndexedVector");
+}
+
table BoolKey { Key : bool (key); }
table ByteKey { Key : ubyte (key); }
table SByteKey { Key : byte (key); }
diff --git a/src/Tests/FlatSharpTests/SerializationTests/MemCopySerializeTests.cs b/src/Tests/FlatSharpTests/SerializationTests/MemCopySerializeTests.cs
deleted file mode 100644
index ce17a201..00000000
--- a/src/Tests/FlatSharpTests/SerializationTests/MemCopySerializeTests.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright 2021 James Courtney
- *
- * 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 FlatSharp;
-
-namespace FlatSharpTests;
-
-///
-/// Tests serialization using the memory copy shortcut.
-///
-public class MemCopySerializeTests
-{
- [Fact]
- public void GreedyMemoryCopySerialization_NoEffect()
- {
- TestTable t = new()
- {
- Foo = "foobar",
- Struct = new Struct
- {
- Bar = 12,
- }
- };
-
- var compiled = FlatBufferSerializer.Default.Compile>().WithSettings(s => s.UseMemoryCopySerialization());
-
- byte[] data = new byte[1024];
- Assert.Equal(70, compiled.GetMaxSize(t));
- int actualBytes = compiled.Write(data, t);
-
- // First test: Parse the array but don't trim the buffer. This causes the underlying
- // buffer to be much larger than the actual data.
- var parsed = compiled.Parse(data);
- byte[] data2 = new byte[2048];
- int bytesWritten = compiled.Write(data2, parsed);
-
- Assert.Equal(35, actualBytes);
- Assert.Equal(35, bytesWritten);
- Assert.Equal(70, compiled.GetMaxSize(parsed));
- }
-
- [Fact]
- public void LazyMemoryCopySerialization()
- {
- TestTable t = new()
- {
- Foo = "foobar",
- Struct = new WriteThroughStruct
- {
- Bar = 12,
- }
- };
-
- FlatBufferSerializer serializer = FlatBufferSerializer.Default;
- var compiled = serializer.Compile>().WithSettings(s => s.UseMemoryCopySerialization().UseLazyDeserialization());
-
- byte[] data = new byte[1024];
- Assert.Equal(70, compiled.GetMaxSize(t));
- int actualBytes = compiled.Write(data, t);
-
- // First test: Parse the array but don't trim the buffer. This causes the underlying
- // buffer to be much larger than the actual data.
- var parsed = compiled.Parse(data);
- byte[] data2 = new byte[2048];
- int bytesWritten = compiled.Write(data2, parsed);
-
- Assert.Equal(35, actualBytes);
- Assert.Equal(1024, bytesWritten); // We use mem copy serialization here, and we gave it 1024 bytes when we parsed. So we get 1024 bytes back out.
- Assert.Equal(1024, compiled.GetMaxSize(parsed));
- Assert.Throws(() => compiled.Write(new byte[35], parsed));
-
- // Repeat, but now using the trimmed array.
- parsed = compiled.Parse(data.AsMemory().Slice(0, actualBytes));
- bytesWritten = compiled.Write(data2, parsed);
- Assert.Equal(35, actualBytes);
- Assert.Equal(35, bytesWritten);
- Assert.Equal(35, compiled.GetMaxSize(parsed));
-
- // Default still returns 70.
- Assert.Equal(70, serializer.GetMaxSize(parsed));
- }
-
- [Fact]
- public void ProgressiveMemoryCopySerialization()
- {
- TestTable t = new()
- {
- Foo = "foobar",
- Struct = new Struct
- {
- Bar = 12,
- }
- };
-
- FlatBufferSerializer serializer = FlatBufferSerializer.Default;
- var compiled = serializer.Compile>().WithSettings(s => s.UseMemoryCopySerialization().UseProgressiveDeserialization());
-
- byte[] data = new byte[1024];
- Assert.Equal(70, compiled.GetMaxSize(t));
- int actualBytes = compiled.Write(data, t);
-
- // First test: Parse the array but don't trim the buffer. This causes the underlying
- // buffer to be much larger than the actual data.
- var parsed = compiled.Parse(data);
- byte[] data2 = new byte[2048];
- int bytesWritten = compiled.Write(data2, parsed);
-
- Assert.Equal(35, actualBytes);
- Assert.Equal(1024, bytesWritten); // We use mem copy serialization here, and we gave it 1024 bytes when we parsed. So we get 1024 bytes back out.
- Assert.Equal(1024, compiled.GetMaxSize(parsed));
- Assert.Throws(() => compiled.Write(new byte[35], parsed));
-
- // Repeat, but now using the trimmed array.
- parsed = compiled.Parse(data.AsMemory().Slice(0, actualBytes));
- bytesWritten = compiled.Write(data2, parsed);
- Assert.Equal(35, actualBytes);
- Assert.Equal(35, bytesWritten);
- Assert.Equal(35, compiled.GetMaxSize(parsed));
-
- // Default still returns 70.
- Assert.Equal(70, serializer.GetMaxSize(parsed));
- }
-
- [FlatBufferTable]
- public class TestTable where T : IInt
- {
- [FlatBufferItem(0)]
- public virtual string? Foo { get; set; }
-
- [FlatBufferItem(1)]
- public virtual T? Struct { get; set; }
- }
-
- public interface IInt
- {
- int Bar { get; set; }
- }
-
- [FlatBufferStruct]
- public class WriteThroughStruct : IInt
- {
- [FlatBufferItem(0, WriteThrough = true)]
- public virtual int Bar { get; set; }
- }
-
- [FlatBufferStruct]
- public class Struct : IInt
- {
- [FlatBufferItem(0)]
- public virtual int Bar { get; set; }
- }
-}
diff --git a/src/Tests/FlatSharpTests/SerializationTests/SharedStringTests.cs b/src/Tests/FlatSharpTests/SerializationTests/SharedStringTests.cs
deleted file mode 100644
index d928e7cf..00000000
--- a/src/Tests/FlatSharpTests/SerializationTests/SharedStringTests.cs
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright 2020 James Courtney
- *
- * 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.Text;
-
-namespace FlatSharpTests;
-
-///
-/// Tests default values on a table.
-///
-public class SharedStringTests
-{
- [Fact]
- public void Test_NonSharedStringVector()
- {
- var t = new RegularStringsVector
- {
- StringVector = new List { "string", "string", "string" },
- };
-
- byte[] destination = new byte[1024];
-
- var serializer = FlatBufferSerializer.Default.Compile();
- int bytesWritten = serializer.Write(default(SpanWriter), destination, t);
-
- byte[] expectedBytes = new byte[]
- {
- 4, 0, 0, 0, // offset to table start
- 248, 255, 255, 255, // soffset to vtable.
- 12, 0, 0, 0, // uoffset to vector
- 6, 0, 8, 0, // vtable length, table length
- 4, 0, 0, 0, // offset within table to item 0 + alignment
- 3, 0, 0, 0, // vector length
- 12, 0, 0, 0, // uffset to first item
- 20, 0, 0, 0, // uoffset to second item
- 28, 0, 0, 0, // uoffset to third item
- 6, 0, 0, 0, // string length
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0, 0, // null terminator + padding
- 6, 0, 0, 0,
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0, 0, // null terminator + padding
- 6, 0, 0, 0,
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0, // null terminator
- };
-
- Assert.True(expectedBytes.AsSpan().SequenceEqual(destination.AsSpan().Slice(0, bytesWritten)));
- }
-
- [Fact]
- public void Test_TableNonSharedStrings()
- {
- var t = new RegularStringsTable
- {
- String1 = "string",
- String2 = "string",
- String3 = "string",
- };
-
- byte[] destination = new byte[1024];
-
- var serializer = FlatBufferSerializer.Default.Compile();
- int bytesWritten = serializer.Write(default(SpanWriter), destination, t);
-
- byte[] expectedBytes = new byte[]
- {
- 4, 0, 0, 0, // offset to table start
- 240, 255, 255, 255, // soffset to vtable.
- 24, 0, 0, 0, // uoffset to string 1
- 32, 0, 0 ,0, // uoffset to string 2
- 40, 0, 0, 0, // uoffset to string 3
- 10, 0, 16, 0, // vtable length, table length
- 12, 0, 8, 0, // vtable(2), vtable(1)
- 4, 0, 0, 0, // vtable(1), padding
- 6, 0, 0, 0, // string length
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0, 0, // null terminator.
- 6, 0, 0, 0,
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0, 0, // null terminator.
- 6, 0, 0, 0,
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0, // null terminator.
- };
-
- Assert.True(expectedBytes.AsSpan().SequenceEqual(destination.AsSpan().Slice(0, bytesWritten)));
- }
-
- [Fact]
- public void Test_VectorSharedStrings()
- {
- var t = new SharedStringsVector
- {
- StringVector = new List { "string", "string", "string" },
- };
-
- byte[] destination = new byte[1024];
-
- int maxBytes = FlatBufferSerializer.Default.GetMaxSize(t);
- var serializer = FlatBufferSerializer.Default.Compile();
-
- int bytesWritten = serializer.Write(default(SpanWriter), destination, t);
-
- Assert.True(bytesWritten <= maxBytes);
-
- byte[] expectedBytes = new byte[]
- {
- 4, 0, 0, 0, // offset to table start
- 248, 255, 255, 255, // soffset to vtable.
- 12, 0, 0, 0, // uoffset to vector
- 6, 0, 8, 0, // vtable length, table length
- 4, 0, 0, 0, // offset within table to item 0 + alignment
- 3, 0, 0, 0, // vector length
- 12, 0, 0, 0, // uffset to first item
- 8, 0, 0, 0, // uoffset to second item
- 4, 0, 0, 0, // uoffset to third item
- 6, 0, 0, 0, // string length
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0 // null terminator.
- };
-
- Assert.True(expectedBytes.AsSpan().SequenceEqual(destination.AsSpan().Slice(0, bytesWritten)));
- }
-
- [Fact]
- public void Test_ISerializerSharedStringSettings()
- {
- var t = new SharedStringsVector
- {
- StringVector = new List { "string", "string", "string" },
- };
-
- byte[] destination = new byte[1024];
-
- int maxBytes = FlatBufferSerializer.Default.GetMaxSize(t);
- var serializer = FlatBufferSerializer.Default.Compile();
-
- int bytesWritten = serializer.Write(default(SpanWriter), destination, t);
-
- Assert.True(bytesWritten <= maxBytes);
-
- byte[] expectedBytes = new byte[]
- {
- 4, 0, 0, 0, // offset to table start
- 248, 255, 255, 255, // soffset to vtable.
- 12, 0, 0, 0, // uoffset to vector
- 6, 0, 8, 0, // vtable length, table length
- 4, 0, 0, 0, // offset within table to item 0 + alignment
- 3, 0, 0, 0, // vector length
- 12, 0, 0, 0, // uffset to first item
- 8, 0, 0, 0, // uoffset to second item
- 4, 0, 0, 0, // uoffset to third item
- 6, 0, 0, 0, // string length
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0 // null terminator.
- };
-
- Assert.True(expectedBytes.AsSpan().SequenceEqual(destination.AsSpan().Slice(0, bytesWritten)));
-
- // Set SharedStringWriter to null. Shared strings remain turned on.
- serializer = serializer.WithSettings(s => s.UseSharedStringWriter());
- bytesWritten = serializer.Write(default(SpanWriter), destination, t);
- Assert.True(expectedBytes.AsSpan().SequenceEqual(destination.AsSpan().Slice(0, bytesWritten)));
-
- // Set SharedStringWriter to return null. Shared strings turn off.
- serializer = serializer.WithSettings(s => s.DisableSharedStrings());
- int bytesWrittenBig = serializer.Write(default(SpanWriter), destination, t);
- Assert.True(bytesWrittenBig > bytesWritten);
- }
-
- [Fact]
- public void Test_TableSharedStrings()
- {
- var t = new SharedStringsTable
- {
- String1 = "string",
- String2 = "string",
- String3 = "string",
- };
-
- byte[] destination = new byte[1024];
-
- var serializer = FlatBufferSerializer.Default.Compile();
- int bytesWritten = serializer.Write(default(SpanWriter), destination, t);
-
- byte[] expectedBytes = new byte[]
- {
- 4, 0, 0, 0, // offset to table start
- 240, 255, 255, 255, // soffset to vtable.
- 24, 0, 0, 0, // uoffset to string 1
- 20, 0, 0 ,0, // uoffset to string 2
- 16, 0, 0, 0, // uoffset to string 3
- 10, 0, 16, 0, // vtable length, table length
- 12, 0, 8, 0, // vtable(0), vtable(1)
- 4, 0, 0, 0, // vtable(2), padding
- 6, 0, 0, 0, // string length
- (byte)'s', (byte)'t', (byte)'r', (byte)'i', (byte)'n', (byte)'g',
- 0 // null terminator.
- };
-
- Assert.True(expectedBytes.AsSpan().SequenceEqual(destination.AsSpan().Slice(0, bytesWritten)));
- }
-
- [Fact]
- public void Test_TableSharedStringsWithNull()
- {
- var t = new SharedStringsTable
- {
- String1 = null,
- String2 = "string",
- String3 = (string)null,
- };
-
- byte[] destination = new byte[1024];
-
- var serializer = FlatBufferSerializer.Default.Compile();
- int bytesWritten = serializer.Write(default(SpanWriter), destination, t);
-
- byte[] expectedBytes = new byte[]
- {
- 4, 0, 0, 0, // offset to table start
- 248, 255, 255, 255, // soffset to vtable.
- 12, 0, 0 ,0, // uoffset to string
- 8, 0, 8, 0, // vtable length, table length
- 0, 0, 4, 0, // vtable(0), vtable(1)
- 6, 0, 0, 0, // string length
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0 // null terminator.
- };
-
- Assert.True(expectedBytes.AsSpan().SequenceEqual(destination.AsSpan().Slice(0, bytesWritten)));
- }
-
- ///
- /// Tests with an LRU string writer that can only hold onto one item at a time. Each new string it sees evicts the old one.
- ///
- [Fact]
- public void Test_TableSharedStringsWithEviction()
- {
- var t = new SharedStringsTable
- {
- String1 = "string",
- String2 = "foo",
- String3 = "string",
- };
-
- byte[] destination = new byte[1024];
- var serializer = FlatBufferSerializer.Default.Compile()
- .WithSettings(s => s.UseDefaultSharedStringWriter(1));
-
- int bytesWritten = serializer.Write(default(SpanWriter), destination, t);
-
- byte[] expectedBytes = new byte[]
- {
- 4, 0, 0, 0, // offset to table start
- 240, 255, 255, 255, // soffset to vtable.
- 24, 0, 0, 0, // uoffset to string 1
- 32, 0, 0 ,0, // uoffset to string 2
- 36, 0, 0, 0, // uoffset to string 3
- 10, 0, 16, 0, // vtable length, table length
- 12, 0, 8, 0, // vtable(0), vtable(1)
- 4, 0, 0, 0, // vtable(2), padding
- 6, 0, 0, 0, // string0 length
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0, 0, // null terminator + 1 byte padding
- 3, 0, 0, 0, // string1 length
- (byte)'f', (byte)'o', (byte)'o', 0, // string1 + null terminator
- 6, 0, 0, 0,
- (byte)'s', (byte)'t', (byte)'r', (byte)'i',
- (byte)'n', (byte)'g', 0 // null terminator
- };
-
- Assert.True(expectedBytes.AsSpan().SequenceEqual(destination.AsSpan().Slice(0, bytesWritten)));
- }
-
- ///
- /// Identical to the above test but with a large enough LRU cache to handle both strings.
- ///
- [Fact]
- public void Test_TableSharedStringsWithoutEviction()
- {
- var t = new SharedStringsTable
- {
- String1 = "string",
- String2 = "foo",
- String3 = "string",
- };
-
- byte[] destination = new byte[1024];
- var serializer = FlatBufferSerializer.Default.Compile();
-
- int bytesWritten = serializer.Write(default(SpanWriter), destination, t);
-
- byte[] stringBytes = Encoding.UTF8.GetBytes("string");
-
- // We can't predict ordering since there is hashing under the hood.
- int firstIndex = destination.AsSpan().IndexOf(stringBytes);
- int secondIndex = destination.AsSpan().Slice(0, firstIndex + 1).IndexOf(stringBytes);
- Assert.Equal(-1, secondIndex);
- }
-
- [FlatBufferTable]
- public class SharedStringsVector : object
- {
- [FlatBufferItem(0, SharedString = true)]
- public virtual IList? StringVector { get; set; }
- }
-
- [FlatBufferTable]
- public class RegularStringsVector : object
- {
- [FlatBufferItem(0)]
- public virtual IList? StringVector { get; set; }
- }
-
- [FlatBufferTable]
- public class SharedStringsTable : object
- {
- [FlatBufferItem(0, SharedString = true)]
- public virtual string? String1 { get; set; }
-
- [FlatBufferItem(1, SharedString = true)]
- public virtual string? String2 { get; set; }
-
- [FlatBufferItem(2, SharedString = true)]
- public virtual string? String3 { get; set; }
- }
-
- [FlatBufferTable]
- public class RegularStringsTable : object
- {
- [FlatBufferItem(0)]
- public virtual string? String1 { get; set; }
-
- [FlatBufferItem(1)]
- public virtual string? String2 { get; set; }
-
- [FlatBufferItem(2)]
- public virtual string? String3 { get; set; }
- }
-}
diff --git a/src/Tests/FlatSharpTests/SerializationTests/TableSerializationTests.cs b/src/Tests/FlatSharpTests/SerializationTests/TableSerializationTests.cs
index 4873e02a..2d56c666 100644
--- a/src/Tests/FlatSharpTests/SerializationTests/TableSerializationTests.cs
+++ b/src/Tests/FlatSharpTests/SerializationTests/TableSerializationTests.cs
@@ -25,112 +25,12 @@ namespace FlatSharpTests;
public class TableSerializationTests
{
- [Fact]
- public void AllMembersNull()
- {
- SimpleTable table = new SimpleTable();
-
- byte[] buffer = new byte[1024];
-
- byte[] expectedData =
- {
- 4, 0, 0, 0,
- 252, 255, 255, 255,
- 4, 0,
- 4, 0,
- };
-
- int bytesWritten = FlatBufferSerializer.Default.Serialize(table, buffer);
- Assert.True(expectedData.AsSpan().SequenceEqual(buffer.AsSpan().Slice(0, bytesWritten)));
- }
-
[Fact]
public void RootTableNull()
{
Assert.Throws(() => FlatBufferSerializer.Default.Serialize(null, new byte[1024]));
}
- [Fact]
- public void TableWithStruct()
- {
- SimpleTable table = new SimpleTable
- {
- Struct = new SimpleStruct { Byte = 1, Long = 2, Uint = 3 }
- };
-
- byte[] buffer = new byte[1024];
-
- byte[] expectedData =
- {
- 4, 0, 0, 0, // uoffset to table start
- 236, 255, 255, 255, // soffet to vtable (4 - x = 24 => x = -20)
- 2, 0, 0, 0, 0, 0, 0, 0, // struct.long
- 1, // struct.byte
- 0, 0, 0, // padding
- 3, 0, 0, 0, // struct.uint
- 8, 0, // vtable length
- 20, 0, // table length
- 0, 0, // index 0 offset
- 4, 0, // Index 1 offset
- };
-
- int bytesWritten = FlatBufferSerializer.Default.Serialize(table, buffer);
- Assert.True(expectedData.AsSpan().SequenceEqual(buffer.AsSpan().Slice(0, bytesWritten)));
- }
-
- [Fact]
- public void TableWithStructAndString()
- {
- SimpleTable table = new SimpleTable
- {
- String = "hi",
- Struct = new SimpleStruct { Byte = 1, Long = 2, Uint = 3 }
- };
-
- byte[] buffer = new byte[1024];
-
- byte[] expectedData =
- {
- 4, 0, 0, 0, // uoffset to table start
- 232, 255, 255, 255, // soffet to vtable (4 - x = 24 => x = -20)
- 2, 0, 0, 0, 0, 0, 0, 0, // struct.long
- 1, 0, 0, 0, // struct.byte + padding
- 3, 0, 0, 0, // struct.uint
- 12, 0, 0, 0, // uoffset to string
- 8, 0, // vtable length
- 24, 0, // table length
- 20, 0, // index 0 offset
- 4, 0, // Index 1 offset
- 2, 0, 0, 0, // string length
- 104, 105, 0, // hi + null terminator
- };
-
- int bytesWritten = FlatBufferSerializer.Default.Serialize(table, buffer);
- Assert.True(expectedData.AsSpan().SequenceEqual(buffer.AsSpan().Slice(0, bytesWritten)));
- }
-
- [Fact]
- public void EmptyTableSerialize()
- {
- EmptyTable table = new EmptyTable();
-
- byte[] buffer = new byte[1024];
-
- byte[] expectedData =
- {
- 4, 0, 0, 0,
- 252, 255, 255, 255,
- 4, 0,
- 4, 0,
- };
-
- int bytesWritten = FlatBufferSerializer.Default.Serialize(table, buffer);
- Assert.True(expectedData.AsSpan().SequenceEqual(buffer.AsSpan().Slice(0, bytesWritten)));
-
- int maxSize = FlatBufferSerializer.Default.GetMaxSize(table);
- Assert.Equal(23, maxSize);
- }
-
[Fact]
public void TableParse_NotMutable()
{
diff --git a/src/Tests/FlatSharpTests/SerializationTests/VectorSerializationTests.cs b/src/Tests/FlatSharpTests/SerializationTests/VectorSerializationTests.cs
index 3ba014d9..e0329d19 100644
--- a/src/Tests/FlatSharpTests/SerializationTests/VectorSerializationTests.cs
+++ b/src/Tests/FlatSharpTests/SerializationTests/VectorSerializationTests.cs
@@ -29,61 +29,6 @@ public class VectorSerializationTests
{
public class SimpleTests
{
- [Fact]
- public void EmptyString()
- {
- var root = new RootTable
- {
- Vector = string.Empty,
- };
-
- Span target = new byte[10240];
- int offset = FlatBufferSerializer.Default.Serialize(root, target);
- target = target.Slice(0, offset);
-
- byte[] expectedResult =
- {
- 4, 0, 0, 0, // offset to table start
- 248, 255, 255, 255, // soffset to vtable (-8)
- 12, 0, 0, 0, // uoffset_t to string
- 6, 0, // vtable length
- 8, 0, // table length
- 4, 0, // offset of index 0 field
- 0, 0, // padding to 4-byte alignment
- 0, 0, 0, 0, // vector length
- 0, // null terminator (special case for strings).
- };
-
- Assert.True(expectedResult.AsSpan().SequenceEqual(target));
- }
-
- [Fact]
- public void SimpleString()
- {
- var root = new RootTable
- {
- Vector = new string(new char[] { (char)1, (char)2, (char)3 }),
- };
-
- Span target = new byte[10240];
- int offset = FlatBufferSerializer.Default.Serialize(root, target);
- target = target.Slice(0, offset);
-
- byte[] expectedResult =
- {
- 4, 0, 0, 0, // offset to table start
- 248, 255, 255, 255, // soffset to vtable (-8)
- 12, 0, 0, 0, // uoffset_t to vector
- 6, 0, // vtable length
- 8, 0, // table length
- 4, 0, // offset of index 0 field
- 0, 0, // padding to 4-byte alignment
- 3, 0, 0, 0, // vector length
- 1, 2, 3, 0, // data + null terminator (special case for string vectors).
- };
-
- Assert.True(expectedResult.AsSpan().SequenceEqual(target));
- }
[Fact]
public void Simple_Scalar_Vectors()
@@ -536,142 +481,6 @@ public void SortedVector_BinarySearch_ErrorCases()
}
}
- public class IndexedVectorTests
- {
- [Fact]
- public void IndexedVector_Simple()
- {
- var table = new RootTableSorted>>
- {
- Vector = new IndexedVector>
- {
- { new TableWithKey { Key = "a", Value = "AAA" } },
- { new TableWithKey { Key = "b", Value = "BBB" } },
- { new TableWithKey { Key = "c", Value = "CCC" } },
- }
- };
-
- var serializer = FlatBufferSerializer.Default.Compile>>>()
- .WithSettings(s => s.UseLazyDeserialization());
-
- byte[] data = new byte[1024 * 1024];
- serializer.Write(data, table);
-
- var parsed = serializer.Parse(data);
-
- Assert.Equal("AAA", parsed.Vector["a"].Value);
- Assert.Equal("BBB", parsed.Vector["b"].Value);
- Assert.Equal("CCC", parsed.Vector["c"].Value);
-
- Assert.True(parsed.Vector.TryGetValue("a", out var value) && value.Value == "AAA");
- Assert.True(parsed.Vector.TryGetValue("b", out value) && value.Value == "BBB");
- Assert.True(parsed.Vector.TryGetValue("c", out value) && value.Value == "CCC");
- }
-
- [Fact]
- public void IndexedVector_RandomString()
- {
- var table = new RootTable>>
- {
- Vector = new IndexedVector>()
- };
-
- List keys = new List();
- for (int i = 0; i < 1000; ++i)
- {
- string key = Guid.NewGuid().ToString();
- keys.Add(key);
-
- table.Vector.AddOrReplace(new TableWithKey { Key = key, Value = Guid.NewGuid().ToString() });
- }
-
- byte[] data = new byte[10 * 1024 * 1024];
- var serializer = FlatBufferSerializer.Default.Compile>>>().WithSettings(s => s.UseLazyDeserialization());
- int bytesWritten = serializer.Write(data, table);
-
- var parsed = serializer.Parse(data);
-
- foreach (var key in keys)
- {
- Assert.Equal(table.Vector[key].Value, parsed.Vector[key].Value);
- }
- }
-
- [Fact]
- public void IndexedVector_RandomByte() => IndexedVectorScalarTest();
-
- [Fact]
- public void IndexedVector_RandomSByte() => IndexedVectorScalarTest();
-
- [Fact]
- public void IndexedVector_RandomUShort() => IndexedVectorScalarTest();
-
- [Fact]
- public void IndexedVector_RandomShort() => IndexedVectorScalarTest();
-
- [Fact]
- public void IndexedVector_RandomUInt() => IndexedVectorScalarTest();
-
- [Fact]
- public void IndexedVector_RandomInt() => IndexedVectorScalarTest();
-
- [Fact]
- public void IndexedVector_RandomULong() => IndexedVectorScalarTest();
-
- [Fact]
- public void IndexedVector_RandomLong() => IndexedVectorScalarTest();
-
- private void IndexedVectorScalarTest() where T : struct
- {
- foreach (FlatBufferDeserializationOption option in Enum.GetValues(typeof(FlatBufferDeserializationOption)))
- {
- var table = new RootTable>>
- {
- Vector = new IndexedVector>()
- };
-
- Random r = new Random();
- byte[] keyBuffer = new byte[8];
- List keys = new List();
- for (int i = 0; i < 1000; ++i)
- {
- r.NextBytes(keyBuffer);
- T key = MemoryMarshal.Cast(keyBuffer)[0];
- keys.Add(key);
- table.Vector.AddOrReplace(new TableWithKey { Key = key, Value = Guid.NewGuid().ToString() });
- }
-
- byte[] data = new byte[1024 * 1024];
- var serializer = FlatBufferSerializer.Default.Compile>>>().WithSettings(s => s.UseDeserializationMode(option));
- int bytesWritten = serializer.Write(data, table);
-
- var parsed = serializer.Parse>>>(data);
-
- foreach (var key in keys)
- {
- Assert.Equal(table.Vector[key].Value, parsed.Vector[key].Value);
- }
-
- // verify sorted and that we can read it when it's from a normal vector.
- var listSerializer = FlatBufferSerializer.Default.Compile>>>().WithSettings(s => s.UseDeserializationMode(option));
- var parsedList = listSerializer.Parse(data);
- Assert.Equal(parsed.Vector.Count, parsedList.Vector.Count);
- var previous = parsedList.Vector[0];
- for (int i = 1; i < parsedList.Vector.Count; ++i)
- {
- var item = parsedList.Vector[i];
- Assert.True(Comparer.Default.Compare(previous.Key, item.Key) <= 0);
-
- Assert.True(parsed.Vector.TryGetValue(item.Key, out var fromDict));
- Assert.Equal(item.Key, fromDict.Key);
- Assert.Equal(item.Value, fromDict.Value);
-
- previous = item;
- }
- }
- }
- }
-
public class VectorOfUnionTests
{
[Fact]