/// <summary> /// Given the metadata for an event and an event payload, decode and deserialize the event payload. /// </summary> internal static object[] DecodePayload(ref EventSource.EventMetadata metadata, ReadOnlySpan <Byte> payload) { ParameterInfo[] parameters = metadata.Parameters; object[] decodedFields = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { // It is possible that an older version of the event was emitted. // If this happens, the payload might be missing arguments at the end. // We can just leave these unset. if (payload.Length <= 0) { break; } Type parameterType = parameters[i].ParameterType; if (parameterType == typeof(IntPtr)) { if (IntPtr.Size == 8) { // Payload is automatically updated to point to the next piece of data. decodedFields[i] = (IntPtr)ReadUnalignedUInt64(ref payload); } else if (IntPtr.Size == 4) { decodedFields[i] = (IntPtr)MemoryMarshal.Read <Int32>(payload); payload = payload.Slice(IntPtr.Size); } else { Debug.Assert(false, "Unsupported pointer size."); } } else if (parameterType == typeof(int)) { decodedFields[i] = MemoryMarshal.Read <int>(payload); payload = payload.Slice(sizeof(int)); } else if (parameterType == typeof(uint)) { decodedFields[i] = MemoryMarshal.Read <uint>(payload); payload = payload.Slice(sizeof(uint)); } else if (parameterType == typeof(long)) { // Payload is automatically updated to point to the next piece of data. decodedFields[i] = (long)ReadUnalignedUInt64(ref payload); } else if (parameterType == typeof(ulong)) { // Payload is automatically updated to point to the next piece of data. decodedFields[i] = ReadUnalignedUInt64(ref payload); } else if (parameterType == typeof(byte)) { decodedFields[i] = MemoryMarshal.Read <byte>(payload); payload = payload.Slice(sizeof(byte)); } else if (parameterType == typeof(sbyte)) { decodedFields[i] = MemoryMarshal.Read <sbyte>(payload); payload = payload.Slice(sizeof(sbyte)); } else if (parameterType == typeof(short)) { decodedFields[i] = MemoryMarshal.Read <short>(payload); payload = payload.Slice(sizeof(short)); } else if (parameterType == typeof(ushort)) { decodedFields[i] = MemoryMarshal.Read <ushort>(payload); payload = payload.Slice(sizeof(ushort)); } else if (parameterType == typeof(float)) { decodedFields[i] = MemoryMarshal.Read <float>(payload); payload = payload.Slice(sizeof(float)); } else if (parameterType == typeof(double)) { // Payload is automatically updated to point to the next piece of data. Int64 doubleBytes = (Int64)ReadUnalignedUInt64(ref payload); decodedFields[i] = BitConverter.Int64BitsToDouble(doubleBytes); } else if (parameterType == typeof(bool)) { // The manifest defines a bool as a 32bit type (WIN32 BOOL), not 1 bit as CLR Does. decodedFields[i] = (MemoryMarshal.Read <int>(payload) == 1); payload = payload.Slice(sizeof(int)); } else if (parameterType == typeof(Guid)) { // Payload is automatically updated to point to the next piece of data. decodedFields[i] = ReadUnalignedGuid(ref payload); } else if (parameterType == typeof(char)) { decodedFields[i] = MemoryMarshal.Read <char>(payload); payload = payload.Slice(sizeof(char)); } else if (parameterType == typeof(string)) { ReadOnlySpan <char> charPayload = MemoryMarshal.Cast <byte, char>(payload); int charCount = 0; foreach (char c in charPayload) { if (c == '\0') { break; } charCount++; } string val = new string(charPayload.ToArray(), 0, charCount); payload = payload.Slice((val.Length + 1) * sizeof(char)); decodedFields[i] = val; } else { Debug.Assert(false, "Unsupported type encountered."); } } return(decodedFields); }
/// <summary> /// Given the metadata for an event and an event payload, decode and deserialize the event payload. /// </summary> internal static object[] DecodePayload(ref EventSource.EventMetadata metadata, ReadOnlySpan <byte> payload) { ParameterInfo[] parameters = metadata.Parameters; object[] decodedFields = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { // It is possible that an older version of the event was emitted. // If this happens, the payload might be missing arguments at the end. // We can just leave these unset. if (payload.Length <= 0) { break; } Type parameterType = parameters[i].ParameterType; if (parameterType == typeof(IntPtr)) { if (IntPtr.Size == 8) { decodedFields[i] = (IntPtr)BinaryPrimitives.ReadInt64LittleEndian(payload); } else { decodedFields[i] = (IntPtr)BinaryPrimitives.ReadInt32LittleEndian(payload); } payload = payload.Slice(IntPtr.Size); } else if (parameterType == typeof(int)) { decodedFields[i] = BinaryPrimitives.ReadInt32LittleEndian(payload); payload = payload.Slice(sizeof(int)); } else if (parameterType == typeof(uint)) { decodedFields[i] = BinaryPrimitives.ReadUInt32LittleEndian(payload); payload = payload.Slice(sizeof(uint)); } else if (parameterType == typeof(long)) { decodedFields[i] = BinaryPrimitives.ReadInt64LittleEndian(payload); payload = payload.Slice(sizeof(long)); } else if (parameterType == typeof(ulong)) { decodedFields[i] = BinaryPrimitives.ReadUInt64LittleEndian(payload); payload = payload.Slice(sizeof(ulong)); } else if (parameterType == typeof(byte)) { decodedFields[i] = MemoryMarshal.Read <byte>(payload); payload = payload.Slice(sizeof(byte)); } else if (parameterType == typeof(sbyte)) { decodedFields[i] = MemoryMarshal.Read <sbyte>(payload); payload = payload.Slice(sizeof(sbyte)); } else if (parameterType == typeof(short)) { decodedFields[i] = BinaryPrimitives.ReadInt16LittleEndian(payload); payload = payload.Slice(sizeof(short)); } else if (parameterType == typeof(ushort)) { decodedFields[i] = BinaryPrimitives.ReadUInt16LittleEndian(payload); payload = payload.Slice(sizeof(ushort)); } else if (parameterType == typeof(float)) { decodedFields[i] = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(payload)); payload = payload.Slice(sizeof(float)); } else if (parameterType == typeof(double)) { decodedFields[i] = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(payload)); payload = payload.Slice(sizeof(double)); } else if (parameterType == typeof(bool)) { // The manifest defines a bool as a 32bit type (WIN32 BOOL), not 1 bit as CLR Does. decodedFields[i] = (BinaryPrimitives.ReadInt32LittleEndian(payload) == 1); payload = payload.Slice(sizeof(int)); } else if (parameterType == typeof(Guid)) { const int sizeOfGuid = 16; decodedFields[i] = new Guid(payload.Slice(0, sizeOfGuid)); payload = payload.Slice(sizeOfGuid); } else if (parameterType == typeof(char)) { decodedFields[i] = (char)BinaryPrimitives.ReadUInt16LittleEndian(payload); payload = payload.Slice(sizeof(char)); } else if (parameterType == typeof(string)) { // Try to find null terminator (0x00) from the byte span // NOTE: we do this by hand instead of using IndexOf because payload may be unaligned due to // mixture of different types being stored in the same buffer. (see eventpipe.cpp:CopyData) int byteCount = -1; for (int j = 1; j < payload.Length; j += 2) { if (payload[j - 1] == (byte)(0) && payload[j] == (byte)(0)) { byteCount = j + 1; break; } } ReadOnlySpan <char> charPayload; if (byteCount < 0) { charPayload = MemoryMarshal.Cast <byte, char>(payload); payload = default; } else { charPayload = MemoryMarshal.Cast <byte, char>(payload.Slice(0, byteCount - 2)); payload = payload.Slice(byteCount); } decodedFields[i] = BitConverter.IsLittleEndian ? new string(charPayload) : Encoding.Unicode.GetString(MemoryMarshal.Cast <char, byte>(charPayload)); } else { Debug.Fail("Unsupported type encountered."); } } return(decodedFields); }
/// <summary> /// Given the metadata for an event and an event payload, decode and deserialize the event payload. /// </summary> internal static object[] DecodePayload(ref EventSource.EventMetadata metadata, ReadOnlySpan <byte> payload) { ParameterInfo[] parameters = metadata.Parameters; object[] decodedFields = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { // It is possible that an older version of the event was emitted. // If this happens, the payload might be missing arguments at the end. // We can just leave these unset. if (payload.Length <= 0) { break; } Type parameterType = parameters[i].ParameterType; if (parameterType == typeof(IntPtr)) { if (IntPtr.Size == 8) { decodedFields[i] = (IntPtr)BinaryPrimitives.ReadInt64LittleEndian(payload); } else { decodedFields[i] = (IntPtr)BinaryPrimitives.ReadInt32LittleEndian(payload); } payload = payload.Slice(IntPtr.Size); } else if (parameterType == typeof(int)) { decodedFields[i] = BinaryPrimitives.ReadInt32LittleEndian(payload); payload = payload.Slice(sizeof(int)); } else if (parameterType == typeof(uint)) { decodedFields[i] = BinaryPrimitives.ReadUInt32LittleEndian(payload); payload = payload.Slice(sizeof(uint)); } else if (parameterType == typeof(long)) { decodedFields[i] = BinaryPrimitives.ReadInt64LittleEndian(payload); payload = payload.Slice(sizeof(long)); } else if (parameterType == typeof(ulong)) { decodedFields[i] = BinaryPrimitives.ReadUInt64LittleEndian(payload); payload = payload.Slice(sizeof(ulong)); } else if (parameterType == typeof(byte)) { decodedFields[i] = MemoryMarshal.Read <byte>(payload); payload = payload.Slice(sizeof(byte)); } else if (parameterType == typeof(sbyte)) { decodedFields[i] = MemoryMarshal.Read <sbyte>(payload); payload = payload.Slice(sizeof(sbyte)); } else if (parameterType == typeof(short)) { decodedFields[i] = BinaryPrimitives.ReadInt16LittleEndian(payload); payload = payload.Slice(sizeof(short)); } else if (parameterType == typeof(ushort)) { decodedFields[i] = BinaryPrimitives.ReadUInt16LittleEndian(payload); payload = payload.Slice(sizeof(ushort)); } else if (parameterType == typeof(float)) { decodedFields[i] = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(payload)); payload = payload.Slice(sizeof(float)); } else if (parameterType == typeof(double)) { decodedFields[i] = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(payload)); payload = payload.Slice(sizeof(double)); } else if (parameterType == typeof(bool)) { // The manifest defines a bool as a 32bit type (WIN32 BOOL), not 1 bit as CLR Does. decodedFields[i] = (BinaryPrimitives.ReadInt32LittleEndian(payload) == 1); payload = payload.Slice(sizeof(int)); } else if (parameterType == typeof(Guid)) { const int sizeOfGuid = 16; decodedFields[i] = new Guid(payload.Slice(0, sizeOfGuid)); payload = payload.Slice(sizeOfGuid); } else if (parameterType == typeof(char)) { decodedFields[i] = (char)BinaryPrimitives.ReadUInt16LittleEndian(payload); payload = payload.Slice(sizeof(char)); } else if (parameterType == typeof(string)) { ReadOnlySpan <char> charPayload = MemoryMarshal.Cast <byte, char>(payload); int charCount = charPayload.IndexOf('\0'); if (charCount < 0) { payload = default; } else { charPayload = charPayload.Slice(0, charCount); payload = payload.Slice((charCount + 1) * sizeof(char)); } decodedFields[i] = BitConverter.IsLittleEndian ? new string(charPayload) : Encoding.Unicode.GetString(MemoryMarshal.Cast <char, byte>(charPayload)); } else { Debug.Assert(false, "Unsupported type encountered."); } } return(decodedFields); }