Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 52 additions & 71 deletions Orm/Xtensive.Orm/Tuples/Packed/TupleLayout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// Created by: Denis Krjuchkov
// Created: 2012.12.29

using System;
using System.Runtime.CompilerServices;
using Xtensive.Reflection;

Expand Down Expand Up @@ -53,79 +52,62 @@ internal static class ValueFieldAccessorResolver
private static readonly ValueFieldAccessor GuidAccessor = new GuidFieldAccessor();
private static readonly ValueFieldAccessor DateTimeOffsetAccessor = new DateTimeOffsetFieldAccessor();

private static readonly ObjectFieldAccessor ObjectAccessor = new ObjectFieldAccessor();
private static readonly ObjectFieldAccessor ObjectAccessor = new();

private static readonly int NullableTypeMetadataToken = WellKnownTypes.NullableOfT.MetadataToken;

public static ValueFieldAccessor GetValue(Type probeType)
private sealed class TypeReferenceEqualityComparer : IEqualityComparer<Type>
{
return (probeType.MetadataToken ^ NullableTypeMetadataToken) == 0
? (ResolveByNullableType(probeType) ?? TryResolveNullableEnum(probeType))
: (ResolveByType(probeType) ?? TryResolveEnum(probeType));
public static readonly TypeReferenceEqualityComparer Instance = new();
public bool Equals(Type x, Type y) => ReferenceEquals(x, y);
public int GetHashCode(Type obj) => obj.GetHashCode();
}

private static ValueFieldAccessor ResolveByType(Type type)
private static readonly Dictionary<Type, ValueFieldAccessor> TypeToAccessor = new(TypeReferenceEqualityComparer.Instance)
{
return ReferenceEquals(type, WellKnownTypes.Int64) ? Int64Accessor :
ReferenceEquals(type, WellKnownTypes.Guid) ? GuidAccessor :
ReferenceEquals(type, WellKnownTypes.Int32) ? Int32Accessor :
ReferenceEquals(type, WellKnownTypes.Bool) ? BoolAccessor :
ReferenceEquals(type, WellKnownTypes.DateTime) ? DateTimeAccessor :
ReferenceEquals(type, WellKnownTypes.TimeSpan) ? TimeSpanAccessor :
ReferenceEquals(type, WellKnownTypes.Double) ? DoubleAccessor :
ReferenceEquals(type, WellKnownTypes.Decimal) ? DecimalAccessor :
ReferenceEquals(type, WellKnownTypes.Single) ? SingleAccessor :
ReferenceEquals(type, WellKnownTypes.DateTimeOffset) ? DateTimeOffsetAccessor :
ReferenceEquals(type, WellKnownTypes.DateOnly) ? DateOnlyAccessor :
ReferenceEquals(type, WellKnownTypes.TimeOnly) ? TimeOnlyAccessor :
ReferenceEquals(type, WellKnownTypes.Int16) ? Int16Accessor :
ReferenceEquals(type, WellKnownTypes.Byte) ? ByteAccessor :
ReferenceEquals(type, WellKnownTypes.SByte) ? SByteAccessor :
ReferenceEquals(type, WellKnownTypes.UInt16) ? UInt16Accessor :
ReferenceEquals(type, WellKnownTypes.UInt32) ? UInt32Accessor :
ReferenceEquals(type, WellKnownTypes.UInt64) ? UInt64Accessor : null;
}
[WellKnownTypes.Int64] = Int64Accessor,
[WellKnownTypes.Guid] = GuidAccessor,
[WellKnownTypes.Int32] = Int32Accessor,
[WellKnownTypes.Bool] = BoolAccessor,
[WellKnownTypes.DateTime] = DateTimeAccessor,
[WellKnownTypes.TimeSpan] = TimeSpanAccessor,
[WellKnownTypes.Double] = DoubleAccessor,
[WellKnownTypes.Decimal] = DecimalAccessor,
[WellKnownTypes.Single] = SingleAccessor,
[WellKnownTypes.DateTimeOffset] = DateTimeOffsetAccessor,
[WellKnownTypes.DateOnly] = DateOnlyAccessor,
[WellKnownTypes.TimeOnly] = TimeOnlyAccessor,
[WellKnownTypes.Int16] = Int16Accessor,
[WellKnownTypes.Byte] = ByteAccessor,
[WellKnownTypes.SByte] = SByteAccessor,
[WellKnownTypes.UInt16] = UInt16Accessor,
[WellKnownTypes.UInt32] = UInt32Accessor,
[WellKnownTypes.UInt64] = UInt64Accessor,
[WellKnownTypes.NullableBool] = BoolAccessor,
[WellKnownTypes.NullableInt32] = Int32Accessor,
[WellKnownTypes.NullableDouble] = DoubleAccessor,
[WellKnownTypes.NullableDecimal] = DecimalAccessor,
[WellKnownTypes.NullableInt64] = Int64Accessor,
[WellKnownTypes.NullableDateTime] = DateTimeAccessor,
[WellKnownTypes.NullableTimeSpan] = TimeSpanAccessor,
[WellKnownTypes.NullableDateTimeOffset] = DateTimeOffsetAccessor,
[WellKnownTypes.NullableSingle] = SingleAccessor,
[WellKnownTypes.NullableDateOnly] = DateOnlyAccessor,
[WellKnownTypes.NullableTimeOnly] = TimeOnlyAccessor,
[WellKnownTypes.NullableGuid] = GuidAccessor,
[WellKnownTypes.NullableInt16] = Int16Accessor,
[WellKnownTypes.NullableByte] = ByteAccessor,
[WellKnownTypes.NullableSByte] = SByteAccessor,
[WellKnownTypes.NullableUInt16] = UInt16Accessor,
[WellKnownTypes.NullableUInt32] = UInt32Accessor,
[WellKnownTypes.NullableUInt64] = UInt64Accessor
};

