Skip to content

Commit

Permalink
Merge remote-tracking branch 'MeikelLP/master' into feature/drops
Browse files Browse the repository at this point in the history
  • Loading branch information
WoozChucky committed May 13, 2024
2 parents eb60598 + a727213 commit 4d7f107
Show file tree
Hide file tree
Showing 22 changed files with 466 additions and 189 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/dotnet-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ jobs:
sudo chmod +x generate_kaitai.sh
./generate_kaitai.sh
# finally tests
- name: Build
run: dotnet build --verbosity minimal src/QuantumCore.sln

- name: Test
run: dotnet test --verbosity normal src/QuantumCore.sln
run: dotnet test --no-build src/QuantumCore.sln
deploy:
needs:
- test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" PrivateAssets="all" />
</ItemGroup>


Expand Down
76 changes: 45 additions & 31 deletions src/Core.Networking.Generators/DeserializeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public DeserializeGenerator(GeneratorContext context)
public string Generate(TypeDeclarationSyntax type, string dynamicByteIndex)
{
var source = new StringBuilder();
source.AppendLine($" public static {type.Identifier.Text} Deserialize(ReadOnlySpan<byte> bytes, in int offset = 0)");
source.AppendLine(
$" public static {type.Identifier.Text} Deserialize(ReadOnlySpan<byte> bytes, in int offset = 0)");
source.AppendLine(" {");
source.AppendLine(GenerateMethodBody(type, dynamicByteIndex, " ", false));
source.AppendLine(" }");
Expand Down Expand Up @@ -50,7 +51,8 @@ public string Generate(TypeDeclarationSyntax type, string dynamicByteIndex)
return source.ToString();
}

