From 0f648a04896809e00cf148d9e1106a100b50930d Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 18 May 2024 14:05:48 +0200 Subject: [PATCH 1/3] Remove LINQ usage from Enum conversion from/to string. This prevents unintended and unbound generic specialization expansion in the NativeAOT compiler. --- src/JsonParseNode.cs | 21 +++++++++++++++------ src/JsonSerializationWriter.cs | 25 ++++++++++++++++++------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/JsonParseNode.cs b/src/JsonParseNode.cs index f91286e..dacb1db 100644 --- a/src/JsonParseNode.cs +++ b/src/JsonParseNode.cs @@ -224,12 +224,21 @@ public JsonParseNode(JsonElement node, KiotaJsonSerializationContext jsonSeriali rawValue = ToEnumRawName(rawValue!); if(type.GetCustomAttributes().Any()) { - return (T)(object)rawValue! - .Split(',') - .Select(x => Enum.TryParse(x, true, out var result) ? result : (T?)null) - .Where(x => !x.Equals(null)) - .Select(x => (int)(object)x!) - .Sum(); + ReadOnlySpan valueSpan = rawValue.AsSpan(); + int value = 0; + while(valueSpan.Length > 0) + { + int commaIndex = valueSpan.IndexOf(','); + ReadOnlySpan valueNameSpan = commaIndex < 0 ? valueSpan : valueSpan.Slice(0, commaIndex); +#if NET6_0_OR_GREATER + if(Enum.TryParse(valueNameSpan, true, out var result)) +#else + if(Enum.TryParse(valueNameSpan.ToString(), true, out var result)) +#endif + value |= (int)(object)result; + valueSpan = commaIndex < 0 ? ReadOnlySpan.Empty : valueSpan.Slice(commaIndex + 1); + } + return (T)(object)value; } else return Enum.TryParse(rawValue, true,out var result) ? result : null; diff --git a/src/JsonSerializationWriter.cs b/src/JsonSerializationWriter.cs index 4674569..acaa4fd 100644 --- a/src/JsonSerializationWriter.cs +++ b/src/JsonSerializationWriter.cs @@ -13,6 +13,8 @@ using Microsoft.Kiota.Abstractions.Extensions; using Microsoft.Kiota.Abstractions; using System.Xml; +using System.Text; + #if NET5_0_OR_GREATER using System.Diagnostics.CodeAnalysis; #endif @@ -278,16 +280,25 @@ public void WriteEnumValue(string? key, T? value) where T : struct, Enum if(value.HasValue) { if(typeof(T).GetCustomAttributes().Any()) - WriteStringValue(null, + { + var values = #if NET5_0_OR_GREATER - Enum.GetValues() + Enum.GetValues(); #else - Enum.GetValues(typeof(T)) - .Cast() + Enum.GetValues(typeof(T)).Cast(); #endif - .Where(x => value.Value.HasFlag(x)) - .Select(GetEnumName) - .Aggregate((x, y) => $"{x},{y}")); + StringBuilder valueNames = new StringBuilder(); + foreach (var x in values) + { + if(value.Value.HasFlag(x) && GetEnumName(x) is string valueName) + { + if (valueNames.Length > 0) + valueNames.Append(","); + valueNames.Append(valueName); + } + } + WriteStringValue(null, valueNames.ToString()); + } else WriteStringValue(null, GetEnumName(value.Value)); } } From fa872ab1375938073d897958f2878bbefc4cd632 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 20 May 2024 10:05:55 +0200 Subject: [PATCH 2/3] Update CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cdbf0b..73c2ec4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.3.0] - 2024-05-13 +### Changed + +- Updated serialization and deserialization of enums to remove LINQ to resolve NativeAOT compatibility issue + ### Added - Implements IAsyncParseNodeFactory interface which adds async support From b39244ee5e2c0e38aeeb0bb0f171a0fe73232e06 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 20 May 2024 10:22:46 +0200 Subject: [PATCH 3/3] Bump version number --- CHANGELOG.md | 4 +++- src/Microsoft.Kiota.Serialization.Json.csproj | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73c2ec4..53fc413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [1.3.0] - 2024-05-13 +## [1.3.1] - 2024-05-20 ### Changed - Updated serialization and deserialization of enums to remove LINQ to resolve NativeAOT compatibility issue +## [1.3.0] - 2024-05-13 + ### Added - Implements IAsyncParseNodeFactory interface which adds async support diff --git a/src/Microsoft.Kiota.Serialization.Json.csproj b/src/Microsoft.Kiota.Serialization.Json.csproj index 623331d..10df288 100644 --- a/src/Microsoft.Kiota.Serialization.Json.csproj +++ b/src/Microsoft.Kiota.Serialization.Json.csproj @@ -15,7 +15,7 @@ https://aka.ms/kiota/docs true true - 1.3.0 + 1.3.1 true true