private static ValueFieldAccessor ResolveByNullableType(Type type)
{
return ReferenceEquals(type, WellKnownTypes.NullableBool) ? BoolAccessor :
ReferenceEquals(type, WellKnownTypes.NullableInt32) ? Int32Accessor :
ReferenceEquals(type, WellKnownTypes.NullableDouble) ? DoubleAccessor :
ReferenceEquals(type, WellKnownTypes.NullableDecimal) ? DecimalAccessor :
ReferenceEquals(type, WellKnownTypes.NullableInt64) ? Int64Accessor :
ReferenceEquals(type, WellKnownTypes.NullableDateTime) ? DateTimeAccessor :
ReferenceEquals(type, WellKnownTypes.NullableTimeSpan) ? TimeSpanAccessor :
ReferenceEquals(type, WellKnownTypes.NullableDateTimeOffset) ? DateTimeOffsetAccessor :
ReferenceEquals(type, WellKnownTypes.NullableSingle) ? SingleAccessor :
ReferenceEquals(type, WellKnownTypes.NullableDateOnly) ? DateOnlyAccessor :
ReferenceEquals(type, WellKnownTypes.NullableTimeOnly) ? TimeOnlyAccessor :
ReferenceEquals(type, WellKnownTypes.NullableGuid) ? GuidAccessor :
ReferenceEquals(type, WellKnownTypes.NullableInt16) ? Int16Accessor :
ReferenceEquals(type, WellKnownTypes.NullableByte) ? ByteAccessor :
ReferenceEquals(type, WellKnownTypes.NullableSByte) ? SByteAccessor :
ReferenceEquals(type, WellKnownTypes.NullableUInt16) ? UInt16Accessor :
ReferenceEquals(type, WellKnownTypes.NullableUInt32) ? UInt32Accessor :
ReferenceEquals(type, WellKnownTypes.NullableUInt64) ? UInt64Accessor : null;
}

private static ValueFieldAccessor TryResolveEnum(Type type)
{
if (!type.IsEnum) {
return null;
}
type = Enum.GetUnderlyingType(type);
return ResolveByType(type);
}
private static readonly int NullableTypeMetadataToken = WellKnownTypes.NullableOfT.MetadataToken;

private static ValueFieldAccessor TryResolveNullableEnum(Type type)
{
var generic = type.GetGenericArguments()[0];
if (!generic.IsEnum) {
return null;
}
type = Enum.GetUnderlyingType(generic);
return ResolveByType(type);
}
public static ValueFieldAccessor GetValue(Type probeType) =>
TypeToAccessor.GetValueOrDefault(probeType)
?? ((probeType.MetadataToken == NullableTypeMetadataToken ? probeType.GetGenericArguments()[0] : probeType) is { IsEnum: true } enumType
? TypeToAccessor.GetValueOrDefault(Enum.GetUnderlyingType(enumType))
: null);
}

internal delegate void CounterIncrementer(ref Counters counters);
Expand All @@ -134,14 +116,13 @@ private static ValueFieldAccessor TryResolveNullableEnum(Type type)

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ConfigureFieldAccessor(ref PackedFieldDescriptor descriptor, Type fieldType) =>
descriptor.AccessorIndex = ((PackedFieldAccessor)ValueFieldAccessorResolver.GetValue(fieldType))?.Index ?? ObjectFieldAccessor.FixedIndex;
descriptor.AccessorIndex = ValueFieldAccessorResolver.GetValue(fieldType)?.Index ?? ObjectFieldAccessor.FixedIndex;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ConfigureLen1(ref Type fieldType, ref PackedFieldDescriptor descriptor, out int valuesLength,
out int objectsLength)
{
var valueAccessor = ValueFieldAccessorResolver.GetValue(fieldType);
if (valueAccessor != null) {
if (ValueFieldAccessorResolver.GetValue(fieldType) is { } valueAccessor) {
descriptor.AccessorIndex = valueAccessor.Index;
descriptor.DataPosition = Val064BitCount;

Expand Down Expand Up @@ -264,4 +245,4 @@ private static void ConfigureFieldPhase1(ref PackedFieldDescriptor descriptor, r
descriptor.Index = counters.ObjectCounter++;
}
}
}
}
Loading