diff --git a/src/libraries/System.Formats.Nrbf/ref/System.Formats.Nrbf.cs b/src/libraries/System.Formats.Nrbf/ref/System.Formats.Nrbf.cs index 22afcd06071199..8e12cf7c3712f5 100644 --- a/src/libraries/System.Formats.Nrbf/ref/System.Formats.Nrbf.cs +++ b/src/libraries/System.Formats.Nrbf/ref/System.Formats.Nrbf.cs @@ -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 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 bytes) { throw null; } public static bool StartsWithPayloadHeader(System.IO.Stream stream) { throw null; } } public sealed partial class PayloadOptions diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs index 426755ee7fe87e..d75a78073e4826 100644 --- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs +++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs @@ -8,6 +8,7 @@ using System.Formats.Nrbf.Utils; using System.Text; using System.Runtime.Serialization; +using System.Runtime.InteropServices; namespace System.Formats.Nrbf; @@ -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 HeaderSuffix => [1, 0, 0, 0, 0, 0, 0, 0]; + /// /// Checks if given buffer starts with NRBF payload header. /// /// The buffer to inspect. /// if it starts with NRBF payload header; otherwise, . - 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 bytes) + => bytes.Length >= SerializedStreamHeaderRecord.Size + && bytes[0] == (byte)SerializationRecordType.SerializedStreamHeader + && bytes.Slice(SerializedStreamHeaderRecord.Size - HeaderSuffix.Length, HeaderSuffix.Length).SequenceEqual(HeaderSuffix); /// /// Checks if given stream starts with NRBF payload header. @@ -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 buffer = stackalloc byte[SerializedStreamHeaderRecord.Size]; + stream.ReadExactly(buffer); #else + byte[] buffer = new byte[SerializedStreamHeaderRecord.Size]; int offset = 0; while (offset < buffer.Length) {