Evan Husted 2317c06364 misc: small Avalonia project restructure
Moved AppLibrary, Configuration, and PlayReport namespaces to Ryujinx.Systems, add the compat list stuff in the base Ryujinx.Systems namespace.
Moved the compatibility UI stuff to the proper UI view/viewmodel folders.
2025-03-04 18:01:48 -06:00

161 lines
6.5 KiB
C#

using MsgPack;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.Ava.Systems.PlayReport
{
/// <summary>
/// The base input data to a ValueFormatter delegate,
/// and the matched <see cref="MessagePackObject"/> from the Play Report.
/// </summary>
public readonly struct Value
{
public Value(MessagePackObject packedValue)
{
PackedValue = packedValue;
}
/// <summary>
/// The matched value from the Play Report.
/// </summary>
public MessagePackObject PackedValue { get; init; }
/// <summary>
/// Access the <see cref="PackedValue"/> as its underlying .NET type.<br/>
///
/// Does not seem to work well with comparing numeric types,
/// so use XValue properties for that.
/// </summary>
public object BoxedValue => PackedValue.ToObject();
public override string ToString()
{
object boxed = BoxedValue;
return boxed == null
? "null"
: boxed.ToString();
}
public static implicit operator Value(MessagePackObject matched) => new(matched);
public static Value[] ConvertPackedObjects(IEnumerable<MessagePackObject> packObjects)
=> packObjects.Select(packObject => new Value(packObject)).ToArray();
public static Dictionary<string, Value> ConvertPackedObjectMap(Dictionary<string, MessagePackObject> packObjects)
=> packObjects.ToDictionary(
x => x.Key,
x => new Value(x.Value)
);
#region AsX accessors
public bool BooleanValue => PackedValue.AsBoolean();
public byte ByteValue => PackedValue.AsByte();
public sbyte SByteValue => PackedValue.AsSByte();
public short ShortValue => PackedValue.AsInt16();
public ushort UShortValue => PackedValue.AsUInt16();
public int IntValue => PackedValue.AsInt32();
public uint UIntValue => PackedValue.AsUInt32();
public long LongValue => PackedValue.AsInt64();
public ulong ULongValue => PackedValue.AsUInt64();
public float FloatValue => PackedValue.AsSingle();
public double DoubleValue => PackedValue.AsDouble();
public string StringValue => PackedValue.AsString();
public Span<byte> BinaryValue => PackedValue.AsBinary();
#endregion
}
/// <summary>
/// A potential formatted value returned by a ValueFormatter delegate.
/// </summary>
public readonly struct FormattedValue
{
/// <summary>
/// Was any handler able to match anything in the Play Report?
/// </summary>
public bool Handled { get; private init; }
/// <summary>
/// Did the handler request the caller of the <see cref="Analyzer"/> to reset the existing value?
/// </summary>
public bool Reset { get; private init; }
/// <summary>
/// The formatted value, only present if <see cref="Handled"/> is true, and <see cref="Reset"/> is false.
/// </summary>
public string FormattedString { get; private init; }
/// <summary>
/// The intended path of execution for having a string to return: simply return the string.
/// This implicit conversion will make the struct for you.<br/><br/>
///
/// If the input is null, <see cref="Unhandled"/> is returned.
/// </summary>
/// <param name="formattedValue">The formatted string value.</param>
/// <returns>The automatically constructed <see cref="FormattedValue"/> struct.</returns>
public static implicit operator FormattedValue(string formattedValue)
=> formattedValue is not null
? new FormattedValue { Handled = true, FormattedString = formattedValue }
: Unhandled;
public override string ToString()
{
if (!Handled)
return "<Unhandled>";
if (Reset)
return "<Reset>";
return FormattedString;
}
/// <summary>
/// Return this to tell the caller there is no value to return.
/// </summary>
public static readonly FormattedValue Unhandled = default;
/// <summary>
/// Return this to suggest the caller reset the value it's using the <see cref="Analyzer"/> for.
/// </summary>
public static readonly FormattedValue ForceReset = new() { Handled = true, Reset = true };
/// <summary>
/// A delegate singleton you can use to always return <see cref="ForceReset"/> in a <see cref="SingleValueFormatter"/>.
/// </summary>
public static readonly SingleValueFormatter SingleAlwaysResets = _ => ForceReset;
/// <summary>
/// A delegate singleton you can use to always return <see cref="ForceReset"/> in a <see cref="MultiValueFormatter"/>.
/// </summary>
public static readonly MultiValueFormatter MultiAlwaysResets = _ => ForceReset;
/// <summary>
/// A delegate singleton you can use to always return <see cref="ForceReset"/> in a <see cref="SparseMultiValueFormatter"/>.
/// </summary>
public static readonly SparseMultiValueFormatter SparseMultiAlwaysResets = _ => ForceReset;
/// <summary>
/// A delegate factory you can use to always return the specified
/// <paramref name="formattedValue"/> in a <see cref="SingleValueFormatter"/>.
/// </summary>
/// <param name="formattedValue">The string to always return for this delegate instance.</param>
public static SingleValueFormatter SingleAlwaysReturns(string formattedValue) => _ => formattedValue;
/// <summary>
/// A delegate factory you can use to always return the specified
/// <paramref name="formattedValue"/> in a <see cref="MultiValueFormatter"/>.
/// </summary>
/// <param name="formattedValue">The string to always return for this delegate instance.</param>
public static MultiValueFormatter MultiAlwaysReturns(string formattedValue) => _ => formattedValue;
/// <summary>
/// A delegate factory you can use to always return the specified
/// <paramref name="formattedValue"/> in a <see cref="SparseMultiValueFormatter"/>.
/// </summary>
/// <param name="formattedValue">The string to always return for this delegate instance.</param>
public static SparseMultiValueFormatter SparseMultiAlwaysReturns(string formattedValue) => _ => formattedValue;
}
}