File: LayoutPairSource.cs
Web Access
Project: src\runtime\src\native\managed\cdac\Microsoft.Diagnostics.DataContractReader.DataGenerator\Microsoft.Diagnostics.DataContractReader.DataGenerator.csproj (Microsoft.Diagnostics.DataContractReader.DataGenerator)
// 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);
    }
}
""";
}