示例#1
0
        private void TestType <T>(bool listCache, Func <T> generator) where T : IEquatable <T>
        {
            var options = new FlatBufferSerializerOptions(listCache ? FlatBufferDeserializationOption.VectorCache : FlatBufferDeserializationOption.Lazy);
            FlatBufferSerializer serializer = new FlatBufferSerializer(options);

            {
                var memoryTable = new RootTable <IList <T> >
                {
                    Vector = Enumerable.Range(0, 10).Select(i => generator()).ToArray()
                };

                Span <byte> memory            = new byte[10240];
                int         offset            = serializer.Serialize(memoryTable, memory);
                var         memoryTableResult = serializer.Parse <RootTable <IList <T> > >(memory.Slice(0, offset).ToArray());

                var resultVector = memoryTableResult.Vector;
                for (int i = 0; i < memoryTableResult.Vector.Count; ++i)
                {
                    Assert.AreEqual <T>(memoryTable.Vector[i], resultVector[i]);

                    // reference equality should correspond to the serializer.
                    Assert.AreEqual(listCache, object.ReferenceEquals(resultVector[i], resultVector[i]));
                }
            }

            {
                var memoryTable = new RootTable <IReadOnlyList <T> >
                {
                    Vector = Enumerable.Range(0, 10).Select(i => generator()).ToArray()
                };

                Span <byte> memory            = new byte[10240];
                int         offset            = serializer.Serialize(memoryTable, memory);
                var         memoryTableResult = serializer.Parse <RootTable <IReadOnlyList <T> > >(memory.Slice(0, offset).ToArray());
                var         resultVector      = memoryTableResult.Vector;
                for (int i = 0; i < memoryTableResult.Vector.Count; ++i)
                {
                    Assert.AreEqual(memoryTable.Vector[i], resultVector[i]);

                    // reference equality should correspond to the serializer.
                    Assert.AreEqual(listCache, object.ReferenceEquals(resultVector[i], resultVector[i]));
                }
            }

            {
                var memoryTable = new RootTable <T[]>
                {
                    Vector = Enumerable.Range(0, 10).Select(i => generator()).ToArray()
                };

                Span <byte> memory            = new byte[10240];
                int         offset            = serializer.Serialize(memoryTable, memory);
                var         memoryTableResult = serializer.Parse <RootTable <T[]> >(memory.Slice(0, offset).ToArray());
                var         resultVector      = memoryTableResult.Vector;
                for (int i = 0; i < memoryTableResult.Vector.Length; ++i)
                {
                    Assert.AreEqual(memoryTable.Vector[i], resultVector[i]);
                }
            }
        }
示例#2
0
        public void TestInitialize()
        {
            this.stringDictionary = new TableVector <string> {
                Vector = new Dictionary <string, VectorMember <string> >()
            };
            this.intDictionary = new TableVector <int> {
                Vector = new Dictionary <int, VectorMember <int> >()
            };

            for (int i = 0; i < 10; ++i)
            {
                this.stringDictionary.Vector[i.ToString()] = new VectorMember <string> {
                    Key = i.ToString(), Value = Guid.NewGuid().ToString()
                };
                this.intDictionary.Vector[i] = new VectorMember <int> {
                    Key = i, Value = Guid.NewGuid().ToString()
                };
            }

            Span <byte> buffer = new byte[1024];

            var serializer   = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Lazy));
            int bytesWritten = serializer.Serialize(this.stringDictionary, buffer);

            this.stringDictionary = serializer.Parse <TableVector <string> >(buffer.Slice(0, bytesWritten).ToArray());

            bytesWritten       = serializer.Serialize(this.intDictionary, buffer);
            this.intDictionary = serializer.Parse <TableVector <int> >(buffer.Slice(0, bytesWritten).ToArray());
        }
            static void Test(FlatBufferDeserializationOption option)
            {
                var table = new Table <IList <WriteThroughStruct <long> > >
                {
                    Struct = new List <WriteThroughStruct <long> >
                    {
                        new WriteThroughStruct <long> {
                            Value = 5
                        }
                    }
                };

                FlatBufferSerializer serializer = new FlatBufferSerializer(option);

                byte[] buffer = new byte[1024];
                serializer.Serialize(table, buffer);

                // parse
                var parsed1 = serializer.Parse <Table <IList <WriteThroughStruct <long> > > >(buffer);

                // mutate
                parsed1.Struct[0].Value = 300;
                Assert.Equal(300, parsed1.Struct[0].Value);

                // verify
                var parsed2 = serializer.Parse <Table <IList <WriteThroughStruct <long> > > >(buffer);

                Assert.Equal(300, parsed2.Struct[0].Value);
            }
    public FlatBufferVectorTests()
    {
        var originalVector = new TableVector <string>
        {
            Vector = ExpectedStringContents.ToList()
        };

        var originalIntVector = new TableVector <int> {
            Vector = ExpectedIntContents.ToList()
        };

        Span <byte> buffer = new byte[1024 * 1024];

        var serializer            = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Lazy));
        var progressiveSerializer = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Progressive));

        int bytesWritten = serializer.Serialize(originalVector, buffer);

        this.stringVector            = serializer.Parse <TableVector <string> >(buffer.Slice(0, bytesWritten).ToArray());
        this.progressiveStringVector = progressiveSerializer.Parse <TableVector <string> >(buffer.Slice(0, bytesWritten).ToArray());

        bytesWritten              = serializer.Serialize(originalIntVector, buffer);
        this.intVector            = serializer.Parse <TableVector <int> >(buffer.Slice(0, bytesWritten).ToArray());
        this.progressiveIntVector = progressiveSerializer.Parse <TableVector <int> >(buffer.Slice(0, bytesWritten).ToArray());
    }
        public void Success(FlatBufferDeserializationOption option)
        {
            FlatBufferSerializer serializer = new FlatBufferSerializer(option);

            WriteThroughTable_NotRequired <IList <ValueStruct> > table = new()
            {
                Item = new List <ValueStruct>
                {
                    new() { Value = 1 }
                }
            };

            byte[] result = new byte[1024];
            serializer.Serialize(table, result);

            var parsed = serializer.Parse <WriteThroughTable_NotRequired <IList <ValueStruct> > >(result);

            Assert.Equal(1, parsed.Item[0].Value);

            parsed.Item[0] = new ValueStruct {
                Value = 4
            };

            // Re-read and verify the in-struct writethrough succeeded.
            parsed = serializer.Parse <WriteThroughTable_NotRequired <IList <ValueStruct> > >(result);
            Assert.Equal(4, parsed.Item[0].Value);
        }
        public void Success_NonNullable(FlatBufferDeserializationOption option)
        {
            FlatBufferSerializer serializer = new FlatBufferSerializer(option);

            WriteThroughTable_Required <ValueStruct> table = new()
            {
                Item = new ValueStruct {
                    Value = 1
                }
            };

            byte[] result = new byte[1024];

            var code = serializer.Compile <WriteThroughTable_Required <ValueStruct> >().CSharp;

            serializer.Serialize(table, result);

            var parsed = serializer.Parse <WriteThroughTable_Required <ValueStruct> >(result);

            Assert.Equal(1, parsed.Item.Value);

            parsed.Item = new ValueStruct {
                Value = 4
            };

            // Re-read and verify the in-struct writethrough succeeded.
            parsed = serializer.Parse <WriteThroughTable_Required <ValueStruct> >(result);
            Assert.Equal(4, parsed.Item.Value);
        }
        public void Success_Nullable(FlatBufferDeserializationOption option)
        {
            FlatBufferSerializer serializer = new FlatBufferSerializer(option);

            WriteThroughTable_Required <ValueStruct?> table = new()
            {
                Item = new ValueStruct {
                    Value = 1
                }
            };

            byte[] result = new byte[1024];

            var code = serializer.Compile <WriteThroughTable_Required <ValueStruct?> >().CSharp;

            serializer.Serialize(table, result);

            var parsed = serializer.Parse <WriteThroughTable_Required <ValueStruct?> >(result);

            Assert.Equal(1, parsed.Item.Value.Value);

            parsed.Item = new ValueStruct {
                Value = 4
            };

            // Re-read and verify the in-struct writethrough succeeded.
            parsed = serializer.Parse <WriteThroughTable_Required <ValueStruct?> >(result);
            Assert.Equal(4, parsed.Item.Value.Value);

            var ex = Assert.Throws <InvalidOperationException>(() => parsed.Item = null);

            Assert.Equal(
                "Nullable object must have a value.",
                ex.Message);
        }