private string GenerateMethodBody(TypeDeclarationSyntax type, string dynamicByteIndex, string indentPrefix, bool isStreamMode)
private string GenerateMethodBody(TypeDeclarationSyntax type, string dynamicByteIndex, string indentPrefix,
bool isStreamMode)
{
var staticByteIndex = 0;
var dynamicByteIndexLocal = new StringBuilder(dynamicByteIndex);
Expand All @@ -61,17 +63,18 @@ private string GenerateMethodBody(TypeDeclarationSyntax type, string dynamicByte
// declare and initialize variables
foreach (var field in fields)
{
var line = GetMethodLine(field, ref staticByteIndex, dynamicByteIndexLocal, "", indentPrefix, true, isStreamMode);

var line = GetMethodLine(field, ref staticByteIndex, dynamicByteIndexLocal, "", indentPrefix, true,
isStreamMode);

// packets dynamic strings will send their size in an early field but this field is the size of the whole
// packet not just the dynamic field's size
var isDynamicSizeField = fieldsCopy.Any(x => x.SizeFieldName == field.Name);
// + 1 because string includes a 0 byte at the end
var staticSizeString = isDynamicSizeField ? $" - {typeStaticSize + 1}" : "";
var staticSizeString = isDynamicSizeField ? $" - {typeStaticSize + 1}" : "";
sb.Append($"{indentPrefix}var {GetVariableNameForExpression(field.Name)} = {line}{staticSizeString}");
if (field is not { IsArray: true, HasDynamicLength: true } || (field.IsArray &&
(field.SemanticType as IArrayTypeSymbol)
?.ElementType.Name == "Byte"))
if (field is not {IsArray: true, HasDynamicLength: true} || (field.IsArray &&
(field.SemanticType as IArrayTypeSymbol)
?.ElementType.Name == "Byte"))
{
// dynamic arrays have a for loop after their declaration so don't put a ;
sb.AppendLine(";");
Expand All @@ -94,14 +97,14 @@ private string GenerateMethodBody(TypeDeclarationSyntax type, string dynamicByte
{
sb.AppendLine($"{indentPrefix}var obj = new {_context.GetTypeInfo(type).GetFullName()}");
sb.AppendLine($"{indentPrefix}{{");
for (var i = 0; i < fields.Count; i++)
for (var i = 0; i < fields.Length; i++)
{
var field = fields[i];
if (field.IsReadonly) continue;
var line = $"{indentPrefix} {field.Name} = {GetVariableNameForExpression(field.Name)}";
sb.Append(line);

if (i < fields.Count - 1)
if (i < fields.Length - 1)
{
sb.AppendLine(",");
}
Expand All @@ -124,17 +127,18 @@ private static string GetStreamReaderLine(FieldData field, INamedTypeSymbol type
var typeName = type.Name;
if (field.IsEnum)
{
return $"({field.SemanticType.GetFullName()}) await stream.ReadEnumFromStreamAsync<{((INamedTypeSymbol)field.SemanticType).EnumUnderlyingType}>(buffer)";
return
$"({field.SemanticType.GetFullName()}) await stream.ReadEnumFromStreamAsync<{((INamedTypeSymbol) field.SemanticType).EnumUnderlyingType}>(buffer)";
}

if (field.IsArray && ((IArrayTypeSymbol)field.SemanticType).ElementType.Name == "Byte")
if (field.IsArray && ((IArrayTypeSymbol) field.SemanticType).ElementType.Name == "Byte")
{
return $"await stream.ReadByteArrayFromStreamAsync(buffer, {field.ArrayLength})";
}

if (typeName is "String")
{
var size = field.HasDynamicLength
var size = field.HasDynamicLength
? GetVariableNameForExpression(field.SizeFieldName!)
: field.ElementSize.ToString();
return $"await stream.ReadStringFromStreamAsync(buffer, (int){size})";
Expand All @@ -144,10 +148,12 @@ private static string GetStreamReaderLine(FieldData field, INamedTypeSymbol type
{
return $"await stream.ReadValueFromStreamAsync<{typeName}>(buffer)";
}

if (typeName is "Single" or "UInt32" or "Int32")
{
return $"await stream.ReadValueFromStreamAsync<{typeName}>(buffer)";
}

if (typeName is "Int64" or "UInt64" or "Double")
{
return $"await stream.ReadValueFromStreamAsync<{typeName}>(buffer)";
Expand All @@ -167,15 +173,17 @@ internal string GetMethodLine(FieldData field, ref int offset, StringBuilder dyn
var finalLine = field switch
{
// handle Custom[]
{ IsArray: true } => GetLineForArray(field, ref offset, dynamicOffset, tempDynamicOffset, indentPrefix,
{IsArray: true} => GetLineForArray(field, ref offset, dynamicOffset, tempDynamicOffset, indentPrefix,
isVariableMode, isStreamMode),
// handle string
{ SemanticType.Name: "String" } => GetValueForString(field, ref offset, dynamicOffset, tempDynamicOffset, isStreamMode),
{SemanticType.Name: "String"} => GetValueForString(field, ref offset, dynamicOffset, tempDynamicOffset,
isStreamMode),
// handle enum
{ IsEnum: true } => GetValueForSingleValue(field, (INamedTypeSymbol)field.SemanticType, ref offset,
{IsEnum: true} => GetValueForSingleValue(field, (INamedTypeSymbol) field.SemanticType, ref offset,
dynamicOffset, tempDynamicOffset, isStreamMode),
// misc
_ => GetLineForMisc(field, ref offset, dynamicOffset, tempDynamicOffset, indentPrefix, isVariableMode, isStreamMode)
_ => GetLineForMisc(field, ref offset, dynamicOffset, tempDynamicOffset, indentPrefix, isVariableMode,
isStreamMode)
};


Expand All @@ -193,8 +201,9 @@ private static string GetValueForString(FieldData fieldData, ref int offset, Str
{
if (isStreamMode)
{
return GetStreamReaderLine(fieldData, (INamedTypeSymbol)fieldData.SemanticType);
return GetStreamReaderLine(fieldData, (INamedTypeSymbol) fieldData.SemanticType);
}

var offsetStr = GetOffsetString(offset, dynamicOffset, tempDynamicOffset);
if (fieldData.SizeFieldName is not null)
{
Expand All @@ -211,16 +220,16 @@ private static string GetValueForString(FieldData fieldData, ref int offset, Str
private static string GetOffsetString(in int offset, StringBuilder dynamicOffset, string tempDynamicOffset,
int? arrayLength = null, bool doNotPrependOffsetVariable = false)
{
var prefix = doNotPrependOffsetVariable
? ""
var prefix = doNotPrependOffsetVariable
? ""
: "offset + ";

if (prefix is "" && dynamicOffset.Length == 0 && tempDynamicOffset is "")
{
return offset.ToString();
}


if (arrayLength.HasValue)
{
if (dynamicOffset.Length > 0)
Expand Down Expand Up @@ -293,7 +302,7 @@ private static string GetValueForSingleValue(FieldData field, INamedTypeSymbol n
{
return GetStreamReaderLine(field, namedTypeSymbol);
}

var cast = namedTypeSymbol.GetFullName();
var typeName = namedTypeSymbol.TypeKind is TypeKind.Enum
? namedTypeSymbol.EnumUnderlyingType!.Name
Expand Down Expand Up @@ -352,7 +361,8 @@ private string GetLineForMisc(FieldData field, ref int offset, StringBuilder dyn
}
else if (field.SemanticType is INamedTypeSymbol namedTypeSymbol)
{
return GetValueForSingleValue(field, namedTypeSymbol, ref offset, dynamicOffset, tempDynamicOffset, isStreamMode);
return GetValueForSingleValue(field, namedTypeSymbol, ref offset, dynamicOffset, tempDynamicOffset,
isStreamMode);
}

throw new ArgumentException($"Type of field is unknown: {field.SemanticType.GetFullName()}", nameof(field));
Expand All @@ -378,7 +388,8 @@ private string GetLineForArray(FieldData field, ref int offset, StringBuilder dy
}
else
{
return GetLineForDynamicArray(field, ref offset, dynamicOffset, tempDynamicOffset, arr, indentPrefix, isStreamMode);
return GetLineForDynamicArray(field, ref offset, dynamicOffset, tempDynamicOffset, arr, indentPrefix,
isStreamMode);
}
}

Expand Down Expand Up @@ -410,7 +421,7 @@ private string GetLineForDynamicArray(FieldData field, ref int offset,
}
else
{
var line = GetValueForSingleValue(field, (INamedTypeSymbol)arr.ElementType, ref offset, dynamicOffset,
var line = GetValueForSingleValue(field, (INamedTypeSymbol) arr.ElementType, ref offset, dynamicOffset,
$"{tempDynamicOffset} + {field.ElementSize} * i", isStreamMode);
sb.AppendLine($"{indent} {variableName}[i] = {line};");
}
Expand Down Expand Up @@ -449,8 +460,9 @@ private string GetLineForFixedArray(FieldData field, ref int offset,
}
else
{
var elementType = (INamedTypeSymbol)((IArrayTypeSymbol)field.SemanticType).ElementType;
var line = GetValueForSingleValue(field, elementType, ref offset, dynamicOffset, tempDynamicOffset, isStreamMode);
var elementType = (INamedTypeSymbol) ((IArrayTypeSymbol) field.SemanticType).ElementType;
var line = GetValueForSingleValue(field, elementType, ref offset, dynamicOffset, tempDynamicOffset,
isStreamMode);
offset += field.ElementSize;
sb.Append($"{indentPrefix} {line}");
}
Expand Down Expand Up @@ -491,7 +503,8 @@ private string GetLineForInitializer(ITypeSymbol t, ref int offset, StringBuilde
{
var member = recordParamMembers[ii];
var valueStr = isVariableMode
? GetMethodLine(member, ref offset, dynamicOffset, tempDynamicOffset, indentPrefix, isVariableMode, isStreamMode)
? GetMethodLine(member, ref offset, dynamicOffset, tempDynamicOffset, indentPrefix, isVariableMode,
isStreamMode)
: GetVariableNameForExpression(member.Name);
var line = $"{indentPrefix} {valueStr}";
line = TrimAssignmentRegex.Replace(line, "$1$2");
Expand All @@ -518,7 +531,8 @@ private string GetLineForInitializer(ITypeSymbol t, ref int offset, StringBuilde
{
var member = propertyMembers[ii];
var valueStr = isVariableMode
? GetMethodLine(member, ref offset, dynamicOffset, tempDynamicOffset, indentPrefix, isVariableMode, isStreamMode)
? GetMethodLine(member, ref offset, dynamicOffset, tempDynamicOffset, indentPrefix, isVariableMode,
isStreamMode)
: GetVariableNameForExpression(member.Name);
var line = $"{indentPrefix} {member.Name} = {valueStr}";

Expand Down Expand Up @@ -550,4 +564,4 @@ private static int GetSizeOfPrimitiveType(string name)
_ => throw new ArgumentOutOfRangeException(nameof(name), $"Don't know the size of {name}")
};
}
}
}
38 changes: 24 additions & 14 deletions src/Core.Networking.Generators/GeneratorContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

Expand All @@ -13,13 +14,14 @@ internal GeneratorContext(SerializerTypeInfo type)
Type = type;
}

internal IReadOnlyList<FieldData> GetFieldsOfType(TypeDeclarationSyntax type)
internal ImmutableArray<FieldData> GetFieldsOfType(TypeDeclarationSyntax type)
{
var fields = new List<FieldData>();
var fieldIndex = 0;
if (type is RecordDeclarationSyntax record)
{
fields.AddRange(record.ParameterList!.Parameters
.Select(x => BuildFieldData(type, x.Type!, x.Identifier, null, null, true, false))
.Select(x => BuildFieldData(type, x.Type!, x.Identifier, ref fieldIndex, null, null, true, false))
);
}

Expand All @@ -42,8 +44,8 @@ internal IReadOnlyList<FieldData> GetFieldsOfType(TypeDeclarationSyntax type)
}

var arrayLength = GetArrayLength(x);
return BuildFieldData(type, x.Type, x.Identifier, arrayLength, orderStr, false,
x is { ExpressionBody: not null }, stringLengthAttr);
return BuildFieldData(type, x.Type, x.Identifier, ref fieldIndex, arrayLength, orderStr, false,
x is {ExpressionBody: not null}, stringLengthAttr);
})
);

Expand Down Expand Up @@ -87,7 +89,7 @@ internal IReadOnlyList<FieldData> GetFieldsOfType(TypeDeclarationSyntax type)
}
}

return finalArr;
return finalArr.OrderBy(x => x.Order).ToImmutableArray();
}

private static int? GetArrayLength(PropertyDeclarationSyntax x)
Expand All @@ -102,7 +104,7 @@ internal IReadOnlyList<FieldData> GetFieldsOfType(TypeDeclarationSyntax type)
arrayCreationExpressionSyntax.Type.RankSpecifiers.Any() &&
arrayCreationExpressionSyntax.Type.RankSpecifiers.First().Sizes.OfType<LiteralExpressionSyntax>().Any())
{
return (int?)arrayCreationExpressionSyntax.Type.RankSpecifiers
return (int?) arrayCreationExpressionSyntax.Type.RankSpecifiers
.First().Sizes.OfType<LiteralExpressionSyntax>()
.First().Token.Value;
}
Expand All @@ -111,12 +113,13 @@ internal IReadOnlyList<FieldData> GetFieldsOfType(TypeDeclarationSyntax type)
}

private FieldData BuildFieldData(TypeDeclarationSyntax declaringType, TypeSyntax type, SyntaxToken name,
ref int fieldIndex,
int? arrayLength = null,
string? orderStr = null, bool isRecordParameter = false, bool isReadonly = false, int? stringLength = null)
{
var isArray = type is ArrayTypeSyntax;
var fieldType = GetTypeInfo(type)!;
var enumType = isArray ? null : (INamedTypeSymbol)fieldType;
var enumType = isArray ? null : (INamedTypeSymbol) fieldType;
var isEnum = enumType?.TypeKind is TypeKind.Enum;
string? sizeFieldName = null;

Expand Down Expand Up @@ -149,6 +152,10 @@ private FieldData BuildFieldData(TypeDeclarationSyntax declaringType, TypeSyntax
name.Parent!.GetLocation());
}

var order = int.TryParse(orderStr, out var orderVal) && orderVal != fieldIndex
? orderVal
: fieldIndex++;

return new FieldData
{
Name = name.Text,
Expand All @@ -161,7 +168,7 @@ private FieldData BuildFieldData(TypeDeclarationSyntax declaringType, TypeSyntax
ElementSize = elementSize,
IsRecordParameter = isRecordParameter,
IsReadonly = isReadonly,
Order = orderStr != null ? int.Parse(orderStr) : null,
Order = order,
SizeFieldName = sizeFieldName
};
}
Expand Down Expand Up @@ -261,7 +268,7 @@ internal static string GetTypeKeyWords(TypeDeclarationSyntax type)
var typeKeyWords = type switch
{
StructDeclarationSyntax => "struct",
RecordDeclarationSyntax { ClassOrStructKeyword.Text: "struct" } => "record struct",
RecordDeclarationSyntax {ClassOrStructKeyword.Text: "struct"} => "record struct",
RecordDeclarationSyntax => "record",
_ => "class"
};
Expand Down Expand Up @@ -299,7 +306,7 @@ public string GetHeaderForType(TypeDeclarationSyntax type)
return attr.ArgumentList.Arguments[0].ToString();
}

public string? GetSubHeaderForType(TypeDeclarationSyntax type)
public (byte Value, int Position)? GetSubHeaderForType(TypeDeclarationSyntax type)
{
var attr = type
.DescendantNodes()
Expand All @@ -308,14 +315,17 @@ public string GetHeaderForType(TypeDeclarationSyntax type)
.DescendantTokens()
.Any(dt => dt.IsKind(SyntaxKind.IdentifierToken) &&
GetTypeInfo(dt.Parent!).GetFullName() == GeneratorConstants.SUBPACKETATTRIBUTE_FULLNAME));
return attr?.ArgumentList?.Arguments[0].ToString();
var value = attr?.ArgumentList?.Arguments[0].ToString();
if (value is null) return null;
var position = attr?.ArgumentList?.Arguments.ElementAtOrDefault(1)?.ToString();
return (Convert.ToByte(value, 16), position is not null ? Convert.ToInt32(position) : 0);
}

public bool HasTypeSequence(TypeDeclarationSyntax type)
{
var attr = type.AttributeLists.SelectMany(x => x.Attributes).FirstOrDefault(x => x.Name.ToString() == "Packet");
return attr?.ArgumentList?.Arguments.Any(x =>
x.NameEquals?.Name.Identifier.Text == "Sequence" &&
((LiteralExpressionSyntax)x.Expression).Token.Text == "true") ?? false;
((LiteralExpressionSyntax) x.Expression).Token.Text == "true") ?? false;
}
}
}
Loading

0 comments on commit 4d7f107

Please sign in to comment.