Skip to content

Commit

Permalink
New API key for nuget + modernize code base
Browse files Browse the repository at this point in the history
  • Loading branch information
MichalBrylka committed May 30, 2022
1 parent e4f1a73 commit 2b36469
Show file tree
Hide file tree
Showing 19 changed files with 133 additions and 72 deletions.
2 changes: 1 addition & 1 deletion Benchmarks/Benchmarks.csproj
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<TargetFrameworks>net6.0</TargetFrameworks>

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

Expand Down
77 changes: 77 additions & 0 deletions Benchmarks/EnumBench.cs
Expand Up @@ -463,6 +463,77 @@ public DaysOfWeek EnumTransformer()
return current;
}
}

/* .NET Core 3.1.22 (CoreCLR 4.700.21.56803, CoreFX 4.700.21.57101), X64 RyuJIT
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---------------- |---------:|----------:|----------:|------:|--------:|------:|------:|------:|----------:|
| EnumTransformer | 2.859 us | 0.0462 us | 0.0409 us | 1.00 | 0.00 | - | - | - | - |
| Generated | 3.161 us | 0.0523 us | 0.0489 us | 1.11 | 0.02 | - | - | - | - |
.NET Core 6.0.1 (CoreCLR 6.0.121.56705, CoreFX 6.0.121.56705), X64 RyuJIT
| Method | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---------------- |---------:|----------:|----------:|------:|------:|------:|------:|----------:|
| EnumTransformer | 2.648 us | 0.0419 us | 0.0392 us | 1.00 | - | - | - | - |
| Generated | 2.226 us | 0.0144 us | 0.0128 us | 0.84 | - | - | - | - |*/
[MemoryDiagnoser]
public class EnumParserBenchNonFlagGenerated
{
public enum DayOfWeek : byte
{
None ,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
}

public static string[] AllEnums =
Enumerable.Range(0, 50).Select(i => ((DayOfWeek)i).ToString("G").Replace(" ", "")).ToArray();

private static readonly ITransformer<DayOfWeek> _parser = TextTransformer.Default.GetTransformer<DayOfWeek>();


[Benchmark(Baseline = true)]
public DayOfWeek EnumTransformer()
{
DayOfWeek current = default;
for (int i = AllEnums.Length - 1; i >= 0; i--)
{
var text = AllEnums[i];
current = _parser.Parse(text.AsSpan());
}
return current;
}

[Benchmark]
public DayOfWeek Generated()
{
DayOfWeek current = default;
for (int i = AllEnums.Length - 1; i >= 0; i--)
{
var text = AllEnums[i];
current = ParseIgnoreCase(text);
}
return current;
}

private static DayOfWeek ParseIgnoreCase(string text) =>
text switch
{
{ } s when s.Equals(nameof(DayOfWeek.None), StringComparison.OrdinalIgnoreCase) => DayOfWeek.None,
{ } s when s.Equals(nameof(DayOfWeek.Monday), StringComparison.OrdinalIgnoreCase) => DayOfWeek.Monday,
{ } s when s.Equals(nameof(DayOfWeek.Tuesday), StringComparison.OrdinalIgnoreCase) => DayOfWeek.Tuesday,
{ } s when s.Equals(nameof(DayOfWeek.Wednesday), StringComparison.OrdinalIgnoreCase) => DayOfWeek.Wednesday,
{ } s when s.Equals(nameof(DayOfWeek.Thursday), StringComparison.OrdinalIgnoreCase) => DayOfWeek.Thursday,
{ } s when s.Equals(nameof(DayOfWeek.Friday), StringComparison.OrdinalIgnoreCase) => DayOfWeek.Friday,
{ } s when s.Equals(nameof(DayOfWeek.Saturday), StringComparison.OrdinalIgnoreCase) => DayOfWeek.Saturday,
{ } s when s.Equals(nameof(DayOfWeek.Sunday), StringComparison.OrdinalIgnoreCase) => DayOfWeek.Sunday,
_ => Enum.Parse<DayOfWeek>(text, true)
};
}

[MemoryDiagnoser]
public class ToEnumBench
Expand Down Expand Up @@ -665,6 +736,12 @@ public DaysOfWeek ExternTest()
}*/
}

/* NET Core 3.1
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|----------------- |----------:|----------:|----------:|------:|--------:|------:|------:|------:|----------:|
| HasFlag_Native | 0.2376 ns | 0.0026 ns | 0.0023 ns | 0.98 | 0.03 | - | - | - | - |
| HasFlags_Dynamic | 5.4291 ns | 0.1069 ns | 0.2183 ns | 22.68 | 1.01 | - | - | - | - |
| HasFlags_Bitwise | 0.2407 ns | 0.0043 ns | 0.0059 ns | 1.00 | 0.00 | - | - | - | - | */
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net47)]
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
Expand Down
13 changes: 6 additions & 7 deletions Nemesis.TextParsers.Tests/RecordsTests.cs
Expand Up @@ -4,12 +4,12 @@