示例#8
0
        public void MemoryVector_LazyDeserialize()
        {
            RootTable <Memory <byte> > root = new RootTable <Memory <byte> >()
            {
                Vector = new Memory <byte>(new byte[100])
            };

            root.Vector.Span.Fill(1);

            byte[] buffer     = new byte[1024];
            var    options    = new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Lazy);
            var    serializer = new FlatBufferSerializer(options);

            serializer.Serialize(root, buffer.AsSpan());

            var parsed1 = serializer.Parse <RootTable <Memory <byte> > >(buffer);
            var parsed2 = serializer.Parse <RootTable <Memory <byte> > >(buffer);

            Assert.AreEqual((byte)1, parsed1.Vector.Span[0]);
            Assert.AreEqual((byte)1, parsed2.Vector.Span[0]);

            // Asser that this change affects both objects.
            parsed1.Vector.Span[0] = 2;

            Assert.AreEqual((byte)2, parsed1.Vector.Span[0]);
            Assert.AreEqual((byte)2, parsed2.Vector.Span[0]);
        }
        public void Parse_SixteenByte(bool marshal)
        {
            byte[] data =
            {
                4,     0,   0,   0,
                236, 255, 255, 255,
                1,     0,   0,   0, 0, 0, 0, 0,
                2,     0,   0,   0, 0, 0, 0, 0,
                6,     0,
                20,    0,
                4,     0,
            };

            var serializer = new FlatBufferSerializer(new FlatBufferSerializerOptions {
                EnableValueStructMemoryMarshalDeserialization = marshal
            });
            var parsed = serializer.Parse <SimpleTableAnything <SixteenByteStruct?> >(data);

            Assert.NotNull(parsed);
            Assert.NotNull(parsed.Item);
            Assert.Equal(1, parsed.Item.Value.A);
            Assert.Equal(2ul, parsed.Item.Value.B);

            Assert.Equal(marshal, serializer.Compile <SimpleTableAnything <SixteenByteStruct?> >().CSharp.Contains("MemoryMarshal.Cast"));
        }
        /// <summary>
        /// In lazy deserialization, FlatSharp reads from the underlying buffer each time. No caching is done. This will be
        /// the fastest option if your access patterns are sparse and you touch each element only once.
        /// </summary>
        public static void LazyDeserialization(DemoTable demo)
        {
            var serializer = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Lazy));

            byte[] buffer = new byte[1024];
            serializer.Serialize(demo, buffer);
            var parsed = serializer.Parse <DemoTable>(buffer);

            // Lazy deserialization reads objects from vectors each time you ask for them.
            InnerTable index0_1 = parsed.ListVector[0];
            InnerTable index0_2 = parsed.ListVector[0];

            Debug.Assert(!object.ReferenceEquals(index0_1, index0_2), "A different instance is returned each time from lazy vectors");

            // Properties from tables and structs are cached after they are read.
            string name  = parsed.Name;
            string name2 = parsed.Name;

            Debug.Assert(
                !object.ReferenceEquals(name, name2),
                "When reading table/struct properties Lazy parsing returns a different instance each time.");

            // Invalidate the whole buffer. Undefined behavior past here!
            Array.Fill(buffer, (byte)0);

            try
            {
                var whoKnows = parsed.ListVector[1];
                Debug.Assert(false);
            }
            catch
            {
                // This can be any sort of exception. This behavior is undefined.
            }
        }
    private InnerTable <T> SerializeAndParse <T>(FlatBufferDeserializationOption option, T item)
    {
        FlatBufferSerializer serializer = new FlatBufferSerializer(new FlatBufferSerializerOptions(option));

        InnerTable <T> value = new InnerTable <T>
        {
            First = new FirstStruct {
                First = 1
            },
            Second = new SecondStruct {
                Second = 2,
            },
            String = "Foo bar baz bat",
            Union  = new FlatBufferUnion <FirstStruct, SecondStruct, string>(new SecondStruct {
                Second = 3
            }),
            Vector = item,
        };

        serializer.Serialize(value, InputBuffer);
        InnerTable <T> parsed = serializer.Parse <InnerTable <T> >(InputBuffer);

        Assert.Equal(1, parsed.First.First);
        Assert.Equal(2, parsed.Second.Second);
        Assert.Equal("Foo bar baz bat", parsed.String);
        Assert.Equal(3, parsed.Union.Value.Item2.Second);

        return(parsed);
    }
