File: BinaryReaderExtensions.cs
Web Access
Project: ..\..\..\src\MSBuildTaskHost\MSBuildTaskHost.csproj (MSBuildTaskHost)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using Microsoft.Build.Framework;
 
namespace Microsoft.Build.Shared
{
    internal static class BinaryReaderExtensions
    {
#if !TASKHOST
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static string? ReadOptionalString(this BinaryReader reader)
        {
            return reader.ReadByte() == 0 ? null : reader.ReadString();
        }
 
#if !TASKHOST
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static int? ReadOptionalInt32(this BinaryReader reader)
        {
            return reader.ReadByte() == 0 ? null : reader.ReadInt32();
        }
 
#if !TASKHOST
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static int Read7BitEncodedInt(this BinaryReader reader)
        {
            // Read out an Int32 7 bits at a time.  The high bit
            // of the byte when on means to continue reading more bytes.
            int count = 0;
            int shift = 0;
            byte b;
            do
            {
                // Check for a corrupted stream.  Read a max of 5 bytes.
                // In a future version, add a DataFormatException.
                if (shift == 5 * 7)  // 5 bytes max per Int32, shift += 7
                {
                    throw new FormatException();
                }
 
                // ReadByte handles end of stream cases for us.
                b = reader.ReadByte();
                count |= (b & 0x7F) << shift;
                shift += 7;
            } while ((b & 0x80) != 0);
            return count;
        }
 
#if !TASKHOST
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static DateTime ReadTimestamp(this BinaryReader reader)
        {
            long timestampTicks = reader.ReadInt64();
            DateTimeKind kind = (DateTimeKind)reader.ReadInt32();
            var timestamp = new DateTime(timestampTicks, kind);
            return timestamp;
        }
 
#if !TASKHOST
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static BuildEventContext? ReadOptionalBuildEventContext(this BinaryReader reader)
        {
            if (reader.ReadByte() == 0)
            {
                return null;
            }
 
            return reader.ReadBuildEventContext();
        }
 
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static BuildEventContext ReadBuildEventContext(this BinaryReader reader)
        {
            int nodeId = reader.ReadInt32();
            int projectContextId = reader.ReadInt32();
            int targetId = reader.ReadInt32();
            int taskId = reader.ReadInt32();
            int submissionId = reader.ReadInt32();
            int projectInstanceId = reader.ReadInt32();
            int evaluationId = reader.ReadInt32();
 
            var buildEventContext = new BuildEventContext(submissionId, nodeId, evaluationId, projectInstanceId, projectContextId, targetId, taskId);
            return buildEventContext;
        }
#endif
 
#if !TASKHOST
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static unsafe Guid ReadGuid(this BinaryReader reader)
        {
            return new Guid(reader.ReadBytes(sizeof(Guid)));
        }
 
        public static void ReadExtendedBuildEventData(this BinaryReader reader, IExtendedBuildEventArgs data)
        {
            data.ExtendedType = reader.ReadString();
            data.ExtendedData = reader.ReadOptionalString();
 
            bool haveMetadata = reader.ReadBoolean();
            if (haveMetadata)
            {
                data.ExtendedMetadata = new Dictionary<string, string?>();
 
                int count = reader.Read7BitEncodedInt();
                for (int i = 0; i < count; i++)
                {
                    string key = reader.ReadString();
                    string? value = reader.ReadOptionalString();
 
                    data.ExtendedMetadata.Add(key, value);
                }
            }
            else
            {
                data.ExtendedMetadata = null;
            }
        }
    }
}