Exemplo n.º 1
0
        /// <summary>
        /// Generates a special property getter for union types. This stems from
        /// the fact that unions occupy two spots in the table's vtable to deserialize one
        /// logical field. This means that the logic to read them must also be special.
        /// </summary>
        private GeneratedProperty CreateUnionTableGetter(TableMemberModel memberModel, int index)
        {
            Type           propertyType = memberModel.ItemTypeModel.ClrType;
            string         defaultValue = CSharpHelpers.GetDefaultValueToken(memberModel);
            UnionTypeModel unionModel   = (UnionTypeModel)memberModel.ItemTypeModel;

            GeneratedProperty generatedProperty = new GeneratedProperty(this.options, index, memberModel.PropertyInfo);

            // Start by generating switch cases. The codegen'ed union types have
            // well-defined constructors for each constituent type, so this .ctor
            // will always be available.
            List <string> switchCases = new List <string>();

            for (int i = 0; i < unionModel.UnionElementTypeModel.Length; ++i)
            {
                var    unionMember            = unionModel.UnionElementTypeModel[i];
                int    unionIndex             = i + 1;
                string structOffsetAdjustment = string.Empty;
                if (unionMember.SchemaType == FlatBufferSchemaType.Struct)
                {
                    structOffsetAdjustment = $"offsetLocation += buffer.{nameof(InputBuffer.ReadUOffset)}(offsetLocation);";
                }

                string @case =
                    $@"
                    case {unionIndex}:
                        {structOffsetAdjustment}
                        return new {CSharpHelpers.GetCompilableTypeName(unionModel.ClrType)}({this.GetReadInvocation(unionMember.ClrType, "buffer", "offsetLocation")});
";
                switchCases.Add(@case);
            }


            generatedProperty.ReadValueMethodDefinition =
                $@"
                    [MethodImpl(MethodImplOptions.AggressiveInlining)]
                    private static {CSharpHelpers.GetCompilableTypeName(propertyType)} {generatedProperty.ReadValueMethodName}(InputBuffer buffer, int offset)
                    {{
                        int discriminatorLocation = buffer.{nameof(InputBuffer.GetAbsoluteTableFieldLocation)}(offset, {index});
                        int offsetLocation = buffer.{nameof(InputBuffer.GetAbsoluteTableFieldLocation)}(offset, {index + 1});
                            
                        if (discriminatorLocation == 0) {{
                            return {defaultValue};
                        }}
                        else {{
                            byte discriminator = buffer.{nameof(InputBuffer.ReadByte)}(discriminatorLocation);
                            if (discriminator == 0 && offsetLocation != 0)
                                throw new System.IO.InvalidDataException(""FlatBuffer union had discriminator set but no offset."");
                            switch (discriminator)
                            {{
                                {string.Join("\r\n", switchCases)}
                                default:
                                    return {defaultValue};
                            }}
                        }}
                    }}
";
            return(generatedProperty);
        }
Exemplo n.º 2
0
        private void ImplementStructReadMethod(StructTypeModel typeModel)
        {
            // We have to implement two items: The table class and the overall "read" method.
            // Let's start with the read method.
            string className = "structReader_" + Guid.NewGuid().ToString("n");

            // Static factory method.
            this.GenerateMethodDefinition(typeModel.ClrType, $"return new {className}(memory, offset);");

            // Implement the class
            {
                // Build up a list of property overrides.
                var propertyOverrides = new List <GeneratedProperty>();
                for (int index = 0; index < typeModel.Members.Count; ++index)
                {
                    var          value              = typeModel.Members[index];
                    PropertyInfo propertyInfo       = value.PropertyInfo;
                    Type         propertyType       = propertyInfo.PropertyType;
                    string       compilableTypeName = CSharpHelpers.GetCompilableTypeName(propertyType);

                    GeneratedProperty generatedProperty = new GeneratedProperty(this.options, index, propertyInfo);
                    generatedProperty.ReadValueMethodDefinition =
                        $@"
                    [MethodImpl(MethodImplOptions.AggressiveInlining)]
                    private static {CSharpHelpers.GetCompilableTypeName(propertyType)} {generatedProperty.ReadValueMethodName}(InputBuffer buffer, int offset)
                    {{
                        return {this.GetReadInvocation(propertyType, "buffer", $"offset + {value.Offset}")};
                    }}
";

                    propertyOverrides.Add(generatedProperty);
                }

                string classDefinition = this.CreateClass(
                    className,
                    typeModel.ClrType,
                    typeModel.Members.Select(x => x.PropertyInfo.Name),
                    propertyOverrides);
                var node = CSharpSyntaxTree.ParseText(classDefinition, ParseOptions);
                this.methodDeclarations.Add(node.GetRoot());
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Generates a standard getter for a normal vtable entry.
        /// </summary>
        private GeneratedProperty CreateStandardTableProperty(TableMemberModel memberModel, int index)
        {
            Type              propertyType = memberModel.ItemTypeModel.ClrType;
            string            defaultValue = CSharpHelpers.GetDefaultValueToken(memberModel);
            GeneratedProperty property     = new GeneratedProperty(this.options, index, memberModel.PropertyInfo);

            property.ReadValueMethodDefinition =
                $@"
                    [MethodImpl(MethodImplOptions.AggressiveInlining)]
                    private static {CSharpHelpers.GetCompilableTypeName(propertyType)} {property.ReadValueMethodName}(InputBuffer buffer, int offset)
                    {{
                        int absoluteLocation = buffer.{nameof(InputBuffer.GetAbsoluteTableFieldLocation)}(offset, {index});
                        if (absoluteLocation == 0) {{
                            return {defaultValue};
                        }}
                        else {{
                            return {this.GetReadInvocation(propertyType, "buffer", "absoluteLocation")};
                        }}
                    }}
";

            return(property);
        }