//using System; //using System.Collections.Generic; //using System.Collections.Immutable; //using System.Linq; //using System.Text; //using Microsoft.CodeAnalysis; //using Microsoft.CodeAnalysis.CSharp.Syntax; //using Microsoft.CodeAnalysis.Text; //namespace AyCode.Core.Serializers.SourceGenerator; ///// ///// Source Generator for AcBinary serialization. ///// Generates optimized serialize/deserialize methods for classes marked with [AcBinarySerializable]. ///// //[Generator] //public class AcBinarySourceGenerator : IIncrementalGenerator //{ // private const string AcBinarySerializableAttributeName = "AyCode.Core.Serializers.Attributes.AcBinarySerializableAttribute"; // public void Initialize(IncrementalGeneratorInitializationContext context) // { // // Find all classes with [AcBinarySerializable] attribute // var classDeclarations = context.SyntaxProvider // .ForAttributeWithMetadataName( // AcBinarySerializableAttributeName, // predicate: static (node, _) => node is ClassDeclarationSyntax || node is StructDeclarationSyntax, // transform: static (ctx, _) => GetClassInfo(ctx)) // .Where(static info => info != null); // // Combine with compilation // var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect()); // // Generate source // context.RegisterSourceOutput(compilationAndClasses, // static (spc, source) => Execute(source.Left, source.Right, spc)); // } // private static SerializableClassInfo GetClassInfo(GeneratorAttributeSyntaxContext context) // { // if (!(context.TargetSymbol is INamedTypeSymbol typeSymbol)) // return null; // var namespaceName = typeSymbol.ContainingNamespace.IsGlobalNamespace // ? string.Empty // : typeSymbol.ContainingNamespace.ToDisplayString(); // var className = typeSymbol.Name; // var fullTypeName = typeSymbol.ToDisplayString(); // var isStruct = typeSymbol.IsValueType; // // Check if this is a nested type // var isNestedType = typeSymbol.ContainingType != null; // // For nested types, we need the full containing type path for method signatures // // e.g. "OuterClass.InnerClass" instead of just "InnerClass" // var typeNameForSignature = isNestedType // ? GetNestedTypeName(typeSymbol) // : className; // // Get all public properties with getter and setter // // DUPLICATED LOGIC: Same filtering as TypeMetadataBase.GetSerializableProperties() // var properties = new List(); // foreach (var member in typeSymbol.GetMembers()) // { // if (member is IPropertySymbol p && // p.DeclaredAccessibility == Accessibility.Public && // p.GetMethod != null && // p.SetMethod != null && // !p.IsIndexer && // !p.IsStatic) // { // properties.Add(new PropertyInfo( // p.Name, // p.Type.ToDisplayString(), // GetPropertyTypeKind(p.Type), // p.Type.NullableAnnotation == NullableAnnotation.Annotated || IsNullableValueType(p.Type))); // } // } // // DUPLICATED LOGIC: Same ordering as TypeMetadataBase.GetSerializableProperties() // properties.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal)); // return new SerializableClassInfo(namespaceName, className, fullTypeName, isStruct, isNestedType, typeNameForSignature, properties); // } // /// // /// Gets the nested type name chain (e.g., "OuterClass.MiddleClass.InnerClass") // /// // private static string GetNestedTypeName(INamedTypeSymbol typeSymbol) // { // var parts = new List(); // var current = typeSymbol; // while (current != null) // { // parts.Insert(0, current.Name); // current = current.ContainingType; // } // return string.Join(".", parts); // } // private static bool IsNullableValueType(ITypeSymbol type) // { // return type is INamedTypeSymbol namedType && // namedType.IsGenericType && // namedType.ConstructedFrom.SpecialType == SpecialType.System_Nullable_T; // } // private static PropertyTypeKind GetPropertyTypeKind(ITypeSymbol type) // { // // Handle nullable value types // if (type is INamedTypeSymbol namedType && namedType.IsGenericType && // namedType.ConstructedFrom.SpecialType == SpecialType.System_Nullable_T) // { // // Get underlying type // var underlyingType = namedType.TypeArguments[0]; // return GetPropertyTypeKindForUnderlying(underlyingType, isNullable: true); // } // return GetPropertyTypeKindForUnderlying(type, isNullable: false); // } // private static PropertyTypeKind GetPropertyTypeKindForUnderlying(ITypeSymbol type, bool isNullable) // { // switch (type.SpecialType) // { // case SpecialType.System_String: return PropertyTypeKind.String; // case SpecialType.System_Int32: return isNullable ? PropertyTypeKind.NullableInt32 : PropertyTypeKind.Int32; // case SpecialType.System_Int64: return isNullable ? PropertyTypeKind.NullableInt64 : PropertyTypeKind.Int64; // case SpecialType.System_Int16: return isNullable ? PropertyTypeKind.NullableInt16 : PropertyTypeKind.Int16; // case SpecialType.System_Byte: return isNullable ? PropertyTypeKind.NullableByte : PropertyTypeKind.Byte; // case SpecialType.System_SByte: return isNullable ? PropertyTypeKind.NullableSByte : PropertyTypeKind.SByte; // case SpecialType.System_UInt16: return isNullable ? PropertyTypeKind.NullableUInt16 : PropertyTypeKind.UInt16; // case SpecialType.System_UInt32: return isNullable ? PropertyTypeKind.NullableUInt32 : PropertyTypeKind.UInt32; // case SpecialType.System_UInt64: return isNullable ? PropertyTypeKind.NullableUInt64 : PropertyTypeKind.UInt64; // case SpecialType.System_Boolean: return isNullable ? PropertyTypeKind.NullableBoolean : PropertyTypeKind.Boolean; // case SpecialType.System_Single: return isNullable ? PropertyTypeKind.NullableSingle : PropertyTypeKind.Single; // case SpecialType.System_Double: return isNullable ? PropertyTypeKind.NullableDouble : PropertyTypeKind.Double; // case SpecialType.System_Decimal: return isNullable ? PropertyTypeKind.NullableDecimal : PropertyTypeKind.Decimal; // case SpecialType.System_DateTime: return isNullable ? PropertyTypeKind.NullableDateTime : PropertyTypeKind.DateTime; // default: return GetNonSpecialTypeKind(type, isNullable); // } // } // private static PropertyTypeKind GetNonSpecialTypeKind(ITypeSymbol type, bool isNullable) // { // var fullName = type.ToDisplayString(); // if (fullName == "System.Guid") return isNullable ? PropertyTypeKind.NullableGuid : PropertyTypeKind.Guid; // if (fullName == "System.TimeSpan") return isNullable ? PropertyTypeKind.NullableTimeSpan : PropertyTypeKind.TimeSpan; // if (fullName == "System.DateTimeOffset") return isNullable ? PropertyTypeKind.NullableDateTimeOffset : PropertyTypeKind.DateTimeOffset; // if (fullName == "System.DateOnly") return isNullable ? PropertyTypeKind.NullableDateOnly : PropertyTypeKind.DateOnly; // if (fullName == "System.TimeOnly") return isNullable ? PropertyTypeKind.NullableTimeOnly : PropertyTypeKind.TimeOnly; // if (type.TypeKind == TypeKind.Enum) return isNullable ? PropertyTypeKind.NullableEnum : PropertyTypeKind.Enum; // if (IsCollectionType(type)) return PropertyTypeKind.Collection; // if (type.TypeKind == TypeKind.Class || type.TypeKind == TypeKind.Struct) return PropertyTypeKind.Complex; // return PropertyTypeKind.Unknown; // } // private static bool IsCollectionType(ITypeSymbol type) // { // if (type is IArrayTypeSymbol) // return true; // if (type is INamedTypeSymbol namedType) // { // foreach (var iface in namedType.AllInterfaces) // { // if (iface.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T) // return true; // var ifaceName = iface.ToDisplayString(); // if (ifaceName.StartsWith("System.Collections.Generic.IList<") || // ifaceName.StartsWith("System.Collections.Generic.ICollection<")) // return true; // } // } // return false; // } // private static void Execute(Compilation compilation, ImmutableArray classes, SourceProductionContext context) // { // if (classes.IsDefaultOrEmpty) // return; // foreach (var classInfo in classes) // { // if (classInfo == null) // continue; // var source = GenerateSerializerClass(classInfo); // context.AddSource($"{classInfo.ClassName}_AcBinarySerializer.g.cs", SourceText.From(source, Encoding.UTF8)); // } // } // private static string GenerateSerializerClass(SerializableClassInfo classInfo) // { // var sb = new StringBuilder(); // sb.AppendLine("// "); // sb.AppendLine("#nullable enable"); // sb.AppendLine(); // sb.AppendLine("using System;"); // sb.AppendLine("using System.Runtime.CompilerServices;"); // sb.AppendLine("using AyCode.Core.Serializers.Binaries;"); // sb.AppendLine(); // if (!string.IsNullOrEmpty(classInfo.Namespace)) // { // sb.AppendLine($"namespace {classInfo.Namespace}"); // sb.AppendLine("{"); // } // var indent = string.IsNullOrEmpty(classInfo.Namespace) ? "" : " "; // sb.AppendLine($"{indent}/// "); // sb.AppendLine($"{indent}/// Generated binary serializer for {classInfo.ClassName}."); // sb.AppendLine($"{indent}/// "); // sb.AppendLine($"{indent}internal static class {classInfo.ClassName}_AcBinarySerializer"); // sb.AppendLine($"{indent}{{"); // // Generate property count constant // sb.AppendLine($"{indent} public const int PropertyCount = {classInfo.Properties.Count};"); // sb.AppendLine(); // // Generate property names array for validation // sb.AppendLine($"{indent} /// "); // sb.AppendLine($"{indent} /// Property names in serialization order (alphabetical)."); // sb.AppendLine($"{indent} /// Used for runtime validation against TypeMetadataBase.GetSerializableProperties()."); // sb.AppendLine($"{indent} /// "); // sb.Append($"{indent} public static readonly string[] PropertyNames = new[] {{ "); // sb.Append(string.Join(", ", classInfo.Properties.Select(p => $"\"{p.Name}\""))); // sb.AppendLine(" };"); // sb.AppendLine(); // // Generate Serialize method // GenerateSerializeMethod(sb, classInfo, indent); // // Generate Deserialize method // GenerateDeserializeMethod(sb, classInfo, indent); // sb.AppendLine($"{indent}}}"); // if (!string.IsNullOrEmpty(classInfo.Namespace)) // { // sb.AppendLine("}"); // } // return sb.ToString(); // } // private static void GenerateSerializeMethod(StringBuilder sb, SerializableClassInfo classInfo, string indent) // { // sb.AppendLine($"{indent} /// "); // sb.AppendLine($"{indent} /// Serializes a {classInfo.ClassName} instance to the binary context."); // sb.AppendLine($"{indent} /// Direct property access - no reflection, no boxing for primitives."); // sb.AppendLine($"{indent} /// "); // sb.AppendLine($"{indent} [MethodImpl(MethodImplOptions.AggressiveInlining)]"); // sb.AppendLine($"{indent} public static void Serialize({classInfo.TypeNameForSignature} obj, AcBinarySerializer.BinarySerializationContext context) where TOutput : BinaryOutputBase"); // sb.AppendLine($"{indent} {{"); // sb.AppendLine($"{indent} var output = context.Output;"); // foreach (var prop in classInfo.Properties) // { // GenerateSerializeProperty(sb, prop, indent + " "); // } // sb.AppendLine($"{indent} }}"); // sb.AppendLine(); // } // private static void GenerateSerializeProperty(StringBuilder sb, PropertyInfo prop, string indent) // { // var propAccess = $"obj.{prop.Name}"; // // Handle nullable VALUE types (Nullable) - these use .HasValue and .Value // if (IsNullableValueTypeKind(prop.TypeKind)) // { // sb.AppendLine($"{indent}// {prop.Name}: {prop.TypeName} (nullable value type)"); // sb.AppendLine($"{indent}if ({propAccess}.HasValue)"); // sb.AppendLine($"{indent}{{"); // GenerateSerializeValue(sb, prop.TypeKind, $"{propAccess}.Value", indent + " "); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.WriteByte(BinaryTypeCode.Null);"); // sb.AppendLine($"{indent}}}"); // return; // } // sb.AppendLine($"{indent}// {prop.Name}: {prop.TypeName}"); // // String needs null check // if (prop.TypeKind == PropertyTypeKind.String) // { // sb.AppendLine($"{indent}if ({propAccess} == null)"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.WriteByte(BinaryTypeCode.Null);"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else if ({propAccess}.Length == 0)"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.WriteByte(BinaryTypeCode.StringEmpty);"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.WriteByte(BinaryTypeCode.String);"); // sb.AppendLine($"{indent} context.WriteStringUtf8({propAccess});"); // sb.AppendLine($"{indent}}}"); // return; // } // // Nullable reference types (Complex/Collection with ? annotation) - use == null // if (prop.IsNullable && (prop.TypeKind == PropertyTypeKind.Complex || prop.TypeKind == PropertyTypeKind.Collection)) // { // sb.AppendLine($"{indent}if ({propAccess} == null)"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.WriteByte(BinaryTypeCode.Null);"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else"); // sb.AppendLine($"{indent}{{"); // GenerateSerializeValue(sb, prop.TypeKind, propAccess, indent + " "); // sb.AppendLine($"{indent}}}"); // return; // } // GenerateSerializeValue(sb, prop.TypeKind, propAccess, indent); // } // /// // /// Checks if the type kind represents a nullable VALUE type (Nullable<T>), not a reference type // /// // private static bool IsNullableValueTypeKind(PropertyTypeKind kind) // { // return kind >= PropertyTypeKind.NullableInt32 && kind <= PropertyTypeKind.NullableEnum; // } // private static void GenerateSerializeValue(StringBuilder sb, PropertyTypeKind typeKind, string valueExpr, string indent) // { // switch (typeKind) // { // case PropertyTypeKind.Int32: // case PropertyTypeKind.NullableInt32: // sb.AppendLine($"{indent}if (BinaryTypeCode.TryEncodeTinyInt({valueExpr}, out var tiny_{valueExpr.Replace(".", "_")}))"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.WriteByte(tiny_{valueExpr.Replace(".", "_")});"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.WriteByte(BinaryTypeCode.Int32);"); // sb.AppendLine($"{indent} context.WriteVarInt({valueExpr});"); // sb.AppendLine($"{indent}}}"); // break; // case PropertyTypeKind.Int64: // case PropertyTypeKind.NullableInt64: // sb.AppendLine($"{indent}context.WriteByte(BinaryTypeCode.Int64);"); // sb.AppendLine($"{indent}context.WriteVarLong({valueExpr});"); // break; // case PropertyTypeKind.Boolean: // case PropertyTypeKind.NullableBoolean: // sb.AppendLine($"{indent}context.WriteByte({valueExpr} ? BinaryTypeCode.True : BinaryTypeCode.False);"); // break; // case PropertyTypeKind.Double: // case PropertyTypeKind.NullableDouble: // sb.AppendLine($"{indent}context.WriteTypeCodeAndRaw(BinaryTypeCode.Float64, {valueExpr});"); // break; // case PropertyTypeKind.Single: // case PropertyTypeKind.NullableSingle: // sb.AppendLine($"{indent}context.WriteTypeCodeAndRaw(BinaryTypeCode.Float32, {valueExpr});"); // break; // case PropertyTypeKind.Decimal: // case PropertyTypeKind.NullableDecimal: // sb.AppendLine($"{indent}context.WriteByte(BinaryTypeCode.Decimal);"); // sb.AppendLine($"{indent}context.WriteDecimalBits({valueExpr});"); // break; // case PropertyTypeKind.DateTime: // case PropertyTypeKind.NullableDateTime: // sb.AppendLine($"{indent}context.WriteByte(BinaryTypeCode.DateTime);"); // sb.AppendLine($"{indent}context.WriteDateTimeBits({valueExpr});"); // break; // case PropertyTypeKind.Guid: // case PropertyTypeKind.NullableGuid: // sb.AppendLine($"{indent}context.WriteByte(BinaryTypeCode.Guid);"); // sb.AppendLine($"{indent}context.WriteGuidBits({valueExpr});"); // break; // case PropertyTypeKind.Byte: // case PropertyTypeKind.NullableByte: // sb.AppendLine($"{indent}context.WriteTwoBytes(BinaryTypeCode.UInt8, {valueExpr});"); // break; // case PropertyTypeKind.Int16: // case PropertyTypeKind.NullableInt16: // sb.AppendLine($"{indent}context.WriteTypeCodeAndRaw(BinaryTypeCode.Int16, {valueExpr});"); // break; // case PropertyTypeKind.UInt16: // case PropertyTypeKind.NullableUInt16: // sb.AppendLine($"{indent}context.WriteTypeCodeAndRaw(BinaryTypeCode.UInt16, {valueExpr});"); // break; // case PropertyTypeKind.UInt32: // case PropertyTypeKind.NullableUInt32: // sb.AppendLine($"{indent}context.WriteByte(BinaryTypeCode.UInt32);"); // sb.AppendLine($"{indent}context.WriteVarUInt({valueExpr});"); // sb.AppendLine($"{indent}context.WriteByte(BinaryTypeCode.UInt32);"); // sb.AppendLine($"{indent}context.WriteVarUInt({valueExpr});"); // break; // case PropertyTypeKind.UInt64: // case PropertyTypeKind.NullableUInt64: // sb.AppendLine($"{indent}context.WriteByte(BinaryTypeCode.UInt64);"); // sb.AppendLine($"{indent}context.WriteVarULong({valueExpr});"); // break; // case PropertyTypeKind.TimeSpan: // case PropertyTypeKind.NullableTimeSpan: // sb.AppendLine($"{indent}context.WriteTypeCodeAndRaw(BinaryTypeCode.TimeSpan, {valueExpr}.Ticks);"); // break; // case PropertyTypeKind.DateTimeOffset: // case PropertyTypeKind.NullableDateTimeOffset: // sb.AppendLine($"{indent}context.WriteByte(BinaryTypeCode.DateTimeOffset);"); // sb.AppendLine($"{indent}context.WriteDateTimeOffsetBits({valueExpr});"); // break; // case PropertyTypeKind.Enum: // case PropertyTypeKind.NullableEnum: // sb.AppendLine($"{indent}context.WriteByte(BinaryTypeCode.Enum);"); // sb.AppendLine($"{indent}var enumVal = (int){valueExpr};"); // sb.AppendLine($"{indent}if (BinaryTypeCode.TryEncodeTinyInt(enumVal, out var tinyEnum))"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.WriteByte(tinyEnum);"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.WriteByte(BinaryTypeCode.Int32);"); // sb.AppendLine($"{indent} context.WriteVarInt(enumVal);"); // sb.AppendLine($"{indent}}}"); // break; // case PropertyTypeKind.Collection: // case PropertyTypeKind.Complex: // // TODO: Collections and complex types will be implemented later // sb.AppendLine($"{indent}// TODO: Complex/Collection type - fallback to runtime serializer"); // sb.AppendLine($"{indent}throw new NotImplementedException(\"Complex/Collection types not yet implemented in generated serializer\");"); // break; // default: // sb.AppendLine($"{indent}// Unknown type - fallback needed"); // sb.AppendLine($"{indent}throw new NotImplementedException($\"Type {typeKind} not implemented in generated serializer\");"); // break; // } // } // private static void GenerateDeserializeMethod(StringBuilder sb, SerializableClassInfo classInfo, string indent) // { // sb.AppendLine($"{indent} /// "); // sb.AppendLine($"{indent} /// Deserializes properties into a {classInfo.ClassName} instance from the binary context."); // sb.AppendLine($"{indent} /// Direct property access - no reflection, no boxing for primitives."); // sb.AppendLine($"{indent} /// "); // sb.AppendLine($"{indent} [MethodImpl(MethodImplOptions.AggressiveInlining)]"); // sb.AppendLine($"{indent} public static void Deserialize({classInfo.TypeNameForSignature} obj, ref AcBinaryDeserializer.BinaryDeserializationContext context)"); // sb.AppendLine($"{indent} {{"); // foreach (var prop in classInfo.Properties) // { // GenerateDeserializeProperty(sb, prop, indent + " "); // } // sb.AppendLine($"{indent} }}"); // } // private static void GenerateDeserializeProperty(StringBuilder sb, PropertyInfo prop, string indent) // { // sb.AppendLine($"{indent}// {prop.Name}: {prop.TypeName}"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} var peekCode = context.PeekByte();"); // // Handle Skip marker // sb.AppendLine($"{indent} if (peekCode == BinaryTypeCode.PropertySkip)"); // sb.AppendLine($"{indent} {{"); // sb.AppendLine($"{indent} context.ReadByte(); // consume Skip marker"); // sb.AppendLine($"{indent} // Property keeps default value"); // sb.AppendLine($"{indent} }}"); // // Handle Null marker // sb.AppendLine($"{indent} else if (peekCode == BinaryTypeCode.Null)"); // sb.AppendLine($"{indent} {{"); // sb.AppendLine($"{indent} context.ReadByte(); // consume Null marker"); // if (prop.IsNullable || prop.TypeKind == PropertyTypeKind.String) // { // sb.AppendLine($"{indent} obj.{prop.Name} = default;"); // } // else // { // sb.AppendLine($"{indent} // Non-nullable property, keep default"); // } // sb.AppendLine($"{indent} }}"); // // Handle actual value // sb.AppendLine($"{indent} else"); // sb.AppendLine($"{indent} {{"); // GenerateDeserializeValue(sb, prop, indent + " "); // sb.AppendLine($"{indent} }}"); // sb.AppendLine($"{indent}}}"); // } // private static void GenerateDeserializeValue(StringBuilder sb, PropertyInfo prop, string indent) // { // var propAccess = $"obj.{prop.Name}"; // switch (prop.TypeKind) // { // case PropertyTypeKind.String: // sb.AppendLine($"{indent}if (peekCode == BinaryTypeCode.StringEmpty)"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.ReadByte();"); // sb.AppendLine($"{indent} {propAccess} = string.Empty;"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else if (peekCode == BinaryTypeCode.String)"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.ReadByte();"); // sb.AppendLine($"{indent} var len = (int)context.ReadVarUInt();"); // sb.AppendLine($"{indent} {propAccess} = context.ReadStringUtf8(len);"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else if (BinaryTypeCode.IsFixStr(peekCode))"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.ReadByte();"); // sb.AppendLine($"{indent} var len = BinaryTypeCode.DecodeFixStrLength(peekCode);"); // sb.AppendLine($"{indent} {propAccess} = len == 0 ? string.Empty : context.ReadStringUtf8(len);"); // sb.AppendLine($"{indent}}}"); // break; // case PropertyTypeKind.Int32: // case PropertyTypeKind.NullableInt32: // sb.AppendLine($"{indent}if (BinaryTypeCode.IsTinyInt(peekCode))"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.ReadByte();"); // sb.AppendLine($"{indent} {propAccess} = BinaryTypeCode.DecodeTinyInt(peekCode);"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else if (peekCode == BinaryTypeCode.Int32)"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.ReadByte();"); // sb.AppendLine($"{indent} {propAccess} = context.ReadVarInt();"); // sb.AppendLine($"{indent}}}"); // break; // case PropertyTypeKind.Int64: // case PropertyTypeKind.NullableInt64: // sb.AppendLine($"{indent}if (BinaryTypeCode.IsTinyInt(peekCode))"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.ReadByte();"); // sb.AppendLine($"{indent} {propAccess} = BinaryTypeCode.DecodeTinyInt(peekCode);"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else if (peekCode == BinaryTypeCode.Int32)"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.ReadByte();"); // sb.AppendLine($"{indent} {propAccess} = context.ReadVarInt();"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else if (peekCode == BinaryTypeCode.Int64)"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.ReadByte();"); // sb.AppendLine($"{indent} {propAccess} = context.ReadVarLong();"); // sb.AppendLine($"{indent}}}"); // break; // case PropertyTypeKind.Boolean: // case PropertyTypeKind.NullableBoolean: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = peekCode == BinaryTypeCode.True;"); // break; // case PropertyTypeKind.Double: // case PropertyTypeKind.NullableDouble: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadDoubleUnsafe();"); // break; // case PropertyTypeKind.Single: // case PropertyTypeKind.NullableSingle: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadSingleUnsafe();"); // break; // case PropertyTypeKind.Decimal: // case PropertyTypeKind.NullableDecimal: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadDecimalUnsafe();"); // break; // case PropertyTypeKind.DateTime: // case PropertyTypeKind.NullableDateTime: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadDateTimeUnsafe();"); // break; // case PropertyTypeKind.Guid: // case PropertyTypeKind.NullableGuid: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadGuidUnsafe();"); // break; // case PropertyTypeKind.Byte: // case PropertyTypeKind.NullableByte: // sb.AppendLine($"{indent}if (BinaryTypeCode.IsTinyInt(peekCode))"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.ReadByte();"); // sb.AppendLine($"{indent} {propAccess} = (byte)BinaryTypeCode.DecodeTinyInt(peekCode);"); // sb.AppendLine($"{indent}}}"); // sb.AppendLine($"{indent}else"); // sb.AppendLine($"{indent}{{"); // sb.AppendLine($"{indent} context.ReadByte();"); // sb.AppendLine($"{indent} {propAccess} = context.ReadByte();"); // sb.AppendLine($"{indent}}}"); // break; // case PropertyTypeKind.Int16: // case PropertyTypeKind.NullableInt16: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadInt16Unsafe();"); // break; // case PropertyTypeKind.UInt16: // case PropertyTypeKind.NullableUInt16: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadUInt16Unsafe();"); // break; // case PropertyTypeKind.UInt32: // case PropertyTypeKind.NullableUInt32: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadVarUInt();"); // break; // case PropertyTypeKind.UInt64: // case PropertyTypeKind.NullableUInt64: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadVarULong();"); // break; // case PropertyTypeKind.TimeSpan: // case PropertyTypeKind.NullableTimeSpan: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadTimeSpanUnsafe();"); // break; // case PropertyTypeKind.DateTimeOffset: // case PropertyTypeKind.NullableDateTimeOffset: // sb.AppendLine($"{indent}context.ReadByte();"); // sb.AppendLine($"{indent}{propAccess} = context.ReadDateTimeOffsetUnsafe();"); // break; // case PropertyTypeKind.Enum: // case PropertyTypeKind.NullableEnum: // sb.AppendLine($"{indent}// TODO: Enum deserialization needs type info"); // sb.AppendLine($"{indent}throw new NotImplementedException(\"Enum deserialization not yet implemented\");"); // break; // case PropertyTypeKind.Collection: // case PropertyTypeKind.Complex: // sb.AppendLine($"{indent}// TODO: Complex/Collection types"); // sb.AppendLine($"{indent}throw new NotImplementedException(\"Complex/Collection deserialization not yet implemented\");"); // break; // default: // sb.AppendLine($"{indent}throw new NotImplementedException($\"Type deserialization not implemented\");"); // break; // } // } //} ///// ///// Information about a class marked with [AcBinarySerializable]. ///// //internal sealed class SerializableClassInfo //{ // public string Namespace { get; } // public string ClassName { get; } // public string FullTypeName { get; } // public bool IsStruct { get; } // public bool IsNestedType { get; } // /// // /// The type name to use in method signatures. For nested types this includes the containing types. // /// e.g., "OuterClass.InnerClass" // /// // public string TypeNameForSignature { get; } // public List Properties { get; } // public SerializableClassInfo(string ns, string className, string fullTypeName, bool isStruct, bool isNestedType, string typeNameForSignature, List properties) // { // Namespace = ns; // ClassName = className; // FullTypeName = fullTypeName; // IsStruct = isStruct; // IsNestedType = isNestedType; // TypeNameForSignature = typeNameForSignature; // Properties = properties; // } //} ///// ///// Information about a serializable property. ///// //internal sealed class PropertyInfo //{ // public string Name { get; } // public string TypeName { get; } // public PropertyTypeKind TypeKind { get; } // public bool IsNullable { get; } // public PropertyInfo(string name, string typeName, PropertyTypeKind typeKind, bool isNullable) // { // Name = name; // TypeName = typeName; // TypeKind = typeKind; // IsNullable = isNullable; // } //} ///// ///// Kind of property type for code generation. ///// //internal enum PropertyTypeKind //{ // Unknown, // String, // Int32, // Int64, // Int16, // Byte, // SByte, // UInt16, // UInt32, // UInt64, // Boolean, // Single, // Double, // Decimal, // DateTime, // DateTimeOffset, // TimeSpan, // DateOnly, // TimeOnly, // Guid, // Enum, // Collection, // Complex, // // Nullable variants // NullableInt32, // NullableInt64, // NullableInt16, // NullableByte, // NullableSByte, // NullableUInt16, // NullableUInt32, // NullableUInt64, // NullableBoolean, // NullableSingle, // NullableDouble, // NullableDecimal, // NullableDateTime, // NullableDateTimeOffset, // NullableTimeSpan, // NullableDateOnly, // NullableTimeOnly, // NullableGuid, // NullableEnum //}