Beispiel #1
0
        /// <inheritdoc />
        public override void VisitField(CppField cppField)
        {
            string fieldName   = cppField.FieldInfo.Name;
            string fieldOffset = $"{cppField.CppStructOffset}";

            Type fieldType = cppField.FieldInfo.FieldType;

            if (cppField.FieldInfo.IsFixedSizedArray())
            {
                // When field is array, get element type to use correct proxy type.
                //
                fieldType = fieldType.GetElementType();
            }

            // Get the proxy type name.
            //
            string cppProxyTypeFullName = CppTypeMapper.GetCppProxyFullTypeName(fieldType);

            // Write the property, for arrays, use PropertyArrayProxy.
            //
            if (cppField.FieldInfo.IsFixedSizedArray())
            {
                // Get the fixed array length and write the property.
                //
                FixedSizeArrayAttribute arrayAttribute = cppField.FieldInfo.GetCustomAttribute <FixedSizeArrayAttribute>();
                WriteLine($"::Mlos::Core::PropertyArrayProxy<{cppProxyTypeFullName}, {arrayAttribute.Length}> {fieldName}() {{ return ::Mlos::Core::PropertyArrayProxy<{cppProxyTypeFullName}, {arrayAttribute.Length}>(buffer, {fieldOffset}); }}");
            }
            else
            {
                WriteLine($"{cppProxyTypeFullName} {fieldName}() {{ return {cppProxyTypeFullName}(buffer, {fieldOffset}); }}");
            }

            WriteLine();
        }
Beispiel #2
0
        /// <inheritdoc />
        public override void BeginVisitType(Type sourceType)
        {
            Type enumUnderlyingType = sourceType.GetEnumUnderlyingType();

            string enumCppUnderlyingType = CppTypeMapper.GetCppFullTypeName(enumUnderlyingType);

            string cppClassName = sourceType.Name;

            WriteLine($"enum class {cppClassName} : {enumCppUnderlyingType}");
            WriteLine("{");

            IndentationLevel++;

            foreach (FieldInfo fieldInfo in sourceType.GetFields())
            {
                if (!fieldInfo.FieldType.IsEnum)
                {
                    // Skip invalid entries.
                    //
                    continue;
                }

                WriteLine($"{fieldInfo.Name} = {fieldInfo.GetRawConstantValue()},");
            }
        }