示例#12
0
    private void RunTest(FlatBufferDeserializationOption option)
    {
        Table table = new Table
        {
            Outer = new OuterStruct
            {
                InnerVirtual = new InnerStruct {
                    A = 3
                },
                NonVirtualInner = new InnerStruct {
                    A = 30
                }
            }
        };

        FlatBufferSerializer serializer = new FlatBufferSerializer(option);

        byte[] data = new byte[1024];
        serializer.Serialize(table, data);

        var parsed = serializer.Parse <Table>(data);

        Assert.Equal(3, parsed.Outer.InnerVirtual.A);
        Assert.Equal(30, parsed.Outer.NonVirtualInner.A);
    }
示例#13
0
        private SimpleTable SerializeAndParse(FlatBufferSerializerOptions options, out WeakReference <byte[]> buffer)
        {
            SimpleTable table = new SimpleTable
            {
                String = "hi",
                Struct = new SimpleStruct {
                    Byte = 1, Long = 2, Uint = 3
                },
                StructVector = new List <SimpleStruct> {
                    new SimpleStruct {
                        Byte = 4, Long = 5, Uint = 6
                    }
                },
            };

            var serializer = new FlatBufferSerializer(options);

            var rawBuffer = new byte[1024];

            serializer.Serialize(table, rawBuffer);
            buffer = new WeakReference <byte[]>(rawBuffer);

            string csharp = serializer.Compile <SimpleTable>().CSharp;

            return(serializer.Parse <SimpleTable>(rawBuffer));
        }
示例#14
0
        public static void Run()
        {
            TypeModelContainer container = TypeModelContainer.CreateDefault();

            container.RegisterTypeFacade <long, DateTimeOffset, DateTimeOffsetTypeFacadeConverter>();
            container.RegisterTypeFacade <byte[], Guid, GuidByteArrayConverter>();

            var example = new FacadeExampleTable
            {
                Guid      = Guid.NewGuid(),
                Timestamp = DateTimeOffset.UtcNow,
            };

            FlatBufferSerializer serializer = new FlatBufferSerializer(
                new FlatBufferSerializerOptions(FlatBufferDeserializationOption.PropertyCache),
                container);

            byte[] destination = new byte[1024];
            serializer.Serialize(example, destination);

            var parsed = serializer.Parse <FacadeExampleTable>(destination);

            Debug.Assert(parsed.Guid == example.Guid);
            Debug.Assert(parsed.Timestamp == example.Timestamp);
        }
    public void SortedVectors(FlatBufferDeserializationOption option)
    {
        var builder = new FlatBuffers.FlatBufferBuilder(1024 * 1024);

        var strings       = new List <string>();
        var stringOffsets = new List <FlatBuffers.Offset <Oracle.SortedVectorStringTable> >();

        List <int> ints       = new List <int>();
        var        intOffsets = new List <FlatBuffers.Offset <Oracle.SortedVectorInt32Table> >();

        List <double> doubles       = new List <double>();
        var           doubleOffsets = new List <FlatBuffers.Offset <Oracle.SortedVectorDoubleTable> >();

        const int Iterations = 1000;
        Random    random     = new Random();

        for (int i = 0; i < Iterations; ++i)
        {
            string value = Guid.NewGuid().ToString();
            strings.Add(value);
            stringOffsets.Add(Oracle.SortedVectorStringTable.CreateSortedVectorStringTable(builder, builder.CreateString(value)));
        }

        for (int i = 0; i < Iterations; ++i)
        {
            int value = random.Next();
            ints.Add(value);
            intOffsets.Add(Oracle.SortedVectorInt32Table.CreateSortedVectorInt32Table(builder, value));
        }

        for (int i = 0; i < Iterations; ++i)
        {
            double value = random.NextDouble() * random.Next();
            doubles.Add(value);
            doubleOffsets.Add(Oracle.SortedVectorDoubleTable.CreateSortedVectorDoubleTable(builder, value));
        }

        var table = Oracle.SortedVectorTest.CreateSortedVectorTest(
            builder,
            Oracle.SortedVectorInt32Table.CreateSortedVectorOfSortedVectorInt32Table(builder, intOffsets.ToArray()),
            Oracle.SortedVectorStringTable.CreateSortedVectorOfSortedVectorStringTable(builder, stringOffsets.ToArray()),
            Oracle.SortedVectorDoubleTable.CreateSortedVectorOfSortedVectorDoubleTable(builder, doubleOffsets.ToArray()));

        builder.Finish(table.Value);
        byte[] serialized = builder.SizedByteArray();

        var serializer = new FlatBufferSerializer(option);
        var parsed     = serializer.Parse <SortedVectorTest <SortedVectorItem <int> > >(serialized);

        VerifySorted(parsed.StringVector, new Utf8StringComparer(), strings, new List <string> {
            Guid.NewGuid().ToString(), "banana"
        });
        VerifySorted(parsed.IntVector, Comparer <int> .Default, ints, new List <int> {
            -1, -3, 0
        });
        VerifySorted(parsed.Double, Comparer <double> .Default, doubles, new List <double> {
            Math.PI, Math.E, Math.Sqrt(2)
        });
    }
