Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating new TypeName without reparsing + usage in NRBF #103713

Merged
merged 21 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
86595de
new TypeName methods
adamsitnik Jun 18, 2024
d906606
do not join the type and library name strings when UndoTruncatedTypeN…
adamsitnik Jun 19, 2024
448f01e
cache known primitive type names (and SZArrays of these)
adamsitnik Jun 19, 2024
b37b8da
add more tests and finish WithAssemblyName implementation
adamsitnik Jun 19, 2024
6b933d9
finish the implementation
adamsitnik Jun 28, 2024
f707dfd
Merge remote-tracking branch 'upstream/main' into extendTypeName
adamsitnik Jun 28, 2024
1736b24
add missing IntPtr and UIntPtr support (discovered once I've re-enabl…
adamsitnik Jun 28, 2024
a54e55f
use TypeNameMatches in more places
adamsitnik Jun 28, 2024
7d2d0d6
Merge remote-tracking branch 'upstream/main' into extendTypeName
adamsitnik Aug 2, 2024
9a0cd58
address API review feedback
adamsitnik Aug 2, 2024
aabe51b
remove CreateSimpleTypeName, introduce MakeSimpleTypeNameThrowsForNon…
adamsitnik Aug 2, 2024
e207e0f
handle nested names properly
adamsitnik Aug 6, 2024
19f1e82
update the code after reading it again on GH
adamsitnik Aug 6, 2024
6d03c00
Merge remote-tracking branch 'upstream/main' into extendTypeName
adamsitnik Aug 12, 2024
3abda02
address code review feedback
adamsitnik Aug 12, 2024
50a58fb
address code review feedback
adamsitnik Aug 12, 2024
ebfc35e
address code review feedback
adamsitnik Aug 13, 2024
f50ae19
rename MakeSimpleTypeName to WithAssemblyName
adamsitnik Aug 13, 2024
69cd1fa
Apply suggestions from code review
adamsitnik Aug 14, 2024
aa0870f
don't use sbyte to store array rank, the limit of 32 can be changed i…
adamsitnik Aug 14, 2024
30be71e
fix the build
adamsitnik Aug 14, 2024
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
3 changes: 3 additions & 0 deletions src/libraries/System.Formats.Nrbf/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,7 @@
<data name="NotSupported_NonZeroOffsets" xml:space="preserve">
<value>Only arrays with zero offsets are supported.</value>
</data>
<data name="Serialization_InvalidAssemblyName" xml:space="preserve">
<value>Invalid assembly name: `{0}`.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@ namespace System.Formats.Nrbf;
/// </remarks>
internal sealed class ArraySingleObjectRecord : SZArrayRecord<object?>
{
private static TypeName? s_typeName;

private ArraySingleObjectRecord(ArrayInfo arrayInfo) : base(arrayInfo) => Records = [];

public override SerializationRecordType RecordType => SerializationRecordType.ArraySingleObject;

public override TypeName TypeName
=> s_typeName ??= TypeName.Parse(("System.Object[], " + TypeNameExtensions.CoreLibAssemblyName).AsSpan());
=> TypeNameHelpers.GetPrimitiveSZArrayTypeName(TypeNameHelpers.ObjectPrimitiveType);

private List<SerializationRecord> Records { get; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ namespace System.Formats.Nrbf;
internal sealed class ArraySinglePrimitiveRecord<T> : SZArrayRecord<T>
where T : unmanaged
{
private static TypeName? s_typeName;

internal ArraySinglePrimitiveRecord(ArrayInfo arrayInfo, IReadOnlyList<T> values) : base(arrayInfo)
{
Values = values;
Expand All @@ -35,8 +33,7 @@ internal ArraySinglePrimitiveRecord(ArrayInfo arrayInfo, IReadOnlyList<T> values
public override SerializationRecordType RecordType => SerializationRecordType.ArraySinglePrimitive;

/// <inheritdoc />
public override TypeName TypeName
=> s_typeName ??= TypeName.Parse((typeof(T[]).FullName + "," + TypeNameExtensions.CoreLibAssemblyName).AsSpan());
public override TypeName TypeName => TypeNameHelpers.GetPrimitiveSZArrayTypeName(TypeNameHelpers.GetPrimitiveType<T>());

internal IReadOnlyList<T> Values { get; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,12 @@ namespace System.Formats.Nrbf;
/// </remarks>
internal sealed class ArraySingleStringRecord : SZArrayRecord<string?>
{
private static TypeName? s_typeName;

private ArraySingleStringRecord(ArrayInfo arrayInfo) : base(arrayInfo) => Records = [];

public override SerializationRecordType RecordType => SerializationRecordType.ArraySingleString;

/// <inheritdoc />
public override TypeName TypeName
=> s_typeName ??= TypeName.Parse(("System.String[], " + TypeNameExtensions.CoreLibAssemblyName).AsSpan());
public override TypeName TypeName => TypeNameHelpers.GetPrimitiveSZArrayTypeName(PrimitiveType.String);

private List<SerializationRecord> Records { get; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Formats.Nrbf.Utils;
using System.IO;
using System.Reflection.Metadata;

Expand All @@ -15,7 +16,13 @@ namespace System.Formats.Nrbf;
/// </remarks>
internal sealed class BinaryLibraryRecord : SerializationRecord
{
private BinaryLibraryRecord(SerializationRecordId libraryId, string libraryName)
private BinaryLibraryRecord(SerializationRecordId libraryId, string rawLibraryName)
{
Id = libraryId;
RawLibraryName = rawLibraryName;
}

private BinaryLibraryRecord(SerializationRecordId libraryId, AssemblyNameInfo libraryName)
{
Id = libraryId;
LibraryName = libraryName;
Expand All @@ -32,11 +39,27 @@ public override TypeName TypeName
}
}

internal string LibraryName { get; }
internal string? RawLibraryName { get; }

internal AssemblyNameInfo? LibraryName { get; }

/// <inheritdoc />
public override SerializationRecordId Id { get; }

internal static BinaryLibraryRecord Decode(BinaryReader reader)
=> new(SerializationRecordId.Decode(reader), reader.ReadString());
internal static BinaryLibraryRecord Decode(BinaryReader reader, PayloadOptions options)
{
SerializationRecordId id = SerializationRecordId.Decode(reader);
string rawName = reader.ReadString();

if (AssemblyNameInfo.TryParse(rawName.AsSpan(), out AssemblyNameInfo? assemblyNameInfo))
{
return new BinaryLibraryRecord(id, assemblyNameInfo);
}
else if (!options.UndoTruncatedTypeNames)
{
ThrowHelper.ThrowInvalidAssemblyName(rawName);
}

return new BinaryLibraryRecord(id, rawName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,63 +142,25 @@ internal TypeName GetArrayTypeName(ArrayInfo arrayInfo)
{
(BinaryType binaryType, object? additionalInfo) = Infos[0];

switch (binaryType)
TypeName elementTypeName = binaryType switch
{
case BinaryType.String:
return typeof(string).BuildCoreLibArrayTypeName(arrayInfo.Rank);
case BinaryType.StringArray:
return typeof(string[]).BuildCoreLibArrayTypeName(arrayInfo.Rank);
case BinaryType.Object:
return typeof(object).BuildCoreLibArrayTypeName(arrayInfo.Rank);
case BinaryType.ObjectArray:
return typeof(object[]).BuildCoreLibArrayTypeName(arrayInfo.Rank);
case BinaryType.Primitive:
Type primitiveType = ((PrimitiveType)additionalInfo!) switch
{
PrimitiveType.Boolean => typeof(bool),
PrimitiveType.Byte => typeof(byte),
PrimitiveType.Char => typeof(char),
PrimitiveType.Decimal => typeof(decimal),
PrimitiveType.Double => typeof(double),
PrimitiveType.Int16 => typeof(short),
PrimitiveType.Int32 => typeof(int),
PrimitiveType.Int64 => typeof(long),
PrimitiveType.SByte => typeof(sbyte),
PrimitiveType.Single => typeof(float),
PrimitiveType.TimeSpan => typeof(TimeSpan),
PrimitiveType.DateTime => typeof(DateTime),
PrimitiveType.UInt16 => typeof(ushort),
PrimitiveType.UInt32 => typeof(uint),
_ => typeof(ulong),
};

return primitiveType.BuildCoreLibArrayTypeName(arrayInfo.Rank);
case BinaryType.PrimitiveArray:
Type primitiveArrayType = ((PrimitiveType)additionalInfo!) switch
{
PrimitiveType.Boolean => typeof(bool[]),
PrimitiveType.Byte => typeof(byte[]),
PrimitiveType.Char => typeof(char[]),
PrimitiveType.Decimal => typeof(decimal[]),
PrimitiveType.Double => typeof(double[]),
PrimitiveType.Int16 => typeof(short[]),
PrimitiveType.Int32 => typeof(int[]),
PrimitiveType.Int64 => typeof(long[]),
PrimitiveType.SByte => typeof(sbyte[]),
PrimitiveType.Single => typeof(float[]),
PrimitiveType.TimeSpan => typeof(TimeSpan[]),
PrimitiveType.DateTime => typeof(DateTime[]),
PrimitiveType.UInt16 => typeof(ushort[]),
PrimitiveType.UInt32 => typeof(uint[]),
_ => typeof(ulong[]),
};

return primitiveArrayType.BuildCoreLibArrayTypeName(arrayInfo.Rank);
case BinaryType.SystemClass:
return ((TypeName)additionalInfo!).BuildArrayTypeName(arrayInfo.Rank);
default:
Debug.Assert(binaryType is BinaryType.Class, "The parsers should reject other inputs");
return (((ClassTypeInfo)additionalInfo!).TypeName).BuildArrayTypeName(arrayInfo.Rank);
}
BinaryType.String => TypeNameHelpers.GetPrimitiveTypeName(PrimitiveType.String),
BinaryType.StringArray => TypeNameHelpers.GetPrimitiveSZArrayTypeName(PrimitiveType.String),
BinaryType.Primitive => TypeNameHelpers.GetPrimitiveTypeName((PrimitiveType)additionalInfo!),
BinaryType.PrimitiveArray => TypeNameHelpers.GetPrimitiveSZArrayTypeName((PrimitiveType)additionalInfo!),
BinaryType.Object => TypeNameHelpers.GetPrimitiveTypeName(TypeNameHelpers.ObjectPrimitiveType),
BinaryType.ObjectArray => TypeNameHelpers.GetPrimitiveSZArrayTypeName(TypeNameHelpers.ObjectPrimitiveType),
BinaryType.SystemClass => (TypeName)additionalInfo!,
_ => ((ClassTypeInfo)additionalInfo!).TypeName,
JeremyKuhne marked this conversation as resolved.
Show resolved Hide resolved
};

// In general, arrayRank == 1 may have two different meanings:
// - [] is a single dimension and zero-indexed array (SZArray)
// - [*] is single dimension, custom offset array.
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
// Custom offset arrays are not supported by design, so in our case it's always SZArray.
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
// That is why we don't call TypeName.MakeArrayTypeName(1) because it would create [*] instead of [] name.
return arrayInfo.Rank == 1
? elementTypeName.MakeArrayTypeName()
: elementTypeName.MakeArrayTypeName(arrayInfo.Rank);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ private static SerializationRecord DecodeNext(BinaryReader reader, RecordMap rec
SerializationRecordType.ArraySinglePrimitive => DecodeArraySinglePrimitiveRecord(reader),
SerializationRecordType.ArraySingleString => ArraySingleStringRecord.Decode(reader),
SerializationRecordType.BinaryArray => BinaryArrayRecord.Decode(reader, recordMap, options),
SerializationRecordType.BinaryLibrary => BinaryLibraryRecord.Decode(reader),
SerializationRecordType.BinaryLibrary => BinaryLibraryRecord.Decode(reader, options),
SerializationRecordType.BinaryObjectString => BinaryObjectStringRecord.Decode(reader),
SerializationRecordType.ClassWithId => ClassWithIdRecord.Decode(reader, recordMap),
SerializationRecordType.ClassWithMembersAndTypes => ClassWithMembersAndTypesRecord.Decode(reader, recordMap, options),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ namespace System.Formats.Nrbf;
[DebuggerDisplay("{Value}")]
public abstract class PrimitiveTypeRecord<T> : PrimitiveTypeRecord
{
private static TypeName? s_typeName;

private protected PrimitiveTypeRecord(T value) => Value = value;

/// <summary>
Expand All @@ -36,8 +34,7 @@ public abstract class PrimitiveTypeRecord<T> : PrimitiveTypeRecord
public new T Value { get; }

/// <inheritdoc />
public override TypeName TypeName
=> s_typeName ??= TypeName.Parse(typeof(T).FullName.AsSpan()).WithCoreLibAssemblyName();
public override TypeName TypeName => TypeNameHelpers.GetPrimitiveTypeName(TypeNameHelpers.GetPrimitiveType<T>());

internal override object? GetValue() => Value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ internal static void ThrowMaxArrayLength(long limit, long actual)
internal static void ThrowArrayContainedNulls()
=> throw new SerializationException(SR.Serialization_ArrayContainedNulls);

internal static void ThrowInvalidAssemblyName(string rawName)
=> throw new SerializationException(SR.Format(SR.Serialization_InvalidAssemblyName, rawName));

internal static void ThrowEndOfStreamException()
=> throw new EndOfStreamException();

Expand Down

This file was deleted.

Loading
Loading