using System.Runtime.CompilerServices;
using static ParsingExtensions;

string input = "Name: Andrew; Age: 31";

string? name = null;
int age = 0;

if (input.TryParse($"Name: {Placeholder(ref name)}; Age: {Placeholder(ref age)}"))
{ 
  Console.WriteLine($"{name} {age}");
}
else
{
  Console.WriteLine("Does not match :(");
}

public static class ParsingExtensions
{
  public static PlaceholderCell<T?> Placeholder<T>(ref T? arg) => new(ref arg);

  public static bool TryParse(this string input, [InterpolatedStringHandlerArgument("input")] ref TryParseHandler handler)
  {
    return handler.Ok;
  }
}

public readonly unsafe ref struct PlaceholderCell<T>
{
  private readonly void* _ptr;
  public PlaceholderCell(ref T? arg) => _ptr = Unsafe.AsPointer(ref arg);

  public bool IsNull => _ptr is null;

  public ref T Get() => ref Unsafe.AsRef<T>(_ptr);
  public void Set(T arg) => Unsafe.Write(_ptr, arg);
}

[InterpolatedStringHandler]
public ref struct TryParseHandler
{
  private ReadOnlySpan<char> _input;
  private PlaceholderCell<string?> _substringPlaceholder;

  public TryParseHandler(int literalLength, int formattedCount, ReadOnlySpan<char> input)
  {
    _input = input;
    _substringPlaceholder = default;
    Ok = true;
  }

  public bool Ok { get; private set; }

  private bool Failed()
  {
    Ok = false;
    return false;
  }

  public bool AppendLiteral(string literal)
  {
    if (!_substringPlaceholder.IsNull)
    {
      var index = _input.IndexOf(literal, StringComparison.Ordinal);
      if (index < 1)
        return Failed();

      _substringPlaceholder.Set(_input.Slice(0, index).ToString());
      _substringPlaceholder = default;

      _input = _input.Slice(index + literal.Length);

      return true;
    }

    if (_input.StartsWith(literal, StringComparison.Ordinal))
    {
      _input = _input.Slice(literal.Length);
      return true;
    }

    return Failed();
  }

  public bool AppendFormatted(PlaceholderCell<string?> placeholder)
  {
    if (_input.Length == 0)
      return Failed();

    if (!_substringPlaceholder.IsNull)
      return Failed();

    _substringPlaceholder = placeholder;

    return true;
  }

  public bool AppendFormatted(PlaceholderCell<int> placeholder)
  {
    if (_input.Length == 0)
      return Failed();

    var startPos = 0;
    while (startPos < _input.Length && !char.IsDigit(_input[startPos]))
      startPos++;

    if (startPos >= _input.Length)
      return Failed();

    var endPos = startPos;
    while (endPos < _input.Length - 1 && char.IsDigit(_input[endPos + 1]))
      endPos++;

    var numberSlice = _input.Slice(startPos, endPos - startPos + 1);
    if (!int.TryParse(numberSlice, out var value))
      return Failed();

    placeholder.Set(value);

    if (!_substringPlaceholder.IsNull)
    {
      _substringPlaceholder.Set(_input.Slice(0, startPos).ToString());
      _substringPlaceholder = default;
    }

    _input = _input.Slice(endPos + 1);

    return true;
  }
}