Beispiel #3
0
        /// <inheritdoc />
        public override void VisitField(CppField cppField)
        {
            AlignAttribute alignmentAttribute = cppField.FieldInfo.GetCustomAttribute <AlignAttribute>();
            string         fieldCodeString    = alignmentAttribute == null
                ? string.Empty
                : $"alignas({alignmentAttribute.Size}) ";

            if (cppField.FieldInfo.IsFixedSizedArray())
            {
                // Field is a fixed size array.
                //
                string cppElementTypeFullName = CppTypeMapper.GetCppFullTypeName(cppField.FieldInfo.FieldType.GetElementType());

                FixedSizeArrayAttribute arrayAttribute = cppField.FieldInfo.GetCustomAttribute <FixedSizeArrayAttribute>();

                fieldCodeString += $"std::array<{cppElementTypeFullName}, {arrayAttribute.Length}> {cppField.FieldInfo.Name} = {{ }};";
            }
            else
            {
                string cppTypeFullName = CppTypeMapper.GetCppFullTypeName(cppField.FieldInfo.FieldType);
                fieldCodeString += $"{cppTypeFullName} {cppField.FieldInfo.Name};";
            }

            WriteLine(fieldCodeString);
            WriteLine();
        }
        /// <summary>
        /// Write a specialization of the serialization function for the provided type.
        /// </summary>
        /// <param name="sourceType"></param>
        public override void BeginVisitType(Type sourceType)
        {
            string cppElementTypeFullName = CppTypeMapper.GenerateCppFullTypeName(sourceType);

            WriteBlock(@$ "
                template<>
                inline size_t SerializeVariableData<{cppElementTypeFullName}>(Mlos::Core::BytePtr buffer, uint64_t objectOffset, uint64_t dataOffset, const {cppElementTypeFullName}& object)
Beispiel #5
0
        /// <inheritdoc/>
        public override void EndVisitType(Type sourceType)
        {
            CppType cppType = CppTypeMapper.GetCppType(sourceType);

            uint  typeIndex     = TypeMetadataMapper.GetTypeIndex(sourceType);
            ulong typeHashValue = TypeMetadataMapper.GetTypeHashValue(sourceType);

            WriteLine();

            WriteLine("return hashValue;");
            IndentationLevel--;
            WriteLine("}");
            WriteLine();

            string dispatchTableBaseIndexVariable =
                "global::" +
                (string.IsNullOrEmpty(DispatchTableCSharpNamespace) ? string.Empty : $"{DispatchTableCSharpNamespace}.")
                + "ObjectDeserializeHandler.DispatchTableBaseIndex";

            WriteBlock($@"
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                uint global::Mlos.Core.ICodegenKey.CodegenTypeIndex() => {typeIndex} + {dispatchTableBaseIndexVariable};");

            WriteBlock($@"
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                ulong global::Mlos.Core.ICodegenKey.CodegenTypeHash() => 0x{typeHashValue:x};");

            WriteBlock($@"
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                ulong global::Mlos.Core.ICodegenType.CodegenTypeSize() => {cppType.TypeSize};");

            WriteCloseTypeDeclaration(sourceType);
        }
Beispiel #6
0
        /// <inheritdoc />
        public override void VisitConstField(CppConstField cppConstField)
        {
            string cppTypeFullName    = CppTypeMapper.GetCppFullTypeName(cppConstField.FieldInfo.FieldType);
            string constValueAsString = cppConstField.ConstValue.ToString();

            WriteLine($"static const {cppTypeFullName} {cppConstField.FieldInfo.Name} = {constValueAsString};");
            WriteLine();
        }
Beispiel #7
0
        /// <inheritdoc />
        public override bool Accept(Type sourceType)
        {
            // Fixed size structures do not have variable data fields.
            // No custom serialization code is required.
            //
            CppType cppType = CppTypeMapper.GetCppType(sourceType);

            return(cppType.HasVariableData);
        }
Beispiel #8
0
        /// <summary>
        /// For each serializable structure, create an entry with deserialization handler in the dispatch callback table.
        /// </summary>
        /// <param name="sourceType"></param>
        public override void BeginVisitType(Type sourceType)
        {
            string cppTypeFullName      = CppTypeMapper.GetCppFullTypeName(sourceType);
            string cppProxyTypeFullName = CppTypeMapper.GetCppProxyFullTypeName(sourceType);

            WriteBlock(@$ "
                ::Mlos::Core::DispatchEntry
                {{
                    {Constants.TypeMetadataInfoNamespace}::CodegenTypeHash<{cppTypeFullName}>(),
        /// <inheritdoc />
        public override bool Accept(Type sourceType)
        {
            // Fixed length structure with no variable length fields.
            // No custom serialization is required.
            //
            CppType cppType = CppTypeMapper.GetCppType(sourceType);

            return(cppType.HasVariableData);
        }
Beispiel #10
0
        /// <inheritdoc />
        public override void VisitField(CppField cppField)
        {
            string cppDeclaringTypeFullName = CppTypeMapper.GetCppFullTypeName(cppField.FieldInfo.DeclaringType);
            string fieldName             = cppField.FieldInfo.Name;
            string actualOffsetText      = $@"offsetof(struct {cppDeclaringTypeFullName}, {fieldName})";
            string assertionErrorMessage = $@"""Invalid offset""";

            WriteLine($@"static_assert({actualOffsetText} == {cppField.CppStructOffset}, {assertionErrorMessage});");
        }
Beispiel #11
0
        /// <summary>
        /// Write a specialization of the template function to calculate the length of the variable fields for the provided type.
        /// </summary>
        /// <param name="sourceType"></param>
        public override void BeginVisitType(Type sourceType)
        {
            string cppElementTypeFullName = CppTypeMapper.GetCppProxyFullTypeName(sourceType);

            WriteBlock($@"
                template<>
                inline bool VerifyVariableData<{cppElementTypeFullName}>({cppElementTypeFullName} object, uint64_t objectOffset, uint64_t totalDataSize, uint64_t& expectedDataOffset)
                {{
                    bool isValid = true;");

            IndentationLevel++;
        }
        /// <inheritdoc />
        public override void BeginVisitType(Type sourceType)
        {
            string cppTypeFullName = CppTypeMapper.GenerateCppFullTypeName(sourceType);

            WriteBlock($@"
                inline bool operator==(const {cppTypeFullName}& a, const {cppTypeFullName}& b)
                {{
                    (void)a;
                    (void)b;
                    bool result = true;");
            IndentationLevel++;
        }
        /// <summary>
        /// For a new structure, create a entry in metadata table.
        /// </summary>
        /// <param name="sourceType"></param>
        public override void BeginVisitType(Type sourceType)
        {
            // Receiver is using proxy struct.
            //
            string cppProxyTypeFullName = CppTypeMapper.GetCppProxyFullTypeName(sourceType);

            // Use type name, as we are already in type namespace.
            //
            string cppTypeNameAsField = $"{sourceType.Name}_Callback";

            WriteLine($"__declspec(selectany) std::function<void ({cppProxyTypeFullName}&&)> {cppTypeNameAsField} = nullptr;");
            WriteLine();
        }
Beispiel #14
0
        public override void EndVisitType(Type sourceType)
        {
            CppType cppType = CppTypeMapper.GetCppType(sourceType);

            if (cppType.PaddingSize != 0)
            {
                // Include padding to match defined structure size.
                //
                WriteLine($"byte __finalPadding[{cppType.PaddingSize}];");
            }

            base.EndVisitType(sourceType);
        }
        /// <inheritdoc />
        public override void BeginVisitType(Type sourceType)
        {
            string cppTypeFullName = CppTypeMapper.GenerateCppFullTypeName(sourceType);

            WriteBlock($@"
                template <typename THash>
                inline uint32_t GetKeyHashValue(const {cppTypeFullName}& v)
                {{
                    (void)v;
                    uint32_t hashValue = THash::GetHashValue(::TypeMetadataInfo::CodegenTypeHash<{cppTypeFullName}>());");

            IndentationLevel++;
        }
Beispiel #16
0
        /// <summary>
        /// Write a specialization of the template function to calculate the length of the variable fields for the provided type.
        /// </summary>
        /// <param name="sourceType"></param>
        public override void BeginVisitType(Type sourceType)
        {
            string cppElementTypeFullName = CppTypeMapper.GenerateCppFullTypeName(sourceType);

            WriteBlock($@"
                template<>
                inline size_t GetVariableDataSize<{cppElementTypeFullName}>(const {cppElementTypeFullName}& object)
                {{
                    // Define a local variable to calculate total data size for all the variable length fields.
                    //
                    size_t dataSize = 0;");

            IndentationLevel++;
        }
Beispiel #17
0
        /// <summary>
        /// For a new structure, create a entry in matadata table.
        /// </summary>
        /// <param name="sourceType"></param>
        public override void EndVisitType(Type sourceType)
        {
            // Type CppType is beeing generated and it is not yet available.
            // Create a full name from CSharp type.
            //
            string cppTypeFullName = CppTypeMapper.GenerateCppFullTypeName(sourceType);

            uint typeIndex = TypeMetadataMapper.GetTypeIndex(sourceType);

            // Write a link to next metadata object.
            //
            WriteBlock(@$ "
                template<>
                constexpr uint32_t CodegenTypeIndex<{cppTypeFullName}>() {{ return {DispatchTableCppNamespace}::DispatchTableBaseIndex() + {typeIndex}; }}");
Beispiel #18
0
        /// <summary>
        /// Write a specialization of the template function to calculate the length of the variable fields for the provided type.
        /// </summary>
        /// <param name="sourceType"></param>
        public override void BeginVisitType(Type sourceType)
        {
            // If serialization is sized size, do nothing.
            //
            string cppElementTypeFullName = CppTypeMapper.GenerateCppFullTypeName(sourceType);

            WriteBlock($@"
                template<>
                inline size_t GetVariableDataSize<{cppElementTypeFullName}>(const {cppElementTypeFullName}& object)
                {{
                    // Define local variable used to calculate total length of variable length fields.
                    //
                    size_t length = 0;");

            IndentationLevel++;
        }
Beispiel #19
0
        /// <inheritdoc/>
        public override void EndVisitType(Type sourceType)
        {
            // Get the cppType.
            //
            CppType cppType = CppTypeMapper.GetCppType(sourceType);

            uint  typeIndex     = TypeMetadataMapper.GetTypeIndex(sourceType);
            ulong typeHashValue = TypeMetadataMapper.GetTypeHashValue(sourceType);

            WriteBlock($@"
                /// <inheritdoc/>
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                uint global::Mlos.Core.ICodegenKey.CodegenTypeIndex()
                {{
                    return {typeIndex} + {DispatchTableBaseIndexVariableName};
                }}");

            WriteBlock($@"
                /// <inheritdoc/>
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                ulong global::Mlos.Core.ICodegenKey.CodegenTypeHash() => 0x{typeHashValue:x};");

            WriteBlock($@"
                /// <inheritdoc/>
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                public ulong CodegenTypeSize() => {cppType.TypeSize};");

            WriteBlock($@"
                /// <inheritdoc/>
                [System.Text.Json.Serialization.JsonIgnore]
                public IntPtr Buffer
                {{
                    get
                    {{
                        return buffer;
                    }}
                    set
                    {{
                        buffer = value;
                    }}
                }}");

            WriteBlock($@"
                private IntPtr buffer;");

            WriteCloseTypeDeclaration(sourceType);
        }
Beispiel #20
0
        /// <inheritdoc />
        public override void BeginVisitType(Type sourceType)
        {
            string cppClassName         = sourceType.Name;
            string cppProxyTypeFullName = CppTypeMapper.GetCppProxyFullTypeName(sourceType);

            AlignAttribute alignmentAttribute      = sourceType.GetCustomAttribute <AlignAttribute>();
            string         structAlignAsCodeString = alignmentAttribute == null
                ? string.Empty
                : $"alignas({alignmentAttribute.Size})";

            WriteBlock($@"
                    struct {structAlignAsCodeString} {cppClassName}
                    {{
                        typedef {cppProxyTypeFullName} ProxyObjectType;");

            IndentationLevel++;
        }
Beispiel #21
0
        /// <inheritdoc />
        public override void BeginVisitType(Type sourceType)
        {
            WriteOpenTypeDeclaration(sourceType);

            CppType cppType = CppTypeMapper.GetCppType(sourceType);

            WriteBlock($@"
                    ulong global::Mlos.Core.ICodegenType.SerializeVariableData(IntPtr buffer, ulong objectOffset, ulong dataOffset)
                    {{
                        ulong totalDataSize = 0;");

            IndentationLevel++;

            if (cppType.HasVariableData)
            {
                WriteLine("ulong dataSize = 0;");
            }

            WriteLine();
        }
Beispiel #22
0
        /// <inheritdoc />
        public override void BeginVisitType(Type sourceType)
        {
            string cppClassName           = sourceType.Name;
            string cppElementTypeFullName = CppTypeMapper.GenerateCppFullTypeName(sourceType);

            WriteBlock($@"
                struct {cppClassName} : public ::Mlos::Core::PropertyProxy<{cppClassName}>
                {{
                    // Define a type to an object that we are create proxy from.
                    //
                    typedef {cppElementTypeFullName} RealObjectType;

                    // Constructor.
                    //
                    {cppClassName}(::Mlos::Core::BytePtr buffer, uint32_t offset = 0)
                     :  ::Mlos::Core::PropertyProxy<{cppClassName}>(buffer, offset)
                    {{}}");
            WriteLine();

            IndentationLevel++;
        }
        /// <summary>
        /// For a new structure, create a entry in matadata table.
        /// </summary>
        /// <param name="sourceType"></param>
        public override void BeginVisitType(Type sourceType)
        {
            string cppClassName = CppTypeMapper.GenerateFieldNameFromCppFullTypeName(sourceType);

            // Align name
            //
            int nameLength = (((cppClassName.Length + 1) + 7) / 8) * 8;

            // Write a link to next metadata object.
            //
            WriteLine($"uint32_t NextOffset_{cppClassName} = {metadataOffset + nameLength + sizeof(uint)};");

            // Write a class name using std::array.
            // std::array<5, char> = { 'C', 'l', 'a', 's', 's', '\0' };
            //
            WriteLine($"std::array<char, {nameLength}> TypeName_{cppClassName} {{{{ {string.Join(",", cppClassName.Select(r => $"'{r}'"))}, '\\0' }}}};");

            metadataOffset += nameLength + sizeof(uint);

            ++ClassCount;
        }
Beispiel #24
0
        /// <inheritdoc />
        public override void VisitField(CppField cppField)
        {
            string fieldName   = cppField.FieldInfo.Name;
            string fieldOffset = $"{cppField.CppStructOffset}";

            Type fieldType = cppField.FieldInfo.FieldType;

            if (cppField.FieldInfo.IsFixedSizedArray())
            {
                // When field is array, get element type to use correct proxy type.
                //
                fieldType = fieldType.GetElementType();
            }

            // Get the proxy type name.
            //
            CppType cppType = CppTypeMapper.GetCppType(fieldType);

            // Get the proxy type name.
            //
            string fieldTypeName = $"global::{fieldType.FullName}";

            // Write the property, for arrays, use PropertyArrayProxy.
            //
            if (cppField.FieldInfo.IsFixedSizedArray() ||
                cppField.CppType.IsCodegenType)
            {
                string csharpProxyTypeFullName = cppType.IsCodegenType ? $"global::Proxy.{fieldType.FullName}" : $"global::{fieldType.FullName}";

                if (cppField.FieldInfo.IsFixedSizedArray())
                {
                    string csharpArrayProxyTypeName = cppType.IsCodegenType ? "global::Mlos.Core.PropertyProxyArray" : "global::Mlos.Core.ProxyArray";

                    // Declare the property.
                    //
                    WriteLine($@"public {csharpArrayProxyTypeName}<{csharpProxyTypeFullName}> {fieldName} => new {csharpArrayProxyTypeName}<{csharpProxyTypeFullName}>(buffer + {fieldOffset}, {cppType.TypeSize});");
                }
                else
                {
                    WriteLine($@"public {csharpProxyTypeFullName} {fieldName} => new {csharpProxyTypeFullName}() {{ Buffer = buffer + {fieldOffset} }};");
                }
            }
            else
            {
                WriteBlock($@"
                    public {fieldTypeName} {fieldName}
                    {{
                        get
                        {{
                            unsafe
                            {{
                                return *({fieldTypeName}*)(buffer + {fieldOffset}).ToPointer();
                            }}
                        }}

                        set
                        {{
                            unsafe
                            {{
                                *({fieldTypeName}*)(buffer + {fieldOffset}).ToPointer() = value;
                            }}
                        }}
                    }}");
            }

            WriteLine();
        }