You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
61 lines
2.0 KiB
61 lines
2.0 KiB
using System.Diagnostics; |
|
using System.Diagnostics.CodeAnalysis; |
|
using System.Text.Json; |
|
using System.Text.Json.Serialization; |
|
using NLog; |
|
|
|
namespace StabilityMatrix.Core.Processes; |
|
|
|
/// <summary> |
|
/// Defines a custom APC message, embeddable in a subprocess output stream. |
|
/// Format is as such: |
|
/// <code>"{APC}{CustomPrefix}(JsonSerialized ApcMessage){StChar}"</code> |
|
/// <example>"\u009f[SM;{"type":"input","data":"hello"}\u009c"</example> |
|
/// </summary> |
|
public readonly record struct ApcMessage |
|
{ |
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); |
|
|
|
public const char ApcChar = (char) 0x9F; |
|
public const char StChar = (char) 0x9C; |
|
public const string CustomPrefix = "[SM;"; |
|
|
|
[JsonPropertyName("type")] |
|
public required ApcType Type { get; init; } |
|
|
|
[JsonPropertyName("data")] |
|
public required string Data { get; init; } |
|
|
|
/// <summary> |
|
/// Attempts to extract an APC message from the given text |
|
/// </summary> |
|
/// <returns>ApcMessage struct</returns> |
|
public static bool TryParse(string value, [NotNullWhen(true)] out ApcMessage? message) |
|
{ |
|
message = null; |
|
var startIndex = value.IndexOf(ApcChar); |
|
if (startIndex == -1) return false; |
|
|
|
// Check the IdPrefix follows the ApcEscape |
|
var idIndex = value.IndexOf(CustomPrefix, startIndex + 1, StringComparison.Ordinal); |
|
if (idIndex == -1) return false; |
|
|
|
// Get the end index (ST escape) |
|
var stIndex = value.IndexOf(StChar, idIndex + CustomPrefix.Length); |
|
if (stIndex == -1) return false; |
|
|
|
// Extract the json string (between idIndex and stIndex) |
|
var json = value.Substring(idIndex + CustomPrefix.Length, stIndex - idIndex - CustomPrefix.Length); |
|
|
|
try |
|
{ |
|
message = JsonSerializer.Deserialize<ApcMessage>(json); |
|
return true; |
|
} |
|
catch (Exception e) |
|
{ |
|
Logger.Warn($"Failed to deserialize APC message: {e.Message}"); |
|
return false; |
|
} |
|
} |
|
}
|
|
|