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

Make System.Formats.Nrbf public #103232

Merged
merged 23 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8a396bb
apply the new library name: System.Formats.Nrbf
adamsitnik Jun 10, 2024
b49c824
rename the types and methods, make them public:
adamsitnik Jun 10, 2024
8ed896f
introduce non-generic PrimitiveTypeRecord, use it where it simplifies…
adamsitnik Jun 10, 2024
380b82e
remove ClassRecord.GetArrayOfPrimitiveType, add GetArrayRecord
adamsitnik Jun 10, 2024
0edfa3c
introduce SerializationRecordId, use it
adamsitnik Jun 10, 2024
f205fa9
make BinaryArrayType internal, add ArrayRecord.IsJagged, remove suppo…
adamsitnik Jun 10, 2024
43336ed
fix the build
adamsitnik Jun 11, 2024
e703c6b
TypeName matching changes:
adamsitnik Jun 11, 2024
7bd4b27
rename RecordType to SerializationRecordType, remove the byte size co…
adamsitnik Jun 11, 2024
a171648
add ref project
adamsitnik Jun 11, 2024
cd54d66
fix the build
adamsitnik Jun 12, 2024
daa7431
remove the need of having a separate stack of ids that are being pars…
adamsitnik Jun 12, 2024
dedcf0c
Apply suggestions from code review
adamsitnik Jun 12, 2024
e0ad582
remove special casing of TimeSpan that seems to be missing [TypeForwa…
adamsitnik Jun 12, 2024
0664932
type name matching: take generic type definition into account
adamsitnik Jun 12, 2024
3673b4f
Apply suggestions from code review
adamsitnik Jun 13, 2024
7352704
address code review feedback
adamsitnik Jun 13, 2024
5c3b266
Merge remote-tracking branch 'upstream/main' into nrbfPublic
adamsitnik Jun 13, 2024
9fbf59c
try to solve the pre-built error about System.ValueTuple by removing …
adamsitnik Jun 13, 2024
39832eb
increase the margin of error (this test needs to ensure 2GB is not be…
adamsitnik Jun 13, 2024
a151e6e
Apply suggestions from code review
adamsitnik Jun 14, 2024
729a61f
Apply suggestions from code review
adamsitnik Jun 14, 2024
770761d
add missing xml docs
adamsitnik Jun 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
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ VisualStudioVersion = 17.11.34906.271
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8721A077-F840-4316-9D8A-6E48B3D5EA03}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.Serialization.BinaryFormat", "src\System.Runtime.Serialization.BinaryFormat.csproj", "{E23A8E5A-9975-4ABE-BE54-B02328207F37}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Formats.Nrbf", "src\System.Formats.Nrbf.csproj", "{E23A8E5A-9975-4ABE-BE54-B02328207F37}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{32F1B10C-7A0C-440E-8F42-D5309D3D7DAA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Runtime.Serialization.BinaryFormat.Tests", "tests\System.Runtime.Serialization.BinaryFormat.Tests.csproj", "{8B45136F-C266-4FE7-B5A3-CFD6F3648289}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Formats.Nrbf.Tests", "tests\System.Formats.Nrbf.Tests.csproj", "{8B45136F-C266-4FE7-B5A3-CFD6F3648289}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{D50A3723-4816-47D5-B6A2-E126D2F02722}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Formats.Nrbf", "ref\System.Formats.Nrbf.csproj", "{3415B821-490E-4B12-9A5F-135CAC6271B8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -25,13 +29,18 @@ Global
{8B45136F-C266-4FE7-B5A3-CFD6F3648289}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B45136F-C266-4FE7-B5A3-CFD6F3648289}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B45136F-C266-4FE7-B5A3-CFD6F3648289}.Release|Any CPU.Build.0 = Release|Any CPU
{3415B821-490E-4B12-9A5F-135CAC6271B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3415B821-490E-4B12-9A5F-135CAC6271B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3415B821-490E-4B12-9A5F-135CAC6271B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3415B821-490E-4B12-9A5F-135CAC6271B8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{E23A8E5A-9975-4ABE-BE54-B02328207F37} = {8721A077-F840-4316-9D8A-6E48B3D5EA03}
{8B45136F-C266-4FE7-B5A3-CFD6F3648289} = {32F1B10C-7A0C-440E-8F42-D5309D3D7DAA}
{3415B821-490E-4B12-9A5F-135CAC6271B8} = {D50A3723-4816-47D5-B6A2-E126D2F02722}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CC885ACA-F5FA-4CAA-BA5F-2517D39C3066}
Expand Down
115 changes: 115 additions & 0 deletions src/libraries/System.Formats.Nrbf/ref/System.Formats.Nrbf.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// ------------------------------------------------------------------------------
// Changes to this file must follow the https://aka.ms/api-review process.
// ------------------------------------------------------------------------------

namespace System.Formats.Nrbf
{
public abstract partial class ArrayRecord : System.Formats.Nrbf.SerializationRecord
{
internal ArrayRecord() { }
public override System.Formats.Nrbf.SerializationRecordId Id { get { throw null; } }
public abstract System.ReadOnlySpan<int> Lengths { get; }
public int Rank { get { throw null; } }
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public System.Array GetArray(System.Type expectedArrayType, bool allowNulls = true) { throw null; }
}
public abstract partial class ClassRecord : System.Formats.Nrbf.SerializationRecord
{
internal ClassRecord() { }
public override System.Formats.Nrbf.SerializationRecordId Id { get { throw null; } }
public System.Collections.Generic.IEnumerable<string> MemberNames { get { throw null; } }
public override System.Reflection.Metadata.TypeName TypeName { get { throw null; } }
public System.Formats.Nrbf.ArrayRecord? GetArrayRecord(string memberName) { throw null; }
public bool GetBoolean(string memberName) { throw null; }
public byte GetByte(string memberName) { throw null; }
public char GetChar(string memberName) { throw null; }
public System.Formats.Nrbf.ClassRecord? GetClassRecord(string memberName) { throw null; }
public System.DateTime GetDateTime(string memberName) { throw null; }
public decimal GetDecimal(string memberName) { throw null; }
public double GetDouble(string memberName) { throw null; }
public short GetInt16(string memberName) { throw null; }
public int GetInt32(string memberName) { throw null; }
public long GetInt64(string memberName) { throw null; }
public object? GetRawValue(string memberName) { throw null; }
public sbyte GetSByte(string memberName) { throw null; }
public System.Formats.Nrbf.SerializationRecord? GetSerializationRecord(string memberName) { throw null; }
public float GetSingle(string memberName) { throw null; }
public string? GetString(string memberName) { throw null; }
public System.TimeSpan GetTimeSpan(string memberName) { throw null; }
public ushort GetUInt16(string memberName) { throw null; }
public uint GetUInt32(string memberName) { throw null; }
public ulong GetUInt64(string memberName) { throw null; }
public bool HasMember(string memberName) { throw null; }
}
public static partial class NrbfDecoder
{
public static System.Formats.Nrbf.SerializationRecord Decode(System.IO.Stream payload, out System.Collections.Generic.IReadOnlyDictionary<System.Formats.Nrbf.SerializationRecordId, System.Formats.Nrbf.SerializationRecord> recordMap, System.Formats.Nrbf.PayloadOptions options=null, bool leaveOpen=false) { throw null; }
public static System.Formats.Nrbf.SerializationRecord Decode(System.IO.Stream payload, System.Formats.Nrbf.PayloadOptions? options=null, bool leaveOpen=false) { throw null; }
public static System.Formats.Nrbf.ClassRecord DecodeClassRecord(System.IO.Stream payload, System.Formats.Nrbf.PayloadOptions? options=null, bool leaveOpen=false) { throw null; }
public static bool StartsWithPayloadHeader(byte[] bytes) { throw null; }
public static bool StartsWithPayloadHeader(System.IO.Stream stream) { throw null; }
}
public sealed partial class PayloadOptions
{
public PayloadOptions() { }
public System.Reflection.Metadata.TypeNameParseOptions? TypeNameParseOptions { get { throw null; } set { } }
public bool UndoTruncatedTypeNames { get { throw null; } set { } }
}
public abstract partial class PrimitiveTypeRecord : System.Formats.Nrbf.SerializationRecord
{
internal PrimitiveTypeRecord() { }
public object Value { get { throw null; } }
}
public abstract partial class PrimitiveTypeRecord<T> : System.Formats.Nrbf.PrimitiveTypeRecord
{
internal PrimitiveTypeRecord() { }
public override System.Reflection.Metadata.TypeName TypeName { get { throw null; } }
public new T Value { get { throw null; } }
}
public abstract partial class SerializationRecord
{
internal SerializationRecord() { }
public abstract System.Formats.Nrbf.SerializationRecordId Id { get; }
public abstract System.Formats.Nrbf.SerializationRecordType RecordType { get; }
public abstract System.Reflection.Metadata.TypeName TypeName { get; }
public bool TypeNameMatches(System.Type type) { throw null; }
}
public partial struct SerializationRecordId : System.IEquatable<System.Formats.Nrbf.SerializationRecordId>
{
public bool Equals(System.Formats.Nrbf.SerializationRecordId other) { throw null; }
public override bool Equals(object? obj) { throw null; }
public override int GetHashCode() { throw null; }
}
public enum SerializationRecordType
{
SerializedStreamHeader = 0,
ClassWithId = 1,
SystemClassWithMembers = 2,
ClassWithMembers = 3,
SystemClassWithMembersAndTypes = 4,
ClassWithMembersAndTypes = 5,
BinaryObjectString = 6,
BinaryArray = 7,
MemberPrimitiveTyped = 8,
MemberReference = 9,
ObjectNull = 10,
MessageEnd = 11,
BinaryLibrary = 12,
ObjectNullMultiple256 = 13,
ObjectNullMultiple = 14,
ArraySinglePrimitive = 15,
ArraySingleObject = 16,
ArraySingleString = 17,
MethodCall = 21,
MethodReturn = 22,
}
public abstract partial class SZArrayRecord<T> : System.Formats.Nrbf.ArrayRecord
{
internal SZArrayRecord() { }
public int Length { get { throw null; } }
public override System.ReadOnlySpan<int> Lengths { get { throw null; } }
public abstract T?[] GetArray(bool allowNulls = true);
}
}
20 changes: 20 additions & 0 deletions src/libraries/System.Formats.Nrbf/ref/System.Formats.Nrbf.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
<CLSCompliant>false</CLSCompliant>
</PropertyGroup>

<ItemGroup>
<Compile Include="System.Formats.Nrbf.cs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="$(LibrariesProjectRoot)System.IO.Hashing\ref\System.IO.Hashing.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Reflection.Metadata\ref\System.Reflection.Metadata.csproj" />
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<Compile Include="$(CoreLibSharedDir)System\Diagnostics\CodeAnalysis\RequiresDynamicCodeAttribute.cs" />
<PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,7 @@
<data name="Serialization_MemberTypeMismatchException" xml:space="preserve">
<value>Specified member '{0}' was not of the expected type.</value>
</data>
<data name="NotSupported_NonZeroOffsets" xml:space="preserve">
<value>Only arrays with zero offsets are supported.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
<EnableDefaultItems>true</EnableDefaultItems>
<CLSCompliant>false</CLSCompliant>
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
<!-- once the APIs get approved this is going to change -->
<IsPackable>false</IsPackable>
<DefineConstants>$(DefineConstants);SYSTEM_RUNTIME_SERIALIZATION_BINARYFORMAT</DefineConstants>
<UseCompilerGeneratedDocXmlFile>true</UseCompilerGeneratedDocXmlFile>
<IsPackable>true</IsPackable>
<PackageDescription>Provides a safe reader for .NET Remoting Binary Format (NRBF) payloads.

Commonly Used Types:
System.Formats.Nrbf.NrbfDecoder</PackageDescription>

<!-- Disabling baseline validation since this is a brand new package.
Once this package has shipped a stable version, the following line
should be removed in order to re-enable validation. -->
<DisablePackageBaselineValidation>true</DisablePackageBaselineValidation>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(LibrariesProjectRoot)\System.IO.Hashing\src\System.IO.Hashing.csproj" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Formats.Nrbf;

[Flags]
internal enum AllowedRecordTypes : uint
{
None = 0,
SerializedStreamHeader = 1 << SerializationRecordType.SerializedStreamHeader,
ClassWithId = 1 << SerializationRecordType.ClassWithId,
SystemClassWithMembersAndTypes = 1 << SerializationRecordType.SystemClassWithMembersAndTypes,
ClassWithMembersAndTypes = 1 << SerializationRecordType.ClassWithMembersAndTypes,
BinaryObjectString = 1 << SerializationRecordType.BinaryObjectString,
BinaryArray = 1 << SerializationRecordType.BinaryArray,
MemberPrimitiveTyped = 1 << SerializationRecordType.MemberPrimitiveTyped,
MemberReference = 1 << SerializationRecordType.MemberReference,
ObjectNull = 1 << SerializationRecordType.ObjectNull,
MessageEnd = 1 << SerializationRecordType.MessageEnd,
BinaryLibrary = 1 << SerializationRecordType.BinaryLibrary,
ObjectNullMultiple256 = 1 << SerializationRecordType.ObjectNullMultiple256,
ObjectNullMultiple = 1 << SerializationRecordType.ObjectNullMultiple,
ArraySinglePrimitive = 1 << SerializationRecordType.ArraySinglePrimitive,
ArraySingleObject = 1 << SerializationRecordType.ArraySingleObject,
ArraySingleString = 1 << SerializationRecordType.ArraySingleString,

Nulls = ObjectNull | ObjectNullMultiple256 | ObjectNullMultiple,

/// <summary>
/// Any .NET object (a primitive, a reference type, a reference or single null).
/// </summary>
AnyObject = MemberPrimitiveTyped
| ArraySingleObject | ArraySinglePrimitive | ArraySingleString | BinaryArray
| ClassWithId | ClassWithMembersAndTypes | SystemClassWithMembersAndTypes
| BinaryObjectString
| MemberReference
| ObjectNull,
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.BinaryFormat.Utils;
using System.Formats.Nrbf.Utils;

namespace System.Runtime.Serialization.BinaryFormat;
namespace System.Formats.Nrbf;

/// <summary>
/// Array information structure.
Expand All @@ -18,15 +18,15 @@ internal readonly struct ArrayInfo
{
internal const int MaxArrayLength = 2147483591; // Array.MaxLength

internal ArrayInfo(int objectId, long totalElementsCount, BinaryArrayType arrayType = BinaryArrayType.Single, int rank = 1)
internal ArrayInfo(SerializationRecordId id, long totalElementsCount, BinaryArrayType arrayType = BinaryArrayType.Single, int rank = 1)
{
ObjectId = objectId;
Id = id;
TotalElementsCount = totalElementsCount;
ArrayType = arrayType;
Rank = rank;
}

internal int ObjectId { get; }
internal SerializationRecordId Id { get; }

internal long TotalElementsCount { get; }

Expand All @@ -41,7 +41,7 @@ internal int GetSZArrayLength()
}

internal static ArrayInfo Decode(BinaryReader reader)
=> new(reader.ReadInt32(), ParseValidArrayLength(reader));
=> new(SerializationRecordId.Decode(reader), ParseValidArrayLength(reader));

internal static int ParseValidArrayLength(BinaryReader reader)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Runtime.Serialization.BinaryFormat.Utils;
using System.Formats.Nrbf.Utils;

namespace System.Runtime.Serialization.BinaryFormat;
namespace System.Formats.Nrbf;

internal sealed class ArrayOfClassesRecord : ArrayRecord<ClassRecord>
internal sealed class ArrayOfClassesRecord : SZArrayRecord<ClassRecord>
{
private TypeName? _elementTypeName;
private TypeName? _typeName;

internal ArrayOfClassesRecord(ArrayInfo arrayInfo, MemberTypeInfo memberTypeInfo)
: base(arrayInfo)
Expand All @@ -18,13 +18,14 @@ internal ArrayOfClassesRecord(ArrayInfo arrayInfo, MemberTypeInfo memberTypeInfo
Records = [];
}

public override RecordType RecordType => RecordType.BinaryArray;
public override SerializationRecordType RecordType => SerializationRecordType.BinaryArray;

internal List<SerializationRecord> Records { get; }

private MemberTypeInfo MemberTypeInfo { get; }

public override TypeName ElementTypeName => _elementTypeName ??= MemberTypeInfo.GetElementTypeName();
public override TypeName TypeName
=> _typeName ??= MemberTypeInfo.GetArrayTypeName(ArrayInfo);

/// <inheritdoc/>
public override ClassRecord?[] GetArray(bool allowNulls = true)
Expand Down Expand Up @@ -79,7 +80,4 @@ internal override (AllowedRecordTypes allowed, PrimitiveType primitiveType) GetA

return (allowed, primitiveType);
}

internal override bool IsElementType(Type typeElement)
=> MemberTypeInfo.IsElementType(typeElement);
}
Loading
Loading