/// <summary>
        /// Disassembles the specified hex code <paramref name="hex"/> and returns the result.
        /// </summary>
        /// <returns>The resulting assembly code from the disassembled hex code.</returns>
        /// <example>
        /// <code>
        /// string assembly = Disassembler.Disassemble ("00008052");
        /// Console.WriteLine (assembly);
        /// </code>
        /// </example>
        /// <exception cref="System.Net.WebException">
        /// Thrown when the hex code is invalid.
        /// </exception>
        /// See <see cref="Disassembler.MultiDisassemble(string[], ArchSelection, int?)"/> to disassemble an array of elements of hex code.
        /// <param name="hex">The hex code string to disassemble.</param>
        /// <param name="archSelection">The architecture that the hex code <paramref name="hex"/> corresponds to.</param>
        /// <param name="offset">The offset integer that the hex code <paramref name="hex"/> is shifted by.</param>
        public static string Disassemble(string hex, ArchSelection archSelection = ArchSelection.AArch64, int?offset = null)
        {
            var webClient = new WebClient();

            webClient.Headers[HttpRequestHeader.ContentType] = "application/json";

            string json   = $"{{\"hex\":\"{hex}\",\"offset\":\"0x{offset ?? 0}\",\"arch\":\"{ArchToString(archSelection)}\"}}";
            string result = webClient.UploadString("https://armconverter.com/api/convert", json);

            switch (archSelection)
            {
            case ArchSelection.AArch64:
                string aArch64Assembly = AArch64Json.FromJson(result).Asm.AArch64[1].ToString();
                return(aArch64Assembly);

            case ArchSelection.AArch32:
                string aArch32Assembly = AArch32Json.FromJson(result).Asm.AArch32[1].ToString();
                return(aArch32Assembly);

            case ArchSelection.AArch32BigEndian:
                string aArch32BigEndianAssembly = AArch32BigEndianJson.FromJson(result).Asm.AArch32BigEndian[1].ToString();
                return(aArch32BigEndianAssembly);

            case ArchSelection.Thumb:
                string thumbAssembly = ThumbJson.FromJson(result).Asm.Thumb[1].ToString();
                return(thumbAssembly);

            case ArchSelection.ThumbBigEndian:
                string thumbBigEndianAssembly = ThumbBigEndianJson.FromJson(result).Asm.ThumbBigEndian[1].ToString();
                return(thumbBigEndianAssembly);

            default:
                return(null);
            }
        }
        /// <summary>
        /// Asynchronously disassembles the specified hex code array <paramref name="hex"/> and returns the result, this method does not block the calling thread.
        /// </summary>
        /// <returns>The resulting assembly code array from the disassembled hex code.</returns>
        /// <example>
        /// <code>
        /// string[] hex = { "00008052", "C0035FD6", "230040B9", "631C0012", "7F840171", "E1000054", "21010010", "FF8301D1", "FD2FFF17" };
        /// string[] assembly = await Disassembler.MultiDisassembleAsync (hex);
        /// Console.WriteLine (string.Join ('\n', assembly));
        /// </code>
        /// </example>
        /// <exception cref ="System.InvalidOperationException">
        /// Thrown when trying to convert one of the ARM64 big-endian hex code elements to assembly code.
        /// </exception>
        /// <exception cref="System.Net.WebException">
        /// Thrown when one of the elements of the hex code is invalid.
        /// </exception>
        /// See <see cref="Disassembler.DisassembleAsync(string, ArchSelection, int?)"/> to disassemble a single line of hex code asynchronously.
        /// <param name="hex">The hex code string array to disassemble.</param>
        /// <param name="archSelection">The architecture that the hex code <paramref name="hex"/> corresponds to.</param>
        /// <param name="offset">The offset integer that the hex code <paramref name="hex"/> is shifted by.</param>
        public static async Task <string[]> MultiDisassembleAsync(string[] hex, ArchSelection archSelection = ArchSelection.AArch64, int?offset = null)
        {
            var assembly = new List <string> ();

            foreach (string element in hex)
            {
                var webClient = new WebClient();
                webClient.Headers[HttpRequestHeader.ContentType] = "application/json";

                string json   = $"{{\"hex\":\"{element}\",\"offset\":\"0x{offset ?? 0}\",\"arch\":\"{ArchToString(archSelection)}\"}}";
                string result = await webClient.UploadStringTaskAsync("https://armconverter.com/api/convert", json);

                switch (archSelection)
                {
                case ArchSelection.AArch64:
                    var aArch64Json = await AArch64Json.FromJsonAsync(result);

                    string aArch64Assembly = aArch64Json.Asm.AArch64[1].ToString();
                    assembly.Add(aArch64Assembly);
                    break;

                case ArchSelection.AArch32:
                    var aArch32Json = await AArch32Json.FromJsonAsync(result);

                    string aArch32Assembly = aArch32Json.Asm.AArch32[1].ToString();
                    assembly.Add(aArch32Assembly);
                    break;

                case ArchSelection.AArch32BigEndian:
                    var aArch32BigEndianJson = await AArch32BigEndianJson.FromJsonAsync(result);

                    string aArch32BigEndianAssembly = aArch32BigEndianJson.Asm.AArch32BigEndian[1].ToString();
                    assembly.Add(aArch32BigEndianAssembly);
                    break;

                case ArchSelection.Thumb:
                    var thumbJson = await ThumbJson.FromJsonAsync(result);

                    string thumbAssembly = thumbJson.Asm.Thumb[1].ToString();
                    assembly.Add(thumbAssembly);
                    break;

                case ArchSelection.ThumbBigEndian:
                    var thumbBigEndianJson = await ThumbBigEndianJson.FromJsonAsync(result);

                    string thumbBigEndianAssembly = thumbBigEndianJson.Asm.ThumbBigEndian[1].ToString();
                    assembly.Add(thumbBigEndianAssembly);
                    break;

                default:
                    return(null);
                }
            }

            return(assembly.ToArray());
        }
        /// <summary>
        /// Assembles the specified assembly code <paramref name="assembly"/> and returns the result.
        /// </summary>
        /// <returns>The resulting hex code from the assembled assembly code.</returns>
        /// <example>
        /// <code>
        /// string hex = Assembler.Assemble ("mov w0, #0");
        /// Console.WriteLine (hex);
        /// </code>
        /// </example>
        /// <exception cref="System.FormatException">
        /// Thrown when an error occurs after attempting to assemble the assembly code.
        /// </exception>
        /// See <see cref="Assembler.MultiAssemble(string[], ArchSelection, int?)"/> to assemble an array of lines of assemble code.
        /// <param name="assembly">The assembly code string to assemble.</param>
        /// <param name="archSelection">The architecture that the assembly code <paramref name="assembly"/> corresponds to.</param>
        /// <param name="offset">The offset integer that the resulting hex code should be shifted by.</param>
        public static string Assemble(string assembly, ArchSelection archSelection = ArchSelection.AArch64, int?offset = null)
        {
            var webClient = new WebClient();

            webClient.Headers[HttpRequestHeader.ContentType] = "application/json";

            string json   = $"{{\"asm\":\"{assembly}\",\"offset\":\"0x{offset ?? 0}\",\"arch\":\"{ArchToString(archSelection)}\"}}";
            string result = webClient.UploadString("https://armconverter.com/api/convert", json);

            switch (archSelection)
            {
            case ArchSelection.AArch64:
                string aArch64Hex = AArch64Json.FromJson(result).Hex.AArch64[1].ToString().Replace("### ", string.Empty);

                if (ExceptionMessageList.Contains(aArch64Hex))
                {
                    throw new FormatException(aArch64Hex);
                }

                return(aArch64Hex);

            case ArchSelection.AArch32:
                string aArch32Hex = AArch32Json.FromJson(result).Hex.AArch32[1].ToString().Replace("### ", string.Empty);

                if (ExceptionMessageList.Contains(aArch32Hex))
                {
                    throw new FormatException(aArch32Hex);
                }

                return(aArch32Hex);

            case ArchSelection.AArch32BigEndian:
                string aArch32BigEndianHex = AArch32BigEndianJson.FromJson(result).Hex.AArch32BigEndian[1].ToString().Replace("### ", string.Empty);

                if (ExceptionMessageList.Contains(aArch32BigEndianHex))
                {
                    throw new FormatException(aArch32BigEndianHex);
                }

                return(aArch32BigEndianHex);

            case ArchSelection.Thumb:
                string thumbHex = ThumbJson.FromJson(result).Hex.Thumb[1].ToString().Replace("### ", string.Empty);

                if (ExceptionMessageList.Contains(thumbHex))
                {
                    throw new FormatException(thumbHex);
                }

                return(thumbHex);

            case ArchSelection.ThumbBigEndian:
                string thumbBigEndianHex = ThumbBigEndianJson.FromJson(result).Hex.ThumbBigEndian[1].ToString().Replace("### ", string.Empty);

                if (ExceptionMessageList.Contains(thumbBigEndianHex))
                {
                    throw new FormatException(thumbBigEndianHex);
                }

                return(thumbBigEndianHex);

            default:
                return(null);
            }
        }
        /// <summary>
        /// Asynchronously assembles the specified assembly code array <paramref name="assembly"/> and returns the result, this method does not block the calling thread.
        /// </summary>
        /// <returns>The resulting hex code array from the assembled assembly code.</returns>
        /// <example>
        /// <code>
        /// string[] assembly = { "mov w0, #0", "ret", "ldr w3, [x1]", "and w3, w3, #0xff", "cmp w3, #0x61", "b.ne #0x1c", "adr x1, #0x24", "sub sp, sp, #0x60", "b #0xfffffffffffcbff4" };
        /// string[] hex = await Assembler.MultiAssembleAsync (assembly);
        /// Console.WriteLine (string.Join ('\n', hex));
        /// </code>
        /// </example>
        /// <exception cref="System.FormatException">
        /// Thrown when an error occurs after attempting to assemble one of the lines of the assembly code.
        /// </exception>
        /// See <see cref="Assembler.AssembleAsync(string, ArchSelection, int?)"/> to assemble a single line of assemble code asynchronously.
        /// <param name="assembly">The assembly code string array to assemble.</param>
        /// <param name="archSelection">The architecture that the assembly code <paramref name="assembly"/> corresponds to.</param>
        /// <param name="offset">The offset integer that the resulting hex code should be shifted by.</param>
        public static async Task <string[]> MultiAssembleAsync(string[] assembly, ArchSelection archSelection = ArchSelection.AArch64, int?offset = null)
        {
            var hex = new List <string> ();

            foreach (string line in assembly)
            {
                var webClient = new WebClient();
                webClient.Headers[HttpRequestHeader.ContentType] = "application/json";

                string json   = $"{{\"asm\":\"{line}\",\"offset\":\"0x{offset ?? 0}\",\"arch\":\"{ArchToString(archSelection)}\"}}";
                string result = await webClient.UploadStringTaskAsync("https://armconverter.com/api/convert", json);

                switch (archSelection)
                {
                case ArchSelection.AArch64:
                    var aArch64Json = await AArch64Json.FromJsonAsync(result);

                    string aArch64Hex = aArch64Json.Hex.AArch64[1].ToString().Replace("### ", string.Empty);

                    if (ExceptionMessageList.Contains(aArch64Hex))
                    {
                        throw new FormatException(aArch64Hex);
                    }

                    hex.Add(aArch64Hex);
                    break;

                case ArchSelection.AArch32:
                    var aArch32Json = await AArch32Json.FromJsonAsync(result);

                    string aArch32Hex = aArch32Json.Hex.AArch32[1].ToString().Replace("### ", string.Empty);

                    if (ExceptionMessageList.Contains(aArch32Hex))
                    {
                        throw new FormatException(aArch32Hex);
                    }

                    hex.Add(aArch32Hex);
                    break;

                case ArchSelection.AArch32BigEndian:
                    var aArch32BigEndianJson = await AArch32BigEndianJson.FromJsonAsync(result);

                    string aArch32BigEndianHex = aArch32BigEndianJson.Hex.AArch32BigEndian[1].ToString().Replace("### ", string.Empty);

                    if (ExceptionMessageList.Contains(aArch32BigEndianHex))
                    {
                        throw new FormatException(aArch32BigEndianHex);
                    }

                    hex.Add(aArch32BigEndianHex);
                    break;

                case ArchSelection.Thumb:
                    var thumbJson = await ThumbJson.FromJsonAsync(result);

                    string thumbHex = thumbJson.Hex.Thumb[1].ToString().Replace("### ", string.Empty);

                    if (ExceptionMessageList.Contains(thumbHex))
                    {
                        throw new FormatException(thumbHex);
                    }

                    hex.Add(thumbHex);
                    break;

                case ArchSelection.ThumbBigEndian:
                    var thumbBigEndianJson = await ThumbBigEndianJson.FromJsonAsync(result);

                    string thumbBigEndianHex = thumbBigEndianJson.Hex.ThumbBigEndian[1].ToString().Replace("### ", string.Empty);

                    if (ExceptionMessageList.Contains(thumbBigEndianHex))
                    {
                        throw new FormatException(thumbBigEndianHex);
                    }

                    hex.Add(thumbBigEndianHex);
                    break;

                default:
                    return(null);
                }
            }

            return(hex.ToArray());
        }