using NUnit.Framework;
#if !NET
using NotNull = JetBrains.Annotations.NotNullAttribute;
using NotNull = JetBrains.Annotations.NotNullAttribute;
#else
using NotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute;
// ReSharper disable NotAccessedPositionalProperty.Local
using NotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute;
#endif

// ReSharper disable NotAccessedPositionalProperty.Local

namespace Nemesis.TextParsers.Tests
{
Expand Down Expand Up @@ -51,13 +51,12 @@ public void ShouldBeAbleToReparseComplexRecords()
Assert.That(parsed.Animals[1].Name, Is.EqualTo("Lizard"));
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("ReSharper", "UnusedMember.Local")]
enum Habitat { Terrestrial, Aquatic, Amphibian }
[System.Diagnostics.CodeAnalysis.SuppressMessage("ReSharper", "UnusedMember.Local")]
enum Diet { Carnivorous, Herbivorous, Omnivorous }
enum Habitat { Terrestrial/*, Aquatic, Amphibian*/ }
enum Diet { Carnivorous/*, Herbivorous, Omnivorous*/ }

record Vertebrate(string Name)
{
[JetBrains.Annotations.UsedImplicitly]
public Vertebrate() : this("") { }
}

Expand Down
1 change: 1 addition & 0 deletions Nemesis.TextParsers/01_Contracts.cs
Expand Up @@ -6,6 +6,7 @@

namespace Nemesis.TextParsers
{
//TODO support nullable NRT
[PublicAPI]
public interface ITransformer
{
Expand Down
10 changes: 4 additions & 6 deletions Nemesis.TextParsers/Parsers/03a_KeyValuePair.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Reflection;

using JetBrains.Annotations;

using Nemesis.TextParsers.Runtime;
using Nemesis.TextParsers.Settings;
using Nemesis.TextParsers.Utils;
Expand Down Expand Up @@ -29,7 +31,7 @@ public ITransformer<TPair> CreateTransformer<TPair>()

var m = _createTransformerCoreMethod.MakeGenericMethod(keyType, valueType);

return (ITransformer<TPair>) m.Invoke(this, null);
return (ITransformer<TPair>)m.Invoke(this, null);
}

private static readonly MethodInfo _createTransformerCoreMethod = Method.OfExpression<
Expand Down Expand Up @@ -95,11 +97,7 @@ public override string Format(KeyValuePair<TKey, TValue> element)
}
}

public override KeyValuePair<TKey, TValue> GetEmpty() =>
new KeyValuePair<TKey, TValue>(
_keyTransformer.GetEmpty(),
_valueTransformer.GetEmpty()
);
public override KeyValuePair<TKey, TValue> GetEmpty() => new(_keyTransformer.GetEmpty(), _valueTransformer.GetEmpty());
}

public bool CanHandle(Type type) =>
Expand Down
3 changes: 1 addition & 2 deletions Nemesis.TextParsers/Parsers/03b_ValueTuple.cs
Expand Up @@ -76,8 +76,7 @@ private ConstructorInfo GetConstructor(Type transformerType, in int arity, Type[

private bool IsSupported(Type type, out Type[] elementTypes) =>
TypeMeta.TryGetValueTupleElements(type, out elementTypes) &&
elementTypes != null &&
elementTypes.Length is { } arity && arity <= MAX_ARITY && arity >= 1 &&
elementTypes is {Length: <= MAX_ARITY and >= 1} &&
elementTypes.All(t => _transformerStore.IsSupportedForTransformation(t));

public sbyte Priority => 12;
Expand Down
18 changes: 5 additions & 13 deletions Nemesis.TextParsers/Parsers/04_FactoryMethods.cs
Expand Up @@ -96,27 +96,19 @@ private ITransformer<TElement> GetTransformer<TElement>()

return methodInputType == typeof(string)
? new StringFactoryTransformer<TElement>(body, inputParameter, formatter, emptyValueProvider, nullValueProvider)
: (ITransformer<TElement>)
new SpanFactoryTransformer<TElement>(body, inputParameter, formatter, emptyValueProvider, nullValueProvider);
: new SpanFactoryTransformer<TElement>(body, inputParameter, formatter, emptyValueProvider, nullValueProvider);


MethodInfo FindMethodWithParameterType(Type paramType) =>
conversionMethods.FirstOrDefault(m =>
m.GetParameters() is { } @params && @params.Length == 1 &&
@params[0].ParameterType == paramType);
m.GetParameters() is {Length: 1} @params && @params[0].ParameterType == paramType);
}


