瀏覽代碼

prepo: Add a MessagePack object formatter (#1034)

jduncanator 6 年之前
父節點
當前提交
82c3df83c4

+ 1 - 0
Ryujinx.Common/Ryujinx.Common.csproj

@@ -28,6 +28,7 @@
 
   <ItemGroup>
     <PackageReference Include="JsonPrettyPrinter" Version="1.0.1.1" />
+    <PackageReference Include="MsgPack.Cli" Version="1.0.1" />
     <PackageReference Include="Utf8Json" Version="1.3.7" /><PackageReference Include="OpenTK.NetStandard" Version="1.0.5.12" />
     <PackageReference Include="SharpFontCore" Version="0.1.1" />
   </ItemGroup>

+ 302 - 0
Ryujinx.Common/Utilities/MessagePackObjectFormatter.cs

@@ -0,0 +1,302 @@
+using MsgPack;
+using System;
+using System.Text;
+
+namespace Ryujinx.Common.Utilities
+{
+    public static class MessagePackObjectFormatter
+    {
+        public static string ToString(this MessagePackObject obj, bool pretty)
+        {
+            if (pretty)
+            {
+                return Format(obj);
+            }
+            else
+            {
+                return obj.ToString();
+            }
+        }
+
+        public static string Format(MessagePackObject obj)
+        {
+            var builder = new IndentedStringBuilder();
+
+            FormatMsgPackObj(obj, builder);
+
+            return builder.ToString();
+        }
+
+        private static void FormatMsgPackObj(MessagePackObject obj, IndentedStringBuilder builder)
+        {
+            if (obj.IsMap || obj.IsDictionary)
+            {
+                FormatMsgPackMap(obj, builder);
+            }
+            else if (obj.IsArray || obj.IsList)
+            {
+                FormatMsgPackArray(obj, builder);
+            }
+            else if (obj.IsNil)
+            {
+                builder.Append("null");
+            }
+            else
+            {
+                var literal = obj.ToObject();
+
+                if (literal is String)
+                {
+                    builder.AppendQuotedString(obj.AsStringUtf16());
+                }
+                else if (literal is byte[] byteArray)
+                {
+                    FormatByteArray(byteArray, builder);
+                }
+                else if (literal is MessagePackExtendedTypeObject extObject)
+                {
+                    builder.Append('{');
+
+                    // Indent
+                    builder.IncreaseIndent()
+                           .AppendLine();
+
+                    // Print TypeCode field
+                    builder.AppendQuotedString("TypeCode")
+                           .Append(": ")
+                           .Append(extObject.TypeCode)
+                           .AppendLine(",");
+
+                    // Print Value field
+                    builder.AppendQuotedString("Value")
+                           .Append(": ");
+
+                    FormatByteArrayAsString(extObject.GetBody(), builder, true);
+
+                    // Unindent
+                    builder.DecreaseIndent()
+                           .AppendLine();
+
+                    builder.Append('}');
+                }
+                else
+                {
+                    builder.Append(literal);
+                }
+            }
+        }
+
+        private static void FormatByteArray(byte[] arr, IndentedStringBuilder builder)
+        {
+            builder.Append("[ ");
+
+            foreach (var b in arr)
+            {
+                builder.Append("0x");
+                builder.Append(ToHexChar(b >> 4));
+                builder.Append(ToHexChar(b & 0xF));
+                builder.Append(", ");
+            }
+
+            // Remove trailing comma
+            builder.Remove(builder.Length - 2, 2);
+
+            builder.Append(" ]");
+        }
+
+        private static void FormatByteArrayAsString(byte[] arr, IndentedStringBuilder builder, bool withPrefix)
+        {
+            builder.Append('"');
+
+            if (withPrefix)
+            {
+                builder.Append("0x");
+            }
+
+            foreach (var b in arr)
+            {
+                builder.Append(ToHexChar(b >> 4));
+                builder.Append(ToHexChar(b & 0xF));
+            }
+
+            builder.Append('"');
+        }
+
+        private static void FormatMsgPackMap(MessagePackObject obj, IndentedStringBuilder builder)
+        {
+            var map = obj.AsDictionary();
+
+            builder.Append('{');
+
+            // Indent
+            builder.IncreaseIndent()
+                   .AppendLine();
+
+            foreach (var item in map)
+            {
+                FormatMsgPackObj(item.Key, builder);
+
+                builder.Append(": ");
+
+                FormatMsgPackObj(item.Value, builder);
+
+                builder.AppendLine(",");
+            }
+
+            // Remove the trailing new line and comma
+            builder.TrimLastLine()
+                   .Remove(builder.Length - 1, 1);
+
+            // Unindent
+            builder.DecreaseIndent()
+                   .AppendLine();
+
+            builder.Append('}');
+        }
+
+        private static void FormatMsgPackArray(MessagePackObject obj, IndentedStringBuilder builder)
+        {
+            var arr = obj.AsList();
+
+            builder.Append("[ ");
+
+            foreach (var item in arr)
+            {
+                FormatMsgPackObj(item, builder);
+
+                builder.Append(", ");
+            }
+
+            // Remove trailing comma
+            builder.Remove(builder.Length - 2, 2);
+
+            builder.Append(" ]");
+        }
+
+        private static char ToHexChar(int b)
+        {
+            if (b < 10)
+            {
+                return unchecked((char)('0' + b));
+            }
+            else
+            {
+                return unchecked((char)('A' + (b - 10)));
+            }
+        }
+
+        internal class IndentedStringBuilder
+        {
+            const string DefaultIndent = "    ";
+
+            private int _indentCount = 0;
+            private int _newLineIndex = 0;
+            private StringBuilder _builder;
+
+            public string IndentString { get; set; } = DefaultIndent;
+
+            public IndentedStringBuilder(StringBuilder builder)
+            {
+                _builder = builder;
+            }
+
+            public IndentedStringBuilder()
+                : this(new StringBuilder())
+            { }
+
+            public IndentedStringBuilder(string str)
+                : this(new StringBuilder(str))
+            { }
+
+            public IndentedStringBuilder(int length)
+                : this(new StringBuilder(length))
+            { }
+
+            public int Length { get => _builder.Length; }
+
+            public IndentedStringBuilder IncreaseIndent()
+            {
+                _indentCount++;
+
+                return this;
+            }
+
+            public IndentedStringBuilder DecreaseIndent()
+            {
+                _indentCount--;
+
+                return this;
+            }
+
+            public IndentedStringBuilder Append(char value)
+            {
+                _builder.Append(value);
+
+                return this;
+            }
+
+            public IndentedStringBuilder Append(string value)
+            {
+                _builder.Append(value);
+
+                return this;
+            }
+
+            public IndentedStringBuilder Append(object value)
+            {
+                this.Append(value.ToString());
+
+                return this;
+            }
+
+            public IndentedStringBuilder AppendQuotedString(string value)
+            {
+                _builder.Append('"');
+                _builder.Append(value);
+                _builder.Append('"');
+
+                return this;
+            }
+
+            public IndentedStringBuilder AppendLine()
+            {
+                _newLineIndex = _builder.Length;
+
+                _builder.AppendLine();
+
+                for (int i = 0; i < _indentCount; i++)
+                    _builder.Append(IndentString);
+
+                return this;
+            }
+
+            public IndentedStringBuilder AppendLine(string value)
+            {
+                _builder.Append(value);
+
+                this.AppendLine();
+
+                return this;
+            }
+
+            public IndentedStringBuilder TrimLastLine()
+            {
+                _builder.Remove(_newLineIndex, _builder.Length - _newLineIndex);
+
+                return this;
+            }
+
+            public IndentedStringBuilder Remove(int startIndex, int length)
+            {
+                _builder.Remove(startIndex, length);
+
+                return this;
+            }
+
+            public override string ToString()
+            {
+                return _builder.ToString();
+            }
+        }
+    }
+}

+ 2 - 3
Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs

@@ -2,11 +2,10 @@ using MsgPack;
 using MsgPack.Serialization;
 using Ryujinx.Common;
 using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
 using Ryujinx.HLE.HOS.Services.Account.Acc;
 using Ryujinx.HLE.Utilities;
-using System.IO;
 using System.Text;
-using Utf8Json;
 
 namespace Ryujinx.HLE.HOS.Services.Prepo
 {
@@ -117,7 +116,7 @@ namespace Ryujinx.HLE.HOS.Services.Prepo
             }
 
             builder.AppendLine($" Room: {room}");
-            builder.AppendLine($" Report: {deserializedReport}");
+            builder.AppendLine($" Report: {MessagePackObjectFormatter.Format(deserializedReport)}");
 
             return builder.ToString();
         }