|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Microsoft.Diagnostics.DataContractReader.DataGenerator;
/// <summary>
/// Source for the <c>LayoutPair</c> struct emitted into each consuming assembly via
/// <c>RegisterPostInitializationOutput</c>. Resolves fields across both a native cdac
/// descriptor and a managed type-metadata layout.
/// </summary>
internal static class LayoutPairSource
{
public const string HintName = "LayoutPair.g.cs";
public const string Namespace = "Microsoft.Diagnostics.DataContractReader.Generated";
public const string FullyQualifiedName = Namespace + ".LayoutPair";
public const string Source = """
// <auto-generated/>
#nullable enable
using System;
using Microsoft.Diagnostics.DataContractReader.Contracts;
namespace Microsoft.Diagnostics.DataContractReader.Generated;
internal readonly struct LayoutPair
{
public LayoutPair(Target.TypeInfo? nativeType, Target.TypeInfo? managedType)
{
NativeType = nativeType;
ManagedType = managedType;
}
public Target.TypeInfo? NativeType { get; }
public Target.TypeInfo? ManagedType { get; }
public ulong InstanceSize
=> NativeType?.Size
?? ManagedType?.Size
?? throw new InvalidOperationException("Neither layout has a known instance size.");
public bool TrySelect(TargetPointer address, out Target.TypeInfo type, out TargetPointer baseAddr, out string name, params ReadOnlySpan<string> names)
{
if (NativeType is Target.TypeInfo nt)
{
foreach (string candidate in names)
{
if (nt.Fields.ContainsKey(candidate))
{
type = nt; baseAddr = address; name = candidate; return true;
}
}
}
if (ManagedType is Target.TypeInfo mt)
{
foreach (string candidate in names)
{
if (mt.Fields.ContainsKey(candidate))
{
type = mt; baseAddr = address; name = candidate; return true;
}
}
}
type = default!; baseAddr = default; name = default!;
return false;
}
public void Select(TargetPointer address, out Target.TypeInfo type, out TargetPointer baseAddr, out string name, params ReadOnlySpan<string> names)
{
if (!TrySelect(address, out type, out baseAddr, out name, names))
{
throw new InvalidOperationException(FormatMissing(names));
}
}
private static string FormatMissing(ReadOnlySpan<string> names)
=> $"Field not found in any layout (names=[{string.Join(",", names.ToArray())}]).";
public static LayoutPair Resolve(Target target, string[] names)
{
Target.TypeInfo? native = null;
Target.TypeInfo? managed = null;
foreach (string name in names)
{
if (target.TryGetTypeInfo(name, out Target.TypeInfo n))
{
native = n;
break;
}
}
if (target.Contracts.TryGetContract(out IManagedTypeSource mts))
{
foreach (string name in names)
{
if (mts.TryGetTypeInfo(name, out Target.TypeInfo m))
{
managed = m;
break;
}
}
}
if (native is null && managed is null)
{
throw new InvalidOperationException(
$"No descriptor available for names=[{string.Join(",", names)}].");
}
return new LayoutPair(native, managed);
}
}
""";
}
|