示例#16
0
    /// <summary>
    /// In lazy deserialization, FlatSharp reads from the underlying buffer each time. No caching is done. This will be
    /// the fastest option if your access patterns are sparse and you touch each element only once.
    /// </summary>
    public static void LazyDeserialization(DemoTable demo)
    {
        var serializer = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Lazy));

        byte[] buffer = new byte[1024];
        serializer.Serialize(demo, buffer);
        var parsed = serializer.Parse <DemoTable>(buffer);

        // Lazy deserialization reads objects from vectors each time you ask for them.
        InnerTable index0_1 = parsed.ListVector ![0];
示例#17
0
    public IndexedVectorTests()
    {
        this.stringVectorSource = new TableVector <string> {
            Vector = new IndexedVector <string, VectorMember <string> >()
        };
        this.intVectorSource = new TableVector <int> {
            Vector = new IndexedVector <int, VectorMember <int> >()
        };
        this.stringKeys = new List <string>();

        for (int i = 0; i < 10; ++i)
        {
            string key = i.ToString();
            stringKeys.Add(key);

            this.stringVectorSource.Vector.AddOrReplace(new VectorMember <string> {
                Key = key, Value = Guid.NewGuid().ToString()
            });
            this.intVectorSource.Vector.AddOrReplace(new VectorMember <int> {
                Key = i, Value = Guid.NewGuid().ToString()
            });
        }

        this.stringVectorSource.Vector.Freeze();
        this.intVectorSource.Vector.Freeze();

        Span <byte> buffer = new byte[1024];

        var serializer            = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Lazy));
        var progressiveSerializer = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Progressive));

        int bytesWritten = serializer.Serialize(this.stringVectorSource, buffer);

        this.stringVectorParsed      = serializer.Parse <TableVector <string> >(buffer.Slice(0, bytesWritten).ToArray());
        this.stringVectorProgressive = progressiveSerializer.Parse <TableVector <string> >(buffer.Slice(0, bytesWritten).ToArray());

        bytesWritten              = serializer.Serialize(this.intVectorSource, buffer);
        this.intVectorParsed      = serializer.Parse <TableVector <int> >(buffer.Slice(0, bytesWritten).ToArray());
        this.intVectorProgressive = progressiveSerializer.Parse <TableVector <int> >(buffer.Slice(0, bytesWritten).ToArray());
    }
示例#18
0
        public void TestInitialize()
        {
            var originalVector = new TableVector
            {
                StringVector = ExpectedContents.ToList()
            };

            Span <byte> buffer = new byte[1024];

            var serializer   = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Greedy));
            int bytesWritten = serializer.Serialize(originalVector, buffer);

            this.parsedVector = serializer.Parse <TableVector>(buffer.Slice(0, bytesWritten).ToArray());
        }
