Skip to content

Commit

Permalink
[NRBF] change StartsWithPayloadHeader to accept a Span rather than ar…
Browse files Browse the repository at this point in the history
…ray (#103636)

* change StartsWithPayloadHeader to accept a Span rather than array

* address code review feedback: don't use MemoryMarshal.Cast<byte, int> because it's not guaranteed to work everywhere
  • Loading branch information
adamsitnik authored Jun 28, 2024
1 parent 203f993 commit a900bbf
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ 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.ReadOnlySpan<byte> bytes) { throw null; }
public static bool StartsWithPayloadHeader(System.IO.Stream stream) { throw null; }
}
public sealed partial class PayloadOptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Formats.Nrbf.Utils;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;

namespace System.Formats.Nrbf;

Expand All @@ -18,33 +19,24 @@ public static class NrbfDecoder
{
private static UTF8Encoding ThrowOnInvalidUtf8Encoding { get; } = new(false, throwOnInvalidBytes: true);

// The header consists of:
// - a byte that describes the record type (SerializationRecordType.SerializedStreamHeader)
// - four 32 bit integers:
// - root Id (every value is valid)
// - header Id (value is ignored)
// - major version, it has to be equal 1.
// - minor version, it has to be equal 0.
private static ReadOnlySpan<byte> HeaderSuffix => [1, 0, 0, 0, 0, 0, 0, 0];

/// <summary>
/// Checks if given buffer starts with <see href="https://learn.microsoft.com/openspecs/windows_protocols/ms-nrbf/a7e578d3-400a-4249-9424-7529d10d1b3c">NRBF payload header</see>.
/// </summary>
/// <param name="bytes">The buffer to inspect.</param>
/// <returns><see langword="true" /> if it starts with NRBF payload header; otherwise, <see langword="false" />.</returns>
public static bool StartsWithPayloadHeader(byte[] bytes)
{
#if NET
ArgumentNullException.ThrowIfNull(bytes);
#else
if (bytes is null)
{
throw new ArgumentNullException(nameof(bytes));
}
#endif

return bytes.Length >= SerializedStreamHeaderRecord.Size
&& bytes[0] == (byte)SerializationRecordType.SerializedStreamHeader
#if NET
&& BinaryPrimitives.ReadInt32LittleEndian(bytes.AsSpan(9)) == SerializedStreamHeaderRecord.MajorVersion
&& BinaryPrimitives.ReadInt32LittleEndian(bytes.AsSpan(13)) == SerializedStreamHeaderRecord.MinorVersion;
#else
&& BitConverter.ToInt32(bytes, 9) == SerializedStreamHeaderRecord.MajorVersion
&& BitConverter.ToInt32(bytes, 13) == SerializedStreamHeaderRecord.MinorVersion;
#endif
}

public static bool StartsWithPayloadHeader(ReadOnlySpan<byte> bytes)
=> bytes.Length >= SerializedStreamHeaderRecord.Size
&& bytes[0] == (byte)SerializationRecordType.SerializedStreamHeader
&& bytes.Slice(SerializedStreamHeaderRecord.Size - HeaderSuffix.Length, HeaderSuffix.Length).SequenceEqual(HeaderSuffix);

/// <summary>
/// Checks if given stream starts with <see href="https://learn.microsoft.com/openspecs/windows_protocols/ms-nrbf/a7e578d3-400a-4249-9424-7529d10d1b3c">NRBF payload header</see>.
Expand Down Expand Up @@ -76,13 +68,13 @@ public static bool StartsWithPayloadHeader(Stream stream)
return false;
}

byte[] buffer = new byte[SerializedStreamHeaderRecord.Size];

try
{
#if NET
stream.ReadExactly(buffer, 0, buffer.Length);
Span<byte> buffer = stackalloc byte[SerializedStreamHeaderRecord.Size];
stream.ReadExactly(buffer);
#else
byte[] buffer = new byte[SerializedStreamHeaderRecord.Size];
int offset = 0;
while (offset < buffer.Length)
{
Expand Down

0 comments on commit a900bbf

Please sign in to comment.