/// <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(); }
/// <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()},"); } }
/// <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)
/// <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); }
/// <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(); }
/// <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); }
/// <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); }
/// <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});"); }
/// <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(); }
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++; }
/// <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++; }
/// <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}; }}");
/// <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++; }
/// <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); }
/// <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++; }
/// <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(); }
/// <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; }
/// <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(); }