示例#19
0
    private void VectorOfUnionTest <V>(
        FlatBufferDeserializationOption option,
        Func <V, FlatBufferUnion <string, Struct, TableWithKey <int> >[]> getItems)
        where V : class, new()
    {
        byte[] data =
        {
            4,     0,   0,   0,
            244, 255, 255, 255,
            16,    0,   0,   0, // uoffset to discriminator vector
            20,    0,   0,   0, // uoffset to offset vector
            8,     0,           // vtable
            12,    0,
            4,     0,
            8,     0,
            3,     0,   0,   0, // discriminator vector length
            1,     2,   3,   0, // values + 1 byte padding
            3,     0,   0,   0, // offset vector length
            12,    0,   0,   0, // value 0
            16,    0,   0,   0, // value 1
            16,    0,   0,   0, // value 2
            3,     0,   0,   0, // string length
            102, 111, 111,   0, // foo + null terminator
            3,     0,   0,   0, // struct value ('3')
            248, 255, 255, 255, // table vtable offset
            1,     0,   0,   0, // value of 'key'
            8,     0,           // table vtable start
            8,     0,
            0,     0,
            4,     0,
        };

        var serializer = new FlatBufferSerializer(option);
        V   parsed     = serializer.Parse <V>(data);
        var items      = getItems(parsed);

        Assert.True(items[0].TryGet(out string str));
        Assert.Equal("foo", str);

        Assert.True(items[1].TryGet(out Struct @struct));
        Assert.Equal(3, @struct.Integer);

        Assert.True(items[2].TryGet(out TableWithKey <int> table));
        Assert.Equal(1, table.Key);
        Assert.Null(table.Value);
    }
        /// <summary>
        /// Greedy deserialization operates the same way that conventional serializers do. The entire buffer is traversed
        /// and the structure is copied into the deserialized object. This is the most straightforward way of using FlatSharp,
        /// because the results it gives are predictable, and require no developer cognitive overhead. However, it can be less efficient
        /// in cases where you do not need to access all data in the buffer.
        /// </summary>
        public static void GreedyDeserialization(DemoTable demo)
        {
            // Same as FlatBufferSerializer.Default
            var serializer = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Greedy));

            byte[] buffer = new byte[1024];
            serializer.Serialize(demo, buffer);
            long originalSum = buffer.Sum(x => (long)x);

            var parsed = serializer.Parse <DemoTable>(buffer);

            // Fill array with 0. Source data is gone now, but we can still read the buffer because we were greedy!
            Array.Fill(buffer, (byte)0);

            InnerTable index0_1 = parsed.ListVector[0];
            InnerTable index0_2 = parsed.ListVector[0];

            Debug.Assert(object.ReferenceEquals(index0_1, index0_2), "Greedy deserialization returns you the same instance each time");

            // We cleared the data, but can still read the name. Greedy deserialization is easy!
            string name = parsed.Name;

            // By default, Flatsharp will not allow mutations to properties. You can learn more about this in the mutable example below.
            try
            {
                parsed.Name = "George Washington";
                Debug.Assert(false);
            }
            catch (NotMutableException)
            {
            }

            try
            {
                parsed.ListVector.Clear();
                Debug.Assert(false);
            }
            catch (NotSupportedException)
            {
            }
        }
        private void RunSuccessTest <TTable, TStruct>()
            where TTable : class, IContextItem, IContextTable <TStruct>, new()
            where TStruct : class, IContextItem, new()
        {
            TTable table = new TTable();

            byte[] data = new byte[1024];

            foreach (FlatBufferDeserializationOption item in Enum.GetValues(typeof(FlatBufferDeserializationOption)))
            {
                var serializer = new FlatBufferSerializer(item);

                serializer.Serialize(table, data);
                TTable result = serializer.Parse <TTable>(data);

                Assert.IsNull(table.Context);
                Assert.AreEqual(item, result.Context.DeserializationOption);
                Assert.AreEqual(item, result.Struct.Context.DeserializationOption);
                Assert.IsFalse(object.ReferenceEquals(result.Context, result.Struct.Context));
            }
        }
        /// <summary>
        /// This example shows GreedyMutable deserialization. This is exactly the same as Greedy deserialization, but setters are generated for
        /// the objects, so vectors and properties are mutable in a predictable way.
        /// </summary>
        public static void GreedyMutableDeserialization(DemoTable demo)
        {
            var serializer = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.GreedyMutable));

            byte[] buffer = new byte[1024];
            serializer.Serialize(demo, buffer);

            long originalSum = buffer.Sum(x => (long)x);

            var parsed = serializer.Parse <DemoTable>(buffer);

            parsed.Name = "James Adams";
            parsed.ListVector.Clear();
            parsed.ListVector.Add(new InnerTable());

            long newSum = buffer.Sum(x => (long)x);

            Debug.Assert(
                newSum == originalSum,
                "Changes to the deserialized objects are not written back to the buffer. You'll need to re-serialize it to a new buffer for that.");
        }
示例#23
0
        public void StringVector_GreedyDeserialize_NotMutable()
        {
            RootTable <IList <string> > root = new RootTable <IList <string> >
            {
                Vector = new List <string> {
                    "one", "two", "three"
                }
            };

            var options = new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Greedy);
            FlatBufferSerializer serializer = new FlatBufferSerializer(options);

            byte[] buffer = new byte[100];
            serializer.Serialize(root, buffer);

            var parsed = serializer.Parse <RootTable <IList <string> > >(buffer);

            Assert.AreEqual(typeof(ReadOnlyCollection <string>), parsed.Vector.GetType());
            Assert.IsTrue(parsed.Vector.IsReadOnly);

            Assert.ThrowsException <NotSupportedException>(() => parsed.Vector.Add("four"));
        }
示例#24
0
        public void StringVector_GreedyDeserialize_Mutable()
        {
            RootTable <IList <string> > root = new RootTable <IList <string> >
            {
                Vector = new List <string> {
                    "one", "two", "three"
                }
            };

            var options = new FlatBufferSerializerOptions(FlatBufferDeserializationOption.GreedyMutable);
            FlatBufferSerializer serializer = new FlatBufferSerializer(options);

            byte[] buffer = new byte[100];
            serializer.Serialize(root, buffer);

            var parsed = serializer.Parse <RootTable <IList <string> > >(buffer);

            Assert.AreEqual(typeof(List <string>), parsed.Vector.GetType());
            Assert.IsFalse(parsed.Vector.IsReadOnly);

            // Shouldn't throw.
            parsed.Vector.Add("four");
        }
        /// <summary>
        /// The next step up in greediness is PropertyCache mode. In this mode, Flatsharp will cache the results of property accesses.
        /// So, if you read the results of FooObject.Property1 multiple times, the same value comes back each time. What this mode
        /// does not do is cache vectors. So reding FooObject.Vector[0] multiple times re-visits the buffer each time.
        /// </summary>
        public static void PropertyCacheDeserialization(DemoTable demo)
        {
            var serializer = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.PropertyCache));

            byte[] buffer = new byte[1024];
            serializer.Serialize(demo, buffer);
            var parsed = serializer.Parse <DemoTable>(buffer);

            // Properties from tables and structs are cached after they are read.
            string name  = parsed.Name;
            string name2 = parsed.Name;

            Debug.Assert(
                object.ReferenceEquals(name, name2),
                "When reading table/struct properties, PropertyCache mode returns the same instance.");

            // PropertyCache deserialization doesn't cache the results of vector lookups.
            InnerTable index0_1 = parsed.ListVector[0];
            InnerTable index0_2 = parsed.ListVector[0];

            Debug.Assert(!object.ReferenceEquals(index0_1, index0_2), "A different instance is returned each time from vectors in PropertyCache mode.");
            Debug.Assert(object.ReferenceEquals(parsed.ListVector, parsed.ListVector), "But the vector instance itself is the cached.");
            Debug.Assert(object.ReferenceEquals(index0_1.Fruit, index0_1.Fruit), "And the items returned from each vector exhibit property cache behavior");

            // Invalidate the whole buffer. Undefined behavior past here!
            Array.Fill(buffer, (byte)0);

            try
            {
                var whoKnows = parsed.ListVector[1];
                Debug.Assert(false);
            }
            catch
            {
                // This can be any sort of exception. This behavior is undefined.
            }
        }
