// Copyright Epic Games, Inc. All Rights Reserved.
using System.Globalization;
using System.Text;
using Grpc.Core;
namespace HordeServer.Utilities
{
///
/// Exception class designed to allow logging structured log messages
///
public class StructuredRpcException : RpcException
{
///
/// The format string with named parameters
///
public string Format { get; }
///
/// The argument list
///
public object[] Args { get; }
///
/// Constructor
///
/// Status code to return
/// The format string
/// Arguments for the format string
public StructuredRpcException(StatusCode statusCode, string format, params object[] args)
: base(new Status(statusCode, FormatMessage(format, args)))
{
Format = format;
Args = args;
}
///
/// Replace named arguments in the format message with their values
///
///
///
///
static string FormatMessage(string format, params object[] args)
{
string newFormat = ConvertToFormatString(format);
return String.Format(CultureInfo.CurrentCulture, newFormat, args);
}
///
/// Converts a named parameter format string to a String.Format style string
///
///
///
static string ConvertToFormatString(string format)
{
int argIdx = 0;
StringBuilder newFormat = new StringBuilder();
for (int idx = 0; idx < format.Length; idx++)
{
char character = format[idx];
newFormat.Append(character);
if (character == '{' && idx + 1 < format.Length)
{
char nextCharacter = format[idx + 1];
if ((nextCharacter >= 'a' && nextCharacter <= 'z') || (nextCharacter >= 'A' && nextCharacter <= 'Z') || nextCharacter == '_')
{
for (int endIdx = idx + 2; endIdx < format.Length; endIdx++)
{
if (format[endIdx] == ':' || format[endIdx] == '}')
{
newFormat.Append(argIdx++);
idx = endIdx - 1;
break;
}
}
}
}
}
return newFormat.ToString();
}
}
}