Skip to content
This repository has been archived by the owner on Jul 9, 2024. It is now read-only.

Commit

Permalink
Merge pull request #148 from kasperk81/main
Browse files Browse the repository at this point in the history
Remove all LINQ usage from repo
  • Loading branch information
baywet authored May 24, 2024
2 parents 5df0e82 + d8288fd commit 5bfc246
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 24 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.2.4] - 2024-05-23

### Changed

- Remove all LINQ usage from repo

## [1.2.3] - 2024-05-23

### Changed
Expand Down
41 changes: 32 additions & 9 deletions src/FormParseNode.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Diagnostics;
using System.Reflection;
using System.Xml;
using System;
using System.Collections.Generic;
using Microsoft.Kiota.Abstractions;
using Microsoft.Kiota.Abstractions.Extensions;
using Microsoft.Kiota.Abstractions.Serialization;
Expand All @@ -21,14 +23,29 @@ public class FormParseNode : IParseNode
public FormParseNode(string rawValue)
{
RawValue = rawValue ?? throw new ArgumentNullException(nameof(rawValue));
Fields = rawValue.Split(new char[] {'&'}, StringSplitOptions.RemoveEmptyEntries)
.Select(static x => x.Split(new char[] {'='}, StringSplitOptions.RemoveEmptyEntries))
.Where(static x => x.Length == 2)
.Select(static x => (key: SanitizeKey(x[0]), value: x[1].Trim()))
.GroupBy(static x => x.key, StringComparer.OrdinalIgnoreCase)
.Select(static x => (key: x.Key, value: string.Join(",", x.Select(static y => y.value))))
.ToDictionary(static x => x.key, static x => x.value, StringComparer.OrdinalIgnoreCase);
Fields = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
char[] pairDelimiter = new char[] { '=' };
string[] pairs = rawValue.Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string pair in pairs)
{
string[] keyValue = pair.Split(pairDelimiter, StringSplitOptions.RemoveEmptyEntries);
if (keyValue.Length == 2)
{
string key = SanitizeKey(keyValue[0]);
string value = keyValue[1].Trim();

if (Fields.ContainsKey(key))
{
Fields[key] += $",{value}";
}
else
{
Fields.Add(key, value);
}
}
}
}

private static string SanitizeKey(string key) {
if (string.IsNullOrEmpty(key)) return key;
return Uri.UnescapeDataString(key.Trim());
Expand Down Expand Up @@ -137,7 +154,7 @@ public T GetObjectValue<T>(ParsableFactory<T> factory) where T : IParsable {
}
private void AssignFieldValues<T>(T item) where T : IParsable
{
if(!Fields.Any()) return;
if(Fields.Count == 0) return;
IDictionary<string, object>? itemAdditionalData = null;
if(item is IAdditionalDataHolder holder)
{
Expand Down Expand Up @@ -171,10 +188,13 @@ private void AssignFieldValues<T>(T item) where T : IParsable
}
}
}

/// <inheritdoc/>
public sbyte? GetSbyteValue() => sbyte.TryParse(DecodedValue, out var result) ? result : null;

/// <inheritdoc/>
public string GetStringValue() => DecodedValue;

/// <inheritdoc/>
public TimeSpan? GetTimeSpanValue() {
var rawString = DecodedValue;
Expand All @@ -184,8 +204,10 @@ private void AssignFieldValues<T>(T item) where T : IParsable
// Parse an ISO8601 duration.http://en.wikipedia.org/wiki/ISO_8601#Durations to a TimeSpan
return XmlConvert.ToTimeSpan(rawString);
}

/// <inheritdoc/>
public Time? GetTimeValue() => DateTime.TryParse(DecodedValue, out var result) ? new Time(result) : null;

Check warning on line 209 in src/FormParseNode.cs

View workflow job for this annotation

GitHub Actions / Build