示例#26
0
    private void FacadeTest <TUnderlyingType, TType, TConverter>(
        TUnderlyingType underlyingValue,
        TType value,
        TypeModelContainer container = null) where TConverter : struct, ITypeFacadeConverter <TUnderlyingType, TType>
    {
        if (container == null)
        {
            container = TypeModelContainer.CreateDefault();
            container.RegisterTypeFacade <TUnderlyingType, TType, TConverter>();
        }

        FlatBufferSerializer serializer = new FlatBufferSerializer(
            new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Greedy),
            container);

        byte[] destination  = new byte[1024];
        byte[] destination2 = new byte[1024];

        var compiled = serializer.Compile <ExtensionTable <TType> >();

        var underlyingItem = new ExtensionTable <TUnderlyingType> {
            Item = underlyingValue
        };
        var facadeItem = new ExtensionTable <TType> {
            Item = value
        };

        serializer.Serialize(facadeItem, destination);
        serializer.Serialize(underlyingItem, destination2);

        Assert.True(destination.AsSpan().SequenceEqual(destination2));

        var parsed = serializer.Parse <ExtensionTable <TType> >(destination);

        Assert.Equal(parsed.Item, value);
        Assert.Equal(serializer.GetMaxSize(facadeItem), serializer.GetMaxSize(underlyingItem));
    }
        /// <summary>
        /// Vector cache is a superset of PropertyCache. The difference is that when deserializing in VectorCache mode, FlatSharp
        /// will allocate a vector for you that gets lazily filled in as elements are accessed. This leads to some array allocations
        /// behind the scenes, since FlatSharp needs to know what objects have been returned for what indices.
        /// </summary>
        public static void VectorCacheDeserialization(DemoTable demo)
        {
            var serializer = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.VectorCache));

            byte[] buffer = new byte[1024];
            serializer.Serialize(demo, buffer);
            var parsed = serializer.Parse <DemoTable>(buffer);

            // Properties from tables and structs are cached after they are read.
            string name  = parsed.Name;
            string name2 = parsed.Name;

            Debug.Assert(
                object.ReferenceEquals(name, name2),
                "When reading table/struct properties, PropertyCache mode returns the same instance.");

            // VectorCache deserialization guarantees only one object per index.
            InnerTable index0_1 = parsed.ListVector[0];
            InnerTable index0_2 = parsed.ListVector[0];

            Debug.Assert(object.ReferenceEquals(index0_1, index0_2), "The same instance is returned each time from vectors in VectorCache mode.");
            Debug.Assert(object.ReferenceEquals(parsed.ListVector, parsed.ListVector), "And the vector instance itself is the same.");
            Debug.Assert(object.ReferenceEquals(index0_1.Fruit, index0_1.Fruit), "And the items returned from each vector exhibit property cache behavior");
        }
