// // PacketIndexAttributeGenerator.cs // // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.CodeDom.Compiler; using NosSmooth.PacketSerializersGenerator.Data; using NosSmooth.PacketSerializersGenerator.Errors; using NosSmooth.PacketSerializersGenerator.Extensions; namespace NosSmooth.PacketSerializersGenerator.AttributeGenerators; /// public class PacketIndexAttributeGenerator : IParameterGenerator { private readonly InlineTypeConverterGenerator _inlineTypeConverterGenerators; /// /// Initializes a new instance of the class. /// /// The generator for types. public PacketIndexAttributeGenerator(InlineTypeConverterGenerator inlineTypeConverterGenerators) { _inlineTypeConverterGenerators = inlineTypeConverterGenerators; } /// /// Gets the full name of the packet index attribute. /// public static string PacketIndexAttributeFullName => "NosSmooth.PacketSerializer.Abstractions.Attributes.PacketIndexAttribute"; /// public bool ShouldHandle(ParameterInfo parameter) => parameter.Attributes.Any(x => x.FullName == PacketIndexAttributeFullName); /// public IError? CheckParameter(PacketInfo packet, ParameterInfo parameter) { var error = ParameterChecker.CheckHasOneAttribute(packet, parameter); if (error is not null) { return error; } return ParameterChecker.CheckOptionalIsNullable(packet, parameter); } /// public IError? GenerateSerializerPart(IndentedTextWriter textWriter, PacketInfo packetInfo) { bool pushedLevel = false; var generator = new ConverterSerializationGenerator(textWriter); var parameter = packetInfo.Parameters.Current; var attribute = parameter.Attributes.First(); if (parameter.IsOptional()) { textWriter.WriteLine($"if (obj.{parameter.GetVariableName()} is not null)"); textWriter.WriteLine("{"); textWriter.Indent++; } // register after separator var afterSeparator = attribute.GetNamedValue("AfterSeparator", null); if (afterSeparator is not null) { generator.SetAfterSeparatorOnce((char)afterSeparator); } // push inner separator level var innerSeparator = attribute.GetNamedValue("InnerSeparator", null); if (innerSeparator is not null) { generator.PushLevel((char)innerSeparator); pushedLevel = true; } // serialize, check the error. _inlineTypeConverterGenerators.Serialize(textWriter, packetInfo); // pop inner separator level if (pushedLevel) { generator.PopLevel(); } // end optional if if (parameter.IsOptional()) { textWriter.Indent--; textWriter.WriteLine("}"); } return null; } /// public IError? GenerateDeserializerPart(IndentedTextWriter textWriter, PacketInfo packetInfo) { bool pushedLevel = false; var generator = new ConverterDeserializationGenerator(textWriter); var parameter = packetInfo.Parameters.Current; var attribute = parameter.Attributes.First(); generator.DeclareLocalVariable(parameter); // add optional if if (parameter.IsOptional()) { generator.StartOptionalCheck(parameter, packetInfo.Name); } var afterSeparator = attribute.GetNamedValue("AfterSeparator", null); if (afterSeparator is not null) { generator.SetAfterSeparatorOnce((char)afterSeparator); } var innerSeparator = attribute.GetNamedValue("InnerSeparator", null); if (innerSeparator is not null) { generator.PushLevel((char)innerSeparator); pushedLevel = true; } generator.DeserializeAndCheck(parameter, packetInfo, _inlineTypeConverterGenerators); if (!parameter.Nullable) { generator.CheckNullError (parameter.GetNullableVariableName(), parameter.GetResultVariableName(), parameter.Name); } generator.AssignLocalVariable(parameter, false); if (pushedLevel) { generator.ReadToLastToken(); generator.PopLevel(); } if (!packetInfo.Parameters.IsLast) { generator.ValidateNotLast(parameter.Name); } // end is last token if body if (parameter.IsOptional()) { generator.EndOptionalCheck(parameter); } return null; } }