private static bool FactoryMethodPredicate(MethodInfo m, Type returnType, string factoryMethodName) =>
m.Name == factoryMethodName &&
m.GetParameters() is { } @params && @params.Length == 1 &&
@params[0].ParameterType is { } firstParamType &&
(
firstParamType == typeof(string)
||
firstParamType == typeof(ReadOnlySpan<char>)
)
&&
m.GetParameters() is {Length: 1} @params &&
@params[0].ParameterType is { } firstParamType &&
(firstParamType == typeof(string) || firstParamType == typeof(ReadOnlySpan<char>)) &&
(
m.ReturnType == returnType
||
Expand Down
16 changes: 7 additions & 9 deletions Nemesis.TextParsers/Parsers/05_Enums.cs
Expand Up @@ -5,20 +5,18 @@
using System.Reflection;
using System.Runtime.CompilerServices;

using JetBrains.Annotations;

using Nemesis.TextParsers.Runtime;
using Nemesis.TextParsers.Settings;
#if !NET
using NotNull = JetBrains.Annotations.NotNullAttribute;
using NotNull = JetBrains.Annotations.NotNullAttribute;
#else
using NotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute;
using NotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute;
#endif


namespace Nemesis.TextParsers.Parsers
{
[UsedImplicitly]
[JetBrains.Annotations.UsedImplicitly]
public sealed class EnumTransformerCreator : ICanCreateTransformer
{
private readonly EnumSettings _settings;
Expand Down Expand Up @@ -86,7 +84,7 @@ public sealed class EnumTransformer<TEnum, TUnderlying, TNumberHandler> : Transf
private readonly EnumTransformerHelper.ParserDelegate<TUnderlying> _elementParser;

// ReSharper disable once RedundantVerbatimPrefix
public EnumTransformer([@NotNull] TNumberHandler numberHandler, EnumSettings settings)
public EnumTransformer([NotNull] TNumberHandler numberHandler, EnumSettings settings)
{
_numberHandler = numberHandler ?? throw new ArgumentNullException(nameof(numberHandler));
_settings = settings;
Expand Down Expand Up @@ -124,8 +122,8 @@ private TUnderlying ParseElement(ReadOnlySpan<char> input)

if (_settings.AllowParsingNumerics)
{
bool isNumeric = input.Length > 0 && input[0] is { } first &&
(char.IsDigit(first) || first == '-' || first == '+');
bool isNumeric = input.Length > 0 && input[0] is var first &&
(char.IsDigit(first) || first is '-' or '+');

return isNumeric && _numberHandler.TryParse(in input, out var number)
? number
Expand Down Expand Up @@ -222,7 +220,7 @@ internal static class EnumTransformerHelper

private static Expression IfThenElseJoin<TResult>(IReadOnlyList<(Expression Condition, TResult value)> expressionList, Expression lastElse, LabelTarget exitTarget)
{
if (expressionList != null && expressionList.Count > 0)
if (expressionList is {Count: > 0})
{
Expression @else = lastElse;

Expand Down
6 changes: 3 additions & 3 deletions Nemesis.TextParsers/Parsers/09_Collection.cs
Expand Up @@ -105,13 +105,13 @@ protected override TCollection ParseCore(in ReadOnlySpan<char> input)
case CollectionKind.SortedSet:
{
ISet<TElement> result = _kind == CollectionKind.HashSet
? (ISet<TElement>)new HashSet<TElement>(
? new HashSet<TElement>(
#if NETSTANDARD2_0 || NETFRAMEWORK

#else
capacity
capacity
#endif
)
)
: new SortedSet<TElement>();

foreach (var part in stream)
Expand Down
14 changes: 5 additions & 9 deletions Nemesis.TextParsers/Parsers/10_Deconstructable.cs
Expand Up @@ -9,9 +9,9 @@
using Builder = Nemesis.TextParsers.Parsers.DeconstructionTransformerBuilder;
using PublicAPI = JetBrains.Annotations.PublicAPIAttribute;
#if !NET
using NotNull = JetBrains.Annotations.NotNullAttribute;
using NotNull = JetBrains.Annotations.NotNullAttribute;
#else
using NotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute;
using NotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute;
#endif


Expand All @@ -33,8 +33,7 @@ public ITransformer<TDeconstructable> CreateTransformer<TDeconstructable>()

public bool CanHandle(Type type) =>
Builder.TryGetDefaultDeconstruct(type, out _, out var ctor) &&
ctor.GetParameters() is { } cp && cp.Length > 0 &&
cp.All(pi => _transformerStore.IsSupportedForTransformation(pi.ParameterType))
ctor.GetParameters() is {Length: > 0} cp && cp.All(pi => _transformerStore.IsSupportedForTransformation(pi.ParameterType))
;

public sbyte Priority => 110;
Expand All @@ -55,7 +54,6 @@ public enum DeconstructionMethod : byte
ProvidedDeconstructMethod = 1,
}

//TODO rework as record + WithBorders + WithoutBorders methods
public sealed class DeconstructionTransformerBuilder
{
private readonly ITransformerStore _transformerStore;
Expand Down Expand Up @@ -88,7 +86,7 @@ public static Builder GetDefault(ITransformerStore transformerStore)
}

public static Builder FromSettings(DeconstructableSettings settings, ITransformerStore transformerStore) =>
new Builder(transformerStore,
new(transformerStore,
settings.Delimiter,
settings.NullElementMarker,
settings.EscapingSequenceStart,
Expand Down Expand Up @@ -470,9 +468,7 @@ Expression GetConvertedSource()
{
var decoSourceType = deconstruct.GetParameters()[0].ParameterType;

return element.Type == decoSourceType
? (Expression)element
: Expression.Convert(element, decoSourceType);
return element.Type == decoSourceType ? element : Expression.Convert(element, decoSourceType);
}

var expressions = new List<Expression>(7 + 2 * arity)
Expand Down
2 changes: 1 addition & 1 deletion Nemesis.TextParsers/ParsingPairSequence.cs
Expand Up @@ -26,7 +26,7 @@ public ParsingPairSequence(in TokenSequence<char> tokenSource, char escapingSequ
}
#endregion

public ParsingPairSequenceEnumerator GetEnumerator() => new ParsingPairSequenceEnumerator(_tokenSource,
public ParsingPairSequenceEnumerator GetEnumerator() => new(_tokenSource,
_escapingSequenceStart, _nullElementMarker, _dictionaryPairsDelimiter, _dictionaryKeyValueDelimiter);

public ref struct ParsingPairSequenceEnumerator
Expand Down
9 changes: 4 additions & 5 deletions Nemesis.TextParsers/ParsingSequence.cs
Expand Up @@ -22,7 +22,7 @@ namespace Nemesis.TextParsers
_sequenceDelimiter = sequenceDelimiter;
}

public ParsingSequenceEnumerator GetEnumerator() => new ParsingSequenceEnumerator(_tokenSource, _escapingSequenceStart, _nullElementMarker, _sequenceDelimiter);
public ParsingSequenceEnumerator GetEnumerator() => new(_tokenSource, _escapingSequenceStart, _nullElementMarker, _sequenceDelimiter);

public ref struct ParsingSequenceEnumerator
{
Expand Down Expand Up @@ -121,12 +121,11 @@ public void Deconstruct(out bool isDefault, out ReadOnlySpan<char> text)
text = Text;
}

public static ParserInput FromDefault() => new ParserInput(true, default);
public static ParserInput FromDefault() => new(true, default);

public static ParserInput FromText(ReadOnlySpan<char> text) => new ParserInput(false, text);
public static ParserInput FromText(ReadOnlySpan<char> text) => new(false, text);

public T ParseWith<T>(ITransformer<T> transformer)
=> IsDefault ? default : transformer.Parse(Text);
public T ParseWith<T>(ITransformer<T> transformer) => IsDefault ? default : transformer.Parse(Text);

public override string ToString() => IsDefault ? "<DEFAULT>" : Text.ToString();
}
Expand Down
4 changes: 2 additions & 2 deletions Nemesis.TextParsers/SpanParserHelper.cs
Expand Up @@ -10,12 +10,12 @@ public static class SpanParserHelper
public static TokenSequence<T> Tokenize<T>(this in ReadOnlySpan<T> sequence, T separator, T escapingElement,
bool emptySequenceYieldsEmpty)
where T : IEquatable<T> =>
new TokenSequence<T>(sequence, separator, escapingElement, emptySequenceYieldsEmpty);
new(sequence, separator, escapingElement, emptySequenceYieldsEmpty);

[PureMethod]
public static ParsingSequence PreParse(this in TokenSequence<char> tokenSource, char escapingElement,
char nullElement, char sequenceDelimiter) =>
new ParsingSequence(tokenSource, escapingElement, nullElement, sequenceDelimiter);
new(tokenSource, escapingElement, nullElement, sequenceDelimiter);



Expand Down

0 comments on commit 2b36469

Please sign in to comment.