Skip to content

Commit

Permalink
Merge pull request #112 from Cysharp/hadashiA/netstandard20
Browse files Browse the repository at this point in the history
Add netstandard2.0 to the targets
  • Loading branch information
neuecc authored Nov 17, 2023
2 parents 03e56d8 + c19df38 commit fd90949
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 35 deletions.
8 changes: 4 additions & 4 deletions src/ZLogger/Formatters/PlainTextZLoggerFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,17 @@ static void Write(IBufferWriter<byte> writer, ReadOnlySpan<byte> message1, strin
{
var span = writer.GetSpan(message1.Length + Encoding.UTF8.GetMaxByteCount(message2.Length));
message1.CopyTo(span);
var written2 = Encoding.UTF8.GetBytes(message2, span.Slice(message1.Length));
var written2 = Encoding.UTF8.GetBytes(message2.AsSpan(), span.Slice(message1.Length));
writer.Advance(message1.Length + written2);
}

static void Write(IBufferWriter<byte> writer, string message1, string message2, string message3)
{
var span = writer.GetSpan(Encoding.UTF8.GetMaxByteCount(message1.Length + message2.Length + message3.Length));

var written1 = Encoding.UTF8.GetBytes(message1, span);
var written2 = Encoding.UTF8.GetBytes(message2, span.Slice(written1));
var written3 = Encoding.UTF8.GetBytes(message3, span.Slice(written1 + written2));
var written1 = Encoding.UTF8.GetBytes(message1.AsSpan(), span);
var written2 = Encoding.UTF8.GetBytes(message2.AsSpan(), span.Slice(written1));
var written3 = Encoding.UTF8.GetBytes(message3.AsSpan(), span.Slice(written1 + written2));
writer.Advance(written1 + written2 + written3);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/ZLogger/Formatters/SystemTextJsonZLoggerFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public void FormatLogEntry<TEntry>(IBufferWriter<byte> writer, TEntry entry) whe
// If `BeginScope(format, arg1, arg2)` style is used, the first argument `format` string is passed with this name
if (x.Key == "{OriginalFormat}") continue;

WriteMutatedJsonKeyName(x.Key, jsonWriter, KeyNameMutator);
WriteMutatedJsonKeyName(x.Key.AsSpan(), jsonWriter, KeyNameMutator);

if (x.Value is { } value)
{
Expand Down
27 changes: 13 additions & 14 deletions src/ZLogger/Internal/EnumDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,14 @@ public static EnumDictionary Create<T>()
{
// dictionary key is enumValue, value is name.
var unboxedEnumValue = (T)enumValue;
var key = MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As<T, byte>(ref unboxedEnumValue), Unsafe.SizeOf<T>()).ToArray();

var keySpan =
#if NETSTANDARD2_0
Shims.CreateReadOnlySpan(ref Unsafe.As<T, byte>(ref unboxedEnumValue), Unsafe.SizeOf<T>());
#else
MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As<T, byte>(ref unboxedEnumValue), Unsafe.SizeOf<T>());
#endif
var key = keySpan.ToArray();

var value1 = Encoding.UTF8.GetBytes(name);
var value2 = JsonEncodedText.Encode(value1);
Expand Down Expand Up @@ -154,20 +161,12 @@ static int GetBytesHashCode(ReadOnlySpan<byte> bytes)
}
}

