Пример #1
0
        private void ImplementMemoryVectorReadMethod(VectorTypeModel typeModel)
        {
            string invocation;

            if (typeModel.ItemTypeModel.ClrType == typeof(byte))
            {
                invocation = nameof(InputBuffer.ReadByteMemoryBlock);
                if (typeModel.IsReadOnly)
                {
                    invocation = nameof(InputBuffer.ReadByteReadOnlyMemoryBlock);
                }
            }
            else
            {
                string methodName = nameof(InputBuffer.ReadMemoryBlock);
                if (typeModel.IsReadOnly)
                {
                    methodName = nameof(InputBuffer.ReadReadOnlyMemoryBlock);
                }

                invocation = $"{methodName}<{CSharpHelpers.GetCompilableTypeName(typeModel.ItemTypeModel.ClrType)}>";
            }

            string body = $"memory.{invocation}(offset, {typeModel.ItemTypeModel.InlineSize})";

            // Greedy deserialize has the invariant that we no longer touch the
            // original buffer. This means a memory copy here.
            if (this.options.GreedyDeserialize)
            {
                body = $"{body}.ToArray().AsMemory()";
            }

            this.GenerateMethodDefinition(typeModel.ClrType, $"return {body};");
        }
Пример #2
0
        private void ImplementArrayVectorReadMethod(VectorTypeModel typeModel)
        {
            var itemTypeModel = typeModel.ItemTypeModel;

            string statement;

            if (itemTypeModel is ScalarTypeModel scalarModel && scalarModel.NativelyReadableFromMemory)
            {
                // Memory is faster in situations where we can get away with it.
                statement = $"memory.{nameof(InputBuffer.ReadMemoryBlock)}<{CSharpHelpers.GetCompilableTypeName(itemTypeModel.ClrType)}>(offset, {itemTypeModel.InlineSize}).ToArray()";
            }
        private void ImplementMemoryVectorInlineWriteMethod(VectorTypeModel vectorModel)
        {
            var type          = vectorModel.ClrType;
            var itemTypeModel = vectorModel.ItemTypeModel;

            string writerMethodName = $"{nameof(SpanWriter.WriteReadOnlyMemoryBlock)}<{CSharpHelpers.GetCompilableTypeName(itemTypeModel.ClrType)}>";

            if (itemTypeModel.ClrType == typeof(byte))
            {
                // Optimization: when we're writing bytes we don't have to change types.
                writerMethodName = nameof(SpanWriter.WriteReadOnlyByteMemoryBlock);
            }

            string body = $"writer.{writerMethodName}(span, item, originalOffset, {itemTypeModel.Alignment}, {itemTypeModel.InlineSize}, context);";

            this.GenerateSerializeMethod(type, body);
        }
Пример #4
0
        private void ImplementListVectorReadMethod(VectorTypeModel typeModel)
        {
            string body = this.CreateFlatBufferVector(typeModel);

            if (this.options.PreallocateVectors)
            {
                // We just call .ToList(). Noe that when full greedy mode is on, these items will be
                // greedily initialized as we traverse the list. Otherwise, they'll be allocated lazily.
                body += $".{nameof(SerializationHelpers.FlatBufferVectorToList)}()";

                if (!this.options.GenerateMutableObjects)
                {
                    // Finally, if we're not in the business of making mutable objects, then convert the list to read only.
                    body += ".AsReadOnly()";
                }
            }

            this.GenerateMethodDefinition(typeModel.ClrType, $"return {body};");
        }
        private void ImplementListVectorInlineWriteMethod(VectorTypeModel vectorModel)
        {
            var    type          = vectorModel.ClrType;
            var    itemTypeModel = vectorModel.ItemTypeModel;
            string propertyName  = vectorModel.LengthPropertyName;

            string body = $@"
                int count = item.{propertyName};
                int vectorOffset = context.{nameof(SerializationContext.AllocateVector)}({itemTypeModel.Alignment}, count, {vectorModel.PaddedMemberInlineSize});
                writer.{nameof(SpanWriter.WriteUOffset)}(span, originalOffset, vectorOffset, context);
                writer.{nameof(SpanWriter.WriteInt)}(span, count, vectorOffset, context);
                vectorOffset += sizeof(int);
                for (int i = 0; i < count; ++i)
                {{
                      var current = item[i];
                      {CSharpHelpers.GetNonNullCheckInvocation(itemTypeModel, "current")};
                      {this.GetSerializeInvocation(itemTypeModel.ClrType, "current", "vectorOffset")}
                      vectorOffset += {vectorModel.PaddedMemberInlineSize};
                }}";

            this.GenerateSerializeMethod(type, body);
        }
Пример #6
0
        /// <summary>
        /// Gets the max size of the vector itself, not the uoffset_t as part of the containing table.
        /// </summary>
        private void ImplementVectorGetMaxSizeMethod(VectorTypeModel vectorModel)
        {
            var    itemModel = vectorModel.ItemTypeModel;
            string body;

            // count of items + padding(uoffset_t);
            int    fixedSize      = sizeof(uint) + SerializationHelpers.GetMaxPadding(sizeof(uint));
            string lengthProperty = $"item.{vectorModel.LengthPropertyName}";

            // Constant size items. We can reduce these reasonably well.
            if (itemModel.IsFixedSize)
            {
                body = $"return {fixedSize} + {SerializationHelpers.GetMaxPadding(itemModel.Alignment)} + ({vectorModel.PaddedMemberInlineSize} * {lengthProperty});";
            }
            else if (itemModel.SchemaType == FlatBufferSchemaType.Table || itemModel.SchemaType == FlatBufferSchemaType.String)
            {
                Debug.Assert(itemModel.Alignment == sizeof(uint));
                Debug.Assert(itemModel.InlineSize == sizeof(uint));

                body =
                    $@"
                    int length = {lengthProperty};
                    int runningSum = {fixedSize} + {SerializationHelpers.GetMaxPadding(itemModel.Alignment)} + ({vectorModel.PaddedMemberInlineSize} * length);
                    for (int i = 0; i < length; ++i)
                    {{
                        var itemTemp = item[i];
                        {CSharpHelpers.GetNonNullCheckInvocation(itemModel, "itemTemp")};
                        runningSum += {this.InvokeGetMaxSizeMethod(itemModel, "itemTemp")};
                    }}
                    return runningSum;";
            }
            else
            {
                throw new NotImplementedException("Vector.GetMaxSize is not implemented for schema type of " + itemModel.SchemaType);
            }

            this.GenerateGetMaxSizeMethod(vectorModel.ClrType, body);
        }
        private (string prepareBlock, string serializeBlock) GetStandardSerializeBlocks(int index, TableMemberModel memberModel)
        {
            string valueVariableName  = $"index{index}Value";
            string offsetVariableName = $"index{index}Offset";

            string condition = $"if ({valueVariableName} != {CSharpHelpers.GetDefaultValueToken(memberModel)})";

            if ((memberModel.ItemTypeModel is VectorTypeModel vector && vector.IsMemoryVector) || memberModel.IsKey)
            {
                // 1) Memory is a struct and can't be null, and 0-length vectors are valid.
                //    Therefore, we just need to omit the conditional check entirely.

                // 2) For sorted vector keys, we must include the value since some other
                //    libraries cannot do binary search with omitted keys.
                condition = string.Empty;
            }

            string keyCheckMethodCall = string.Empty;

            if (memberModel.IsKey)
            {
                keyCheckMethodCall = $"{nameof(SortedVectorHelpers)}.{nameof(SortedVectorHelpers.EnsureKeyNonNull)}({valueVariableName});";
            }

            string prepareBlock =
                $@"
                    var {valueVariableName} = item.{memberModel.PropertyInfo.Name};
                    int {offsetVariableName} = 0;
                    {keyCheckMethodCall}
                    {condition} 
                    {{
                            currentOffset += {CSharpHelpers.GetFullMethodName(ReflectedMethods.SerializationHelpers_GetAlignmentErrorMethod)}(currentOffset, {memberModel.ItemTypeModel.Alignment});
                            {offsetVariableName} = currentOffset;
                            vtable.{nameof(VTableBuilder.SetOffset)}({index}, currentOffset - tableStart);
                            currentOffset += {memberModel.ItemTypeModel.InlineSize};
                    }}";

            string sortInvocation = string.Empty;

            if (memberModel.IsSortedVector)
            {
                VectorTypeModel  vectorModel = (VectorTypeModel)memberModel.ItemTypeModel;
                TableTypeModel   tableModel  = (TableTypeModel)vectorModel.ItemTypeModel;
                TableMemberModel keyMember   = tableModel.IndexToMemberMap.Single(x => x.Value.PropertyInfo == tableModel.KeyProperty).Value;

                var    builtInType = BuiltInType.BuiltInTypes[keyMember.ItemTypeModel.ClrType];
                string inlineSize  = builtInType.TypeModel.SchemaType == FlatBufferSchemaType.Scalar ? builtInType.TypeModel.InlineSize.ToString() : "null";

                sortInvocation = $"{nameof(SortedVectorHelpers)}.{nameof(SortedVectorHelpers.SortVector)}(" +
                                 $"span, {offsetVariableName}, {keyMember.Index}, {inlineSize}, {CSharpHelpers.GetCompilableTypeName(builtInType.SpanComparerType)}.Instance);";
            }

            string serializeBlock =
                $@"
                    if ({offsetVariableName} != 0)
                    {{
                        {this.GetSerializeInvocation(memberModel.ItemTypeModel.ClrType, valueVariableName, offsetVariableName)}
                        {sortInvocation}
                    }}";

            return(prepareBlock, serializeBlock);
        }