AyCode.Core/AyCode.Core.Serializers.Sou.../AcBinarySourceGenerator.cs

780 lines
35 KiB
C#

//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;
///// <summary>
///// Source Generator for AcBinary serialization.
///// Generates optimized serialize/deserialize methods for classes marked with [AcBinarySerializable].
///// </summary>
//[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<PropertyInfo>();
// 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);
// }
// /// <summary>
// /// Gets the nested type name chain (e.g., "OuterClass.MiddleClass.InnerClass")
// /// </summary>
// private static string GetNestedTypeName(INamedTypeSymbol typeSymbol)
// {
// var parts = new List<string>();
// 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<SerializableClassInfo> 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("// <auto-generated/>");
// 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}/// <summary>");
// sb.AppendLine($"{indent}/// Generated binary serializer for {classInfo.ClassName}.");
// sb.AppendLine($"{indent}/// </summary>");
// 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} /// <summary>");
// sb.AppendLine($"{indent} /// Property names in serialization order (alphabetical).");
// sb.AppendLine($"{indent} /// Used for runtime validation against TypeMetadataBase.GetSerializableProperties().");
// sb.AppendLine($"{indent} /// </summary>");
// 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} /// <summary>");
// 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} /// </summary>");
// sb.AppendLine($"{indent} [MethodImpl(MethodImplOptions.AggressiveInlining)]");
// sb.AppendLine($"{indent} public static void Serialize<TOutput>({classInfo.TypeNameForSignature} obj, AcBinarySerializer.BinarySerializationContext<TOutput> 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<T>) - 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);
// }
// /// <summary>
// /// Checks if the type kind represents a nullable VALUE type (Nullable&lt;T&gt;), not a reference type
// /// </summary>
// 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} /// <summary>");
// 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} /// </summary>");
// 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;
// }
// }
//}
///// <summary>
///// Information about a class marked with [AcBinarySerializable].
///// </summary>
//internal sealed class SerializableClassInfo
//{
// public string Namespace { get; }
// public string ClassName { get; }
// public string FullTypeName { get; }
// public bool IsStruct { get; }
// public bool IsNestedType { get; }
// /// <summary>
// /// The type name to use in method signatures. For nested types this includes the containing types.
// /// e.g., "OuterClass.InnerClass"
// /// </summary>
// public string TypeNameForSignature { get; }
// public List<PropertyInfo> Properties { get; }
// public SerializableClassInfo(string ns, string className, string fullTypeName, bool isStruct, bool isNestedType, string typeNameForSignature, List<PropertyInfo> properties)
// {
// Namespace = ns;
// ClassName = className;
// FullTypeName = fullTypeName;
// IsStruct = isStruct;
// IsNestedType = isNestedType;
// TypeNameForSignature = typeNameForSignature;
// Properties = properties;
// }
//}
///// <summary>
///// Information about a serializable property.
///// </summary>
//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;
// }
//}
///// <summary>
///// Kind of property type for code generation.
///// </summary>
//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
//}