readonly struct Entry
readonly struct Entry(byte[] key, string name, byte[] utf8Name, JsonEncodedText jsonEncoded)
{
public readonly byte[] Key;
public readonly string Name;
public readonly byte[] Utf8Name;
public readonly JsonEncodedText JsonEncoded;

public Entry(byte[] key, string name, byte[] utf8Name, JsonEncodedText jsonEncoded)
{
Key = key;
Name = name;
Utf8Name = utf8Name;
JsonEncoded = jsonEncoded;
}
public readonly byte[] Key = key;
public readonly string Name = name;
public readonly byte[] Utf8Name = utf8Name;
public readonly JsonEncodedText JsonEncoded = jsonEncoded;

// for debugging
public override string ToString()
Expand Down
64 changes: 58 additions & 6 deletions src/ZLogger/Internal/MagicalBox.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Buffers;
using System;
using System.Buffers;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand All @@ -23,7 +24,7 @@ public MagicalBox(byte[] storage)

public bool TryWrite<T>(T value, out int offset)
{
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
if (!IsSupportedType<T>())
{
offset = 0;
return false;
Expand All @@ -47,7 +48,7 @@ public bool TryWrite<T>(T value, out int offset)

public bool TryRead<T>(int offset, out T value)
{
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>()
if (!IsSupportedType<T>()
|| offset < 0
|| (storage.Length < offset + Unsafe.SizeOf<T>()))
{
Expand Down Expand Up @@ -77,7 +78,11 @@ public T Read<T>(int offset)
public ReadOnlySpan<byte> ReadRawEnumValue(Type type, int offset)
{
var (_, size, _) = ReaderCache.GetEnumDictionaryAndValueSize(type);
#if NETSTANDARD2_0
return Shims.CreateReadOnlySpan(ref storage[offset], size);
#else
return MemoryMarshal.CreateReadOnlySpan(ref storage[offset], size);
#endif
}

public bool TryReadTo(Type type, int offset, int alignment, string? format, ref Utf8StringWriter<IBufferWriter<byte>> handler)
Expand Down Expand Up @@ -136,7 +141,12 @@ public bool TryReadTo(Type type, int offset, int alignment, string? format, ref
if (type.IsEnum)
{
var (dict, size, converter) = ReaderCache.GetEnumDictionaryAndValueSize(type);
var rawValue = MemoryMarshal.CreateReadOnlySpan(ref storage[offset], size);
var rawValue =
#if NETSTANDARD2_0
Shims.CreateReadOnlySpan(ref storage[offset], size);
#else
MemoryMarshal.CreateReadOnlySpan(ref storage[offset], size);
#endif
var name = dict.GetUtf8Name(rawValue);
if (name == null)
{
Expand Down Expand Up @@ -234,7 +244,11 @@ public bool TryReadTo(Type type, int offset, int alignment, string? format, ref
if (type.IsEnum)
{
var (dict, size, converter) = ReaderCache.GetEnumDictionaryAndValueSize(type);
#if NETSTANDARD2_0
var rawValue = Shims.CreateReadOnlySpan(ref storage[offset], size);
#else
var rawValue = MemoryMarshal.CreateReadOnlySpan(ref storage[offset], size);
#endif
var name = dict.GetStringName(rawValue);
if (name == null)
{
Expand Down Expand Up @@ -334,7 +348,12 @@ public bool TryReadTo(Type type, int offset, Utf8JsonWriter jsonWriter)
if (type.IsEnum)
{
var (dict, size, converter) = ReaderCache.GetEnumDictionaryAndValueSize(type);
var rawValue = MemoryMarshal.CreateReadOnlySpan(ref storage[offset], size);
var rawValue =
#if NETSTANDARD2_0
Shims.CreateReadOnlySpan(ref storage[offset], size);
#else
MemoryMarshal.CreateReadOnlySpan(ref storage[offset], size);
#endif
var name = dict.GetJsonEncodedName(rawValue);
if (name == null)
{
Expand Down Expand Up @@ -362,6 +381,39 @@ public bool TryReadTo(Type type, int offset, Utf8JsonWriter jsonWriter)
return true;
}

static bool IsSupportedType<T>()
{
#if NETSTANDARD2_0
var type = typeof(T);
var code = Type.GetTypeCode(type);
switch (code)
{
case TypeCode.Boolean:
case TypeCode.Byte:
case TypeCode.Char:
case TypeCode.DateTime:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.SByte:
case TypeCode.Single:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return true;
}
if (type.IsEnum || type == typeof(Guid) || type == typeof(DateTimeOffset))
{
return true;
}
return false;
#else
return !RuntimeHelpers.IsReferenceOrContainsReferences<T>();
#endif
}

static void ThrowArgumentOutOfRangeException()
{
throw new ArgumentOutOfRangeException();
Expand Down Expand Up @@ -391,7 +443,7 @@ static class ReaderCache<T>
{
static ReaderCache()
{
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
if (!IsSupportedType<T>())
{
ReaderCache.readCache.TryAdd(typeof(T), null);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace System.Runtime.CompilerServices;

/// <summary>Provides a handler used by the language compiler to process interpolated strings into <see cref="string"/> instances.</summary>
[InterpolatedStringHandler]
public ref struct DefaultInterpolatedStringHandler
internal ref struct DefaultInterpolatedStringHandler
{
// Implementation note:
// As this type lives in CompilerServices and is only intended to be targeted by the compiler,
Expand Down Expand Up @@ -94,7 +94,7 @@ internal static int GetDefaultLength(int literalLength, int formattedCount) =>

/// <summary>Gets the built <see cref="string"/>.</summary>
/// <returns>The built string.</returns>
public override string ToString() => new string(Text);
public override string ToString() => Text.ToString();

/// <summary>Gets the built <see cref="string"/> and clears the handler.</summary>
/// <returns>The built string.</returns>
Expand All @@ -106,7 +106,7 @@ internal static int GetDefaultLength(int literalLength, int formattedCount) =>
/// </remarks>
public string ToStringAndClear()
{
string result = new string(Text);
string result = Text.ToString();
Clear();
return result;
}
Expand Down Expand Up @@ -627,7 +627,7 @@ private void GrowCore(uint requiredMinCapacity)

// uint newCapacity = Math.Max(requiredMinCapacity, Math.Min((uint)_chars.Length * 2, string.MaxLength));
uint newCapacity = Math.Max(requiredMinCapacity, Math.Min((uint)_chars.Length * 2, 0x3FFFFFDF));
int arraySize = (int)Math.Clamp(newCapacity, MinimumArrayPoolLength, int.MaxValue);
var arraySize = (int)Math.Max(Math.Min(newCapacity, int.MaxValue), MinimumArrayPoolLength);

char[] newArray = ArrayPool<char>.Shared.Rent(arraySize);
_chars.Slice(0, _pos).CopyTo(newArray);
Expand Down
36 changes: 36 additions & 0 deletions src/ZLogger/Internal/Shims/Shims.NetStandard2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#if NETSTANDARD2_0
using System.Text;

namespace ZLogger;

internal static partial class Shims
{
public static int GetBytes(this Encoding encoding, ReadOnlySpan<char> chars, ReadOnlySpan<byte> bytes)
{
unsafe
{
fixed (char* charsPtr = &chars[0])
fixed (byte* bytesPtr = &bytes[0])
{
return encoding.GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length);
}
}
}

public static unsafe Span<T> CreateSpan<T>(ref T value, int length) where T : unmanaged
{
fixed(T* pointer = &value)
{
return new Span<T>(pointer, length);
}
}

public static unsafe ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T value, int length) where T : unmanaged
{
fixed(T* pointer = &value)
{
return new ReadOnlySpan<T>(pointer, length);
}
}
}
#endif
4 changes: 2 additions & 2 deletions src/ZLogger/LogStates/InterpolatedStringLogState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public void WriteJsonParameterKeyValues(Utf8JsonWriter jsonWriter, JsonSerialize
for (var i = 0; i < ParameterCount; i++)
{
ref var p = ref parameters[i];
SystemTextJsonZLoggerFormatter.WriteMutatedJsonKeyName(p.Name, jsonWriter, keyNameMutator);
SystemTextJsonZLoggerFormatter.WriteMutatedJsonKeyName(p.Name.AsSpan(), jsonWriter, keyNameMutator);

if (magicalBox.TryReadTo(p.Type, p.BoxOffset, jsonWriter))
{
Expand All @@ -119,7 +119,7 @@ public ReadOnlySpan<byte> GetParameterKey(int index)

public ReadOnlySpan<char> GetParameterKeyAsString(int index)
{
return parameters[index].Name;
return parameters[index].Name.AsSpan();
}

public object? GetParameterValue(int index)
Expand Down
2 changes: 1 addition & 1 deletion src/ZLogger/LogStates/StringFormatterLogState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public ReadOnlySpan<char> GetParameterKeyAsString(int index)
{
if (originalStateParameters != null)
{
return originalStateParameters[index].Key;
return originalStateParameters[index].Key.AsSpan();
}
throw new IndexOutOfRangeException(nameof(index));
}
Expand Down
6 changes: 3 additions & 3 deletions src/ZLogger/ZLogger.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.1;net6.0;net8.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
<Nullable>enable</Nullable>
<LangVersion>12.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
Expand All @@ -24,14 +24,14 @@
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="8.0.0" />
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
<PackageReference Include="Utf8StringInterpolation" Version="1.1.0" />
<PackageReference Include="Utf8StringInterpolation" Version="1.2.0" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework) == 'net6.0'">
<PackageReference Include="Microsoft.Bcl.TimeProvider" Version="8.0.0" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework) == 'netstandard2.1'">
<ItemGroup Condition="$(TargetFramework) == 'netstandard2.0' Or $(TargetFramework) == 'netstandard2.1'">
<PackageReference Include="System.Text.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Bcl.TimeProvider" Version="8.0.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
Expand Down
9 changes: 9 additions & 0 deletions src/ZLogger/ZLoggerInterpolatedStringHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,18 @@ public bool Equals(LiteralList other)
// convert const strings as address sequence
static ReadOnlySpan<byte> AsBytes(ReadOnlySpan<string?> literals)
{
#if NETSTANDARD2_0
if (literals.IsEmpty)
return default;

return Shims.CreateSpan(
ref Unsafe.As<string?, byte>(ref Unsafe.AsRef(in literals[0])),
literals.Length * Unsafe.SizeOf<string>());
#else
return MemoryMarshal.CreateSpan(
ref Unsafe.As<string?, byte>(ref MemoryMarshal.GetReference(literals)),
literals.Length * Unsafe.SizeOf<string>());
#endif
}
}
}
Expand Down

0 comments on commit fd90949

Please sign in to comment.