Use a format provider when parsing date and time. (https://rules.sonarsource.com/csharp/RSPEC-6580)

#if NET5_0_OR_GREATER
IEnumerable<T?> IParseNode.GetCollectionOfEnumValues<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>()
#else
Expand All @@ -195,6 +217,7 @@ private void AssignFieldValues<T>(T item) where T : IParsable
foreach (var v in DecodedValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
yield return GetEnumValueInternal<T>(v);
}

#if NET5_0_OR_GREATER
T? IParseNode.GetEnumValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>()
#else
Expand All @@ -208,7 +231,7 @@ private void AssignFieldValues<T>(T item) where T : IParsable
{
if(string.IsNullOrEmpty(rawValue))
return null;
if(typeof(T).GetCustomAttributes<FlagsAttribute>().Any())
if (typeof(T).IsDefined(typeof(FlagsAttribute)))
{
ReadOnlySpan<char> valueSpan = rawValue.AsSpan();
int value = 0;
Expand Down
4 changes: 4 additions & 0 deletions src/FormParseNodeFactory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
using Microsoft.Kiota.Abstractions.Serialization;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.Kiota.Serialization.Form;

Expand Down
40 changes: 28 additions & 12 deletions src/FormSerializationWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
using Microsoft.Kiota.Abstractions;
using Microsoft.Kiota.Abstractions.Extensions;
using Microsoft.Kiota.Abstractions.Serialization;
using System.IO;
#if NET5_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
using System;
using System.Collections.Generic;

namespace Microsoft.Kiota.Serialization.Form;
/// <summary>Represents a serialization writer that can be used to write a form url encoded string.</summary>
Expand Down Expand Up @@ -89,30 +92,39 @@ private void WriteAnyValue(string? key, object value)

}
}

/// <inheritdoc/>
public void WriteBoolValue(string? key, bool? value) {
if(value.HasValue)
WriteStringValue(key, value.Value.ToString().ToLowerInvariant());
}

/// <inheritdoc/>
public void WriteByteArrayValue(string? key, byte[]? value) {
if(value != null)//empty array is meaningful
WriteStringValue(key, value.Length > 0 ? Convert.ToBase64String(value) : string.Empty);
}

/// <inheritdoc/>
public void WriteByteValue(string? key, byte? value) {
if(value.HasValue)
WriteIntValue(key, Convert.ToInt32(value.Value));
}

/// <inheritdoc/>
public void WriteCollectionOfObjectValues<T>(string? key, IEnumerable<T>? values) where T : IParsable => throw new InvalidOperationException("Form serialization does not support collections.");

/// <inheritdoc/>
public void WriteCollectionOfPrimitiveValues<T>(string? key, IEnumerable<T>? values)
{
if(values == null) return;
foreach(var value in values.Where(static x => x != null))
WriteAnyValue(key,value!);
if (values == null) return;
foreach (var value in values)
{
if (value != null)

Check warning on line 123 in src/FormSerializationWriter.cs

View workflow job for this annotation

GitHub Actions / Build

Use a comparison to 'default(T)' instead or add a constraint to 'T' so that it can't be a value type. (https://rules.sonarsource.com/csharp/RSPEC-2955)
WriteAnyValue(key, value);
}
}

/// <inheritdoc/>
public void WriteDateTimeOffsetValue(string? key, DateTimeOffset? value) {
if(value.HasValue)
Expand Down Expand Up @@ -162,18 +174,21 @@ public void WriteObjectValue<T>(string? key, T? value, params IParsable?[] addit
{
if(depth > 0) throw new InvalidOperationException("Form serialization does not support nested objects.");
depth++;
if(value == null && !additionalValuesToMerge.Any(static x => x != null)) return;
if (value == null && !Array.Exists(additionalValuesToMerge, static x => x is not null)) return;

Check warning on line 177 in src/FormSerializationWriter.cs

View workflow job for this annotation

GitHub Actions / Build

Use a comparison to 'default(T)' instead or add a constraint to 'T' so that it can't be a value type. (https://rules.sonarsource.com/csharp/RSPEC-2955)

if(value != null) {

Check warning on line 179 in src/FormSerializationWriter.cs

View workflow job for this annotation

GitHub Actions / Build

Use a comparison to 'default(T)' instead or add a constraint to 'T' so that it can't be a value type. (https://rules.sonarsource.com/csharp/RSPEC-2955)
OnBeforeObjectSerialization?.Invoke(value);
OnStartObjectSerialization?.Invoke(value, this);
value.Serialize(this);
}
foreach(var additionalValueToMerge in additionalValuesToMerge.Where(static x => x != null))
foreach (var additionalValueToMerge in additionalValuesToMerge)
{
OnBeforeObjectSerialization?.Invoke(additionalValueToMerge!);
OnStartObjectSerialization?.Invoke(additionalValueToMerge!, this);
additionalValueToMerge!.Serialize(this);
OnAfterObjectSerialization?.Invoke(additionalValueToMerge!);
if (additionalValueToMerge is null) continue;

OnBeforeObjectSerialization?.Invoke(additionalValueToMerge);
OnStartObjectSerialization?.Invoke(additionalValueToMerge, this);
additionalValueToMerge.Serialize(this);
OnAfterObjectSerialization?.Invoke(additionalValueToMerge);
}
if(value != null)

Check warning on line 193 in src/FormSerializationWriter.cs

View workflow job for this annotation

GitHub Actions / Build

Use a comparison to 'default(T)' instead or add a constraint to 'T' so that it can't be a value type. (https://rules.sonarsource.com/csharp/RSPEC-2955)
OnAfterObjectSerialization?.Invoke(value);
Expand Down Expand Up @@ -224,6 +239,7 @@ public void WriteCollectionOfEnumValues<T>(string? key, IEnumerable<T?>? values)
if(valueNames is not null)
WriteStringValue(key, valueNames.ToString());
}

/// <inheritdoc/>
#if NET5_0_OR_GREATER
public void WriteEnumValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>(string? key, T? value) where T : struct, Enum
Expand All @@ -233,13 +249,13 @@ public void WriteEnumValue<T>(string? key, T? value) where T : struct, Enum
{
if(value.HasValue)
{
if(typeof(T).GetCustomAttributes<FlagsAttribute>().Any())
if (typeof(T).IsDefined(typeof(FlagsAttribute)))
{
var values =
T[] values =
#if NET5_0_OR_GREATER
Enum.GetValues<T>();
#else
Enum.GetValues(typeof(T)).Cast<T>();
(T[])Enum.GetValues(typeof(T));
#endif
StringBuilder valueNames = new StringBuilder();
foreach(var x in values)
Expand Down
3 changes: 2 additions & 1 deletion src/FormSerializationWriterFactory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Kiota.Abstractions.Serialization;
using System;

namespace Microsoft.Kiota.Serialization.Form;
/// <summary>Represents a serialization writer factory that can be used to create a form url encoded serialization writer.</summary>
Expand All @@ -14,4 +15,4 @@ public ISerializationWriter GetSerializationWriter(string contentType) {
throw new ArgumentOutOfRangeException($"expected a {ValidContentType} content type");
return new FormSerializationWriter();
}
}
}
3 changes: 1 addition & 2 deletions src/Microsoft.Kiota.Serialization.Form.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@
<Authors>Microsoft</Authors>
<TargetFrameworks>netstandard2.0;netstandard2.1;net5.0;net6.0;net8.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<PackageIconUrl>http://go.microsoft.com/fwlink/?LinkID=288890</PackageIconUrl>
<RepositoryUrl>https://github.com/microsoft/kiota-serialization-form-dotnet</RepositoryUrl>
<PackageProjectUrl>https://aka.ms/kiota/docs</PackageProjectUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<Deterministic>true</Deterministic>
<VersionPrefix>1.2.3</VersionPrefix>
<VersionPrefix>1.2.4</VersionPrefix>
<VersionSuffix></VersionSuffix>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand Down

0 comments on commit 5bfc246

Please sign in to comment.