示例#28
0
        static void Main(string[] args)
        {
            Upstream up = new Upstream();

            up.Structure      = new FSeed();
            up.Structure.Data = new ConfigEntry[1];
            var e0 = new ConfigEntry();

            up.Structure.Data[0] = e0;
            e0.Tag  = "stuff";
            e0.Type = "string";
            e0.Used = true;

            Console.WriteLine("test serializing up");

            var testBuffer = new byte[1000];

            var serializer = new FlatBufferSerializer(new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Default));

            var testLength = serializer.Serialize(up, testBuffer);

            Upstream up2 = serializer.Parse <Upstream>(testBuffer);


            Console.WriteLine("Starting Main");

            // For some reason, I have to copy the args into a local array, or else they disappear
            int[] fileDescriptors = new int[2];
            for (int i = 0; i < fileDescriptors.Length && i < args.Length; i++)
            {
                int n = ParsedFd(args[i]);
                Console.WriteLine(n);
                fileDescriptors[i] = n;
            }

            // Grab the FDs from the environment variables and translate to a IntPtr
            int            fdNumIn      = fileDescriptors[0];
            SafeFileHandle inPipeHandle = new SafeFileHandle(new IntPtr(fdNumIn), true);

            int            fdNumOut      = fileDescriptors[1];
            SafeFileHandle outPipeHandle = new SafeFileHandle(new IntPtr(fdNumOut), true);

            Console.WriteLine("GO_FUZZ_IN_FD: " + fdNumIn);
            Console.WriteLine("GO_FUZZ_OUT_FD: " + fdNumOut);

            string[] commName = new string[4];
            for (int i = 2; i < args.Length; i++)
            {
                commName[i - 2] = args[i];
                Console.WriteLine(("comm" + (i - 2)) + ": " + commName[(i - 2)]);
            }

            const int MaxInputSize     = 1 << 24;
            const int ReturnResultSize = 1 << 25;
            const int CoverSize        = 64 << 10;
            const int SonarRegionSize  = 1 << 20;

            // Use the filehandles
            Stream inStream = new FileStream(inPipeHandle, FileAccess.Read);

            Console.WriteLine("created inStream");
            Stream outStream = new FileStream(outPipeHandle, FileAccess.Write);

            Console.WriteLine("created outStream");

            MemoryMappedFileSecurity security = new MemoryMappedFileSecurity();

            security.AddAccessRule(new AccessRule <MemoryMappedFileRights>(("Everyone"), MemoryMappedFileRights.FullControl, AccessControlType.Allow));

            Console.WriteLine("created security");

            MemoryMappedFile comm0 = MemoryMappedFile.OpenExisting(commName[0], MemoryMappedFileRights.ReadWrite, HandleInheritability.Inheritable);

            Console.WriteLine("created comm0");
            var comm0Accessor = comm0.CreateViewAccessor(0, MaxInputSize);

            Console.WriteLine("created comm0Accessor");

            MemoryMappedFile comm1 = MemoryMappedFile.OpenExisting(commName[1], MemoryMappedFileRights.ReadWrite, HandleInheritability.Inheritable);

            Console.WriteLine("created comm1");
            var comm1Accessor = comm1.CreateViewAccessor(0, ReturnResultSize);

            Console.WriteLine("created comm1Accessor");

            MemoryMappedFile comm2 = MemoryMappedFile.OpenExisting(commName[2], MemoryMappedFileRights.ReadWrite, HandleInheritability.Inheritable);

            Console.WriteLine("created comm2");
            var comm2Accessor = comm2.CreateViewAccessor(0, CoverSize);

            Console.WriteLine("created comm2Accessor");

            //var comm3Stream = new FileStream(commNames[3], FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
            //Console.WriteLine("created comm3Stream");
            MemoryMappedFile comm3 = MemoryMappedFile.OpenExisting(commName[3], MemoryMappedFileRights.ReadWrite, HandleInheritability.Inheritable);

            Console.WriteLine("created comm3");
            var comm3Accessor = comm3.CreateViewAccessor(0, SonarRegionSize);

            Console.WriteLine("created comm3Accessor");

            char[] inPipeBuffer       = new char[10];
            char[] outputBuffer       = new char[24];
            char[] returnLengthBuffer = new char[8];

            StreamReader inPipeReader = new StreamReader(inStream);
            StreamWriter outputWriter = new StreamWriter(outStream);

            while (true)
            {
                inPipeReader.Read(inPipeBuffer, 0, inPipeBuffer.Length);

                int fnidx = inPipeBuffer[0];
                fnidx += inPipeBuffer[1] << 8;
                Console.WriteLine("fnidx: " + fnidx);

                char[] lengthBuffer = new char[8];
                for (int i = 2; i < inPipeBuffer.Length; i++)
                {
                    lengthBuffer[i - 2] = inPipeBuffer[i];
                }
                Int64 inputLength = Deserialize64(lengthBuffer);
                Console.WriteLine("input length: " + inputLength);

                // read inputBuffer data from comm0
                var inputBuffer = new byte[inputLength];
                comm0Accessor.ReadArray(0, inputBuffer, 0, (int)inputLength);
                for (int i = 0; i < inputLength; i++)
                {
                    inputBuffer[i] = comm0Accessor.ReadByte(i);
                }

                var inputString = Encoding.UTF8.GetString(inputBuffer);

                Console.WriteLine("downstream: ");
                Console.WriteLine(inputString);

                //var downstream = Downstream.Deserialize(inputString);
                var downstream = FlatBufferSerializer.Default.Parse <Downstream>(inputBuffer);
                Console.WriteLine("downstream deserialized");

                var         seed    = downstream.Seed;
                var         entries = seed.Data;
                ConfigEntry entry   = null;
                if (entries.Count >= 1)
                {
                    entry = entries[0];
                }
                else
                {
                    Console.WriteLine("zero entries!");
                }

                var value = entry.Value;
                Console.WriteLine("got entry value: " + value);

                Int64 res = 0;
                Int64 ns;
                Int64 sonar        = 0;
                Int64 returnLength = 0;

                // Start the clock
                var nsStart = DateTime.UtcNow.Ticks;

                // Actually run the function to fuzz
                Console.WriteLine("BrokenMethod()");
                Console.WriteLine(BrokenMethod(value));

                ns = DateTime.UtcNow.Ticks - nsStart;
                Console.WriteLine("ns: " + ns);

                char[] resBuffer   = new char[8];
                char[] nsBuffer    = new char[8];
                char[] sonarBuffer = new char[8];

                Serialize56(resBuffer, res);
                Serialize56(nsBuffer, ns);
                Serialize56(sonarBuffer, sonar);

                Console.WriteLine("instantiating upstream");

                Upstream upstream = new Upstream();
                upstream.Structure      = new FSeed();
                upstream.Structure.Data = new ConfigEntry[1];
                var upEntry = upstream.Structure.Data[0];
                upEntry.Tag  = "stuff";
                upEntry.Type = "string";
                upEntry.Used = true;

                Console.WriteLine("serializing upstream");

                int maxReturnSize = FlatBufferSerializer.Default.GetMaxSize(upstream);
                var returnBuffer  = new byte[maxReturnSize];
                returnLength = FlatBufferSerializer.Default.Serialize(upstream, returnBuffer);
                Console.WriteLine("return length: " + returnLength);
                Serialize56(returnLengthBuffer, returnLength);

                for (int i = 0; i < 8; i++)
                {
                    Console.WriteLine("returnLengthBuffer: " + (byte)returnLengthBuffer[i]);
                    comm1Accessor.Write(i, returnLengthBuffer[i]);
                }

                for (int i = 0; i < returnLength; i++)
                {
                    comm1Accessor.Write(i + 8, returnBuffer[i]);
                }

                comm1Accessor.Flush();
                Console.WriteLine("wrote to comm1Accessor");

                for (int i = 0; i < 8; i++)
                {
                    outputBuffer[i]      = resBuffer[i];
                    outputBuffer[i + 8]  = nsBuffer[i];
                    outputBuffer[i + 16] = sonarBuffer[i];
                }

                outputWriter.Write(outputBuffer, 0, outputBuffer.Length);
                outputWriter.Flush();
                Console.WriteLine("wrote outputbuffer");
            }
        }
            static void Test(FlatBufferDeserializationOption option)
            {
                var table = new Table <WriteThroughStruct>
                {
                    Struct = new WriteThroughStruct
                    {
                        Value = new OtherStruct {
                            Prop1 = 10, Prop2 = 10
                        },
                        ValueStruct = new() { Value = 3, }
                    }
                };

                FlatBufferSerializer serializer = new FlatBufferSerializer(option);

                byte[] buffer = new byte[1024];
                serializer.Serialize(table, buffer);

                // parse
                var parsed1 = serializer.Parse <Table <WriteThroughStruct> >(buffer);

                // mutate
                Assert.Equal(10, parsed1.Struct.Value.Prop1);
                Assert.Equal(10, parsed1.Struct.Value.Prop2);
                Assert.Equal(3, parsed1.Struct.ValueStruct.Value);
                parsed1.Struct.Value = new OtherStruct {
                    Prop1 = 300, Prop2 = 300
                };
                parsed1.Struct.ValueStruct = new() { Value = -1 };
                Assert.Equal(300, parsed1.Struct.Value.Prop1);
                Assert.Equal(300, parsed1.Struct.Value.Prop2);
                Assert.Equal(-1, parsed1.Struct.ValueStruct.Value);

                // verify, set to null
                var parsed2 = serializer.Parse <Table <WriteThroughStruct> >(buffer);

                Assert.Equal(300, parsed2.Struct.Value.Prop1);
                Assert.Equal(300, parsed2.Struct.Value.Prop2);
                Assert.Equal(-1, parsed2.Struct.ValueStruct.Value);
                parsed2.Struct.Value = null !;

                if (option == FlatBufferDeserializationOption.Progressive)
                {
                    // we are null temporarily until we re-parse.
                    Assert.Null(parsed2.Struct.Value);
                }
                else if (option == FlatBufferDeserializationOption.Lazy)
                {
                    // lazy write through clears it out.
                    Assert.Equal(0, parsed2.Struct.Value.Prop1);
                    Assert.Equal(0, parsed2.Struct.Value.Prop2);
                }
                else
                {
                    Assert.False(true);
                }

                // verify, set to null
                var parsed3 = serializer.Parse <Table <WriteThroughStruct> >(buffer);

                Assert.Equal(0, parsed3.Struct.Value.Prop1);
                Assert.Equal(0, parsed3.Struct.Value.Prop2);
            }

            Test(FlatBufferDeserializationOption.Progressive);
            Test(FlatBufferDeserializationOption.Lazy);
        }
        public static void Run()
        {
            FooBarContainer container = new FooBarContainer
            {
                fruit       = Fruit.Pears,
                initialized = true,
                location    = "location",
                list        = new List <FooBar>
                {
                    new FooBar
                    {
                        name    = "name",
                        postfix = 1,
                        rating  = 3,
                        sibling = new Bar
                        {
                            ratio = 3.14f,
                            size  = ushort.MaxValue,
                            time  = int.MinValue,

                            // Nested structs are not intended to have null values,
                            // but it is possible due to FlatSharp modeling
                            // them as reference types. However, null structs
                            // do not cause a problem when serializing or parsing.
                            parent = null !,
                        }
                    }
                },
            };

            // Simple use case: make a deep copy of an object you're using.
            var copy = new FooBarContainer(container);

            Debug.Assert(!object.ReferenceEquals(copy.list, container.list), "A new list is created");
            for (int i = 0; i < container.list.Count; ++i)
            {
                var originalItem = container.list[i];

                Debug.Assert(copy.list is not null);
                var copyItem = copy.list[i];
                Debug.Assert(!object.ReferenceEquals(copyItem, originalItem));
            }

            // Now let's look at how this can be useful when operating on deserialized objects.
            var serializer = new FlatBufferSerializer(FlatBufferDeserializationOption.Lazy);

            byte[] data = new byte[1024];
            serializer.Serialize(container, data);
            var deserialized = serializer.Parse <FooBarContainer>(data);

            // Take a deserialized item and "upcast" it back to the original type.
            // This performs a full traversal of the object and allows the underlying buffer to be reused.
            Debug.Assert(deserialized.GetType() != container.GetType(), "The deserialized type is a subclass of the FooBarContainer type");
            copy = new FooBarContainer(deserialized);
            Debug.Assert(copy.GetType() == container.GetType(), "By using the copy constructor, we can get an instance of the original type.");

            // Next: Some deserialization modes, such as Lazy, don't permit mutation of the object.
            // Using the copy constructor can convert this to an object that we can mutate!
            try
            {
                // will throw
                deserialized.fruit = Fruit.Apples;
                Debug.Assert(false);
            }
            catch
            {
            }

            // Modifying the copy is just fine, though.
            copy.fruit = Fruit.Apples;
        }