using System; using System.Buffers; using System.Buffers.Binary; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Data.SqlTypes; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Sockets; using System.Net.WebSockets; using System.Numerics; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using DSharpPlus; using DSharpPlus.AsyncEvents; using DSharpPlus.Entities; using DSharpPlus.EventArgs; using DSharpPlus.Exceptions; using DSharpPlus.Net; using DSharpPlus.Net.Abstractions; using DSharpPlus.Net.Models; using DSharpPlus.Net.Serialization; using DSharpPlus.Net.Udp; using DSharpPlus.Net.WebSocket; using DiscordRcon.Config; using DiscordRcon.Models; using DiscordRcon.Services; using FxResources.Microsoft.Extensions.Logging.Abstractions; using FxResources.System.Collections.Immutable; using Microsoft.CodeAnalysis; using Microsoft.Extensions.Internal; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq.JsonPath; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("DiscordRcon")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+287a44b2b33c54b3377ff5808d24403da1499be1")] [assembly: AssemblyProduct("DiscordRcon")] [assembly: AssemblyTitle("DiscordRcon")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DiscordRcon { internal static class Core { public static ManualLogSource Log => Plugin.LogInstance; public static ConfigService ConfigService { get; private set; } public static RconService RconService { get; private set; } public static DiscordBotService DiscordBotService { get; private set; } public static CommandDiscoveryService CommandDiscoveryService { get; private set; } public static void Initialize() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown ConfigService = new ConfigService(); try { ConfigService.Initialize(); } catch (Exception ex) { ManualLogSource log = Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(52, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Config failed to load: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". DiscordRcon will not start."); } log.LogError(val); return; } RconService = new RconService(); DiscordBotService = new DiscordBotService(); CommandDiscoveryService = new CommandDiscoveryService(); if (ConfigService.IsFirstRun) { LogFirstRunSetup(); return; } DiscordBotService.Initialize(); LogStartupStatus(); } private static void LogFirstRunSetup() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Expected O, but got Unknown Log.LogWarning((object)"========================================"); Log.LogWarning((object)"DiscordRcon - First Run Setup Required"); Log.LogWarning((object)"========================================"); Log.LogWarning((object)"This mod needs configuration before it can start."); Log.LogWarning((object)""); Log.LogWarning((object)"1. Edit the BepInEx config file:"); ManualLogSource log = Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(30, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Paths.ConfigPath); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\\io.vrising.DiscordRcon.cfg"); } log.LogWarning(val); Log.LogWarning((object)" - Set Discord.BotToken to your bot token"); Log.LogWarning((object)" - Set Discord.GuildId to your Discord server ID"); Log.LogWarning((object)" - Set RCON.Password to your RCON password"); Log.LogWarning((object)""); Log.LogWarning((object)"2. Edit the role config file:"); ManualLogSource log2 = Log; val = new BepInExWarningLogInterpolatedStringHandler(3, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ConfigService.RoleConfigPath); } log2.LogWarning(val); Log.LogWarning((object)" - Add your Discord role IDs to adminRoles"); Log.LogWarning((object)" - Or add per-command grants in commandRoles"); Log.LogWarning((object)""); Log.LogWarning((object)"3. Optionally edit the custom commands file:"); ManualLogSource log3 = Log; val = new BepInExWarningLogInterpolatedStringHandler(3, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ConfigService.CustomCommandsPath); } log3.LogWarning(val); Log.LogWarning((object)" - Add or remove slash command shortcuts for RCON commands"); Log.LogWarning((object)""); Log.LogWarning((object)"4. Restart the server"); Log.LogWarning((object)"========================================"); } private static void LogStartupStatus() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, but got Unknown ConfigService configService = ConfigService; Log.LogInfo((object)"--- DiscordRcon Startup Status ---"); ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(11, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" Discord: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(string.IsNullOrEmpty(configService.DiscordBotToken) ? "NOT CONFIGURED" : "Token set"); } log.LogInfo(val); ManualLogSource log2 = Log; val = new BepInExInfoLogInterpolatedStringHandler(17, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" Discord Guild: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted((configService.DiscordGuildId == 0L) ? "NOT SET" : configService.DiscordGuildId.ToString()); } log2.LogInfo(val); ManualLogSource log3 = Log; val = new BepInExInfoLogInterpolatedStringHandler(21, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" RCON: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(configService.RconHost); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(":"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(configService.RconPort); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (password "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(string.IsNullOrEmpty(configService.RconPassword) ? "NOT SET" : "set"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")"); } log3.LogInfo(val); ManualLogSource log4 = Log; val = new BepInExInfoLogInterpolatedStringHandler(43, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" Role Config: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(configService.RoleConfig.AdminRoles.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" admin roles, "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(configService.RoleConfig.CommandRoles.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" command roles"); } log4.LogInfo(val); ManualLogSource log5 = Log; val = new BepInExInfoLogInterpolatedStringHandler(28, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" Custom Commands: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(configService.CustomCommands.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" commands"); } log5.LogInfo(val); Log.LogInfo((object)"-----------------------------------"); } public static void Shutdown() { DiscordBotService?.Shutdown(); RconService?.Shutdown(); } } [BepInPlugin("io.vrising.DiscordRcon", "DiscordRcon", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class Plugin : BasePlugin { internal static Plugin Instance { get; private set; } public static ManualLogSource LogInstance => ((BasePlugin)Instance).Log; public static bool IsServer { get; private set; } public override void Load() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown Instance = this; IsServer = Application.productName == "VRisingServer"; if (!IsServer) { ((BasePlugin)this).Log.LogWarning((object)"DiscordRcon is a server-only plugin. It will not function on the client."); return; } Core.Initialize(); ManualLogSource log = ((BasePlugin)this).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(23, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("DiscordRcon"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" v"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("1.0.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded successfully!"); } log.LogInfo(val); } public override bool Unload() { if (IsServer) { Core.Shutdown(); } return true; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "io.vrising.DiscordRcon"; public const string PLUGIN_NAME = "DiscordRcon"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace DiscordRcon.Services { public class CommandDiscoveryService { private volatile int _discoveryRunning; private static readonly Regex _ansiRegex = new Regex("\\x1b\\[\\d+(?:;\\d+)*m", RegexOptions.Compiled); public List DiscoveredCommands { get; private set; } = new List(); public bool IsReady { get; private set; } public void RunDiscovery() { if (Interlocked.CompareExchange(ref _discoveryRunning, 1, 0) == 0) { DiscoverAndRetryAsync(); } } private async Task DiscoverAndRetryAsync() { int attempt = 0; try { bool flag = default(bool); while (true) { if (await DiscoverAndBuildIndexAsync()) { IsReady = true; return; } attempt++; if (attempt >= 20) { break; } ManualLogSource log = Core.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(47, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Discovery failed (attempt "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(attempt); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("), retrying in 30s..."); } log.LogInfo(val); await Task.Delay(30000); } Core.Log.LogError((object)"Discovery failed after 20 attempts. Restart the server to retry."); } finally { Interlocked.Exchange(ref _discoveryRunning, 0); } } private async Task DiscoverAndBuildIndexAsync() { bool flag = default(bool); try { RconResult rconResult = await Core.RconService.SendCommandAsync("help", 30000); if (!rconResult.Success) { ManualLogSource log = Core.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(18, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Discovery failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(rconResult.Message); } log.LogWarning(val); return false; } string helpText = _ansiRegex.Replace(rconResult.Message, ""); List list2 = (DiscoveredCommands = ParseHelpOutput(helpText)); IsReady = true; ManualLogSource log2 = Core.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(37, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Discovery complete: indexed "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(list2.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" commands"); } log2.LogInfo(val2); return true; } catch (Exception ex) { ManualLogSource log3 = Core.Log; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(17, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Discovery error: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex.Message); } log3.LogError(val3); return false; } } private List ParseHelpOutput(string helpText) { List list = new List(); string[] array = helpText.Split('\n'); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (string.IsNullOrEmpty(text) || text.StartsWith("Total commands:", StringComparison.OrdinalIgnoreCase) || !text.StartsWith("-")) { continue; } string text2 = text; string text3 = text2.Substring(1, text2.Length - 1).Trim(); int num = text3.IndexOf(':'); if (num < 0) { continue; } string text4 = text3.Substring(0, num).Trim(); if (!string.IsNullOrEmpty(text4)) { text2 = text3; int num2 = num + 1; string text5 = text2.Substring(num2, text2.Length - num2).Trim(); string usage = ""; string description = text5; int num3 = text5.IndexOf(" - "); if (num3 >= 0) { usage = text5.Substring(0, num3).Trim(); text2 = text5; num2 = num3 + 3; description = text2.Substring(num2, text2.Length - num2).Trim(); } list.Add(new DiscoveredCommand(text4, usage, description)); } } return list; } public List SearchCommands(string query) { if (string.IsNullOrEmpty(query) || DiscoveredCommands.Count == 0) { return new List(); } string query2 = query.ToLowerInvariant(); List list = PrefixMatches(query2); if (list.Count > 0) { return list; } List list2 = ParentPrefixMatches(query2); if (list2.Count > 0) { return list2; } List list3 = SubstringMatches(query2); if (list3.Count > 0) { return list3; } return new List(); } private List PrefixMatches(string query) { return DiscoveredCommands.Where((DiscoveredCommand c) => c.CommandId.ToLowerInvariant() == query || c.CommandId.ToLowerInvariant().StartsWith(query + ".")).ToList(); } private List ParentPrefixMatches(string query) { int num = query.LastIndexOf('.'); while (num > 0) { string text = query.Substring(0, num); List list = PrefixMatches(text); if (list.Count > 0) { return list; } num = text.LastIndexOf('.'); } return new List(); } private List SubstringMatches(string query) { return DiscoveredCommands.Where((DiscoveredCommand c) => c.CommandId.ToLowerInvariant().Contains(query)).Take(10).ToList(); } public DiscoveredCommand FindExact(string commandId) { return DiscoveredCommands.FirstOrDefault((DiscoveredCommand c) => string.Equals(c.CommandId, commandId, StringComparison.OrdinalIgnoreCase)); } } public class DiscordBotService { private DiscordClient _client; private bool _shuttingDown; private Dictionary _customCommandMap = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly FieldInfo _roleIdField = typeof(DiscordMember).GetField("_role_ids", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly Regex _ansiRegex = new Regex("\\x1b\\[(\\d+(?:;\\d+)*)m", RegexOptions.Compiled); private static readonly Regex _validSlashName = new Regex("^[a-z0-9_-]{1,32}$", RegexOptions.Compiled); private static string AnsiToMarkdown(string input) { StringBuilder stringBuilder = new StringBuilder(input.Length); string text = input; bool flag = false; while (text.Length > 0) { Match match = _ansiRegex.Match(text); if (!match.Success) { stringBuilder.Append(text); break; } stringBuilder.Append(text.Substring(0, match.Index)); string[] array = match.Groups[1].Value.Split(';'); if (array.Contains("0")) { if (flag) { stringBuilder.Append("**"); flag = false; } } else { string[] array2 = array; foreach (string text2 in array2) { if ((text2 == "1" || text2 == "97") && !flag) { stringBuilder.Append("**"); flag = true; } } } string text3 = text; int i = match.Index + match.Length; text = text3.Substring(i, text3.Length - i); } if (flag) { stringBuilder.Append("**"); } return stringBuilder.ToString(); } private static List GetMemberRoleIds(DiscordMember member) { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown bool flag = default(bool); try { return member.Roles.Select((DiscordRole r) => r.Id).ToList(); } catch (KeyNotFoundException) { if (Core.ConfigService.LogDiscordEvents) { ManualLogSource log = Core.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(87, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Perm] DiscordMember.Roles threw KeyNotFoundException for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(member.Username); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(member.Id); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("), falling back to _role_ids"); } log.LogWarning(val); } } if (_roleIdField == null) { Core.Log.LogWarning((object)"[Perm] _role_ids field not found via reflection"); return null; } try { List list = (List)_roleIdField.GetValue(member); if (Core.ConfigService.LogDiscordEvents) { ManualLogSource log2 = Core.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(40, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[Perm] read "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(list.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" role IDs from _role_ids: ["); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(string.Join(", ", list)); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("]"); } log2.LogInfo(val2); } return list; } catch (Exception ex2) { ManualLogSource log3 = Core.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(33, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Perm] failed to read _role_ids: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex2.Message); } log3.LogWarning(val); return null; } } private static string FormatSuggestions(List matches) { StringBuilder stringBuilder = new StringBuilder(); foreach (DiscoveredCommand match in matches) { StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2); handler.AppendLiteral("\n - **"); handler.AppendFormatted(match.CommandId); handler.AppendLiteral("**"); stringBuilder3.Append(ref handler); if (!string.IsNullOrEmpty(match.Usage)) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(3, 1, stringBuilder2); handler.AppendLiteral(" `"); handler.AppendFormatted(match.Usage); handler.AppendLiteral("`"); stringBuilder4.Append(ref handler); } if (!string.IsNullOrEmpty(match.Description)) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder5 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(3, 1, stringBuilder2); handler.AppendLiteral(" - "); handler.AppendFormatted(match.Description); stringBuilder5.Append(ref handler); } } return stringBuilder.ToString(); } private static string FormatFullListing(List commands) { StringBuilder stringBuilder = new StringBuilder(); foreach (DiscoveredCommand command in commands) { StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(6, 1, stringBuilder2); handler.AppendLiteral("- **"); handler.AppendFormatted(command.CommandId); handler.AppendLiteral("**"); stringBuilder3.Append(ref handler); if (!string.IsNullOrEmpty(command.Usage)) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(3, 1, stringBuilder2); handler.AppendLiteral(" `"); handler.AppendFormatted(command.Usage); handler.AppendLiteral("`"); stringBuilder4.Append(ref handler); } if (!string.IsNullOrEmpty(command.Description)) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder5 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(3, 1, stringBuilder2); handler.AppendLiteral(" - "); handler.AppendFormatted(command.Description); stringBuilder5.Append(ref handler); } stringBuilder.Append('\n'); } return stringBuilder.ToString(); } public void Initialize() { ConfigService configService = Core.ConfigService; if (string.IsNullOrEmpty(configService.DiscordBotToken)) { Core.Log.LogWarning((object)"Discord bot token is not configured. Set Discord.BotToken in the config and restart."); return; } if (configService.DiscordGuildId == 0L) { Core.Log.LogWarning((object)"Discord guild ID is not configured. Set Discord.GuildId in the config and restart."); return; } _client = new DiscordClient(new DiscordConfiguration { Token = configService.DiscordBotToken, TokenType = TokenType.Bot, Intents = (DiscordIntents.Guilds | DiscordIntents.GuildMembers) }); _client.InteractionCreated += OnInteractionCreated; _client.SocketErrored += OnSocketError; _client.SocketClosed += OnSocketClosed; _client.Ready += OnReady; _client.GuildAvailable += OnGuildAvailable; ConnectAsync(); } private async Task ConnectAsync() { try { await _client.ConnectAsync(); } catch (Exception ex) { ManualLogSource log = Core.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(106, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to connect Discord bot: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Verify your BotToken and that the bot is not already connected elsewhere."); } log.LogError(val); } } private async Task OnReady(DiscordClient sender, ReadyEventArgs e) { ManualLogSource log = Core.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(39, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Discord bot is ready, guilds in cache: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(sender.Guilds.Count); } log.LogInfo(val); if (sender.Guilds.Count == 0) { Core.Log.LogWarning((object)"Discord guild cache is empty. Check that the bot has been added to your server."); } await RegisterSlashCommandsAsync(); Core.Log.LogInfo((object)"Discovery will run in 60s"); Task.Run(async delegate { await Task.Delay(60000); try { Core.CommandDiscoveryService.RunDiscovery(); } catch (Exception ex) { ManualLogSource log2 = Core.Log; bool flag2 = default(bool); BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(24, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Discovery launch error: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } log2.LogError(val2); } }); } private async Task RegisterSlashCommandsAsync() { bool flag = default(bool); try { ulong discordGuildId = Core.ConfigService.DiscordGuildId; List commands = new List { new DiscordApplicationCommand("rcon", "Execute an RCON command", new List { new DiscordApplicationCommandOption("command", "The RCON command to execute", ApplicationCommandOptionType.String, true) }), new DiscordApplicationCommand("help", "Show available RCON commands or details for a specific command", new List { new DiscordApplicationCommandOption("command", "Command name to get help for", ApplicationCommandOptionType.String, false) }) }; _customCommandMap.Clear(); HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (CustomCommand customCommand in Core.ConfigService.CustomCommands) { if (string.IsNullOrEmpty(customCommand.Name) || string.IsNullOrEmpty(customCommand.RconCommand)) { ManualLogSource log = Core.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(54, 0, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Skipping custom command with empty name or rconCommand"); } log.LogWarning(val); } else if (customCommand.Name == "rcon" || customCommand.Name == "help") { ManualLogSource log2 = Core.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(65, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Custom command name '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(customCommand.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' conflicts with built-in commands, skipping"); } log2.LogWarning(val); } else if (!_validSlashName.IsMatch(customCommand.Name)) { ManualLogSource log3 = Core.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(107, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Custom command name '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(customCommand.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' is invalid (must be lowercase, 1-32 chars, a-z/0-9/hyphen/underscore only), skipping"); } log3.LogWarning(val); } else if (!hashSet.Add(customCommand.Name)) { ManualLogSource log4 = Core.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(42, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Duplicate custom command name '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(customCommand.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("', skipping"); } log4.LogWarning(val); } else { _customCommandMap[customCommand.Name] = customCommand; commands.Add(new DiscordApplicationCommand(customCommand.Name, customCommand.Description ?? ("Shortcut for " + customCommand.RconCommand), new List { new DiscordApplicationCommandOption("arguments", "Arguments for " + customCommand.RconCommand, ApplicationCommandOptionType.String, false) })); } } await _client.BulkOverwriteGuildApplicationCommandsAsync(discordGuildId, commands); ManualLogSource log5 = Core.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(50, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Registered "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(commands.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" slash commands (/rcon, /help, "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(_customCommandMap.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" custom)"); } log5.LogInfo(val2); } catch (Exception ex) { ManualLogSource log6 = Core.Log; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Failed to register slash commands: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex.Message); } log6.LogError(val3); } } private Task OnGuildAvailable(DiscordClient sender, GuildCreateEventArgs e) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if (Core.ConfigService.LogDiscordEvents) { ManualLogSource log = Core.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Discord guild available: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(e.Guild.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(e.Guild.Id); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")"); } log.LogInfo(val); } return Task.CompletedTask; } private async Task OnInteractionCreated(DiscordClient sender, InteractionCreateEventArgs e) { if (e.Interaction.Type == InteractionType.ApplicationCommand) { DiscordInteraction interaction = e.Interaction; string name = interaction.Data.Name; CustomCommand value; if (name == "rcon") { await HandleRconAsync(interaction); } else if (name == "help") { await HandleHelpAsync(interaction); } else if (_customCommandMap.TryGetValue(name, out value)) { await HandleCustomCommandAsync(interaction, value); } } } private async Task HandleRconAsync(DiscordInteraction interaction) { string commandText = (interaction.Data.Options?.FirstOrDefault((DiscordInteractionDataOption o) => o.Name == "command"))?.Value?.ToString() ?? ""; if (string.IsNullOrWhiteSpace(commandText)) { await interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder().WithContent(":x: No command provided.")); return; } string commandId = commandText.Split(' ')[0]; ManualLogSource log = Core.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[/rcon] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(interaction.User.Username); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(commandText); } log.LogInfo(val); if (!(await HasPermission(interaction.User, interaction.GuildId, commandId))) { await interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder().WithContent(":x: You don't have permission to use that command.")); return; } await interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource); RconResult rconResult = await Core.RconService.SendCommandAsync(commandText); string text = AnsiToMarkdown(rconResult.Message); if (!rconResult.Success) { text = ":x: " + text; } else if (IsUnknownCommand(text) && Core.CommandDiscoveryService.IsReady) { List list = Core.CommandDiscoveryService.SearchCommands(commandId); if (list.Count > 0) { text = text + "\n\nDid you mean one of these?" + FormatSuggestions(list); } } await RespondAsync(interaction, text); } private async Task HandleHelpAsync(DiscordInteraction interaction) { string query = (interaction.Data.Options?.FirstOrDefault((DiscordInteractionDataOption o) => o.Name == "command"))?.Value?.ToString() ?? ""; ManualLogSource log = Core.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[/help] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(interaction.User.Username); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(string.IsNullOrEmpty(query) ? "(full listing)" : query); } log.LogInfo(val); if (string.IsNullOrEmpty(query)) { if (!(await HasAnyPermission(interaction.User, interaction.GuildId))) { await interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder().WithContent(":x: You don't have permission to use that command.")); return; } } else if (!(await HasPermission(interaction.User, interaction.GuildId, query))) { await interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder().WithContent(":x: You don't have permission to use that command.")); return; } await interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource); string text; if (Core.CommandDiscoveryService.IsReady) { if (string.IsNullOrEmpty(query)) { text = FormatFullListing(Core.CommandDiscoveryService.DiscoveredCommands); } else { DiscoveredCommand discoveredCommand = Core.CommandDiscoveryService.FindExact(query); if (discoveredCommand != null) { StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(4, 1, stringBuilder2); handler.AppendLiteral("**"); handler.AppendFormatted(discoveredCommand.CommandId); handler.AppendLiteral("**"); stringBuilder3.Append(ref handler); if (!string.IsNullOrEmpty(discoveredCommand.Usage)) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(10, 1, stringBuilder2); handler.AppendLiteral("\nUsage: `"); handler.AppendFormatted(discoveredCommand.Usage); handler.AppendLiteral("`"); stringBuilder4.Append(ref handler); } if (!string.IsNullOrEmpty(discoveredCommand.Description)) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder5 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(1, 1, stringBuilder2); handler.AppendLiteral("\n"); handler.AppendFormatted(discoveredCommand.Description); stringBuilder5.Append(ref handler); } text = stringBuilder.ToString(); } else { List list = Core.CommandDiscoveryService.SearchCommands(query); text = ((list.Count <= 0) ? ("No commands found matching \"" + query + "\".") : ("No exact match for \"" + query + "\". Similar commands:" + FormatSuggestions(list))); } } } else { string command = (string.IsNullOrEmpty(query) ? "help" : ("help " + query)); RconResult rconResult = await Core.RconService.SendCommandAsync(command); text = AnsiToMarkdown(rconResult.Message); if (!rconResult.Success) { text = ":x: " + text; } } await RespondAsync(interaction, text); } private static bool IsUnknownCommand(string response) { return response.IndexOf("unknown command", StringComparison.OrdinalIgnoreCase) >= 0; } private async Task HandleCustomCommandAsync(DiscordInteraction interaction, CustomCommand custom) { string text = (interaction.Data.Options?.FirstOrDefault((DiscordInteractionDataOption o) => o.Name == "arguments"))?.Value?.ToString() ?? ""; string commandText = (string.IsNullOrEmpty(text) ? custom.RconCommand : (custom.RconCommand + " " + text)); ManualLogSource log = Core.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(6, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[/"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(custom.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(interaction.User.Username); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(commandText); } log.LogInfo(val); if (!(await HasPermission(interaction.User, interaction.GuildId, custom.RconCommand))) { await interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder().WithContent(":x: You don't have permission to use that command.")); return; } await interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource); RconResult rconResult = await Core.RconService.SendCommandAsync(commandText); string text2 = AnsiToMarkdown(rconResult.Message); if (!rconResult.Success) { text2 = ":x: " + text2; } else if (IsUnknownCommand(text2) && Core.CommandDiscoveryService.IsReady) { List list = Core.CommandDiscoveryService.SearchCommands(custom.RconCommand); if (list.Count > 0) { text2 = text2 + "\n\nDid you mean one of these?" + FormatSuggestions(list); } } await RespondAsync(interaction, text2); } private async Task RespondAsync(DiscordInteraction interaction, string text) { if (text.Length <= 2000) { await interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent(text)); } else { await RespondLongAsync(interaction, text); } } private async Task RespondLongAsync(DiscordInteraction interaction, string text) { string[] array = text.Split('\n'); string text2 = ""; bool first = true; string[] array2 = array; foreach (string line in array2) { if (text2.Length + line.Length + 1 > 2000) { if (!first) { await interaction.CreateFollowupMessageAsync(new DiscordFollowupMessageBuilder().WithContent(text2)); } else { await interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent(text2)); first = false; } text2 = line; } else { text2 = ((text2.Length == 0) ? line : (text2 + "\n" + line)); } } if (text2.Length > 0) { if (first) { await interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent(text2)); } else { await interaction.CreateFollowupMessageAsync(new DiscordFollowupMessageBuilder().WithContent(text2)); } } } private async Task HasAnyPermission(DiscordUser user, ulong? guildId) { var (flag, source) = await ResolveUserRoleIds(user, guildId); if (!flag) { return false; } RoleConfig roleConfig = Core.ConfigService.RoleConfig; if (roleConfig.AdminRoles.Count > 0 && source.Any((string id) => roleConfig.AdminRoles.Contains(id))) { return true; } foreach (List entry in roleConfig.CommandRoles.Values) { if (source.Any((string id) => entry.Contains(id))) { return true; } } return false; } private async Task<(bool resolved, List roleIds)> ResolveUserRoleIds(DiscordUser user, ulong? guildId) { if (_client == null) { return (false, null); } if (user == null) { Core.Log.LogWarning((object)"[Perm] user is null, denying"); return (false, null); } List roleIds = null; if (user is DiscordMember member) { roleIds = GetMemberRoleIds(member); } else if (guildId.HasValue) { if (_client.Guilds.TryGetValue(guildId.Value, out var value) && value.Members.TryGetValue(user.Id, out var value2)) { roleIds = GetMemberRoleIds(value2); } if (roleIds == null) { try { roleIds = GetMemberRoleIds(await (await _client.GetGuildAsync(guildId.Value)).GetMemberAsync(user.Id)); } catch (Exception ex) { ManualLogSource log = Core.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(33, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Perm] REST API fallback failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogWarning(val); } } } if (roleIds == null || roleIds.Count == 0) { Core.Log.LogWarning((object)"[Perm] no role IDs resolved, denying"); return (false, null); } return (true, roleIds.Select((ulong id) => id.ToString()).ToList()); } private async Task HasPermission(DiscordUser user, ulong? guildId, string commandId) { var (flag, source) = await ResolveUserRoleIds(user, guildId); if (!flag) { return false; } RoleConfig roleConfig = Core.ConfigService.RoleConfig; if (roleConfig.AdminRoles.Count > 0 && source.Any((string id) => roleConfig.AdminRoles.Contains(id))) { return true; } if (roleConfig.CommandRoles.TryGetValue(commandId, out var commandRoleIds) && source.Any((string id) => commandRoleIds.Contains(id))) { return true; } Core.Log.LogWarning((object)"[Perm] no admin or command role match, denying"); return false; } private Task OnSocketError(DiscordClient sender, SocketErrorEventArgs e) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown ManualLogSource log = Core.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(22, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Discord socket error: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(e.Exception?.Message); } log.LogWarning(val); return Task.CompletedTask; } private Task OnSocketClosed(DiscordClient sender, SocketCloseEventArgs e) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (_shuttingDown) { return Task.CompletedTask; } ManualLogSource log = Core.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(26, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Discord socket closed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(e.CloseCode); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" - "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(e.CloseMessage); } log.LogWarning(val); ReconnectWithBackoffAsync(); return Task.CompletedTask; } private async Task ReconnectWithBackoffAsync() { int[] delays = new int[7] { 1, 2, 4, 8, 16, 32, 60 }; int attempt = 0; bool flag = default(bool); while (!_shuttingDown && attempt < delays.Length) { await Task.Delay(delays[attempt] * 1000); try { ManualLogSource log = Core.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(29, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Discord reconnect attempt "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(attempt + 1); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("..."); } log.LogInfo(val); await _client.ConnectAsync(); Core.Log.LogInfo((object)"Discord reconnected successfully"); return; } catch (Exception ex) { ManualLogSource log2 = Core.Log; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(26, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Discord reconnect failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } log2.LogWarning(val2); attempt++; } } Core.Log.LogError((object)"Discord reconnect exhausted all attempts. Manual restart required."); } public void Shutdown() { _shuttingDown = true; if (_client != null) { _client.DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false).GetAwaiter() .GetResult(); _client.Dispose(); } } } public class RconClient : IDisposable { private TcpClient _tcp; private NetworkStream _stream; private int _requestId; private const int SERVERDATA_AUTH = 3; private const int SERVERDATA_AUTH_RESPONSE = 2; private const int SERVERDATA_EXECCOMMAND = 2; private const int SERVERDATA_RESPONSE_VALUE = 0; public async Task ConnectAsync(string host, int port, string password, int timeoutMs = 5000) { _tcp = new TcpClient(); IPAddress[] array = await Dns.GetHostAddressesAsync(host); if (array.Length == 0) { throw new Exception("Could not resolve RCON host: " + host); } using CancellationTokenSource cts = new CancellationTokenSource(timeoutMs); await _tcp.ConnectAsync(array[0], port, cts.Token); _stream = _tcp.GetStream(); SendPacket(NextRequestId(), 3, password); (int, int, string) obj; int num; do { obj = await ReadPacketAsync(cts.Token); (num, _, _) = obj; } while (obj.Item2 != 2); if (num == -1) { throw new Exception("RCON authentication failed"); } } public async Task SendCommandAsync(string command, int timeoutMs = 10000) { SendPacket(NextRequestId(), 2, command); using CancellationTokenSource cts = new CancellationTokenSource(timeoutMs); int item; string item2; do { (int, int, string) obj = await ReadPacketAsync(cts.Token); item = obj.Item2; item2 = obj.Item3; } while (item != 0); return item2; } private int NextRequestId() { return ++_requestId; } private void SendPacket(int id, int type, string body) { byte[] bytes = Encoding.UTF8.GetBytes(body); int num = 8 + bytes.Length + 2; byte[] array = new byte[4 + num]; BitConverter.TryWriteBytes(array.AsSpan(0), num); BitConverter.TryWriteBytes(array.AsSpan(4), id); BitConverter.TryWriteBytes(array.AsSpan(8), type); bytes.CopyTo(array, 12); _stream.Write(array, 0, array.Length); } private async Task<(int id, int type, string body)> ReadPacketAsync(CancellationToken ct = default(CancellationToken)) { byte[] sizeBuf = new byte[4]; await ReadExactAsync(sizeBuf, ct); int size = BitConverter.ToInt32(sizeBuf, 0); if (size < 10 || size > 65536) { throw new Exception($"Invalid RCON packet size: {size}"); } byte[] data = new byte[size]; await ReadExactAsync(data, ct); int item = BitConverter.ToInt32(data, 0); int item2 = BitConverter.ToInt32(data, 4); int num = size - 4 - 4 - 2; string item3 = ((num > 0) ? Encoding.UTF8.GetString(data, 8, num) : ""); return (item, item2, item3); } private async Task ReadExactAsync(byte[] buffer, CancellationToken ct) { int num; for (int offset = 0; offset < buffer.Length; offset += num) { num = await _stream.ReadAsync(buffer, offset, buffer.Length - offset, ct); if (num == 0) { throw new Exception("RCON connection closed"); } } } public void Dispose() { _stream?.Dispose(); _tcp?.Dispose(); } } public class RconService { private readonly SemaphoreSlim _concurrencyLimiter = new SemaphoreSlim(1, 1); public async Task SendCommandAsync(string command, int? timeoutMs = null) { ConfigService cfg = Core.ConfigService; if (string.IsNullOrEmpty(cfg.RconPassword)) { return RconResult.Fail("RCON password not configured"); } await _concurrencyLimiter.WaitAsync(); bool flag = default(bool); try { int timeout = timeoutMs ?? cfg.RconCommandTimeoutMs; using RconClient client = new RconClient(); await client.ConnectAsync(cfg.RconHost, cfg.RconPort, cfg.RconPassword); string text = await client.SendCommandAsync(command, timeout); if (Core.ConfigService.LogRconEvents) { ManualLogSource log = Core.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(11, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("RCON ["); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(command); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] -> "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text); } log.LogInfo(val); } return RconResult.Ok(string.IsNullOrEmpty(text) ? "Command executed (no output)" : text); } catch (OperationCanceledException) { return RconResult.Fail("RCON command timed out"); } catch (Exception ex2) { ManualLogSource log2 = Core.Log; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(13, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("RCON failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex2.Message); } log2.LogWarning(val2); return RconResult.Fail("RCON not ready: " + ex2.Message); } finally { _concurrencyLimiter.Release(); } } public void Shutdown() { _concurrencyLimiter.Dispose(); } } public readonly struct RconResult { public bool Success { get; } public string Message { get; } private RconResult(bool success, string message) { Success = success; Message = message; } public static RconResult Ok(string message) { return new RconResult(success: true, message); } public static RconResult Fail(string message) { return new RconResult(success: false, message); } } } namespace DiscordRcon.Models { public class CustomCommand { [JsonPropertyName("name")] public string Name { get; set; } = ""; [JsonPropertyName("description")] public string Description { get; set; } = ""; [JsonPropertyName("rconCommand")] public string RconCommand { get; set; } = ""; } public class DiscoveredCommand { public string CommandId { get; set; } = ""; public string Usage { get; set; } = ""; public string Description { get; set; } = ""; public DiscoveredCommand(string commandId, string usage, string description) { CommandId = commandId; Usage = usage; Description = description; } } public class RoleConfig { [JsonPropertyName("adminRoles")] public List AdminRoles { get; set; } = new List(); [JsonPropertyName("commandRoles")] public Dictionary> CommandRoles { get; set; } = new Dictionary>(StringComparer.OrdinalIgnoreCase); } } namespace DiscordRcon.Config { public class ConfigService { public static readonly string ConfigDir = Path.Combine(Paths.ConfigPath, "DiscordRcon"); public static readonly string RoleConfigPath = Path.Combine(ConfigDir, "discordrcon_roles.json"); public static readonly string CustomCommandsPath = Path.Combine(ConfigDir, "discordrcon_commands.json"); public string DiscordBotToken { get; private set; } = ""; public ulong DiscordGuildId { get; private set; } public string RconHost { get; private set; } = "127.0.0.1"; public int RconPort { get; private set; } = 25575; public string RconPassword { get; private set; } = ""; public int RconCommandTimeoutMs { get; private set; } = 10000; public bool LogDiscordEvents { get; private set; } public bool LogRconEvents { get; private set; } public RoleConfig RoleConfig { get; private set; } = new RoleConfig(); public List CustomCommands { get; private set; } = new List(); public bool IsFirstRun { get; private set; } public void Initialize() { Directory.CreateDirectory(ConfigDir); BindConfig(); DetectFirstRun(); LoadRoleConfig(); LoadCustomCommands(); } private void DetectFirstRun() { IsFirstRun = string.IsNullOrEmpty(DiscordBotToken) && DiscordGuildId == 0L && string.IsNullOrEmpty(RconPassword); } private void BindConfig() { ConfigFile config = ((BasePlugin)Plugin.Instance).Config; DiscordBotToken = config.Bind("Discord", "BotToken", "", "Discord bot token. Get this from https://discord.com/developers/applications").Value; DiscordGuildId = config.Bind("Discord", "GuildId", 0uL, "Discord server (guild) ID for registering slash commands").Value; RconHost = config.Bind("RCON", "Host", "127.0.0.1", "RCON server hostname").Value; RconPort = config.Bind("RCON", "Port", 25575, "RCON server port").Value; RconPassword = config.Bind("RCON", "Password", "", "RCON server password").Value; RconCommandTimeoutMs = config.Bind("RCON", "CommandTimeoutMs", 10000, "Timeout in milliseconds for RCON command responses").Value; LogDiscordEvents = config.Bind("Debug", "LogDiscordEvents", false, "Verbose logging of Discord gateway events").Value; LogRconEvents = config.Bind("Debug", "LogRconEvents", false, "Verbose logging of RCON events").Value; } private void LoadRoleConfig() { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown bool flag = default(bool); if (!File.Exists(RoleConfigPath)) { RoleConfig config = new RoleConfig(); SaveRoleConfig(config); ManualLogSource log = Core.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Created role config at "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(RoleConfigPath); } log.LogInfo(val); } try { string json = File.ReadAllText(RoleConfigPath); RoleConfig = System.Text.Json.JsonSerializer.Deserialize(json) ?? new RoleConfig(); ManualLogSource log2 = Core.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(48, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded role config: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(RoleConfig.AdminRoles.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" admin roles, "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(RoleConfig.CommandRoles.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" command roles"); } log2.LogInfo(val); } catch (Exception ex) { ManualLogSource log3 = Core.Log; BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(66, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to load role config: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(". Fix or delete the file and restart: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(RoleConfigPath); } log3.LogError(val2); throw; } } private void SaveRoleConfig(RoleConfig config) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown try { string contents = System.Text.Json.JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(RoleConfigPath, contents); } catch (Exception ex) { ManualLogSource log = Core.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(28, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to save role config: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogError(val); } } private void LoadCustomCommands() { //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown bool flag = default(bool); if (!File.Exists(CustomCommandsPath)) { List commands = new List { new CustomCommand { Name = "kick", Description = "Kick a player from the server", RconCommand = "kick" }, new CustomCommand { Name = "ban", Description = "Ban a player from the server", RconCommand = "ban" }, new CustomCommand { Name = "listplayers", Description = "List all online players", RconCommand = "listplayers" } }; SaveCustomCommands(commands); ManualLogSource log = Core.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(34, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Created custom commands config at "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(CustomCommandsPath); } log.LogInfo(val); } try { string json = File.ReadAllText(CustomCommandsPath); CustomCommands = System.Text.Json.JsonSerializer.Deserialize>(json) ?? new List(); ManualLogSource log2 = Core.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded custom commands: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(CustomCommands.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" commands"); } log2.LogInfo(val); } catch (Exception ex) { ManualLogSource log3 = Core.Log; BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(70, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to load custom commands: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(". Fix or delete the file and restart: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(CustomCommandsPath); } log3.LogError(val2); throw; } } private void SaveCustomCommands(List commands) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown try { string contents = System.Text.Json.JsonSerializer.Serialize(commands, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(CustomCommandsPath, contents); } catch (Exception ex) { ManualLogSource log = Core.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(32, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to save custom commands: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogError(val); } } } } [CompilerGenerated] internal sealed class { [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 28)] internal struct __StaticArrayInitTypeSize=28 { } internal static readonly __StaticArrayInitTypeSize=28 BF7002736ADB60A23C32230A9AF55DF45D5C23AD0F3F03C0AF765A16CDB52EB6/* Not supported: data(01 00 00 00 02 00 00 00 04 00 00 00 08 00 00 00 10 00 00 00 20 00 00 00 3C 00 00 00) */; } namespace Newtonsoft.Json { internal enum ConstructorHandling { Default, AllowNonPublicDefaultConstructor } internal enum DateFormatHandling { IsoDateFormat, MicrosoftDateFormat } internal enum DateParseHandling { None, DateTime, DateTimeOffset } internal enum DateTimeZoneHandling { Local, Utc, Unspecified, RoundtripKind } internal class DefaultJsonNameTable : JsonNameTable { private class Entry { internal readonly string Value; internal readonly int HashCode; internal Entry Next; internal Entry(string value, int hashCode, Entry next) { Value = value; HashCode = hashCode; Next = next; } } private static readonly int HashCodeRandomizer; private int _count; private Entry[] _entries; private int _mask = 31; static DefaultJsonNameTable() { HashCodeRandomizer = Environment.TickCount; } public DefaultJsonNameTable() { _entries = new Entry[_mask + 1]; } public override string? Get(char[] key, int start, int length) { if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; num += (num << 7) ^ key[start]; int num2 = start + length; for (int i = start + 1; i < num2; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; int num3 = Volatile.Read(ref _mask); int num4 = num & num3; for (Entry entry = _entries[num4]; entry != null; entry = entry.Next) { if (entry.HashCode == num && TextEquals(entry.Value, key, start, length)) { return entry.Value; } } return null; } public string Add(string key) { if (key == null) { throw new ArgumentNullException("key"); } int length = key.Length; if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; for (int i = 0; i < key.Length; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next) { if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal)) { return entry.Value; } } return AddEntry(key, num); } private string AddEntry(string str, int hashCode) { int num = hashCode & _mask; Entry entry = new Entry(str, hashCode, _entries[num]); _entries[num] = entry; if (_count++ == _mask) { Grow(); } return entry.Value; } private void Grow() { Entry[] entries = _entries; int num = _mask * 2 + 1; Entry[] array = new Entry[num + 1]; for (int i = 0; i < entries.Length; i++) { Entry entry = entries[i]; while (entry != null) { int num2 = entry.HashCode & num; Entry next = entry.Next; entry.Next = array[num2]; array[num2] = entry; entry = next; } } _entries = array; Volatile.Write(ref _mask, num); } private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) { if (str1.Length != str2Length) { return false; } for (int i = 0; i < str1.Length; i++) { if (str1[i] != str2[str2Start + i]) { return false; } } return true; } } [Flags] internal enum DefaultValueHandling { Include = 0, Ignore = 1, Populate = 2, IgnoreAndPopulate = 3 } internal enum FloatFormatHandling { String, Symbol, DefaultValue } internal enum FloatParseHandling { Double, Decimal } internal enum Formatting { None, Indented } internal interface IArrayPool { T[] Rent(int minimumLength); void Return(T[]? array); } internal interface IJsonLineInfo { int LineNumber { get; } int LinePosition { get; } bool HasLineInfo(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] internal sealed class JsonArrayAttribute : JsonContainerAttribute { private bool _allowNullItems; public bool AllowNullItems { get { return _allowNullItems; } set { _allowNullItems = value; } } public JsonArrayAttribute() { } public JsonArrayAttribute(bool allowNullItems) { _allowNullItems = allowNullItems; } public JsonArrayAttribute(string id) : base(id) { } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)] internal sealed class JsonConstructorAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] internal abstract class JsonContainerAttribute : Attribute { internal bool? _isReference; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; private Type? _namingStrategyType; private object[]? _namingStrategyParameters; public string? Id { get; set; } public string? Title { get; set; } public string? Description { get; set; } public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get { return _namingStrategyType; } set { _namingStrategyType = value; NamingStrategyInstance = null; } } public object[]? NamingStrategyParameters { get { return _namingStrategyParameters; } set { _namingStrategyParameters = value; NamingStrategyInstance = null; } } internal NamingStrategy? NamingStrategyInstance { get; set; } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } protected JsonContainerAttribute() { } protected JsonContainerAttribute(string id) { Id = id; } } internal static class JsonConvert { public static readonly string True = "true"; public static readonly string False = "false"; public static readonly string Null = "null"; public static readonly string Undefined = "undefined"; public static readonly string PositiveInfinity = "Infinity"; public static readonly string NegativeInfinity = "-Infinity"; public static readonly string NaN = "NaN"; public static Func? DefaultSettings { get; set; } public static string ToString(DateTime value) { return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); } public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) { DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling); using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(DateTimeOffset value) { return ToString(value, DateFormatHandling.IsoDateFormat); } public static string ToString(DateTimeOffset value, DateFormatHandling format) { using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(bool value) { if (!value) { return False; } return True; } public static string ToString(char value) { return ToString(char.ToString(value)); } public static string ToString(Enum value) { return value.ToString("D"); } public static string ToString(int value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(short value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(long value) { return value.ToString(null, CultureInfo.InvariantCulture); } private static string ToStringInternal(BigInteger value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(float value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value))) { return text; } if (floatFormatHandling == FloatFormatHandling.DefaultValue) { if (nullable) { return Null; } return "0.0"; } return quoteChar + text + quoteChar; } public static string ToString(double value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || StringUtils.IndexOf(text, '.') != -1 || StringUtils.IndexOf(text, 'E') != -1 || StringUtils.IndexOf(text, 'e') != -1) { return text; } return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (StringUtils.IndexOf(text, '.') != -1) { return text; } return text + ".0"; } public static string ToString(byte value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(decimal value) { return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); } public static string ToString(Guid value) { return ToString(value, '"'); } internal static string ToString(Guid value, char quoteChar) { string text = value.ToString("D", CultureInfo.InvariantCulture); string text2 = quoteChar.ToString(CultureInfo.InvariantCulture); return text2 + text + text2; } public static string ToString(TimeSpan value) { return ToString(value, '"'); } internal static string ToString(TimeSpan value, char quoteChar) { return ToString(value.ToString(), quoteChar); } public static string ToString(Uri? value) { if (value == null) { return Null; } return ToString(value, '"'); } internal static string ToString(Uri value, char quoteChar) { return ToString(value.OriginalString, quoteChar); } public static string ToString(string? value) { return ToString(value, '"'); } public static string ToString(string? value, char delimiter) { return ToString(value, delimiter, StringEscapeHandling.Default); } public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) { if (delimiter != '"' && delimiter != '\'') { throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter"); } return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling); } public static string ToString(object? value) { if (value == null) { return Null; } return ConvertUtils.GetTypeCode(value.GetType()) switch { PrimitiveTypeCode.String => ToString((string)value), PrimitiveTypeCode.Char => ToString((char)value), PrimitiveTypeCode.Boolean => ToString((bool)value), PrimitiveTypeCode.SByte => ToString((sbyte)value), PrimitiveTypeCode.Int16 => ToString((short)value), PrimitiveTypeCode.UInt16 => ToString((ushort)value), PrimitiveTypeCode.Int32 => ToString((int)value), PrimitiveTypeCode.Byte => ToString((byte)value), PrimitiveTypeCode.UInt32 => ToString((uint)value), PrimitiveTypeCode.Int64 => ToString((long)value), PrimitiveTypeCode.UInt64 => ToString((ulong)value), PrimitiveTypeCode.Single => ToString((float)value), PrimitiveTypeCode.Double => ToString((double)value), PrimitiveTypeCode.DateTime => ToString((DateTime)value), PrimitiveTypeCode.Decimal => ToString((decimal)value), PrimitiveTypeCode.DBNull => Null, PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), PrimitiveTypeCode.Guid => ToString((Guid)value), PrimitiveTypeCode.Uri => ToString((Uri)value), PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), _ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), }; } [DebuggerStepThrough] public static string SerializeObject(object? value) { return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, JsonSerializerSettings? settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); return SerializeObjectInternal(value, type, jsonSerializer); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) { return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); jsonSerializer.Formatting = formatting; return SerializeObjectInternal(value, type, jsonSerializer); } private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) { StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)) { jsonTextWriter.Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize(jsonTextWriter, value, type); } return stringWriter.ToString(); } [DebuggerStepThrough] public static object? DeserializeObject(string value) { return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static object? DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeObject(string value) { return JsonConvert.DeserializeObject(value, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeAnonymousType(string value, T anonymousTypeObject) { return DeserializeObject(value); } [DebuggerStepThrough] public static T? DeserializeAnonymousType(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject(value, settings); } [DebuggerStepThrough] public static T? DeserializeObject(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } [DebuggerStepThrough] public static T? DeserializeObject(string value, JsonSerializerSettings? settings) { return (T)DeserializeObject(value, typeof(T), settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return DeserializeObject(value, type, settings); } public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) { ValidationUtils.ArgumentNotNull(value, "value"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); if (!jsonSerializer.IsCheckAdditionalContentSet()) { jsonSerializer.CheckAdditionalContent = true; } using JsonTextReader reader = new JsonTextReader(new StringReader(value)); return jsonSerializer.Deserialize(reader, type); } [DebuggerStepThrough] public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); using JsonReader jsonReader = new JsonTextReader(new StringReader(value)); jsonSerializer.Populate(jsonReader, target); if (settings == null || !settings.CheckAdditionalContent) { return; } while (jsonReader.Read()) { if (jsonReader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object."); } } } public static string SerializeXmlNode(XmlNode? node) { return SerializeXmlNode(node, Formatting.None); } public static string SerializeXmlNode(XmlNode? node, Formatting formatting) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); return SerializeObject(node, formatting, xmlNodeConverter); } public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XmlDocument? DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter); } public static string SerializeXNode(XObject? node) { return SerializeXNode(node, Formatting.None); } public static string SerializeXNode(XObject? node, Formatting formatting) { return SerializeXNode(node, formatting, omitRootObject: false); } public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XDocument? DeserializeXNode(string value) { return DeserializeXNode(value, null); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter); } } internal abstract class JsonConverter { public virtual bool CanRead => true; public virtual bool CanWrite => true; public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); public abstract bool CanConvert(Type objectType); } internal abstract class JsonConverter : JsonConverter { public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T)))) { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } WriteJson(writer, (T)value, serializer); } public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = existingValue == null; if (!flag && !(existingValue is T)) { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer); } public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); public sealed override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class JsonConverterAttribute : Attribute { private readonly Type _converterType; public Type ConverterType => _converterType; public object[]? ConverterParameters { get; } public JsonConverterAttribute(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } _converterType = converterType; } public JsonConverterAttribute(Type converterType, params object[] converterParameters) : this(converterType) { ConverterParameters = converterParameters; } } internal class JsonConverterCollection : Collection { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] internal sealed class JsonDictionaryAttribute : JsonContainerAttribute { public JsonDictionaryAttribute() { } public JsonDictionaryAttribute(string id) : base(id) { } } [Serializable] internal class JsonException : Exception { public JsonException() { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception? innerException) : base(message, innerException) { } public JsonException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message) { message = JsonPosition.FormatMessage(lineInfo, path, message); return new JsonException(message); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] internal class JsonExtensionDataAttribute : Attribute { public bool WriteData { get; set; } public bool ReadData { get; set; } public JsonExtensionDataAttribute() { WriteData = true; ReadData = true; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] internal sealed class JsonIgnoreAttribute : Attribute { } internal abstract class JsonNameTable { public abstract string? Get(char[] key, int start, int length); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)] internal sealed class JsonObjectAttribute : JsonContainerAttribute { private MemberSerialization _memberSerialization; internal MissingMemberHandling? _missingMemberHandling; internal Required? _itemRequired; internal NullValueHandling? _itemNullValueHandling; public MemberSerialization MemberSerialization { get { return _memberSerialization; } set { _memberSerialization = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public NullValueHandling ItemNullValueHandling { get { return _itemNullValueHandling.GetValueOrDefault(); } set { _itemNullValueHandling = value; } } public Required ItemRequired { get { return _itemRequired.GetValueOrDefault(); } set { _itemRequired = value; } } public JsonObjectAttribute() { } public JsonObjectAttribute(MemberSerialization memberSerialization) { MemberSerialization = memberSerialization; } public JsonObjectAttribute(string id) : base(id) { } } internal enum JsonContainerType { None, Object, Array, Constructor } internal struct JsonPosition { private static readonly char[] SpecialCharacters = new char[18] { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; internal JsonContainerType Type; internal int Position; internal string? PropertyName; internal bool HasIndex; public JsonPosition(JsonContainerType type) { Type = type; HasIndex = TypeHasIndex(type); Position = -1; PropertyName = null; } internal int CalculateLength() { switch (Type) { case JsonContainerType.Object: return PropertyName.Length + 5; case JsonContainerType.Array: case JsonContainerType.Constructor: return MathUtils.IntLength((ulong)Position) + 2; default: throw new ArgumentOutOfRangeException("Type"); } } internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) { switch (Type) { case JsonContainerType.Object: { string propertyName = PropertyName; if (propertyName.IndexOfAny(SpecialCharacters) != -1) { sb.Append("['"); if (writer == null) { writer = new StringWriter(sb); } JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer); sb.Append("']"); } else { if (sb.Length > 0) { sb.Append('.'); } sb.Append(propertyName); } break; } case JsonContainerType.Array: case JsonContainerType.Constructor: sb.Append('['); sb.Append(Position); sb.Append(']'); break; } } internal static bool TypeHasIndex(JsonContainerType type) { if (type != JsonContainerType.Array) { return type == JsonContainerType.Constructor; } return true; } internal static string BuildPath(List positions, JsonPosition? currentPosition) { int num = 0; if (positions != null) { for (int i = 0; i < positions.Count; i++) { num += positions[i].CalculateLength(); } } if (currentPosition.HasValue) { num += currentPosition.GetValueOrDefault().CalculateLength(); } StringBuilder stringBuilder = new StringBuilder(num); StringWriter writer = null; char[] buffer = null; if (positions != null) { foreach (JsonPosition position in positions) { position.WriteTo(stringBuilder, ref writer, ref buffer); } } currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer); return stringBuilder.ToString(); } internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) { if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { message = message.Trim(); if (!message.EndsWith('.')) { message += "."; } message += " "; } message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path); if (lineInfo != null && lineInfo.HasLineInfo()) { message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition); } message += "."; return message; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class JsonPropertyAttribute : Attribute { internal NullValueHandling? _nullValueHandling; internal DefaultValueHandling? _defaultValueHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal ObjectCreationHandling? _objectCreationHandling; internal TypeNameHandling? _typeNameHandling; internal bool? _isReference; internal int? _order; internal Required? _required; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get; set; } public object[]? NamingStrategyParameters { get; set; } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public int Order { get { return _order.GetValueOrDefault(); } set { _order = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public string? PropertyName { get; set; } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public JsonPropertyAttribute() { } public JsonPropertyAttribute(string propertyName) { PropertyName = propertyName; } } internal abstract class JsonReader : IAsyncDisposable, IDisposable { protected internal enum State { Start, Complete, Property, ObjectStart, Object, ArrayStart, Array, Closed, PostValue, ConstructorStart, Constructor, Error, Finished } private JsonToken _tokenType; private object? _value; internal char _quoteChar; internal State _currentState; private JsonPosition _currentPosition; private CultureInfo? _culture; private DateTimeZoneHandling _dateTimeZoneHandling; private int? _maxDepth; private bool _hasExceededMaxDepth; internal DateParseHandling _dateParseHandling; internal FloatParseHandling _floatParseHandling; private string? _dateFormatString; private List? _stack; protected State CurrentState => _currentState; public bool CloseInput { get; set; } public bool SupportMultipleContent { get; set; } public virtual char QuoteChar { get { return _quoteChar; } protected internal set { _quoteChar = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling; } set { if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset) { throw new ArgumentOutOfRangeException("value"); } _dateParseHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling; } set { if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal) { throw new ArgumentOutOfRangeException("value"); } _floatParseHandling = value; } } public string? DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; } } public virtual JsonToken TokenType => _tokenType; public virtual object? Value => _value; public virtual Type? ValueType => _value?.GetType(); public virtual int Depth { get { int num = _stack?.Count ?? 0; if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None) { return num; } return num + 1; } } public virtual string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } ValueTask IAsyncDisposable.DisposeAsync() { try { Dispose(disposing: true); return default(ValueTask); } catch (Exception exception) { return ValueTask.FromException(exception); } } public virtual Task ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Read().ToAsync(); } public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (TokenType == JsonToken.PropertyName) { await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth) { } } } internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken) { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedEndException(); } } public virtual Task ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsBoolean()); } public virtual Task ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsBytes()); } internal async Task ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) { List buffer = new List(); do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(buffer)); byte[] array = buffer.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } public virtual Task ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsDateTime()); } public virtual Task ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsDateTimeOffset()); } public virtual Task ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsDecimal()); } public virtual Task ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(ReadAsDouble()); } public virtual Task ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsInt32()); } public virtual Task ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsString()); } internal async Task ReadAndMoveToContentAsync(CancellationToken cancellationToken) { bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (flag) { flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return flag; } internal Task MoveToContentAsync(CancellationToken cancellationToken) { JsonToken tokenType = TokenType; if (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { return MoveToContentFromNonContentAsync(cancellationToken); } return AsyncUtils.True; } private async Task MoveToContentFromNonContentAsync(CancellationToken cancellationToken) { JsonToken tokenType; do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return false; } tokenType = TokenType; } while (tokenType == JsonToken.None || tokenType == JsonToken.Comment); return true; } internal JsonPosition GetPosition(int depth) { if (_stack != null && depth < _stack.Count) { return _stack[depth]; } return _currentPosition; } protected JsonReader() { _currentState = State.Start; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateParseHandling = DateParseHandling.DateTime; _floatParseHandling = FloatParseHandling.Double; _maxDepth = 64; CloseInput = true; } private void Push(JsonContainerType value) { UpdateScopeWithFinishedValue(); if (_currentPosition.Type == JsonContainerType.None) { _currentPosition = new JsonPosition(value); return; } if (_stack == null) { _stack = new List(); } _stack.Add(_currentPosition); _currentPosition = new JsonPosition(value); if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth) { return; } _hasExceededMaxDepth = true; throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth)); } private JsonContainerType Pop() { JsonPosition currentPosition; if (_stack != null && _stack.Count > 0) { currentPosition = _currentPosition; _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { currentPosition = _currentPosition; _currentPosition = default(JsonPosition); } if (_maxDepth.HasValue && Depth <= _maxDepth) { _hasExceededMaxDepth = false; } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract bool Read(); public virtual int? ReadAsInt32() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is int) { return (int)value; } int num; if (value is BigInteger bigInteger) { num = (int)bigInteger; } else { try { num = Convert.ToInt32(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Integer, num, updateIndex: false); return num; } case JsonToken.String: { string s = (string)Value; return ReadInt32String(s); } default: throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal int? ReadInt32String(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (int.TryParse(s, NumberStyles.Integer, Culture, out var result)) { SetToken(JsonToken.Integer, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual string? ReadAsString() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.String: return (string)Value; default: if (JsonTokenUtils.IsPrimitiveToken(contentToken)) { object value = Value; if (value != null) { string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture)); SetToken(JsonToken.String, text, updateIndex: false); return text; } } throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } public virtual byte[]? ReadAsBytes() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.StartObject: { ReadIntoWrappedTypeObject(); byte[] array2 = ReadAsBytes(); ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array2, updateIndex: false); return array2; } case JsonToken.String: { string text = (string)Value; Guid g; byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray())); SetToken(JsonToken.Bytes, array3, updateIndex: false); return array3; } case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Bytes: if (Value is Guid guid) { byte[] array = guid.ToByteArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } return (byte[])Value; case JsonToken.StartArray: return ReadArrayIntoByteArray(); default: throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal byte[] ReadArrayIntoByteArray() { List list = new List(); do { if (!Read()) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(list)); byte[] array = list.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } private bool ReadArrayElementIntoByteArrayReportDone(List buffer) { switch (TokenType) { case JsonToken.None: throw JsonReaderException.Create(this, "Unexpected end when reading bytes."); case JsonToken.Integer: buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); return false; case JsonToken.EndArray: return true; case JsonToken.Comment: return false; default: throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } public virtual double? ReadAsDouble() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is double) { return (double)value; } double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger)); SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDoubleString((string)Value); default: throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal double? ReadDoubleString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual bool? ReadAsBoolean() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L)); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case JsonToken.String: return ReadBooleanString((string)Value); case JsonToken.Boolean: return (bool)Value; default: throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal bool? ReadBooleanString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (bool.TryParse(s, out var result)) { SetToken(JsonToken.Boolean, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual decimal? ReadAsDecimal() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is decimal) { return (decimal)value; } decimal num; if (value is BigInteger bigInteger) { num = (decimal)bigInteger; } else { try { num = Convert.ToDecimal(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDecimalString((string)Value); default: throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal decimal? ReadDecimalString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTime? ReadAsDateTime() { switch (GetContentToken()) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTimeOffset dateTimeOffset) { SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false); } return (DateTime)Value; case JsonToken.String: return ReadDateTimeString((string)Value); default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } internal DateTime? ReadDateTimeString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTimeOffset? ReadAsDateTimeOffset() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTime dateTime) { SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false); } return (DateTimeOffset)Value; case JsonToken.String: { string s = (string)Value; return ReadDateTimeOffsetString(s); } default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal DateTimeOffset? ReadDateTimeOffsetString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } internal void ReaderReadAndAssert() { if (!Read()) { throw CreateUnexpectedEndException(); } } internal JsonReaderException CreateUnexpectedEndException() { return JsonReaderException.Create(this, "Unexpected end when reading JSON."); } internal void ReadIntoWrappedTypeObject() { ReaderReadAndAssert(); if (Value != null && Value.ToString() == "$type") { ReaderReadAndAssert(); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { ReaderReadAndAssert(); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public void Skip() { if (TokenType == JsonToken.PropertyName) { Read(); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (Read() && depth < Depth) { } } } protected void SetToken(JsonToken newToken) { SetToken(newToken, null, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value) { SetToken(newToken, value, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value, bool updateIndex) { _tokenType = newToken; _value = value; switch (newToken) { case JsonToken.StartObject: _currentState = State.ObjectStart; Push(JsonContainerType.Object); break; case JsonToken.StartArray: _currentState = State.ArrayStart; Push(JsonContainerType.Array); break; case JsonToken.StartConstructor: _currentState = State.ConstructorStart; Push(JsonContainerType.Constructor); break; case JsonToken.EndObject: ValidateEnd(JsonToken.EndObject); break; case JsonToken.EndArray: ValidateEnd(JsonToken.EndArray); break; case JsonToken.EndConstructor: ValidateEnd(JsonToken.EndConstructor); break; case JsonToken.PropertyName: _currentState = State.Property; _currentPosition.PropertyName = (string)value; break; case JsonToken.Raw: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: SetPostValueState(updateIndex); break; case JsonToken.Comment: break; } } internal void SetPostValueState(bool updateIndex) { if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } if (updateIndex) { UpdateScopeWithFinishedValue(); } } private void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void ValidateEnd(JsonToken endToken) { JsonContainerType jsonContainerType = Pop(); if (GetTypeForCloseToken(endToken) != jsonContainerType) { throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType)); } if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } } protected void SetStateBasedOnCurrent() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Constructor; break; case JsonContainerType.None: SetFinished(); break; default: throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType)); } } private void SetFinished() { _currentState = ((!SupportMultipleContent) ? State.Finished : State.Start); } private JsonContainerType GetTypeForCloseToken(JsonToken token) { return token switch { JsonToken.EndObject => JsonContainerType.Object, JsonToken.EndArray => JsonContainerType.Array, JsonToken.EndConstructor => JsonContainerType.Constructor, _ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), }; } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } public virtual void Close() { _currentState = State.Closed; _tokenType = JsonToken.None; _value = null; } internal void ReadAndAssert() { if (!Read()) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) { if (!ReadForType(contract, hasConverter)) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal bool ReadForType(JsonContract? contract, bool hasConverter) { if (hasConverter) { return Read(); } switch (contract?.InternalReadType ?? ReadType.Read) { case ReadType.Read: return ReadAndMoveToContent(); case ReadType.ReadAsInt32: ReadAsInt32(); break; case ReadType.ReadAsInt64: { bool result = ReadAndMoveToContent(); if (TokenType == JsonToken.Undefined) { throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long))); } return result; } case ReadType.ReadAsDecimal: ReadAsDecimal(); break; case ReadType.ReadAsDouble: ReadAsDouble(); break; case ReadType.ReadAsBytes: ReadAsBytes(); break; case ReadType.ReadAsBoolean: ReadAsBoolean(); break; case ReadType.ReadAsString: ReadAsString(); break; case ReadType.ReadAsDateTime: ReadAsDateTime(); break; case ReadType.ReadAsDateTimeOffset: ReadAsDateTimeOffset(); break; default: throw new ArgumentOutOfRangeException(); } return TokenType != JsonToken.None; } internal bool ReadAndMoveToContent() { if (Read()) { return MoveToContent(); } return false; } internal bool MoveToContent() { JsonToken tokenType = TokenType; while (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { if (!Read()) { return false; } tokenType = TokenType; } return true; } private JsonToken GetContentToken() { JsonToken tokenType; do { if (!Read()) { SetToken(JsonToken.None); return JsonToken.None; } tokenType = TokenType; } while (tokenType == JsonToken.Comment); return tokenType; } } [Serializable] internal class JsonReaderException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonReaderException() { } public JsonReaderException(string message) : base(message) { } public JsonReaderException(string message, Exception innerException) : base(message, innerException) { } public JsonReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonReaderException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonReaderException(message, path, lineNumber, linePosition, ex); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] internal sealed class JsonRequiredAttribute : Attribute { } [Serializable] internal class JsonSerializationException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonSerializationException() { } public JsonSerializationException(string message) : base(message) { } public JsonSerializationException(string message, Exception innerException) : base(message, innerException) { } public JsonSerializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonSerializationException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonSerializationException(message, path, lineNumber, linePosition, ex); } } internal class JsonSerializer { internal TypeNameHandling _typeNameHandling; internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling; internal PreserveReferencesHandling _preserveReferencesHandling; internal ReferenceLoopHandling _referenceLoopHandling; internal MissingMemberHandling _missingMemberHandling; internal ObjectCreationHandling _objectCreationHandling; internal NullValueHandling _nullValueHandling; internal DefaultValueHandling _defaultValueHandling; internal ConstructorHandling _constructorHandling; internal MetadataPropertyHandling _metadataPropertyHandling; internal JsonConverterCollection? _converters; internal IContractResolver _contractResolver; internal ITraceWriter? _traceWriter; internal IEqualityComparer? _equalityComparer; internal ISerializationBinder _serializationBinder; internal StreamingContext _context; private IReferenceResolver? _referenceResolver; private Formatting? _formatting; private DateFormatHandling? _dateFormatHandling; private DateTimeZoneHandling? _dateTimeZoneHandling; private DateParseHandling? _dateParseHandling; private FloatFormatHandling? _floatFormatHandling; private FloatParseHandling? _floatParseHandling; private StringEscapeHandling? _stringEscapeHandling; private CultureInfo _culture; private int? _maxDepth; private bool _maxDepthSet; private bool? _checkAdditionalContent; private string? _dateFormatString; private bool _dateFormatStringSet; public virtual IReferenceResolver? ReferenceResolver { get { return GetReferenceResolver(); } set { if (value == null) { throw new ArgumentNullException("value", "Reference resolver cannot be null."); } _referenceResolver = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public virtual SerializationBinder Binder { get { if (_serializationBinder is SerializationBinder result) { return result; } if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value); } } public virtual ISerializationBinder SerializationBinder { get { return _serializationBinder; } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = value; } } public virtual ITraceWriter? TraceWriter { get { return _traceWriter; } set { _traceWriter = value; } } public virtual IEqualityComparer? EqualityComparer { get { return _equalityComparer; } set { _equalityComparer = value; } } public virtual TypeNameHandling TypeNameHandling { get { return _typeNameHandling; } set { if (value < TypeNameHandling.None || value > TypeNameHandling.Auto) { throw new ArgumentOutOfRangeException("value"); } _typeNameHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public virtual FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling; } set { if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling; } set { if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = value; } } public virtual PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling; } set { if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All) { throw new ArgumentOutOfRangeException("value"); } _preserveReferencesHandling = value; } } public virtual ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling; } set { if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize) { throw new ArgumentOutOfRangeException("value"); } _referenceLoopHandling = value; } } public virtual MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling; } set { if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _missingMemberHandling = value; } } public virtual NullValueHandling NullValueHandling { get { return _nullValueHandling; } set { if (value < NullValueHandling.Include || value > NullValueHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _nullValueHandling = value; } } public virtual DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling; } set { if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate) { throw new ArgumentOutOfRangeException("value"); } _defaultValueHandling = value; } } public virtual ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling; } set { if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace) { throw new ArgumentOutOfRangeException("value"); } _objectCreationHandling = value; } } public virtual ConstructorHandling ConstructorHandling { get { return _constructorHandling; } set { if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor) { throw new ArgumentOutOfRangeException("value"); } _constructorHandling = value; } } public virtual MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling; } set { if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _metadataPropertyHandling = value; } } public virtual JsonConverterCollection Converters { get { if (_converters == null) { _converters = new JsonConverterCollection(); } return _converters; } } public virtual IContractResolver ContractResolver { get { return _contractResolver; } set { _contractResolver = value ?? DefaultContractResolver.Instance; } } public virtual StreamingContext Context { get { return _context; } set { _context = value; } } public virtual Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public virtual DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public virtual DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind; } set { _dateTimeZoneHandling = value; } } public virtual DateParseHandling DateParseHandling { get { return _dateParseHandling ?? DateParseHandling.DateTime; } set { _dateParseHandling = value; } } public virtual FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public virtual string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public virtual CultureInfo Culture { get { return _culture ?? JsonSerializerSettings.DefaultCulture; } set { _culture = value; } } public virtual int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public virtual bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } public virtual event EventHandler? Error; internal bool IsCheckAdditionalContentSet() { return _checkAdditionalContent.HasValue; } public JsonSerializer() { _referenceLoopHandling = ReferenceLoopHandling.Error; _missingMemberHandling = MissingMemberHandling.Ignore; _nullValueHandling = NullValueHandling.Include; _defaultValueHandling = DefaultValueHandling.Include; _objectCreationHandling = ObjectCreationHandling.Auto; _preserveReferencesHandling = PreserveReferencesHandling.None; _constructorHandling = ConstructorHandling.Default; _typeNameHandling = TypeNameHandling.None; _metadataPropertyHandling = MetadataPropertyHandling.Default; _context = JsonSerializerSettings.DefaultContext; _serializationBinder = DefaultSerializationBinder.Instance; _culture = JsonSerializerSettings.DefaultCulture; _contractResolver = DefaultContractResolver.Instance; } public static JsonSerializer Create() { return new JsonSerializer(); } public static JsonSerializer Create(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = Create(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } public static JsonSerializer CreateDefault() { return Create(JsonConvert.DefaultSettings?.Invoke()); } public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = CreateDefault(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings) { if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) { for (int i = 0; i < settings.Converters.Count; i++) { serializer.Converters.Insert(i, settings.Converters[i]); } } if (settings._typeNameHandling.HasValue) { serializer.TypeNameHandling = settings.TypeNameHandling; } if (settings._metadataPropertyHandling.HasValue) { serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling; } if (settings._typeNameAssemblyFormatHandling.HasValue) { serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling; } if (settings._preserveReferencesHandling.HasValue) { serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; } if (settings._referenceLoopHandling.HasValue) { serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; } if (settings._missingMemberHandling.HasValue) { serializer.MissingMemberHandling = settings.MissingMemberHandling; } if (settings._objectCreationHandling.HasValue) { serializer.ObjectCreationHandling = settings.ObjectCreationHandling; } if (settings._nullValueHandling.HasValue) { serializer.NullValueHandling = settings.NullValueHandling; } if (settings._defaultValueHandling.HasValue) { serializer.DefaultValueHandling = settings.DefaultValueHandling; } if (settings._constructorHandling.HasValue) { serializer.ConstructorHandling = settings.ConstructorHandling; } if (settings._context.HasValue) { serializer.Context = settings.Context; } if (settings._checkAdditionalContent.HasValue) { serializer._checkAdditionalContent = settings._checkAdditionalContent; } if (settings.Error != null) { serializer.Error += settings.Error; } if (settings.ContractResolver != null) { serializer.ContractResolver = settings.ContractResolver; } if (settings.ReferenceResolverProvider != null) { serializer.ReferenceResolver = settings.ReferenceResolverProvider(); } if (settings.TraceWriter != null) { serializer.TraceWriter = settings.TraceWriter; } if (settings.EqualityComparer != null) { serializer.EqualityComparer = settings.EqualityComparer; } if (settings.SerializationBinder != null) { serializer.SerializationBinder = settings.SerializationBinder; } if (settings._formatting.HasValue) { serializer._formatting = settings._formatting; } if (settings._dateFormatHandling.HasValue) { serializer._dateFormatHandling = settings._dateFormatHandling; } if (settings._dateTimeZoneHandling.HasValue) { serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling; } if (settings._dateParseHandling.HasValue) { serializer._dateParseHandling = settings._dateParseHandling; } if (settings._dateFormatStringSet) { serializer._dateFormatString = settings._dateFormatString; serializer._dateFormatStringSet = settings._dateFormatStringSet; } if (settings._floatFormatHandling.HasValue) { serializer._floatFormatHandling = settings._floatFormatHandling; } if (settings._floatParseHandling.HasValue) { serializer._floatParseHandling = settings._floatParseHandling; } if (settings._stringEscapeHandling.HasValue) { serializer._stringEscapeHandling = settings._stringEscapeHandling; } if (settings._culture != null) { serializer._culture = settings._culture; } if (settings._maxDepthSet) { serializer._maxDepth = settings._maxDepth; serializer._maxDepthSet = settings._maxDepthSet; } } [DebuggerStepThrough] public void Populate(TextReader reader, object target) { Populate(new JsonTextReader(reader), target); } [DebuggerStepThrough] public void Populate(JsonReader reader, object target) { PopulateInternal(reader, target); } internal virtual void PopulateInternal(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(target, "target"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader) { return Deserialize(reader, null); } [DebuggerStepThrough] public object? Deserialize(TextReader reader, Type objectType) { return Deserialize(new JsonTextReader(reader), objectType); } [DebuggerStepThrough] public T? Deserialize(JsonReader reader) { return (T)Deserialize(reader, typeof(T)); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader, Type? objectType) { return DeserializeInternal(reader, objectType); } internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) { ValidationUtils.ArgumentNotNull(reader, "reader"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); object? result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); return result; } internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { previousCulture = reader.Culture; reader.Culture = _culture; } else { previousCulture = null; } if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling) { previousDateTimeZoneHandling = reader.DateTimeZoneHandling; reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } else { previousDateTimeZoneHandling = null; } if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling) { previousDateParseHandling = reader.DateParseHandling; reader.DateParseHandling = _dateParseHandling.GetValueOrDefault(); } else { previousDateParseHandling = null; } if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling) { previousFloatParseHandling = reader.FloatParseHandling; reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault(); } else { previousFloatParseHandling = null; } if (_maxDepthSet && reader.MaxDepth != _maxDepth) { previousMaxDepth = reader.MaxDepth; reader.MaxDepth = _maxDepth; } else { previousMaxDepth = null; } if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString) { previousDateFormatString = reader.DateFormatString; reader.DateFormatString = _dateFormatString; } else { previousDateFormatString = null; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver defaultContractResolver) { jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable(); } } private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString) { if (previousCulture != null) { reader.Culture = previousCulture; } if (previousDateTimeZoneHandling.HasValue) { reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault(); } if (previousDateParseHandling.HasValue) { reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault(); } if (previousFloatParseHandling.HasValue) { reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault(); } if (_maxDepthSet) { reader.MaxDepth = previousMaxDepth; } if (_dateFormatStringSet) { reader.DateFormatString = previousDateFormatString; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable != null && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable()) { jsonTextReader.PropertyNameTable = null; } } public void Serialize(TextWriter textWriter, object? value) { Serialize(new JsonTextWriter(textWriter), value); } public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) { SerializeInternal(jsonWriter, value, objectType); } public void Serialize(TextWriter textWriter, object? value, Type objectType) { Serialize(new JsonTextWriter(textWriter), value, objectType); } public void Serialize(JsonWriter jsonWriter, object? value) { SerializeInternal(jsonWriter, value, null); } private TraceJsonReader CreateTraceJsonReader(JsonReader reader) { TraceJsonReader traceJsonReader = new TraceJsonReader(reader); if (reader.TokenType != 0) { traceJsonReader.WriteCurrentToken(); } return traceJsonReader; } internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType) { ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter"); Formatting? formatting = null; if (_formatting.HasValue && jsonWriter.Formatting != _formatting) { formatting = jsonWriter.Formatting; jsonWriter.Formatting = _formatting.GetValueOrDefault(); } DateFormatHandling? dateFormatHandling = null; if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling) { dateFormatHandling = jsonWriter.DateFormatHandling; jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault(); } DateTimeZoneHandling? dateTimeZoneHandling = null; if (_dateTimeZoneHandling.HasValue && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling) { dateTimeZoneHandling = jsonWriter.DateTimeZoneHandling; jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } FloatFormatHandling? floatFormatHandling = null; if (_floatFormatHandling.HasValue && jsonWriter.FloatFormatHandling != _floatFormatHandling) { floatFormatHandling = jsonWriter.FloatFormatHandling; jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault(); } StringEscapeHandling? stringEscapeHandling = null; if (_stringEscapeHandling.HasValue && jsonWriter.StringEscapeHandling != _stringEscapeHandling) { stringEscapeHandling = jsonWriter.StringEscapeHandling; jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault(); } CultureInfo cultureInfo = null; if (_culture != null && !_culture.Equals(jsonWriter.Culture)) { cultureInfo = jsonWriter.Culture; jsonWriter.Culture = _culture; } string dateFormatString = null; if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) { dateFormatString = jsonWriter.DateFormatString; jsonWriter.DateFormatString = _dateFormatString; } TraceJsonWriter traceJsonWriter = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null); new JsonSerializerInternalWriter(this).Serialize(traceJsonWriter ?? jsonWriter, value, objectType); if (traceJsonWriter != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); } if (formatting.HasValue) { jsonWriter.Formatting = formatting.GetValueOrDefault(); } if (dateFormatHandling.HasValue) { jsonWriter.DateFormatHandling = dateFormatHandling.GetValueOrDefault(); } if (dateTimeZoneHandling.HasValue) { jsonWriter.DateTimeZoneHandling = dateTimeZoneHandling.GetValueOrDefault(); } if (floatFormatHandling.HasValue) { jsonWriter.FloatFormatHandling = floatFormatHandling.GetValueOrDefault(); } if (stringEscapeHandling.HasValue) { jsonWriter.StringEscapeHandling = stringEscapeHandling.GetValueOrDefault(); } if (_dateFormatStringSet) { jsonWriter.DateFormatString = dateFormatString; } if (cultureInfo != null) { jsonWriter.Culture = cultureInfo; } } internal IReferenceResolver GetReferenceResolver() { if (_referenceResolver == null) { _referenceResolver = new DefaultReferenceResolver(); } return _referenceResolver; } internal JsonConverter? GetMatchingConverter(Type type) { return GetMatchingConverter(_converters, type); } internal static JsonConverter? GetMatchingConverter(IList? converters, Type objectType) { if (converters != null) { for (int i = 0; i < converters.Count; i++) { JsonConverter jsonConverter = converters[i]; if (jsonConverter.CanConvert(objectType)) { return jsonConverter; } } } return null; } internal void OnError(Newtonsoft.Json.Serialization.ErrorEventArgs e) { this.Error?.Invoke(this, e); } } internal class JsonSerializerSettings { internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error; internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore; internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include; internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include; internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto; internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None; internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default; internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None; internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default; internal static readonly StreamingContext DefaultContext; internal const Formatting DefaultFormatting = Formatting.None; internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat; internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime; internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double; internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String; internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default; internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple; internal static readonly CultureInfo DefaultCulture; internal const bool DefaultCheckAdditionalContent = false; internal const string DefaultDateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; internal const int DefaultMaxDepth = 64; internal Formatting? _formatting; internal DateFormatHandling? _dateFormatHandling; internal DateTimeZoneHandling? _dateTimeZoneHandling; internal DateParseHandling? _dateParseHandling; internal FloatFormatHandling? _floatFormatHandling; internal FloatParseHandling? _floatParseHandling; internal StringEscapeHandling? _stringEscapeHandling; internal CultureInfo? _culture; internal bool? _checkAdditionalContent; internal int? _maxDepth; internal bool _maxDepthSet; internal string? _dateFormatString; internal bool _dateFormatStringSet; internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling; internal DefaultValueHandling? _defaultValueHandling; internal PreserveReferencesHandling? _preserveReferencesHandling; internal NullValueHandling? _nullValueHandling; internal ObjectCreationHandling? _objectCreationHandling; internal MissingMemberHandling? _missingMemberHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal StreamingContext? _context; internal ConstructorHandling? _constructorHandling; internal TypeNameHandling? _typeNameHandling; internal MetadataPropertyHandling? _metadataPropertyHandling; public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public IList Converters { get; set; } public PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling.GetValueOrDefault(); } set { _preserveReferencesHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling.GetValueOrDefault(); } set { _metadataPropertyHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)TypeNameAssemblyFormatHandling; } set { TypeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling.GetValueOrDefault(); } set { _typeNameAssemblyFormatHandling = value; } } public ConstructorHandling ConstructorHandling { get { return _constructorHandling.GetValueOrDefault(); } set { _constructorHandling = value; } } public IContractResolver? ContractResolver { get; set; } public IEqualityComparer? EqualityComparer { get; set; } [Obsolete("ReferenceResolver property is obsolete. Use the ReferenceResolverProvider property to set the IReferenceResolver: settings.ReferenceResolverProvider = () => resolver")] public IReferenceResolver? ReferenceResolver { get { return ReferenceResolverProvider?.Invoke(); } set { IReferenceResolver value2 = value; ReferenceResolverProvider = ((value2 != null) ? ((Func)(() => value2)) : null); } } public Func? ReferenceResolverProvider { get; set; } public ITraceWriter? TraceWriter { get; set; } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public SerializationBinder? Binder { get { if (SerializationBinder == null) { return null; } if (SerializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { SerializationBinder = ((value == null) ? null : new SerializationBinderAdapter(value)); } } public ISerializationBinder? SerializationBinder { get; set; } public EventHandler? Error { get; set; } public StreamingContext Context { get { return _context ?? DefaultContext; } set { _context = value; } } public string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public int? MaxDepth { get { if (!_maxDepthSet) { return 64; } return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind; } set { _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling ?? DateParseHandling.DateTime; } set { _dateParseHandling = value; } } public FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public CultureInfo Culture { get { return _culture ?? DefaultCulture; } set { _culture = value; } } public bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } static JsonSerializerSettings() { DefaultContext = default(StreamingContext); DefaultCulture = CultureInfo.InvariantCulture; } [DebuggerStepThrough] public JsonSerializerSettings() { Converters = new List(); } public JsonSerializerSettings(JsonSerializerSettings original) { _floatParseHandling = original._floatParseHandling; _floatFormatHandling = original._floatFormatHandling; _dateParseHandling = original._dateParseHandling; _dateTimeZoneHandling = original._dateTimeZoneHandling; _dateFormatHandling = original._dateFormatHandling; _formatting = original._formatting; _maxDepth = original._maxDepth; _maxDepthSet = original._maxDepthSet; _dateFormatString = original._dateFormatString; _dateFormatStringSet = original._dateFormatStringSet; _context = original._context; Error = original.Error; SerializationBinder = original.SerializationBinder; TraceWriter = original.TraceWriter; _culture = original._culture; ReferenceResolverProvider = original.ReferenceResolverProvider; EqualityComparer = original.EqualityComparer; ContractResolver = original.ContractResolver; _constructorHandling = original._constructorHandling; _typeNameAssemblyFormatHandling = original._typeNameAssemblyFormatHandling; _metadataPropertyHandling = original._metadataPropertyHandling; _typeNameHandling = original._typeNameHandling; _preserveReferencesHandling = original._preserveReferencesHandling; Converters = original.Converters.ToList(); _defaultValueHandling = original._defaultValueHandling; _nullValueHandling = original._nullValueHandling; _objectCreationHandling = original._objectCreationHandling; _missingMemberHandling = original._missingMemberHandling; _referenceLoopHandling = original._referenceLoopHandling; _checkAdditionalContent = original._checkAdditionalContent; _stringEscapeHandling = original._stringEscapeHandling; } } internal class JsonTextReader : JsonReader, IJsonLineInfo { private readonly bool _safeAsync; private const char UnicodeReplacementChar = '\ufffd'; private const int MaximumJavascriptIntegerCharacterLength = 380; private const int LargeBufferLength = 1073741823; private readonly TextReader _reader; private char[]? _chars; private int _charsUsed; private int _charPos; private int _lineStartPos; private int _lineNumber; private bool _isEndOfFile; private StringBuffer _stringBuffer; private StringReference _stringReference; private IArrayPool? _arrayPool; public JsonNameTable? PropertyNameTable { get; set; } public IArrayPool? ArrayPool { get { return _arrayPool; } set { if (value == null) { throw new ArgumentNullException("value"); } _arrayPool = value; } } public int LineNumber { get { if (base.CurrentState == State.Start && LinePosition == 0 && TokenType != JsonToken.Comment) { return 0; } return _lineNumber; } } public int LinePosition => _charPos - _lineStartPos; public override Task ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsync(cancellationToken); } return DoReadAsync(cancellationToken); } internal Task DoReadAsync(CancellationToken cancellationToken) { EnsureBuffer(); Task task; do { switch (_currentState) { case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: return ParseValueAsync(cancellationToken); case State.ObjectStart: case State.Object: return ParseObjectAsync(cancellationToken); case State.PostValue: task = ParsePostValueAsync(ignoreComments: false, cancellationToken); if (!task.IsCompletedSuccessfully()) { return DoReadAsync(task, cancellationToken); } break; case State.Finished: return ReadFromFinishedAsync(cancellationToken); default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } while (!task.Result); return AsyncUtils.True; } private async Task DoReadAsync(Task task, CancellationToken cancellationToken) { if (await task.ConfigureAwait(continueOnCapturedContext: false)) { return true; } return await DoReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } private async Task ParsePostValueAsync(bool ignoreComments, CancellationToken cancellationToken) { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (await ReadDataAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { _currentState = State.Finished; return false; } } else { _charPos++; } continue; case '}': _charPos++; SetToken(JsonToken.EndObject); return true; case ']': _charPos++; SetToken(JsonToken.EndArray); return true; case ')': _charPos++; SetToken(JsonToken.EndConstructor); return true; case '/': await ParseCommentAsync(!ignoreComments, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!ignoreComments) { return true; } continue; case ',': _charPos++; SetStateBasedOnCurrent(); return false; case '\t': case ' ': _charPos++; continue; case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); continue; case '\n': ProcessLineFeed(); continue; } if (char.IsWhiteSpace(c)) { _charPos++; continue; } if (base.SupportMultipleContent && Depth == 0) { SetStateBasedOnCurrent(); return false; } throw JsonReaderException.Create(this, "After parsing a value an unexpected character was encountered: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); } } private async Task ReadFromFinishedAsync(CancellationToken cancellationToken) { if (await EnsureCharsAsync(0, append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { await EatWhitespaceAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (_isEndOfFile) { SetToken(JsonToken.None); return false; } if (_chars[_charPos] == '/') { await ParseCommentAsync(setToken: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; } throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } SetToken(JsonToken.None); return false; } private Task ReadDataAsync(bool append, CancellationToken cancellationToken) { return ReadDataAsync(append, 0, cancellationToken); } private async Task ReadDataAsync(bool append, int charsRequired, CancellationToken cancellationToken) { if (_isEndOfFile) { return 0; } PrepareBufferForReadData(append, charsRequired); int num = await _reader.ReadAsync(_chars, _charsUsed, _chars.Length - _charsUsed - 1, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); _charsUsed += num; if (num == 0) { _isEndOfFile = true; } _chars[_charsUsed] = '\0'; return num; } private async Task ParseValueAsync(CancellationToken cancellationToken) { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (await ReadDataAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { return false; } } else { _charPos++; } break; case '"': case '\'': await ParseStringAsync(c, ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case 't': await ParseTrueAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case 'f': await ParseFalseAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case 'n': if (await EnsureCharsAsync(1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { switch (_chars[_charPos + 1]) { case 'u': await ParseNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case 'e': await ParseConstructorAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; default: throw CreateUnexpectedCharacterException(_chars[_charPos]); } return true; } _charPos++; throw CreateUnexpectedEndException(); case 'N': await ParseNumberNaNAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case 'I': await ParseNumberPositiveInfinityAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case '-': if (!(await EnsureCharsAsync(1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) || _chars[_charPos + 1] != 'I') { await ParseNumberAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { await ParseNumberNegativeInfinityAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return true; case '/': await ParseCommentAsync(setToken: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case 'u': await ParseUndefinedAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case '{': _charPos++; SetToken(JsonToken.StartObject); return true; case '[': _charPos++; SetToken(JsonToken.StartArray); return true; case ']': _charPos++; SetToken(JsonToken.EndArray); return true; case ',': SetToken(JsonToken.Undefined); return true; case ')': _charPos++; SetToken(JsonToken.EndConstructor); return true; case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: if (char.IsWhiteSpace(c)) { _charPos++; break; } if (char.IsNumber(c) || c == '-' || c == '.') { await ParseNumberAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; } throw CreateUnexpectedCharacterException(c); } } } private async Task ReadStringIntoBufferAsync(char quote, CancellationToken cancellationToken) { int charPos = _charPos; int initialPosition = _charPos; int lastWritePosition = _charPos; _stringBuffer.Position = 0; while (true) { switch (_chars[charPos++]) { case '\0': if (_charsUsed == charPos - 1) { charPos--; if (await ReadDataAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { _charPos = charPos; throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); } } break; case '\\': { _charPos = charPos; if (!(await EnsureCharsAsync(0, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); } int escapeStartPos = charPos - 1; char c = _chars[charPos]; charPos++; char writeChar; switch (c) { case 'b': writeChar = '\b'; break; case 't': writeChar = '\t'; break; case 'n': writeChar = '\n'; break; case 'f': writeChar = '\f'; break; case 'r': writeChar = '\r'; break; case '\\': writeChar = '\\'; break; case '"': case '\'': case '/': writeChar = c; break; case 'u': _charPos = charPos; writeChar = await ParseUnicodeAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (StringUtils.IsLowSurrogate(writeChar)) { writeChar = '\ufffd'; } else if (StringUtils.IsHighSurrogate(writeChar)) { bool anotherHighSurrogate; do { anotherHighSurrogate = false; if (await EnsureCharsAsync(2, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && _chars[_charPos] == '\\' && _chars[_charPos + 1] == 'u') { char highSurrogate = writeChar; _charPos += 2; writeChar = await ParseUnicodeAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!StringUtils.IsLowSurrogate(writeChar)) { if (StringUtils.IsHighSurrogate(writeChar)) { highSurrogate = '\ufffd'; anotherHighSurrogate = true; } else { highSurrogate = '\ufffd'; } } EnsureBufferNotEmpty(); WriteCharToBuffer(highSurrogate, lastWritePosition, escapeStartPos); lastWritePosition = _charPos; } else { writeChar = '\ufffd'; } } while (anotherHighSurrogate); } charPos = _charPos; break; default: _charPos = charPos; throw JsonReaderException.Create(this, "Bad JSON escape sequence: {0}.".FormatWith(CultureInfo.InvariantCulture, "\\" + c)); } EnsureBufferNotEmpty(); WriteCharToBuffer(writeChar, lastWritePosition, escapeStartPos); lastWritePosition = charPos; break; } case '\r': _charPos = charPos - 1; await ProcessCarriageReturnAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); charPos = _charPos; break; case '\n': _charPos = charPos - 1; ProcessLineFeed(); charPos = _charPos; break; case '"': case '\'': if (_chars[charPos - 1] == quote) { FinishReadStringIntoBuffer(charPos - 1, initialPosition, lastWritePosition); return; } break; } } } private Task ProcessCarriageReturnAsync(bool append, CancellationToken cancellationToken) { _charPos++; Task task = EnsureCharsAsync(1, append, cancellationToken); if (task.IsCompletedSuccessfully()) { SetNewLine(task.Result); return AsyncUtils.CompletedTask; } return ProcessCarriageReturnAsync(task); } private async Task ProcessCarriageReturnAsync(Task task) { SetNewLine(await task.ConfigureAwait(continueOnCapturedContext: false)); } private async Task ParseUnicodeAsync(CancellationToken cancellationToken) { return ConvertUnicode(await EnsureCharsAsync(4, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } private Task EnsureCharsAsync(int relativePosition, bool append, CancellationToken cancellationToken) { if (_charPos + relativePosition < _charsUsed) { return AsyncUtils.True; } if (_isEndOfFile) { return AsyncUtils.False; } return ReadCharsAsync(relativePosition, append, cancellationToken); } private async Task ReadCharsAsync(int relativePosition, bool append, CancellationToken cancellationToken) { int charsRequired = _charPos + relativePosition - _charsUsed + 1; do { int num = await ReadDataAsync(append, charsRequired, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (num == 0) { return false; } charsRequired -= num; } while (charsRequired > 0); return true; } private async Task ParseObjectAsync(CancellationToken cancellationToken) { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (await ReadDataAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { return false; } } else { _charPos++; } break; case '}': SetToken(JsonToken.EndObject); _charPos++; return true; case '/': await ParseCommentAsync(setToken: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: if (char.IsWhiteSpace(c)) { _charPos++; break; } return await ParsePropertyAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } } private async Task ParseCommentAsync(bool setToken, CancellationToken cancellationToken) { _charPos++; if (!(await EnsureCharsAsync(1, append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); } bool singlelineComment; if (_chars[_charPos] == '*') { singlelineComment = false; } else { if (_chars[_charPos] != '/') { throw JsonReaderException.Create(this, "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } singlelineComment = true; } _charPos++; int initialPosition = _charPos; while (true) { switch (_chars[_charPos]) { case '\0': if (_charsUsed == _charPos) { if (await ReadDataAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { if (!singlelineComment) { throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); } EndComment(setToken, initialPosition, _charPos); return; } } else { _charPos++; } break; case '*': _charPos++; if (!singlelineComment && await EnsureCharsAsync(0, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && _chars[_charPos] == '/') { EndComment(setToken, initialPosition, _charPos - 1); _charPos++; return; } break; case '\r': if (singlelineComment) { EndComment(setToken, initialPosition, _charPos); return; } await ProcessCarriageReturnAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': if (singlelineComment) { EndComment(setToken, initialPosition, _charPos); return; } ProcessLineFeed(); break; default: _charPos++; break; } } } private async Task EatWhitespaceAsync(CancellationToken cancellationToken) { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (await ReadDataAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { return; } } else { _charPos++; } break; case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; default: if (!char.IsWhiteSpace(c)) { return; } goto case ' '; case ' ': _charPos++; break; } } } private async Task ParseStringAsync(char quote, ReadType readType, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); _charPos++; ShiftBufferIfNeeded(); await ReadStringIntoBufferAsync(quote, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); ParseReadString(quote, readType); } private async Task MatchValueAsync(string value, CancellationToken cancellationToken) { return MatchValue(await EnsureCharsAsync(value.Length - 1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false), value); } private async Task MatchValueWithTrailingSeparatorAsync(string value, CancellationToken cancellationToken) { if (!(await MatchValueAsync(value, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return false; } if (!(await EnsureCharsAsync(0, append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return true; } return IsSeparator(_chars[_charPos]) || _chars[_charPos] == '\0'; } private async Task MatchAndSetAsync(string value, JsonToken newToken, object? tokenValue, CancellationToken cancellationToken) { if (await MatchValueWithTrailingSeparatorAsync(value, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { SetToken(newToken, tokenValue); return; } throw JsonReaderException.Create(this, "Error parsing " + newToken.ToString().ToLowerInvariant() + " value."); } private Task ParseTrueAsync(CancellationToken cancellationToken) { return MatchAndSetAsync(JsonConvert.True, JsonToken.Boolean, true, cancellationToken); } private Task ParseFalseAsync(CancellationToken cancellationToken) { return MatchAndSetAsync(JsonConvert.False, JsonToken.Boolean, false, cancellationToken); } private Task ParseNullAsync(CancellationToken cancellationToken) { return MatchAndSetAsync(JsonConvert.Null, JsonToken.Null, null, cancellationToken); } private async Task ParseConstructorAsync(CancellationToken cancellationToken) { if (await MatchValueWithTrailingSeparatorAsync("new", cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { await EatWhitespaceAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); int initialPosition = _charPos; int endPosition; while (true) { char c = _chars[_charPos]; if (c == '\0') { if (_charsUsed == _charPos) { if (await ReadDataAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { throw JsonReaderException.Create(this, "Unexpected end while parsing constructor."); } continue; } endPosition = _charPos; _charPos++; break; } if (char.IsLetterOrDigit(c)) { _charPos++; continue; } switch (c) { case '\r': endPosition = _charPos; await ProcessCarriageReturnAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': endPosition = _charPos; ProcessLineFeed(); break; default: if (char.IsWhiteSpace(c)) { endPosition = _charPos; _charPos++; break; } if (c == '(') { endPosition = _charPos; break; } throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); } break; } _stringReference = new StringReference(_chars, initialPosition, endPosition - initialPosition); string constructorName = _stringReference.ToString(); await EatWhitespaceAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (_chars[_charPos] != '(') { throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } _charPos++; ClearRecentString(); SetToken(JsonToken.StartConstructor, constructorName); return; } throw JsonReaderException.Create(this, "Unexpected content while parsing JSON."); } private async Task ParseNumberNaNAsync(ReadType readType, CancellationToken cancellationToken) { return ParseNumberNaN(readType, await MatchValueWithTrailingSeparatorAsync(JsonConvert.NaN, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } private async Task ParseNumberPositiveInfinityAsync(ReadType readType, CancellationToken cancellationToken) { return ParseNumberPositiveInfinity(readType, await MatchValueWithTrailingSeparatorAsync(JsonConvert.PositiveInfinity, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } private async Task ParseNumberNegativeInfinityAsync(ReadType readType, CancellationToken cancellationToken) { return ParseNumberNegativeInfinity(readType, await MatchValueWithTrailingSeparatorAsync(JsonConvert.NegativeInfinity, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } private async Task ParseNumberAsync(ReadType readType, CancellationToken cancellationToken) { ShiftBufferIfNeeded(); char firstChar = _chars[_charPos]; int initialPosition = _charPos; await ReadNumberIntoBufferAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); ParseReadNumber(readType, firstChar, initialPosition); } private Task ParseUndefinedAsync(CancellationToken cancellationToken) { return MatchAndSetAsync(JsonConvert.Undefined, JsonToken.Undefined, null, cancellationToken); } private async Task ParsePropertyAsync(CancellationToken cancellationToken) { char c = _chars[_charPos]; char quoteChar; if (c == '"' || c == '\'') { _charPos++; quoteChar = c; ShiftBufferIfNeeded(); await ReadStringIntoBufferAsync(quoteChar, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { if (!ValidIdentifierChar(c)) { throw JsonReaderException.Create(this, "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } quoteChar = '\0'; ShiftBufferIfNeeded(); await ParseUnquotedPropertyAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } string propertyName = ((PropertyNameTable == null) ? _stringReference.ToString() : (PropertyNameTable.Get(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length) ?? _stringReference.ToString())); await EatWhitespaceAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (_chars[_charPos] != ':') { throw JsonReaderException.Create(this, "Invalid character after parsing property name. Expected ':' but got: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } _charPos++; SetToken(JsonToken.PropertyName, propertyName); _quoteChar = quoteChar; ClearRecentString(); return true; } private async Task ReadNumberIntoBufferAsync(CancellationToken cancellationToken) { int charPos = _charPos; while (true) { char c = _chars[charPos]; if (c == '\0') { _charPos = charPos; if (_charsUsed != charPos || await ReadDataAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { break; } } else { if (ReadNumberCharIntoBuffer(c, charPos)) { break; } charPos++; } } } private async Task ParseUnquotedPropertyAsync(CancellationToken cancellationToken) { int initialPosition = _charPos; while (true) { char c = _chars[_charPos]; if (c == '\0') { if (_charsUsed != _charPos) { _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition); break; } if (await ReadDataAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { throw JsonReaderException.Create(this, "Unexpected end while parsing unquoted property name."); } } else if (ReadUnquotedPropertyReportIfDone(c, initialPosition)) { break; } } } private async Task ReadNullCharAsync(CancellationToken cancellationToken) { if (_charsUsed == _charPos) { if (await ReadDataAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { _isEndOfFile = true; return true; } } else { _charPos++; } return false; } private async Task HandleNullAsync(CancellationToken cancellationToken) { if (await EnsureCharsAsync(1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { if (_chars[_charPos + 1] == 'u') { await ParseNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return; } _charPos += 2; throw CreateUnexpectedCharacterException(_chars[_charPos - 1]); } _charPos = _charsUsed; throw CreateUnexpectedEndException(); } private async Task ReadFinishedAsync(CancellationToken cancellationToken) { if (await EnsureCharsAsync(0, append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { await EatWhitespaceAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (_isEndOfFile) { SetToken(JsonToken.None); return; } if (_chars[_charPos] != '/') { throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } await ParseCommentAsync(setToken: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } SetToken(JsonToken.None); } private async Task ReadStringValueAsync(ReadType readType, CancellationToken cancellationToken) { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (await ParsePostValueAsync(ignoreComments: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': await ParseStringAsync(c, readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return FinishReadQuotedStringValue(readType); case '-': if (await EnsureCharsAsync(1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && _chars[_charPos + 1] == 'I') { return ParseNumberNegativeInfinity(readType); } await ParseNumberAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return Value; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (readType != ReadType.ReadAsString) { _charPos++; throw CreateUnexpectedCharacterException(c); } await ParseNumberAsync(ReadType.ReadAsString, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return Value; case 'f': case 't': { if (readType != ReadType.ReadAsString) { _charPos++; throw CreateUnexpectedCharacterException(c); } string expected = ((c == 't') ? JsonConvert.True : JsonConvert.False); if (!(await MatchValueWithTrailingSeparatorAsync(expected, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedCharacterException(_chars[_charPos]); } SetToken(JsonToken.String, expected); return expected; } case 'I': return await ParseNumberPositiveInfinityAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case 'N': return await ParseNumberNaNAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case 'n': await HandleNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; case '/': await ParseCommentAsync(setToken: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: await ReadFinishedAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private async Task ReadNumberValueAsync(ReadType readType, CancellationToken cancellationToken) { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (await ParsePostValueAsync(ignoreComments: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': await ParseStringAsync(c, readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return FinishReadQuotedNumber(readType); case 'n': await HandleNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; case 'N': return await ParseNumberNaNAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case 'I': return await ParseNumberPositiveInfinityAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case '-': if (await EnsureCharsAsync(1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && _chars[_charPos + 1] == 'I') { return await ParseNumberNegativeInfinityAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await ParseNumberAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return Value; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': await ParseNumberAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return Value; case '/': await ParseCommentAsync(setToken: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: await ReadFinishedAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } public override Task ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsBooleanAsync(cancellationToken); } return DoReadAsBooleanAsync(cancellationToken); } internal async Task DoReadAsBooleanAsync(CancellationToken cancellationToken) { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (await ParsePostValueAsync(ignoreComments: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': await ParseStringAsync(c, ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return ReadBooleanString(_stringReference.ToString()); case 'n': await HandleNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { await ParseNumberAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); bool flag = ((!(Value is BigInteger i)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (i != 0L)); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case 'f': case 't': { bool isTrue = c == 't'; if (!(await MatchValueWithTrailingSeparatorAsync(isTrue ? JsonConvert.True : JsonConvert.False, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedCharacterException(_chars[_charPos]); } SetToken(JsonToken.Boolean, isTrue); return isTrue; } case '/': await ParseCommentAsync(setToken: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: await ReadFinishedAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } public override Task ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsBytesAsync(cancellationToken); } return DoReadAsBytesAsync(cancellationToken); } internal async Task DoReadAsBytesAsync(CancellationToken cancellationToken) { EnsureBuffer(); bool isWrapped = false; switch (_currentState) { case State.PostValue: if (await ParsePostValueAsync(ignoreComments: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': { await ParseStringAsync(c, ReadType.ReadAsBytes, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); byte[] data = (byte[])Value; if (isWrapped) { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, data, updateIndex: false); } return data; } case '{': _charPos++; SetToken(JsonToken.StartObject); await ReadIntoWrappedTypeObjectAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); isWrapped = true; break; case '[': _charPos++; SetToken(JsonToken.StartArray); return await ReadArrayIntoByteArrayAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case 'n': await HandleNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; case '/': await ParseCommentAsync(setToken: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: await ReadFinishedAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private async Task ReadIntoWrappedTypeObjectAsync(CancellationToken cancellationToken) { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (Value != null && Value.ToString() == "$type") { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public override Task ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsDateTimeAsync(cancellationToken); } return DoReadAsDateTimeAsync(cancellationToken); } internal async Task DoReadAsDateTimeAsync(CancellationToken cancellationToken) { return (DateTime?)(await ReadStringValueAsync(ReadType.ReadAsDateTime, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public override Task ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsDateTimeOffsetAsync(cancellationToken); } return DoReadAsDateTimeOffsetAsync(cancellationToken); } internal async Task DoReadAsDateTimeOffsetAsync(CancellationToken cancellationToken) { return (DateTimeOffset?)(await ReadStringValueAsync(ReadType.ReadAsDateTimeOffset, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public override Task ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsDecimalAsync(cancellationToken); } return DoReadAsDecimalAsync(cancellationToken); } internal async Task DoReadAsDecimalAsync(CancellationToken cancellationToken) { return (decimal?)(await ReadNumberValueAsync(ReadType.ReadAsDecimal, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public override Task ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsDoubleAsync(cancellationToken); } return DoReadAsDoubleAsync(cancellationToken); } internal async Task DoReadAsDoubleAsync(CancellationToken cancellationToken) { return (double?)(await ReadNumberValueAsync(ReadType.ReadAsDouble, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public override Task ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsInt32Async(cancellationToken); } return DoReadAsInt32Async(cancellationToken); } internal async Task DoReadAsInt32Async(CancellationToken cancellationToken) { return (int?)(await ReadNumberValueAsync(ReadType.ReadAsInt32, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public override Task ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsStringAsync(cancellationToken); } return DoReadAsStringAsync(cancellationToken); } internal async Task DoReadAsStringAsync(CancellationToken cancellationToken) { return (string)(await ReadStringValueAsync(ReadType.ReadAsString, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public JsonTextReader(TextReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } _reader = reader; _lineNumber = 1; _safeAsync = GetType() == typeof(JsonTextReader); } private void EnsureBufferNotEmpty() { if (_stringBuffer.IsEmpty) { _stringBuffer = new StringBuffer(_arrayPool, 1024); } } private void SetNewLine(bool hasNextChar) { if (hasNextChar && _chars[_charPos] == '\n') { _charPos++; } OnNewLine(_charPos); } private void OnNewLine(int pos) { _lineNumber++; _lineStartPos = pos; } private void ParseString(char quote, ReadType readType) { _charPos++; ShiftBufferIfNeeded(); ReadStringIntoBuffer(quote); ParseReadString(quote, readType); } private void ParseReadString(char quote, ReadType readType) { SetPostValueState(updateIndex: true); switch (readType) { case ReadType.ReadAsBytes: { Guid g; byte[] value2 = ((_stringReference.Length == 0) ? CollectionUtils.ArrayEmpty() : ((_stringReference.Length != 36 || !ConvertUtils.TryConvertGuid(_stringReference.ToString(), out g)) ? Convert.FromBase64CharArray(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length) : g.ToByteArray())); SetToken(JsonToken.Bytes, value2, updateIndex: false); return; } case ReadType.ReadAsString: { string value = _stringReference.ToString(); SetToken(JsonToken.String, value, updateIndex: false); _quoteChar = quote; return; } case ReadType.ReadAsInt32: case ReadType.ReadAsDecimal: case ReadType.ReadAsBoolean: return; } if (_dateParseHandling != 0) { DateTimeOffset dt2; if (readType switch { ReadType.ReadAsDateTime => 1, ReadType.ReadAsDateTimeOffset => 2, _ => (int)_dateParseHandling, } == 1) { if (DateTimeUtils.TryParseDateTime(_stringReference, base.DateTimeZoneHandling, base.DateFormatString, base.Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return; } } else if (DateTimeUtils.TryParseDateTimeOffset(_stringReference, base.DateFormatString, base.Culture, out dt2)) { SetToken(JsonToken.Date, dt2, updateIndex: false); return; } } SetToken(JsonToken.String, _stringReference.ToString(), updateIndex: false); _quoteChar = quote; } private static void BlockCopyChars(char[] src, int srcOffset, char[] dst, int dstOffset, int count) { Buffer.BlockCopy(src, srcOffset * 2, dst, dstOffset * 2, count * 2); } private void ShiftBufferIfNeeded() { int num = _chars.Length; if ((double)(num - _charPos) <= (double)num * 0.1 || num >= 1073741823) { int num2 = _charsUsed - _charPos; if (num2 > 0) { BlockCopyChars(_chars, _charPos, _chars, 0, num2); } _lineStartPos -= _charPos; _charPos = 0; _charsUsed = num2; _chars[_charsUsed] = '\0'; } } private int ReadData(bool append) { return ReadData(append, 0); } private void PrepareBufferForReadData(bool append, int charsRequired) { if (_charsUsed + charsRequired < _chars.Length - 1) { return; } if (append) { int num = _chars.Length * 2; int minSize = Math.Max((num < 0) ? int.MaxValue : num, _charsUsed + charsRequired + 1); char[] array = BufferUtils.RentBuffer(_arrayPool, minSize); BlockCopyChars(_chars, 0, array, 0, _chars.Length); BufferUtils.ReturnBuffer(_arrayPool, _chars); _chars = array; return; } int num2 = _charsUsed - _charPos; if (num2 + charsRequired + 1 >= _chars.Length) { char[] array2 = BufferUtils.RentBuffer(_arrayPool, num2 + charsRequired + 1); if (num2 > 0) { BlockCopyChars(_chars, _charPos, array2, 0, num2); } BufferUtils.ReturnBuffer(_arrayPool, _chars); _chars = array2; } else if (num2 > 0) { BlockCopyChars(_chars, _charPos, _chars, 0, num2); } _lineStartPos -= _charPos; _charPos = 0; _charsUsed = num2; } private int ReadData(bool append, int charsRequired) { if (_isEndOfFile) { return 0; } PrepareBufferForReadData(append, charsRequired); int count = _chars.Length - _charsUsed - 1; int num = _reader.Read(_chars, _charsUsed, count); _charsUsed += num; if (num == 0) { _isEndOfFile = true; } _chars[_charsUsed] = '\0'; return num; } private bool EnsureChars(int relativePosition, bool append) { if (_charPos + relativePosition >= _charsUsed) { return ReadChars(relativePosition, append); } return true; } private bool ReadChars(int relativePosition, bool append) { if (_isEndOfFile) { return false; } int num = _charPos + relativePosition - _charsUsed + 1; int num2 = 0; do { int num3 = ReadData(append, num - num2); if (num3 == 0) { break; } num2 += num3; } while (num2 < num); if (num2 < num) { return false; } return true; } public override bool Read() { EnsureBuffer(); do { switch (_currentState) { case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: return ParseValue(); case State.ObjectStart: case State.Object: return ParseObject(); case State.PostValue: break; case State.Finished: if (EnsureChars(0, append: false)) { EatWhitespace(); if (_isEndOfFile) { SetToken(JsonToken.None); return false; } if (_chars[_charPos] == '/') { ParseComment(setToken: true); return true; } throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } SetToken(JsonToken.None); return false; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } while (!ParsePostValue(ignoreComments: false)); return true; } public override int? ReadAsInt32() { return (int?)ReadNumberValue(ReadType.ReadAsInt32); } public override DateTime? ReadAsDateTime() { return (DateTime?)ReadStringValue(ReadType.ReadAsDateTime); } public override string? ReadAsString() { return (string)ReadStringValue(ReadType.ReadAsString); } public override byte[]? ReadAsBytes() { EnsureBuffer(); bool flag = false; switch (_currentState) { case State.PostValue: if (ParsePostValue(ignoreComments: true)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (ReadNullChar()) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': { ParseString(c, ReadType.ReadAsBytes); byte[] array = (byte[])Value; if (flag) { ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array, updateIndex: false); } return array; } case '{': _charPos++; SetToken(JsonToken.StartObject); ReadIntoWrappedTypeObject(); flag = true; break; case '[': _charPos++; SetToken(JsonToken.StartArray); return ReadArrayIntoByteArray(); case 'n': HandleNull(); return null; case '/': ParseComment(setToken: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: ReadFinished(); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private object? ReadStringValue(ReadType readType) { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (ParsePostValue(ignoreComments: true)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (ReadNullChar()) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': ParseString(c, readType); return FinishReadQuotedStringValue(readType); case '-': if (EnsureChars(1, append: true) && _chars[_charPos + 1] == 'I') { return ParseNumberNegativeInfinity(readType); } ParseNumber(readType); return Value; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (readType != ReadType.ReadAsString) { _charPos++; throw CreateUnexpectedCharacterException(c); } ParseNumber(ReadType.ReadAsString); return Value; case 'f': case 't': { if (readType != ReadType.ReadAsString) { _charPos++; throw CreateUnexpectedCharacterException(c); } string text = ((c == 't') ? JsonConvert.True : JsonConvert.False); if (!MatchValueWithTrailingSeparator(text)) { throw CreateUnexpectedCharacterException(_chars[_charPos]); } SetToken(JsonToken.String, text); return text; } case 'I': return ParseNumberPositiveInfinity(readType); case 'N': return ParseNumberNaN(readType); case 'n': HandleNull(); return null; case '/': ParseComment(setToken: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: ReadFinished(); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private object? FinishReadQuotedStringValue(ReadType readType) { switch (readType) { case ReadType.ReadAsBytes: case ReadType.ReadAsString: return Value; case ReadType.ReadAsDateTime: if (Value is DateTime dateTime) { return dateTime; } return ReadDateTimeString((string)Value); case ReadType.ReadAsDateTimeOffset: if (Value is DateTimeOffset dateTimeOffset) { return dateTimeOffset; } return ReadDateTimeOffsetString((string)Value); default: throw new ArgumentOutOfRangeException("readType"); } } private JsonReaderException CreateUnexpectedCharacterException(char c) { return JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); } public override bool? ReadAsBoolean() { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (ParsePostValue(ignoreComments: true)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (ReadNullChar()) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': ParseString(c, ReadType.Read); return ReadBooleanString(_stringReference.ToString()); case 'n': HandleNull(); return null; case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { ParseNumber(ReadType.Read); bool flag2 = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L)); SetToken(JsonToken.Boolean, flag2, updateIndex: false); return flag2; } case 'f': case 't': { bool flag = c == 't'; string value = (flag ? JsonConvert.True : JsonConvert.False); if (!MatchValueWithTrailingSeparator(value)) { throw CreateUnexpectedCharacterException(_chars[_charPos]); } SetToken(JsonToken.Boolean, BoxedPrimitives.Get(flag)); return flag; } case '/': ParseComment(setToken: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: ReadFinished(); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private void ProcessValueComma() { _charPos++; if (_currentState != State.PostValue) { SetToken(JsonToken.Undefined); JsonReaderException ex = CreateUnexpectedCharacterException(','); _charPos--; throw ex; } SetStateBasedOnCurrent(); } private object? ReadNumberValue(ReadType readType) { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (ParsePostValue(ignoreComments: true)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (ReadNullChar()) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': ParseString(c, readType); return FinishReadQuotedNumber(readType); case 'n': HandleNull(); return null; case 'N': return ParseNumberNaN(readType); case 'I': return ParseNumberPositiveInfinity(readType); case '-': if (EnsureChars(1, append: true) && _chars[_charPos + 1] == 'I') { return ParseNumberNegativeInfinity(readType); } ParseNumber(readType); return Value; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ParseNumber(readType); return Value; case '/': ParseComment(setToken: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: ReadFinished(); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private object? FinishReadQuotedNumber(ReadType readType) { return readType switch { ReadType.ReadAsInt32 => ReadInt32String(_stringReference.ToString()), ReadType.ReadAsDecimal => ReadDecimalString(_stringReference.ToString()), ReadType.ReadAsDouble => ReadDoubleString(_stringReference.ToString()), _ => throw new ArgumentOutOfRangeException("readType"), }; } public override DateTimeOffset? ReadAsDateTimeOffset() { return (DateTimeOffset?)ReadStringValue(ReadType.ReadAsDateTimeOffset); } public override decimal? ReadAsDecimal() { return (decimal?)ReadNumberValue(ReadType.ReadAsDecimal); } public override double? ReadAsDouble() { return (double?)ReadNumberValue(ReadType.ReadAsDouble); } private void HandleNull() { if (EnsureChars(1, append: true)) { if (_chars[_charPos + 1] == 'u') { ParseNull(); return; } _charPos += 2; throw CreateUnexpectedCharacterException(_chars[_charPos - 1]); } _charPos = _charsUsed; throw CreateUnexpectedEndException(); } private void ReadFinished() { if (EnsureChars(0, append: false)) { EatWhitespace(); if (_isEndOfFile) { return; } if (_chars[_charPos] != '/') { throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } ParseComment(setToken: false); } SetToken(JsonToken.None); } private bool ReadNullChar() { if (_charsUsed == _charPos) { if (ReadData(append: false) == 0) { _isEndOfFile = true; return true; } } else { _charPos++; } return false; } private void EnsureBuffer() { if (_chars == null) { _chars = BufferUtils.RentBuffer(_arrayPool, 1024); _chars[0] = '\0'; } } private void ReadStringIntoBuffer(char quote) { int num = _charPos; int charPos = _charPos; int lastWritePosition = _charPos; _stringBuffer.Position = 0; while (true) { switch (_chars[num++]) { case '\0': if (_charsUsed == num - 1) { num--; if (ReadData(append: true) == 0) { _charPos = num; throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); } } break; case '\\': { _charPos = num; if (!EnsureChars(0, append: true)) { throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); } int writeToPosition = num - 1; char c = _chars[num]; num++; char c2; switch (c) { case 'b': c2 = '\b'; break; case 't': c2 = '\t'; break; case 'n': c2 = '\n'; break; case 'f': c2 = '\f'; break; case 'r': c2 = '\r'; break; case '\\': c2 = '\\'; break; case '"': case '\'': case '/': c2 = c; break; case 'u': _charPos = num; c2 = ParseUnicode(); if (StringUtils.IsLowSurrogate(c2)) { c2 = '\ufffd'; } else if (StringUtils.IsHighSurrogate(c2)) { bool flag; do { flag = false; if (EnsureChars(2, append: true) && _chars[_charPos] == '\\' && _chars[_charPos + 1] == 'u') { char writeChar = c2; _charPos += 2; c2 = ParseUnicode(); if (!StringUtils.IsLowSurrogate(c2)) { if (StringUtils.IsHighSurrogate(c2)) { writeChar = '\ufffd'; flag = true; } else { writeChar = '\ufffd'; } } EnsureBufferNotEmpty(); WriteCharToBuffer(writeChar, lastWritePosition, writeToPosition); lastWritePosition = _charPos; } else { c2 = '\ufffd'; } } while (flag); } num = _charPos; break; default: _charPos = num; throw JsonReaderException.Create(this, "Bad JSON escape sequence: {0}.".FormatWith(CultureInfo.InvariantCulture, "\\" + c)); } EnsureBufferNotEmpty(); WriteCharToBuffer(c2, lastWritePosition, writeToPosition); lastWritePosition = num; break; } case '\r': _charPos = num - 1; ProcessCarriageReturn(append: true); num = _charPos; break; case '\n': _charPos = num - 1; ProcessLineFeed(); num = _charPos; break; case '"': case '\'': if (_chars[num - 1] == quote) { FinishReadStringIntoBuffer(num - 1, charPos, lastWritePosition); return; } break; } } } private void FinishReadStringIntoBuffer(int charPos, int initialPosition, int lastWritePosition) { if (initialPosition == lastWritePosition) { _stringReference = new StringReference(_chars, initialPosition, charPos - initialPosition); } else { EnsureBufferNotEmpty(); if (charPos > lastWritePosition) { _stringBuffer.Append(_arrayPool, _chars, lastWritePosition, charPos - lastWritePosition); } _stringReference = new StringReference(_stringBuffer.InternalBuffer, 0, _stringBuffer.Position); } _charPos = charPos + 1; } private void WriteCharToBuffer(char writeChar, int lastWritePosition, int writeToPosition) { if (writeToPosition > lastWritePosition) { _stringBuffer.Append(_arrayPool, _chars, lastWritePosition, writeToPosition - lastWritePosition); } _stringBuffer.Append(_arrayPool, writeChar); } private char ConvertUnicode(bool enoughChars) { if (enoughChars) { if (ConvertUtils.TryHexTextToInt(_chars, _charPos, _charPos + 4, out var value)) { char result = Convert.ToChar(value); _charPos += 4; return result; } throw JsonReaderException.Create(this, "Invalid Unicode escape sequence: \\u{0}.".FormatWith(CultureInfo.InvariantCulture, new string(_chars, _charPos, 4))); } throw JsonReaderException.Create(this, "Unexpected end while parsing Unicode escape sequence."); } private char ParseUnicode() { return ConvertUnicode(EnsureChars(4, append: true)); } private void ReadNumberIntoBuffer() { int num = _charPos; while (true) { char c = _chars[num]; if (c == '\0') { _charPos = num; if (_charsUsed != num || ReadData(append: true) == 0) { break; } } else { if (ReadNumberCharIntoBuffer(c, num)) { break; } num++; } } } private bool ReadNumberCharIntoBuffer(char currentChar, int charPos) { switch (currentChar) { case '+': case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'X': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'x': return false; default: _charPos = charPos; if (char.IsWhiteSpace(currentChar) || currentChar == ',' || currentChar == '}' || currentChar == ']' || currentChar == ')' || currentChar == '/') { return true; } throw JsonReaderException.Create(this, "Unexpected character encountered while parsing number: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); } } private void ClearRecentString() { _stringBuffer.Position = 0; _stringReference = default(StringReference); } private bool ParsePostValue(bool ignoreComments) { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (ReadData(append: false) == 0) { _currentState = State.Finished; return false; } } else { _charPos++; } continue; case '}': _charPos++; SetToken(JsonToken.EndObject); return true; case ']': _charPos++; SetToken(JsonToken.EndArray); return true; case ')': _charPos++; SetToken(JsonToken.EndConstructor); return true; case '/': ParseComment(!ignoreComments); if (!ignoreComments) { return true; } continue; case ',': _charPos++; SetStateBasedOnCurrent(); return false; case '\t': case ' ': _charPos++; continue; case '\r': ProcessCarriageReturn(append: false); continue; case '\n': ProcessLineFeed(); continue; } if (char.IsWhiteSpace(c)) { _charPos++; continue; } if (base.SupportMultipleContent && Depth == 0) { SetStateBasedOnCurrent(); return false; } throw JsonReaderException.Create(this, "After parsing a value an unexpected character was encountered: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); } } private bool ParseObject() { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (ReadData(append: false) == 0) { return false; } } else { _charPos++; } break; case '}': SetToken(JsonToken.EndObject); _charPos++; return true; case '/': ParseComment(setToken: true); return true; case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: if (char.IsWhiteSpace(c)) { _charPos++; break; } return ParseProperty(); } } } private bool ParseProperty() { char c = _chars[_charPos]; char c2; if (c == '"' || c == '\'') { _charPos++; c2 = c; ShiftBufferIfNeeded(); ReadStringIntoBuffer(c2); } else { if (!ValidIdentifierChar(c)) { throw JsonReaderException.Create(this, "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } c2 = '\0'; ShiftBufferIfNeeded(); ParseUnquotedProperty(); } string text; if (PropertyNameTable != null) { text = PropertyNameTable.Get(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length); if (text == null) { text = _stringReference.ToString(); } } else { text = _stringReference.ToString(); } EatWhitespace(); if (_chars[_charPos] != ':') { throw JsonReaderException.Create(this, "Invalid character after parsing property name. Expected ':' but got: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } _charPos++; SetToken(JsonToken.PropertyName, text); _quoteChar = c2; ClearRecentString(); return true; } private bool ValidIdentifierChar(char value) { if (!char.IsLetterOrDigit(value) && value != '_') { return value == '$'; } return true; } private void ParseUnquotedProperty() { int charPos = _charPos; while (true) { char c = _chars[_charPos]; if (c == '\0') { if (_charsUsed != _charPos) { _stringReference = new StringReference(_chars, charPos, _charPos - charPos); break; } if (ReadData(append: true) == 0) { throw JsonReaderException.Create(this, "Unexpected end while parsing unquoted property name."); } } else if (ReadUnquotedPropertyReportIfDone(c, charPos)) { break; } } } private bool ReadUnquotedPropertyReportIfDone(char currentChar, int initialPosition) { if (ValidIdentifierChar(currentChar)) { _charPos++; return false; } if (char.IsWhiteSpace(currentChar) || currentChar == ':') { _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition); return true; } throw JsonReaderException.Create(this, "Invalid JavaScript property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); } private bool ParseValue() { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (ReadData(append: false) == 0) { return false; } } else { _charPos++; } break; case '"': case '\'': ParseString(c, ReadType.Read); return true; case 't': ParseTrue(); return true; case 'f': ParseFalse(); return true; case 'n': if (EnsureChars(1, append: true)) { switch (_chars[_charPos + 1]) { case 'u': ParseNull(); break; case 'e': ParseConstructor(); break; default: throw CreateUnexpectedCharacterException(_chars[_charPos]); } return true; } _charPos++; throw CreateUnexpectedEndException(); case 'N': ParseNumberNaN(ReadType.Read); return true; case 'I': ParseNumberPositiveInfinity(ReadType.Read); return true; case '-': if (EnsureChars(1, append: true) && _chars[_charPos + 1] == 'I') { ParseNumberNegativeInfinity(ReadType.Read); } else { ParseNumber(ReadType.Read); } return true; case '/': ParseComment(setToken: true); return true; case 'u': ParseUndefined(); return true; case '{': _charPos++; SetToken(JsonToken.StartObject); return true; case '[': _charPos++; SetToken(JsonToken.StartArray); return true; case ']': _charPos++; SetToken(JsonToken.EndArray); return true; case ',': SetToken(JsonToken.Undefined); return true; case ')': _charPos++; SetToken(JsonToken.EndConstructor); return true; case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: if (char.IsWhiteSpace(c)) { _charPos++; break; } if (char.IsNumber(c) || c == '-' || c == '.') { ParseNumber(ReadType.Read); return true; } throw CreateUnexpectedCharacterException(c); } } } private void ProcessLineFeed() { _charPos++; OnNewLine(_charPos); } private void ProcessCarriageReturn(bool append) { _charPos++; SetNewLine(EnsureChars(1, append)); } private void EatWhitespace() { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (ReadData(append: false) == 0) { return; } } else { _charPos++; } break; case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; default: if (!char.IsWhiteSpace(c)) { return; } goto case ' '; case ' ': _charPos++; break; } } } private void ParseConstructor() { if (MatchValueWithTrailingSeparator("new")) { EatWhitespace(); int charPos = _charPos; int charPos2; while (true) { char c = _chars[_charPos]; if (c == '\0') { if (_charsUsed == _charPos) { if (ReadData(append: true) == 0) { throw JsonReaderException.Create(this, "Unexpected end while parsing constructor."); } continue; } charPos2 = _charPos; _charPos++; break; } if (char.IsLetterOrDigit(c)) { _charPos++; continue; } switch (c) { case '\r': charPos2 = _charPos; ProcessCarriageReturn(append: true); break; case '\n': charPos2 = _charPos; ProcessLineFeed(); break; default: if (char.IsWhiteSpace(c)) { charPos2 = _charPos; _charPos++; break; } if (c == '(') { charPos2 = _charPos; break; } throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); } break; } _stringReference = new StringReference(_chars, charPos, charPos2 - charPos); string value = _stringReference.ToString(); EatWhitespace(); if (_chars[_charPos] != '(') { throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } _charPos++; ClearRecentString(); SetToken(JsonToken.StartConstructor, value); return; } throw JsonReaderException.Create(this, "Unexpected content while parsing JSON."); } private void ParseNumber(ReadType readType) { ShiftBufferIfNeeded(); char firstChar = _chars[_charPos]; int charPos = _charPos; ReadNumberIntoBuffer(); ParseReadNumber(readType, firstChar, charPos); } private void ParseReadNumber(ReadType readType, char firstChar, int initialPosition) { SetPostValueState(updateIndex: true); _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition); bool flag = char.IsDigit(firstChar) && _stringReference.Length == 1; bool flag2 = firstChar == '0' && _stringReference.Length > 1 && _stringReference.Chars[_stringReference.StartIndex + 1] != '.' && _stringReference.Chars[_stringReference.StartIndex + 1] != 'e' && _stringReference.Chars[_stringReference.StartIndex + 1] != 'E'; JsonToken newToken; object value; switch (readType) { case ReadType.ReadAsString: { string text5 = _stringReference.ToString(); double result3; if (flag2) { try { if (text5.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { Convert.ToInt64(text5, 16); } else { Convert.ToInt64(text5, 8); } } catch (Exception ex4) { throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, text5), ex4); } } else if (!double.TryParse(text5, NumberStyles.Float, CultureInfo.InvariantCulture, out result3)) { throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } newToken = JsonToken.String; value = text5; break; } case ReadType.ReadAsInt32: if (flag) { value = BoxedPrimitives.Get(firstChar - 48); } else if (flag2) { string text6 = _stringReference.ToString(); try { value = BoxedPrimitives.Get(text6.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt32(text6, 16) : Convert.ToInt32(text6, 8)); } catch (Exception ex5) { throw ThrowReaderError("Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, text6), ex5); } } else { int value5; switch (ConvertUtils.Int32TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value5)) { case ParseResult.Success: break; case ParseResult.Overflow: throw ThrowReaderError("JSON integer {0} is too large or small for an Int32.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); default: throw ThrowReaderError("Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BoxedPrimitives.Get(value5); } newToken = JsonToken.Integer; break; case ReadType.ReadAsDecimal: if (flag) { value = BoxedPrimitives.Get((decimal)firstChar - 48m); } else if (flag2) { string text3 = _stringReference.ToString(); try { value = BoxedPrimitives.Get(Convert.ToDecimal(text3.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(text3, 16) : Convert.ToInt64(text3, 8))); } catch (Exception ex2) { throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, text3), ex2); } } else { if (ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out var value4) != ParseResult.Success) { throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BoxedPrimitives.Get(value4); } newToken = JsonToken.Float; break; case ReadType.ReadAsDouble: if (flag) { value = BoxedPrimitives.Get((double)(int)firstChar - 48.0); } else if (flag2) { string text4 = _stringReference.ToString(); try { value = BoxedPrimitives.Get(Convert.ToDouble(text4.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(text4, 16) : Convert.ToInt64(text4, 8))); } catch (Exception ex3) { throw ThrowReaderError("Input string '{0}' is not a valid double.".FormatWith(CultureInfo.InvariantCulture, text4), ex3); } } else { if (!double.TryParse(_stringReference.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { throw ThrowReaderError("Input string '{0}' is not a valid double.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BoxedPrimitives.Get(result2); } newToken = JsonToken.Float; break; case ReadType.Read: case ReadType.ReadAsInt64: { if (flag) { value = BoxedPrimitives.Get((long)firstChar - 48L); newToken = JsonToken.Integer; break; } if (flag2) { string text = _stringReference.ToString(); try { value = BoxedPrimitives.Get(text.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(text, 16) : Convert.ToInt64(text, 8)); } catch (Exception ex) { throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, text), ex); } newToken = JsonToken.Integer; break; } long value2; switch (ConvertUtils.Int64TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value2)) { case ParseResult.Success: value = BoxedPrimitives.Get(value2); newToken = JsonToken.Integer; break; case ParseResult.Overflow: { string text2 = _stringReference.ToString(); if (text2.Length > 380) { throw ThrowReaderError("JSON integer {0} is too large to parse.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BigIntegerParse(text2, CultureInfo.InvariantCulture); newToken = JsonToken.Integer; break; } default: if (_floatParseHandling == FloatParseHandling.Decimal) { decimal value3; ParseResult parseResult = ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value3); if (parseResult != ParseResult.Success) { throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BoxedPrimitives.Get(value3); } else { if (!double.TryParse(_stringReference.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BoxedPrimitives.Get(result); } newToken = JsonToken.Float; break; } break; } default: throw JsonReaderException.Create(this, "Cannot read number value as type."); } ClearRecentString(); SetToken(newToken, value, updateIndex: false); } private JsonReaderException ThrowReaderError(string message, Exception? ex = null) { SetToken(JsonToken.Undefined, null, updateIndex: false); return JsonReaderException.Create(this, message, ex); } [MethodImpl(MethodImplOptions.NoInlining)] private static object BigIntegerParse(string number, CultureInfo culture) { return BigInteger.Parse(number, culture); } private void ParseComment(bool setToken) { _charPos++; if (!EnsureChars(1, append: false)) { throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); } bool flag; if (_chars[_charPos] == '*') { flag = false; } else { if (_chars[_charPos] != '/') { throw JsonReaderException.Create(this, "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } flag = true; } _charPos++; int charPos = _charPos; while (true) { switch (_chars[_charPos]) { case '\0': if (_charsUsed == _charPos) { if (ReadData(append: true) == 0) { if (!flag) { throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); } EndComment(setToken, charPos, _charPos); return; } } else { _charPos++; } break; case '*': _charPos++; if (!flag && EnsureChars(0, append: true) && _chars[_charPos] == '/') { EndComment(setToken, charPos, _charPos - 1); _charPos++; return; } break; case '\r': if (flag) { EndComment(setToken, charPos, _charPos); return; } ProcessCarriageReturn(append: true); break; case '\n': if (flag) { EndComment(setToken, charPos, _charPos); return; } ProcessLineFeed(); break; default: _charPos++; break; } } } private void EndComment(bool setToken, int initialPosition, int endPosition) { if (setToken) { SetToken(JsonToken.Comment, new string(_chars, initialPosition, endPosition - initialPosition)); } } private bool MatchValue(string value) { return MatchValue(EnsureChars(value.Length - 1, append: true), value); } private bool MatchValue(bool enoughChars, string value) { if (!enoughChars) { _charPos = _charsUsed; throw CreateUnexpectedEndException(); } for (int i = 0; i < value.Length; i++) { if (_chars[_charPos + i] != value[i]) { _charPos += i; return false; } } _charPos += value.Length; return true; } private bool MatchValueWithTrailingSeparator(string value) { if (!MatchValue(value)) { return false; } if (!EnsureChars(0, append: false)) { return true; } if (!IsSeparator(_chars[_charPos])) { return _chars[_charPos] == '\0'; } return true; } private bool IsSeparator(char c) { switch (c) { case ',': case ']': case '}': return true; case '/': { if (!EnsureChars(1, append: false)) { return false; } char c2 = _chars[_charPos + 1]; if (c2 != '*') { return c2 == '/'; } return true; } case ')': if (base.CurrentState == State.Constructor || base.CurrentState == State.ConstructorStart) { return true; } break; case '\t': case '\n': case '\r': case ' ': return true; default: if (char.IsWhiteSpace(c)) { return true; } break; } return false; } private void ParseTrue() { if (MatchValueWithTrailingSeparator(JsonConvert.True)) { SetToken(JsonToken.Boolean, BoxedPrimitives.BooleanTrue); return; } throw JsonReaderException.Create(this, "Error parsing boolean value."); } private void ParseNull() { if (MatchValueWithTrailingSeparator(JsonConvert.Null)) { SetToken(JsonToken.Null); return; } throw JsonReaderException.Create(this, "Error parsing null value."); } private void ParseUndefined() { if (MatchValueWithTrailingSeparator(JsonConvert.Undefined)) { SetToken(JsonToken.Undefined); return; } throw JsonReaderException.Create(this, "Error parsing undefined value."); } private void ParseFalse() { if (MatchValueWithTrailingSeparator(JsonConvert.False)) { SetToken(JsonToken.Boolean, BoxedPrimitives.BooleanFalse); return; } throw JsonReaderException.Create(this, "Error parsing boolean value."); } private object ParseNumberNegativeInfinity(ReadType readType) { return ParseNumberNegativeInfinity(readType, MatchValueWithTrailingSeparator(JsonConvert.NegativeInfinity)); } private object ParseNumberNegativeInfinity(ReadType readType, bool matched) { if (matched) { switch (readType) { case ReadType.Read: case ReadType.ReadAsDouble: if (_floatParseHandling == FloatParseHandling.Double) { SetToken(JsonToken.Float, BoxedPrimitives.DoubleNegativeInfinity); return double.NegativeInfinity; } break; case ReadType.ReadAsString: SetToken(JsonToken.String, JsonConvert.NegativeInfinity); return JsonConvert.NegativeInfinity; } throw JsonReaderException.Create(this, "Cannot read -Infinity value."); } throw JsonReaderException.Create(this, "Error parsing -Infinity value."); } private object ParseNumberPositiveInfinity(ReadType readType) { return ParseNumberPositiveInfinity(readType, MatchValueWithTrailingSeparator(JsonConvert.PositiveInfinity)); } private object ParseNumberPositiveInfinity(ReadType readType, bool matched) { if (matched) { switch (readType) { case ReadType.Read: case ReadType.ReadAsDouble: if (_floatParseHandling == FloatParseHandling.Double) { SetToken(JsonToken.Float, BoxedPrimitives.DoublePositiveInfinity); return double.PositiveInfinity; } break; case ReadType.ReadAsString: SetToken(JsonToken.String, JsonConvert.PositiveInfinity); return JsonConvert.PositiveInfinity; } throw JsonReaderException.Create(this, "Cannot read Infinity value."); } throw JsonReaderException.Create(this, "Error parsing Infinity value."); } private object ParseNumberNaN(ReadType readType) { return ParseNumberNaN(readType, MatchValueWithTrailingSeparator(JsonConvert.NaN)); } private object ParseNumberNaN(ReadType readType, bool matched) { if (matched) { switch (readType) { case ReadType.Read: case ReadType.ReadAsDouble: if (_floatParseHandling == FloatParseHandling.Double) { SetToken(JsonToken.Float, BoxedPrimitives.DoubleNaN); return double.NaN; } break; case ReadType.ReadAsString: SetToken(JsonToken.String, JsonConvert.NaN); return JsonConvert.NaN; } throw JsonReaderException.Create(this, "Cannot read NaN value."); } throw JsonReaderException.Create(this, "Error parsing NaN value."); } public override void Close() { base.Close(); if (_chars != null) { BufferUtils.ReturnBuffer(_arrayPool, _chars); _chars = null; } if (base.CloseInput) { _reader?.Close(); } _stringBuffer.Clear(_arrayPool); } public bool HasLineInfo() { return true; } } internal enum ReadType { Read, ReadAsInt32, ReadAsInt64, ReadAsBytes, ReadAsString, ReadAsDecimal, ReadAsDateTime, ReadAsDateTimeOffset, ReadAsDouble, ReadAsBoolean } internal class JsonTextWriter : JsonWriter { private readonly bool _safeAsync; private const int IndentCharBufferSize = 12; private readonly TextWriter _writer; private Base64Encoder? _base64Encoder; private char _indentChar; private int _indentation; private char _quoteChar; private bool _quoteName; private bool[]? _charEscapeFlags; private char[]? _writeBuffer; private IArrayPool? _arrayPool; private char[]? _indentChars; private Base64Encoder Base64Encoder { get { if (_base64Encoder == null) { _base64Encoder = new Base64Encoder(_writer); } return _base64Encoder; } } public IArrayPool? ArrayPool { get { return _arrayPool; } set { if (value == null) { throw new ArgumentNullException("value"); } _arrayPool = value; } } public int Indentation { get { return _indentation; } set { if (value < 0) { throw new ArgumentException("Indentation value must be greater than 0."); } _indentation = value; } } public char QuoteChar { get { return _quoteChar; } set { if (value != '"' && value != '\'') { throw new ArgumentException("Invalid JavaScript string quote character. Valid quote characters are ' and \"."); } _quoteChar = value; UpdateCharEscapeFlags(); } } public char IndentChar { get { return _indentChar; } set { if (value != _indentChar) { _indentChar = value; _indentChars = null; } } } public bool QuoteName { get { return _quoteName; } set { _quoteName = value; } } public override Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.FlushAsync(cancellationToken); } return DoFlushAsync(cancellationToken); } internal Task DoFlushAsync(CancellationToken cancellationToken) { return cancellationToken.CancelIfRequestedAsync() ?? _writer.FlushAsync(); } protected override Task WriteValueDelimiterAsync(CancellationToken cancellationToken) { if (!_safeAsync) { return base.WriteValueDelimiterAsync(cancellationToken); } return DoWriteValueDelimiterAsync(cancellationToken); } internal Task DoWriteValueDelimiterAsync(CancellationToken cancellationToken) { return _writer.WriteAsync(',', cancellationToken); } protected override Task WriteEndAsync(JsonToken token, CancellationToken cancellationToken) { if (!_safeAsync) { return base.WriteEndAsync(token, cancellationToken); } return DoWriteEndAsync(token, cancellationToken); } internal Task DoWriteEndAsync(JsonToken token, CancellationToken cancellationToken) { return token switch { JsonToken.EndObject => _writer.WriteAsync('}', cancellationToken), JsonToken.EndArray => _writer.WriteAsync(']', cancellationToken), JsonToken.EndConstructor => _writer.WriteAsync(')', cancellationToken), _ => throw JsonWriterException.Create(this, "Invalid JsonToken: " + token, null), }; } public override Task CloseAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.CloseAsync(cancellationToken); } return DoCloseAsync(cancellationToken); } internal async Task DoCloseAsync(CancellationToken cancellationToken) { if (base.Top == 0) { cancellationToken.ThrowIfCancellationRequested(); } while (base.Top > 0) { await WriteEndAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await CloseBufferAndWriterAsync().ConfigureAwait(continueOnCapturedContext: false); } private async Task CloseBufferAndWriterAsync() { if (_writeBuffer != null) { BufferUtils.ReturnBuffer(_arrayPool, _writeBuffer); _writeBuffer = null; } if (base.CloseOutput && _writer != null) { await _writer.DisposeAsync().ConfigureAwait(continueOnCapturedContext: false); } } public override Task WriteEndAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteEndAsync(cancellationToken); } return WriteEndInternalAsync(cancellationToken); } protected override Task WriteIndentAsync(CancellationToken cancellationToken) { if (!_safeAsync) { return base.WriteIndentAsync(cancellationToken); } return DoWriteIndentAsync(cancellationToken); } internal Task DoWriteIndentAsync(CancellationToken cancellationToken) { int num = base.Top * _indentation; int num2 = SetIndentChars(); if (num <= 12) { return _writer.WriteAsync(_indentChars, 0, num2 + num, cancellationToken); } return WriteIndentAsync(num, num2, cancellationToken); } private async Task WriteIndentAsync(int currentIndentCount, int newLineLen, CancellationToken cancellationToken) { await _writer.WriteAsync(_indentChars, 0, newLineLen + Math.Min(currentIndentCount, 12), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); while (true) { int num; currentIndentCount = (num = currentIndentCount - 12); if (num <= 0) { break; } await _writer.WriteAsync(_indentChars, newLineLen, Math.Min(currentIndentCount, 12), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } private Task WriteValueInternalAsync(JsonToken token, string value, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(token, cancellationToken); if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync(value, cancellationToken); } return WriteValueInternalAsync(task, value, cancellationToken); } private async Task WriteValueInternalAsync(Task task, string value, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(value, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } protected override Task WriteIndentSpaceAsync(CancellationToken cancellationToken) { if (!_safeAsync) { return base.WriteIndentSpaceAsync(cancellationToken); } return DoWriteIndentSpaceAsync(cancellationToken); } internal Task DoWriteIndentSpaceAsync(CancellationToken cancellationToken) { return _writer.WriteAsync(' ', cancellationToken); } public override Task WriteRawAsync(string? json, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteRawAsync(json, cancellationToken); } return DoWriteRawAsync(json, cancellationToken); } internal Task DoWriteRawAsync(string? json, CancellationToken cancellationToken) { return _writer.WriteAsync(json, cancellationToken); } public override Task WriteNullAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteNullAsync(cancellationToken); } return DoWriteNullAsync(cancellationToken); } internal Task DoWriteNullAsync(CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Null, JsonConvert.Null, cancellationToken); } private Task WriteDigitsAsync(ulong uvalue, bool negative, CancellationToken cancellationToken) { if (uvalue <= 9 && !negative) { return _writer.WriteAsync((char)(48 + uvalue), cancellationToken); } int count = WriteNumberToBuffer(uvalue, negative); return _writer.WriteAsync(_writeBuffer, 0, count, cancellationToken); } private Task WriteIntegerValueAsync(ulong uvalue, bool negative, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.Integer, cancellationToken); if (task.IsCompletedSuccessfully()) { return WriteDigitsAsync(uvalue, negative, cancellationToken); } return WriteIntegerValueAsync(task, uvalue, negative, cancellationToken); } private async Task WriteIntegerValueAsync(Task task, ulong uvalue, bool negative, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteDigitsAsync(uvalue, negative, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } internal Task WriteIntegerValueAsync(long value, CancellationToken cancellationToken) { bool flag = value < 0; if (flag) { value = -value; } return WriteIntegerValueAsync((ulong)value, flag, cancellationToken); } internal Task WriteIntegerValueAsync(ulong uvalue, CancellationToken cancellationToken) { return WriteIntegerValueAsync(uvalue, negative: false, cancellationToken); } private Task WriteEscapedStringAsync(string value, bool quote, CancellationToken cancellationToken) { return JavaScriptUtils.WriteEscapedJavaScriptStringAsync(_writer, value, _quoteChar, quote, _charEscapeFlags, base.StringEscapeHandling, this, _writeBuffer, cancellationToken); } public override Task WritePropertyNameAsync(string name, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WritePropertyNameAsync(name, cancellationToken); } return DoWritePropertyNameAsync(name, cancellationToken); } internal Task DoWritePropertyNameAsync(string name, CancellationToken cancellationToken) { Task task = InternalWritePropertyNameAsync(name, cancellationToken); if (!task.IsCompletedSuccessfully()) { return DoWritePropertyNameAsync(task, name, cancellationToken); } task = WriteEscapedStringAsync(name, _quoteName, cancellationToken); if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync(':', cancellationToken); } return JavaScriptUtils.WriteCharAsync(task, _writer, ':', cancellationToken); } private async Task DoWritePropertyNameAsync(Task task, string name, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteEscapedStringAsync(name, _quoteName, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(':').ConfigureAwait(continueOnCapturedContext: false); } public override Task WritePropertyNameAsync(string name, bool escape, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WritePropertyNameAsync(name, escape, cancellationToken); } return DoWritePropertyNameAsync(name, escape, cancellationToken); } internal async Task DoWritePropertyNameAsync(string name, bool escape, CancellationToken cancellationToken) { await InternalWritePropertyNameAsync(name, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (escape) { await WriteEscapedStringAsync(name, _quoteName, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { if (_quoteName) { await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } await _writer.WriteAsync(name, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (_quoteName) { await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } } await _writer.WriteAsync(':').ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteStartArrayAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteStartArrayAsync(cancellationToken); } return DoWriteStartArrayAsync(cancellationToken); } internal Task DoWriteStartArrayAsync(CancellationToken cancellationToken) { Task task = InternalWriteStartAsync(JsonToken.StartArray, JsonContainerType.Array, cancellationToken); if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync('[', cancellationToken); } return DoWriteStartArrayAsync(task, cancellationToken); } internal async Task DoWriteStartArrayAsync(Task task, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync('[', cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteStartObjectAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteStartObjectAsync(cancellationToken); } return DoWriteStartObjectAsync(cancellationToken); } internal Task DoWriteStartObjectAsync(CancellationToken cancellationToken) { Task task = InternalWriteStartAsync(JsonToken.StartObject, JsonContainerType.Object, cancellationToken); if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync('{', cancellationToken); } return DoWriteStartObjectAsync(task, cancellationToken); } internal async Task DoWriteStartObjectAsync(Task task, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync('{', cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteStartConstructorAsync(string name, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteStartConstructorAsync(name, cancellationToken); } return DoWriteStartConstructorAsync(name, cancellationToken); } internal async Task DoWriteStartConstructorAsync(string name, CancellationToken cancellationToken) { await InternalWriteStartAsync(JsonToken.StartConstructor, JsonContainerType.Constructor, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync("new ", cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(name, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync('(').ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteUndefinedAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteUndefinedAsync(cancellationToken); } return DoWriteUndefinedAsync(cancellationToken); } internal Task DoWriteUndefinedAsync(CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.Undefined, cancellationToken); if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync(JsonConvert.Undefined, cancellationToken); } return DoWriteUndefinedAsync(task, cancellationToken); } private async Task DoWriteUndefinedAsync(Task task, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(JsonConvert.Undefined, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteWhitespaceAsync(string ws, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteWhitespaceAsync(ws, cancellationToken); } return DoWriteWhitespaceAsync(ws, cancellationToken); } internal Task DoWriteWhitespaceAsync(string ws, CancellationToken cancellationToken) { InternalWriteWhitespace(ws); return _writer.WriteAsync(ws, cancellationToken); } public override Task WriteValueAsync(bool value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(bool value, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Boolean, JsonConvert.ToString(value), cancellationToken); } public override Task WriteValueAsync(bool? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(bool? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(byte value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } public override Task WriteValueAsync(byte? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(byte? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } if (value != null) { return WriteValueNonNullAsync(value, cancellationToken); } return WriteNullAsync(cancellationToken); } internal async Task WriteValueNonNullAsync(byte[] value, CancellationToken cancellationToken) { await InternalWriteValueAsync(JsonToken.Bytes, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); await Base64Encoder.EncodeAsync(value, 0, value.Length, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await Base64Encoder.FlushAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteValueAsync(char value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(char value, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.String, JsonConvert.ToString(value), cancellationToken); } public override Task WriteValueAsync(char? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(char? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(DateTime value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal async Task DoWriteValueAsync(DateTime value, CancellationToken cancellationToken) { await InternalWriteValueAsync(JsonToken.Date, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); value = DateTimeUtils.EnsureDateTime(value, base.DateTimeZoneHandling); if (StringUtils.IsNullOrEmpty(base.DateFormatString)) { int count = WriteValueToBuffer(value); await _writer.WriteAsync(_writeBuffer, 0, count, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(value.ToString(base.DateFormatString, base.Culture), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } } public override Task WriteValueAsync(DateTime? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(DateTime? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(DateTimeOffset value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal async Task DoWriteValueAsync(DateTimeOffset value, CancellationToken cancellationToken) { await InternalWriteValueAsync(JsonToken.Date, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (StringUtils.IsNullOrEmpty(base.DateFormatString)) { int count = WriteValueToBuffer(value); await _writer.WriteAsync(_writeBuffer, 0, count, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(value.ToString(base.DateFormatString, base.Culture), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } } public override Task WriteValueAsync(DateTimeOffset? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(DateTimeOffset? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(decimal value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(decimal value, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Float, JsonConvert.ToString(value), cancellationToken); } public override Task WriteValueAsync(decimal? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(decimal? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(double value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteValueAsync(value, nullable: false, cancellationToken); } internal Task WriteValueAsync(double value, bool nullable, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Float, JsonConvert.ToString(value, base.FloatFormatHandling, QuoteChar, nullable), cancellationToken); } public override Task WriteValueAsync(double? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } if (!value.HasValue) { return WriteNullAsync(cancellationToken); } return WriteValueAsync(value.GetValueOrDefault(), nullable: true, cancellationToken); } public override Task WriteValueAsync(float value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteValueAsync(value, nullable: false, cancellationToken); } internal Task WriteValueAsync(float value, bool nullable, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Float, JsonConvert.ToString(value, base.FloatFormatHandling, QuoteChar, nullable), cancellationToken); } public override Task WriteValueAsync(float? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } if (!value.HasValue) { return WriteNullAsync(cancellationToken); } return WriteValueAsync(value.GetValueOrDefault(), nullable: true, cancellationToken); } public override Task WriteValueAsync(Guid value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal async Task DoWriteValueAsync(Guid value, CancellationToken cancellationToken) { await InternalWriteValueAsync(JsonToken.String, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(value.ToString("D", CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteValueAsync(Guid? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(Guid? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(int value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } public override Task WriteValueAsync(int? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(int? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(long value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } public override Task WriteValueAsync(long? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(long? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } internal Task WriteValueAsync(BigInteger value, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Integer, value.ToString(CultureInfo.InvariantCulture), cancellationToken); } public override Task WriteValueAsync(object? value, CancellationToken cancellationToken = default(CancellationToken)) { if (_safeAsync) { if (value == null) { return WriteNullAsync(cancellationToken); } if (value is BigInteger value2) { return WriteValueAsync(value2, cancellationToken); } return JsonWriter.WriteValueAsync(this, ConvertUtils.GetTypeCode(value.GetType()), value, cancellationToken); } return base.WriteValueAsync(value, cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(sbyte value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(sbyte? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(sbyte? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(short value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } public override Task WriteValueAsync(short? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(short? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(string? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(string? value, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken); if (task.IsCompletedSuccessfully()) { if (value != null) { return WriteEscapedStringAsync(value, quote: true, cancellationToken); } return _writer.WriteAsync(JsonConvert.Null, cancellationToken); } return DoWriteValueAsync(task, value, cancellationToken); } private async Task DoWriteValueAsync(Task task, string? value, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await ((value == null) ? _writer.WriteAsync(JsonConvert.Null, cancellationToken) : WriteEscapedStringAsync(value, quote: true, cancellationToken)).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteValueAsync(TimeSpan value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal async Task DoWriteValueAsync(TimeSpan value, CancellationToken cancellationToken) { await InternalWriteValueAsync(JsonToken.String, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(value.ToString(null, CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteValueAsync(TimeSpan? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(TimeSpan? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(uint value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(uint? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(uint? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(ulong value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(ulong? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(ulong? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } if (!(value == null)) { return WriteValueNotNullAsync(value, cancellationToken); } return WriteNullAsync(cancellationToken); } internal Task WriteValueNotNullAsync(Uri value, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken); if (task.IsCompletedSuccessfully()) { return WriteEscapedStringAsync(value.OriginalString, quote: true, cancellationToken); } return WriteValueNotNullAsync(task, value, cancellationToken); } internal async Task WriteValueNotNullAsync(Task task, Uri value, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteEscapedStringAsync(value.OriginalString, quote: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } [CLSCompliant(false)] public override Task WriteValueAsync(ushort value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(ushort? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(ushort? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteCommentAsync(text, cancellationToken); } return DoWriteCommentAsync(text, cancellationToken); } internal async Task DoWriteCommentAsync(string? text, CancellationToken cancellationToken) { await InternalWriteCommentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync("/*", cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(text ?? string.Empty, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync("*/", cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteEndArrayAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteEndArrayAsync(cancellationToken); } return InternalWriteEndAsync(JsonContainerType.Array, cancellationToken); } public override Task WriteEndConstructorAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteEndConstructorAsync(cancellationToken); } return InternalWriteEndAsync(JsonContainerType.Constructor, cancellationToken); } public override Task WriteEndObjectAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteEndObjectAsync(cancellationToken); } return InternalWriteEndAsync(JsonContainerType.Object, cancellationToken); } public override Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteRawValueAsync(json, cancellationToken); } return DoWriteRawValueAsync(json, cancellationToken); } internal Task DoWriteRawValueAsync(string? json, CancellationToken cancellationToken) { UpdateScopeWithFinishedValue(); Task task = AutoCompleteAsync(JsonToken.Undefined, cancellationToken); if (task.IsCompletedSuccessfully()) { return WriteRawAsync(json, cancellationToken); } return DoWriteRawValueAsync(task, json, cancellationToken); } private async Task DoWriteRawValueAsync(Task task, string? json, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteRawAsync(json, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } internal char[] EnsureWriteBuffer(int length, int copyTo) { if (length < 35) { length = 35; } char[] writeBuffer = _writeBuffer; if (writeBuffer == null) { return _writeBuffer = BufferUtils.RentBuffer(_arrayPool, length); } if (writeBuffer.Length >= length) { return writeBuffer; } char[] array = BufferUtils.RentBuffer(_arrayPool, length); if (copyTo != 0) { Array.Copy(writeBuffer, array, copyTo); } BufferUtils.ReturnBuffer(_arrayPool, writeBuffer); _writeBuffer = array; return array; } public JsonTextWriter(TextWriter textWriter) { if (textWriter == null) { throw new ArgumentNullException("textWriter"); } _writer = textWriter; _quoteChar = '"'; _quoteName = true; _indentChar = ' '; _indentation = 2; UpdateCharEscapeFlags(); _safeAsync = GetType() == typeof(JsonTextWriter); } public override void Flush() { _writer.Flush(); } public override void Close() { base.Close(); CloseBufferAndWriter(); } private void CloseBufferAndWriter() { if (_writeBuffer != null) { BufferUtils.ReturnBuffer(_arrayPool, _writeBuffer); _writeBuffer = null; } if (base.CloseOutput) { _writer?.Close(); } } public override void WriteStartObject() { InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object); _writer.Write('{'); } public override void WriteStartArray() { InternalWriteStart(JsonToken.StartArray, JsonContainerType.Array); _writer.Write('['); } public override void WriteStartConstructor(string name) { InternalWriteStart(JsonToken.StartConstructor, JsonContainerType.Constructor); _writer.Write("new "); _writer.Write(name); _writer.Write('('); } protected override void WriteEnd(JsonToken token) { switch (token) { case JsonToken.EndObject: _writer.Write('}'); break; case JsonToken.EndArray: _writer.Write(']'); break; case JsonToken.EndConstructor: _writer.Write(')'); break; default: throw JsonWriterException.Create(this, "Invalid JsonToken: " + token, null); } } public override void WritePropertyName(string name) { InternalWritePropertyName(name); WriteEscapedString(name, _quoteName); _writer.Write(':'); } public override void WritePropertyName(string name, bool escape) { InternalWritePropertyName(name); if (escape) { WriteEscapedString(name, _quoteName); } else { if (_quoteName) { _writer.Write(_quoteChar); } _writer.Write(name); if (_quoteName) { _writer.Write(_quoteChar); } } _writer.Write(':'); } internal override void OnStringEscapeHandlingChanged() { UpdateCharEscapeFlags(); } private void UpdateCharEscapeFlags() { _charEscapeFlags = JavaScriptUtils.GetCharEscapeFlags(base.StringEscapeHandling, _quoteChar); } protected override void WriteIndent() { int num = base.Top * _indentation; int num2 = SetIndentChars(); _writer.Write(_indentChars, 0, num2 + Math.Min(num, 12)); while ((num -= 12) > 0) { _writer.Write(_indentChars, num2, Math.Min(num, 12)); } } private int SetIndentChars() { string newLine = _writer.NewLine; int length = newLine.Length; bool flag = _indentChars != null && _indentChars.Length == 12 + length; if (flag) { for (int i = 0; i != length; i++) { if (newLine[i] != _indentChars[i]) { flag = false; break; } } } if (!flag) { _indentChars = (newLine + new string(_indentChar, 12)).ToCharArray(); } return length; } protected override void WriteValueDelimiter() { _writer.Write(','); } protected override void WriteIndentSpace() { _writer.Write(' '); } private void WriteValueInternal(string value, JsonToken token) { _writer.Write(value); } public override void WriteValue(object? value) { if (value is BigInteger bigInteger) { InternalWriteValue(JsonToken.Integer); WriteValueInternal(bigInteger.ToString(CultureInfo.InvariantCulture), JsonToken.String); } else { base.WriteValue(value); } } public override void WriteNull() { InternalWriteValue(JsonToken.Null); WriteValueInternal(JsonConvert.Null, JsonToken.Null); } public override void WriteUndefined() { InternalWriteValue(JsonToken.Undefined); WriteValueInternal(JsonConvert.Undefined, JsonToken.Undefined); } public override void WriteRaw(string? json) { InternalWriteRaw(); _writer.Write(json); } public override void WriteValue(string? value) { InternalWriteValue(JsonToken.String); if (value == null) { WriteValueInternal(JsonConvert.Null, JsonToken.Null); } else { WriteEscapedString(value, quote: true); } } private void WriteEscapedString(string value, bool quote) { EnsureWriteBuffer(); JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, quote, _charEscapeFlags, base.StringEscapeHandling, _arrayPool, ref _writeBuffer); } public override void WriteValue(int value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } [CLSCompliant(false)] public override void WriteValue(uint value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } public override void WriteValue(long value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } [CLSCompliant(false)] public override void WriteValue(ulong value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value, negative: false); } public override void WriteValue(float value) { InternalWriteValue(JsonToken.Float); WriteValueInternal(JsonConvert.ToString(value, base.FloatFormatHandling, QuoteChar, nullable: false), JsonToken.Float); } public override void WriteValue(float? value) { if (!value.HasValue) { WriteNull(); return; } InternalWriteValue(JsonToken.Float); WriteValueInternal(JsonConvert.ToString(value.GetValueOrDefault(), base.FloatFormatHandling, QuoteChar, nullable: true), JsonToken.Float); } public override void WriteValue(double value) { InternalWriteValue(JsonToken.Float); WriteValueInternal(JsonConvert.ToString(value, base.FloatFormatHandling, QuoteChar, nullable: false), JsonToken.Float); } public override void WriteValue(double? value) { if (!value.HasValue) { WriteNull(); return; } InternalWriteValue(JsonToken.Float); WriteValueInternal(JsonConvert.ToString(value.GetValueOrDefault(), base.FloatFormatHandling, QuoteChar, nullable: true), JsonToken.Float); } public override void WriteValue(bool value) { InternalWriteValue(JsonToken.Boolean); WriteValueInternal(JsonConvert.ToString(value), JsonToken.Boolean); } public override void WriteValue(short value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } [CLSCompliant(false)] public override void WriteValue(ushort value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } public override void WriteValue(char value) { InternalWriteValue(JsonToken.String); WriteValueInternal(JsonConvert.ToString(value), JsonToken.String); } public override void WriteValue(byte value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } [CLSCompliant(false)] public override void WriteValue(sbyte value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } public override void WriteValue(decimal value) { InternalWriteValue(JsonToken.Float); WriteValueInternal(JsonConvert.ToString(value), JsonToken.Float); } public override void WriteValue(DateTime value) { InternalWriteValue(JsonToken.Date); value = DateTimeUtils.EnsureDateTime(value, base.DateTimeZoneHandling); if (StringUtils.IsNullOrEmpty(base.DateFormatString)) { int count = WriteValueToBuffer(value); _writer.Write(_writeBuffer, 0, count); } else { _writer.Write(_quoteChar); _writer.Write(value.ToString(base.DateFormatString, base.Culture)); _writer.Write(_quoteChar); } } private int WriteValueToBuffer(DateTime value) { EnsureWriteBuffer(); int start = 0; _writeBuffer[start++] = _quoteChar; start = DateTimeUtils.WriteDateTimeString(_writeBuffer, start, value, null, value.Kind, base.DateFormatHandling); _writeBuffer[start++] = _quoteChar; return start; } public override void WriteValue(byte[]? value) { if (value == null) { WriteNull(); return; } InternalWriteValue(JsonToken.Bytes); _writer.Write(_quoteChar); Base64Encoder.Encode(value, 0, value.Length); Base64Encoder.Flush(); _writer.Write(_quoteChar); } public override void WriteValue(DateTimeOffset value) { InternalWriteValue(JsonToken.Date); if (StringUtils.IsNullOrEmpty(base.DateFormatString)) { int count = WriteValueToBuffer(value); _writer.Write(_writeBuffer, 0, count); } else { _writer.Write(_quoteChar); _writer.Write(value.ToString(base.DateFormatString, base.Culture)); _writer.Write(_quoteChar); } } private int WriteValueToBuffer(DateTimeOffset value) { EnsureWriteBuffer(); int start = 0; _writeBuffer[start++] = _quoteChar; start = DateTimeUtils.WriteDateTimeString(_writeBuffer, start, (base.DateFormatHandling == DateFormatHandling.IsoDateFormat) ? value.DateTime : value.UtcDateTime, value.Offset, DateTimeKind.Local, base.DateFormatHandling); _writeBuffer[start++] = _quoteChar; return start; } public override void WriteValue(Guid value) { InternalWriteValue(JsonToken.String); string value2 = value.ToString("D", CultureInfo.InvariantCulture); _writer.Write(_quoteChar); _writer.Write(value2); _writer.Write(_quoteChar); } public override void WriteValue(TimeSpan value) { InternalWriteValue(JsonToken.String); string value2 = value.ToString(null, CultureInfo.InvariantCulture); _writer.Write(_quoteChar); _writer.Write(value2); _writer.Write(_quoteChar); } public override void WriteValue(Uri? value) { if (value == null) { WriteNull(); return; } InternalWriteValue(JsonToken.String); WriteEscapedString(value.OriginalString, quote: true); } public override void WriteComment(string? text) { InternalWriteComment(); _writer.Write("/*"); _writer.Write(text); _writer.Write("*/"); } public override void WriteWhitespace(string ws) { InternalWriteWhitespace(ws); _writer.Write(ws); } private void EnsureWriteBuffer() { if (_writeBuffer == null) { _writeBuffer = BufferUtils.RentBuffer(_arrayPool, 35); } } private void WriteIntegerValue(long value) { if (value >= 0 && value <= 9) { _writer.Write((char)(48 + value)); return; } bool flag = value < 0; WriteIntegerValue((ulong)(flag ? (-value) : value), flag); } private void WriteIntegerValue(ulong value, bool negative) { if (!negative && value <= 9) { _writer.Write((char)(48 + value)); return; } int count = WriteNumberToBuffer(value, negative); _writer.Write(_writeBuffer, 0, count); } private int WriteNumberToBuffer(ulong value, bool negative) { if (value <= uint.MaxValue) { return WriteNumberToBuffer((uint)value, negative); } EnsureWriteBuffer(); int num = MathUtils.IntLength(value); if (negative) { num++; _writeBuffer[0] = '-'; } int num2 = num; do { ulong num3 = value / 10; ulong num4 = value - num3 * 10; _writeBuffer[--num2] = (char)(48 + num4); value = num3; } while (value != 0L); return num; } private void WriteIntegerValue(int value) { if (value >= 0 && value <= 9) { _writer.Write((char)(48 + value)); return; } bool flag = value < 0; WriteIntegerValue((uint)(flag ? (-value) : value), flag); } private void WriteIntegerValue(uint value, bool negative) { if (!negative && value <= 9) { _writer.Write((char)(48 + value)); return; } int count = WriteNumberToBuffer(value, negative); _writer.Write(_writeBuffer, 0, count); } private int WriteNumberToBuffer(uint value, bool negative) { EnsureWriteBuffer(); int num = MathUtils.IntLength(value); if (negative) { num++; _writeBuffer[0] = '-'; } int num2 = num; do { uint num3 = value / 10; uint num4 = value - num3 * 10; _writeBuffer[--num2] = (char)(48 + num4); value = num3; } while (value != 0); return num; } } internal enum JsonToken { None, StartObject, StartArray, StartConstructor, PropertyName, Comment, Raw, Integer, Float, String, Boolean, Null, Undefined, EndObject, EndArray, EndConstructor, Date, Bytes } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonValidatingReader : JsonReader, IJsonLineInfo { private class SchemaScope { private readonly JTokenType _tokenType; private readonly IList _schemas; private readonly Dictionary _requiredProperties; public string CurrentPropertyName { get; set; } public int ArrayItemCount { get; set; } public bool IsUniqueArray { get; } public IList UniqueArrayItems { get; } public JTokenWriter CurrentItemWriter { get; set; } public IList Schemas => _schemas; public Dictionary RequiredProperties => _requiredProperties; public JTokenType TokenType => _tokenType; public SchemaScope(JTokenType tokenType, IList schemas) { _tokenType = tokenType; _schemas = schemas; _requiredProperties = schemas.SelectMany(GetRequiredProperties).Distinct().ToDictionary((string p) => p, (string p) => false); if (tokenType == JTokenType.Array && schemas.Any((JsonSchemaModel s) => s.UniqueItems)) { IsUniqueArray = true; UniqueArrayItems = new List(); } } private IEnumerable GetRequiredProperties(JsonSchemaModel schema) { if (schema?.Properties == null) { return Enumerable.Empty(); } return from p in schema.Properties where p.Value.Required select p.Key; } } private readonly JsonReader _reader; private readonly Stack _stack; private JsonSchema _schema; private JsonSchemaModel _model; private SchemaScope _currentScope; private static readonly IList EmptySchemaList = new List(); public override object Value => _reader.Value; public override int Depth => _reader.Depth; public override string Path => _reader.Path; public override char QuoteChar { get { return _reader.QuoteChar; } protected internal set { } } public override JsonToken TokenType => _reader.TokenType; public override Type ValueType => _reader.ValueType; private IList CurrentSchemas => _currentScope.Schemas; private IList CurrentMemberSchemas { get { if (_currentScope == null) { return new List(new JsonSchemaModel[1] { _model }); } if (_currentScope.Schemas == null || _currentScope.Schemas.Count == 0) { return EmptySchemaList; } switch (_currentScope.TokenType) { case JTokenType.None: return _currentScope.Schemas; case JTokenType.Object: { if (_currentScope.CurrentPropertyName == null) { throw new JsonReaderException("CurrentPropertyName has not been set on scope."); } IList list2 = new List(); { foreach (JsonSchemaModel currentSchema in CurrentSchemas) { if (currentSchema.Properties != null && currentSchema.Properties.TryGetValue(_currentScope.CurrentPropertyName, out var value)) { list2.Add(value); } if (currentSchema.PatternProperties != null) { foreach (KeyValuePair patternProperty in currentSchema.PatternProperties) { if (Regex.IsMatch(_currentScope.CurrentPropertyName, patternProperty.Key)) { list2.Add(patternProperty.Value); } } } if (list2.Count == 0 && currentSchema.AllowAdditionalProperties && currentSchema.AdditionalProperties != null) { list2.Add(currentSchema.AdditionalProperties); } } return list2; } } case JTokenType.Array: { IList list = new List(); { foreach (JsonSchemaModel currentSchema2 in CurrentSchemas) { if (!currentSchema2.PositionalItemsValidation) { if (currentSchema2.Items != null && currentSchema2.Items.Count > 0) { list.Add(currentSchema2.Items[0]); } continue; } if (currentSchema2.Items != null && currentSchema2.Items.Count > 0 && currentSchema2.Items.Count > _currentScope.ArrayItemCount - 1) { list.Add(currentSchema2.Items[_currentScope.ArrayItemCount - 1]); } if (currentSchema2.AllowAdditionalItems && currentSchema2.AdditionalItems != null) { list.Add(currentSchema2.AdditionalItems); } } return list; } } case JTokenType.Constructor: return EmptySchemaList; default: throw new ArgumentOutOfRangeException("TokenType", "Unexpected token type: {0}".FormatWith(CultureInfo.InvariantCulture, _currentScope.TokenType)); } } } public JsonSchema Schema { get { return _schema; } set { if (TokenType != 0) { throw new InvalidOperationException("Cannot change schema while validating JSON."); } _schema = value; _model = null; } } public JsonReader Reader => _reader; int IJsonLineInfo.LineNumber { get { if (!(_reader is IJsonLineInfo jsonLineInfo)) { return 0; } return jsonLineInfo.LineNumber; } } int IJsonLineInfo.LinePosition { get { if (!(_reader is IJsonLineInfo jsonLineInfo)) { return 0; } return jsonLineInfo.LinePosition; } } public event ValidationEventHandler ValidationEventHandler; private void Push(SchemaScope scope) { _stack.Push(scope); _currentScope = scope; } private SchemaScope Pop() { SchemaScope result = _stack.Pop(); _currentScope = ((_stack.Count != 0) ? _stack.Peek() : null); return result; } private void RaiseError(string message, JsonSchemaModel schema) { string message2 = (((IJsonLineInfo)this).HasLineInfo() ? (message + " Line {0}, position {1}.".FormatWith(CultureInfo.InvariantCulture, ((IJsonLineInfo)this).LineNumber, ((IJsonLineInfo)this).LinePosition)) : message); OnValidationEvent(new JsonSchemaException(message2, null, Path, ((IJsonLineInfo)this).LineNumber, ((IJsonLineInfo)this).LinePosition)); } private void OnValidationEvent(JsonSchemaException exception) { ValidationEventHandler validationEventHandler = this.ValidationEventHandler; if (validationEventHandler != null) { validationEventHandler(this, new ValidationEventArgs(exception)); return; } throw exception; } public JsonValidatingReader(JsonReader reader) { ValidationUtils.ArgumentNotNull(reader, "reader"); _reader = reader; _stack = new Stack(); } public override void Close() { base.Close(); if (base.CloseInput) { _reader?.Close(); } } private void ValidateNotDisallowed(JsonSchemaModel schema) { if (schema != null) { JsonSchemaType? currentNodeSchemaType = GetCurrentNodeSchemaType(); if (currentNodeSchemaType.HasValue && JsonSchemaGenerator.HasFlag(schema.Disallow, currentNodeSchemaType.GetValueOrDefault())) { RaiseError("Type {0} is disallowed.".FormatWith(CultureInfo.InvariantCulture, currentNodeSchemaType), schema); } } } private JsonSchemaType? GetCurrentNodeSchemaType() { return _reader.TokenType switch { JsonToken.StartObject => JsonSchemaType.Object, JsonToken.StartArray => JsonSchemaType.Array, JsonToken.Integer => JsonSchemaType.Integer, JsonToken.Float => JsonSchemaType.Float, JsonToken.String => JsonSchemaType.String, JsonToken.Boolean => JsonSchemaType.Boolean, JsonToken.Null => JsonSchemaType.Null, _ => null, }; } public override int? ReadAsInt32() { int? result = _reader.ReadAsInt32(); ValidateCurrentToken(); return result; } public override byte[] ReadAsBytes() { byte[]? result = _reader.ReadAsBytes(); ValidateCurrentToken(); return result; } public override decimal? ReadAsDecimal() { decimal? result = _reader.ReadAsDecimal(); ValidateCurrentToken(); return result; } public override double? ReadAsDouble() { double? result = _reader.ReadAsDouble(); ValidateCurrentToken(); return result; } public override bool? ReadAsBoolean() { bool? result = _reader.ReadAsBoolean(); ValidateCurrentToken(); return result; } public override string ReadAsString() { string? result = _reader.ReadAsString(); ValidateCurrentToken(); return result; } public override DateTime? ReadAsDateTime() { DateTime? result = _reader.ReadAsDateTime(); ValidateCurrentToken(); return result; } public override DateTimeOffset? ReadAsDateTimeOffset() { DateTimeOffset? result = _reader.ReadAsDateTimeOffset(); ValidateCurrentToken(); return result; } public override bool Read() { if (!_reader.Read()) { return false; } if (_reader.TokenType == JsonToken.Comment) { return true; } ValidateCurrentToken(); return true; } private void ValidateCurrentToken() { if (_model == null) { JsonSchemaModelBuilder jsonSchemaModelBuilder = new JsonSchemaModelBuilder(); _model = jsonSchemaModelBuilder.Build(_schema); if (!JsonTokenUtils.IsStartToken(_reader.TokenType)) { Push(new SchemaScope(JTokenType.None, CurrentMemberSchemas)); } } switch (_reader.TokenType) { case JsonToken.StartObject: { ProcessValue(); IList schemas2 = CurrentMemberSchemas.Where(ValidateObject).ToList(); Push(new SchemaScope(JTokenType.Object, schemas2)); WriteToken(CurrentSchemas); break; } case JsonToken.StartArray: { ProcessValue(); IList schemas = CurrentMemberSchemas.Where(ValidateArray).ToList(); Push(new SchemaScope(JTokenType.Array, schemas)); WriteToken(CurrentSchemas); break; } case JsonToken.StartConstructor: ProcessValue(); Push(new SchemaScope(JTokenType.Constructor, null)); WriteToken(CurrentSchemas); break; case JsonToken.PropertyName: WriteToken(CurrentSchemas); { foreach (JsonSchemaModel currentSchema in CurrentSchemas) { ValidatePropertyName(currentSchema); } break; } case JsonToken.Raw: ProcessValue(); break; case JsonToken.Integer: ProcessValue(); WriteToken(CurrentMemberSchemas); { foreach (JsonSchemaModel currentMemberSchema in CurrentMemberSchemas) { ValidateInteger(currentMemberSchema); } break; } case JsonToken.Float: ProcessValue(); WriteToken(CurrentMemberSchemas); { foreach (JsonSchemaModel currentMemberSchema2 in CurrentMemberSchemas) { ValidateFloat(currentMemberSchema2); } break; } case JsonToken.String: ProcessValue(); WriteToken(CurrentMemberSchemas); { foreach (JsonSchemaModel currentMemberSchema3 in CurrentMemberSchemas) { ValidateString(currentMemberSchema3); } break; } case JsonToken.Boolean: ProcessValue(); WriteToken(CurrentMemberSchemas); { foreach (JsonSchemaModel currentMemberSchema4 in CurrentMemberSchemas) { ValidateBoolean(currentMemberSchema4); } break; } case JsonToken.Null: ProcessValue(); WriteToken(CurrentMemberSchemas); { foreach (JsonSchemaModel currentMemberSchema5 in CurrentMemberSchemas) { ValidateNull(currentMemberSchema5); } break; } case JsonToken.EndObject: WriteToken(CurrentSchemas); foreach (JsonSchemaModel currentSchema2 in CurrentSchemas) { ValidateEndObject(currentSchema2); } Pop(); break; case JsonToken.EndArray: WriteToken(CurrentSchemas); foreach (JsonSchemaModel currentSchema3 in CurrentSchemas) { ValidateEndArray(currentSchema3); } Pop(); break; case JsonToken.EndConstructor: WriteToken(CurrentSchemas); Pop(); break; case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: WriteToken(CurrentMemberSchemas); break; default: throw new ArgumentOutOfRangeException(); case JsonToken.None: break; } } private void WriteToken(IList schemas) { foreach (SchemaScope item in _stack) { bool flag = item.TokenType == JTokenType.Array && item.IsUniqueArray && item.ArrayItemCount > 0; if (!flag && !schemas.Any((JsonSchemaModel s) => s.Enum != null)) { continue; } if (item.CurrentItemWriter == null) { if (JsonTokenUtils.IsEndToken(_reader.TokenType)) { continue; } item.CurrentItemWriter = new JTokenWriter(); } item.CurrentItemWriter.WriteToken(_reader, writeChildren: false); if (item.CurrentItemWriter.Top != 0 || _reader.TokenType == JsonToken.PropertyName) { continue; } JToken token = item.CurrentItemWriter.Token; item.CurrentItemWriter = null; if (flag) { if (item.UniqueArrayItems.Contains(token, JToken.EqualityComparer)) { RaiseError("Non-unique array item at index {0}.".FormatWith(CultureInfo.InvariantCulture, item.ArrayItemCount - 1), item.Schemas.First((JsonSchemaModel s) => s.UniqueItems)); } item.UniqueArrayItems.Add(token); } else { if (!schemas.Any((JsonSchemaModel s) => s.Enum != null)) { continue; } foreach (JsonSchemaModel schema in schemas) { if (schema.Enum != null && !schema.Enum.ContainsValue(token, JToken.EqualityComparer)) { StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); token.WriteTo(new JsonTextWriter(stringWriter)); RaiseError("Value {0} is not defined in enum.".FormatWith(CultureInfo.InvariantCulture, stringWriter.ToString()), schema); } } } } } private void ValidateEndObject(JsonSchemaModel schema) { if (schema == null) { return; } Dictionary requiredProperties = _currentScope.RequiredProperties; if (requiredProperties != null && requiredProperties.Values.Any((bool v) => !v)) { IEnumerable values = from kv in requiredProperties where !kv.Value select kv.Key; RaiseError("Required properties are missing from object: {0}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", values)), schema); } } private void ValidateEndArray(JsonSchemaModel schema) { if (schema != null) { int arrayItemCount = _currentScope.ArrayItemCount; if (schema.MaximumItems.HasValue && arrayItemCount > schema.MaximumItems) { RaiseError("Array item count {0} exceeds maximum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, schema.MaximumItems), schema); } if (schema.MinimumItems.HasValue && arrayItemCount < schema.MinimumItems) { RaiseError("Array item count {0} is less than minimum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, schema.MinimumItems), schema); } } } private void ValidateNull(JsonSchemaModel schema) { if (schema != null && TestType(schema, JsonSchemaType.Null)) { ValidateNotDisallowed(schema); } } private void ValidateBoolean(JsonSchemaModel schema) { if (schema != null && TestType(schema, JsonSchemaType.Boolean)) { ValidateNotDisallowed(schema); } } private void ValidateString(JsonSchemaModel schema) { if (schema == null || !TestType(schema, JsonSchemaType.String)) { return; } ValidateNotDisallowed(schema); string text = _reader.Value.ToString(); if (schema.MaximumLength.HasValue && text.Length > schema.MaximumLength) { RaiseError("String '{0}' exceeds maximum length of {1}.".FormatWith(CultureInfo.InvariantCulture, text, schema.MaximumLength), schema); } if (schema.MinimumLength.HasValue && text.Length < schema.MinimumLength) { RaiseError("String '{0}' is less than minimum length of {1}.".FormatWith(CultureInfo.InvariantCulture, text, schema.MinimumLength), schema); } if (schema.Patterns == null) { return; } foreach (string pattern in schema.Patterns) { if (!Regex.IsMatch(text, pattern)) { RaiseError("String '{0}' does not match regex pattern '{1}'.".FormatWith(CultureInfo.InvariantCulture, text, pattern), schema); } } } private void ValidateInteger(JsonSchemaModel schema) { if (schema == null || !TestType(schema, JsonSchemaType.Integer)) { return; } ValidateNotDisallowed(schema); object value = _reader.Value; if (schema.Maximum.HasValue) { if (JValue.Compare(JTokenType.Integer, value, schema.Maximum) > 0) { RaiseError("Integer {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema); } if (schema.ExclusiveMaximum && JValue.Compare(JTokenType.Integer, value, schema.Maximum) == 0) { RaiseError("Integer {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema); } } if (schema.Minimum.HasValue) { if (JValue.Compare(JTokenType.Integer, value, schema.Minimum) < 0) { RaiseError("Integer {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema); } if (schema.ExclusiveMinimum && JValue.Compare(JTokenType.Integer, value, schema.Minimum) == 0) { RaiseError("Integer {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema); } } if (schema.DivisibleBy.HasValue && ((!(value is BigInteger bigInteger)) ? (!IsZero((double)Convert.ToInt64(value, CultureInfo.InvariantCulture) % schema.DivisibleBy.GetValueOrDefault())) : (Math.Abs(schema.DivisibleBy.Value - Math.Truncate(schema.DivisibleBy.Value)).Equals(0.0) ? (bigInteger % new BigInteger(schema.DivisibleBy.Value) != 0L) : (bigInteger != 0L)))) { RaiseError("Integer {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.DivisibleBy), schema); } } private void ProcessValue() { if (_currentScope == null || _currentScope.TokenType != JTokenType.Array) { return; } _currentScope.ArrayItemCount++; foreach (JsonSchemaModel currentSchema in CurrentSchemas) { if (currentSchema != null && currentSchema.PositionalItemsValidation && !currentSchema.AllowAdditionalItems && (currentSchema.Items == null || _currentScope.ArrayItemCount - 1 >= currentSchema.Items.Count)) { RaiseError("Index {0} has not been defined and the schema does not allow additional items.".FormatWith(CultureInfo.InvariantCulture, _currentScope.ArrayItemCount), currentSchema); } } } private void ValidateFloat(JsonSchemaModel schema) { if (schema == null || !TestType(schema, JsonSchemaType.Float)) { return; } ValidateNotDisallowed(schema); double num = Convert.ToDouble(_reader.Value, CultureInfo.InvariantCulture); if (schema.Maximum.HasValue) { if (num > schema.Maximum) { RaiseError("Float {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(num), schema.Maximum), schema); } if (schema.ExclusiveMaximum && num == schema.Maximum) { RaiseError("Float {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(num), schema.Maximum), schema); } } if (schema.Minimum.HasValue) { if (num < schema.Minimum) { RaiseError("Float {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(num), schema.Minimum), schema); } if (schema.ExclusiveMinimum && num == schema.Minimum) { RaiseError("Float {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(num), schema.Minimum), schema); } } if (schema.DivisibleBy.HasValue && !IsZero(FloatingPointRemainder(num, schema.DivisibleBy.GetValueOrDefault()))) { RaiseError("Float {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(num), schema.DivisibleBy), schema); } } private static double FloatingPointRemainder(double dividend, double divisor) { return dividend - Math.Floor(dividend / divisor) * divisor; } private static bool IsZero(double value) { return Math.Abs(value) < 4.440892098500626E-15; } private void ValidatePropertyName(JsonSchemaModel schema) { if (schema != null) { string text = Convert.ToString(_reader.Value, CultureInfo.InvariantCulture); if (_currentScope.RequiredProperties.ContainsKey(text)) { _currentScope.RequiredProperties[text] = true; } if (!schema.AllowAdditionalProperties && !IsPropertyDefinied(schema, text)) { RaiseError("Property '{0}' has not been defined and the schema does not allow additional properties.".FormatWith(CultureInfo.InvariantCulture, text), schema); } _currentScope.CurrentPropertyName = text; } } private bool IsPropertyDefinied(JsonSchemaModel schema, string propertyName) { if (schema.Properties != null && schema.Properties.ContainsKey(propertyName)) { return true; } if (schema.PatternProperties != null) { foreach (string key in schema.PatternProperties.Keys) { if (Regex.IsMatch(propertyName, key)) { return true; } } } return false; } private bool ValidateArray(JsonSchemaModel schema) { if (schema == null) { return true; } return TestType(schema, JsonSchemaType.Array); } private bool ValidateObject(JsonSchemaModel schema) { if (schema == null) { return true; } return TestType(schema, JsonSchemaType.Object); } private bool TestType(JsonSchemaModel currentSchema, JsonSchemaType currentType) { if (!JsonSchemaGenerator.HasFlag(currentSchema.Type, currentType)) { RaiseError("Invalid type. Expected {0} but got {1}.".FormatWith(CultureInfo.InvariantCulture, currentSchema.Type, currentType), currentSchema); return false; } return true; } bool IJsonLineInfo.HasLineInfo() { if (_reader is IJsonLineInfo jsonLineInfo) { return jsonLineInfo.HasLineInfo(); } return false; } } internal abstract class JsonWriter : IAsyncDisposable, IDisposable { internal enum State { Start, Property, ObjectStart, Object, ArrayStart, Array, ConstructorStart, Constructor, Closed, Error } private static readonly State[][] StateArray; internal static readonly State[][] StateArrayTemplate; private List? _stack; private JsonPosition _currentPosition; private State _currentState; private Formatting _formatting; private DateFormatHandling _dateFormatHandling; private DateTimeZoneHandling _dateTimeZoneHandling; private StringEscapeHandling _stringEscapeHandling; private FloatFormatHandling _floatFormatHandling; private string? _dateFormatString; private CultureInfo? _culture; public bool CloseOutput { get; set; } public bool AutoCompleteOnClose { get; set; } protected internal int Top { get { int num = _stack?.Count ?? 0; if (Peek() != 0) { num++; } return num; } } public WriteState WriteState { get { switch (_currentState) { case State.Error: return WriteState.Error; case State.Closed: return WriteState.Closed; case State.ObjectStart: case State.Object: return WriteState.Object; case State.ArrayStart: case State.Array: return WriteState.Array; case State.ConstructorStart: case State.Constructor: return WriteState.Constructor; case State.Property: return WriteState.Property; case State.Start: return WriteState.Start; default: throw JsonWriterException.Create(this, "Invalid state: " + _currentState, null); } } } internal string ContainerPath { get { if (_currentPosition.Type == JsonContainerType.None || _stack == null) { return string.Empty; } return JsonPosition.BuildPath(_stack, null); } } public string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public Formatting Formatting { get { return _formatting; } set { if (value < Formatting.None || value > Formatting.Indented) { throw new ArgumentOutOfRangeException("value"); } _formatting = value; } } public DateFormatHandling DateFormatHandling { get { return _dateFormatHandling; } set { if (value < DateFormatHandling.IsoDateFormat || value > DateFormatHandling.MicrosoftDateFormat) { throw new ArgumentOutOfRangeException("value"); } _dateFormatHandling = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling; } set { if (value < StringEscapeHandling.Default || value > StringEscapeHandling.EscapeHtml) { throw new ArgumentOutOfRangeException("value"); } _stringEscapeHandling = value; OnStringEscapeHandlingChanged(); } } public FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling; } set { if (value < FloatFormatHandling.String || value > FloatFormatHandling.DefaultValue) { throw new ArgumentOutOfRangeException("value"); } _floatFormatHandling = value; } } public string? DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } async ValueTask IAsyncDisposable.DisposeAsync() { if (_currentState != State.Closed) { await CloseAsync().ConfigureAwait(continueOnCapturedContext: false); } } internal Task AutoCompleteAsync(JsonToken tokenBeingWritten, CancellationToken cancellationToken) { State currentState = _currentState; State state = StateArray[(int)tokenBeingWritten][(int)currentState]; if (state == State.Error) { throw JsonWriterException.Create(this, "Token {0} in state {1} would result in an invalid JSON object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), currentState.ToString()), null); } _currentState = state; if (_formatting == Formatting.Indented) { switch (currentState) { case State.Property: return WriteIndentSpaceAsync(cancellationToken); case State.ArrayStart: case State.ConstructorStart: return WriteIndentAsync(cancellationToken); case State.Array: case State.Constructor: if (tokenBeingWritten != JsonToken.Comment) { return AutoCompleteAsync(cancellationToken); } return WriteIndentAsync(cancellationToken); case State.Object: switch (tokenBeingWritten) { case JsonToken.PropertyName: return AutoCompleteAsync(cancellationToken); default: return WriteValueDelimiterAsync(cancellationToken); case JsonToken.Comment: break; } break; default: if (tokenBeingWritten == JsonToken.PropertyName) { return WriteIndentAsync(cancellationToken); } break; case State.Start: break; } } else if (tokenBeingWritten != JsonToken.Comment) { switch (currentState) { case State.Object: case State.Array: case State.Constructor: return WriteValueDelimiterAsync(cancellationToken); } } return AsyncUtils.CompletedTask; } private async Task AutoCompleteAsync(CancellationToken cancellationToken) { await WriteValueDelimiterAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await WriteIndentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public virtual Task CloseAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } Close(); return AsyncUtils.CompletedTask; } public virtual Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } Flush(); return AsyncUtils.CompletedTask; } protected virtual Task WriteEndAsync(JsonToken token, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteEnd(token); return AsyncUtils.CompletedTask; } protected virtual Task WriteIndentAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteIndent(); return AsyncUtils.CompletedTask; } protected virtual Task WriteValueDelimiterAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValueDelimiter(); return AsyncUtils.CompletedTask; } protected virtual Task WriteIndentSpaceAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteIndentSpace(); return AsyncUtils.CompletedTask; } public virtual Task WriteRawAsync(string? json, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteRaw(json); return AsyncUtils.CompletedTask; } public virtual Task WriteEndAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteEnd(); return AsyncUtils.CompletedTask; } internal Task WriteEndInternalAsync(CancellationToken cancellationToken) { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: return WriteEndObjectAsync(cancellationToken); case JsonContainerType.Array: return WriteEndArrayAsync(cancellationToken); case JsonContainerType.Constructor: return WriteEndConstructorAsync(cancellationToken); default: if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } throw JsonWriterException.Create(this, "Unexpected type when writing end: " + jsonContainerType, null); } } internal Task InternalWriteEndAsync(JsonContainerType type, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } int levelsToComplete = CalculateLevelsToComplete(type); while (levelsToComplete-- > 0) { JsonToken closeTokenForType = GetCloseTokenForType(Pop()); Task task2; if (_currentState == State.Property) { task2 = WriteNullAsync(cancellationToken); if (!task2.IsCompletedSuccessfully()) { return AwaitProperty(task2, levelsToComplete, closeTokenForType, cancellationToken); } } if (_formatting == Formatting.Indented && _currentState != State.ObjectStart && _currentState != State.ArrayStart) { task2 = WriteIndentAsync(cancellationToken); if (!task2.IsCompletedSuccessfully()) { return AwaitIndent(task2, levelsToComplete, closeTokenForType, cancellationToken); } } task2 = WriteEndAsync(closeTokenForType, cancellationToken); if (!task2.IsCompletedSuccessfully()) { return AwaitEnd(task2, levelsToComplete, cancellationToken); } UpdateCurrentState(); } return AsyncUtils.CompletedTask; async Task AwaitEnd(Task task, int LevelsToComplete, CancellationToken CancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); UpdateCurrentState(); await AwaitRemaining(LevelsToComplete, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } async Task AwaitIndent(Task task, int LevelsToComplete, JsonToken token, CancellationToken CancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteEndAsync(token, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); UpdateCurrentState(); await AwaitRemaining(LevelsToComplete, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } async Task AwaitProperty(Task task, int LevelsToComplete, JsonToken token, CancellationToken CancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); if (_formatting == Formatting.Indented && _currentState != State.ObjectStart && _currentState != State.ArrayStart) { await WriteIndentAsync(CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await WriteEndAsync(token, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); UpdateCurrentState(); await AwaitRemaining(LevelsToComplete, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } async Task AwaitRemaining(int LevelsToComplete, CancellationToken CancellationToken) { while (LevelsToComplete-- > 0) { JsonToken token2 = GetCloseTokenForType(Pop()); if (_currentState == State.Property) { await WriteNullAsync(CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } if (_formatting == Formatting.Indented && _currentState != State.ObjectStart && _currentState != State.ArrayStart) { await WriteIndentAsync(CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await WriteEndAsync(token2, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); UpdateCurrentState(); } } } public virtual Task WriteEndArrayAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteEndArray(); return AsyncUtils.CompletedTask; } public virtual Task WriteEndConstructorAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteEndConstructor(); return AsyncUtils.CompletedTask; } public virtual Task WriteEndObjectAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteEndObject(); return AsyncUtils.CompletedTask; } public virtual Task WriteNullAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteNull(); return AsyncUtils.CompletedTask; } public virtual Task WritePropertyNameAsync(string name, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WritePropertyName(name); return AsyncUtils.CompletedTask; } public virtual Task WritePropertyNameAsync(string name, bool escape, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WritePropertyName(name, escape); return AsyncUtils.CompletedTask; } internal Task InternalWritePropertyNameAsync(string name, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } _currentPosition.PropertyName = name; return AutoCompleteAsync(JsonToken.PropertyName, cancellationToken); } public virtual Task WriteStartArrayAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteStartArray(); return AsyncUtils.CompletedTask; } internal async Task InternalWriteStartAsync(JsonToken token, JsonContainerType container, CancellationToken cancellationToken) { UpdateScopeWithFinishedValue(); await AutoCompleteAsync(token, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); Push(container); } public virtual Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteComment(text); return AsyncUtils.CompletedTask; } internal Task InternalWriteCommentAsync(CancellationToken cancellationToken) { return AutoCompleteAsync(JsonToken.Comment, cancellationToken); } public virtual Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteRawValue(json); return AsyncUtils.CompletedTask; } public virtual Task WriteStartConstructorAsync(string name, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteStartConstructor(name); return AsyncUtils.CompletedTask; } public virtual Task WriteStartObjectAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteStartObject(); return AsyncUtils.CompletedTask; } public Task WriteTokenAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return WriteTokenAsync(reader, writeChildren: true, cancellationToken); } public Task WriteTokenAsync(JsonReader reader, bool writeChildren, CancellationToken cancellationToken = default(CancellationToken)) { ValidationUtils.ArgumentNotNull(reader, "reader"); return WriteTokenAsync(reader, writeChildren, writeDateConstructorAsDate: true, writeComments: true, cancellationToken); } public Task WriteTokenAsync(JsonToken token, CancellationToken cancellationToken = default(CancellationToken)) { return WriteTokenAsync(token, null, cancellationToken); } public Task WriteTokenAsync(JsonToken token, object? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } switch (token) { case JsonToken.None: return AsyncUtils.CompletedTask; case JsonToken.StartObject: return WriteStartObjectAsync(cancellationToken); case JsonToken.StartArray: return WriteStartArrayAsync(cancellationToken); case JsonToken.StartConstructor: ValidationUtils.ArgumentNotNull(value, "value"); return WriteStartConstructorAsync(value.ToString(), cancellationToken); case JsonToken.PropertyName: ValidationUtils.ArgumentNotNull(value, "value"); return WritePropertyNameAsync(value.ToString(), cancellationToken); case JsonToken.Comment: return WriteCommentAsync(value?.ToString(), cancellationToken); case JsonToken.Integer: ValidationUtils.ArgumentNotNull(value, "value"); if (!(value is BigInteger bigInteger)) { return WriteValueAsync(Convert.ToInt64(value, CultureInfo.InvariantCulture), cancellationToken); } return WriteValueAsync(bigInteger, cancellationToken); case JsonToken.Float: ValidationUtils.ArgumentNotNull(value, "value"); if (value is decimal value4) { return WriteValueAsync(value4, cancellationToken); } if (value is double value5) { return WriteValueAsync(value5, cancellationToken); } if (value is float value6) { return WriteValueAsync(value6, cancellationToken); } return WriteValueAsync(Convert.ToDouble(value, CultureInfo.InvariantCulture), cancellationToken); case JsonToken.String: ValidationUtils.ArgumentNotNull(value, "value"); return WriteValueAsync(value.ToString(), cancellationToken); case JsonToken.Boolean: ValidationUtils.ArgumentNotNull(value, "value"); return WriteValueAsync(Convert.ToBoolean(value, CultureInfo.InvariantCulture), cancellationToken); case JsonToken.Null: return WriteNullAsync(cancellationToken); case JsonToken.Undefined: return WriteUndefinedAsync(cancellationToken); case JsonToken.EndObject: return WriteEndObjectAsync(cancellationToken); case JsonToken.EndArray: return WriteEndArrayAsync(cancellationToken); case JsonToken.EndConstructor: return WriteEndConstructorAsync(cancellationToken); case JsonToken.Date: ValidationUtils.ArgumentNotNull(value, "value"); if (value is DateTimeOffset value3) { return WriteValueAsync(value3, cancellationToken); } return WriteValueAsync(Convert.ToDateTime(value, CultureInfo.InvariantCulture), cancellationToken); case JsonToken.Raw: return WriteRawValueAsync(value?.ToString(), cancellationToken); case JsonToken.Bytes: ValidationUtils.ArgumentNotNull(value, "value"); if (value is Guid value2) { return WriteValueAsync(value2, cancellationToken); } return WriteValueAsync((byte[])value, cancellationToken); default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("token", token, "Unexpected token type."); } } internal virtual async Task WriteTokenAsync(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments, CancellationToken cancellationToken) { int initialDepth = CalculateWriteTokenInitialDepth(reader); bool flag; do { if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { await WriteConstructorDateAsync(reader, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else if (writeComments || reader.TokenType != JsonToken.Comment) { await WriteTokenAsync(reader.TokenType, reader.Value, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } flag = initialDepth - 1 < reader.Depth - (JsonTokenUtils.IsEndToken(reader.TokenType) ? 1 : 0) && writeChildren; if (flag) { flag = await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } while (flag); if (IsWriteTokenIncomplete(reader, writeChildren, initialDepth)) { throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); } } internal async Task WriteTokenSyncReadingAsync(JsonReader reader, CancellationToken cancellationToken) { int initialDepth = CalculateWriteTokenInitialDepth(reader); bool flag; do { if (reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { WriteConstructorDate(reader); } else { WriteToken(reader.TokenType, reader.Value); } flag = initialDepth - 1 < reader.Depth - (JsonTokenUtils.IsEndToken(reader.TokenType) ? 1 : 0); if (flag) { flag = await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } while (flag); if (initialDepth < CalculateWriteTokenFinalDepth(reader)) { throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); } } private async Task WriteConstructorDateAsync(JsonReader reader, CancellationToken cancellationToken) { if (!(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null); } if (reader.TokenType != JsonToken.Integer) { throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType, null); } DateTime date = DateTimeUtils.ConvertJavaScriptTicksToDateTime((long)reader.Value); if (!(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null); } if (reader.TokenType != JsonToken.EndConstructor) { throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected EndConstructor, got " + reader.TokenType, null); } await WriteValueAsync(date, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public virtual Task WriteValueAsync(bool value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(bool? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(byte value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(byte? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(char value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(char? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(DateTime value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(DateTime? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(DateTimeOffset value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(DateTimeOffset? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(decimal value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(decimal? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(double value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(double? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(float value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(float? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(Guid value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(Guid? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(int value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(int? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(long value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(long? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(object? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(sbyte value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(sbyte? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(short value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(short? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(string? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(TimeSpan value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(TimeSpan? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(uint value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(uint? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(ulong value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(ulong? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(ushort value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(ushort? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteUndefinedAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteUndefined(); return AsyncUtils.CompletedTask; } public virtual Task WriteWhitespaceAsync(string ws, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteWhitespace(ws); return AsyncUtils.CompletedTask; } internal Task InternalWriteValueAsync(JsonToken token, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } UpdateScopeWithFinishedValue(); return AutoCompleteAsync(token, cancellationToken); } protected Task SetWriteStateAsync(JsonToken token, object value, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } switch (token) { case JsonToken.StartObject: return InternalWriteStartAsync(token, JsonContainerType.Object, cancellationToken); case JsonToken.StartArray: return InternalWriteStartAsync(token, JsonContainerType.Array, cancellationToken); case JsonToken.StartConstructor: return InternalWriteStartAsync(token, JsonContainerType.Constructor, cancellationToken); case JsonToken.PropertyName: if (!(value is string name)) { throw new ArgumentException("A name is required when setting property name state.", "value"); } return InternalWritePropertyNameAsync(name, cancellationToken); case JsonToken.Comment: return InternalWriteCommentAsync(cancellationToken); case JsonToken.Raw: return AsyncUtils.CompletedTask; case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: return InternalWriteValueAsync(token, cancellationToken); case JsonToken.EndObject: return InternalWriteEndAsync(JsonContainerType.Object, cancellationToken); case JsonToken.EndArray: return InternalWriteEndAsync(JsonContainerType.Array, cancellationToken); case JsonToken.EndConstructor: return InternalWriteEndAsync(JsonContainerType.Constructor, cancellationToken); default: throw new ArgumentOutOfRangeException("token"); } } internal static Task WriteValueAsync(JsonWriter writer, PrimitiveTypeCode typeCode, object value, CancellationToken cancellationToken) { while (true) { switch (typeCode) { case PrimitiveTypeCode.Char: return writer.WriteValueAsync((char)value, cancellationToken); case PrimitiveTypeCode.CharNullable: return writer.WriteValueAsync((value == null) ? null : new char?((char)value), cancellationToken); case PrimitiveTypeCode.Boolean: return writer.WriteValueAsync((bool)value, cancellationToken); case PrimitiveTypeCode.BooleanNullable: return writer.WriteValueAsync((value == null) ? null : new bool?((bool)value), cancellationToken); case PrimitiveTypeCode.SByte: return writer.WriteValueAsync((sbyte)value, cancellationToken); case PrimitiveTypeCode.SByteNullable: return writer.WriteValueAsync((value == null) ? null : new sbyte?((sbyte)value), cancellationToken); case PrimitiveTypeCode.Int16: return writer.WriteValueAsync((short)value, cancellationToken); case PrimitiveTypeCode.Int16Nullable: return writer.WriteValueAsync((value == null) ? null : new short?((short)value), cancellationToken); case PrimitiveTypeCode.UInt16: return writer.WriteValueAsync((ushort)value, cancellationToken); case PrimitiveTypeCode.UInt16Nullable: return writer.WriteValueAsync((value == null) ? null : new ushort?((ushort)value), cancellationToken); case PrimitiveTypeCode.Int32: return writer.WriteValueAsync((int)value, cancellationToken); case PrimitiveTypeCode.Int32Nullable: return writer.WriteValueAsync((value == null) ? null : new int?((int)value), cancellationToken); case PrimitiveTypeCode.Byte: return writer.WriteValueAsync((byte)value, cancellationToken); case PrimitiveTypeCode.ByteNullable: return writer.WriteValueAsync((value == null) ? null : new byte?((byte)value), cancellationToken); case PrimitiveTypeCode.UInt32: return writer.WriteValueAsync((uint)value, cancellationToken); case PrimitiveTypeCode.UInt32Nullable: return writer.WriteValueAsync((value == null) ? null : new uint?((uint)value), cancellationToken); case PrimitiveTypeCode.Int64: return writer.WriteValueAsync((long)value, cancellationToken); case PrimitiveTypeCode.Int64Nullable: return writer.WriteValueAsync((value == null) ? null : new long?((long)value), cancellationToken); case PrimitiveTypeCode.UInt64: return writer.WriteValueAsync((ulong)value, cancellationToken); case PrimitiveTypeCode.UInt64Nullable: return writer.WriteValueAsync((value == null) ? null : new ulong?((ulong)value), cancellationToken); case PrimitiveTypeCode.Single: return writer.WriteValueAsync((float)value, cancellationToken); case PrimitiveTypeCode.SingleNullable: return writer.WriteValueAsync((value == null) ? null : new float?((float)value), cancellationToken); case PrimitiveTypeCode.Double: return writer.WriteValueAsync((double)value, cancellationToken); case PrimitiveTypeCode.DoubleNullable: return writer.WriteValueAsync((value == null) ? null : new double?((double)value), cancellationToken); case PrimitiveTypeCode.DateTime: return writer.WriteValueAsync((DateTime)value, cancellationToken); case PrimitiveTypeCode.DateTimeNullable: return writer.WriteValueAsync((value == null) ? null : new DateTime?((DateTime)value), cancellationToken); case PrimitiveTypeCode.DateTimeOffset: return writer.WriteValueAsync((DateTimeOffset)value, cancellationToken); case PrimitiveTypeCode.DateTimeOffsetNullable: return writer.WriteValueAsync((value == null) ? null : new DateTimeOffset?((DateTimeOffset)value), cancellationToken); case PrimitiveTypeCode.Decimal: return writer.WriteValueAsync((decimal)value, cancellationToken); case PrimitiveTypeCode.DecimalNullable: return writer.WriteValueAsync((value == null) ? null : new decimal?((decimal)value), cancellationToken); case PrimitiveTypeCode.Guid: return writer.WriteValueAsync((Guid)value, cancellationToken); case PrimitiveTypeCode.GuidNullable: return writer.WriteValueAsync((value == null) ? null : new Guid?((Guid)value), cancellationToken); case PrimitiveTypeCode.TimeSpan: return writer.WriteValueAsync((TimeSpan)value, cancellationToken); case PrimitiveTypeCode.TimeSpanNullable: return writer.WriteValueAsync((value == null) ? null : new TimeSpan?((TimeSpan)value), cancellationToken); case PrimitiveTypeCode.BigInteger: return writer.WriteValueAsync((BigInteger)value, cancellationToken); case PrimitiveTypeCode.BigIntegerNullable: return writer.WriteValueAsync((value == null) ? null : new BigInteger?((BigInteger)value), cancellationToken); case PrimitiveTypeCode.Uri: return writer.WriteValueAsync((Uri)value, cancellationToken); case PrimitiveTypeCode.String: return writer.WriteValueAsync((string)value, cancellationToken); case PrimitiveTypeCode.Bytes: return writer.WriteValueAsync((byte[])value, cancellationToken); case PrimitiveTypeCode.DBNull: return writer.WriteNullAsync(cancellationToken); } if (value is IConvertible convertible) { ResolveConvertibleValue(convertible, out typeCode, out value); continue; } if (value == null) { return writer.WriteNullAsync(cancellationToken); } throw CreateUnsupportedTypeException(writer, value); } } internal static State[][] BuildStateArray() { List list = StateArrayTemplate.ToList(); State[] item = StateArrayTemplate[0]; State[] item2 = StateArrayTemplate[7]; ulong[] values = EnumUtils.GetEnumValuesAndNames(typeof(JsonToken)).Values; foreach (ulong num in values) { if (list.Count <= (int)num) { JsonToken jsonToken = (JsonToken)num; if ((uint)(jsonToken - 7) <= 5u || (uint)(jsonToken - 16) <= 1u) { list.Add(item2); } else { list.Add(item); } } } return list.ToArray(); } static JsonWriter() { StateArrayTemplate = new State[8][] { new State[10] { State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error }, new State[10] { State.ObjectStart, State.ObjectStart, State.Error, State.Error, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.Error, State.Error }, new State[10] { State.ArrayStart, State.ArrayStart, State.Error, State.Error, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.Error, State.Error }, new State[10] { State.ConstructorStart, State.ConstructorStart, State.Error, State.Error, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.Error, State.Error }, new State[10] { State.Property, State.Error, State.Property, State.Property, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error }, new State[10] { State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error }, new State[10] { State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error }, new State[10] { State.Start, State.Object, State.Error, State.Error, State.Array, State.Array, State.Constructor, State.Constructor, State.Error, State.Error } }; StateArray = BuildStateArray(); } internal virtual void OnStringEscapeHandlingChanged() { } protected JsonWriter() { _currentState = State.Start; _formatting = Formatting.None; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; CloseOutput = true; AutoCompleteOnClose = true; } internal void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void Push(JsonContainerType value) { if (_currentPosition.Type != 0) { if (_stack == null) { _stack = new List(); } _stack.Add(_currentPosition); } _currentPosition = new JsonPosition(value); } private JsonContainerType Pop() { JsonPosition currentPosition = _currentPosition; if (_stack != null && _stack.Count > 0) { _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { _currentPosition = default(JsonPosition); } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract void Flush(); public virtual void Close() { if (AutoCompleteOnClose) { AutoCompleteAll(); } } public virtual void WriteStartObject() { InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object); } public virtual void WriteEndObject() { InternalWriteEnd(JsonContainerType.Object); } public virtual void WriteStartArray() { InternalWriteStart(JsonToken.StartArray, JsonContainerType.Array); } public virtual void WriteEndArray() { InternalWriteEnd(JsonContainerType.Array); } public virtual void WriteStartConstructor(string name) { InternalWriteStart(JsonToken.StartConstructor, JsonContainerType.Constructor); } public virtual void WriteEndConstructor() { InternalWriteEnd(JsonContainerType.Constructor); } public virtual void WritePropertyName(string name) { InternalWritePropertyName(name); } public virtual void WritePropertyName(string name, bool escape) { WritePropertyName(name); } public virtual void WriteEnd() { WriteEnd(Peek()); } public void WriteToken(JsonReader reader) { WriteToken(reader, writeChildren: true); } public void WriteToken(JsonReader reader, bool writeChildren) { ValidationUtils.ArgumentNotNull(reader, "reader"); WriteToken(reader, writeChildren, writeDateConstructorAsDate: true, writeComments: true); } public void WriteToken(JsonToken token, object? value) { switch (token) { case JsonToken.StartObject: WriteStartObject(); break; case JsonToken.StartArray: WriteStartArray(); break; case JsonToken.StartConstructor: ValidationUtils.ArgumentNotNull(value, "value"); WriteStartConstructor(value.ToString()); break; case JsonToken.PropertyName: ValidationUtils.ArgumentNotNull(value, "value"); WritePropertyName(value.ToString()); break; case JsonToken.Comment: WriteComment(value?.ToString()); break; case JsonToken.Integer: ValidationUtils.ArgumentNotNull(value, "value"); if (value is BigInteger bigInteger) { WriteValue(bigInteger); } else { WriteValue(Convert.ToInt64(value, CultureInfo.InvariantCulture)); } break; case JsonToken.Float: ValidationUtils.ArgumentNotNull(value, "value"); if (value is decimal value3) { WriteValue(value3); } else if (value is double value4) { WriteValue(value4); } else if (value is float value5) { WriteValue(value5); } else { WriteValue(Convert.ToDouble(value, CultureInfo.InvariantCulture)); } break; case JsonToken.String: WriteValue(value?.ToString()); break; case JsonToken.Boolean: ValidationUtils.ArgumentNotNull(value, "value"); WriteValue(Convert.ToBoolean(value, CultureInfo.InvariantCulture)); break; case JsonToken.Null: WriteNull(); break; case JsonToken.Undefined: WriteUndefined(); break; case JsonToken.EndObject: WriteEndObject(); break; case JsonToken.EndArray: WriteEndArray(); break; case JsonToken.EndConstructor: WriteEndConstructor(); break; case JsonToken.Date: ValidationUtils.ArgumentNotNull(value, "value"); if (value is DateTimeOffset value6) { WriteValue(value6); } else { WriteValue(Convert.ToDateTime(value, CultureInfo.InvariantCulture)); } break; case JsonToken.Raw: WriteRawValue(value?.ToString()); break; case JsonToken.Bytes: ValidationUtils.ArgumentNotNull(value, "value"); if (value is Guid value2) { WriteValue(value2); } else { WriteValue((byte[])value); } break; default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("token", token, "Unexpected token type."); case JsonToken.None: break; } } public void WriteToken(JsonToken token) { WriteToken(token, null); } internal virtual void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments) { int num = CalculateWriteTokenInitialDepth(reader); do { if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { WriteConstructorDate(reader); } else if (writeComments || reader.TokenType != JsonToken.Comment) { WriteToken(reader.TokenType, reader.Value); } } while (num - 1 < reader.Depth - (JsonTokenUtils.IsEndToken(reader.TokenType) ? 1 : 0) && writeChildren && reader.Read()); if (IsWriteTokenIncomplete(reader, writeChildren, num)) { throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); } } private bool IsWriteTokenIncomplete(JsonReader reader, bool writeChildren, int initialDepth) { int num = CalculateWriteTokenFinalDepth(reader); if (initialDepth >= num) { if (writeChildren && initialDepth == num) { return JsonTokenUtils.IsStartToken(reader.TokenType); } return false; } return true; } private int CalculateWriteTokenInitialDepth(JsonReader reader) { JsonToken tokenType = reader.TokenType; if (tokenType == JsonToken.None) { return -1; } if (!JsonTokenUtils.IsStartToken(tokenType)) { return reader.Depth + 1; } return reader.Depth; } private int CalculateWriteTokenFinalDepth(JsonReader reader) { JsonToken tokenType = reader.TokenType; if (tokenType == JsonToken.None) { return -1; } if (!JsonTokenUtils.IsEndToken(tokenType)) { return reader.Depth; } return reader.Depth - 1; } private void WriteConstructorDate(JsonReader reader) { if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime dateTime, out string errorMessage)) { throw JsonWriterException.Create(this, errorMessage, null); } WriteValue(dateTime); } private void WriteEnd(JsonContainerType type) { switch (type) { case JsonContainerType.Object: WriteEndObject(); break; case JsonContainerType.Array: WriteEndArray(); break; case JsonContainerType.Constructor: WriteEndConstructor(); break; default: throw JsonWriterException.Create(this, "Unexpected type when writing end: " + type, null); } } private void AutoCompleteAll() { while (Top > 0) { WriteEnd(); } } private JsonToken GetCloseTokenForType(JsonContainerType type) { return type switch { JsonContainerType.Object => JsonToken.EndObject, JsonContainerType.Array => JsonToken.EndArray, JsonContainerType.Constructor => JsonToken.EndConstructor, _ => throw JsonWriterException.Create(this, "No close token for type: " + type, null), }; } private void AutoCompleteClose(JsonContainerType type) { int num = CalculateLevelsToComplete(type); for (int i = 0; i < num; i++) { JsonToken closeTokenForType = GetCloseTokenForType(Pop()); if (_currentState == State.Property) { WriteNull(); } if (_formatting == Formatting.Indented && _currentState != State.ObjectStart && _currentState != State.ArrayStart) { WriteIndent(); } WriteEnd(closeTokenForType); UpdateCurrentState(); } } private int CalculateLevelsToComplete(JsonContainerType type) { int num = 0; if (_currentPosition.Type == type) { num = 1; } else { int num2 = Top - 2; for (int num3 = num2; num3 >= 0; num3--) { int index = num2 - num3; if (_stack[index].Type == type) { num = num3 + 2; break; } } } if (num == 0) { throw JsonWriterException.Create(this, "No token to close.", null); } return num; } private void UpdateCurrentState() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Array; break; case JsonContainerType.None: _currentState = State.Start; break; default: throw JsonWriterException.Create(this, "Unknown JsonType: " + jsonContainerType, null); } } protected virtual void WriteEnd(JsonToken token) { } protected virtual void WriteIndent() { } protected virtual void WriteValueDelimiter() { } protected virtual void WriteIndentSpace() { } internal void AutoComplete(JsonToken tokenBeingWritten) { State state = StateArray[(int)tokenBeingWritten][(int)_currentState]; if (state == State.Error) { throw JsonWriterException.Create(this, "Token {0} in state {1} would result in an invalid JSON object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), _currentState.ToString()), null); } if ((_currentState == State.Object || _currentState == State.Array || _currentState == State.Constructor) && tokenBeingWritten != JsonToken.Comment) { WriteValueDelimiter(); } if (_formatting == Formatting.Indented) { if (_currentState == State.Property) { WriteIndentSpace(); } if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.Constructor || _currentState == State.ConstructorStart || (tokenBeingWritten == JsonToken.PropertyName && _currentState != 0)) { WriteIndent(); } } _currentState = state; } public virtual void WriteNull() { InternalWriteValue(JsonToken.Null); } public virtual void WriteUndefined() { InternalWriteValue(JsonToken.Undefined); } public virtual void WriteRaw(string? json) { InternalWriteRaw(); } public virtual void WriteRawValue(string? json) { UpdateScopeWithFinishedValue(); AutoComplete(JsonToken.Undefined); WriteRaw(json); } public virtual void WriteValue(string? value) { InternalWriteValue(JsonToken.String); } public virtual void WriteValue(int value) { InternalWriteValue(JsonToken.Integer); } [CLSCompliant(false)] public virtual void WriteValue(uint value) { InternalWriteValue(JsonToken.Integer); } public virtual void WriteValue(long value) { InternalWriteValue(JsonToken.Integer); } [CLSCompliant(false)] public virtual void WriteValue(ulong value) { InternalWriteValue(JsonToken.Integer); } public virtual void WriteValue(float value) { InternalWriteValue(JsonToken.Float); } public virtual void WriteValue(double value) { InternalWriteValue(JsonToken.Float); } public virtual void WriteValue(bool value) { InternalWriteValue(JsonToken.Boolean); } public virtual void WriteValue(short value) { InternalWriteValue(JsonToken.Integer); } [CLSCompliant(false)] public virtual void WriteValue(ushort value) { InternalWriteValue(JsonToken.Integer); } public virtual void WriteValue(char value) { InternalWriteValue(JsonToken.String); } public virtual void WriteValue(byte value) { InternalWriteValue(JsonToken.Integer); } [CLSCompliant(false)] public virtual void WriteValue(sbyte value) { InternalWriteValue(JsonToken.Integer); } public virtual void WriteValue(decimal value) { InternalWriteValue(JsonToken.Float); } public virtual void WriteValue(DateTime value) { InternalWriteValue(JsonToken.Date); } public virtual void WriteValue(DateTimeOffset value) { InternalWriteValue(JsonToken.Date); } public virtual void WriteValue(Guid value) { InternalWriteValue(JsonToken.String); } public virtual void WriteValue(TimeSpan value) { InternalWriteValue(JsonToken.String); } public virtual void WriteValue(int? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } [CLSCompliant(false)] public virtual void WriteValue(uint? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(long? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } [CLSCompliant(false)] public virtual void WriteValue(ulong? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(float? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(double? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(bool? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(short? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } [CLSCompliant(false)] public virtual void WriteValue(ushort? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(char? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(byte? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } [CLSCompliant(false)] public virtual void WriteValue(sbyte? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(decimal? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(DateTime? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(DateTimeOffset? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(Guid? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(TimeSpan? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(byte[]? value) { if (value == null) { WriteNull(); } else { InternalWriteValue(JsonToken.Bytes); } } public virtual void WriteValue(Uri? value) { if (value == null) { WriteNull(); } else { InternalWriteValue(JsonToken.String); } } public virtual void WriteValue(object? value) { if (value == null) { WriteNull(); return; } if (value is BigInteger) { throw CreateUnsupportedTypeException(this, value); } WriteValue(this, ConvertUtils.GetTypeCode(value.GetType()), value); } public virtual void WriteComment(string? text) { InternalWriteComment(); } public virtual void WriteWhitespace(string ws) { InternalWriteWhitespace(ws); } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } internal static void WriteValue(JsonWriter writer, PrimitiveTypeCode typeCode, object value) { while (true) { switch (typeCode) { case PrimitiveTypeCode.Char: writer.WriteValue((char)value); return; case PrimitiveTypeCode.CharNullable: writer.WriteValue((value == null) ? null : new char?((char)value)); return; case PrimitiveTypeCode.Boolean: writer.WriteValue((bool)value); return; case PrimitiveTypeCode.BooleanNullable: writer.WriteValue((value == null) ? null : new bool?((bool)value)); return; case PrimitiveTypeCode.SByte: writer.WriteValue((sbyte)value); return; case PrimitiveTypeCode.SByteNullable: writer.WriteValue((value == null) ? null : new sbyte?((sbyte)value)); return; case PrimitiveTypeCode.Int16: writer.WriteValue((short)value); return; case PrimitiveTypeCode.Int16Nullable: writer.WriteValue((value == null) ? null : new short?((short)value)); return; case PrimitiveTypeCode.UInt16: writer.WriteValue((ushort)value); return; case PrimitiveTypeCode.UInt16Nullable: writer.WriteValue((value == null) ? null : new ushort?((ushort)value)); return; case PrimitiveTypeCode.Int32: writer.WriteValue((int)value); return; case PrimitiveTypeCode.Int32Nullable: writer.WriteValue((value == null) ? null : new int?((int)value)); return; case PrimitiveTypeCode.Byte: writer.WriteValue((byte)value); return; case PrimitiveTypeCode.ByteNullable: writer.WriteValue((value == null) ? null : new byte?((byte)value)); return; case PrimitiveTypeCode.UInt32: writer.WriteValue((uint)value); return; case PrimitiveTypeCode.UInt32Nullable: writer.WriteValue((value == null) ? null : new uint?((uint)value)); return; case PrimitiveTypeCode.Int64: writer.WriteValue((long)value); return; case PrimitiveTypeCode.Int64Nullable: writer.WriteValue((value == null) ? null : new long?((long)value)); return; case PrimitiveTypeCode.UInt64: writer.WriteValue((ulong)value); return; case PrimitiveTypeCode.UInt64Nullable: writer.WriteValue((value == null) ? null : new ulong?((ulong)value)); return; case PrimitiveTypeCode.Single: writer.WriteValue((float)value); return; case PrimitiveTypeCode.SingleNullable: writer.WriteValue((value == null) ? null : new float?((float)value)); return; case PrimitiveTypeCode.Double: writer.WriteValue((double)value); return; case PrimitiveTypeCode.DoubleNullable: writer.WriteValue((value == null) ? null : new double?((double)value)); return; case PrimitiveTypeCode.DateTime: writer.WriteValue((DateTime)value); return; case PrimitiveTypeCode.DateTimeNullable: writer.WriteValue((value == null) ? null : new DateTime?((DateTime)value)); return; case PrimitiveTypeCode.DateTimeOffset: writer.WriteValue((DateTimeOffset)value); return; case PrimitiveTypeCode.DateTimeOffsetNullable: writer.WriteValue((value == null) ? null : new DateTimeOffset?((DateTimeOffset)value)); return; case PrimitiveTypeCode.Decimal: writer.WriteValue((decimal)value); return; case PrimitiveTypeCode.DecimalNullable: writer.WriteValue((value == null) ? null : new decimal?((decimal)value)); return; case PrimitiveTypeCode.Guid: writer.WriteValue((Guid)value); return; case PrimitiveTypeCode.GuidNullable: writer.WriteValue((value == null) ? null : new Guid?((Guid)value)); return; case PrimitiveTypeCode.TimeSpan: writer.WriteValue((TimeSpan)value); return; case PrimitiveTypeCode.TimeSpanNullable: writer.WriteValue((value == null) ? null : new TimeSpan?((TimeSpan)value)); return; case PrimitiveTypeCode.BigInteger: writer.WriteValue((BigInteger)value); return; case PrimitiveTypeCode.BigIntegerNullable: writer.WriteValue((value == null) ? null : new BigInteger?((BigInteger)value)); return; case PrimitiveTypeCode.Uri: writer.WriteValue((Uri)value); return; case PrimitiveTypeCode.String: writer.WriteValue((string)value); return; case PrimitiveTypeCode.Bytes: writer.WriteValue((byte[])value); return; case PrimitiveTypeCode.DBNull: writer.WriteNull(); return; } if (value is IConvertible convertible) { ResolveConvertibleValue(convertible, out typeCode, out value); continue; } if (value == null) { writer.WriteNull(); return; } throw CreateUnsupportedTypeException(writer, value); } } private static void ResolveConvertibleValue(IConvertible convertible, out PrimitiveTypeCode typeCode, out object value) { TypeInformation typeInformation = ConvertUtils.GetTypeInformation(convertible); typeCode = ((typeInformation.TypeCode == PrimitiveTypeCode.Object) ? PrimitiveTypeCode.String : typeInformation.TypeCode); Type conversionType = ((typeInformation.TypeCode == PrimitiveTypeCode.Object) ? typeof(string) : typeInformation.Type); value = convertible.ToType(conversionType, CultureInfo.InvariantCulture); } private static JsonWriterException CreateUnsupportedTypeException(JsonWriter writer, object value) { return JsonWriterException.Create(writer, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); } protected void SetWriteState(JsonToken token, object value) { switch (token) { case JsonToken.StartObject: InternalWriteStart(token, JsonContainerType.Object); break; case JsonToken.StartArray: InternalWriteStart(token, JsonContainerType.Array); break; case JsonToken.StartConstructor: InternalWriteStart(token, JsonContainerType.Constructor); break; case JsonToken.PropertyName: if (!(value is string name)) { throw new ArgumentException("A name is required when setting property name state.", "value"); } InternalWritePropertyName(name); break; case JsonToken.Comment: InternalWriteComment(); break; case JsonToken.Raw: InternalWriteRaw(); break; case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: InternalWriteValue(token); break; case JsonToken.EndObject: InternalWriteEnd(JsonContainerType.Object); break; case JsonToken.EndArray: InternalWriteEnd(JsonContainerType.Array); break; case JsonToken.EndConstructor: InternalWriteEnd(JsonContainerType.Constructor); break; default: throw new ArgumentOutOfRangeException("token"); } } internal void InternalWriteEnd(JsonContainerType container) { AutoCompleteClose(container); } internal void InternalWritePropertyName(string name) { _currentPosition.PropertyName = name; AutoComplete(JsonToken.PropertyName); } internal void InternalWriteRaw() { } internal void InternalWriteStart(JsonToken token, JsonContainerType container) { UpdateScopeWithFinishedValue(); AutoComplete(token); Push(container); } internal void InternalWriteValue(JsonToken token) { UpdateScopeWithFinishedValue(); AutoComplete(token); } internal void InternalWriteWhitespace(string ws) { if (ws != null && !StringUtils.IsWhiteSpace(ws)) { throw JsonWriterException.Create(this, "Only white space characters should be used.", null); } } internal void InternalWriteComment() { AutoComplete(JsonToken.Comment); } } [Serializable] internal class JsonWriterException : JsonException { public string? Path { get; } public JsonWriterException() { } public JsonWriterException(string message) : base(message) { } public JsonWriterException(string message, Exception innerException) : base(message, innerException) { } public JsonWriterException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonWriterException(string message, string path, Exception? innerException) : base(message, innerException) { Path = path; } internal static JsonWriterException Create(JsonWriter writer, string message, Exception? ex) { return Create(writer.ContainerPath, message, ex); } internal static JsonWriterException Create(string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(null, path, message); return new JsonWriterException(message, path, ex); } } internal enum MemberSerialization { OptOut, OptIn, Fields } internal enum MetadataPropertyHandling { Default, ReadAhead, Ignore } internal enum MissingMemberHandling { Ignore, Error } internal enum NullValueHandling { Include, Ignore } internal enum ObjectCreationHandling { Auto, Reuse, Replace } [Flags] internal enum PreserveReferencesHandling { None = 0, Objects = 1, Arrays = 2, All = 3 } internal enum ReferenceLoopHandling { Error, Ignore, Serialize } internal enum Required { Default, AllowNull, Always, DisallowNull } internal enum StringEscapeHandling { Default, EscapeNonAscii, EscapeHtml } internal enum TypeNameAssemblyFormatHandling { Simple, Full } [Flags] internal enum TypeNameHandling { None = 0, Objects = 1, Arrays = 2, All = 3, Auto = 4 } internal enum WriteState { Error, Closed, Object, Array, Constructor, Property, Start } } namespace Newtonsoft.Json.Utilities { internal static class AsyncUtils { public static readonly Task False = Task.FromResult(result: false); public static readonly Task True = Task.FromResult(result: true); internal static readonly Task CompletedTask = Task.Delay(0); internal static Task ToAsync(this bool value) { if (!value) { return False; } return True; } public static Task? CancelIfRequestedAsync(this CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return null; } return cancellationToken.FromCanceled(); } public static Task? CancelIfRequestedAsync(this CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return null; } return cancellationToken.FromCanceled(); } public static Task FromCanceled(this CancellationToken cancellationToken) { return new Task(delegate { }, cancellationToken); } public static Task FromCanceled(this CancellationToken cancellationToken) { return new Task(() => default(T), cancellationToken); } public static Task WriteAsync(this TextWriter writer, char value, CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return writer.WriteAsync(value); } return cancellationToken.FromCanceled(); } public static Task WriteAsync(this TextWriter writer, string? value, CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return writer.WriteAsync(value); } return cancellationToken.FromCanceled(); } public static Task WriteAsync(this TextWriter writer, char[] value, int start, int count, CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return writer.WriteAsync(value, start, count); } return cancellationToken.FromCanceled(); } public static Task ReadAsync(this TextReader reader, char[] buffer, int index, int count, CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return reader.ReadAsync(buffer, index, count); } return cancellationToken.FromCanceled(); } public static bool IsCompletedSuccessfully(this Task task) { return task.IsCompletedSuccessfully; } } internal class Base64Encoder { private const int Base64LineSize = 76; private const int LineSizeInBytes = 57; private readonly char[] _charsLine = new char[76]; private readonly TextWriter _writer; private byte[]? _leftOverBytes; private int _leftOverBytesCount; public Base64Encoder(TextWriter writer) { ValidationUtils.ArgumentNotNull(writer, "writer"); _writer = writer; } private void ValidateEncode(byte[] buffer, int index, int count) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (index < 0) { throw new ArgumentOutOfRangeException("index"); } if (count < 0) { throw new ArgumentOutOfRangeException("count"); } if (count > buffer.Length - index) { throw new ArgumentOutOfRangeException("count"); } } public void Encode(byte[] buffer, int index, int count) { ValidateEncode(buffer, index, count); if (_leftOverBytesCount > 0) { if (FulfillFromLeftover(buffer, index, ref count)) { return; } int count2 = Convert.ToBase64CharArray(_leftOverBytes, 0, 3, _charsLine, 0); WriteChars(_charsLine, 0, count2); } StoreLeftOverBytes(buffer, index, ref count); int num = index + count; int num2 = 57; while (index < num) { if (index + num2 > num) { num2 = num - index; } int count3 = Convert.ToBase64CharArray(buffer, index, num2, _charsLine, 0); WriteChars(_charsLine, 0, count3); index += num2; } } private void StoreLeftOverBytes(byte[] buffer, int index, ref int count) { int num = count % 3; if (num > 0) { count -= num; if (_leftOverBytes == null) { _leftOverBytes = new byte[3]; } for (int i = 0; i < num; i++) { _leftOverBytes[i] = buffer[index + count + i]; } } _leftOverBytesCount = num; } private bool FulfillFromLeftover(byte[] buffer, int index, ref int count) { int leftOverBytesCount = _leftOverBytesCount; while (leftOverBytesCount < 3 && count > 0) { _leftOverBytes[leftOverBytesCount++] = buffer[index++]; count--; } if (count == 0 && leftOverBytesCount < 3) { _leftOverBytesCount = leftOverBytesCount; return true; } return false; } public void Flush() { if (_leftOverBytesCount > 0) { int count = Convert.ToBase64CharArray(_leftOverBytes, 0, _leftOverBytesCount, _charsLine, 0); WriteChars(_charsLine, 0, count); _leftOverBytesCount = 0; } } private void WriteChars(char[] chars, int index, int count) { _writer.Write(chars, index, count); } public async Task EncodeAsync(byte[] buffer, int index, int count, CancellationToken cancellationToken) { ValidateEncode(buffer, index, count); if (_leftOverBytesCount > 0) { if (FulfillFromLeftover(buffer, index, ref count)) { return; } int count2 = Convert.ToBase64CharArray(_leftOverBytes, 0, 3, _charsLine, 0); await WriteCharsAsync(_charsLine, 0, count2, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } StoreLeftOverBytes(buffer, index, ref count); int num4 = index + count; int length = 57; while (index < num4) { if (index + length > num4) { length = num4 - index; } int count3 = Convert.ToBase64CharArray(buffer, index, length, _charsLine, 0); await WriteCharsAsync(_charsLine, 0, count3, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); index += length; } } private Task WriteCharsAsync(char[] chars, int index, int count, CancellationToken cancellationToken) { return _writer.WriteAsync(chars, index, count, cancellationToken); } public Task FlushAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } if (_leftOverBytesCount > 0) { int count = Convert.ToBase64CharArray(_leftOverBytes, 0, _leftOverBytesCount, _charsLine, 0); _leftOverBytesCount = 0; return WriteCharsAsync(_charsLine, 0, count, cancellationToken); } return AsyncUtils.CompletedTask; } } internal class BidirectionalDictionary where TFirst : notnull where TSecond : notnull { private readonly IDictionary _firstToSecond; private readonly IDictionary _secondToFirst; private readonly string _duplicateFirstErrorMessage; private readonly string _duplicateSecondErrorMessage; public BidirectionalDictionary() : this((IEqualityComparer)EqualityComparer.Default, (IEqualityComparer)EqualityComparer.Default) { } public BidirectionalDictionary(IEqualityComparer firstEqualityComparer, IEqualityComparer secondEqualityComparer) : this(firstEqualityComparer, secondEqualityComparer, "Duplicate item already exists for '{0}'.", "Duplicate item already exists for '{0}'.") { } public BidirectionalDictionary(IEqualityComparer firstEqualityComparer, IEqualityComparer secondEqualityComparer, string duplicateFirstErrorMessage, string duplicateSecondErrorMessage) { _firstToSecond = new Dictionary(firstEqualityComparer); _secondToFirst = new Dictionary(secondEqualityComparer); _duplicateFirstErrorMessage = duplicateFirstErrorMessage; _duplicateSecondErrorMessage = duplicateSecondErrorMessage; } public void Set(TFirst first, TSecond second) { if (_firstToSecond.TryGetValue(first, out var value) && !value.Equals(second)) { throw new ArgumentException(_duplicateFirstErrorMessage.FormatWith(CultureInfo.InvariantCulture, first)); } if (_secondToFirst.TryGetValue(second, out var value2) && !value2.Equals(first)) { throw new ArgumentException(_duplicateSecondErrorMessage.FormatWith(CultureInfo.InvariantCulture, second)); } _firstToSecond.Add(first, second); _secondToFirst.Add(second, first); } public bool TryGetByFirst(TFirst first, [NotNullWhen(true)] out TSecond? second) { return _firstToSecond.TryGetValue(first, out second); } public bool TryGetBySecond(TSecond second, [NotNullWhen(true)] out TFirst? first) { return _secondToFirst.TryGetValue(second, out first); } } internal static class BoxedPrimitives { internal static readonly object BooleanTrue = true; internal static readonly object BooleanFalse = false; internal static readonly object Int32_M1 = -1; internal static readonly object Int32_0 = 0; internal static readonly object Int32_1 = 1; internal static readonly object Int32_2 = 2; internal static readonly object Int32_3 = 3; internal static readonly object Int32_4 = 4; internal static readonly object Int32_5 = 5; internal static readonly object Int32_6 = 6; internal static readonly object Int32_7 = 7; internal static readonly object Int32_8 = 8; internal static readonly object Int64_M1 = -1L; internal static readonly object Int64_0 = 0L; internal static readonly object Int64_1 = 1L; internal static readonly object Int64_2 = 2L; internal static readonly object Int64_3 = 3L; internal static readonly object Int64_4 = 4L; internal static readonly object Int64_5 = 5L; internal static readonly object Int64_6 = 6L; internal static readonly object Int64_7 = 7L; internal static readonly object Int64_8 = 8L; private static readonly object DecimalZero = 0m; internal static readonly object DoubleNaN = double.NaN; internal static readonly object DoublePositiveInfinity = double.PositiveInfinity; internal static readonly object DoubleNegativeInfinity = double.NegativeInfinity; internal static readonly object DoubleZero = 0.0; internal static object Get(bool value) { if (!value) { return BooleanFalse; } return BooleanTrue; } internal static object Get(int value) { return value switch { -1 => Int32_M1, 0 => Int32_0, 1 => Int32_1, 2 => Int32_2, 3 => Int32_3, 4 => Int32_4, 5 => Int32_5, 6 => Int32_6, 7 => Int32_7, 8 => Int32_8, _ => value, }; } internal static object Get(long value) { long num = value - -1; if ((ulong)num <= 9uL) { switch (num) { case 0L: return Int64_M1; case 1L: return Int64_0; case 2L: return Int64_1; case 3L: return Int64_2; case 4L: return Int64_3; case 5L: return Int64_4; case 6L: return Int64_5; case 7L: return Int64_6; case 8L: return Int64_7; case 9L: return Int64_8; } } return value; } internal static object Get(decimal value) { if (!(value == 0m)) { return value; } return DecimalZero; } internal static object Get(double value) { if (value == 0.0) { return DoubleZero; } if (double.IsInfinity(value)) { if (!double.IsPositiveInfinity(value)) { return DoubleNegativeInfinity; } return DoublePositiveInfinity; } if (double.IsNaN(value)) { return DoubleNaN; } return value; } } internal static class CollectionUtils { public static bool IsNullOrEmpty(ICollection collection) { if (collection != null) { return collection.Count == 0; } return true; } public static void AddRange(this IList initial, IEnumerable collection) { if (initial == null) { throw new ArgumentNullException("initial"); } if (collection == null) { return; } foreach (T item in collection) { initial.Add(item); } } public static bool IsDictionaryType(Type type) { ValidationUtils.ArgumentNotNull(type, "type"); if (typeof(IDictionary).IsAssignableFrom(type)) { return true; } if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IDictionary<, >))) { return true; } if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IReadOnlyDictionary<, >))) { return true; } return false; } public static ConstructorInfo? ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType) { Type constructorArgumentType = typeof(IList<>).MakeGenericType(collectionItemType); return ResolveEnumerableCollectionConstructor(collectionType, collectionItemType, constructorArgumentType); } public static ConstructorInfo? ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType, Type constructorArgumentType) { Type type = typeof(IEnumerable<>).MakeGenericType(collectionItemType); ConstructorInfo constructorInfo = null; ConstructorInfo[] constructors = collectionType.GetConstructors(BindingFlags.Instance | BindingFlags.Public); foreach (ConstructorInfo constructorInfo2 in constructors) { IList parameters = constructorInfo2.GetParameters(); if (parameters.Count == 1) { Type parameterType = parameters[0].ParameterType; if (type == parameterType) { constructorInfo = constructorInfo2; break; } if (constructorInfo == null && parameterType.IsAssignableFrom(constructorArgumentType)) { constructorInfo = constructorInfo2; } } } return constructorInfo; } public static bool AddDistinct(this IList list, T value) { return list.AddDistinct(value, EqualityComparer.Default); } public static bool AddDistinct(this IList list, T value, IEqualityComparer comparer) { if (list.ContainsValue(value, comparer)) { return false; } list.Add(value); return true; } public static bool ContainsValue(this IEnumerable source, TSource value, IEqualityComparer comparer) { if (comparer == null) { comparer = EqualityComparer.Default; } if (source == null) { throw new ArgumentNullException("source"); } foreach (TSource item in source) { if (comparer.Equals(item, value)) { return true; } } return false; } public static bool AddRangeDistinct(this IList list, IEnumerable values, IEqualityComparer comparer) { bool result = true; foreach (T value in values) { if (!list.AddDistinct(value, comparer)) { result = false; } } return result; } public static int IndexOf(this IEnumerable collection, Func predicate) { int num = 0; foreach (T item in collection) { if (predicate(item)) { return num; } num++; } return -1; } public static bool Contains(this List list, T value, IEqualityComparer comparer) { for (int i = 0; i < list.Count; i++) { if (comparer.Equals(value, list[i])) { return true; } } return false; } public static int IndexOfReference(this List list, T item) { for (int i = 0; i < list.Count; i++) { if ((object)item == (object)list[i]) { return i; } } return -1; } public static void FastReverse(this List list) { int num = 0; int num2 = list.Count - 1; while (num < num2) { T value = list[num]; list[num] = list[num2]; list[num2] = value; num++; num2--; } } private static IList GetDimensions(IList values, int dimensionsCount) { IList list = new List(); IList list2 = values; while (true) { list.Add(list2.Count); if (list.Count == dimensionsCount || list2.Count == 0 || !(list2[0] is IList list3)) { break; } list2 = list3; } return list; } private static void CopyFromJaggedToMultidimensionalArray(IList values, Array multidimensionalArray, int[] indices) { int num = indices.Length; if (num == multidimensionalArray.Rank) { multidimensionalArray.SetValue(JaggedArrayGetValue(values, indices), indices); return; } int length = multidimensionalArray.GetLength(num); if (((IList)JaggedArrayGetValue(values, indices)).Count != length) { throw new Exception("Cannot deserialize non-cubical array as multidimensional array."); } int[] array = new int[num + 1]; for (int i = 0; i < num; i++) { array[i] = indices[i]; } for (int j = 0; j < multidimensionalArray.GetLength(num); j++) { array[num] = j; CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, array); } } private static object JaggedArrayGetValue(IList values, int[] indices) { IList list = values; for (int i = 0; i < indices.Length; i++) { int index = indices[i]; if (i == indices.Length - 1) { return list[index]; } list = (IList)list[index]; } return list; } public static Array ToMultidimensionalArray(IList values, Type type, int rank) { IList dimensions = GetDimensions(values, rank); while (dimensions.Count < rank) { dimensions.Add(0); } Array array = Array.CreateInstance(type, dimensions.ToArray()); CopyFromJaggedToMultidimensionalArray(values, array, ArrayEmpty()); return array; } public static T[] ArrayEmpty() { return Array.Empty(); } } internal interface IWrappedCollection : IList, ICollection, IEnumerable { object UnderlyingCollection { get; } } internal class CollectionWrapper : ICollection, IEnumerable, IEnumerable, IWrappedCollection, IList, ICollection { private readonly IList? _list; private readonly ICollection? _genericCollection; private object? _syncRoot; public virtual int Count { get { if (_genericCollection != null) { return _genericCollection.Count; } return _list.Count; } } public virtual bool IsReadOnly { get { if (_genericCollection != null) { return _genericCollection.IsReadOnly; } return _list.IsReadOnly; } } bool IList.IsFixedSize { get { if (_genericCollection != null) { return _genericCollection.IsReadOnly; } return _list.IsFixedSize; } } object? IList.this[int index] { get { if (_genericCollection != null) { throw new InvalidOperationException("Wrapped ICollection does not support indexer."); } return _list[index]; } set { if (_genericCollection != null) { throw new InvalidOperationException("Wrapped ICollection does not support indexer."); } VerifyValueType(value); _list[index] = (T)value; } } bool ICollection.IsSynchronized => false; object ICollection.SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), null); } return _syncRoot; } } public object UnderlyingCollection => ((object)_genericCollection) ?? ((object)_list); public CollectionWrapper(IList list) { ValidationUtils.ArgumentNotNull(list, "list"); if (list is ICollection genericCollection) { _genericCollection = genericCollection; } else { _list = list; } } public CollectionWrapper(ICollection list) { ValidationUtils.ArgumentNotNull(list, "list"); _genericCollection = list; } public virtual void Add(T item) { if (_genericCollection != null) { _genericCollection.Add(item); } else { _list.Add(item); } } public virtual void Clear() { if (_genericCollection != null) { _genericCollection.Clear(); } else { _list.Clear(); } } public virtual bool Contains(T item) { if (_genericCollection != null) { return _genericCollection.Contains(item); } return _list.Contains(item); } public virtual void CopyTo(T[] array, int arrayIndex) { if (_genericCollection != null) { _genericCollection.CopyTo(array, arrayIndex); } else { _list.CopyTo(array, arrayIndex); } } public virtual bool Remove(T item) { if (_genericCollection != null) { return _genericCollection.Remove(item); } bool num = _list.Contains(item); if (num) { _list.Remove(item); } return num; } public virtual IEnumerator GetEnumerator() { IEnumerable genericCollection = _genericCollection; return (genericCollection ?? _list.Cast()).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { IEnumerable genericCollection = _genericCollection; return (genericCollection ?? _list).GetEnumerator(); } int IList.Add(object? value) { VerifyValueType(value); Add((T)value); return Count - 1; } bool IList.Contains(object? value) { if (IsCompatibleObject(value)) { return Contains((T)value); } return false; } int IList.IndexOf(object? value) { if (_genericCollection != null) { throw new InvalidOperationException("Wrapped ICollection does not support IndexOf."); } if (IsCompatibleObject(value)) { return _list.IndexOf((T)value); } return -1; } void IList.RemoveAt(int index) { if (_genericCollection != null) { throw new InvalidOperationException("Wrapped ICollection does not support RemoveAt."); } _list.RemoveAt(index); } void IList.Insert(int index, object? value) { if (_genericCollection != null) { throw new InvalidOperationException("Wrapped ICollection does not support Insert."); } VerifyValueType(value); _list.Insert(index, (T)value); } void IList.Remove(object? value) { if (IsCompatibleObject(value)) { Remove((T)value); } } void ICollection.CopyTo(Array array, int arrayIndex) { CopyTo((T[])array, arrayIndex); } private static void VerifyValueType(object? value) { if (!IsCompatibleObject(value)) { throw new ArgumentException("The value '{0}' is not of type '{1}' and cannot be used in this generic collection.".FormatWith(CultureInfo.InvariantCulture, value, typeof(T)), "value"); } } private static bool IsCompatibleObject(object? value) { if (!(value is T) && (value != null || (typeof(T).IsValueType() && !ReflectionUtils.IsNullableType(typeof(T))))) { return false; } return true; } } internal enum PrimitiveTypeCode { Empty, Object, Char, CharNullable, Boolean, BooleanNullable, SByte, SByteNullable, Int16, Int16Nullable, UInt16, UInt16Nullable, Int32, Int32Nullable, Byte, ByteNullable, UInt32, UInt32Nullable, Int64, Int64Nullable, UInt64, UInt64Nullable, Single, SingleNullable, Double, DoubleNullable, DateTime, DateTimeNullable, DateTimeOffset, DateTimeOffsetNullable, Decimal, DecimalNullable, Guid, GuidNullable, TimeSpan, TimeSpanNullable, BigInteger, BigIntegerNullable, Uri, String, Bytes, DBNull } internal class TypeInformation { public Type Type { get; } public PrimitiveTypeCode TypeCode { get; } public TypeInformation(Type type, PrimitiveTypeCode typeCode) { Type = type; TypeCode = typeCode; } } internal enum ParseResult { None, Success, Overflow, Invalid } internal static class ConvertUtils { internal enum ConvertResult { Success, CannotConvertNull, NotInstantiableType, NoValidConversion } private static readonly Dictionary TypeCodeMap = new Dictionary { { typeof(char), PrimitiveTypeCode.Char }, { typeof(char?), PrimitiveTypeCode.CharNullable }, { typeof(bool), PrimitiveTypeCode.Boolean }, { typeof(bool?), PrimitiveTypeCode.BooleanNullable }, { typeof(sbyte), PrimitiveTypeCode.SByte }, { typeof(sbyte?), PrimitiveTypeCode.SByteNullable }, { typeof(short), PrimitiveTypeCode.Int16 }, { typeof(short?), PrimitiveTypeCode.Int16Nullable }, { typeof(ushort), PrimitiveTypeCode.UInt16 }, { typeof(ushort?), PrimitiveTypeCode.UInt16Nullable }, { typeof(int), PrimitiveTypeCode.Int32 }, { typeof(int?), PrimitiveTypeCode.Int32Nullable }, { typeof(byte), PrimitiveTypeCode.Byte }, { typeof(byte?), PrimitiveTypeCode.ByteNullable }, { typeof(uint), PrimitiveTypeCode.UInt32 }, { typeof(uint?), PrimitiveTypeCode.UInt32Nullable }, { typeof(long), PrimitiveTypeCode.Int64 }, { typeof(long?), PrimitiveTypeCode.Int64Nullable }, { typeof(ulong), PrimitiveTypeCode.UInt64 }, { typeof(ulong?), PrimitiveTypeCode.UInt64Nullable }, { typeof(float), PrimitiveTypeCode.Single }, { typeof(float?), PrimitiveTypeCode.SingleNullable }, { typeof(double), PrimitiveTypeCode.Double }, { typeof(double?), PrimitiveTypeCode.DoubleNullable }, { typeof(DateTime), PrimitiveTypeCode.DateTime }, { typeof(DateTime?), PrimitiveTypeCode.DateTimeNullable }, { typeof(DateTimeOffset), PrimitiveTypeCode.DateTimeOffset }, { typeof(DateTimeOffset?), PrimitiveTypeCode.DateTimeOffsetNullable }, { typeof(decimal), PrimitiveTypeCode.Decimal }, { typeof(decimal?), PrimitiveTypeCode.DecimalNullable }, { typeof(Guid), PrimitiveTypeCode.Guid }, { typeof(Guid?), PrimitiveTypeCode.GuidNullable }, { typeof(TimeSpan), PrimitiveTypeCode.TimeSpan }, { typeof(TimeSpan?), PrimitiveTypeCode.TimeSpanNullable }, { typeof(BigInteger), PrimitiveTypeCode.BigInteger }, { typeof(BigInteger?), PrimitiveTypeCode.BigIntegerNullable }, { typeof(Uri), PrimitiveTypeCode.Uri }, { typeof(string), PrimitiveTypeCode.String }, { typeof(byte[]), PrimitiveTypeCode.Bytes }, { typeof(DBNull), PrimitiveTypeCode.DBNull } }; private static readonly TypeInformation[] PrimitiveTypeCodes = new TypeInformation[19] { new TypeInformation(typeof(object), PrimitiveTypeCode.Empty), new TypeInformation(typeof(object), PrimitiveTypeCode.Object), new TypeInformation(typeof(object), PrimitiveTypeCode.DBNull), new TypeInformation(typeof(bool), PrimitiveTypeCode.Boolean), new TypeInformation(typeof(char), PrimitiveTypeCode.Char), new TypeInformation(typeof(sbyte), PrimitiveTypeCode.SByte), new TypeInformation(typeof(byte), PrimitiveTypeCode.Byte), new TypeInformation(typeof(short), PrimitiveTypeCode.Int16), new TypeInformation(typeof(ushort), PrimitiveTypeCode.UInt16), new TypeInformation(typeof(int), PrimitiveTypeCode.Int32), new TypeInformation(typeof(uint), PrimitiveTypeCode.UInt32), new TypeInformation(typeof(long), PrimitiveTypeCode.Int64), new TypeInformation(typeof(ulong), PrimitiveTypeCode.UInt64), new TypeInformation(typeof(float), PrimitiveTypeCode.Single), new TypeInformation(typeof(double), PrimitiveTypeCode.Double), new TypeInformation(typeof(decimal), PrimitiveTypeCode.Decimal), new TypeInformation(typeof(DateTime), PrimitiveTypeCode.DateTime), new TypeInformation(typeof(object), PrimitiveTypeCode.Empty), new TypeInformation(typeof(string), PrimitiveTypeCode.String) }; private static readonly ThreadSafeStore, Func?> CastConverters = new ThreadSafeStore, Func>(CreateCastConverter); public static PrimitiveTypeCode GetTypeCode(Type t) { bool isEnum; return GetTypeCode(t, out isEnum); } public static PrimitiveTypeCode GetTypeCode(Type t, out bool isEnum) { if (TypeCodeMap.TryGetValue(t, out var value)) { isEnum = false; return value; } if (t.IsEnum()) { isEnum = true; return GetTypeCode(Enum.GetUnderlyingType(t)); } if (ReflectionUtils.IsNullableType(t)) { Type underlyingType = Nullable.GetUnderlyingType(t); if (underlyingType.IsEnum()) { Type t2 = typeof(Nullable<>).MakeGenericType(Enum.GetUnderlyingType(underlyingType)); isEnum = true; return GetTypeCode(t2); } } isEnum = false; return PrimitiveTypeCode.Object; } public static TypeInformation GetTypeInformation(IConvertible convertable) { return PrimitiveTypeCodes[(int)convertable.GetTypeCode()]; } public static bool IsConvertible(Type t) { return typeof(IConvertible).IsAssignableFrom(t); } public static TimeSpan ParseTimeSpan(string input) { return TimeSpan.Parse(input, CultureInfo.InvariantCulture); } private static Func? CreateCastConverter(StructMultiKey t) { Type value = t.Value1; Type value2 = t.Value2; MethodInfo methodInfo = value2.GetMethod("op_Implicit", new Type[1] { value }) ?? value2.GetMethod("op_Explicit", new Type[1] { value }); if (methodInfo == null) { return null; } MethodCall call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(methodInfo); return (object? o) => call(null, o); } internal static BigInteger ToBigInteger(object value) { if (value is BigInteger) { return (BigInteger)value; } if (value is string value2) { return BigInteger.Parse(value2, CultureInfo.InvariantCulture); } if (value is float value3) { return new BigInteger(value3); } if (value is double value4) { return new BigInteger(value4); } if (value is decimal value5) { return new BigInteger(value5); } if (value is int value6) { return new BigInteger(value6); } if (value is long value7) { return new BigInteger(value7); } if (value is uint value8) { return new BigInteger(value8); } if (value is ulong value9) { return new BigInteger(value9); } if (value is byte[] value10) { return new BigInteger(value10); } throw new InvalidCastException("Cannot convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } public static object FromBigInteger(BigInteger i, Type targetType) { if (targetType == typeof(decimal)) { return (decimal)i; } if (targetType == typeof(double)) { return (double)i; } if (targetType == typeof(float)) { return (float)i; } if (targetType == typeof(ulong)) { return (ulong)i; } if (targetType == typeof(bool)) { return i != 0L; } try { return System.Convert.ChangeType((long)i, targetType, CultureInfo.InvariantCulture); } catch (Exception innerException) { throw new InvalidOperationException("Can not convert from BigInteger to {0}.".FormatWith(CultureInfo.InvariantCulture, targetType), innerException); } } public static object Convert(object initialValue, CultureInfo culture, Type targetType) { object value; return TryConvertInternal(initialValue, culture, targetType, out value) switch { ConvertResult.Success => value, ConvertResult.CannotConvertNull => throw new Exception("Can not convert null {0} into non-nullable {1}.".FormatWith(CultureInfo.InvariantCulture, initialValue.GetType(), targetType)), ConvertResult.NotInstantiableType => throw new ArgumentException("Target type {0} is not a value type or a non-abstract class.".FormatWith(CultureInfo.InvariantCulture, targetType), "targetType"), ConvertResult.NoValidConversion => throw new InvalidOperationException("Can not convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, initialValue.GetType(), targetType)), _ => throw new InvalidOperationException("Unexpected conversion result."), }; } private static bool TryConvert(object? initialValue, CultureInfo culture, Type targetType, out object? value) { try { if (TryConvertInternal(initialValue, culture, targetType, out value) == ConvertResult.Success) { return true; } value = null; return false; } catch { value = null; return false; } } private static ConvertResult TryConvertInternal(object? initialValue, CultureInfo culture, Type targetType, out object? value) { if (initialValue == null) { throw new ArgumentNullException("initialValue"); } if (ReflectionUtils.IsNullableType(targetType)) { targetType = Nullable.GetUnderlyingType(targetType); } Type type = initialValue.GetType(); if (targetType == type) { value = initialValue; return ConvertResult.Success; } if (IsConvertible(initialValue.GetType()) && IsConvertible(targetType)) { if (targetType.IsEnum()) { if (initialValue is string) { value = Enum.Parse(targetType, initialValue.ToString(), ignoreCase: true); return ConvertResult.Success; } if (IsInteger(initialValue)) { value = Enum.ToObject(targetType, initialValue); return ConvertResult.Success; } } value = System.Convert.ChangeType(initialValue, targetType, culture); return ConvertResult.Success; } if (initialValue is DateTime dateTime && targetType == typeof(DateTimeOffset)) { value = new DateTimeOffset(dateTime); return ConvertResult.Success; } if (initialValue is byte[] b && targetType == typeof(Guid)) { value = new Guid(b); return ConvertResult.Success; } if (initialValue is Guid guid && targetType == typeof(byte[])) { value = guid.ToByteArray(); return ConvertResult.Success; } if (initialValue is string text) { if (targetType == typeof(Guid)) { value = new Guid(text); return ConvertResult.Success; } if (targetType == typeof(Uri)) { value = new Uri(text, UriKind.RelativeOrAbsolute); return ConvertResult.Success; } if (targetType == typeof(TimeSpan)) { value = ParseTimeSpan(text); return ConvertResult.Success; } if (targetType == typeof(byte[])) { value = System.Convert.FromBase64String(text); return ConvertResult.Success; } if (targetType == typeof(Version)) { if (VersionTryParse(text, out Version result)) { value = result; return ConvertResult.Success; } value = null; return ConvertResult.NoValidConversion; } if (typeof(Type).IsAssignableFrom(targetType)) { value = Type.GetType(text, throwOnError: true); return ConvertResult.Success; } if (targetType == typeof(DateOnly)) { value = DateOnly.ParseExact(text, "yyyy'-'MM'-'dd", CultureInfo.InvariantCulture); return ConvertResult.Success; } if (targetType == typeof(TimeOnly)) { value = TimeOnly.ParseExact(text, "HH':'mm':'ss.FFFFFFF", CultureInfo.InvariantCulture); return ConvertResult.Success; } } if (targetType == typeof(BigInteger)) { value = ToBigInteger(initialValue); return ConvertResult.Success; } if (initialValue is BigInteger i) { value = FromBigInteger(i, targetType); return ConvertResult.Success; } TypeConverter converter = TypeDescriptor.GetConverter(type); if (converter != null && converter.CanConvertTo(targetType)) { value = converter.ConvertTo(null, culture, initialValue, targetType); return ConvertResult.Success; } TypeConverter converter2 = TypeDescriptor.GetConverter(targetType); if (converter2 != null && converter2.CanConvertFrom(type)) { value = converter2.ConvertFrom(null, culture, initialValue); return ConvertResult.Success; } if (initialValue == DBNull.Value) { if (ReflectionUtils.IsNullable(targetType)) { value = EnsureTypeAssignable(null, type, targetType); return ConvertResult.Success; } value = null; return ConvertResult.CannotConvertNull; } if (targetType.IsInterface() || targetType.IsGenericTypeDefinition() || targetType.IsAbstract()) { value = null; return ConvertResult.NotInstantiableType; } value = null; return ConvertResult.NoValidConversion; } public static object? ConvertOrCast(object? initialValue, CultureInfo culture, Type targetType) { if (targetType == typeof(object)) { return initialValue; } if (initialValue == null && ReflectionUtils.IsNullable(targetType)) { return null; } if (TryConvert(initialValue, culture, targetType, out object value)) { return value; } return EnsureTypeAssignable(initialValue, ReflectionUtils.GetObjectType(initialValue), targetType); } private static object? EnsureTypeAssignable(object? value, Type initialType, Type targetType) { if (value != null) { Type type = value.GetType(); if (targetType.IsAssignableFrom(type)) { return value; } Func func = CastConverters.Get(new StructMultiKey(type, targetType)); if (func != null) { return func(value); } } else if (ReflectionUtils.IsNullable(targetType)) { return null; } throw new ArgumentException("Could not cast or convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, initialType?.ToString() ?? "{null}", targetType)); } public static bool VersionTryParse(string input, [NotNullWhen(true)] out Version? result) { return Version.TryParse(input, out result); } public static bool IsInteger(object value) { switch (GetTypeCode(value.GetType())) { case PrimitiveTypeCode.SByte: case PrimitiveTypeCode.Int16: case PrimitiveTypeCode.UInt16: case PrimitiveTypeCode.Int32: case PrimitiveTypeCode.Byte: case PrimitiveTypeCode.UInt32: case PrimitiveTypeCode.Int64: case PrimitiveTypeCode.UInt64: return true; default: return false; } } public static ParseResult Int32TryParse(char[] chars, int start, int length, out int value) { value = 0; if (length == 0) { return ParseResult.Invalid; } bool flag = chars[start] == '-'; if (flag) { if (length == 1) { return ParseResult.Invalid; } start++; length--; } int num = start + length; if (length > 10 || (length == 10 && chars[start] - 48 > 2)) { for (int i = start; i < num; i++) { int num2 = chars[i] - 48; if (num2 < 0 || num2 > 9) { return ParseResult.Invalid; } } return ParseResult.Overflow; } for (int j = start; j < num; j++) { int num3 = chars[j] - 48; if (num3 < 0 || num3 > 9) { return ParseResult.Invalid; } int num4 = 10 * value - num3; if (num4 > value) { for (j++; j < num; j++) { num3 = chars[j] - 48; if (num3 < 0 || num3 > 9) { return ParseResult.Invalid; } } return ParseResult.Overflow; } value = num4; } if (!flag) { if (value == int.MinValue) { return ParseResult.Overflow; } value = -value; } return ParseResult.Success; } public static ParseResult Int64TryParse(char[] chars, int start, int length, out long value) { value = 0L; if (length == 0) { return ParseResult.Invalid; } bool flag = chars[start] == '-'; if (flag) { if (length == 1) { return ParseResult.Invalid; } start++; length--; } int num = start + length; if (length > 19) { for (int i = start; i < num; i++) { int num2 = chars[i] - 48; if (num2 < 0 || num2 > 9) { return ParseResult.Invalid; } } return ParseResult.Overflow; } for (int j = start; j < num; j++) { int num3 = chars[j] - 48; if (num3 < 0 || num3 > 9) { return ParseResult.Invalid; } long num4 = 10 * value - num3; if (num4 > value) { for (j++; j < num; j++) { num3 = chars[j] - 48; if (num3 < 0 || num3 > 9) { return ParseResult.Invalid; } } return ParseResult.Overflow; } value = num4; } if (!flag) { if (value == long.MinValue) { return ParseResult.Overflow; } value = -value; } return ParseResult.Success; } public static ParseResult DecimalTryParse(char[] chars, int start, int length, out decimal value) { value = default(decimal); if (length == 0) { return ParseResult.Invalid; } bool flag = chars[start] == '-'; if (flag) { if (length == 1) { return ParseResult.Invalid; } start++; length--; } int i = start; int num = start + length; int num2 = num; int num3 = num; int num4 = 0; ulong num5 = 0uL; ulong num6 = 0uL; int num7 = 0; int num8 = 0; char? c = null; bool? flag2 = null; for (; i < num; i++) { char c2 = chars[i]; if (c2 == '.') { goto IL_0074; } if (c2 == 'E' || c2 == 'e') { goto IL_0091; } if (c2 < '0' || c2 > '9') { return ParseResult.Invalid; } if (i == start && c2 == '0') { i++; if (i != num) { c2 = chars[i]; if (c2 == '.') { goto IL_0074; } if (c2 != 'e' && c2 != 'E') { return ParseResult.Invalid; } goto IL_0091; } } if (num7 < 29) { if (num7 == 28) { bool? flag3 = flag2; bool valueOrDefault; if (!flag3.HasValue) { flag2 = num5 > 7922816251426433759L || (num5 == 7922816251426433759L && (num6 > 354395033 || (num6 == 354395033 && c2 > '5'))); bool? flag4 = flag2; valueOrDefault = flag4.GetValueOrDefault(); } else { valueOrDefault = flag3.GetValueOrDefault(); } if (valueOrDefault) { goto IL_01ff; } } if (num7 < 19) { num5 = num5 * 10 + (ulong)(c2 - 48); } else { num6 = num6 * 10 + (ulong)(c2 - 48); } num7++; continue; } goto IL_01ff; IL_0074: if (i == start) { return ParseResult.Invalid; } if (i + 1 == num) { return ParseResult.Invalid; } if (num2 != num) { return ParseResult.Invalid; } num2 = i + 1; continue; IL_01ff: if (!c.HasValue) { c = c2; } num8++; continue; IL_0091: if (i == start) { return ParseResult.Invalid; } if (i == num2) { return ParseResult.Invalid; } i++; if (i == num) { return ParseResult.Invalid; } if (num2 < num) { num3 = i - 1; } c2 = chars[i]; bool flag5 = false; switch (c2) { case '-': flag5 = true; i++; break; case '+': i++; break; } for (; i < num; i++) { c2 = chars[i]; if (c2 < '0' || c2 > '9') { return ParseResult.Invalid; } int num9 = 10 * num4 + (c2 - 48); if (num4 < num9) { num4 = num9; } } if (flag5) { num4 = -num4; } } num4 += num8; num4 -= num3 - num2; if (num7 <= 19) { value = num5; } else { value = (decimal)num5 / new decimal(1, 0, 0, isNegative: false, (byte)(num7 - 19)) + (decimal)num6; } if (num4 > 0) { num7 += num4; if (num7 > 29) { return ParseResult.Overflow; } if (num7 == 29) { if (num4 > 1) { value /= new decimal(1, 0, 0, isNegative: false, (byte)(num4 - 1)); if (value > 7922816251426433759354395033m) { return ParseResult.Overflow; } } else if (value == 7922816251426433759354395033m && c > '5') { return ParseResult.Overflow; } value *= 10m; } else { value /= new decimal(1, 0, 0, isNegative: false, (byte)num4); } } else { if (c >= '5' && num4 >= -28) { ++value; } if (num4 < 0) { if (num7 + num4 + 28 <= 0) { value = (flag ? 0m : 0m); return ParseResult.Success; } if (num4 >= -28) { value *= new decimal(1, 0, 0, isNegative: false, (byte)(-num4)); } else { value /= 10000000000000000000000000000m; value *= new decimal(1, 0, 0, isNegative: false, (byte)(-num4 - 28)); } } } if (flag) { value = -value; } return ParseResult.Success; } public static bool TryConvertGuid(string s, out Guid g) { return Guid.TryParseExact(s, "D", out g); } public static bool TryHexTextToInt(char[] text, int start, int end, out int value) { value = 0; for (int i = start; i < end; i++) { char c = text[i]; int num; if (c <= '9' && c >= '0') { num = c - 48; } else if (c <= 'F' && c >= 'A') { num = c - 55; } else { if (c > 'f' || c < 'a') { value = 0; return false; } num = c - 87; } value += num << (end - 1 - i) * 4; } return true; } } internal enum ParserTimeZone { Unspecified, Utc, LocalWestOfUtc, LocalEastOfUtc } internal struct DateTimeParser { public int Year; public int Month; public int Day; public int Hour; public int Minute; public int Second; public int Fraction; public int ZoneHour; public int ZoneMinute; public ParserTimeZone Zone; private char[] _text; private int _end; private static readonly int[] Power10; private static readonly int Lzyyyy; private static readonly int Lzyyyy_; private static readonly int Lzyyyy_MM; private static readonly int Lzyyyy_MM_; private static readonly int Lzyyyy_MM_dd; private static readonly int Lzyyyy_MM_ddT; private static readonly int LzHH; private static readonly int LzHH_; private static readonly int LzHH_mm; private static readonly int LzHH_mm_; private static readonly int LzHH_mm_ss; private static readonly int Lz_; private static readonly int Lz_zz; private const short MaxFractionDigits = 7; static DateTimeParser() { Power10 = new int[7] { -1, 10, 100, 1000, 10000, 100000, 1000000 }; Lzyyyy = "yyyy".Length; Lzyyyy_ = "yyyy-".Length; Lzyyyy_MM = "yyyy-MM".Length; Lzyyyy_MM_ = "yyyy-MM-".Length; Lzyyyy_MM_dd = "yyyy-MM-dd".Length; Lzyyyy_MM_ddT = "yyyy-MM-ddT".Length; LzHH = "HH".Length; LzHH_ = "HH:".Length; LzHH_mm = "HH:mm".Length; LzHH_mm_ = "HH:mm:".Length; LzHH_mm_ss = "HH:mm:ss".Length; Lz_ = "-".Length; Lz_zz = "-zz".Length; } public bool Parse(char[] text, int startIndex, int length) { _text = text; _end = startIndex + length; if (ParseDate(startIndex) && ParseChar(Lzyyyy_MM_dd + startIndex, 'T') && ParseTimeAndZoneAndWhitespace(Lzyyyy_MM_ddT + startIndex)) { return true; } return false; } private bool ParseDate(int start) { if (Parse4Digit(start, out Year) && 1 <= Year && ParseChar(start + Lzyyyy, '-') && Parse2Digit(start + Lzyyyy_, out Month) && 1 <= Month && Month <= 12 && ParseChar(start + Lzyyyy_MM, '-') && Parse2Digit(start + Lzyyyy_MM_, out Day) && 1 <= Day) { return Day <= DateTime.DaysInMonth(Year, Month); } return false; } private bool ParseTimeAndZoneAndWhitespace(int start) { if (ParseTime(ref start)) { return ParseZone(start); } return false; } private bool ParseTime(ref int start) { if (!Parse2Digit(start, out Hour) || Hour > 24 || !ParseChar(start + LzHH, ':') || !Parse2Digit(start + LzHH_, out Minute) || Minute >= 60 || !ParseChar(start + LzHH_mm, ':') || !Parse2Digit(start + LzHH_mm_, out Second) || Second >= 60 || (Hour == 24 && (Minute != 0 || Second != 0))) { return false; } start += LzHH_mm_ss; if (ParseChar(start, '.')) { Fraction = 0; int num = 0; while (++start < _end && num < 7) { int num2 = _text[start] - 48; if (num2 < 0 || num2 > 9) { break; } Fraction = Fraction * 10 + num2; num++; } if (num < 7) { if (num == 0) { return false; } Fraction *= Power10[7 - num]; } if (Hour == 24 && Fraction != 0) { return false; } } return true; } private bool ParseZone(int start) { if (start < _end) { char c = _text[start]; if (c == 'Z' || c == 'z') { Zone = ParserTimeZone.Utc; start++; } else { if (start + 2 < _end && Parse2Digit(start + Lz_, out ZoneHour) && ZoneHour <= 99) { switch (c) { case '-': Zone = ParserTimeZone.LocalWestOfUtc; start += Lz_zz; break; case '+': Zone = ParserTimeZone.LocalEastOfUtc; start += Lz_zz; break; } } if (start < _end) { if (ParseChar(start, ':')) { start++; if (start + 1 < _end && Parse2Digit(start, out ZoneMinute) && ZoneMinute <= 99) { start += 2; } } else if (start + 1 < _end && Parse2Digit(start, out ZoneMinute) && ZoneMinute <= 99) { start += 2; } } } } return start == _end; } private bool Parse4Digit(int start, out int num) { if (start + 3 < _end) { int num2 = _text[start] - 48; int num3 = _text[start + 1] - 48; int num4 = _text[start + 2] - 48; int num5 = _text[start + 3] - 48; if (0 <= num2 && num2 < 10 && 0 <= num3 && num3 < 10 && 0 <= num4 && num4 < 10 && 0 <= num5 && num5 < 10) { num = ((num2 * 10 + num3) * 10 + num4) * 10 + num5; return true; } } num = 0; return false; } private bool Parse2Digit(int start, out int num) { if (start + 1 < _end) { int num2 = _text[start] - 48; int num3 = _text[start + 1] - 48; if (0 <= num2 && num2 < 10 && 0 <= num3 && num3 < 10) { num = num2 * 10 + num3; return true; } } num = 0; return false; } private bool ParseChar(int start, char ch) { if (start < _end) { return _text[start] == ch; } return false; } } internal static class DateTimeUtils { internal static readonly long InitialJavaScriptDateTicks; private const string IsoDateFormat = "yyyy-MM-ddTHH:mm:ss.FFFFFFFK"; private const int DaysPer100Years = 36524; private const int DaysPer400Years = 146097; private const int DaysPer4Years = 1461; private const int DaysPerYear = 365; private const long TicksPerDay = 864000000000L; private static readonly int[] DaysToMonth365; private static readonly int[] DaysToMonth366; static DateTimeUtils() { InitialJavaScriptDateTicks = 621355968000000000L; DaysToMonth365 = new int[13] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; DaysToMonth366 = new int[13] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; } public static TimeSpan GetUtcOffset(this DateTime d) { return TimeZoneInfo.Local.GetUtcOffset(d); } public static XmlDateTimeSerializationMode ToSerializationMode(DateTimeKind kind) { return kind switch { DateTimeKind.Local => XmlDateTimeSerializationMode.Local, DateTimeKind.Unspecified => XmlDateTimeSerializationMode.Unspecified, DateTimeKind.Utc => XmlDateTimeSerializationMode.Utc, _ => throw MiscellaneousUtils.CreateArgumentOutOfRangeException("kind", kind, "Unexpected DateTimeKind value."), }; } internal static DateTime EnsureDateTime(DateTime value, DateTimeZoneHandling timeZone) { switch (timeZone) { case DateTimeZoneHandling.Local: value = SwitchToLocalTime(value); break; case DateTimeZoneHandling.Utc: value = SwitchToUtcTime(value); break; case DateTimeZoneHandling.Unspecified: value = new DateTime(value.Ticks, DateTimeKind.Unspecified); break; default: throw new ArgumentException("Invalid date time handling value."); case DateTimeZoneHandling.RoundtripKind: break; } return value; } private static DateTime SwitchToLocalTime(DateTime value) { return value.Kind switch { DateTimeKind.Unspecified => new DateTime(value.Ticks, DateTimeKind.Local), DateTimeKind.Utc => value.ToLocalTime(), DateTimeKind.Local => value, _ => value, }; } private static DateTime SwitchToUtcTime(DateTime value) { return value.Kind switch { DateTimeKind.Unspecified => new DateTime(value.Ticks, DateTimeKind.Utc), DateTimeKind.Utc => value, DateTimeKind.Local => value.ToUniversalTime(), _ => value, }; } private static long ToUniversalTicks(DateTime dateTime) { if (dateTime.Kind == DateTimeKind.Utc) { return dateTime.Ticks; } return ToUniversalTicks(dateTime, dateTime.GetUtcOffset()); } private static long ToUniversalTicks(DateTime dateTime, TimeSpan offset) { if (dateTime.Kind == DateTimeKind.Utc || dateTime == DateTime.MaxValue || dateTime == DateTime.MinValue) { return dateTime.Ticks; } long num = dateTime.Ticks - offset.Ticks; if (num > 3155378975999999999L) { return 3155378975999999999L; } if (num < 0) { return 0L; } return num; } internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, TimeSpan offset) { return UniversalTicksToJavaScriptTicks(ToUniversalTicks(dateTime, offset)); } internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime) { return ConvertDateTimeToJavaScriptTicks(dateTime, convertToUtc: true); } internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, bool convertToUtc) { return UniversalTicksToJavaScriptTicks(convertToUtc ? ToUniversalTicks(dateTime) : dateTime.Ticks); } private static long UniversalTicksToJavaScriptTicks(long universalTicks) { return (universalTicks - InitialJavaScriptDateTicks) / 10000; } internal static DateTime ConvertJavaScriptTicksToDateTime(long javaScriptTicks) { return new DateTime(javaScriptTicks * 10000 + InitialJavaScriptDateTicks, DateTimeKind.Utc); } internal static bool TryParseDateTimeIso(StringReference text, DateTimeZoneHandling dateTimeZoneHandling, out DateTime dt) { DateTimeParser dateTimeParser = default(DateTimeParser); if (!dateTimeParser.Parse(text.Chars, text.StartIndex, text.Length)) { dt = default(DateTime); return false; } DateTime dateTime = CreateDateTime(dateTimeParser); switch (dateTimeParser.Zone) { case ParserTimeZone.Utc: dateTime = new DateTime(dateTime.Ticks, DateTimeKind.Utc); break; case ParserTimeZone.LocalWestOfUtc: { TimeSpan timeSpan2 = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0); long num = dateTime.Ticks + timeSpan2.Ticks; if (num <= DateTime.MaxValue.Ticks) { dateTime = new DateTime(num, DateTimeKind.Utc).ToLocalTime(); break; } num += dateTime.GetUtcOffset().Ticks; if (num > DateTime.MaxValue.Ticks) { num = DateTime.MaxValue.Ticks; } dateTime = new DateTime(num, DateTimeKind.Local); break; } case ParserTimeZone.LocalEastOfUtc: { TimeSpan timeSpan = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0); long num = dateTime.Ticks - timeSpan.Ticks; if (num >= DateTime.MinValue.Ticks) { dateTime = new DateTime(num, DateTimeKind.Utc).ToLocalTime(); break; } num += dateTime.GetUtcOffset().Ticks; if (num < DateTime.MinValue.Ticks) { num = DateTime.MinValue.Ticks; } dateTime = new DateTime(num, DateTimeKind.Local); break; } } dt = EnsureDateTime(dateTime, dateTimeZoneHandling); return true; } internal static bool TryParseDateTimeOffsetIso(StringReference text, out DateTimeOffset dt) { DateTimeParser dateTimeParser = default(DateTimeParser); if (!dateTimeParser.Parse(text.Chars, text.StartIndex, text.Length)) { dt = default(DateTimeOffset); return false; } DateTime dateTime = CreateDateTime(dateTimeParser); TimeSpan offset = dateTimeParser.Zone switch { ParserTimeZone.Utc => new TimeSpan(0L), ParserTimeZone.LocalWestOfUtc => new TimeSpan(-dateTimeParser.ZoneHour, -dateTimeParser.ZoneMinute, 0), ParserTimeZone.LocalEastOfUtc => new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0), _ => TimeZoneInfo.Local.GetUtcOffset(dateTime), }; long num = dateTime.Ticks - offset.Ticks; if (num < 0 || num > 3155378975999999999L) { dt = default(DateTimeOffset); return false; } dt = new DateTimeOffset(dateTime, offset); return true; } private static DateTime CreateDateTime(DateTimeParser dateTimeParser) { bool flag; if (dateTimeParser.Hour == 24) { flag = true; dateTimeParser.Hour = 0; } else { flag = false; } DateTime result = new DateTime(dateTimeParser.Year, dateTimeParser.Month, dateTimeParser.Day, dateTimeParser.Hour, dateTimeParser.Minute, dateTimeParser.Second).AddTicks(dateTimeParser.Fraction); if (flag) { result = result.AddDays(1.0); } return result; } internal static bool TryParseDateTime(StringReference s, DateTimeZoneHandling dateTimeZoneHandling, string? dateFormatString, CultureInfo culture, out DateTime dt) { if (s.Length > 0) { int startIndex = s.StartIndex; if (s[startIndex] == '/') { if (s.Length >= 9 && s.StartsWith("/Date(") && s.EndsWith(")/") && TryParseDateTimeMicrosoft(s, dateTimeZoneHandling, out dt)) { return true; } } else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[startIndex]) && s[startIndex + 10] == 'T' && TryParseDateTimeIso(s, dateTimeZoneHandling, out dt)) { return true; } if (!StringUtils.IsNullOrEmpty(dateFormatString) && TryParseDateTimeExact(s.ToString(), dateTimeZoneHandling, dateFormatString, culture, out dt)) { return true; } } dt = default(DateTime); return false; } internal static bool TryParseDateTime(string s, DateTimeZoneHandling dateTimeZoneHandling, string? dateFormatString, CultureInfo culture, out DateTime dt) { if (s.Length > 0) { if (s[0] == '/') { if (s.Length >= 9 && s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal) && TryParseDateTimeMicrosoft(new StringReference(s.ToCharArray(), 0, s.Length), dateTimeZoneHandling, out dt)) { return true; } } else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[0]) && s[10] == 'T' && DateTime.TryParseExact(s, "yyyy-MM-ddTHH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt)) { dt = EnsureDateTime(dt, dateTimeZoneHandling); return true; } if (!StringUtils.IsNullOrEmpty(dateFormatString) && TryParseDateTimeExact(s, dateTimeZoneHandling, dateFormatString, culture, out dt)) { return true; } } dt = default(DateTime); return false; } internal static bool TryParseDateTimeOffset(StringReference s, string? dateFormatString, CultureInfo culture, out DateTimeOffset dt) { if (s.Length > 0) { int startIndex = s.StartIndex; if (s[startIndex] == '/') { if (s.Length >= 9 && s.StartsWith("/Date(") && s.EndsWith(")/") && TryParseDateTimeOffsetMicrosoft(s, out dt)) { return true; } } else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[startIndex]) && s[startIndex + 10] == 'T' && TryParseDateTimeOffsetIso(s, out dt)) { return true; } if (!StringUtils.IsNullOrEmpty(dateFormatString) && TryParseDateTimeOffsetExact(s.ToString(), dateFormatString, culture, out dt)) { return true; } } dt = default(DateTimeOffset); return false; } internal static bool TryParseDateTimeOffset(string s, string? dateFormatString, CultureInfo culture, out DateTimeOffset dt) { if (s.Length > 0) { if (s[0] == '/') { if (s.Length >= 9 && s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal) && TryParseDateTimeOffsetMicrosoft(new StringReference(s.ToCharArray(), 0, s.Length), out dt)) { return true; } } else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[0]) && s[10] == 'T' && DateTimeOffset.TryParseExact(s, "yyyy-MM-ddTHH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt) && TryParseDateTimeOffsetIso(new StringReference(s.ToCharArray(), 0, s.Length), out dt)) { return true; } if (!StringUtils.IsNullOrEmpty(dateFormatString) && TryParseDateTimeOffsetExact(s, dateFormatString, culture, out dt)) { return true; } } dt = default(DateTimeOffset); return false; } private static bool TryParseMicrosoftDate(StringReference text, out long ticks, out TimeSpan offset, out DateTimeKind kind) { kind = DateTimeKind.Utc; int num = text.IndexOf('+', 7, text.Length - 8); if (num == -1) { num = text.IndexOf('-', 7, text.Length - 8); } if (num != -1) { kind = DateTimeKind.Local; if (!TryReadOffset(text, num + text.StartIndex, out offset)) { ticks = 0L; return false; } } else { offset = TimeSpan.Zero; num = text.Length - 2; } return ConvertUtils.Int64TryParse(text.Chars, 6 + text.StartIndex, num - 6, out ticks) == ParseResult.Success; } private static bool TryParseDateTimeMicrosoft(StringReference text, DateTimeZoneHandling dateTimeZoneHandling, out DateTime dt) { if (!TryParseMicrosoftDate(text, out var ticks, out var _, out var kind)) { dt = default(DateTime); return false; } DateTime dateTime = ConvertJavaScriptTicksToDateTime(ticks); switch (kind) { case DateTimeKind.Unspecified: dt = DateTime.SpecifyKind(dateTime.ToLocalTime(), DateTimeKind.Unspecified); break; case DateTimeKind.Local: dt = dateTime.ToLocalTime(); break; default: dt = dateTime; break; } dt = EnsureDateTime(dt, dateTimeZoneHandling); return true; } private static bool TryParseDateTimeExact(string text, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out DateTime dt) { if (DateTime.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out var result)) { result = EnsureDateTime(result, dateTimeZoneHandling); dt = result; return true; } dt = default(DateTime); return false; } private static bool TryParseDateTimeOffsetMicrosoft(StringReference text, out DateTimeOffset dt) { if (!TryParseMicrosoftDate(text, out var ticks, out var offset, out var _)) { dt = default(DateTime); return false; } dt = new DateTimeOffset(ConvertJavaScriptTicksToDateTime(ticks).Add(offset).Ticks, offset); return true; } private static bool TryParseDateTimeOffsetExact(string text, string dateFormatString, CultureInfo culture, out DateTimeOffset dt) { if (DateTimeOffset.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out var result)) { dt = result; return true; } dt = default(DateTimeOffset); return false; } private static bool TryReadOffset(StringReference offsetText, int startIndex, out TimeSpan offset) { bool flag = offsetText[startIndex] == '-'; if (ConvertUtils.Int32TryParse(offsetText.Chars, startIndex + 1, 2, out var value) != ParseResult.Success) { offset = default(TimeSpan); return false; } int value2 = 0; if (offsetText.Length - startIndex > 5 && ConvertUtils.Int32TryParse(offsetText.Chars, startIndex + 3, 2, out value2) != ParseResult.Success) { offset = default(TimeSpan); return false; } offset = TimeSpan.FromHours(value) + TimeSpan.FromMinutes(value2); if (flag) { offset = offset.Negate(); } return true; } internal static void WriteDateTimeString(TextWriter writer, DateTime value, DateFormatHandling format, string? formatString, CultureInfo culture) { if (StringUtils.IsNullOrEmpty(formatString)) { char[] array = new char[64]; int count = WriteDateTimeString(array, 0, value, null, value.Kind, format); writer.Write(array, 0, count); } else { writer.Write(value.ToString(formatString, culture)); } } internal static int WriteDateTimeString(char[] chars, int start, DateTime value, TimeSpan? offset, DateTimeKind kind, DateFormatHandling format) { int num = start; if (format == DateFormatHandling.MicrosoftDateFormat) { TimeSpan offset2 = offset ?? value.GetUtcOffset(); long num2 = ConvertDateTimeToJavaScriptTicks(value, offset2); "\\/Date(".CopyTo(0, chars, num, 7); num += 7; string text = num2.ToString(CultureInfo.InvariantCulture); text.CopyTo(0, chars, num, text.Length); num += text.Length; switch (kind) { case DateTimeKind.Unspecified: if (value != DateTime.MaxValue && value != DateTime.MinValue) { num = WriteDateTimeOffset(chars, num, offset2, format); } break; case DateTimeKind.Local: num = WriteDateTimeOffset(chars, num, offset2, format); break; } ")\\/".CopyTo(0, chars, num, 3); num += 3; } else { num = WriteDefaultIsoDate(chars, num, value); switch (kind) { case DateTimeKind.Local: num = WriteDateTimeOffset(chars, num, offset ?? value.GetUtcOffset(), format); break; case DateTimeKind.Utc: chars[num++] = 'Z'; break; } } return num; } internal static int WriteDefaultIsoDate(char[] chars, int start, DateTime dt) { int num = 19; GetDateValues(dt, out var year, out var month, out var day); CopyIntToCharArray(chars, start, year, 4); chars[start + 4] = '-'; CopyIntToCharArray(chars, start + 5, month, 2); chars[start + 7] = '-'; CopyIntToCharArray(chars, start + 8, day, 2); chars[start + 10] = 'T'; CopyIntToCharArray(chars, start + 11, dt.Hour, 2); chars[start + 13] = ':'; CopyIntToCharArray(chars, start + 14, dt.Minute, 2); chars[start + 16] = ':'; CopyIntToCharArray(chars, start + 17, dt.Second, 2); int num2 = (int)(dt.Ticks % 10000000); if (num2 != 0) { int num3 = 7; while (num2 % 10 == 0) { num3--; num2 /= 10; } chars[start + 19] = '.'; CopyIntToCharArray(chars, start + 20, num2, num3); num += num3 + 1; } return start + num; } private static void CopyIntToCharArray(char[] chars, int start, int value, int digits) { while (digits-- != 0) { chars[start + digits] = (char)(value % 10 + 48); value /= 10; } } internal static int WriteDateTimeOffset(char[] chars, int start, TimeSpan offset, DateFormatHandling format) { chars[start++] = ((offset.Ticks >= 0) ? '+' : '-'); int value = Math.Abs(offset.Hours); CopyIntToCharArray(chars, start, value, 2); start += 2; if (format == DateFormatHandling.IsoDateFormat) { chars[start++] = ':'; } int value2 = Math.Abs(offset.Minutes); CopyIntToCharArray(chars, start, value2, 2); start += 2; return start; } internal static void WriteDateTimeOffsetString(TextWriter writer, DateTimeOffset value, DateFormatHandling format, string? formatString, CultureInfo culture) { if (StringUtils.IsNullOrEmpty(formatString)) { char[] array = new char[64]; int count = WriteDateTimeString(array, 0, (format == DateFormatHandling.IsoDateFormat) ? value.DateTime : value.UtcDateTime, value.Offset, DateTimeKind.Local, format); writer.Write(array, 0, count); } else { writer.Write(value.ToString(formatString, culture)); } } private static void GetDateValues(DateTime td, out int year, out int month, out int day) { int num = (int)(td.Ticks / 864000000000L); int num2 = num / 146097; num -= num2 * 146097; int num3 = num / 36524; if (num3 == 4) { num3 = 3; } num -= num3 * 36524; int num4 = num / 1461; num -= num4 * 1461; int num5 = num / 365; if (num5 == 4) { num5 = 3; } year = num2 * 400 + num3 * 100 + num4 * 4 + num5 + 1; num -= num5 * 365; int[] array = ((num5 == 3 && (num4 != 24 || num3 == 3)) ? DaysToMonth366 : DaysToMonth365); int i; for (i = num >> 6; num >= array[i]; i++) { } month = i; day = num - array[i - 1] + 1; } } internal interface IWrappedDictionary : IDictionary, ICollection, IEnumerable { object UnderlyingDictionary { get; } } internal class DictionaryWrapper : IDictionary, ICollection>, IEnumerable>, IEnumerable, IWrappedDictionary, IDictionary, ICollection { private readonly struct DictionaryEnumerator : IDictionaryEnumerator, IEnumerator { private readonly IEnumerator> _e; public DictionaryEntry Entry => (DictionaryEntry)Current; public object Key => Entry.Key; public object? Value => Entry.Value; public object Current => new DictionaryEntry(_e.Current.Key, _e.Current.Value); public DictionaryEnumerator(IEnumerator> e) { ValidationUtils.ArgumentNotNull(e, "e"); _e = e; } public bool MoveNext() { return _e.MoveNext(); } public void Reset() { _e.Reset(); } } private readonly IDictionary? _dictionary; private readonly IDictionary? _genericDictionary; private readonly IReadOnlyDictionary? _readOnlyDictionary; private object? _syncRoot; internal IDictionary GenericDictionary => _genericDictionary; public ICollection Keys { get { if (_dictionary != null) { return _dictionary.Keys.Cast().ToList(); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Keys.ToList(); } return GenericDictionary.Keys; } } public ICollection Values { get { if (_dictionary != null) { return _dictionary.Values.Cast().ToList(); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Values.ToList(); } return GenericDictionary.Values; } } public TValue this[TKey key] { get { if (_dictionary != null) { return (TValue)_dictionary[key]; } if (_readOnlyDictionary != null) { return _readOnlyDictionary[key]; } return GenericDictionary[key]; } set { if (_dictionary != null) { _dictionary[key] = value; return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary[key] = value; } } public int Count { get { if (_dictionary != null) { return _dictionary.Count; } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Count; } return GenericDictionary.Count; } } public bool IsReadOnly { get { if (_dictionary != null) { return _dictionary.IsReadOnly; } if (_readOnlyDictionary != null) { return true; } return GenericDictionary.IsReadOnly; } } object? IDictionary.this[object key] { get { if (_dictionary != null) { return _dictionary[key]; } if (_readOnlyDictionary != null) { return _readOnlyDictionary[(TKey)key]; } return GenericDictionary[(TKey)key]; } set { if (_dictionary != null) { _dictionary[key] = value; return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary[(TKey)key] = (TValue)value; } } bool IDictionary.IsFixedSize { get { if (_genericDictionary != null) { return false; } if (_readOnlyDictionary != null) { return true; } return _dictionary.IsFixedSize; } } ICollection IDictionary.Keys { get { if (_genericDictionary != null) { return _genericDictionary.Keys.ToList(); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Keys.ToList(); } return _dictionary.Keys; } } ICollection IDictionary.Values { get { if (_genericDictionary != null) { return _genericDictionary.Values.ToList(); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Values.ToList(); } return _dictionary.Values; } } bool ICollection.IsSynchronized { get { if (_dictionary != null) { return _dictionary.IsSynchronized; } return false; } } object ICollection.SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), null); } return _syncRoot; } } public object UnderlyingDictionary { get { if (_dictionary != null) { return _dictionary; } if (_readOnlyDictionary != null) { return _readOnlyDictionary; } return GenericDictionary; } } public DictionaryWrapper(IDictionary dictionary) { ValidationUtils.ArgumentNotNull(dictionary, "dictionary"); _dictionary = dictionary; } public DictionaryWrapper(IDictionary dictionary) { ValidationUtils.ArgumentNotNull(dictionary, "dictionary"); _genericDictionary = dictionary; } public DictionaryWrapper(IReadOnlyDictionary dictionary) { ValidationUtils.ArgumentNotNull(dictionary, "dictionary"); _readOnlyDictionary = dictionary; } public void Add(TKey key, TValue value) { if (_dictionary != null) { _dictionary.Add(key, value); return; } if (_genericDictionary != null) { _genericDictionary.Add(key, value); return; } throw new NotSupportedException(); } public bool ContainsKey(TKey key) { if (_dictionary != null) { return _dictionary.Contains(key); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.ContainsKey(key); } return GenericDictionary.ContainsKey(key); } public bool Remove(TKey key) { if (_dictionary != null) { if (_dictionary.Contains(key)) { _dictionary.Remove(key); return true; } return false; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } return GenericDictionary.Remove(key); } public bool TryGetValue(TKey key, out TValue? value) { if (_dictionary != null) { if (!_dictionary.Contains(key)) { value = default(TValue); return false; } value = (TValue)_dictionary[key]; return true; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } return GenericDictionary.TryGetValue(key, out value); } public void Add(KeyValuePair item) { if (_dictionary != null) { ((IList)_dictionary).Add(item); return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } _genericDictionary?.Add(item); } public void Clear() { if (_dictionary != null) { _dictionary.Clear(); return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary.Clear(); } public bool Contains(KeyValuePair item) { if (_dictionary != null) { return ((IList)_dictionary).Contains(item); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Contains(item); } return GenericDictionary.Contains(item); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { if (_dictionary != null) { foreach (DictionaryEntry item in _dictionary) { array[arrayIndex++] = new KeyValuePair((TKey)item.Key, (TValue)item.Value); } return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary.CopyTo(array, arrayIndex); } public bool Remove(KeyValuePair item) { if (_dictionary != null) { if (_dictionary.Contains(item.Key)) { if (object.Equals(_dictionary[item.Key], item.Value)) { _dictionary.Remove(item.Key); return true; } return false; } return true; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } return GenericDictionary.Remove(item); } public IEnumerator> GetEnumerator() { if (_dictionary != null) { return (from DictionaryEntry de in _dictionary select new KeyValuePair((TKey)de.Key, (TValue)de.Value)).GetEnumerator(); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.GetEnumerator(); } return GenericDictionary.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void IDictionary.Add(object key, object? value) { if (_dictionary != null) { _dictionary.Add(key, value); return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary.Add((TKey)key, (TValue)value); } IDictionaryEnumerator IDictionary.GetEnumerator() { if (_dictionary != null) { return _dictionary.GetEnumerator(); } if (_readOnlyDictionary != null) { return new DictionaryEnumerator(_readOnlyDictionary.GetEnumerator()); } return new DictionaryEnumerator(GenericDictionary.GetEnumerator()); } bool IDictionary.Contains(object key) { if (_genericDictionary != null) { return _genericDictionary.ContainsKey((TKey)key); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.ContainsKey((TKey)key); } return _dictionary.Contains(key); } public void Remove(object key) { if (_dictionary != null) { _dictionary.Remove(key); return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary.Remove((TKey)key); } void ICollection.CopyTo(Array array, int index) { if (_dictionary != null) { _dictionary.CopyTo(array, index); return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary.CopyTo((KeyValuePair[])array, index); } } internal class DynamicProxy { public virtual IEnumerable GetDynamicMemberNames(T instance) { return CollectionUtils.ArrayEmpty(); } public virtual bool TryBinaryOperation(T instance, BinaryOperationBinder binder, object arg, out object? result) { result = null; return false; } public virtual bool TryConvert(T instance, ConvertBinder binder, out object? result) { result = null; return false; } public virtual bool TryCreateInstance(T instance, CreateInstanceBinder binder, object[] args, out object? result) { result = null; return false; } public virtual bool TryDeleteIndex(T instance, DeleteIndexBinder binder, object[] indexes) { return false; } public virtual bool TryDeleteMember(T instance, DeleteMemberBinder binder) { return false; } public virtual bool TryGetIndex(T instance, GetIndexBinder binder, object[] indexes, out object? result) { result = null; return false; } public virtual bool TryGetMember(T instance, GetMemberBinder binder, out object? result) { result = null; return false; } public virtual bool TryInvoke(T instance, InvokeBinder binder, object[] args, out object? result) { result = null; return false; } public virtual bool TryInvokeMember(T instance, InvokeMemberBinder binder, object[] args, out object? result) { result = null; return false; } public virtual bool TrySetIndex(T instance, SetIndexBinder binder, object[] indexes, object value) { return false; } public virtual bool TrySetMember(T instance, SetMemberBinder binder, object value) { return false; } public virtual bool TryUnaryOperation(T instance, UnaryOperationBinder binder, out object? result) { result = null; return false; } } internal sealed class DynamicProxyMetaObject : DynamicMetaObject { private delegate DynamicMetaObject Fallback(DynamicMetaObject? errorSuggestion); private sealed class GetBinderAdapter : GetMemberBinder { internal GetBinderAdapter(InvokeMemberBinder binder) : base(binder.Name, binder.IgnoreCase) { } public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject? errorSuggestion) { throw new NotSupportedException(); } } private readonly DynamicProxy _proxy; private static Expression[] NoArgs => CollectionUtils.ArrayEmpty(); internal DynamicProxyMetaObject(Expression expression, T value, DynamicProxy proxy) : base(expression, BindingRestrictions.Empty, value) { _proxy = proxy; } private bool IsOverridden(string method) { return ReflectionUtils.IsMethodOverridden(_proxy.GetType(), typeof(DynamicProxy), method); } public override DynamicMetaObject BindGetMember(GetMemberBinder binder) { GetMemberBinder binder2 = binder; if (!IsOverridden("TryGetMember")) { return base.BindGetMember(binder2); } return CallMethodWithResult("TryGetMember", binder2, NoArgs, (DynamicMetaObject? e) => binder2.FallbackGetMember(this, e)); } public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) { SetMemberBinder binder2 = binder; DynamicMetaObject value2 = value; if (!IsOverridden("TrySetMember")) { return base.BindSetMember(binder2, value2); } return CallMethodReturnLast("TrySetMember", binder2, GetArgs(value2), (DynamicMetaObject? e) => binder2.FallbackSetMember(this, value2, e)); } public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) { DeleteMemberBinder binder2 = binder; if (!IsOverridden("TryDeleteMember")) { return base.BindDeleteMember(binder2); } return CallMethodNoResult("TryDeleteMember", binder2, NoArgs, (DynamicMetaObject? e) => binder2.FallbackDeleteMember(this, e)); } public override DynamicMetaObject BindConvert(ConvertBinder binder) { ConvertBinder binder2 = binder; if (!IsOverridden("TryConvert")) { return base.BindConvert(binder2); } return CallMethodWithResult("TryConvert", binder2, NoArgs, (DynamicMetaObject? e) => binder2.FallbackConvert(this, e)); } public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) { InvokeMemberBinder binder2 = binder; DynamicMetaObject[] args2 = args; if (!IsOverridden("TryInvokeMember")) { return base.BindInvokeMember(binder2, args2); } Fallback fallback = (DynamicMetaObject? e) => binder2.FallbackInvokeMember(this, args2, e); return BuildCallMethodWithResult("TryInvokeMember", binder2, GetArgArray(args2), BuildCallMethodWithResult("TryGetMember", new GetBinderAdapter(binder2), NoArgs, fallback(null), (DynamicMetaObject? e) => binder2.FallbackInvoke(e, args2, null)), null); } public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args) { CreateInstanceBinder binder2 = binder; DynamicMetaObject[] args2 = args; if (!IsOverridden("TryCreateInstance")) { return base.BindCreateInstance(binder2, args2); } return CallMethodWithResult("TryCreateInstance", binder2, GetArgArray(args2), (DynamicMetaObject? e) => binder2.FallbackCreateInstance(this, args2, e)); } public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { InvokeBinder binder2 = binder; DynamicMetaObject[] args2 = args; if (!IsOverridden("TryInvoke")) { return base.BindInvoke(binder2, args2); } return CallMethodWithResult("TryInvoke", binder2, GetArgArray(args2), (DynamicMetaObject? e) => binder2.FallbackInvoke(this, args2, e)); } public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg) { BinaryOperationBinder binder2 = binder; DynamicMetaObject arg2 = arg; if (!IsOverridden("TryBinaryOperation")) { return base.BindBinaryOperation(binder2, arg2); } return CallMethodWithResult("TryBinaryOperation", binder2, GetArgs(arg2), (DynamicMetaObject? e) => binder2.FallbackBinaryOperation(this, arg2, e)); } public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder) { UnaryOperationBinder binder2 = binder; if (!IsOverridden("TryUnaryOperation")) { return base.BindUnaryOperation(binder2); } return CallMethodWithResult("TryUnaryOperation", binder2, NoArgs, (DynamicMetaObject? e) => binder2.FallbackUnaryOperation(this, e)); } public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) { GetIndexBinder binder2 = binder; DynamicMetaObject[] indexes2 = indexes; if (!IsOverridden("TryGetIndex")) { return base.BindGetIndex(binder2, indexes2); } return CallMethodWithResult("TryGetIndex", binder2, GetArgArray(indexes2), (DynamicMetaObject? e) => binder2.FallbackGetIndex(this, indexes2, e)); } public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { SetIndexBinder binder2 = binder; DynamicMetaObject[] indexes2 = indexes; DynamicMetaObject value2 = value; if (!IsOverridden("TrySetIndex")) { return base.BindSetIndex(binder2, indexes2, value2); } return CallMethodReturnLast("TrySetIndex", binder2, GetArgArray(indexes2, value2), (DynamicMetaObject? e) => binder2.FallbackSetIndex(this, indexes2, value2, e)); } public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes) { DeleteIndexBinder binder2 = binder; DynamicMetaObject[] indexes2 = indexes; if (!IsOverridden("TryDeleteIndex")) { return base.BindDeleteIndex(binder2, indexes2); } return CallMethodNoResult("TryDeleteIndex", binder2, GetArgArray(indexes2), (DynamicMetaObject? e) => binder2.FallbackDeleteIndex(this, indexes2, e)); } private static IEnumerable GetArgs(params DynamicMetaObject[] args) { return args.Select(delegate(DynamicMetaObject arg) { Expression expression = arg.Expression; return (!expression.Type.IsValueType()) ? expression : System.Linq.Expressions.Expression.Convert(expression, typeof(object)); }); } private static Expression[] GetArgArray(DynamicMetaObject[] args) { return new NewArrayExpression[1] { System.Linq.Expressions.Expression.NewArrayInit(typeof(object), GetArgs(args)) }; } private static Expression[] GetArgArray(DynamicMetaObject[] args, DynamicMetaObject value) { Expression expression = value.Expression; return new Expression[2] { System.Linq.Expressions.Expression.NewArrayInit(typeof(object), GetArgs(args)), expression.Type.IsValueType() ? System.Linq.Expressions.Expression.Convert(expression, typeof(object)) : expression }; } private static ConstantExpression Constant(DynamicMetaObjectBinder binder) { Type type = binder.GetType(); while (!type.IsVisible()) { type = type.BaseType(); } return System.Linq.Expressions.Expression.Constant(binder, type); } private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, Fallback fallback, Fallback? fallbackInvoke = null) { DynamicMetaObject fallbackResult = fallback(null); return BuildCallMethodWithResult(methodName, binder, args, fallbackResult, fallbackInvoke); } private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, DynamicMetaObject fallbackResult, Fallback? fallbackInvoke) { ParameterExpression parameterExpression = System.Linq.Expressions.Expression.Parameter(typeof(object), null); IList list = new List(); list.Add(System.Linq.Expressions.Expression.Convert(base.Expression, typeof(T))); list.Add(Constant(binder)); list.AddRange(args); list.Add(parameterExpression); DynamicMetaObject dynamicMetaObject = new DynamicMetaObject(parameterExpression, BindingRestrictions.Empty); if (binder.ReturnType != typeof(object)) { dynamicMetaObject = new DynamicMetaObject(System.Linq.Expressions.Expression.Convert(dynamicMetaObject.Expression, binder.ReturnType), dynamicMetaObject.Restrictions); } if (fallbackInvoke != null) { dynamicMetaObject = fallbackInvoke(dynamicMetaObject); } return new DynamicMetaObject(System.Linq.Expressions.Expression.Block(new ParameterExpression[1] { parameterExpression }, System.Linq.Expressions.Expression.Condition(System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression.Constant(_proxy), typeof(DynamicProxy).GetMethod(methodName), list), dynamicMetaObject.Expression, fallbackResult.Expression, binder.ReturnType)), GetRestrictions().Merge(dynamicMetaObject.Restrictions).Merge(fallbackResult.Restrictions)); } private DynamicMetaObject CallMethodReturnLast(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, Fallback fallback) { DynamicMetaObject dynamicMetaObject = fallback(null); ParameterExpression parameterExpression = System.Linq.Expressions.Expression.Parameter(typeof(object), null); IList list = new List(); list.Add(System.Linq.Expressions.Expression.Convert(base.Expression, typeof(T))); list.Add(Constant(binder)); list.AddRange(args); list[list.Count - 1] = System.Linq.Expressions.Expression.Assign(parameterExpression, list[list.Count - 1]); return new DynamicMetaObject(System.Linq.Expressions.Expression.Block(new ParameterExpression[1] { parameterExpression }, System.Linq.Expressions.Expression.Condition(System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression.Constant(_proxy), typeof(DynamicProxy).GetMethod(methodName), list), parameterExpression, dynamicMetaObject.Expression, typeof(object))), GetRestrictions().Merge(dynamicMetaObject.Restrictions)); } private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) { DynamicMetaObject dynamicMetaObject = fallback(null); IList list = new List(); list.Add(System.Linq.Expressions.Expression.Convert(base.Expression, typeof(T))); list.Add(Constant(binder)); list.AddRange(args); return new DynamicMetaObject(System.Linq.Expressions.Expression.Condition(System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression.Constant(_proxy), typeof(DynamicProxy).GetMethod(methodName), list), System.Linq.Expressions.Expression.Empty(), dynamicMetaObject.Expression, typeof(void)), GetRestrictions().Merge(dynamicMetaObject.Restrictions)); } private BindingRestrictions GetRestrictions() { if (base.Value != null || !base.HasValue) { return BindingRestrictions.GetTypeRestriction(base.Expression, base.LimitType); } return BindingRestrictions.GetInstanceRestriction(base.Expression, null); } public override IEnumerable GetDynamicMemberNames() { return _proxy.GetDynamicMemberNames((T)base.Value); } } internal class DynamicReflectionDelegateFactory : ReflectionDelegateFactory { internal static DynamicReflectionDelegateFactory Instance { get; } = new DynamicReflectionDelegateFactory(); private static DynamicMethod CreateDynamicMethod(string name, Type? returnType, Type[] parameterTypes, Type owner) { if (owner.IsInterface()) { return new DynamicMethod(name, returnType, parameterTypes, owner.Module, skipVisibility: true); } return new DynamicMethod(name, returnType, parameterTypes, owner, skipVisibility: true); } public override ObjectConstructor CreateParameterizedConstructor(MethodBase method) { DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new Type[1] { typeof(object[]) }, method.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateMethodCallIL(method, iLGenerator, 0); return (ObjectConstructor)dynamicMethod.CreateDelegate(typeof(ObjectConstructor)); } public override MethodCall CreateMethodCall(MethodBase method) { DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new Type[2] { typeof(object), typeof(object[]) }, method.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateMethodCallIL(method, iLGenerator, 1); return (MethodCall)dynamicMethod.CreateDelegate(typeof(MethodCall)); } private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator, int argsIndex) { ParameterInfo[] parameters = method.GetParameters(); Label label = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg, argsIndex); generator.Emit(OpCodes.Ldlen); generator.Emit(OpCodes.Ldc_I4, parameters.Length); generator.Emit(OpCodes.Beq, label); generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(ReflectionUtils.EmptyTypes)); generator.Emit(OpCodes.Throw); generator.MarkLabel(label); if (!method.IsConstructor && !method.IsStatic) { generator.PushInstance(method.DeclaringType); } LocalBuilder local = generator.DeclareLocal(typeof(IConvertible)); LocalBuilder local2 = generator.DeclareLocal(typeof(object)); OpCode opcode = ((parameters.Length < 256) ? OpCodes.Ldloca_S : OpCodes.Ldloca); OpCode opcode2 = ((parameters.Length < 256) ? OpCodes.Ldloc_S : OpCodes.Ldloc); for (int i = 0; i < parameters.Length; i++) { ParameterInfo parameterInfo = parameters[i]; Type parameterType = parameterInfo.ParameterType; if (parameterType.IsByRef) { parameterType = parameterType.GetElementType(); LocalBuilder local3 = generator.DeclareLocal(parameterType); if (!parameterInfo.IsOut) { generator.PushArrayInstance(argsIndex, i); if (parameterType.IsValueType()) { Label label2 = generator.DefineLabel(); Label label3 = generator.DefineLabel(); generator.Emit(OpCodes.Brtrue_S, label2); generator.Emit(opcode, local3); generator.Emit(OpCodes.Initobj, parameterType); generator.Emit(OpCodes.Br_S, label3); generator.MarkLabel(label2); generator.PushArrayInstance(argsIndex, i); generator.UnboxIfNeeded(parameterType); generator.Emit(OpCodes.Stloc_S, local3); generator.MarkLabel(label3); } else { generator.UnboxIfNeeded(parameterType); generator.Emit(OpCodes.Stloc_S, local3); } } generator.Emit(opcode, local3); } else if (parameterType.IsValueType()) { generator.PushArrayInstance(argsIndex, i); generator.Emit(OpCodes.Stloc_S, local2); Label label4 = generator.DefineLabel(); Label label5 = generator.DefineLabel(); generator.Emit(OpCodes.Ldloc_S, local2); generator.Emit(OpCodes.Brtrue_S, label4); LocalBuilder local4 = generator.DeclareLocal(parameterType); generator.Emit(opcode, local4); generator.Emit(OpCodes.Initobj, parameterType); generator.Emit(opcode2, local4); generator.Emit(OpCodes.Br_S, label5); generator.MarkLabel(label4); if (parameterType.IsPrimitive()) { MethodInfo method2 = typeof(IConvertible).GetMethod("To" + parameterType.Name, new Type[1] { typeof(IFormatProvider) }); if (method2 != null) { Label label6 = generator.DefineLabel(); generator.Emit(OpCodes.Ldloc_S, local2); generator.Emit(OpCodes.Isinst, parameterType); generator.Emit(OpCodes.Brtrue_S, label6); generator.Emit(OpCodes.Ldloc_S, local2); generator.Emit(OpCodes.Isinst, typeof(IConvertible)); generator.Emit(OpCodes.Stloc_S, local); generator.Emit(OpCodes.Ldloc_S, local); generator.Emit(OpCodes.Brfalse_S, label6); generator.Emit(OpCodes.Ldloc_S, local); generator.Emit(OpCodes.Ldnull); generator.Emit(OpCodes.Callvirt, method2); generator.Emit(OpCodes.Br_S, label5); generator.MarkLabel(label6); } } generator.Emit(OpCodes.Ldloc_S, local2); generator.UnboxIfNeeded(parameterType); generator.MarkLabel(label5); } else { generator.PushArrayInstance(argsIndex, i); generator.UnboxIfNeeded(parameterType); } } if (method.IsConstructor) { generator.Emit(OpCodes.Newobj, (ConstructorInfo)method); } else { generator.CallMethod((MethodInfo)method); } Type type = (method.IsConstructor ? method.DeclaringType : ((MethodInfo)method).ReturnType); if (type != typeof(void)) { generator.BoxIfNeeded(type); } else { generator.Emit(OpCodes.Ldnull); } generator.Return(); } public override Func CreateDefaultConstructor(Type type) { DynamicMethod dynamicMethod = CreateDynamicMethod("Create" + type.FullName, typeof(T), ReflectionUtils.EmptyTypes, type); dynamicMethod.InitLocals = true; ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateDefaultConstructorIL(type, iLGenerator, typeof(T)); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private void GenerateCreateDefaultConstructorIL(Type type, ILGenerator generator, Type delegateType) { if (type.IsValueType()) { generator.DeclareLocal(type); generator.Emit(OpCodes.Ldloc_0); if (type != delegateType) { generator.Emit(OpCodes.Box, type); } } else { ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, ReflectionUtils.EmptyTypes, null); if (constructor == null) { throw new ArgumentException("Could not get constructor for {0}.".FormatWith(CultureInfo.InvariantCulture, type)); } generator.Emit(OpCodes.Newobj, constructor); } generator.Return(); } public override Func CreateGet(PropertyInfo propertyInfo) { DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(object), new Type[1] { typeof(T) }, propertyInfo.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateGetPropertyIL(propertyInfo, iLGenerator); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) { MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true); if (getMethod == null) { throw new ArgumentException("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture, propertyInfo.Name)); } if (!getMethod.IsStatic) { generator.PushInstance(propertyInfo.DeclaringType); } generator.CallMethod(getMethod); generator.BoxIfNeeded(propertyInfo.PropertyType); generator.Return(); } public override Func CreateGet(FieldInfo fieldInfo) { if (fieldInfo.IsLiteral) { object constantValue = fieldInfo.GetValue(null); return (T o) => constantValue; } DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new Type[1] { typeof(object) }, fieldInfo.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateGetFieldIL(fieldInfo, iLGenerator); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private void GenerateCreateGetFieldIL(FieldInfo fieldInfo, ILGenerator generator) { if (!fieldInfo.IsStatic) { generator.PushInstance(fieldInfo.DeclaringType); generator.Emit(OpCodes.Ldfld, fieldInfo); } else { generator.Emit(OpCodes.Ldsfld, fieldInfo); } generator.BoxIfNeeded(fieldInfo.FieldType); generator.Return(); } public override Action CreateSet(FieldInfo fieldInfo) { DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new Type[2] { typeof(T), typeof(object) }, fieldInfo.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateSetFieldIL(fieldInfo, iLGenerator); return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator generator) { if (!fieldInfo.IsStatic) { generator.PushInstance(fieldInfo.DeclaringType); } generator.Emit(OpCodes.Ldarg_1); generator.UnboxIfNeeded(fieldInfo.FieldType); if (!fieldInfo.IsStatic) { generator.Emit(OpCodes.Stfld, fieldInfo); } else { generator.Emit(OpCodes.Stsfld, fieldInfo); } generator.Return(); } public override Action CreateSet(PropertyInfo propertyInfo) { DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new Type[2] { typeof(T), typeof(object) }, propertyInfo.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateSetPropertyIL(propertyInfo, iLGenerator); return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } internal static void GenerateCreateSetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) { MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true); if (!setMethod.IsStatic) { generator.PushInstance(propertyInfo.DeclaringType); } generator.Emit(OpCodes.Ldarg_1); generator.UnboxIfNeeded(propertyInfo.PropertyType); generator.CallMethod(setMethod); generator.Return(); } } internal static class DynamicUtils { internal static class BinderWrapper { public const string CSharpAssemblyName = "Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; private const string BinderTypeName = "Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; private const string CSharpArgumentInfoTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; private const string CSharpArgumentInfoFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; private const string CSharpBinderFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; private static object? _getCSharpArgumentInfoArray; private static object? _setCSharpArgumentInfoArray; private static MethodCall? _getMemberCall; private static MethodCall? _setMemberCall; private static bool _init; private static void Init() { if (!_init) { if (Type.GetType("Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false) == null) { throw new InvalidOperationException("Could not resolve type '{0}'. You may need to add a reference to Microsoft.CSharp.dll to work with dynamic types.".FormatWith(CultureInfo.InvariantCulture, "Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")); } _getCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(default(int)); _setCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0, 3); CreateMemberCalls(); _init = true; } } private static object CreateSharpArgumentInfoArray(params int[] values) { Type type = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); Type type2 = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); Array array = Array.CreateInstance(type, values.Length); for (int i = 0; i < values.Length; i++) { object value = type.GetMethod("Create", new Type[2] { type2, typeof(string) }).Invoke(null, new object[2] { 0, null }); array.SetValue(value, i); } return array; } private static void CreateMemberCalls() { Type type = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); Type type2 = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); Type type3 = Type.GetType("Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); Type type4 = typeof(IEnumerable<>).MakeGenericType(type); MethodInfo method = type3.GetMethod("GetMember", new Type[4] { type2, typeof(string), typeof(Type), type4 }); _getMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(method); MethodInfo method2 = type3.GetMethod("SetMember", new Type[4] { type2, typeof(string), typeof(Type), type4 }); _setMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(method2); } public static CallSiteBinder GetMember(string name, Type context) { Init(); return (CallSiteBinder)_getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray); } public static CallSiteBinder SetMember(string name, Type context) { Init(); return (CallSiteBinder)_setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray); } } public static IEnumerable GetDynamicMemberNames(this IDynamicMetaObjectProvider dynamicProvider) { return dynamicProvider.GetMetaObject(Expression.Constant(dynamicProvider)).GetDynamicMemberNames(); } } internal class NoThrowGetBinderMember : GetMemberBinder { private readonly GetMemberBinder _innerBinder; public NoThrowGetBinderMember(GetMemberBinder innerBinder) : base(innerBinder.Name, innerBinder.IgnoreCase) { _innerBinder = innerBinder; } public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject? errorSuggestion) { DynamicMetaObject dynamicMetaObject = _innerBinder.Bind(target, CollectionUtils.ArrayEmpty()); return new DynamicMetaObject(new NoThrowExpressionVisitor().Visit(dynamicMetaObject.Expression), dynamicMetaObject.Restrictions); } } internal class NoThrowSetBinderMember : SetMemberBinder { private readonly SetMemberBinder _innerBinder; public NoThrowSetBinderMember(SetMemberBinder innerBinder) : base(innerBinder.Name, innerBinder.IgnoreCase) { _innerBinder = innerBinder; } public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject? errorSuggestion) { DynamicMetaObject dynamicMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[1] { value }); return new DynamicMetaObject(new NoThrowExpressionVisitor().Visit(dynamicMetaObject.Expression), dynamicMetaObject.Restrictions); } } internal class NoThrowExpressionVisitor : ExpressionVisitor { internal static readonly object ErrorResult = new object(); protected override Expression VisitConditional(ConditionalExpression node) { if (node.IfFalse.NodeType == ExpressionType.Throw) { return Expression.Condition(node.Test, node.IfTrue, Expression.Constant(ErrorResult)); } return base.VisitConditional(node); } } internal class EnumInfo { public readonly bool IsFlags; public readonly ulong[] Values; public readonly string[] Names; public readonly string[] ResolvedNames; public EnumInfo(bool isFlags, ulong[] values, string[] names, string[] resolvedNames) { IsFlags = isFlags; Values = values; Names = names; ResolvedNames = resolvedNames; } } internal static class EnumUtils { private const char EnumSeparatorChar = ','; private const string EnumSeparatorString = ", "; private static readonly ThreadSafeStore, EnumInfo> ValuesAndNamesPerEnum = new ThreadSafeStore, EnumInfo>(InitializeValuesAndNames); private static CamelCaseNamingStrategy _camelCaseNamingStrategy = new CamelCaseNamingStrategy(); private static EnumInfo InitializeValuesAndNames(StructMultiKey key) { Type value = key.Value1; string[] names = Enum.GetNames(value); string[] array = new string[names.Length]; ulong[] array2 = new ulong[names.Length]; for (int i = 0; i < names.Length; i++) { string text = names[i]; FieldInfo field = value.GetField(text, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); array2[i] = ToUInt64(field.GetValue(null)); string text2 = (from EnumMemberAttribute a in field.GetCustomAttributes(typeof(EnumMemberAttribute), inherit: true) select a.Value).SingleOrDefault(); bool hasSpecifiedName = text2 != null; if (text2 == null) { text2 = text; } string text3 = text2; if (Array.IndexOf(array, text3, 0, i) != -1) { throw new InvalidOperationException("Enum name '{0}' already exists on enum '{1}'.".FormatWith(CultureInfo.InvariantCulture, text3, value.Name)); } array[i] = ((key.Value2 != null) ? key.Value2.GetPropertyName(text3, hasSpecifiedName) : text3); } return new EnumInfo(value.IsDefined(typeof(FlagsAttribute), inherit: false), array2, names, array); } public static IList GetFlagsValues(T value) where T : struct { Type typeFromHandle = typeof(T); if (!typeFromHandle.IsDefined(typeof(FlagsAttribute), inherit: false)) { throw new ArgumentException("Enum type {0} is not a set of flags.".FormatWith(CultureInfo.InvariantCulture, typeFromHandle)); } Type underlyingType = Enum.GetUnderlyingType(value.GetType()); ulong num = ToUInt64(value); EnumInfo enumValuesAndNames = GetEnumValuesAndNames(typeFromHandle); IList list = new List(); for (int i = 0; i < enumValuesAndNames.Values.Length; i++) { ulong num2 = enumValuesAndNames.Values[i]; if ((num & num2) == num2 && num2 != 0L) { list.Add((T)Convert.ChangeType(num2, underlyingType, CultureInfo.CurrentCulture)); } } if (list.Count == 0 && enumValuesAndNames.Values.Any((ulong v) => v == 0)) { list.Add(default(T)); } return list; } public static bool TryToString(Type enumType, object value, bool camelCase, [NotNullWhen(true)] out string? name) { return TryToString(enumType, value, camelCase ? _camelCaseNamingStrategy : null, out name); } public static bool TryToString(Type enumType, object value, NamingStrategy? namingStrategy, [NotNullWhen(true)] out string? name) { EnumInfo enumInfo = ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, namingStrategy)); ulong num = ToUInt64(value); if (!enumInfo.IsFlags) { int num2 = Array.BinarySearch(enumInfo.Values, num); if (num2 >= 0) { name = enumInfo.ResolvedNames[num2]; return true; } name = null; return false; } name = InternalFlagsFormat(enumInfo, num); return name != null; } private static string? InternalFlagsFormat(EnumInfo entry, ulong result) { string[] resolvedNames = entry.ResolvedNames; ulong[] values = entry.Values; int num = values.Length - 1; StringBuilder stringBuilder = new StringBuilder(); bool flag = true; ulong num2 = result; while (num >= 0 && (num != 0 || values[num] != 0L)) { if ((result & values[num]) == values[num]) { result -= values[num]; if (!flag) { stringBuilder.Insert(0, ", "); } string value = resolvedNames[num]; stringBuilder.Insert(0, value); flag = false; } num--; } if (result != 0L) { return null; } if (num2 == 0L) { if (values.Length != 0 && values[0] == 0L) { return resolvedNames[0]; } return null; } return stringBuilder.ToString(); } public static EnumInfo GetEnumValuesAndNames(Type enumType) { return ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, null)); } private static ulong ToUInt64(object value) { bool isEnum; return ConvertUtils.GetTypeCode(value.GetType(), out isEnum) switch { PrimitiveTypeCode.SByte => (ulong)(sbyte)value, PrimitiveTypeCode.Byte => (byte)value, PrimitiveTypeCode.Boolean => Convert.ToByte((bool)value), PrimitiveTypeCode.Int16 => (ulong)(short)value, PrimitiveTypeCode.UInt16 => (ushort)value, PrimitiveTypeCode.Char => (char)value, PrimitiveTypeCode.UInt32 => (uint)value, PrimitiveTypeCode.Int32 => (ulong)(int)value, PrimitiveTypeCode.UInt64 => (ulong)value, PrimitiveTypeCode.Int64 => (ulong)(long)value, _ => throw new InvalidOperationException("Unknown enum type."), }; } public static object ParseEnum(Type enumType, NamingStrategy? namingStrategy, string value, bool disallowNumber) { ValidationUtils.ArgumentNotNull(enumType, "enumType"); ValidationUtils.ArgumentNotNull(value, "value"); if (!enumType.IsEnum()) { throw new ArgumentException("Type provided must be an Enum.", "enumType"); } EnumInfo enumInfo = ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, namingStrategy)); string[] names = enumInfo.Names; string[] resolvedNames = enumInfo.ResolvedNames; ulong[] values = enumInfo.Values; int? num = FindIndexByName(resolvedNames, value, 0, value.Length, StringComparison.Ordinal); if (num.HasValue) { return Enum.ToObject(enumType, values[num.Value]); } int num2 = -1; for (int i = 0; i < value.Length; i++) { if (!char.IsWhiteSpace(value[i])) { num2 = i; break; } } if (num2 == -1) { throw new ArgumentException("Must specify valid information for parsing in the string."); } char c = value[num2]; if (char.IsDigit(c) || c == '-' || c == '+') { Type underlyingType = Enum.GetUnderlyingType(enumType); value = value.Trim(); object obj = null; try { obj = Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture); } catch (FormatException) { } if (obj != null) { if (disallowNumber) { throw new FormatException("Integer string '{0}' is not allowed.".FormatWith(CultureInfo.InvariantCulture, value)); } return Enum.ToObject(enumType, obj); } } ulong num3 = 0uL; int j = num2; while (j <= value.Length) { int num4 = value.IndexOf(',', j); if (num4 == -1) { num4 = value.Length; } int num5 = num4; for (; j < num4 && char.IsWhiteSpace(value[j]); j++) { } while (num5 > j && char.IsWhiteSpace(value[num5 - 1])) { num5--; } int valueSubstringLength = num5 - j; num = MatchName(value, names, resolvedNames, j, valueSubstringLength, StringComparison.Ordinal); if (!num.HasValue) { num = MatchName(value, names, resolvedNames, j, valueSubstringLength, StringComparison.OrdinalIgnoreCase); } if (!num.HasValue) { num = FindIndexByName(resolvedNames, value, 0, value.Length, StringComparison.OrdinalIgnoreCase); if (num.HasValue) { return Enum.ToObject(enumType, values[num.Value]); } throw new ArgumentException("Requested value '{0}' was not found.".FormatWith(CultureInfo.InvariantCulture, value)); } num3 |= values[num.Value]; j = num4 + 1; } return Enum.ToObject(enumType, num3); } private static int? MatchName(string value, string[] enumNames, string[] resolvedNames, int valueIndex, int valueSubstringLength, StringComparison comparison) { int? result = FindIndexByName(resolvedNames, value, valueIndex, valueSubstringLength, comparison); if (!result.HasValue) { result = FindIndexByName(enumNames, value, valueIndex, valueSubstringLength, comparison); } return result; } private static int? FindIndexByName(string[] enumNames, string value, int valueIndex, int valueSubstringLength, StringComparison comparison) { for (int i = 0; i < enumNames.Length; i++) { if (enumNames[i].Length == valueSubstringLength && string.Compare(enumNames[i], 0, value, valueIndex, valueSubstringLength, comparison) == 0) { return i; } } return null; } } internal class ExpressionReflectionDelegateFactory : ReflectionDelegateFactory { private class ByRefParameter { public Expression Value; public ParameterExpression Variable; public bool IsOut; public ByRefParameter(Expression value, ParameterExpression variable, bool isOut) { Value = value; Variable = variable; IsOut = isOut; } } private static readonly ExpressionReflectionDelegateFactory _instance = new ExpressionReflectionDelegateFactory(); internal static ReflectionDelegateFactory Instance => _instance; public override ObjectConstructor CreateParameterizedConstructor(MethodBase method) { ValidationUtils.ArgumentNotNull(method, "method"); Type typeFromHandle = typeof(object); ParameterExpression parameterExpression = Expression.Parameter(typeof(object[]), "args"); Expression body = BuildMethodCall(method, typeFromHandle, null, parameterExpression); return (ObjectConstructor)Expression.Lambda(typeof(ObjectConstructor), body, parameterExpression).Compile(); } public override MethodCall CreateMethodCall(MethodBase method) { ValidationUtils.ArgumentNotNull(method, "method"); Type typeFromHandle = typeof(object); ParameterExpression parameterExpression = Expression.Parameter(typeFromHandle, "target"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object[]), "args"); Expression body = BuildMethodCall(method, typeFromHandle, parameterExpression, parameterExpression2); return (MethodCall)Expression.Lambda(typeof(MethodCall), body, parameterExpression, parameterExpression2).Compile(); } private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpression? targetParameterExpression, ParameterExpression argsParameterExpression) { ParameterInfo[] parameters = method.GetParameters(); Expression[] array; IList list; if (parameters.Length == 0) { array = CollectionUtils.ArrayEmpty(); list = CollectionUtils.ArrayEmpty(); } else { array = new Expression[parameters.Length]; list = new List(); for (int i = 0; i < parameters.Length; i++) { ParameterInfo parameterInfo = parameters[i]; Type type2 = parameterInfo.ParameterType; bool flag = false; if (type2.IsByRef) { type2 = type2.GetElementType(); flag = true; } Expression index = Expression.Constant(i); Expression expression = Expression.ArrayIndex(argsParameterExpression, index); Expression expression2 = EnsureCastExpression(expression, type2, !flag); if (flag) { ParameterExpression parameterExpression = Expression.Variable(type2); list.Add(new ByRefParameter(expression2, parameterExpression, parameterInfo.IsOut)); expression2 = parameterExpression; } array[i] = expression2; } } Expression expression3 = (method.IsConstructor ? ((Expression)Expression.New((ConstructorInfo)method, array)) : ((Expression)((!method.IsStatic) ? Expression.Call(EnsureCastExpression(targetParameterExpression, method.DeclaringType), (MethodInfo)method, array) : Expression.Call((MethodInfo)method, array)))); expression3 = ((!(method is MethodInfo methodInfo)) ? EnsureCastExpression(expression3, type) : ((!(methodInfo.ReturnType != typeof(void))) ? Expression.Block(expression3, Expression.Constant(null)) : EnsureCastExpression(expression3, type))); if (list.Count > 0) { IList list2 = new List(); IList list3 = new List(); foreach (ByRefParameter item in list) { if (!item.IsOut) { list3.Add(Expression.Assign(item.Variable, item.Value)); } list2.Add(item.Variable); } list3.Add(expression3); expression3 = Expression.Block(list2, list3); } return expression3; } public override Func CreateDefaultConstructor(Type type) { Type type2 = type; ValidationUtils.ArgumentNotNull(type2, "type"); if (type2.IsAbstract()) { return () => (T)Activator.CreateInstance(type2); } try { Type typeFromHandle = typeof(T); Expression expression = Expression.New(type2); expression = EnsureCastExpression(expression, typeFromHandle); return (Func)Expression.Lambda(typeof(Func), expression).Compile(); } catch { return () => (T)Activator.CreateInstance(type2); } } public override Func CreateGet(PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo"); Type typeFromHandle = typeof(T); Type typeFromHandle2 = typeof(object); ParameterExpression parameterExpression = Expression.Parameter(typeFromHandle, "instance"); MethodInfo? getMethod = propertyInfo.GetGetMethod(nonPublic: true); if (getMethod == null) { throw new ArgumentException("Property does not have a getter."); } Expression expression = ((!getMethod.IsStatic) ? Expression.MakeMemberAccess(EnsureCastExpression(parameterExpression, propertyInfo.DeclaringType), propertyInfo) : Expression.MakeMemberAccess(null, propertyInfo)); expression = EnsureCastExpression(expression, typeFromHandle2); return (Func)Expression.Lambda(typeof(Func), expression, parameterExpression).Compile(); } public override Func CreateGet(FieldInfo fieldInfo) { ValidationUtils.ArgumentNotNull(fieldInfo, "fieldInfo"); ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "source"); Expression expression = ((!fieldInfo.IsStatic) ? Expression.Field(EnsureCastExpression(parameterExpression, fieldInfo.DeclaringType), fieldInfo) : Expression.Field(null, fieldInfo)); expression = EnsureCastExpression(expression, typeof(object)); return Expression.Lambda>(expression, new ParameterExpression[1] { parameterExpression }).Compile(); } public override Action CreateSet(FieldInfo fieldInfo) { ValidationUtils.ArgumentNotNull(fieldInfo, "fieldInfo"); if (fieldInfo.DeclaringType.IsValueType() || fieldInfo.IsInitOnly) { return LateBoundReflectionDelegateFactory.Instance.CreateSet(fieldInfo); } ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "source"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value"); Expression expression = ((!fieldInfo.IsStatic) ? Expression.Field(EnsureCastExpression(parameterExpression, fieldInfo.DeclaringType), fieldInfo) : Expression.Field(null, fieldInfo)); Expression right = EnsureCastExpression(parameterExpression2, expression.Type); BinaryExpression body = Expression.Assign(expression, right); return (Action)Expression.Lambda(typeof(Action), body, parameterExpression, parameterExpression2).Compile(); } public override Action CreateSet(PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo"); if (propertyInfo.DeclaringType.IsValueType()) { return LateBoundReflectionDelegateFactory.Instance.CreateSet(propertyInfo); } Type typeFromHandle = typeof(T); Type typeFromHandle2 = typeof(object); ParameterExpression parameterExpression = Expression.Parameter(typeFromHandle, "instance"); ParameterExpression parameterExpression2 = Expression.Parameter(typeFromHandle2, "value"); Expression expression = EnsureCastExpression(parameterExpression2, propertyInfo.PropertyType); MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true); if (setMethod == null) { throw new ArgumentException("Property does not have a setter."); } return (Action)Expression.Lambda(body: (!setMethod.IsStatic) ? Expression.Call(EnsureCastExpression(parameterExpression, propertyInfo.DeclaringType), setMethod, expression) : Expression.Call(setMethod, expression), delegateType: typeof(Action), parameters: new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); } private Expression EnsureCastExpression(Expression expression, Type targetType, bool allowWidening = false) { Type type = expression.Type; if (type == targetType || (!type.IsValueType() && targetType.IsAssignableFrom(type))) { return expression; } if (targetType.IsValueType()) { Expression expression2 = Expression.Unbox(expression, targetType); if (allowWidening && targetType.IsPrimitive()) { MethodInfo method = typeof(Convert).GetMethod("To" + targetType.Name, new Type[1] { typeof(object) }); if (method != null) { expression2 = Expression.Condition(Expression.TypeIs(expression, targetType), expression2, Expression.Call(method, expression)); } } return Expression.Condition(Expression.Equal(expression, Expression.Constant(null, typeof(object))), Expression.Default(targetType), expression2); } return Expression.Convert(expression, targetType); } } internal class FSharpFunction { private readonly object? _instance; private readonly MethodCall _invoker; public FSharpFunction(object? instance, MethodCall invoker) { _instance = instance; _invoker = invoker; } public object Invoke(params object[] args) { return _invoker(_instance, args); } } internal class FSharpUtils { private static readonly object Lock = new object(); private static FSharpUtils? _instance; private MethodInfo _ofSeq; private Type _mapType; public const string FSharpSetTypeName = "FSharpSet`1"; public const string FSharpListTypeName = "FSharpList`1"; public const string FSharpMapTypeName = "FSharpMap`2"; public static FSharpUtils Instance => _instance; public Assembly FSharpCoreAssembly { get; private set; } public MethodCall IsUnion { get; private set; } public MethodCall GetUnionCases { get; private set; } public MethodCall PreComputeUnionTagReader { get; private set; } public MethodCall PreComputeUnionReader { get; private set; } public MethodCall PreComputeUnionConstructor { get; private set; } public Func GetUnionCaseInfoDeclaringType { get; private set; } public Func GetUnionCaseInfoName { get; private set; } public Func GetUnionCaseInfoTag { get; private set; } public MethodCall GetUnionCaseInfoFields { get; private set; } private FSharpUtils(Assembly fsharpCoreAssembly) { FSharpCoreAssembly = fsharpCoreAssembly; Type? type = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpType"); MethodInfo methodWithNonPublicFallback = GetMethodWithNonPublicFallback(type, "IsUnion", BindingFlags.Static | BindingFlags.Public); IsUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(methodWithNonPublicFallback); MethodInfo methodWithNonPublicFallback2 = GetMethodWithNonPublicFallback(type, "GetUnionCases", BindingFlags.Static | BindingFlags.Public); GetUnionCases = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(methodWithNonPublicFallback2); Type type2 = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpValue"); PreComputeUnionTagReader = CreateFSharpFuncCall(type2, "PreComputeUnionTagReader"); PreComputeUnionReader = CreateFSharpFuncCall(type2, "PreComputeUnionReader"); PreComputeUnionConstructor = CreateFSharpFuncCall(type2, "PreComputeUnionConstructor"); Type type3 = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.UnionCaseInfo"); GetUnionCaseInfoName = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(type3.GetProperty("Name")); GetUnionCaseInfoTag = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(type3.GetProperty("Tag")); GetUnionCaseInfoDeclaringType = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(type3.GetProperty("DeclaringType")); GetUnionCaseInfoFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(type3.GetMethod("GetFields")); Type type4 = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.ListModule"); _ofSeq = type4.GetMethod("OfSeq"); _mapType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpMap`2"); } public static void EnsureInitialized(Assembly fsharpCoreAssembly) { if (_instance != null) { return; } lock (Lock) { if (_instance == null) { _instance = new FSharpUtils(fsharpCoreAssembly); } } } private static MethodInfo GetMethodWithNonPublicFallback(Type type, string methodName, BindingFlags bindingFlags) { MethodInfo method = type.GetMethod(methodName, bindingFlags); if (method == null && (bindingFlags & BindingFlags.NonPublic) != BindingFlags.NonPublic) { method = type.GetMethod(methodName, bindingFlags | BindingFlags.NonPublic); } return method; } private static MethodCall CreateFSharpFuncCall(Type type, string methodName) { MethodInfo methodWithNonPublicFallback = GetMethodWithNonPublicFallback(type, methodName, BindingFlags.Static | BindingFlags.Public); MethodInfo method = methodWithNonPublicFallback.ReturnType.GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public); MethodCall call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(methodWithNonPublicFallback); MethodCall invoke = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(method); return (object? target, object?[] args) => new FSharpFunction(call(target, args), invoke); } public ObjectConstructor CreateSeq(Type t) { MethodInfo method = _ofSeq.MakeGenericMethod(t); return JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method); } public ObjectConstructor CreateMap(Type keyType, Type valueType) { return (ObjectConstructor)typeof(FSharpUtils).GetMethod("BuildMapCreator").MakeGenericMethod(keyType, valueType).Invoke(this, null); } public ObjectConstructor BuildMapCreator() { ConstructorInfo constructor = _mapType.MakeGenericType(typeof(TKey), typeof(TValue)).GetConstructor(new Type[1] { typeof(IEnumerable>) }); ObjectConstructor ctorDelegate = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); return delegate(object?[] args) { IEnumerable> enumerable = ((IEnumerable>)args[0]).Select((KeyValuePair kv) => new Tuple(kv.Key, kv.Value)); return ctorDelegate(enumerable); }; } } internal static class ILGeneratorExtensions { public static void PushInstance(this ILGenerator generator, Type type) { generator.Emit(OpCodes.Ldarg_0); if (type.IsValueType()) { generator.Emit(OpCodes.Unbox, type); } else { generator.Emit(OpCodes.Castclass, type); } } public static void PushArrayInstance(this ILGenerator generator, int argsIndex, int arrayIndex) { generator.Emit(OpCodes.Ldarg, argsIndex); generator.Emit(OpCodes.Ldc_I4, arrayIndex); generator.Emit(OpCodes.Ldelem_Ref); } public static void BoxIfNeeded(this ILGenerator generator, Type type) { if (type.IsValueType()) { generator.Emit(OpCodes.Box, type); } else { generator.Emit(OpCodes.Castclass, type); } } public static void UnboxIfNeeded(this ILGenerator generator, Type type) { if (type.IsValueType()) { generator.Emit(OpCodes.Unbox_Any, type); } else { generator.Emit(OpCodes.Castclass, type); } } public static void CallMethod(this ILGenerator generator, MethodInfo methodInfo) { if (methodInfo.IsFinal || !methodInfo.IsVirtual) { generator.Emit(OpCodes.Call, methodInfo); } else { generator.Emit(OpCodes.Callvirt, methodInfo); } } public static void Return(this ILGenerator generator) { generator.Emit(OpCodes.Ret); } } internal static class ImmutableCollectionsUtils { internal class ImmutableCollectionTypeInfo { public string ContractTypeName { get; set; } public string CreatedTypeName { get; set; } public string BuilderTypeName { get; set; } public ImmutableCollectionTypeInfo(string contractTypeName, string createdTypeName, string builderTypeName) { ContractTypeName = contractTypeName; CreatedTypeName = createdTypeName; BuilderTypeName = builderTypeName; } } private const string ImmutableListGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableList`1"; private const string ImmutableQueueGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableQueue`1"; private const string ImmutableStackGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableStack`1"; private const string ImmutableSetGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableSet`1"; private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray"; private const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1"; private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList"; private const string ImmutableListGenericTypeName = "System.Collections.Immutable.ImmutableList`1"; private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue"; private const string ImmutableQueueGenericTypeName = "System.Collections.Immutable.ImmutableQueue`1"; private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack"; private const string ImmutableStackGenericTypeName = "System.Collections.Immutable.ImmutableStack`1"; private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet"; private const string ImmutableSortedSetGenericTypeName = "System.Collections.Immutable.ImmutableSortedSet`1"; private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet"; private const string ImmutableHashSetGenericTypeName = "System.Collections.Immutable.ImmutableHashSet`1"; private static readonly IList ArrayContractImmutableCollectionDefinitions = new List { new ImmutableCollectionTypeInfo("System.Collections.Immutable.IImmutableList`1", "System.Collections.Immutable.ImmutableList`1", "System.Collections.Immutable.ImmutableList"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableList`1", "System.Collections.Immutable.ImmutableList`1", "System.Collections.Immutable.ImmutableList"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.IImmutableQueue`1", "System.Collections.Immutable.ImmutableQueue`1", "System.Collections.Immutable.ImmutableQueue"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableQueue`1", "System.Collections.Immutable.ImmutableQueue`1", "System.Collections.Immutable.ImmutableQueue"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.IImmutableStack`1", "System.Collections.Immutable.ImmutableStack`1", "System.Collections.Immutable.ImmutableStack"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableStack`1", "System.Collections.Immutable.ImmutableStack`1", "System.Collections.Immutable.ImmutableStack"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.IImmutableSet`1", "System.Collections.Immutable.ImmutableHashSet`1", "System.Collections.Immutable.ImmutableHashSet"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableSortedSet`1", "System.Collections.Immutable.ImmutableSortedSet`1", "System.Collections.Immutable.ImmutableSortedSet"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableHashSet`1", "System.Collections.Immutable.ImmutableHashSet`1", "System.Collections.Immutable.ImmutableHashSet"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableArray`1", "System.Collections.Immutable.ImmutableArray`1", "System.Collections.Immutable.ImmutableArray") }; private const string ImmutableDictionaryGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableDictionary`2"; private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary"; private const string ImmutableDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableDictionary`2"; private const string ImmutableSortedDictionaryTypeName = "System.Collections.Immutable.ImmutableSortedDictionary"; private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDictionary`2"; private static readonly IList DictionaryContractImmutableCollectionDefinitions = new List { new ImmutableCollectionTypeInfo("System.Collections.Immutable.IImmutableDictionary`2", "System.Collections.Immutable.ImmutableDictionary`2", "System.Collections.Immutable.ImmutableDictionary"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableSortedDictionary`2", "System.Collections.Immutable.ImmutableSortedDictionary`2", "System.Collections.Immutable.ImmutableSortedDictionary"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableDictionary`2", "System.Collections.Immutable.ImmutableDictionary`2", "System.Collections.Immutable.ImmutableDictionary") }; internal static bool TryBuildImmutableForArrayContract(Type underlyingType, Type collectionItemType, [NotNullWhen(true)] out Type? createdType, [NotNullWhen(true)] out ObjectConstructor? parameterizedCreator) { if (underlyingType.IsGenericType()) { Type genericTypeDefinition = underlyingType.GetGenericTypeDefinition(); string name = genericTypeDefinition.FullName; ImmutableCollectionTypeInfo immutableCollectionTypeInfo = ArrayContractImmutableCollectionDefinitions.FirstOrDefault((ImmutableCollectionTypeInfo d) => d.ContractTypeName == name); if (immutableCollectionTypeInfo != null) { Type type = genericTypeDefinition.Assembly().GetType(immutableCollectionTypeInfo.CreatedTypeName); Type type2 = genericTypeDefinition.Assembly().GetType(immutableCollectionTypeInfo.BuilderTypeName); if (type != null && type2 != null) { MethodInfo methodInfo = type2.GetMethods().FirstOrDefault((MethodInfo m) => m.Name == "CreateRange" && m.GetParameters().Length == 1); if (methodInfo != null) { createdType = type.MakeGenericType(collectionItemType); MethodInfo method = methodInfo.MakeGenericMethod(collectionItemType); parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method); return true; } } } } createdType = null; parameterizedCreator = null; return false; } internal static bool TryBuildImmutableForDictionaryContract(Type underlyingType, Type keyItemType, Type valueItemType, [NotNullWhen(true)] out Type? createdType, [NotNullWhen(true)] out ObjectConstructor? parameterizedCreator) { if (underlyingType.IsGenericType()) { Type genericTypeDefinition = underlyingType.GetGenericTypeDefinition(); string name = genericTypeDefinition.FullName; ImmutableCollectionTypeInfo immutableCollectionTypeInfo = DictionaryContractImmutableCollectionDefinitions.FirstOrDefault((ImmutableCollectionTypeInfo d) => d.ContractTypeName == name); if (immutableCollectionTypeInfo != null) { Type type = genericTypeDefinition.Assembly().GetType(immutableCollectionTypeInfo.CreatedTypeName); Type type2 = genericTypeDefinition.Assembly().GetType(immutableCollectionTypeInfo.BuilderTypeName); if (type != null && type2 != null) { MethodInfo methodInfo = type2.GetMethods().FirstOrDefault(delegate(MethodInfo m) { ParameterInfo[] parameters = m.GetParameters(); return m.Name == "CreateRange" && parameters.Length == 1 && parameters[0].ParameterType.IsGenericType() && parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>); }); if (methodInfo != null) { createdType = type.MakeGenericType(keyItemType, valueItemType); MethodInfo method = methodInfo.MakeGenericMethod(keyItemType, valueItemType); parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method); return true; } } } } createdType = null; parameterizedCreator = null; return false; } } internal static class BufferUtils { public static char[] RentBuffer(IArrayPool? bufferPool, int minSize) { if (bufferPool == null) { return new char[minSize]; } return bufferPool.Rent(minSize); } public static void ReturnBuffer(IArrayPool? bufferPool, char[]? buffer) { bufferPool?.Return(buffer); } public static char[] EnsureBufferSize(IArrayPool? bufferPool, int size, char[]? buffer) { if (bufferPool == null) { return new char[size]; } if (buffer != null) { bufferPool.Return(buffer); } return bufferPool.Rent(size); } } internal static class JavaScriptUtils { internal static readonly bool[] SingleQuoteCharEscapeFlags; internal static readonly bool[] DoubleQuoteCharEscapeFlags; internal static readonly bool[] HtmlCharEscapeFlags; private const int UnicodeTextLength = 6; private const string EscapedUnicodeText = "!"; static JavaScriptUtils() { SingleQuoteCharEscapeFlags = new bool[128]; DoubleQuoteCharEscapeFlags = new bool[128]; HtmlCharEscapeFlags = new bool[128]; IList list = new List { '\n', '\r', '\t', '\\', '\f', '\b' }; for (int i = 0; i < 32; i++) { list.Add((char)i); } foreach (char item in list.Union(new char[1] { '\'' })) { SingleQuoteCharEscapeFlags[(uint)item] = true; } foreach (char item2 in list.Union(new char[1] { '"' })) { DoubleQuoteCharEscapeFlags[(uint)item2] = true; } foreach (char item3 in list.Union(new char[5] { '"', '\'', '<', '>', '&' })) { HtmlCharEscapeFlags[(uint)item3] = true; } } public static bool[] GetCharEscapeFlags(StringEscapeHandling stringEscapeHandling, char quoteChar) { if (stringEscapeHandling == StringEscapeHandling.EscapeHtml) { return HtmlCharEscapeFlags; } if (quoteChar == '"') { return DoubleQuoteCharEscapeFlags; } return SingleQuoteCharEscapeFlags; } public static bool ShouldEscapeJavaScriptString(string? s, bool[] charEscapeFlags) { if (s == null) { return false; } foreach (char c in s) { if (c >= charEscapeFlags.Length || charEscapeFlags[(uint)c]) { return true; } } return false; } public static void WriteEscapedJavaScriptString(TextWriter writer, string? s, char delimiter, bool appendDelimiters, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, IArrayPool? bufferPool, ref char[]? writeBuffer) { if (appendDelimiters) { writer.Write(delimiter); } if (!StringUtils.IsNullOrEmpty(s)) { int num = FirstCharToEscape(s, charEscapeFlags, stringEscapeHandling); if (num == -1) { writer.Write(s); } else { if (num != 0) { if (writeBuffer == null || writeBuffer.Length < num) { writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, num, writeBuffer); } s.CopyTo(0, writeBuffer, 0, num); writer.Write(writeBuffer, 0, num); } int num2; for (int i = num; i < s.Length; i++) { char c = s[i]; if (c < charEscapeFlags.Length && !charEscapeFlags[(uint)c]) { continue; } string text; switch (c) { case '\t': text = "\\t"; break; case '\n': text = "\\n"; break; case '\r': text = "\\r"; break; case '\f': text = "\\f"; break; case '\b': text = "\\b"; break; case '\\': text = "\\\\"; break; case '\u0085': text = "\\u0085"; break; case '\u2028': text = "\\u2028"; break; case '\u2029': text = "\\u2029"; break; default: if (c < charEscapeFlags.Length || stringEscapeHandling == StringEscapeHandling.EscapeNonAscii) { if (c == '\'' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) { text = "\\'"; break; } if (c == '"' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) { text = "\\\""; break; } if (writeBuffer == null || writeBuffer.Length < 6) { writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, 6, writeBuffer); } StringUtils.ToCharAsUnicode(c, writeBuffer); text = "!"; } else { text = null; } break; } if (text == null) { continue; } bool flag = string.Equals(text, "!", StringComparison.Ordinal); if (i > num) { num2 = i - num + (flag ? 6 : 0); int num3 = (flag ? 6 : 0); if (writeBuffer == null || writeBuffer.Length < num2) { char[] array = BufferUtils.RentBuffer(bufferPool, num2); if (flag) { Array.Copy(writeBuffer, array, 6); } BufferUtils.ReturnBuffer(bufferPool, writeBuffer); writeBuffer = array; } s.CopyTo(num, writeBuffer, num3, num2 - num3); writer.Write(writeBuffer, num3, num2 - num3); } num = i + 1; if (!flag) { writer.Write(text); } else { writer.Write(writeBuffer, 0, 6); } } num2 = s.Length - num; if (num2 > 0) { if (writeBuffer == null || writeBuffer.Length < num2) { writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, num2, writeBuffer); } s.CopyTo(num, writeBuffer, 0, num2); writer.Write(writeBuffer, 0, num2); } } } if (appendDelimiters) { writer.Write(delimiter); } } public static string ToEscapedJavaScriptString(string? value, char delimiter, bool appendDelimiters, StringEscapeHandling stringEscapeHandling) { bool[] charEscapeFlags = GetCharEscapeFlags(stringEscapeHandling, delimiter); using StringWriter stringWriter = StringUtils.CreateStringWriter(value?.Length ?? 16); char[] writeBuffer = null; WriteEscapedJavaScriptString(stringWriter, value, delimiter, appendDelimiters, charEscapeFlags, stringEscapeHandling, null, ref writeBuffer); return stringWriter.ToString(); } private static int FirstCharToEscape(string s, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling) { for (int i = 0; i != s.Length; i++) { char c = s[i]; if (c < charEscapeFlags.Length) { if (charEscapeFlags[(uint)c]) { return i; } continue; } if (stringEscapeHandling == StringEscapeHandling.EscapeNonAscii) { return i; } if (c == '\u0085' || c == '\u2028' || c == '\u2029') { return i; } } return -1; } public static Task WriteEscapedJavaScriptStringAsync(TextWriter writer, string s, char delimiter, bool appendDelimiters, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } if (appendDelimiters) { return WriteEscapedJavaScriptStringWithDelimitersAsync(writer, s, delimiter, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); } if (StringUtils.IsNullOrEmpty(s)) { return cancellationToken.CancelIfRequestedAsync() ?? AsyncUtils.CompletedTask; } return WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); } private static Task WriteEscapedJavaScriptStringWithDelimitersAsync(TextWriter writer, string s, char delimiter, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) { Task task = writer.WriteAsync(delimiter, cancellationToken); if (!task.IsCompletedSuccessfully()) { return WriteEscapedJavaScriptStringWithDelimitersAsync(task, writer, s, delimiter, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); } if (!StringUtils.IsNullOrEmpty(s)) { task = WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); if (task.IsCompletedSuccessfully()) { return writer.WriteAsync(delimiter, cancellationToken); } } return WriteCharAsync(task, writer, delimiter, cancellationToken); } private static async Task WriteEscapedJavaScriptStringWithDelimitersAsync(Task task, TextWriter writer, string s, char delimiter, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); if (!StringUtils.IsNullOrEmpty(s)) { await WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await writer.WriteAsync(delimiter).ConfigureAwait(continueOnCapturedContext: false); } public static async Task WriteCharAsync(Task task, TextWriter writer, char c, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await writer.WriteAsync(c, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } private static Task WriteEscapedJavaScriptStringWithoutDelimitersAsync(TextWriter writer, string s, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) { int num = FirstCharToEscape(s, charEscapeFlags, stringEscapeHandling); if (num != -1) { return WriteDefinitelyEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, num, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); } return writer.WriteAsync(s, cancellationToken); } private static async Task WriteDefinitelyEscapedJavaScriptStringWithoutDelimitersAsync(TextWriter writer, string s, int lastWritePosition, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) { if (writeBuffer == null || writeBuffer.Length < lastWritePosition) { writeBuffer = client.EnsureWriteBuffer(lastWritePosition, 6); } if (lastWritePosition != 0) { s.CopyTo(0, writeBuffer, 0, lastWritePosition); await writer.WriteAsync(writeBuffer, 0, lastWritePosition, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } bool isEscapedUnicodeText = false; string escapedValue = null; int num; for (int i = lastWritePosition; i < s.Length; i++) { char c = s[i]; if (c < charEscapeFlags.Length && !charEscapeFlags[(uint)c]) { continue; } switch (c) { case '\t': escapedValue = "\\t"; break; case '\n': escapedValue = "\\n"; break; case '\r': escapedValue = "\\r"; break; case '\f': escapedValue = "\\f"; break; case '\b': escapedValue = "\\b"; break; case '\\': escapedValue = "\\\\"; break; case '\u0085': escapedValue = "\\u0085"; break; case '\u2028': escapedValue = "\\u2028"; break; case '\u2029': escapedValue = "\\u2029"; break; default: if (c >= charEscapeFlags.Length && stringEscapeHandling != StringEscapeHandling.EscapeNonAscii) { continue; } if (c == '\'' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) { escapedValue = "\\'"; break; } if (c == '"' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) { escapedValue = "\\\""; break; } if (writeBuffer.Length < 6) { writeBuffer = client.EnsureWriteBuffer(6, 0); } StringUtils.ToCharAsUnicode(c, writeBuffer); isEscapedUnicodeText = true; break; } if (i > lastWritePosition) { num = i - lastWritePosition + (isEscapedUnicodeText ? 6 : 0); int num2 = (isEscapedUnicodeText ? 6 : 0); if (writeBuffer.Length < num) { writeBuffer = client.EnsureWriteBuffer(num, 6); } s.CopyTo(lastWritePosition, writeBuffer, num2, num - num2); await writer.WriteAsync(writeBuffer, num2, num - num2, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } lastWritePosition = i + 1; if (!isEscapedUnicodeText) { await writer.WriteAsync(escapedValue, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); continue; } await writer.WriteAsync(writeBuffer, 0, 6, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); isEscapedUnicodeText = false; } num = s.Length - lastWritePosition; if (num != 0) { if (writeBuffer.Length < num) { writeBuffer = client.EnsureWriteBuffer(num, 0); } s.CopyTo(lastWritePosition, writeBuffer, 0, num); await writer.WriteAsync(writeBuffer, 0, num, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } public static bool TryGetDateFromConstructorJson(JsonReader reader, out DateTime dateTime, [NotNullWhen(false)] out string? errorMessage) { dateTime = default(DateTime); errorMessage = null; if (!TryGetDateConstructorValue(reader, out var integer, out errorMessage) || !integer.HasValue) { errorMessage = errorMessage ?? "Date constructor has no arguments."; return false; } if (!TryGetDateConstructorValue(reader, out var integer2, out errorMessage)) { return false; } if (integer2.HasValue) { List list = new List { integer.Value, integer2.Value }; while (true) { if (!TryGetDateConstructorValue(reader, out var integer3, out errorMessage)) { return false; } if (!integer3.HasValue) { break; } list.Add(integer3.Value); } if (list.Count > 7) { errorMessage = "Unexpected number of arguments when reading date constructor."; return false; } while (list.Count < 7) { list.Add(0L); } dateTime = new DateTime((int)list[0], (int)list[1] + 1, (int)((list[2] == 0L) ? 1 : list[2]), (int)list[3], (int)list[4], (int)list[5], (int)list[6]); } else { dateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(integer.Value); } return true; } private static bool TryGetDateConstructorValue(JsonReader reader, out long? integer, [NotNullWhen(false)] out string? errorMessage) { integer = null; errorMessage = null; if (!reader.Read()) { errorMessage = "Unexpected end when reading date constructor."; return false; } if (reader.TokenType == JsonToken.EndConstructor) { return true; } if (reader.TokenType != JsonToken.Integer) { errorMessage = "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType; return false; } integer = (long)reader.Value; return true; } } internal static class JsonTokenUtils { internal static bool IsEndToken(JsonToken token) { if ((uint)(token - 13) <= 2u) { return true; } return false; } internal static bool IsStartToken(JsonToken token) { if ((uint)(token - 1) <= 2u) { return true; } return false; } internal static bool IsPrimitiveToken(JsonToken token) { if ((uint)(token - 7) <= 5u || (uint)(token - 16) <= 1u) { return true; } return false; } } internal class LateBoundReflectionDelegateFactory : ReflectionDelegateFactory { private static readonly LateBoundReflectionDelegateFactory _instance = new LateBoundReflectionDelegateFactory(); internal static ReflectionDelegateFactory Instance => _instance; public override ObjectConstructor CreateParameterizedConstructor(MethodBase method) { MethodBase method2 = method; ValidationUtils.ArgumentNotNull(method2, "method"); ConstructorInfo c = method2 as ConstructorInfo; if ((object)c != null) { return (object?[] a) => c.Invoke(a); } return (object?[] a) => method2.Invoke(null, a); } public override MethodCall CreateMethodCall(MethodBase method) { MethodBase method2 = method; ValidationUtils.ArgumentNotNull(method2, "method"); ConstructorInfo c = method2 as ConstructorInfo; if ((object)c != null) { return (T o, object?[] a) => c.Invoke(a); } return (T o, object?[] a) => method2.Invoke(o, a); } public override Func CreateDefaultConstructor(Type type) { Type type2 = type; ValidationUtils.ArgumentNotNull(type2, "type"); if (type2.IsValueType()) { return () => (T)Activator.CreateInstance(type2); } ConstructorInfo constructorInfo = ReflectionUtils.GetDefaultConstructor(type2, nonPublic: true); if (constructorInfo == null) { throw new InvalidOperationException("Unable to find default constructor for " + type2.FullName); } return () => (T)constructorInfo.Invoke(null); } public override Func CreateGet(PropertyInfo propertyInfo) { PropertyInfo propertyInfo2 = propertyInfo; ValidationUtils.ArgumentNotNull(propertyInfo2, "propertyInfo"); return (T o) => propertyInfo2.GetValue(o, null); } public override Func CreateGet(FieldInfo fieldInfo) { FieldInfo fieldInfo2 = fieldInfo; ValidationUtils.ArgumentNotNull(fieldInfo2, "fieldInfo"); return (T o) => fieldInfo2.GetValue(o); } public override Action CreateSet(FieldInfo fieldInfo) { FieldInfo fieldInfo2 = fieldInfo; ValidationUtils.ArgumentNotNull(fieldInfo2, "fieldInfo"); return delegate(T o, object? v) { fieldInfo2.SetValue(o, v); }; } public override Action CreateSet(PropertyInfo propertyInfo) { PropertyInfo propertyInfo2 = propertyInfo; ValidationUtils.ArgumentNotNull(propertyInfo2, "propertyInfo"); return delegate(T o, object? v) { propertyInfo2.SetValue(o, v, null); }; } } internal static class MathUtils { public static int IntLength(ulong i) { if (i < 10000000000L) { if (i < 10) { return 1; } if (i < 100) { return 2; } if (i < 1000) { return 3; } if (i < 10000) { return 4; } if (i < 100000) { return 5; } if (i < 1000000) { return 6; } if (i < 10000000) { return 7; } if (i < 100000000) { return 8; } if (i < 1000000000) { return 9; } return 10; } if (i < 100000000000L) { return 11; } if (i < 1000000000000L) { return 12; } if (i < 10000000000000L) { return 13; } if (i < 100000000000000L) { return 14; } if (i < 1000000000000000L) { return 15; } if (i < 10000000000000000L) { return 16; } if (i < 100000000000000000L) { return 17; } if (i < 1000000000000000000L) { return 18; } if (i < 10000000000000000000uL) { return 19; } return 20; } public static char IntToHex(int n) { if (n <= 9) { return (char)(n + 48); } return (char)(n - 10 + 97); } public static int? Min(int? val1, int? val2) { if (!val1.HasValue) { return val2; } if (!val2.HasValue) { return val1; } return Math.Min(val1.GetValueOrDefault(), val2.GetValueOrDefault()); } public static int? Max(int? val1, int? val2) { if (!val1.HasValue) { return val2; } if (!val2.HasValue) { return val1; } return Math.Max(val1.GetValueOrDefault(), val2.GetValueOrDefault()); } public static double? Max(double? val1, double? val2) { if (!val1.HasValue) { return val2; } if (!val2.HasValue) { return val1; } return Math.Max(val1.GetValueOrDefault(), val2.GetValueOrDefault()); } public static bool ApproxEquals(double d1, double d2) { if (d1 == d2) { return true; } double num = (Math.Abs(d1) + Math.Abs(d2) + 10.0) * 2.220446049250313E-16; double num2 = d1 - d2; if (0.0 - num < num2) { return num > num2; } return false; } } internal delegate TResult MethodCall(T target, params object?[] args); internal delegate T Creator(); internal static class MiscellaneousUtils { [Conditional("DEBUG")] public static void Assert([DoesNotReturnIf(false)] bool condition, string? message = null) { } public static bool ValueEquals(object? objA, object? objB) { if (objA == objB) { return true; } if (objA == null || objB == null) { return false; } if (objA.GetType() != objB.GetType()) { if (ConvertUtils.IsInteger(objA) && ConvertUtils.IsInteger(objB)) { return Convert.ToDecimal(objA, CultureInfo.CurrentCulture).Equals(Convert.ToDecimal(objB, CultureInfo.CurrentCulture)); } if ((objA is double || objA is float || objA is decimal) && (objB is double || objB is float || objB is decimal)) { return MathUtils.ApproxEquals(Convert.ToDouble(objA, CultureInfo.CurrentCulture), Convert.ToDouble(objB, CultureInfo.CurrentCulture)); } return false; } return objA.Equals(objB); } public static ArgumentOutOfRangeException CreateArgumentOutOfRangeException(string paramName, object actualValue, string message) { string message2 = message + Environment.NewLine + "Actual value was {0}.".FormatWith(CultureInfo.InvariantCulture, actualValue); return new ArgumentOutOfRangeException(paramName, message2); } public static string ToString(object? value) { if (value == null) { return "{null}"; } if (!(value is string text)) { return value.ToString(); } return "\"" + text + "\""; } public static int ByteArrayCompare(byte[] a1, byte[] a2) { int num = a1.Length.CompareTo(a2.Length); if (num != 0) { return num; } for (int i = 0; i < a1.Length; i++) { int num2 = a1[i].CompareTo(a2[i]); if (num2 != 0) { return num2; } } return 0; } public static string? GetPrefix(string qualifiedName) { GetQualifiedNameParts(qualifiedName, out string prefix, out string _); return prefix; } public static string GetLocalName(string qualifiedName) { GetQualifiedNameParts(qualifiedName, out string _, out string localName); return localName; } public static void GetQualifiedNameParts(string qualifiedName, out string? prefix, out string localName) { int num = StringUtils.IndexOf(qualifiedName, ':'); if (num == -1 || num == 0 || qualifiedName.Length - 1 == num) { prefix = null; localName = qualifiedName; } else { prefix = qualifiedName.Substring(0, num); localName = qualifiedName.Substring(num + 1); } } internal static RegexOptions GetRegexOptions(string optionsText) { RegexOptions regexOptions = RegexOptions.None; for (int i = 0; i < optionsText.Length; i++) { switch (optionsText[i]) { case 'i': regexOptions |= RegexOptions.IgnoreCase; break; case 'm': regexOptions |= RegexOptions.Multiline; break; case 's': regexOptions |= RegexOptions.Singleline; break; case 'x': regexOptions |= RegexOptions.ExplicitCapture; break; } } return regexOptions; } } internal abstract class ReflectionDelegateFactory { public Func CreateGet(MemberInfo memberInfo) { if (memberInfo is PropertyInfo propertyInfo) { if (propertyInfo.PropertyType.IsByRef) { throw new InvalidOperationException("Could not create getter for {0}. ByRef return values are not supported.".FormatWith(CultureInfo.InvariantCulture, propertyInfo)); } return CreateGet(propertyInfo); } if (memberInfo is FieldInfo fieldInfo) { return CreateGet(fieldInfo); } throw new Exception("Could not create getter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo)); } public Action CreateSet(MemberInfo memberInfo) { if (memberInfo is PropertyInfo propertyInfo) { return CreateSet(propertyInfo); } if (memberInfo is FieldInfo fieldInfo) { return CreateSet(fieldInfo); } throw new Exception("Could not create setter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo)); } public abstract MethodCall CreateMethodCall(MethodBase method); public abstract ObjectConstructor CreateParameterizedConstructor(MethodBase method); public abstract Func CreateDefaultConstructor(Type type); public abstract Func CreateGet(PropertyInfo propertyInfo); public abstract Func CreateGet(FieldInfo fieldInfo); public abstract Action CreateSet(FieldInfo fieldInfo); public abstract Action CreateSet(PropertyInfo propertyInfo); } internal class ReflectionMember { public Type? MemberType { get; set; } public Func? Getter { get; set; } public Action? Setter { get; set; } } internal class ReflectionObject { public ObjectConstructor? Creator { get; } public IDictionary Members { get; } private ReflectionObject(ObjectConstructor? creator) { Members = new Dictionary(); Creator = creator; } public object? GetValue(object target, string member) { return Members[member].Getter(target); } public void SetValue(object target, string member, object? value) { Members[member].Setter(target, value); } public Type GetType(string member) { return Members[member].MemberType; } public static ReflectionObject Create(Type t, params string[] memberNames) { return Create(t, null, memberNames); } public static ReflectionObject Create(Type t, MethodBase? creator, params string[] memberNames) { ReflectionDelegateFactory reflectionDelegateFactory = JsonTypeReflector.ReflectionDelegateFactory; ObjectConstructor creator2 = null; if (creator != null) { creator2 = reflectionDelegateFactory.CreateParameterizedConstructor(creator); } else if (ReflectionUtils.HasDefaultConstructor(t, nonPublic: false)) { Func ctor = reflectionDelegateFactory.CreateDefaultConstructor(t); creator2 = (object?[] args) => ctor(); } ReflectionObject reflectionObject = new ReflectionObject(creator2); foreach (string text in memberNames) { MemberInfo[] member = t.GetMember(text, BindingFlags.Instance | BindingFlags.Public); if (member.Length != 1) { throw new ArgumentException("Expected a single member with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, text)); } MemberInfo memberInfo = member.Single(); ReflectionMember reflectionMember = new ReflectionMember(); switch (memberInfo.MemberType()) { case MemberTypes.Field: case MemberTypes.Property: if (ReflectionUtils.CanReadMemberValue(memberInfo, nonPublic: false)) { reflectionMember.Getter = reflectionDelegateFactory.CreateGet(memberInfo); } if (ReflectionUtils.CanSetMemberValue(memberInfo, nonPublic: false, canSetReadOnly: false)) { reflectionMember.Setter = reflectionDelegateFactory.CreateSet(memberInfo); } break; case MemberTypes.Method: { MethodInfo methodInfo = (MethodInfo)memberInfo; if (!methodInfo.IsPublic) { break; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 0 && methodInfo.ReturnType != typeof(void)) { MethodCall call2 = reflectionDelegateFactory.CreateMethodCall(methodInfo); reflectionMember.Getter = (object target) => call2(target); } else if (parameters.Length == 1 && methodInfo.ReturnType == typeof(void)) { MethodCall call = reflectionDelegateFactory.CreateMethodCall(methodInfo); reflectionMember.Setter = delegate(object target, object? arg) { call(target, arg); }; } break; } default: throw new ArgumentException("Unexpected member type '{0}' for member '{1}'.".FormatWith(CultureInfo.InvariantCulture, memberInfo.MemberType(), memberInfo.Name)); } reflectionMember.MemberType = ReflectionUtils.GetMemberUnderlyingType(memberInfo); reflectionObject.Members[text] = reflectionMember; } return reflectionObject; } } internal static class ReflectionUtils { public static readonly Type[] EmptyTypes; static ReflectionUtils() { EmptyTypes = Type.EmptyTypes; } public static bool IsVirtual(this PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo"); MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true); if (getMethod != null && getMethod.IsVirtual) { return true; } getMethod = propertyInfo.GetSetMethod(nonPublic: true); if (getMethod != null && getMethod.IsVirtual) { return true; } return false; } public static MethodInfo? GetBaseDefinition(this PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo"); MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true); if (getMethod != null) { return getMethod.GetBaseDefinition(); } return propertyInfo.GetSetMethod(nonPublic: true)?.GetBaseDefinition(); } public static bool IsPublic(PropertyInfo property) { MethodInfo getMethod = property.GetGetMethod(); if (getMethod != null && getMethod.IsPublic) { return true; } MethodInfo setMethod = property.GetSetMethod(); if (setMethod != null && setMethod.IsPublic) { return true; } return false; } public static Type? GetObjectType(object? v) { return v?.GetType(); } public static string GetTypeName(Type t, TypeNameAssemblyFormatHandling assemblyFormat, ISerializationBinder? binder) { string fullyQualifiedTypeName = GetFullyQualifiedTypeName(t, binder); return assemblyFormat switch { TypeNameAssemblyFormatHandling.Simple => RemoveAssemblyDetails(fullyQualifiedTypeName), TypeNameAssemblyFormatHandling.Full => fullyQualifiedTypeName, _ => throw new ArgumentOutOfRangeException(), }; } private static string GetFullyQualifiedTypeName(Type t, ISerializationBinder? binder) { if (binder != null) { binder.BindToName(t, out string assemblyName, out string typeName); return typeName + ((assemblyName == null) ? "" : (", " + assemblyName)); } return t.AssemblyQualifiedName; } private static string RemoveAssemblyDetails(string fullyQualifiedTypeName) { StringBuilder stringBuilder = new StringBuilder(); bool flag = false; bool flag2 = false; bool flag3 = false; foreach (char c in fullyQualifiedTypeName) { switch (c) { case '[': flag = false; flag2 = false; flag3 = true; stringBuilder.Append(c); break; case ']': flag = false; flag2 = false; flag3 = false; stringBuilder.Append(c); break; case ',': if (flag3) { stringBuilder.Append(c); } else if (!flag) { flag = true; stringBuilder.Append(c); } else { flag2 = true; } break; default: flag3 = false; if (!flag2) { stringBuilder.Append(c); } break; } } return stringBuilder.ToString(); } public static bool HasDefaultConstructor(Type t, bool nonPublic) { ValidationUtils.ArgumentNotNull(t, "t"); if (t.IsValueType()) { return true; } return GetDefaultConstructor(t, nonPublic) != null; } public static ConstructorInfo? GetDefaultConstructor(Type t) { return GetDefaultConstructor(t, nonPublic: false); } public static ConstructorInfo? GetDefaultConstructor(Type t, bool nonPublic) { BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public; if (nonPublic) { bindingFlags |= BindingFlags.NonPublic; } return t.GetConstructors(bindingFlags).SingleOrDefault((ConstructorInfo c) => !c.GetParameters().Any()); } public static bool IsNullable(Type t) { ValidationUtils.ArgumentNotNull(t, "t"); if (t.IsValueType()) { return IsNullableType(t); } return true; } public static bool IsNullableType(Type t) { ValidationUtils.ArgumentNotNull(t, "t"); if (t.IsGenericType()) { return t.GetGenericTypeDefinition() == typeof(Nullable<>); } return false; } public static Type EnsureNotNullableType(Type t) { if (!IsNullableType(t)) { return t; } return Nullable.GetUnderlyingType(t); } public static Type EnsureNotByRefType(Type t) { if (!t.IsByRef || !t.HasElementType) { return t; } return t.GetElementType(); } public static bool IsGenericDefinition(Type type, Type genericInterfaceDefinition) { if (!type.IsGenericType()) { return false; } return type.GetGenericTypeDefinition() == genericInterfaceDefinition; } public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition) { Type implementingType; return ImplementsGenericDefinition(type, genericInterfaceDefinition, out implementingType); } public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition, [NotNullWhen(true)] out Type? implementingType) { ValidationUtils.ArgumentNotNull(type, "type"); ValidationUtils.ArgumentNotNull(genericInterfaceDefinition, "genericInterfaceDefinition"); if (!genericInterfaceDefinition.IsInterface() || !genericInterfaceDefinition.IsGenericTypeDefinition()) { throw new ArgumentNullException("'{0}' is not a generic interface definition.".FormatWith(CultureInfo.InvariantCulture, genericInterfaceDefinition)); } if (type.IsInterface() && type.IsGenericType()) { Type genericTypeDefinition = type.GetGenericTypeDefinition(); if (genericInterfaceDefinition == genericTypeDefinition) { implementingType = type; return true; } } Type[] interfaces = type.GetInterfaces(); foreach (Type type2 in interfaces) { if (type2.IsGenericType()) { Type genericTypeDefinition2 = type2.GetGenericTypeDefinition(); if (genericInterfaceDefinition == genericTypeDefinition2) { implementingType = type2; return true; } } } implementingType = null; return false; } public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition) { Type implementingType; return InheritsGenericDefinition(type, genericClassDefinition, out implementingType); } public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition, out Type? implementingType) { ValidationUtils.ArgumentNotNull(type, "type"); ValidationUtils.ArgumentNotNull(genericClassDefinition, "genericClassDefinition"); if (!genericClassDefinition.IsClass() || !genericClassDefinition.IsGenericTypeDefinition()) { throw new ArgumentNullException("'{0}' is not a generic class definition.".FormatWith(CultureInfo.InvariantCulture, genericClassDefinition)); } return InheritsGenericDefinitionInternal(type, genericClassDefinition, out implementingType); } private static bool InheritsGenericDefinitionInternal(Type type, Type genericClassDefinition, out Type? implementingType) { Type type2 = type; do { if (type2.IsGenericType() && genericClassDefinition == type2.GetGenericTypeDefinition()) { implementingType = type2; return true; } type2 = type2.BaseType(); } while (type2 != null); implementingType = null; return false; } public static Type? GetCollectionItemType(Type type) { ValidationUtils.ArgumentNotNull(type, "type"); if (type.IsArray) { return type.GetElementType(); } if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out Type implementingType)) { if (implementingType.IsGenericTypeDefinition()) { throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type)); } return implementingType.GetGenericArguments()[0]; } if (typeof(IEnumerable).IsAssignableFrom(type)) { return null; } throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type)); } public static void GetDictionaryKeyValueTypes(Type dictionaryType, out Type? keyType, out Type? valueType) { ValidationUtils.ArgumentNotNull(dictionaryType, "dictionaryType"); if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<, >), out Type implementingType)) { if (implementingType.IsGenericTypeDefinition()) { throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType)); } Type[] genericArguments = implementingType.GetGenericArguments(); keyType = genericArguments[0]; valueType = genericArguments[1]; } else { if (!typeof(IDictionary).IsAssignableFrom(dictionaryType)) { throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType)); } keyType = null; valueType = null; } } public static Type GetMemberUnderlyingType(MemberInfo member) { ValidationUtils.ArgumentNotNull(member, "member"); return member.MemberType() switch { MemberTypes.Field => ((FieldInfo)member).FieldType, MemberTypes.Property => ((PropertyInfo)member).PropertyType, MemberTypes.Event => ((EventInfo)member).EventHandlerType, MemberTypes.Method => ((MethodInfo)member).ReturnType, _ => throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo, EventInfo or MethodInfo", "member"), }; } public static bool IsByRefLikeType(Type type) { if (!type.IsValueType()) { return false; } Attribute[] attributes = GetAttributes(type, null, inherit: false); for (int i = 0; i < attributes.Length; i++) { if (string.Equals(attributes[i].GetType().FullName, "System.Runtime.CompilerServices.IsByRefLikeAttribute", StringComparison.Ordinal)) { return true; } } return false; } public static bool IsIndexedProperty(PropertyInfo property) { ValidationUtils.ArgumentNotNull(property, "property"); return property.GetIndexParameters().Length != 0; } public static object? GetMemberValue(MemberInfo member, object target) { ValidationUtils.ArgumentNotNull(member, "member"); ValidationUtils.ArgumentNotNull(target, "target"); switch (member.MemberType()) { case MemberTypes.Field: return ((FieldInfo)member).GetValue(target); case MemberTypes.Property: try { return ((PropertyInfo)member).GetValue(target, null); } catch (TargetParameterCountException innerException) { throw new ArgumentException("MemberInfo '{0}' has index parameters".FormatWith(CultureInfo.InvariantCulture, member.Name), innerException); } default: throw new ArgumentException("MemberInfo '{0}' is not of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), "member"); } } public static void SetMemberValue(MemberInfo member, object target, object? value) { ValidationUtils.ArgumentNotNull(member, "member"); ValidationUtils.ArgumentNotNull(target, "target"); switch (member.MemberType()) { case MemberTypes.Field: ((FieldInfo)member).SetValue(target, value); break; case MemberTypes.Property: ((PropertyInfo)member).SetValue(target, value, null); break; default: throw new ArgumentException("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), "member"); } } public static bool CanReadMemberValue(MemberInfo member, bool nonPublic) { switch (member.MemberType()) { case MemberTypes.Field: { FieldInfo fieldInfo = (FieldInfo)member; if (nonPublic) { return true; } if (fieldInfo.IsPublic) { return true; } return false; } case MemberTypes.Property: { PropertyInfo propertyInfo = (PropertyInfo)member; if (!propertyInfo.CanRead) { return false; } if (nonPublic) { return true; } return propertyInfo.GetGetMethod(nonPublic) != null; } default: return false; } } public static bool CanSetMemberValue(MemberInfo member, bool nonPublic, bool canSetReadOnly) { switch (member.MemberType()) { case MemberTypes.Field: { FieldInfo fieldInfo = (FieldInfo)member; if (fieldInfo.IsLiteral) { return false; } if (fieldInfo.IsInitOnly && !canSetReadOnly) { return false; } if (nonPublic) { return true; } if (fieldInfo.IsPublic) { return true; } return false; } case MemberTypes.Property: { PropertyInfo propertyInfo = (PropertyInfo)member; if (!propertyInfo.CanWrite) { return false; } if (nonPublic) { return true; } return propertyInfo.GetSetMethod(nonPublic) != null; } default: return false; } } public static List GetFieldsAndProperties(Type type, BindingFlags bindingAttr) { List list = new List(); list.AddRange(GetFields(type, bindingAttr)); list.AddRange(GetProperties(type, bindingAttr)); List list2 = new List(list.Count); foreach (IGrouping item in from m in list group m by m.Name) { if (item.Count() == 1) { list2.Add(item.First()); continue; } List list3 = new List(); foreach (MemberInfo memberInfo in item) { if (list3.Count == 0) { list3.Add(memberInfo); } else if ((!IsOverridenGenericMember(memberInfo, bindingAttr) || memberInfo.Name == "Item") && !list3.Any((MemberInfo m) => m.DeclaringType == memberInfo.DeclaringType)) { list3.Add(memberInfo); } } list2.AddRange(list3); } return list2; } private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags bindingAttr) { if (memberInfo.MemberType() != MemberTypes.Property) { return false; } PropertyInfo propertyInfo = (PropertyInfo)memberInfo; if (!propertyInfo.IsVirtual()) { return false; } Type declaringType = propertyInfo.DeclaringType; if (!declaringType.IsGenericType()) { return false; } Type genericTypeDefinition = declaringType.GetGenericTypeDefinition(); if (genericTypeDefinition == null) { return false; } MemberInfo[] member = genericTypeDefinition.GetMember(propertyInfo.Name, bindingAttr); if (member.Length == 0) { return false; } if (!GetMemberUnderlyingType(member[0]).IsGenericParameter) { return false; } return true; } public static T? GetAttribute(object attributeProvider) where T : Attribute { return GetAttribute(attributeProvider, inherit: true); } public static T? GetAttribute(object attributeProvider, bool inherit) where T : Attribute { T[] attributes = GetAttributes(attributeProvider, inherit); if (attributes == null) { return null; } return attributes.FirstOrDefault(); } public static T[] GetAttributes(object attributeProvider, bool inherit) where T : Attribute { Attribute[] attributes = GetAttributes(attributeProvider, typeof(T), inherit); if (attributes is T[] result) { return result; } return attributes.Cast().ToArray(); } public static Attribute[] GetAttributes(object attributeProvider, Type? attributeType, bool inherit) { ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider"); if (!(attributeProvider is Type type)) { if (!(attributeProvider is Assembly element)) { if (!(attributeProvider is MemberInfo element2)) { if (!(attributeProvider is Module element3)) { if (attributeProvider is ParameterInfo element4) { if (!(attributeType != null)) { return Attribute.GetCustomAttributes(element4, inherit); } return Attribute.GetCustomAttributes(element4, attributeType, inherit); } ICustomAttributeProvider customAttributeProvider = (ICustomAttributeProvider)attributeProvider; return (Attribute[])((attributeType != null) ? customAttributeProvider.GetCustomAttributes(attributeType, inherit) : customAttributeProvider.GetCustomAttributes(inherit)); } if (!(attributeType != null)) { return Attribute.GetCustomAttributes(element3, inherit); } return Attribute.GetCustomAttributes(element3, attributeType, inherit); } if (!(attributeType != null)) { return Attribute.GetCustomAttributes(element2, inherit); } return Attribute.GetCustomAttributes(element2, attributeType, inherit); } if (!(attributeType != null)) { return Attribute.GetCustomAttributes(element); } return Attribute.GetCustomAttributes(element, attributeType); } return ((attributeType != null) ? type.GetCustomAttributes(attributeType, inherit) : type.GetCustomAttributes(inherit)).Cast().ToArray(); } public static StructMultiKey SplitFullyQualifiedTypeName(string fullyQualifiedTypeName) { int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName); string v; string v2; if (assemblyDelimiterIndex.HasValue) { v = fullyQualifiedTypeName.Trim(0, assemblyDelimiterIndex.GetValueOrDefault()); v2 = fullyQualifiedTypeName.Trim(assemblyDelimiterIndex.GetValueOrDefault() + 1, fullyQualifiedTypeName.Length - assemblyDelimiterIndex.GetValueOrDefault() - 1); } else { v = fullyQualifiedTypeName; v2 = null; } return new StructMultiKey(v2, v); } private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName) { int num = 0; for (int i = 0; i < fullyQualifiedTypeName.Length; i++) { switch (fullyQualifiedTypeName[i]) { case '[': num++; break; case ']': num--; break; case ',': if (num == 0) { return i; } break; } } return null; } public static MemberInfo? GetMemberInfoFromType(Type targetType, MemberInfo memberInfo) { if (memberInfo.MemberType() == MemberTypes.Property) { PropertyInfo propertyInfo = (PropertyInfo)memberInfo; Type[] types = (from p in propertyInfo.GetIndexParameters() select p.ParameterType).ToArray(); return targetType.GetProperty(propertyInfo.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, propertyInfo.PropertyType, types, null); } return targetType.GetMember(memberInfo.Name, memberInfo.MemberType(), BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).SingleOrDefault(); } public static IEnumerable GetFields(Type targetType, BindingFlags bindingAttr) { ValidationUtils.ArgumentNotNull(targetType, "targetType"); List list = new List(targetType.GetFields(bindingAttr)); GetChildPrivateFields(list, targetType, bindingAttr); return list.Cast(); } private static void GetChildPrivateFields(IList initialFields, Type type, BindingFlags bindingAttr) { Type type2 = type; if ((bindingAttr & BindingFlags.NonPublic) == 0) { return; } BindingFlags bindingAttr2 = bindingAttr.RemoveFlag(BindingFlags.Public); while ((type2 = type2.BaseType()) != null) { IEnumerable collection = from f in type2.GetFields(bindingAttr2) where f.IsPrivate select f; initialFields.AddRange(collection); } } public static IEnumerable GetProperties(Type targetType, BindingFlags bindingAttr) { ValidationUtils.ArgumentNotNull(targetType, "targetType"); List list = new List(targetType.GetProperties(bindingAttr)); if (targetType.IsInterface()) { Type[] interfaces = targetType.GetInterfaces(); foreach (Type type in interfaces) { list.AddRange(type.GetProperties(bindingAttr)); } } GetChildPrivateProperties(list, targetType, bindingAttr); for (int j = 0; j < list.Count; j++) { PropertyInfo propertyInfo = list[j]; if (propertyInfo.DeclaringType != targetType) { PropertyInfo value = (PropertyInfo)GetMemberInfoFromType(propertyInfo.DeclaringType, propertyInfo); list[j] = value; } } return list; } public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlags flag) { if ((bindingAttr & flag) != flag) { return bindingAttr; } return bindingAttr ^ flag; } private static void GetChildPrivateProperties(IList initialProperties, Type type, BindingFlags bindingAttr) { Type type2 = type; while ((type2 = type2.BaseType()) != null) { PropertyInfo[] properties = type2.GetProperties(bindingAttr); foreach (PropertyInfo propertyInfo in properties) { PropertyInfo subTypeProperty = propertyInfo; if (!subTypeProperty.IsVirtual()) { if (!IsPublic(subTypeProperty)) { int num = initialProperties.IndexOf((PropertyInfo p) => p.Name == subTypeProperty.Name); if (num == -1) { initialProperties.Add(subTypeProperty); } else if (!IsPublic(initialProperties[num])) { initialProperties[num] = subTypeProperty; } } else if (initialProperties.IndexOf((PropertyInfo p) => p.Name == subTypeProperty.Name && p.DeclaringType == subTypeProperty.DeclaringType) == -1) { initialProperties.Add(subTypeProperty); } } else { Type subTypePropertyDeclaringType = subTypeProperty.GetBaseDefinition()?.DeclaringType ?? subTypeProperty.DeclaringType; if (initialProperties.IndexOf((PropertyInfo p) => p.Name == subTypeProperty.Name && p.IsVirtual() && (p.GetBaseDefinition()?.DeclaringType ?? p.DeclaringType).IsAssignableFrom(subTypePropertyDeclaringType)) == -1) { initialProperties.Add(subTypeProperty); } } } } } public static bool IsMethodOverridden(Type currentType, Type methodDeclaringType, string method) { string method2 = method; Type methodDeclaringType2 = methodDeclaringType; return currentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any((MethodInfo info) => info.Name == method2 && info.DeclaringType != methodDeclaringType2 && info.GetBaseDefinition().DeclaringType == methodDeclaringType2); } public static object? GetDefaultValue(Type type) { if (!type.IsValueType()) { return null; } switch (ConvertUtils.GetTypeCode(type)) { case PrimitiveTypeCode.Boolean: return false; case PrimitiveTypeCode.Char: case PrimitiveTypeCode.SByte: case PrimitiveTypeCode.Int16: case PrimitiveTypeCode.UInt16: case PrimitiveTypeCode.Int32: case PrimitiveTypeCode.Byte: case PrimitiveTypeCode.UInt32: return 0; case PrimitiveTypeCode.Int64: case PrimitiveTypeCode.UInt64: return 0L; case PrimitiveTypeCode.Single: return 0f; case PrimitiveTypeCode.Double: return 0.0; case PrimitiveTypeCode.Decimal: return 0m; case PrimitiveTypeCode.DateTime: return default(DateTime); case PrimitiveTypeCode.BigInteger: return default(BigInteger); case PrimitiveTypeCode.Guid: return default(Guid); case PrimitiveTypeCode.DateTimeOffset: return default(DateTimeOffset); default: if (IsNullable(type)) { return null; } return Activator.CreateInstance(type); } } } internal struct StringBuffer { private char[]? _buffer; private int _position; public int Position { get { return _position; } set { _position = value; } } public bool IsEmpty => _buffer == null; public char[]? InternalBuffer => _buffer; public StringBuffer(IArrayPool? bufferPool, int initalSize) : this(BufferUtils.RentBuffer(bufferPool, initalSize)) { } private StringBuffer(char[] buffer) { _buffer = buffer; _position = 0; } public void Append(IArrayPool? bufferPool, char value) { if (_position == _buffer.Length) { EnsureSize(bufferPool, 1); } _buffer[_position++] = value; } public void Append(IArrayPool? bufferPool, char[] buffer, int startIndex, int count) { if (_position + count >= _buffer.Length) { EnsureSize(bufferPool, count); } Array.Copy(buffer, startIndex, _buffer, _position, count); _position += count; } public void Clear(IArrayPool? bufferPool) { if (_buffer != null) { BufferUtils.ReturnBuffer(bufferPool, _buffer); _buffer = null; } _position = 0; } private void EnsureSize(IArrayPool? bufferPool, int appendLength) { char[] array = BufferUtils.RentBuffer(bufferPool, (_position + appendLength) * 2); if (_buffer != null) { Array.Copy(_buffer, array, _position); BufferUtils.ReturnBuffer(bufferPool, _buffer); } _buffer = array; } public override string ToString() { return ToString(0, _position); } public string ToString(int start, int length) { return new string(_buffer, start, length); } } internal readonly struct StringReference { private readonly char[] _chars; private readonly int _startIndex; private readonly int _length; public char this[int i] => _chars[i]; public char[] Chars => _chars; public int StartIndex => _startIndex; public int Length => _length; public StringReference(char[] chars, int startIndex, int length) { _chars = chars; _startIndex = startIndex; _length = length; } public override string ToString() { return new string(_chars, _startIndex, _length); } } internal static class StringReferenceExtensions { public static int IndexOf(this StringReference s, char c, int startIndex, int length) { int num = Array.IndexOf(s.Chars, c, s.StartIndex + startIndex, length); if (num == -1) { return -1; } return num - s.StartIndex; } public static bool StartsWith(this StringReference s, string text) { if (text.Length > s.Length) { return false; } char[] chars = s.Chars; for (int i = 0; i < text.Length; i++) { if (text[i] != chars[i + s.StartIndex]) { return false; } } return true; } public static bool EndsWith(this StringReference s, string text) { if (text.Length > s.Length) { return false; } char[] chars = s.Chars; int num = s.StartIndex + s.Length - text.Length; for (int i = 0; i < text.Length; i++) { if (text[i] != chars[i + num]) { return false; } } return true; } } internal static class StringUtils { private enum SeparatedCaseState { Start, Lower, Upper, NewWord } public const string CarriageReturnLineFeed = "\r\n"; public const string Empty = ""; public const char CarriageReturn = '\r'; public const char LineFeed = '\n'; public const char Tab = '\t'; public static bool IsNullOrEmpty([NotNullWhen(false)] string? value) { return string.IsNullOrEmpty(value); } public static string FormatWith(this string format, IFormatProvider provider, object? arg0) { return format.FormatWith(provider, new object[1] { arg0 }); } public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1) { return format.FormatWith(provider, new object[2] { arg0, arg1 }); } public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1, object? arg2) { return format.FormatWith(provider, new object[3] { arg0, arg1, arg2 }); } public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1, object? arg2, object? arg3) { return format.FormatWith(provider, new object[4] { arg0, arg1, arg2, arg3 }); } private static string FormatWith(this string format, IFormatProvider provider, params object?[] args) { ValidationUtils.ArgumentNotNull(format, "format"); return string.Format(provider, format, args); } public static bool IsWhiteSpace(string s) { if (s == null) { throw new ArgumentNullException("s"); } if (s.Length == 0) { return false; } for (int i = 0; i < s.Length; i++) { if (!char.IsWhiteSpace(s[i])) { return false; } } return true; } public static StringWriter CreateStringWriter(int capacity) { return new StringWriter(new StringBuilder(capacity), CultureInfo.InvariantCulture); } public static void ToCharAsUnicode(char c, char[] buffer) { buffer[0] = '\\'; buffer[1] = 'u'; buffer[2] = MathUtils.IntToHex(((int)c >> 12) & 0xF); buffer[3] = MathUtils.IntToHex(((int)c >> 8) & 0xF); buffer[4] = MathUtils.IntToHex(((int)c >> 4) & 0xF); buffer[5] = MathUtils.IntToHex(c & 0xF); } public static TSource? ForgivingCaseSensitiveFind(this IEnumerable source, Func valueSelector, string testValue) { Func valueSelector2 = valueSelector; string testValue2 = testValue; if (source == null) { throw new ArgumentNullException("source"); } if (valueSelector2 == null) { throw new ArgumentNullException("valueSelector"); } IEnumerable source2 = source.Where((TSource s) => string.Equals(valueSelector2(s), testValue2, StringComparison.OrdinalIgnoreCase)); if (source2.Count() <= 1) { return source2.SingleOrDefault(); } return source.Where((TSource s) => string.Equals(valueSelector2(s), testValue2, StringComparison.Ordinal)).SingleOrDefault(); } public static string ToCamelCase(string s) { if (IsNullOrEmpty(s) || !char.IsUpper(s[0])) { return s; } char[] array = s.ToCharArray(); for (int i = 0; i < array.Length && (i != 1 || char.IsUpper(array[i])); i++) { bool flag = i + 1 < array.Length; if (i > 0 && flag && !char.IsUpper(array[i + 1])) { if (char.IsSeparator(array[i + 1])) { array[i] = ToLower(array[i]); } break; } array[i] = ToLower(array[i]); } return new string(array); } private static char ToLower(char c) { c = char.ToLower(c, CultureInfo.InvariantCulture); return c; } public static string ToSnakeCase(string s) { return ToSeparatedCase(s, '_'); } public static string ToKebabCase(string s) { return ToSeparatedCase(s, '-'); } private static string ToSeparatedCase(string s, char separator) { if (IsNullOrEmpty(s)) { return s; } StringBuilder stringBuilder = new StringBuilder(); SeparatedCaseState separatedCaseState = SeparatedCaseState.Start; for (int i = 0; i < s.Length; i++) { if (s[i] == ' ') { if (separatedCaseState != 0) { separatedCaseState = SeparatedCaseState.NewWord; } } else if (char.IsUpper(s[i])) { switch (separatedCaseState) { case SeparatedCaseState.Upper: { bool flag = i + 1 < s.Length; if (i > 0 && flag) { char c = s[i + 1]; if (!char.IsUpper(c) && c != separator) { stringBuilder.Append(separator); } } break; } case SeparatedCaseState.Lower: case SeparatedCaseState.NewWord: stringBuilder.Append(separator); break; } char value = char.ToLower(s[i], CultureInfo.InvariantCulture); stringBuilder.Append(value); separatedCaseState = SeparatedCaseState.Upper; } else if (s[i] == separator) { stringBuilder.Append(separator); separatedCaseState = SeparatedCaseState.Start; } else { if (separatedCaseState == SeparatedCaseState.NewWord) { stringBuilder.Append(separator); } stringBuilder.Append(s[i]); separatedCaseState = SeparatedCaseState.Lower; } } return stringBuilder.ToString(); } public static bool IsHighSurrogate(char c) { return char.IsHighSurrogate(c); } public static bool IsLowSurrogate(char c) { return char.IsLowSurrogate(c); } public static int IndexOf(string s, char c) { return s.IndexOf(c, StringComparison.Ordinal); } public static string Replace(string s, string oldValue, string newValue) { return s.Replace(oldValue, newValue, StringComparison.Ordinal); } public static bool StartsWith(this string source, char value) { if (source.Length > 0) { return source[0] == value; } return false; } public static bool EndsWith(this string source, char value) { if (source.Length > 0) { return source[source.Length - 1] == value; } return false; } public static string Trim(this string s, int start, int length) { if (s == null) { throw new ArgumentNullException(); } if (start < 0) { throw new ArgumentOutOfRangeException("start"); } if (length < 0) { throw new ArgumentOutOfRangeException("length"); } int num = start + length - 1; if (num >= s.Length) { throw new ArgumentOutOfRangeException("length"); } while (start < num && char.IsWhiteSpace(s[start])) { start++; } while (num >= start && char.IsWhiteSpace(s[num])) { num--; } return s.Substring(start, num - start + 1); } } internal readonly struct StructMultiKey : IEquatable> { public readonly T1 Value1; public readonly T2 Value2; public StructMultiKey(T1 v1, T2 v2) { Value1 = v1; Value2 = v2; } public override int GetHashCode() { T1 value = Value1; int num = ((value != null) ? value.GetHashCode() : 0); T2 value2 = Value2; return num ^ ((value2 != null) ? value2.GetHashCode() : 0); } public override bool Equals(object? obj) { if (!(obj is StructMultiKey other)) { return false; } return Equals(other); } public bool Equals(StructMultiKey other) { if (object.Equals(Value1, other.Value1)) { return object.Equals(Value2, other.Value2); } return false; } } internal class ThreadSafeStore where TKey : notnull { private readonly ConcurrentDictionary _concurrentStore; private readonly Func _creator; public ThreadSafeStore(Func creator) { ValidationUtils.ArgumentNotNull(creator, "creator"); _creator = creator; _concurrentStore = new ConcurrentDictionary(); } public TValue Get(TKey key) { return _concurrentStore.GetOrAdd(key, _creator); } } internal static class TypeExtensions { public static MethodInfo Method(this Delegate d) { return d.Method; } public static MemberTypes MemberType(this MemberInfo memberInfo) { return memberInfo.MemberType; } public static bool ContainsGenericParameters(this Type type) { return type.ContainsGenericParameters; } public static bool IsInterface(this Type type) { return type.IsInterface; } public static bool IsGenericType(this Type type) { return type.IsGenericType; } public static bool IsGenericTypeDefinition(this Type type) { return type.IsGenericTypeDefinition; } public static Type? BaseType(this Type type) { return type.BaseType; } public static Assembly Assembly(this Type type) { return type.Assembly; } public static bool IsEnum(this Type type) { return type.IsEnum; } public static bool IsClass(this Type type) { return type.IsClass; } public static bool IsSealed(this Type type) { return type.IsSealed; } public static bool IsAbstract(this Type type) { return type.IsAbstract; } public static bool IsVisible(this Type type) { return type.IsVisible; } public static bool IsValueType(this Type type) { return type.IsValueType; } public static bool IsPrimitive(this Type type) { return type.IsPrimitive; } public static bool AssignableToTypeName(this Type type, string fullTypeName, bool searchInterfaces, [NotNullWhen(true)] out Type? match) { Type type2 = type; while (type2 != null) { if (string.Equals(type2.FullName, fullTypeName, StringComparison.Ordinal)) { match = type2; return true; } type2 = type2.BaseType(); } if (searchInterfaces) { Type[] interfaces = type.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { if (string.Equals(interfaces[i].Name, fullTypeName, StringComparison.Ordinal)) { match = type; return true; } } } match = null; return false; } public static bool AssignableToTypeName(this Type type, string fullTypeName, bool searchInterfaces) { Type match; return type.AssignableToTypeName(fullTypeName, searchInterfaces, out match); } public static bool ImplementInterface(this Type type, Type interfaceType) { Type type2 = type; while (type2 != null) { foreach (Type item in (IEnumerable)type2.GetInterfaces()) { if (item == interfaceType || (item != null && item.ImplementInterface(interfaceType))) { return true; } } type2 = type2.BaseType(); } return false; } } internal static class ValidationUtils { public static void ArgumentNotNull([NotNull] object? value, string parameterName) { if (value == null) { throw new ArgumentNullException(parameterName); } } } } namespace Newtonsoft.Json.Serialization { internal static class CachedAttributeGetter where T : Attribute { private static readonly ThreadSafeStore TypeAttributeCache = new ThreadSafeStore(JsonTypeReflector.GetAttribute); public static T? GetAttribute(object type) { return TypeAttributeCache.Get(type); } } internal class CamelCaseNamingStrategy : NamingStrategy { public CamelCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames) { base.ProcessDictionaryKeys = processDictionaryKeys; base.OverrideSpecifiedNames = overrideSpecifiedNames; } public CamelCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) : this(processDictionaryKeys, overrideSpecifiedNames) { base.ProcessExtensionDataNames = processExtensionDataNames; } public CamelCaseNamingStrategy() { } protected override string ResolvePropertyName(string name) { return StringUtils.ToCamelCase(name); } } internal class CamelCasePropertyNamesContractResolver : DefaultContractResolver { private static readonly object TypeContractCacheLock = new object(); private static readonly DefaultJsonNameTable NameTable = new DefaultJsonNameTable(); private static Dictionary, JsonContract>? _contractCache; public CamelCasePropertyNamesContractResolver() { base.NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = true, OverrideSpecifiedNames = true }; } public override JsonContract ResolveContract(Type type) { if (type == null) { throw new ArgumentNullException("type"); } StructMultiKey key = new StructMultiKey(GetType(), type); Dictionary, JsonContract> contractCache = _contractCache; if (contractCache == null || !contractCache.TryGetValue(key, out var value)) { value = CreateContract(type); lock (TypeContractCacheLock) { contractCache = _contractCache; Dictionary, JsonContract> obj = ((contractCache != null) ? new Dictionary, JsonContract>(contractCache) : new Dictionary, JsonContract>()); obj[key] = value; _contractCache = obj; } } return value; } internal override DefaultJsonNameTable GetNameTable() { return NameTable; } } internal class DefaultContractResolver : IContractResolver { internal class EnumerableDictionaryWrapper : IEnumerable>, IEnumerable { private readonly IEnumerable> _e; public EnumerableDictionaryWrapper(IEnumerable> e) { ValidationUtils.ArgumentNotNull(e, "e"); _e = e; } public IEnumerator> GetEnumerator() { foreach (KeyValuePair item in _e) { yield return new KeyValuePair(item.Key, item.Value); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private static readonly IContractResolver _instance = new DefaultContractResolver(); private static readonly string[] BlacklistedTypeNames = new string[3] { "System.IO.DriveInfo", "System.IO.FileInfo", "System.IO.DirectoryInfo" }; private static readonly JsonConverter[] BuiltInConverters = new JsonConverter[10] { new EntityKeyMemberConverter(), new ExpandoObjectConverter(), new XmlNodeConverter(), new BinaryConverter(), new DataSetConverter(), new DataTableConverter(), new DiscriminatedUnionConverter(), new KeyValuePairConverter(), new BsonObjectIdConverter(), new RegexConverter() }; private readonly DefaultJsonNameTable _nameTable = new DefaultJsonNameTable(); private readonly ThreadSafeStore _contractCache; internal static IContractResolver Instance => _instance; public bool DynamicCodeGeneration => JsonTypeReflector.DynamicCodeGeneration; [Obsolete("DefaultMembersSearchFlags is obsolete. To modify the members serialized inherit from DefaultContractResolver and override the GetSerializableMembers method instead.")] public BindingFlags DefaultMembersSearchFlags { get; set; } public bool SerializeCompilerGeneratedMembers { get; set; } public bool IgnoreSerializableInterface { get; set; } public bool IgnoreSerializableAttribute { get; set; } public bool IgnoreIsSpecifiedMembers { get; set; } public bool IgnoreShouldSerializeMembers { get; set; } public NamingStrategy? NamingStrategy { get; set; } public DefaultContractResolver() { IgnoreSerializableAttribute = true; DefaultMembersSearchFlags = BindingFlags.Instance | BindingFlags.Public; _contractCache = new ThreadSafeStore(CreateContract); } public virtual JsonContract ResolveContract(Type type) { ValidationUtils.ArgumentNotNull(type, "type"); return _contractCache.Get(type); } private static bool FilterMembers(MemberInfo member) { if (member is PropertyInfo propertyInfo) { if (ReflectionUtils.IsIndexedProperty(propertyInfo)) { return false; } return !ReflectionUtils.IsByRefLikeType(propertyInfo.PropertyType); } if (member is FieldInfo fieldInfo) { return !ReflectionUtils.IsByRefLikeType(fieldInfo.FieldType); } return true; } protected virtual List GetSerializableMembers(Type objectType) { bool ignoreSerializableAttribute = IgnoreSerializableAttribute; MemberSerialization objectMemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType, ignoreSerializableAttribute); IEnumerable enumerable = from m in ReflectionUtils.GetFieldsAndProperties(objectType, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where !(m is PropertyInfo property) || !ReflectionUtils.IsIndexedProperty(property) select m; List list = new List(); if (objectMemberSerialization != MemberSerialization.Fields) { DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType); List list2 = ReflectionUtils.GetFieldsAndProperties(objectType, DefaultMembersSearchFlags).Where(FilterMembers).ToList(); foreach (MemberInfo item in enumerable) { if (SerializeCompilerGeneratedMembers || !item.IsDefined(typeof(CompilerGeneratedAttribute), inherit: true)) { if (list2.Contains(item)) { list.Add(item); } else if (JsonTypeReflector.GetAttribute(item) != null) { list.Add(item); } else if (JsonTypeReflector.GetAttribute(item) != null) { list.Add(item); } else if (dataContractAttribute != null && JsonTypeReflector.GetAttribute(item) != null) { list.Add(item); } else if (objectMemberSerialization == MemberSerialization.Fields && item.MemberType() == MemberTypes.Field) { list.Add(item); } } } if (objectType.AssignableToTypeName("System.Data.Objects.DataClasses.EntityObject", searchInterfaces: false, out Type _)) { list = list.Where(ShouldSerializeEntityMember).ToList(); } if (typeof(Exception).IsAssignableFrom(objectType)) { list = list.Where((MemberInfo m) => !string.Equals(m.Name, "TargetSite", StringComparison.Ordinal)).ToList(); } } else { foreach (MemberInfo item2 in enumerable) { if (item2 is FieldInfo fieldInfo && !fieldInfo.IsStatic) { list.Add(item2); } } } return list; } private bool ShouldSerializeEntityMember(MemberInfo memberInfo) { if (memberInfo is PropertyInfo propertyInfo && propertyInfo.PropertyType.IsGenericType() && propertyInfo.PropertyType.GetGenericTypeDefinition().FullName == "System.Data.Objects.DataClasses.EntityReference`1") { return false; } return true; } protected virtual JsonObjectContract CreateObjectContract(Type objectType) { JsonObjectContract jsonObjectContract = new JsonObjectContract(objectType); InitializeContract(jsonObjectContract); bool ignoreSerializableAttribute = IgnoreSerializableAttribute; jsonObjectContract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(jsonObjectContract.NonNullableUnderlyingType, ignoreSerializableAttribute); jsonObjectContract.Properties.AddRange(CreateProperties(jsonObjectContract.NonNullableUnderlyingType, jsonObjectContract.MemberSerialization)); Func func = null; JsonObjectAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(jsonObjectContract.NonNullableUnderlyingType); if (cachedAttribute != null) { jsonObjectContract.ItemRequired = cachedAttribute._itemRequired; jsonObjectContract.ItemNullValueHandling = cachedAttribute._itemNullValueHandling; jsonObjectContract.MissingMemberHandling = cachedAttribute._missingMemberHandling; if (cachedAttribute.NamingStrategyType != null) { NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(cachedAttribute); func = (string s) => namingStrategy.GetDictionaryKey(s); } } if (func == null) { func = ResolveExtensionDataName; } jsonObjectContract.ExtensionDataNameResolver = func; if (jsonObjectContract.IsInstantiable) { ConstructorInfo attributeConstructor = GetAttributeConstructor(jsonObjectContract.NonNullableUnderlyingType); if (attributeConstructor != null) { jsonObjectContract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(attributeConstructor); jsonObjectContract.CreatorParameters.AddRange(CreateConstructorParameters(attributeConstructor, jsonObjectContract.Properties)); } else if (jsonObjectContract.MemberSerialization == MemberSerialization.Fields) { if (JsonTypeReflector.FullyTrusted) { jsonObjectContract.DefaultCreator = jsonObjectContract.GetUninitializedObject; } } else if (jsonObjectContract.DefaultCreator == null || jsonObjectContract.DefaultCreatorNonPublic) { ConstructorInfo parameterizedConstructor = GetParameterizedConstructor(jsonObjectContract.NonNullableUnderlyingType); if (parameterizedConstructor != null) { jsonObjectContract.ParameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(parameterizedConstructor); jsonObjectContract.CreatorParameters.AddRange(CreateConstructorParameters(parameterizedConstructor, jsonObjectContract.Properties)); } } else if (jsonObjectContract.NonNullableUnderlyingType.IsValueType()) { ConstructorInfo immutableConstructor = GetImmutableConstructor(jsonObjectContract.NonNullableUnderlyingType, jsonObjectContract.Properties); if (immutableConstructor != null) { jsonObjectContract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(immutableConstructor); jsonObjectContract.CreatorParameters.AddRange(CreateConstructorParameters(immutableConstructor, jsonObjectContract.Properties)); } } } MemberInfo extensionDataMemberForType = GetExtensionDataMemberForType(jsonObjectContract.NonNullableUnderlyingType); if (extensionDataMemberForType != null) { SetExtensionDataDelegates(jsonObjectContract, extensionDataMemberForType); } if (Array.IndexOf(BlacklistedTypeNames, objectType.FullName) != -1) { jsonObjectContract.OnSerializingCallbacks.Add(ThrowUnableToSerializeError); } return jsonObjectContract; } private static void ThrowUnableToSerializeError(object o, StreamingContext context) { throw new JsonSerializationException("Unable to serialize instance of '{0}'.".FormatWith(CultureInfo.InvariantCulture, o.GetType())); } private MemberInfo? GetExtensionDataMemberForType(Type type) { return GetClassHierarchyForType(type).SelectMany(delegate(Type baseType) { List list = new List(); CollectionUtils.AddRange(list, baseType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); CollectionUtils.AddRange(list, baseType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); return list; }).LastOrDefault(delegate(MemberInfo m) { MemberTypes memberTypes = m.MemberType(); if (memberTypes != MemberTypes.Property && memberTypes != MemberTypes.Field) { return false; } if (!m.IsDefined(typeof(JsonExtensionDataAttribute), inherit: false)) { return false; } if (!ReflectionUtils.CanReadMemberValue(m, nonPublic: true)) { throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' must have a getter.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name)); } if (ReflectionUtils.ImplementsGenericDefinition(ReflectionUtils.GetMemberUnderlyingType(m), typeof(IDictionary<, >), out Type implementingType)) { Type obj = implementingType.GetGenericArguments()[0]; Type type2 = implementingType.GetGenericArguments()[1]; if (obj.IsAssignableFrom(typeof(string)) && type2.IsAssignableFrom(typeof(JToken))) { return true; } } throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' type must implement IDictionary.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name)); }); } private static void SetExtensionDataDelegates(JsonObjectContract contract, MemberInfo member) { MemberInfo member2 = member; JsonExtensionDataAttribute attribute = ReflectionUtils.GetAttribute(member2); if (attribute == null) { return; } Type memberUnderlyingType = ReflectionUtils.GetMemberUnderlyingType(member2); ReflectionUtils.ImplementsGenericDefinition(memberUnderlyingType, typeof(IDictionary<, >), out Type implementingType); Type type = implementingType.GetGenericArguments()[0]; Type type2 = implementingType.GetGenericArguments()[1]; Type type3 = ((!ReflectionUtils.IsGenericDefinition(memberUnderlyingType, typeof(IDictionary<, >))) ? memberUnderlyingType : typeof(Dictionary<, >).MakeGenericType(type, type2)); Func getExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(member2); if (attribute.ReadData) { Action setExtensionDataDictionary = (ReflectionUtils.CanSetMemberValue(member2, nonPublic: true, canSetReadOnly: false) ? JsonTypeReflector.ReflectionDelegateFactory.CreateSet(member2) : null); Func createExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(type3); MethodInfo methodInfo = memberUnderlyingType.GetProperty("Item", BindingFlags.Instance | BindingFlags.Public, null, type2, new Type[1] { type }, null)?.GetSetMethod(); if (methodInfo == null) { methodInfo = implementingType.GetProperty("Item", BindingFlags.Instance | BindingFlags.Public, null, type2, new Type[1] { type }, null)?.GetSetMethod(); } MethodCall setExtensionDataDictionaryValue = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(methodInfo); ExtensionDataSetter extensionDataSetter = delegate(object o, string key, object? value) { object obj2 = getExtensionDataDictionary(o); if (obj2 == null) { if (setExtensionDataDictionary == null) { throw new JsonSerializationException("Cannot set value onto extension data member '{0}'. The extension data collection is null and it cannot be set.".FormatWith(CultureInfo.InvariantCulture, member2.Name)); } obj2 = createExtensionDataDictionary(); setExtensionDataDictionary(o, obj2); } setExtensionDataDictionaryValue(obj2, key, value); }; contract.ExtensionDataSetter = extensionDataSetter; } if (attribute.WriteData) { ConstructorInfo method = typeof(EnumerableDictionaryWrapper<, >).MakeGenericType(type, type2).GetConstructors().First(); ObjectConstructor createEnumerableWrapper = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method); ExtensionDataGetter extensionDataGetter = delegate(object o) { object obj = getExtensionDataDictionary(o); return (obj == null) ? null : ((IEnumerable>)createEnumerableWrapper(obj)); }; contract.ExtensionDataGetter = extensionDataGetter; } contract.ExtensionDataValueType = type2; } private ConstructorInfo? GetAttributeConstructor(Type objectType) { IEnumerator enumerator = (from c in objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where c.IsDefined(typeof(JsonConstructorAttribute), inherit: true) select c).GetEnumerator(); if (enumerator.MoveNext()) { ConstructorInfo current = enumerator.Current; if (enumerator.MoveNext()) { throw new JsonException("Multiple constructors with the JsonConstructorAttribute."); } return current; } if (objectType == typeof(Version)) { return objectType.GetConstructor(new Type[4] { typeof(int), typeof(int), typeof(int), typeof(int) }); } return null; } private ConstructorInfo? GetImmutableConstructor(Type objectType, JsonPropertyCollection memberProperties) { IEnumerator enumerator = ((IEnumerable)objectType.GetConstructors()).GetEnumerator(); if (enumerator.MoveNext()) { ConstructorInfo current = enumerator.Current; if (!enumerator.MoveNext()) { ParameterInfo[] parameters = current.GetParameters(); if (parameters.Length != 0) { ParameterInfo[] array = parameters; foreach (ParameterInfo parameterInfo in array) { JsonProperty jsonProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); if (jsonProperty == null || jsonProperty.Writable) { return null; } } return current; } } } return null; } private ConstructorInfo? GetParameterizedConstructor(Type objectType) { ConstructorInfo[] constructors = objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public); if (constructors.Length == 1) { return constructors[0]; } return null; } protected virtual IList CreateConstructorParameters(ConstructorInfo constructor, JsonPropertyCollection memberProperties) { ParameterInfo[] parameters = constructor.GetParameters(); JsonPropertyCollection jsonPropertyCollection = new JsonPropertyCollection(constructor.DeclaringType); ParameterInfo[] array = parameters; foreach (ParameterInfo parameterInfo in array) { if (parameterInfo.Name == null) { continue; } JsonProperty jsonProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); if (jsonProperty != null || parameterInfo.Name != null) { JsonProperty jsonProperty2 = CreatePropertyFromConstructorParameter(jsonProperty, parameterInfo); if (jsonProperty2 != null) { jsonPropertyCollection.AddProperty(jsonProperty2); } } } return jsonPropertyCollection; } private JsonProperty? MatchProperty(JsonPropertyCollection properties, string name, Type type) { if (name == null) { return null; } JsonProperty closestMatchProperty = properties.GetClosestMatchProperty(name); if (closestMatchProperty == null || closestMatchProperty.PropertyType != type) { return null; } return closestMatchProperty; } protected virtual JsonProperty CreatePropertyFromConstructorParameter(JsonProperty? matchingMemberProperty, ParameterInfo parameterInfo) { JsonProperty jsonProperty = new JsonProperty(); jsonProperty.PropertyType = parameterInfo.ParameterType; jsonProperty.AttributeProvider = new ReflectionAttributeProvider(parameterInfo); SetPropertySettingsFromAttributes(jsonProperty, parameterInfo, parameterInfo.Name, parameterInfo.Member.DeclaringType, MemberSerialization.OptOut, out var _); jsonProperty.Readable = false; jsonProperty.Writable = true; if (matchingMemberProperty != null) { jsonProperty.PropertyName = ((jsonProperty.PropertyName != parameterInfo.Name) ? jsonProperty.PropertyName : matchingMemberProperty.PropertyName); jsonProperty.Converter = jsonProperty.Converter ?? matchingMemberProperty.Converter; if (!jsonProperty._hasExplicitDefaultValue && matchingMemberProperty._hasExplicitDefaultValue) { jsonProperty.DefaultValue = matchingMemberProperty.DefaultValue; } jsonProperty._required = jsonProperty._required ?? matchingMemberProperty._required; jsonProperty.IsReference = jsonProperty.IsReference ?? matchingMemberProperty.IsReference; jsonProperty.NullValueHandling = jsonProperty.NullValueHandling ?? matchingMemberProperty.NullValueHandling; jsonProperty.DefaultValueHandling = jsonProperty.DefaultValueHandling ?? matchingMemberProperty.DefaultValueHandling; jsonProperty.ReferenceLoopHandling = jsonProperty.ReferenceLoopHandling ?? matchingMemberProperty.ReferenceLoopHandling; jsonProperty.ObjectCreationHandling = jsonProperty.ObjectCreationHandling ?? matchingMemberProperty.ObjectCreationHandling; jsonProperty.TypeNameHandling = jsonProperty.TypeNameHandling ?? matchingMemberProperty.TypeNameHandling; } return jsonProperty; } protected virtual JsonConverter? ResolveContractConverter(Type objectType) { return JsonTypeReflector.GetJsonConverter(objectType); } private Func GetDefaultCreator(Type createdType) { return JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(createdType); } private void InitializeContract(JsonContract contract) { JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(contract.NonNullableUnderlyingType); if (cachedAttribute != null) { contract.IsReference = cachedAttribute._isReference; } else { DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(contract.NonNullableUnderlyingType); if (dataContractAttribute != null && dataContractAttribute.IsReference) { contract.IsReference = true; } } contract.Converter = ResolveContractConverter(contract.NonNullableUnderlyingType); contract.InternalConverter = JsonSerializer.GetMatchingConverter(BuiltInConverters, contract.NonNullableUnderlyingType); if (contract.IsInstantiable && (ReflectionUtils.HasDefaultConstructor(contract.CreatedType, nonPublic: true) || contract.CreatedType.IsValueType())) { contract.DefaultCreator = GetDefaultCreator(contract.CreatedType); contract.DefaultCreatorNonPublic = !contract.CreatedType.IsValueType() && ReflectionUtils.GetDefaultConstructor(contract.CreatedType) == null; } ResolveCallbackMethods(contract, contract.NonNullableUnderlyingType); } private void ResolveCallbackMethods(JsonContract contract, Type t) { GetCallbackMethodsForType(t, out List onSerializing, out List onSerialized, out List onDeserializing, out List onDeserialized, out List onError); if (onSerializing != null) { contract.OnSerializingCallbacks.AddRange(onSerializing); } if (onSerialized != null) { contract.OnSerializedCallbacks.AddRange(onSerialized); } if (onDeserializing != null) { contract.OnDeserializingCallbacks.AddRange(onDeserializing); } if (onDeserialized != null) { contract.OnDeserializedCallbacks.AddRange(onDeserialized); } if (onError != null) { contract.OnErrorCallbacks.AddRange(onError); } } private void GetCallbackMethodsForType(Type type, out List? onSerializing, out List? onSerialized, out List? onDeserializing, out List? onDeserialized, out List? onError) { onSerializing = null; onSerialized = null; onDeserializing = null; onDeserialized = null; onError = null; foreach (Type item in GetClassHierarchyForType(type)) { MethodInfo currentCallback = null; MethodInfo currentCallback2 = null; MethodInfo currentCallback3 = null; MethodInfo currentCallback4 = null; MethodInfo currentCallback5 = null; bool flag = ShouldSkipSerializing(item); bool flag2 = ShouldSkipDeserialized(item); MethodInfo[] methods = item.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!methodInfo.ContainsGenericParameters) { Type prevAttributeType = null; ParameterInfo[] parameters = methodInfo.GetParameters(); if (!flag && IsValidCallback(methodInfo, parameters, typeof(OnSerializingAttribute), currentCallback, ref prevAttributeType)) { onSerializing = onSerializing ?? new List(); onSerializing.Add(JsonContract.CreateSerializationCallback(methodInfo)); currentCallback = methodInfo; } if (IsValidCallback(methodInfo, parameters, typeof(OnSerializedAttribute), currentCallback2, ref prevAttributeType)) { onSerialized = onSerialized ?? new List(); onSerialized.Add(JsonContract.CreateSerializationCallback(methodInfo)); currentCallback2 = methodInfo; } if (IsValidCallback(methodInfo, parameters, typeof(OnDeserializingAttribute), currentCallback3, ref prevAttributeType)) { onDeserializing = onDeserializing ?? new List(); onDeserializing.Add(JsonContract.CreateSerializationCallback(methodInfo)); currentCallback3 = methodInfo; } if (!flag2 && IsValidCallback(methodInfo, parameters, typeof(OnDeserializedAttribute), currentCallback4, ref prevAttributeType)) { onDeserialized = onDeserialized ?? new List(); onDeserialized.Add(JsonContract.CreateSerializationCallback(methodInfo)); currentCallback4 = methodInfo; } if (IsValidCallback(methodInfo, parameters, typeof(OnErrorAttribute), currentCallback5, ref prevAttributeType)) { onError = onError ?? new List(); onError.Add(JsonContract.CreateSerializationErrorCallback(methodInfo)); currentCallback5 = methodInfo; } } } } } private static bool IsConcurrentOrObservableCollection(Type t) { if (t.IsGenericType()) { switch (t.GetGenericTypeDefinition().FullName) { case "System.Collections.Concurrent.ConcurrentQueue`1": case "System.Collections.Concurrent.ConcurrentStack`1": case "System.Collections.Concurrent.ConcurrentBag`1": case "System.Collections.Concurrent.ConcurrentDictionary`2": case "System.Collections.ObjectModel.ObservableCollection`1": return true; } } return false; } private static bool ShouldSkipDeserialized(Type t) { if (IsConcurrentOrObservableCollection(t)) { return true; } if (t.Name == "FSharpSet`1" || t.Name == "FSharpMap`2") { return true; } return false; } private static bool ShouldSkipSerializing(Type t) { if (IsConcurrentOrObservableCollection(t)) { return true; } if (t.Name == "FSharpSet`1" || t.Name == "FSharpMap`2") { return true; } return false; } private List GetClassHierarchyForType(Type type) { List list = new List(); Type type2 = type; while (type2 != null && type2 != typeof(object)) { list.Add(type2); type2 = type2.BaseType(); } list.Reverse(); return list; } protected virtual JsonDictionaryContract CreateDictionaryContract(Type objectType) { JsonDictionaryContract jsonDictionaryContract = new JsonDictionaryContract(objectType); InitializeContract(jsonDictionaryContract); JsonContainerAttribute attribute = JsonTypeReflector.GetAttribute(objectType); if (attribute?.NamingStrategyType != null) { NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(attribute); jsonDictionaryContract.DictionaryKeyResolver = (string s) => namingStrategy.GetDictionaryKey(s); } else { jsonDictionaryContract.DictionaryKeyResolver = ResolveDictionaryKey; } ConstructorInfo attributeConstructor = GetAttributeConstructor(jsonDictionaryContract.NonNullableUnderlyingType); if (attributeConstructor != null) { ParameterInfo[] parameters = attributeConstructor.GetParameters(); Type type = ((jsonDictionaryContract.DictionaryKeyType != null && jsonDictionaryContract.DictionaryValueType != null) ? typeof(IEnumerable<>).MakeGenericType(typeof(KeyValuePair<, >).MakeGenericType(jsonDictionaryContract.DictionaryKeyType, jsonDictionaryContract.DictionaryValueType)) : typeof(IDictionary)); if (parameters.Length == 0) { jsonDictionaryContract.HasParameterizedCreator = false; } else { if (parameters.Length != 1 || !type.IsAssignableFrom(parameters[0].ParameterType)) { throw new JsonException("Constructor for '{0}' must have no parameters or a single parameter that implements '{1}'.".FormatWith(CultureInfo.InvariantCulture, jsonDictionaryContract.UnderlyingType, type)); } jsonDictionaryContract.HasParameterizedCreator = true; } jsonDictionaryContract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(attributeConstructor); } return jsonDictionaryContract; } protected virtual JsonArrayContract CreateArrayContract(Type objectType) { JsonArrayContract jsonArrayContract = new JsonArrayContract(objectType); InitializeContract(jsonArrayContract); ConstructorInfo attributeConstructor = GetAttributeConstructor(jsonArrayContract.NonNullableUnderlyingType); if (attributeConstructor != null) { ParameterInfo[] parameters = attributeConstructor.GetParameters(); Type type = ((jsonArrayContract.CollectionItemType != null) ? typeof(IEnumerable<>).MakeGenericType(jsonArrayContract.CollectionItemType) : typeof(IEnumerable)); if (parameters.Length == 0) { jsonArrayContract.HasParameterizedCreator = false; } else { if (parameters.Length != 1 || !type.IsAssignableFrom(parameters[0].ParameterType)) { throw new JsonException("Constructor for '{0}' must have no parameters or a single parameter that implements '{1}'.".FormatWith(CultureInfo.InvariantCulture, jsonArrayContract.UnderlyingType, type)); } jsonArrayContract.HasParameterizedCreator = true; } jsonArrayContract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(attributeConstructor); } return jsonArrayContract; } protected virtual JsonPrimitiveContract CreatePrimitiveContract(Type objectType) { JsonPrimitiveContract jsonPrimitiveContract = new JsonPrimitiveContract(objectType); InitializeContract(jsonPrimitiveContract); return jsonPrimitiveContract; } protected virtual JsonLinqContract CreateLinqContract(Type objectType) { JsonLinqContract jsonLinqContract = new JsonLinqContract(objectType); InitializeContract(jsonLinqContract); return jsonLinqContract; } protected virtual JsonISerializableContract CreateISerializableContract(Type objectType) { JsonISerializableContract jsonISerializableContract = new JsonISerializableContract(objectType); InitializeContract(jsonISerializableContract); if (jsonISerializableContract.IsInstantiable) { ConstructorInfo constructor = jsonISerializableContract.NonNullableUnderlyingType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(SerializationInfo), typeof(StreamingContext) }, null); if (constructor != null) { ObjectConstructor iSerializableCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); jsonISerializableContract.ISerializableCreator = iSerializableCreator; } } return jsonISerializableContract; } protected virtual JsonDynamicContract CreateDynamicContract(Type objectType) { JsonDynamicContract jsonDynamicContract = new JsonDynamicContract(objectType); InitializeContract(jsonDynamicContract); JsonContainerAttribute attribute = JsonTypeReflector.GetAttribute(objectType); if (attribute?.NamingStrategyType != null) { NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(attribute); jsonDynamicContract.PropertyNameResolver = (string s) => namingStrategy.GetDictionaryKey(s); } else { jsonDynamicContract.PropertyNameResolver = ResolveDictionaryKey; } jsonDynamicContract.Properties.AddRange(CreateProperties(objectType, MemberSerialization.OptOut)); return jsonDynamicContract; } protected virtual JsonStringContract CreateStringContract(Type objectType) { JsonStringContract jsonStringContract = new JsonStringContract(objectType); InitializeContract(jsonStringContract); return jsonStringContract; } protected virtual JsonContract CreateContract(Type objectType) { Type t = ReflectionUtils.EnsureNotByRefType(objectType); if (IsJsonPrimitiveType(t)) { return CreatePrimitiveContract(objectType); } t = ReflectionUtils.EnsureNotNullableType(t); JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(t); if (cachedAttribute is JsonObjectAttribute) { return CreateObjectContract(objectType); } if (cachedAttribute is JsonArrayAttribute) { return CreateArrayContract(objectType); } if (cachedAttribute is JsonDictionaryAttribute) { return CreateDictionaryContract(objectType); } if (t == typeof(JToken) || t.IsSubclassOf(typeof(JToken))) { return CreateLinqContract(objectType); } if (CollectionUtils.IsDictionaryType(t)) { return CreateDictionaryContract(objectType); } if (typeof(IEnumerable).IsAssignableFrom(t)) { return CreateArrayContract(objectType); } if (CanConvertToString(t)) { return CreateStringContract(objectType); } if (!IgnoreSerializableInterface && typeof(ISerializable).IsAssignableFrom(t) && JsonTypeReflector.IsSerializable(t)) { return CreateISerializableContract(objectType); } if (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(t)) { return CreateDynamicContract(objectType); } if (IsIConvertible(t)) { return CreatePrimitiveContract(t); } return CreateObjectContract(objectType); } internal static bool IsJsonPrimitiveType(Type t) { PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(t); if (typeCode != 0) { return typeCode != PrimitiveTypeCode.Object; } return false; } internal static bool IsIConvertible(Type t) { if (typeof(IConvertible).IsAssignableFrom(t) || (ReflectionUtils.IsNullableType(t) && typeof(IConvertible).IsAssignableFrom(Nullable.GetUnderlyingType(t)))) { return !typeof(JToken).IsAssignableFrom(t); } return false; } internal static bool CanConvertToString(Type type) { if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out TypeConverter _)) { return true; } if (type == typeof(Type) || type.IsSubclassOf(typeof(Type))) { return true; } if (type == typeof(DateOnly) || type == typeof(TimeOnly)) { return true; } return false; } private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameters, Type attributeType, MethodInfo? currentCallback, ref Type? prevAttributeType) { if (!method.IsDefined(attributeType, inherit: false)) { return false; } if (currentCallback != null) { throw new JsonException("Invalid attribute. Both '{0}' and '{1}' in type '{2}' have '{3}'.".FormatWith(CultureInfo.InvariantCulture, method, currentCallback, GetClrTypeFullName(method.DeclaringType), attributeType)); } if (prevAttributeType != null) { throw new JsonException("Invalid Callback. Method '{3}' in type '{2}' has both '{0}' and '{1}'.".FormatWith(CultureInfo.InvariantCulture, prevAttributeType, attributeType, GetClrTypeFullName(method.DeclaringType), method)); } if (method.IsVirtual) { throw new JsonException("Virtual Method '{0}' of type '{1}' cannot be marked with '{2}' attribute.".FormatWith(CultureInfo.InvariantCulture, method, GetClrTypeFullName(method.DeclaringType), attributeType)); } if (method.ReturnType != typeof(void)) { throw new JsonException("Serialization Callback '{1}' in type '{0}' must return void.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method)); } if (attributeType == typeof(OnErrorAttribute)) { if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) || parameters[1].ParameterType != typeof(ErrorContext)) { throw new JsonException("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext), typeof(ErrorContext))); } } else if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(StreamingContext)) { throw new JsonException("Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext))); } prevAttributeType = attributeType; return true; } internal static string GetClrTypeFullName(Type type) { if (type.IsGenericTypeDefinition() || !type.ContainsGenericParameters()) { return type.FullName; } return "{0}.{1}".FormatWith(CultureInfo.InvariantCulture, type.Namespace, type.Name); } protected virtual IList CreateProperties(Type type, MemberSerialization memberSerialization) { List obj = GetSerializableMembers(type) ?? throw new JsonSerializationException("Null collection of serializable members returned."); DefaultJsonNameTable nameTable = GetNameTable(); JsonPropertyCollection jsonPropertyCollection = new JsonPropertyCollection(type); foreach (MemberInfo item in obj) { JsonProperty jsonProperty = CreateProperty(item, memberSerialization); if (jsonProperty != null) { lock (nameTable) { jsonProperty.PropertyName = nameTable.Add(jsonProperty.PropertyName); } jsonPropertyCollection.AddProperty(jsonProperty); } } return jsonPropertyCollection.OrderBy((JsonProperty p) => p.Order ?? (-1)).ToList(); } internal virtual DefaultJsonNameTable GetNameTable() { return _nameTable; } protected virtual IValueProvider CreateMemberValueProvider(MemberInfo member) { return new ExpressionValueProvider(member); } protected virtual JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty jsonProperty = new JsonProperty(); jsonProperty.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member); jsonProperty.DeclaringType = member.DeclaringType; jsonProperty.ValueProvider = CreateMemberValueProvider(member); jsonProperty.AttributeProvider = new ReflectionAttributeProvider(member); SetPropertySettingsFromAttributes(jsonProperty, member, member.Name, member.DeclaringType, memberSerialization, out var allowNonPublicAccess); if (memberSerialization != MemberSerialization.Fields) { jsonProperty.Readable = ReflectionUtils.CanReadMemberValue(member, allowNonPublicAccess); jsonProperty.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess, jsonProperty.HasMemberAttribute); } else { jsonProperty.Readable = true; jsonProperty.Writable = true; } if (!IgnoreShouldSerializeMembers) { jsonProperty.ShouldSerialize = CreateShouldSerializeTest(member); } if (!IgnoreIsSpecifiedMembers) { SetIsSpecifiedActions(jsonProperty, member, allowNonPublicAccess); } return jsonProperty; } private void SetPropertySettingsFromAttributes(JsonProperty property, object attributeProvider, string name, Type declaringType, MemberSerialization memberSerialization, out bool allowNonPublicAccess) { DataContractAttribute? dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(declaringType); MemberInfo memberInfo = attributeProvider as MemberInfo; DataMemberAttribute dataMemberAttribute = ((dataContractAttribute == null || !(memberInfo != null)) ? null : JsonTypeReflector.GetDataMemberAttribute(memberInfo)); JsonPropertyAttribute attribute = JsonTypeReflector.GetAttribute(attributeProvider); JsonRequiredAttribute? attribute2 = JsonTypeReflector.GetAttribute(attributeProvider); string text; bool hasSpecifiedName; if (attribute != null && attribute.PropertyName != null) { text = attribute.PropertyName; hasSpecifiedName = true; } else if (dataMemberAttribute != null && dataMemberAttribute.Name != null) { text = dataMemberAttribute.Name; hasSpecifiedName = true; } else { text = name; hasSpecifiedName = false; } JsonContainerAttribute attribute3 = JsonTypeReflector.GetAttribute(declaringType); NamingStrategy namingStrategy = ((attribute?.NamingStrategyType != null) ? JsonTypeReflector.CreateNamingStrategyInstance(attribute.NamingStrategyType, attribute.NamingStrategyParameters) : ((!(attribute3?.NamingStrategyType != null)) ? NamingStrategy : JsonTypeReflector.GetContainerNamingStrategy(attribute3))); if (namingStrategy != null) { property.PropertyName = namingStrategy.GetPropertyName(text, hasSpecifiedName); } else { property.PropertyName = ResolvePropertyName(text); } property.UnderlyingName = name; bool flag = false; if (attribute != null) { property._required = attribute._required; property.Order = attribute._order; property.DefaultValueHandling = attribute._defaultValueHandling; flag = true; property.NullValueHandling = attribute._nullValueHandling; property.ReferenceLoopHandling = attribute._referenceLoopHandling; property.ObjectCreationHandling = attribute._objectCreationHandling; property.TypeNameHandling = attribute._typeNameHandling; property.IsReference = attribute._isReference; property.ItemIsReference = attribute._itemIsReference; property.ItemConverter = ((attribute.ItemConverterType != null) ? JsonTypeReflector.CreateJsonConverterInstance(attribute.ItemConverterType, attribute.ItemConverterParameters) : null); property.ItemReferenceLoopHandling = attribute._itemReferenceLoopHandling; property.ItemTypeNameHandling = attribute._itemTypeNameHandling; } else { property.NullValueHandling = null; property.ReferenceLoopHandling = null; property.ObjectCreationHandling = null; property.TypeNameHandling = null; property.IsReference = null; property.ItemIsReference = null; property.ItemConverter = null; property.ItemReferenceLoopHandling = null; property.ItemTypeNameHandling = null; if (dataMemberAttribute != null) { property._required = (dataMemberAttribute.IsRequired ? Required.AllowNull : Required.Default); property.Order = ((dataMemberAttribute.Order != -1) ? new int?(dataMemberAttribute.Order) : null); property.DefaultValueHandling = ((!dataMemberAttribute.EmitDefaultValue) ? new DefaultValueHandling?(DefaultValueHandling.Ignore) : null); flag = true; } } if (attribute2 != null) { property._required = Required.Always; flag = true; } property.HasMemberAttribute = flag; bool flag2 = JsonTypeReflector.GetAttribute(attributeProvider) != null || JsonTypeReflector.GetAttribute(attributeProvider) != null || JsonTypeReflector.IsNonSerializable(attributeProvider); if (memberSerialization != MemberSerialization.OptIn) { bool flag3 = false; flag3 = JsonTypeReflector.GetAttribute(attributeProvider) != null; property.Ignored = flag2 || flag3; } else { property.Ignored = flag2 || !flag; } property.Converter = JsonTypeReflector.GetJsonConverter(attributeProvider); DefaultValueAttribute attribute4 = JsonTypeReflector.GetAttribute(attributeProvider); if (attribute4 != null) { property.DefaultValue = attribute4.Value; } allowNonPublicAccess = false; if ((DefaultMembersSearchFlags & BindingFlags.NonPublic) == BindingFlags.NonPublic) { allowNonPublicAccess = true; } if (flag) { allowNonPublicAccess = true; } if (memberSerialization == MemberSerialization.Fields) { allowNonPublicAccess = true; } } private Predicate? CreateShouldSerializeTest(MemberInfo member) { MethodInfo method = member.DeclaringType.GetMethod("ShouldSerialize" + member.Name, ReflectionUtils.EmptyTypes); if (method == null || method.ReturnType != typeof(bool)) { return null; } MethodCall shouldSerializeCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(method); return (object o) => (bool)shouldSerializeCall(o); } private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member, bool allowNonPublicAccess) { MemberInfo memberInfo = member.DeclaringType.GetProperty(member.Name + "Specified", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (memberInfo == null) { memberInfo = member.DeclaringType.GetField(member.Name + "Specified", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (!(memberInfo == null) && !(ReflectionUtils.GetMemberUnderlyingType(memberInfo) != typeof(bool))) { Func specifiedPropertyGet = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(memberInfo); property.GetIsSpecified = (object o) => (bool)specifiedPropertyGet(o); if (ReflectionUtils.CanSetMemberValue(memberInfo, allowNonPublicAccess, canSetReadOnly: false)) { property.SetIsSpecified = JsonTypeReflector.ReflectionDelegateFactory.CreateSet(memberInfo); } } } protected virtual string ResolvePropertyName(string propertyName) { if (NamingStrategy != null) { return NamingStrategy.GetPropertyName(propertyName, hasSpecifiedName: false); } return propertyName; } protected virtual string ResolveExtensionDataName(string extensionDataName) { if (NamingStrategy != null) { return NamingStrategy.GetExtensionDataName(extensionDataName); } return extensionDataName; } protected virtual string ResolveDictionaryKey(string dictionaryKey) { if (NamingStrategy != null) { return NamingStrategy.GetDictionaryKey(dictionaryKey); } return ResolvePropertyName(dictionaryKey); } public string GetResolvedPropertyName(string propertyName) { return ResolvePropertyName(propertyName); } } internal class DefaultNamingStrategy : NamingStrategy { protected override string ResolvePropertyName(string name) { return name; } } internal class DefaultReferenceResolver : IReferenceResolver { private int _referenceCount; private BidirectionalDictionary GetMappings(object context) { JsonSerializerInternalBase jsonSerializerInternalBase = context as JsonSerializerInternalBase; if (jsonSerializerInternalBase == null) { if (!(context is JsonSerializerProxy jsonSerializerProxy)) { throw new JsonException("The DefaultReferenceResolver can only be used internally."); } jsonSerializerInternalBase = jsonSerializerProxy.GetInternalSerializer(); } return jsonSerializerInternalBase.DefaultReferenceMappings; } public object ResolveReference(object context, string reference) { GetMappings(context).TryGetByFirst(reference, out object second); return second; } public string GetReference(object context, object value) { BidirectionalDictionary mappings = GetMappings(context); if (!mappings.TryGetBySecond(value, out string first)) { _referenceCount++; first = _referenceCount.ToString(CultureInfo.InvariantCulture); mappings.Set(first, value); } return first; } public void AddReference(object context, string reference, object value) { GetMappings(context).Set(reference, value); } public bool IsReferenced(object context, object value) { string first; return GetMappings(context).TryGetBySecond(value, out first); } } internal class DefaultSerializationBinder : SerializationBinder, ISerializationBinder { internal static readonly DefaultSerializationBinder Instance = new DefaultSerializationBinder(); private readonly ThreadSafeStore, Type> _typeCache; public DefaultSerializationBinder() { _typeCache = new ThreadSafeStore, Type>(GetTypeFromTypeNameKey); } private Type GetTypeFromTypeNameKey(StructMultiKey typeNameKey) { string value = typeNameKey.Value1; string value2 = typeNameKey.Value2; if (value != null) { Assembly assembly = Assembly.LoadWithPartialName(value); if (assembly == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly2 in assemblies) { if (assembly2.FullName == value || assembly2.GetName().Name == value) { assembly = assembly2; break; } } } if (assembly == null) { throw new JsonSerializationException("Could not load assembly '{0}'.".FormatWith(CultureInfo.InvariantCulture, value)); } Type type = assembly.GetType(value2); if (type == null) { if (StringUtils.IndexOf(value2, '`') >= 0) { try { type = GetGenericTypeFromTypeName(value2, assembly); } catch (Exception innerException) { throw new JsonSerializationException("Could not find type '{0}' in assembly '{1}'.".FormatWith(CultureInfo.InvariantCulture, value2, assembly.FullName), innerException); } } if (type == null) { throw new JsonSerializationException("Could not find type '{0}' in assembly '{1}'.".FormatWith(CultureInfo.InvariantCulture, value2, assembly.FullName)); } } return type; } return Type.GetType(value2); } private Type? GetGenericTypeFromTypeName(string typeName, Assembly assembly) { Type result = null; int num = StringUtils.IndexOf(typeName, '['); if (num >= 0) { string name = typeName.Substring(0, num); Type type = assembly.GetType(name); if (type != null) { List list = new List(); int num2 = 0; int num3 = 0; int num4 = typeName.Length - 1; for (int i = num + 1; i < num4; i++) { switch (typeName[i]) { case '[': if (num2 == 0) { num3 = i + 1; } num2++; break; case ']': num2--; if (num2 == 0) { StructMultiKey typeNameKey = ReflectionUtils.SplitFullyQualifiedTypeName(typeName.Substring(num3, i - num3)); list.Add(GetTypeByName(typeNameKey)); } break; } } result = type.MakeGenericType(list.ToArray()); } } return result; } private Type GetTypeByName(StructMultiKey typeNameKey) { return _typeCache.Get(typeNameKey); } public override Type BindToType(string? assemblyName, string typeName) { return GetTypeByName(new StructMultiKey(assemblyName, typeName)); } public override void BindToName(Type serializedType, out string? assemblyName, out string? typeName) { assemblyName = serializedType.Assembly.FullName; typeName = serializedType.FullName; } } internal class DiagnosticsTraceWriter : ITraceWriter { public TraceLevel LevelFilter { get; set; } private TraceEventType GetTraceEventType(TraceLevel level) { return level switch { TraceLevel.Error => TraceEventType.Error, TraceLevel.Warning => TraceEventType.Warning, TraceLevel.Info => TraceEventType.Information, TraceLevel.Verbose => TraceEventType.Verbose, _ => throw new ArgumentOutOfRangeException("level"), }; } public void Trace(TraceLevel level, string message, Exception? ex) { if (level == TraceLevel.Off) { return; } TraceEventCache eventCache = new TraceEventCache(); TraceEventType traceEventType = GetTraceEventType(level); foreach (TraceListener listener in System.Diagnostics.Trace.Listeners) { if (!listener.IsThreadSafe) { lock (listener) { listener.TraceEvent(eventCache, "Newtonsoft.Json", traceEventType, 0, message); } } else { listener.TraceEvent(eventCache, "Newtonsoft.Json", traceEventType, 0, message); } if (System.Diagnostics.Trace.AutoFlush) { listener.Flush(); } } } } internal class DynamicValueProvider : IValueProvider { private readonly MemberInfo _memberInfo; private Func? _getter; private Action? _setter; public DynamicValueProvider(MemberInfo memberInfo) { ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo"); _memberInfo = memberInfo; } public void SetValue(object target, object? value) { try { if (_setter == null) { _setter = DynamicReflectionDelegateFactory.Instance.CreateSet(_memberInfo); } _setter(target, value); } catch (Exception innerException) { throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } public object? GetValue(object target) { try { if (_getter == null) { _getter = DynamicReflectionDelegateFactory.Instance.CreateGet(_memberInfo); } return _getter(target); } catch (Exception innerException) { throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } } internal class ErrorContext { internal bool Traced { get; set; } public Exception Error { get; } public object? OriginalObject { get; } public object? Member { get; } public string Path { get; } public bool Handled { get; set; } internal ErrorContext(object? originalObject, object? member, string path, Exception error) { OriginalObject = originalObject; Member = member; Error = error; Path = path; } } internal class ErrorEventArgs : EventArgs { public object? CurrentObject { get; } public ErrorContext ErrorContext { get; } public ErrorEventArgs(object? currentObject, ErrorContext errorContext) { CurrentObject = currentObject; ErrorContext = errorContext; } } internal class ExpressionValueProvider : IValueProvider { private readonly MemberInfo _memberInfo; private Func? _getter; private Action? _setter; public ExpressionValueProvider(MemberInfo memberInfo) { ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo"); _memberInfo = memberInfo; } public void SetValue(object target, object? value) { try { if (_setter == null) { _setter = ExpressionReflectionDelegateFactory.Instance.CreateSet(_memberInfo); } _setter(target, value); } catch (Exception innerException) { throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } public object? GetValue(object target) { try { if (_getter == null) { _getter = ExpressionReflectionDelegateFactory.Instance.CreateGet(_memberInfo); } return _getter(target); } catch (Exception innerException) { throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } } internal interface IAttributeProvider { IList GetAttributes(bool inherit); IList GetAttributes(Type attributeType, bool inherit); } internal interface IContractResolver { JsonContract ResolveContract(Type type); } internal interface IReferenceResolver { object ResolveReference(object context, string reference); string GetReference(object context, object value); bool IsReferenced(object context, object value); void AddReference(object context, string reference, object value); } internal interface ISerializationBinder { Type BindToType(string? assemblyName, string typeName); void BindToName(Type serializedType, out string? assemblyName, out string? typeName); } internal interface ITraceWriter { TraceLevel LevelFilter { get; } void Trace(TraceLevel level, string message, Exception? ex); } internal interface IValueProvider { void SetValue(object target, object? value); object? GetValue(object target); } internal class JsonArrayContract : JsonContainerContract { private readonly Type? _genericCollectionDefinitionType; private Type? _genericWrapperType; private ObjectConstructor? _genericWrapperCreator; private Func? _genericTemporaryCollectionCreator; private readonly ConstructorInfo? _parameterizedConstructor; private ObjectConstructor? _parameterizedCreator; private ObjectConstructor? _overrideCreator; public Type? CollectionItemType { get; } public bool IsMultidimensionalArray { get; } internal bool IsArray { get; } internal bool ShouldCreateWrapper { get; } internal bool CanDeserialize { get; private set; } internal ObjectConstructor? ParameterizedCreator { get { if (_parameterizedCreator == null && _parameterizedConstructor != null) { _parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(_parameterizedConstructor); } return _parameterizedCreator; } } public ObjectConstructor? OverrideCreator { get { return _overrideCreator; } set { _overrideCreator = value; CanDeserialize = true; } } public bool HasParameterizedCreator { get; set; } internal bool HasParameterizedCreatorInternal { get { if (!HasParameterizedCreator && _parameterizedCreator == null) { return _parameterizedConstructor != null; } return true; } } public JsonArrayContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Array; IsArray = base.CreatedType.IsArray || (NonNullableUnderlyingType.IsGenericType() && NonNullableUnderlyingType.GetGenericTypeDefinition().FullName == "System.Linq.EmptyPartition`1"); bool canDeserialize; Type implementingType; if (IsArray) { CollectionItemType = ReflectionUtils.GetCollectionItemType(base.UnderlyingType); IsReadOnlyOrFixedSize = true; _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); canDeserialize = true; IsMultidimensionalArray = base.CreatedType.IsArray && base.UnderlyingType.GetArrayRank() > 1; } else if (typeof(IList).IsAssignableFrom(NonNullableUnderlyingType)) { if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType)) { CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0]; } else { CollectionItemType = ReflectionUtils.GetCollectionItemType(NonNullableUnderlyingType); } if (NonNullableUnderlyingType == typeof(IList)) { base.CreatedType = typeof(List); } if (CollectionItemType != null) { _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType); } IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(NonNullableUnderlyingType, typeof(ReadOnlyCollection<>)); canDeserialize = true; } else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType)) { CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0]; if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>)) || ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IList<>))) { base.CreatedType = typeof(List<>).MakeGenericType(CollectionItemType); } if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(ISet<>))) { base.CreatedType = typeof(HashSet<>).MakeGenericType(CollectionItemType); } _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType); canDeserialize = true; ShouldCreateWrapper = true; } else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyCollection<>), out implementingType)) { CollectionItemType = implementingType.GetGenericArguments()[0]; if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyCollection<>)) || ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyList<>))) { base.CreatedType = typeof(ReadOnlyCollection<>).MakeGenericType(CollectionItemType); } _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(base.CreatedType, CollectionItemType); StoreFSharpListCreatorIfNecessary(NonNullableUnderlyingType); IsReadOnlyOrFixedSize = true; canDeserialize = HasParameterizedCreatorInternal; } else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IEnumerable<>), out implementingType)) { CollectionItemType = implementingType.GetGenericArguments()[0]; if (ReflectionUtils.IsGenericDefinition(base.UnderlyingType, typeof(IEnumerable<>))) { base.CreatedType = typeof(List<>).MakeGenericType(CollectionItemType); } _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType); StoreFSharpListCreatorIfNecessary(NonNullableUnderlyingType); if (NonNullableUnderlyingType.IsGenericType() && NonNullableUnderlyingType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) { _genericCollectionDefinitionType = implementingType; IsReadOnlyOrFixedSize = false; ShouldCreateWrapper = false; canDeserialize = true; } else { _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); IsReadOnlyOrFixedSize = true; ShouldCreateWrapper = true; canDeserialize = HasParameterizedCreatorInternal; } } else { canDeserialize = false; ShouldCreateWrapper = true; } CanDeserialize = canDeserialize; if (CollectionItemType != null && ImmutableCollectionsUtils.TryBuildImmutableForArrayContract(NonNullableUnderlyingType, CollectionItemType, out Type createdType, out ObjectConstructor parameterizedCreator)) { base.CreatedType = createdType; _parameterizedCreator = parameterizedCreator; IsReadOnlyOrFixedSize = true; CanDeserialize = true; } } internal IWrappedCollection CreateWrapper(object list) { if (_genericWrapperCreator == null) { _genericWrapperType = typeof(CollectionWrapper<>).MakeGenericType(CollectionItemType); Type type = ((!ReflectionUtils.InheritsGenericDefinition(_genericCollectionDefinitionType, typeof(List<>)) && !(_genericCollectionDefinitionType.GetGenericTypeDefinition() == typeof(IEnumerable<>))) ? _genericCollectionDefinitionType : typeof(ICollection<>).MakeGenericType(CollectionItemType)); ConstructorInfo constructor = _genericWrapperType.GetConstructor(new Type[1] { type }); _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); } return (IWrappedCollection)_genericWrapperCreator(list); } internal IList CreateTemporaryCollection() { if (_genericTemporaryCollectionCreator == null) { Type type = ((IsMultidimensionalArray || CollectionItemType == null) ? typeof(object) : CollectionItemType); Type type2 = typeof(List<>).MakeGenericType(type); _genericTemporaryCollectionCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(type2); } return (IList)_genericTemporaryCollectionCreator(); } private void StoreFSharpListCreatorIfNecessary(Type underlyingType) { if (!HasParameterizedCreatorInternal && underlyingType.Name == "FSharpList`1") { FSharpUtils.EnsureInitialized(underlyingType.Assembly()); _parameterizedCreator = FSharpUtils.Instance.CreateSeq(CollectionItemType); } } } internal class JsonContainerContract : JsonContract { private JsonContract? _itemContract; private JsonContract? _finalItemContract; internal JsonContract? ItemContract { get { return _itemContract; } set { _itemContract = value; if (_itemContract != null) { _finalItemContract = (_itemContract.UnderlyingType.IsSealed() ? _itemContract : null); } else { _finalItemContract = null; } } } internal JsonContract? FinalItemContract => _finalItemContract; public JsonConverter? ItemConverter { get; set; } public bool? ItemIsReference { get; set; } public ReferenceLoopHandling? ItemReferenceLoopHandling { get; set; } public TypeNameHandling? ItemTypeNameHandling { get; set; } internal JsonContainerContract(Type underlyingType) : base(underlyingType) { JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(underlyingType); if (cachedAttribute != null) { if (cachedAttribute.ItemConverterType != null) { ItemConverter = JsonTypeReflector.CreateJsonConverterInstance(cachedAttribute.ItemConverterType, cachedAttribute.ItemConverterParameters); } ItemIsReference = cachedAttribute._itemIsReference; ItemReferenceLoopHandling = cachedAttribute._itemReferenceLoopHandling; ItemTypeNameHandling = cachedAttribute._itemTypeNameHandling; } } } internal enum JsonContractType { None, Object, Array, Primitive, String, Dictionary, Dynamic, Serializable, Linq } internal delegate void SerializationCallback(object o, StreamingContext context); internal delegate void SerializationErrorCallback(object o, StreamingContext context, ErrorContext errorContext); internal delegate void ExtensionDataSetter(object o, string key, object? value); internal delegate IEnumerable>? ExtensionDataGetter(object o); internal abstract class JsonContract { internal bool IsNullable; internal bool IsConvertable; internal bool IsEnum; internal Type NonNullableUnderlyingType; internal ReadType InternalReadType; internal JsonContractType ContractType; internal bool IsReadOnlyOrFixedSize; internal bool IsSealed; internal bool IsInstantiable; private List? _onDeserializedCallbacks; private List? _onDeserializingCallbacks; private List? _onSerializedCallbacks; private List? _onSerializingCallbacks; private List? _onErrorCallbacks; private Type _createdType; public Type UnderlyingType { get; } public Type CreatedType { get { return _createdType; } set { ValidationUtils.ArgumentNotNull(value, "value"); _createdType = value; IsSealed = _createdType.IsSealed(); IsInstantiable = !_createdType.IsInterface() && !_createdType.IsAbstract(); } } public bool? IsReference { get; set; } public JsonConverter? Converter { get; set; } public JsonConverter? InternalConverter { get; internal set; } public IList OnDeserializedCallbacks { get { if (_onDeserializedCallbacks == null) { _onDeserializedCallbacks = new List(); } return _onDeserializedCallbacks; } } public IList OnDeserializingCallbacks { get { if (_onDeserializingCallbacks == null) { _onDeserializingCallbacks = new List(); } return _onDeserializingCallbacks; } } public IList OnSerializedCallbacks { get { if (_onSerializedCallbacks == null) { _onSerializedCallbacks = new List(); } return _onSerializedCallbacks; } } public IList OnSerializingCallbacks { get { if (_onSerializingCallbacks == null) { _onSerializingCallbacks = new List(); } return _onSerializingCallbacks; } } public IList OnErrorCallbacks { get { if (_onErrorCallbacks == null) { _onErrorCallbacks = new List(); } return _onErrorCallbacks; } } public Func? DefaultCreator { get; set; } public bool DefaultCreatorNonPublic { get; set; } internal JsonContract(Type underlyingType) { ValidationUtils.ArgumentNotNull(underlyingType, "underlyingType"); UnderlyingType = underlyingType; underlyingType = ReflectionUtils.EnsureNotByRefType(underlyingType); IsNullable = ReflectionUtils.IsNullable(underlyingType); NonNullableUnderlyingType = ((IsNullable && ReflectionUtils.IsNullableType(underlyingType)) ? Nullable.GetUnderlyingType(underlyingType) : underlyingType); _createdType = (CreatedType = NonNullableUnderlyingType); IsConvertable = ConvertUtils.IsConvertible(NonNullableUnderlyingType); IsEnum = NonNullableUnderlyingType.IsEnum(); InternalReadType = ReadType.Read; } internal void InvokeOnSerializing(object o, StreamingContext context) { if (_onSerializingCallbacks == null) { return; } foreach (SerializationCallback onSerializingCallback in _onSerializingCallbacks) { onSerializingCallback(o, context); } } internal void InvokeOnSerialized(object o, StreamingContext context) { if (_onSerializedCallbacks == null) { return; } foreach (SerializationCallback onSerializedCallback in _onSerializedCallbacks) { onSerializedCallback(o, context); } } internal void InvokeOnDeserializing(object o, StreamingContext context) { if (_onDeserializingCallbacks == null) { return; } foreach (SerializationCallback onDeserializingCallback in _onDeserializingCallbacks) { onDeserializingCallback(o, context); } } internal void InvokeOnDeserialized(object o, StreamingContext context) { if (_onDeserializedCallbacks == null) { return; } foreach (SerializationCallback onDeserializedCallback in _onDeserializedCallbacks) { onDeserializedCallback(o, context); } } internal void InvokeOnError(object o, StreamingContext context, ErrorContext errorContext) { if (_onErrorCallbacks == null) { return; } foreach (SerializationErrorCallback onErrorCallback in _onErrorCallbacks) { onErrorCallback(o, context, errorContext); } } internal static SerializationCallback CreateSerializationCallback(MethodInfo callbackMethodInfo) { MethodInfo callbackMethodInfo2 = callbackMethodInfo; return delegate(object o, StreamingContext context) { callbackMethodInfo2.Invoke(o, new object[1] { context }); }; } internal static SerializationErrorCallback CreateSerializationErrorCallback(MethodInfo callbackMethodInfo) { MethodInfo callbackMethodInfo2 = callbackMethodInfo; return delegate(object o, StreamingContext context, ErrorContext econtext) { callbackMethodInfo2.Invoke(o, new object[2] { context, econtext }); }; } } internal class JsonDictionaryContract : JsonContainerContract { private readonly Type? _genericCollectionDefinitionType; private Type? _genericWrapperType; private ObjectConstructor? _genericWrapperCreator; private Func? _genericTemporaryDictionaryCreator; private readonly ConstructorInfo? _parameterizedConstructor; private ObjectConstructor? _overrideCreator; private ObjectConstructor? _parameterizedCreator; public Func? DictionaryKeyResolver { get; set; } public Type? DictionaryKeyType { get; } public Type? DictionaryValueType { get; } internal JsonContract? KeyContract { get; set; } internal bool ShouldCreateWrapper { get; } internal ObjectConstructor? ParameterizedCreator { get { if (_parameterizedCreator == null && _parameterizedConstructor != null) { _parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(_parameterizedConstructor); } return _parameterizedCreator; } } public ObjectConstructor? OverrideCreator { get { return _overrideCreator; } set { _overrideCreator = value; } } public bool HasParameterizedCreator { get; set; } internal bool HasParameterizedCreatorInternal { get { if (!HasParameterizedCreator && _parameterizedCreator == null) { return _parameterizedConstructor != null; } return true; } } public JsonDictionaryContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Dictionary; Type keyType; Type valueType; if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IDictionary<, >), out _genericCollectionDefinitionType)) { keyType = _genericCollectionDefinitionType.GetGenericArguments()[0]; valueType = _genericCollectionDefinitionType.GetGenericArguments()[1]; if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IDictionary<, >))) { base.CreatedType = typeof(Dictionary<, >).MakeGenericType(keyType, valueType); } else if (NonNullableUnderlyingType.IsGenericType() && NonNullableUnderlyingType.GetGenericTypeDefinition().FullName == "System.Collections.Concurrent.ConcurrentDictionary`2") { ShouldCreateWrapper = true; } IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(NonNullableUnderlyingType, typeof(ReadOnlyDictionary<, >)); } else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyDictionary<, >), out _genericCollectionDefinitionType)) { keyType = _genericCollectionDefinitionType.GetGenericArguments()[0]; valueType = _genericCollectionDefinitionType.GetGenericArguments()[1]; if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyDictionary<, >))) { base.CreatedType = typeof(ReadOnlyDictionary<, >).MakeGenericType(keyType, valueType); } IsReadOnlyOrFixedSize = true; } else { ReflectionUtils.GetDictionaryKeyValueTypes(NonNullableUnderlyingType, out keyType, out valueType); if (NonNullableUnderlyingType == typeof(IDictionary)) { base.CreatedType = typeof(Dictionary); } } if (keyType != null && valueType != null) { _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(base.CreatedType, typeof(KeyValuePair<, >).MakeGenericType(keyType, valueType), typeof(IDictionary<, >).MakeGenericType(keyType, valueType)); if (!HasParameterizedCreatorInternal && NonNullableUnderlyingType.Name == "FSharpMap`2") { FSharpUtils.EnsureInitialized(NonNullableUnderlyingType.Assembly()); _parameterizedCreator = FSharpUtils.Instance.CreateMap(keyType, valueType); } } if (!typeof(IDictionary).IsAssignableFrom(base.CreatedType)) { ShouldCreateWrapper = true; } DictionaryKeyType = keyType; DictionaryValueType = valueType; if (DictionaryKeyType != null && DictionaryValueType != null && ImmutableCollectionsUtils.TryBuildImmutableForDictionaryContract(NonNullableUnderlyingType, DictionaryKeyType, DictionaryValueType, out Type createdType, out ObjectConstructor parameterizedCreator)) { base.CreatedType = createdType; _parameterizedCreator = parameterizedCreator; IsReadOnlyOrFixedSize = true; } } internal IWrappedDictionary CreateWrapper(object dictionary) { if (_genericWrapperCreator == null) { _genericWrapperType = typeof(DictionaryWrapper<, >).MakeGenericType(DictionaryKeyType, DictionaryValueType); ConstructorInfo constructor = _genericWrapperType.GetConstructor(new Type[1] { _genericCollectionDefinitionType }); _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); } return (IWrappedDictionary)_genericWrapperCreator(dictionary); } internal IDictionary CreateTemporaryDictionary() { if (_genericTemporaryDictionaryCreator == null) { Type type = typeof(Dictionary<, >).MakeGenericType(DictionaryKeyType ?? typeof(object), DictionaryValueType ?? typeof(object)); _genericTemporaryDictionaryCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(type); } return (IDictionary)_genericTemporaryDictionaryCreator(); } } internal class JsonDynamicContract : JsonContainerContract { private readonly ThreadSafeStore>> _callSiteGetters = new ThreadSafeStore>>(CreateCallSiteGetter); private readonly ThreadSafeStore>> _callSiteSetters = new ThreadSafeStore>>(CreateCallSiteSetter); public JsonPropertyCollection Properties { get; } public Func? PropertyNameResolver { get; set; } private static CallSite> CreateCallSiteGetter(string name) { return CallSite>.Create(new NoThrowGetBinderMember((GetMemberBinder)DynamicUtils.BinderWrapper.GetMember(name, typeof(DynamicUtils)))); } private static CallSite> CreateCallSiteSetter(string name) { return CallSite>.Create(new NoThrowSetBinderMember((SetMemberBinder)DynamicUtils.BinderWrapper.SetMember(name, typeof(DynamicUtils)))); } public JsonDynamicContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Dynamic; Properties = new JsonPropertyCollection(base.UnderlyingType); } internal bool TryGetMember(IDynamicMetaObjectProvider dynamicProvider, string name, out object? value) { ValidationUtils.ArgumentNotNull(dynamicProvider, "dynamicProvider"); CallSite> callSite = _callSiteGetters.Get(name); object obj = callSite.Target(callSite, dynamicProvider); if (obj != NoThrowExpressionVisitor.ErrorResult) { value = obj; return true; } value = null; return false; } internal bool TrySetMember(IDynamicMetaObjectProvider dynamicProvider, string name, object? value) { ValidationUtils.ArgumentNotNull(dynamicProvider, "dynamicProvider"); CallSite> callSite = _callSiteSetters.Get(name); return callSite.Target(callSite, dynamicProvider, value) != NoThrowExpressionVisitor.ErrorResult; } } internal class JsonFormatterConverter : IFormatterConverter { private readonly JsonSerializerInternalReader _reader; private readonly JsonISerializableContract _contract; private readonly JsonProperty? _member; public JsonFormatterConverter(JsonSerializerInternalReader reader, JsonISerializableContract contract, JsonProperty? member) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(contract, "contract"); _reader = reader; _contract = contract; _member = member; } private T GetTokenValue(object value) { ValidationUtils.ArgumentNotNull(value, "value"); return (T)System.Convert.ChangeType(((JValue)value).Value, typeof(T), CultureInfo.InvariantCulture); } public object Convert(object value, Type type) { ValidationUtils.ArgumentNotNull(value, "value"); if (!(value is JToken token)) { throw new ArgumentException("Value is not a JToken.", "value"); } return _reader.CreateISerializableItem(token, type, _contract, _member); } public object Convert(object value, TypeCode typeCode) { ValidationUtils.ArgumentNotNull(value, "value"); return System.Convert.ChangeType((value is JValue jValue) ? jValue.Value : value, typeCode, CultureInfo.InvariantCulture); } public bool ToBoolean(object value) { return GetTokenValue(value); } public byte ToByte(object value) { return GetTokenValue(value); } public char ToChar(object value) { return GetTokenValue(value); } public DateTime ToDateTime(object value) { return GetTokenValue(value); } public decimal ToDecimal(object value) { return GetTokenValue(value); } public double ToDouble(object value) { return GetTokenValue(value); } public short ToInt16(object value) { return GetTokenValue(value); } public int ToInt32(object value) { return GetTokenValue(value); } public long ToInt64(object value) { return GetTokenValue(value); } public sbyte ToSByte(object value) { return GetTokenValue(value); } public float ToSingle(object value) { return GetTokenValue(value); } public string ToString(object value) { return GetTokenValue(value); } public ushort ToUInt16(object value) { return GetTokenValue(value); } public uint ToUInt32(object value) { return GetTokenValue(value); } public ulong ToUInt64(object value) { return GetTokenValue(value); } } internal class JsonISerializableContract : JsonContainerContract { public ObjectConstructor? ISerializableCreator { get; set; } public JsonISerializableContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Serializable; } } internal class JsonLinqContract : JsonContract { public JsonLinqContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Linq; } } internal class JsonObjectContract : JsonContainerContract { internal bool ExtensionDataIsJToken; private bool? _hasRequiredOrDefaultValueProperties; private ObjectConstructor? _overrideCreator; private ObjectConstructor? _parameterizedCreator; private JsonPropertyCollection? _creatorParameters; private Type? _extensionDataValueType; public MemberSerialization MemberSerialization { get; set; } public MissingMemberHandling? MissingMemberHandling { get; set; } public Required? ItemRequired { get; set; } public NullValueHandling? ItemNullValueHandling { get; set; } public JsonPropertyCollection Properties { get; } public JsonPropertyCollection CreatorParameters { get { if (_creatorParameters == null) { _creatorParameters = new JsonPropertyCollection(base.UnderlyingType); } return _creatorParameters; } } public ObjectConstructor? OverrideCreator { get { return _overrideCreator; } set { _overrideCreator = value; } } internal ObjectConstructor? ParameterizedCreator { get { return _parameterizedCreator; } set { _parameterizedCreator = value; } } public ExtensionDataSetter? ExtensionDataSetter { get; set; } public ExtensionDataGetter? ExtensionDataGetter { get; set; } public Type? ExtensionDataValueType { get { return _extensionDataValueType; } set { _extensionDataValueType = value; ExtensionDataIsJToken = value != null && typeof(JToken).IsAssignableFrom(value); } } public Func? ExtensionDataNameResolver { get; set; } internal bool HasRequiredOrDefaultValueProperties { get { if (!_hasRequiredOrDefaultValueProperties.HasValue) { _hasRequiredOrDefaultValueProperties = false; if (ItemRequired.GetValueOrDefault(Required.Default) != 0) { _hasRequiredOrDefaultValueProperties = true; } else { foreach (JsonProperty property in Properties) { if (property.Required != 0 || ((uint?)property.DefaultValueHandling & 2u) == 2) { _hasRequiredOrDefaultValueProperties = true; break; } } } } return _hasRequiredOrDefaultValueProperties.GetValueOrDefault(); } } public JsonObjectContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Object; Properties = new JsonPropertyCollection(base.UnderlyingType); } [SecuritySafeCritical] internal object GetUninitializedObject() { if (!JsonTypeReflector.FullyTrusted) { throw new JsonException("Insufficient permissions. Creating an uninitialized '{0}' type requires full trust.".FormatWith(CultureInfo.InvariantCulture, NonNullableUnderlyingType)); } return FormatterServices.GetUninitializedObject(NonNullableUnderlyingType); } } internal class JsonPrimitiveContract : JsonContract { private static readonly Dictionary ReadTypeMap = new Dictionary { [typeof(byte[])] = ReadType.ReadAsBytes, [typeof(byte)] = ReadType.ReadAsInt32, [typeof(short)] = ReadType.ReadAsInt32, [typeof(int)] = ReadType.ReadAsInt32, [typeof(decimal)] = ReadType.ReadAsDecimal, [typeof(bool)] = ReadType.ReadAsBoolean, [typeof(string)] = ReadType.ReadAsString, [typeof(DateTime)] = ReadType.ReadAsDateTime, [typeof(DateTimeOffset)] = ReadType.ReadAsDateTimeOffset, [typeof(float)] = ReadType.ReadAsDouble, [typeof(double)] = ReadType.ReadAsDouble, [typeof(long)] = ReadType.ReadAsInt64 }; internal PrimitiveTypeCode TypeCode { get; set; } public JsonPrimitiveContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Primitive; TypeCode = ConvertUtils.GetTypeCode(underlyingType); IsReadOnlyOrFixedSize = true; if (ReadTypeMap.TryGetValue(NonNullableUnderlyingType, out var value)) { InternalReadType = value; } } } internal class JsonProperty { internal Required? _required; internal bool _hasExplicitDefaultValue; private object? _defaultValue; private bool _hasGeneratedDefaultValue; private string? _propertyName; internal bool _skipPropertyNameEscape; private Type? _propertyType; internal JsonContract? PropertyContract { get; set; } public string? PropertyName { get { return _propertyName; } set { _propertyName = value; _skipPropertyNameEscape = !JavaScriptUtils.ShouldEscapeJavaScriptString(_propertyName, JavaScriptUtils.HtmlCharEscapeFlags); } } public Type? DeclaringType { get; set; } public int? Order { get; set; } public string? UnderlyingName { get; set; } public IValueProvider? ValueProvider { get; set; } public IAttributeProvider? AttributeProvider { get; set; } public Type? PropertyType { get { return _propertyType; } set { if (_propertyType != value) { _propertyType = value; _hasGeneratedDefaultValue = false; } } } public JsonConverter? Converter { get; set; } [Obsolete("MemberConverter is obsolete. Use Converter instead.")] public JsonConverter? MemberConverter { get { return Converter; } set { Converter = value; } } public bool Ignored { get; set; } public bool Readable { get; set; } public bool Writable { get; set; } public bool HasMemberAttribute { get; set; } public object? DefaultValue { get { if (!_hasExplicitDefaultValue) { return null; } return _defaultValue; } set { _hasExplicitDefaultValue = true; _defaultValue = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public bool IsRequiredSpecified => _required.HasValue; public bool? IsReference { get; set; } public NullValueHandling? NullValueHandling { get; set; } public DefaultValueHandling? DefaultValueHandling { get; set; } public ReferenceLoopHandling? ReferenceLoopHandling { get; set; } public ObjectCreationHandling? ObjectCreationHandling { get; set; } public TypeNameHandling? TypeNameHandling { get; set; } public Predicate? ShouldSerialize { get; set; } public Predicate? ShouldDeserialize { get; set; } public Predicate? GetIsSpecified { get; set; } public Action? SetIsSpecified { get; set; } public JsonConverter? ItemConverter { get; set; } public bool? ItemIsReference { get; set; } public TypeNameHandling? ItemTypeNameHandling { get; set; } public ReferenceLoopHandling? ItemReferenceLoopHandling { get; set; } internal object? GetResolvedDefaultValue() { if (_propertyType == null) { return null; } if (!_hasExplicitDefaultValue && !_hasGeneratedDefaultValue) { _defaultValue = ReflectionUtils.GetDefaultValue(_propertyType); _hasGeneratedDefaultValue = true; } return _defaultValue; } public override string ToString() { return PropertyName ?? string.Empty; } internal void WritePropertyName(JsonWriter writer) { string propertyName = PropertyName; if (_skipPropertyNameEscape) { writer.WritePropertyName(propertyName, escape: false); } else { writer.WritePropertyName(propertyName); } } } internal class JsonPropertyCollection : KeyedCollection { private readonly Type _type; private readonly List _list; public JsonPropertyCollection(Type type) : base((IEqualityComparer?)StringComparer.Ordinal) { ValidationUtils.ArgumentNotNull(type, "type"); _type = type; _list = (List)base.Items; } protected override string GetKeyForItem(JsonProperty item) { return item.PropertyName; } public void AddProperty(JsonProperty property) { if (Contains(property.PropertyName)) { if (property.Ignored) { return; } JsonProperty jsonProperty = base[property.PropertyName]; bool flag = true; if (jsonProperty.Ignored) { Remove(jsonProperty); flag = false; } else if (property.DeclaringType != null && jsonProperty.DeclaringType != null) { if (property.DeclaringType.IsSubclassOf(jsonProperty.DeclaringType) || (jsonProperty.DeclaringType.IsInterface() && property.DeclaringType.ImplementInterface(jsonProperty.DeclaringType))) { Remove(jsonProperty); flag = false; } if (jsonProperty.DeclaringType.IsSubclassOf(property.DeclaringType) || (property.DeclaringType.IsInterface() && jsonProperty.DeclaringType.ImplementInterface(property.DeclaringType)) || (_type.ImplementInterface(jsonProperty.DeclaringType) && _type.ImplementInterface(property.DeclaringType))) { return; } } if (flag) { throw new JsonSerializationException("A member with the name '{0}' already exists on '{1}'. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, _type)); } } Add(property); } public JsonProperty? GetClosestMatchProperty(string propertyName) { JsonProperty property = GetProperty(propertyName, StringComparison.Ordinal); if (property == null) { property = GetProperty(propertyName, StringComparison.OrdinalIgnoreCase); } return property; } private bool TryGetProperty(string key, [NotNullWhen(true)] out JsonProperty? item) { if (base.Dictionary == null) { item = null; return false; } return base.Dictionary.TryGetValue(key, out item); } public JsonProperty? GetProperty(string propertyName, StringComparison comparisonType) { if (comparisonType == StringComparison.Ordinal) { if (TryGetProperty(propertyName, out JsonProperty item)) { return item; } return null; } for (int i = 0; i < _list.Count; i++) { JsonProperty jsonProperty = _list[i]; if (string.Equals(propertyName, jsonProperty.PropertyName, comparisonType)) { return jsonProperty; } } return null; } } internal abstract class JsonSerializerInternalBase { private class ReferenceEqualsEqualityComparer : IEqualityComparer { bool IEqualityComparer.Equals(object? x, object? y) { return x == y; } int IEqualityComparer.GetHashCode(object obj) { return RuntimeHelpers.GetHashCode(obj); } } private ErrorContext? _currentErrorContext; private BidirectionalDictionary? _mappings; internal readonly JsonSerializer Serializer; internal readonly ITraceWriter? TraceWriter; protected JsonSerializerProxy? InternalSerializer; internal BidirectionalDictionary DefaultReferenceMappings { get { if (_mappings == null) { _mappings = new BidirectionalDictionary(EqualityComparer.Default, new ReferenceEqualsEqualityComparer(), "A different value already has the Id '{0}'.", "A different Id has already been assigned for value '{0}'. This error may be caused by an object being reused multiple times during deserialization and can be fixed with the setting ObjectCreationHandling.Replace."); } return _mappings; } } protected JsonSerializerInternalBase(JsonSerializer serializer) { ValidationUtils.ArgumentNotNull(serializer, "serializer"); Serializer = serializer; TraceWriter = serializer.TraceWriter; } protected NullValueHandling ResolvedNullValueHandling(JsonObjectContract? containerContract, JsonProperty property) { return property.NullValueHandling ?? containerContract?.ItemNullValueHandling ?? Serializer._nullValueHandling; } private ErrorContext GetErrorContext(object? currentObject, object? member, string path, Exception error) { if (_currentErrorContext == null) { _currentErrorContext = new ErrorContext(currentObject, member, path, error); } if (_currentErrorContext.Error != error) { throw new InvalidOperationException("Current error context error is different to requested error."); } return _currentErrorContext; } protected void ClearErrorContext() { if (_currentErrorContext == null) { throw new InvalidOperationException("Could not clear error context. Error context is already null."); } _currentErrorContext = null; } protected bool IsErrorHandled(object? currentObject, JsonContract? contract, object? keyValue, IJsonLineInfo? lineInfo, string path, Exception ex) { ErrorContext errorContext = GetErrorContext(currentObject, keyValue, path, ex); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Error && !errorContext.Traced) { errorContext.Traced = true; string text = ((GetType() == typeof(JsonSerializerInternalWriter)) ? "Error serializing" : "Error deserializing"); if (contract != null) { text = text + " " + contract.UnderlyingType; } text = text + ". " + ex.Message; if (!(ex is JsonException)) { text = JsonPosition.FormatMessage(lineInfo, path, text); } TraceWriter.Trace(TraceLevel.Error, text, ex); } if (contract != null && currentObject != null) { contract.InvokeOnError(currentObject, Serializer.Context, errorContext); } if (!errorContext.Handled) { Serializer.OnError(new ErrorEventArgs(currentObject, errorContext)); } return errorContext.Handled; } } internal class JsonSerializerInternalReader : JsonSerializerInternalBase { internal enum PropertyPresence { None, Null, Value } internal class CreatorPropertyContext { public readonly string Name; public JsonProperty? Property; public JsonProperty? ConstructorProperty; public PropertyPresence? Presence; public object? Value; public bool Used; public CreatorPropertyContext(string name) { Name = name; } } public JsonSerializerInternalReader(JsonSerializer serializer) : base(serializer) { } public void Populate(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(target, "target"); Type type = target.GetType(); JsonContract jsonContract = Serializer._contractResolver.ResolveContract(type); if (!reader.MoveToContent()) { throw JsonSerializationException.Create(reader, "No JSON content found."); } if (reader.TokenType == JsonToken.StartArray) { if (jsonContract.ContractType == JsonContractType.Array) { JsonArrayContract jsonArrayContract = (JsonArrayContract)jsonContract; object list; if (!jsonArrayContract.ShouldCreateWrapper) { list = (IList)target; } else { IList list2 = jsonArrayContract.CreateWrapper(target); list = list2; } PopulateList((IList)list, reader, jsonArrayContract, null, null); return; } throw JsonSerializationException.Create(reader, "Cannot populate JSON array onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, type)); } if (reader.TokenType == JsonToken.StartObject) { reader.ReadAndAssert(); string id = null; if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore && reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), "$id", StringComparison.Ordinal)) { reader.ReadAndAssert(); id = reader.Value?.ToString(); reader.ReadAndAssert(); } if (jsonContract.ContractType == JsonContractType.Dictionary) { JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)jsonContract; object dictionary; if (!jsonDictionaryContract.ShouldCreateWrapper) { dictionary = (IDictionary)target; } else { IDictionary dictionary2 = jsonDictionaryContract.CreateWrapper(target); dictionary = dictionary2; } PopulateDictionary((IDictionary)dictionary, reader, jsonDictionaryContract, null, id); } else { if (jsonContract.ContractType != JsonContractType.Object) { throw JsonSerializationException.Create(reader, "Cannot populate JSON object onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, type)); } PopulateObject(target, reader, (JsonObjectContract)jsonContract, null, id); } return; } throw JsonSerializationException.Create(reader, "Unexpected initial token '{0}' when populating object. Expected JSON object or array.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } private JsonContract? GetContractSafe(Type? type) { if (type == null) { return null; } return GetContract(type); } private JsonContract GetContract(Type type) { return Serializer._contractResolver.ResolveContract(type); } public object? Deserialize(JsonReader reader, Type? objectType, bool checkAdditionalContent) { if (reader == null) { throw new ArgumentNullException("reader"); } JsonContract contractSafe = GetContractSafe(objectType); try { JsonConverter converter = GetConverter(contractSafe, null, null, null); if (reader.TokenType == JsonToken.None && !reader.ReadForType(contractSafe, converter != null)) { if (contractSafe != null && !contractSafe.IsNullable) { throw JsonSerializationException.Create(reader, "No JSON content found and type '{0}' is not nullable.".FormatWith(CultureInfo.InvariantCulture, contractSafe.UnderlyingType)); } return null; } object result = ((converter == null || !converter.CanRead) ? CreateValueInternal(reader, objectType, contractSafe, null, null, null, null) : DeserializeConvertable(converter, reader, objectType, null)); if (checkAdditionalContent) { while (reader.Read()) { if (reader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(reader, "Additional text found in JSON string after finishing deserializing object."); } } } return result; } catch (Exception ex) { if (IsErrorHandled(null, contractSafe, null, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: false, 0); return null; } ClearErrorContext(); throw; } } private JsonSerializerProxy GetInternalSerializer() { if (InternalSerializer == null) { InternalSerializer = new JsonSerializerProxy(this); } return InternalSerializer; } private JToken? CreateJToken(JsonReader reader, JsonContract? contract) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (contract != null) { if (contract.UnderlyingType == typeof(JRaw)) { return JRaw.Create(reader); } if (reader.TokenType == JsonToken.Null && !(contract.UnderlyingType == typeof(JValue)) && !(contract.UnderlyingType == typeof(JToken))) { return null; } } JToken token; using (JTokenWriter jTokenWriter = new JTokenWriter()) { jTokenWriter.WriteToken(reader); token = jTokenWriter.Token; } if (contract != null && token != null && !contract.UnderlyingType.IsAssignableFrom(token.GetType())) { throw JsonSerializationException.Create(reader, "Deserialized JSON type '{0}' is not compatible with expected type '{1}'.".FormatWith(CultureInfo.InvariantCulture, token.GetType().FullName, contract.UnderlyingType.FullName)); } return token; } private JToken CreateJObject(JsonReader reader) { ValidationUtils.ArgumentNotNull(reader, "reader"); using JTokenWriter jTokenWriter = new JTokenWriter(); jTokenWriter.WriteStartObject(); do { if (reader.TokenType == JsonToken.PropertyName) { string text = (string)reader.Value; if (!reader.ReadAndMoveToContent()) { break; } if (!CheckPropertyName(reader, text)) { jTokenWriter.WritePropertyName(text); jTokenWriter.WriteToken(reader, writeChildren: true, writeDateConstructorAsDate: true, writeComments: false); } } else if (reader.TokenType != JsonToken.Comment) { jTokenWriter.WriteEndObject(); return jTokenWriter.Token; } } while (reader.Read()); throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } private object? CreateValueInternal(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue) { if (contract != null && contract.ContractType == JsonContractType.Linq) { return CreateJToken(reader, contract); } do { switch (reader.TokenType) { case JsonToken.StartObject: return CreateObject(reader, objectType, contract, member, containerContract, containerMember, existingValue); case JsonToken.StartArray: return CreateList(reader, objectType, contract, member, existingValue, null); case JsonToken.Integer: case JsonToken.Float: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.String: { string text = (string)reader.Value; if (objectType == typeof(byte[])) { return Convert.FromBase64String(text); } if (CoerceEmptyStringToNull(objectType, contract, text)) { return null; } return EnsureType(reader, text, CultureInfo.InvariantCulture, contract, objectType); } case JsonToken.StartConstructor: { string value = reader.Value.ToString(); return EnsureType(reader, value, CultureInfo.InvariantCulture, contract, objectType); } case JsonToken.Null: case JsonToken.Undefined: if (objectType == typeof(DBNull)) { return DBNull.Value; } return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.Raw: return new JRaw((string)reader.Value); default: throw JsonSerializationException.Create(reader, "Unexpected token while deserializing object: " + reader.TokenType); case JsonToken.Comment: break; } } while (reader.Read()); throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } private static bool CoerceEmptyStringToNull(Type? objectType, JsonContract? contract, string s) { if (StringUtils.IsNullOrEmpty(s) && objectType != null && objectType != typeof(string) && objectType != typeof(object) && contract != null) { return contract.IsNullable; } return false; } internal string GetExpectedDescription(JsonContract contract) { switch (contract.ContractType) { case JsonContractType.Object: case JsonContractType.Dictionary: case JsonContractType.Dynamic: case JsonContractType.Serializable: return "JSON object (e.g. {\"name\":\"value\"})"; case JsonContractType.Array: return "JSON array (e.g. [1,2,3])"; case JsonContractType.Primitive: return "JSON primitive value (e.g. string, number, boolean, null)"; case JsonContractType.String: return "JSON string value"; default: throw new ArgumentOutOfRangeException(); } } private JsonConverter? GetConverter(JsonContract? contract, JsonConverter? memberConverter, JsonContainerContract? containerContract, JsonProperty? containerProperty) { JsonConverter result = null; if (memberConverter != null) { result = memberConverter; } else if (containerProperty?.ItemConverter != null) { result = containerProperty.ItemConverter; } else if (containerContract?.ItemConverter != null) { result = containerContract.ItemConverter; } else if (contract != null) { if (contract.Converter != null) { result = contract.Converter; } else { JsonConverter matchingConverter = Serializer.GetMatchingConverter(contract.UnderlyingType); if (matchingConverter != null) { result = matchingConverter; } else if (contract.InternalConverter != null) { result = contract.InternalConverter; } } } return result; } private object? CreateObject(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue) { Type objectType2 = objectType; string id; if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.Ignore) { reader.ReadAndAssert(); id = null; } else if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead) { JTokenReader jTokenReader = reader as JTokenReader; if (jTokenReader == null) { jTokenReader = (JTokenReader)JToken.ReadFrom(reader).CreateReader(); jTokenReader.Culture = reader.Culture; jTokenReader.DateFormatString = reader.DateFormatString; jTokenReader.DateParseHandling = reader.DateParseHandling; jTokenReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; jTokenReader.FloatParseHandling = reader.FloatParseHandling; jTokenReader.SupportMultipleContent = reader.SupportMultipleContent; jTokenReader.ReadAndAssert(); reader = jTokenReader; } if (ReadMetadataPropertiesToken(jTokenReader, ref objectType2, ref contract, member, containerContract, containerMember, existingValue, out object newValue, out id)) { return newValue; } } else { reader.ReadAndAssert(); if (ReadMetadataProperties(reader, ref objectType2, ref contract, member, containerContract, containerMember, existingValue, out object newValue2, out id)) { return newValue2; } } if (HasNoDefinedType(contract)) { return CreateJObject(reader); } switch (contract.ContractType) { case JsonContractType.Object: { bool createdFromNonDefaultCreator2 = false; JsonObjectContract jsonObjectContract = (JsonObjectContract)contract; object obj = ((existingValue == null || (!(objectType2 == objectType) && !objectType2.IsAssignableFrom(existingValue.GetType()))) ? CreateNewObject(reader, jsonObjectContract, member, containerMember, id, out createdFromNonDefaultCreator2) : existingValue); if (createdFromNonDefaultCreator2) { return obj; } return PopulateObject(obj, reader, jsonObjectContract, member, id); } case JsonContractType.Primitive: { JsonPrimitiveContract contract4 = (JsonPrimitiveContract)contract; if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore && reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), "$value", StringComparison.Ordinal)) { reader.ReadAndAssert(); if (reader.TokenType == JsonToken.StartObject) { throw JsonSerializationException.Create(reader, "Unexpected token when deserializing primitive value: " + reader.TokenType); } object? result = CreateValueInternal(reader, objectType2, contract4, member, null, null, existingValue); reader.ReadAndAssert(); return result; } break; } case JsonContractType.Dictionary: { JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)contract; if (existingValue == null) { bool createdFromNonDefaultCreator; IDictionary dictionary = CreateNewDictionary(reader, jsonDictionaryContract, out createdFromNonDefaultCreator); if (createdFromNonDefaultCreator) { if (id != null) { throw JsonSerializationException.Create(reader, "Cannot preserve reference to readonly dictionary, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.OnSerializingCallbacks.Count > 0) { throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on readonly dictionary, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.OnErrorCallbacks.Count > 0) { throw JsonSerializationException.Create(reader, "Cannot call OnError on readonly list, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (!jsonDictionaryContract.HasParameterizedCreatorInternal) { throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } } PopulateDictionary(dictionary, reader, jsonDictionaryContract, member, id); if (createdFromNonDefaultCreator) { return (jsonDictionaryContract.OverrideCreator ?? jsonDictionaryContract.ParameterizedCreator)(dictionary); } if (dictionary is IWrappedDictionary wrappedDictionary) { return wrappedDictionary.UnderlyingDictionary; } return dictionary; } object dictionary2; if (!jsonDictionaryContract.ShouldCreateWrapper && existingValue is IDictionary) { dictionary2 = (IDictionary)existingValue; } else { IDictionary dictionary3 = jsonDictionaryContract.CreateWrapper(existingValue); dictionary2 = dictionary3; } return PopulateDictionary((IDictionary)dictionary2, reader, jsonDictionaryContract, member, id); } case JsonContractType.Dynamic: { JsonDynamicContract contract3 = (JsonDynamicContract)contract; return CreateDynamic(reader, contract3, member, id); } case JsonContractType.Serializable: { JsonISerializableContract contract2 = (JsonISerializableContract)contract; return CreateISerializable(reader, contract2, member, id); } } string format = "Cannot deserialize the current JSON object (e.g. {{\"name\":\"value\"}}) into type '{0}' because the type requires a {1} to deserialize correctly." + Environment.NewLine + "To fix this error either change the JSON to a {1} or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object." + Environment.NewLine; format = format.FormatWith(CultureInfo.InvariantCulture, objectType2, GetExpectedDescription(contract)); throw JsonSerializationException.Create(reader, format); } private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue, out object? newValue, out string? id) { id = null; newValue = null; if (reader.TokenType == JsonToken.StartObject) { JObject jObject = (JObject)reader.CurrentToken; JProperty jProperty = jObject.Property("$ref", StringComparison.Ordinal); if (jProperty != null) { JToken value = jProperty.Value; if (value.Type != JTokenType.String && value.Type != JTokenType.Null) { throw JsonSerializationException.Create(value, value.Path, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, "$ref"), null); } string text = (string?)(JToken?)jProperty; if (text != null) { JToken jToken = jProperty.Next ?? jProperty.Previous; if (jToken != null) { throw JsonSerializationException.Create(jToken, jToken.Path, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, "$ref"), null); } newValue = Serializer.GetReferenceResolver().ResolveReference(this, text); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, text, newValue.GetType())), null); } reader.Skip(); return true; } } JToken jToken2 = jObject["$type"]; if (jToken2 != null) { string qualifiedTypeName = (string?)jToken2; JsonReader jsonReader = jToken2.CreateReader(); jsonReader.ReadAndAssert(); ResolveTypeName(jsonReader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName); if (jObject["$value"] != null) { while (true) { reader.ReadAndAssert(); if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "$value") { break; } reader.ReadAndAssert(); reader.Skip(); } return false; } } JToken jToken3 = jObject["$id"]; if (jToken3 != null) { id = (string?)jToken3; } JToken jToken4 = jObject["$values"]; if (jToken4 != null) { JsonReader jsonReader2 = jToken4.CreateReader(); jsonReader2.ReadAndAssert(); newValue = CreateList(jsonReader2, objectType, contract, member, existingValue, id); reader.Skip(); return true; } } reader.ReadAndAssert(); return false; } private bool ReadMetadataProperties(JsonReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue, out object? newValue, out string? id) { id = null; newValue = null; if (reader.TokenType == JsonToken.PropertyName) { string text = reader.Value.ToString(); if (text.Length > 0 && text[0] == '$') { bool flag; do { text = reader.Value.ToString(); if (string.Equals(text, "$ref", StringComparison.Ordinal)) { reader.ReadAndAssert(); if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Null) { throw JsonSerializationException.Create(reader, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, "$ref")); } string text2 = reader.Value?.ToString(); reader.ReadAndAssert(); if (text2 != null) { if (reader.TokenType == JsonToken.PropertyName) { throw JsonSerializationException.Create(reader, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, "$ref")); } newValue = Serializer.GetReferenceResolver().ResolveReference(this, text2); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, text2, newValue.GetType())), null); } return true; } flag = true; } else if (string.Equals(text, "$type", StringComparison.Ordinal)) { reader.ReadAndAssert(); string qualifiedTypeName = reader.Value.ToString(); ResolveTypeName(reader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName); reader.ReadAndAssert(); flag = true; } else if (string.Equals(text, "$id", StringComparison.Ordinal)) { reader.ReadAndAssert(); id = reader.Value?.ToString(); reader.ReadAndAssert(); flag = true; } else { if (string.Equals(text, "$values", StringComparison.Ordinal)) { reader.ReadAndAssert(); object obj = CreateList(reader, objectType, contract, member, existingValue, id); reader.ReadAndAssert(); newValue = obj; return true; } flag = false; } } while (flag && reader.TokenType == JsonToken.PropertyName); } } return false; } private void ResolveTypeName(JsonReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, string qualifiedTypeName) { if ((member?.TypeNameHandling ?? containerContract?.ItemTypeNameHandling ?? containerMember?.ItemTypeNameHandling ?? Serializer._typeNameHandling) != 0) { StructMultiKey structMultiKey = ReflectionUtils.SplitFullyQualifiedTypeName(qualifiedTypeName); Type type; try { type = Serializer._serializationBinder.BindToType(structMultiKey.Value1, structMultiKey.Value2); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error resolving type specified in JSON '{0}'.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName), ex); } if (type == null) { throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' was not resolved.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName)); } if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved type '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName, type)), null); } if (objectType != null && objectType != typeof(IDynamicMetaObjectProvider) && !objectType.IsAssignableFrom(type)) { throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, type.AssemblyQualifiedName, objectType.AssemblyQualifiedName)); } objectType = type; contract = GetContract(type); } } private JsonArrayContract EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract) { if (contract == null) { throw JsonSerializationException.Create(reader, "Could not resolve type '{0}' to a JsonContract.".FormatWith(CultureInfo.InvariantCulture, objectType)); } JsonArrayContract obj = contract as JsonArrayContract; if (obj == null) { string format = "Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '{0}' because the type requires a {1} to deserialize correctly." + Environment.NewLine + "To fix this error either change the JSON to a {1} or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array." + Environment.NewLine; format = format.FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract)); throw JsonSerializationException.Create(reader, format); } return obj; } private object? CreateList(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, object? existingValue, string? id) { if (HasNoDefinedType(contract)) { return CreateJToken(reader, contract); } JsonArrayContract jsonArrayContract = EnsureArrayContract(reader, objectType, contract); if (existingValue == null) { bool createdFromNonDefaultCreator; IList list = CreateNewList(reader, jsonArrayContract, out createdFromNonDefaultCreator); if (createdFromNonDefaultCreator) { if (id != null) { throw JsonSerializationException.Create(reader, "Cannot preserve reference to array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.OnSerializingCallbacks.Count > 0) { throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.OnErrorCallbacks.Count > 0) { throw JsonSerializationException.Create(reader, "Cannot call OnError on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (!jsonArrayContract.HasParameterizedCreatorInternal && !jsonArrayContract.IsArray) { throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } } if (!jsonArrayContract.IsMultidimensionalArray) { PopulateList(list, reader, jsonArrayContract, member, id); } else { PopulateMultidimensionalArray(list, reader, jsonArrayContract, member, id); } if (createdFromNonDefaultCreator) { if (jsonArrayContract.IsMultidimensionalArray) { list = CollectionUtils.ToMultidimensionalArray(list, jsonArrayContract.CollectionItemType, contract.CreatedType.GetArrayRank()); } else { if (!jsonArrayContract.IsArray) { return (jsonArrayContract.OverrideCreator ?? jsonArrayContract.ParameterizedCreator)(list); } Array array = Array.CreateInstance(jsonArrayContract.CollectionItemType, list.Count); list.CopyTo(array, 0); list = array; } } else if (list is IWrappedCollection wrappedCollection) { return wrappedCollection.UnderlyingCollection; } return list; } if (!jsonArrayContract.CanDeserialize) { throw JsonSerializationException.Create(reader, "Cannot populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType)); } IList list3; if (!jsonArrayContract.ShouldCreateWrapper && existingValue is IList list2) { list3 = list2; } else { IList list4 = jsonArrayContract.CreateWrapper(existingValue); list3 = list4; } return PopulateList(list3, reader, jsonArrayContract, member, id); } private bool HasNoDefinedType(JsonContract? contract) { if (contract != null && !(contract.UnderlyingType == typeof(object)) && contract.ContractType != JsonContractType.Linq) { return contract.UnderlyingType == typeof(IDynamicMetaObjectProvider); } return true; } private object? EnsureType(JsonReader reader, object? value, CultureInfo culture, JsonContract? contract, Type? targetType) { if (targetType == null) { return value; } if (ReflectionUtils.GetObjectType(value) != targetType) { if (value == null && contract.IsNullable) { return null; } try { if (contract.IsConvertable) { JsonPrimitiveContract jsonPrimitiveContract = (JsonPrimitiveContract)contract; DateTime dt; if (contract.IsEnum) { if (value is string value2) { return EnumUtils.ParseEnum(contract.NonNullableUnderlyingType, null, value2, disallowNumber: false); } if (ConvertUtils.IsInteger(jsonPrimitiveContract.TypeCode)) { return Enum.ToObject(contract.NonNullableUnderlyingType, value); } } else if (contract.NonNullableUnderlyingType == typeof(DateTime) && value is string s && DateTimeUtils.TryParseDateTime(s, reader.DateTimeZoneHandling, reader.DateFormatString, reader.Culture, out dt)) { return DateTimeUtils.EnsureDateTime(dt, reader.DateTimeZoneHandling); } if (value is BigInteger i) { return ConvertUtils.FromBigInteger(i, contract.NonNullableUnderlyingType); } return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture); } return ConvertUtils.ConvertOrCast(value, culture, contract.NonNullableUnderlyingType); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(value), targetType), ex); } } return value; } private bool SetPropertyValue(JsonProperty property, JsonConverter? propertyConverter, JsonContainerContract? containerContract, JsonProperty? containerProperty, JsonReader reader, object target) { if (CalculatePropertyDetails(property, ref propertyConverter, containerContract, containerProperty, reader, target, out bool useExistingValue, out object currentValue, out JsonContract propertyContract, out bool gottenCurrentValue, out bool ignoredValue)) { if (ignoredValue) { return true; } return false; } object obj; if (propertyConverter != null && propertyConverter.CanRead) { if (!gottenCurrentValue && property.Readable) { currentValue = property.ValueProvider.GetValue(target); } obj = DeserializeConvertable(propertyConverter, reader, property.PropertyType, currentValue); } else { obj = CreateValueInternal(reader, property.PropertyType, propertyContract, property, containerContract, containerProperty, useExistingValue ? currentValue : null); } if ((!useExistingValue || obj != currentValue) && ShouldSetPropertyValue(property, containerContract as JsonObjectContract, obj)) { property.ValueProvider.SetValue(target, obj); if (property.SetIsSpecified != null) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "IsSpecified for property '{0}' on {1} set to true.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType)), null); } property.SetIsSpecified(target, true); } return true; } return useExistingValue; } private bool CalculatePropertyDetails(JsonProperty property, ref JsonConverter? propertyConverter, JsonContainerContract? containerContract, JsonProperty? containerProperty, JsonReader reader, object target, out bool useExistingValue, out object? currentValue, out JsonContract? propertyContract, out bool gottenCurrentValue, out bool ignoredValue) { currentValue = null; useExistingValue = false; propertyContract = null; gottenCurrentValue = false; ignoredValue = false; if (property.Ignored) { return true; } JsonToken tokenType = reader.TokenType; if (property.PropertyContract == null) { property.PropertyContract = GetContractSafe(property.PropertyType); } if (property.ObjectCreationHandling.GetValueOrDefault(Serializer._objectCreationHandling) != ObjectCreationHandling.Replace && (tokenType == JsonToken.StartArray || tokenType == JsonToken.StartObject || propertyConverter != null) && property.Readable) { JsonContract? propertyContract2 = property.PropertyContract; if (propertyContract2 == null || propertyContract2.ContractType != JsonContractType.Linq) { currentValue = property.ValueProvider.GetValue(target); gottenCurrentValue = true; if (currentValue != null) { propertyContract = GetContract(currentValue.GetType()); useExistingValue = !propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType(); } } } if (!property.Writable && !useExistingValue) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Unable to deserialize value to non-writable property '{0}' on {1}.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType)), null); } return true; } if (tokenType == JsonToken.Null && ResolvedNullValueHandling(containerContract as JsonObjectContract, property) == NullValueHandling.Ignore) { ignoredValue = true; return true; } if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && JsonTokenUtils.IsPrimitiveToken(tokenType) && MiscellaneousUtils.ValueEquals(reader.Value, property.GetResolvedDefaultValue())) { ignoredValue = true; return true; } if (currentValue == null) { propertyContract = property.PropertyContract; } else { propertyContract = GetContract(currentValue.GetType()); if (propertyContract != property.PropertyContract) { propertyConverter = GetConverter(propertyContract, property.Converter, containerContract, containerProperty); } } return false; } private void AddReference(JsonReader reader, string id, object value) { try { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Read object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, id, value.GetType())), null); } Serializer.GetReferenceResolver().AddReference(this, id, value); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error reading object reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, id), ex); } } private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag) { return (value & flag) == flag; } private bool ShouldSetPropertyValue(JsonProperty property, JsonObjectContract? contract, object? value) { if (value == null && ResolvedNullValueHandling(contract, property) == NullValueHandling.Ignore) { return false; } if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && MiscellaneousUtils.ValueEquals(value, property.GetResolvedDefaultValue())) { return false; } if (!property.Writable) { return false; } return true; } private IList CreateNewList(JsonReader reader, JsonArrayContract contract, out bool createdFromNonDefaultCreator) { if (!contract.CanDeserialize) { throw JsonSerializationException.Create(reader, "Cannot create and populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType)); } if (contract.OverrideCreator != null) { if (contract.HasParameterizedCreator) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryCollection(); } object obj = contract.OverrideCreator(); if (contract.ShouldCreateWrapper) { obj = contract.CreateWrapper(obj); } createdFromNonDefaultCreator = false; return (IList)obj; } if (contract.IsReadOnlyOrFixedSize) { createdFromNonDefaultCreator = true; IList list = contract.CreateTemporaryCollection(); if (contract.ShouldCreateWrapper) { list = contract.CreateWrapper(list); } return list; } if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) { object obj2 = contract.DefaultCreator(); if (contract.ShouldCreateWrapper) { obj2 = contract.CreateWrapper(obj2); } createdFromNonDefaultCreator = false; return (IList)obj2; } if (contract.HasParameterizedCreatorInternal) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryCollection(); } if (!contract.IsInstantiable) { throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } private IDictionary CreateNewDictionary(JsonReader reader, JsonDictionaryContract contract, out bool createdFromNonDefaultCreator) { if (contract.OverrideCreator != null) { if (contract.HasParameterizedCreator) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryDictionary(); } createdFromNonDefaultCreator = false; return (IDictionary)contract.OverrideCreator(); } if (contract.IsReadOnlyOrFixedSize) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryDictionary(); } if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) { object obj = contract.DefaultCreator(); if (contract.ShouldCreateWrapper) { obj = contract.CreateWrapper(obj); } createdFromNonDefaultCreator = false; return (IDictionary)obj; } if (contract.HasParameterizedCreatorInternal) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryDictionary(); } if (!contract.IsInstantiable) { throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } private void OnDeserializing(JsonReader reader, JsonContract contract, object value) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); } contract.InvokeOnDeserializing(value, Serializer._context); } private void OnDeserialized(JsonReader reader, JsonContract contract, object value) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Finished deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); } contract.InvokeOnDeserialized(value, Serializer._context); } private object PopulateDictionary(IDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty? containerProperty, string? id) { object obj = ((dictionary is IWrappedDictionary wrappedDictionary) ? wrappedDictionary.UnderlyingDictionary : dictionary); if (id != null) { AddReference(reader, id, obj); } OnDeserializing(reader, contract, obj); int depth = reader.Depth; if (contract.KeyContract == null) { contract.KeyContract = GetContractSafe(contract.DictionaryKeyType); } if (contract.ItemContract == null) { contract.ItemContract = GetContractSafe(contract.DictionaryValueType); } JsonConverter jsonConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract, containerProperty); PrimitiveTypeCode primitiveTypeCode = ((contract.KeyContract is JsonPrimitiveContract jsonPrimitiveContract) ? jsonPrimitiveContract.TypeCode : PrimitiveTypeCode.Empty); bool flag = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: { object obj2 = reader.Value; if (CheckPropertyName(reader, obj2.ToString())) { break; } try { try { switch (primitiveTypeCode) { case PrimitiveTypeCode.DateTime: case PrimitiveTypeCode.DateTimeNullable: { obj2 = (DateTimeUtils.TryParseDateTime(obj2.ToString(), reader.DateTimeZoneHandling, reader.DateFormatString, reader.Culture, out var dt2) ? ((object)dt2) : EnsureType(reader, obj2, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType)); break; } case PrimitiveTypeCode.DateTimeOffset: case PrimitiveTypeCode.DateTimeOffsetNullable: { obj2 = (DateTimeUtils.TryParseDateTimeOffset(obj2.ToString(), reader.DateFormatString, reader.Culture, out var dt) ? ((object)dt) : EnsureType(reader, obj2, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType)); break; } default: obj2 = ((contract.KeyContract != null && contract.KeyContract.IsEnum) ? EnumUtils.ParseEnum(contract.KeyContract.NonNullableUnderlyingType, (Serializer._contractResolver as DefaultContractResolver)?.NamingStrategy, obj2.ToString(), disallowNumber: false) : EnsureType(reader, obj2, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType)); break; } } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Could not convert string '{0}' to dictionary key type '{1}'. Create a TypeConverter to convert from the string to the key type object.".FormatWith(CultureInfo.InvariantCulture, reader.Value, contract.DictionaryKeyType), ex); } if (!reader.ReadForType(contract.ItemContract, jsonConverter != null)) { throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } object value = ((jsonConverter == null || !jsonConverter.CanRead) ? CreateValueInternal(reader, contract.DictionaryValueType, contract.ItemContract, null, contract, containerProperty, null) : DeserializeConvertable(jsonConverter, reader, contract.DictionaryValueType, null)); dictionary[obj2] = value; } catch (Exception ex2) { if (IsErrorHandled(obj, contract, obj2, reader as IJsonLineInfo, reader.Path, ex2)) { HandleError(reader, readPastError: true, depth); break; } throw; } break; } case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); case JsonToken.Comment: break; } } while (!flag && reader.Read()); if (!flag) { ThrowUnexpectedEndException(reader, contract, obj, "Unexpected end when deserializing object."); } OnDeserialized(reader, contract, obj); return obj; } private object PopulateMultidimensionalArray(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty? containerProperty, string? id) { int arrayRank = contract.UnderlyingType.GetArrayRank(); if (id != null) { AddReference(reader, id, list); } OnDeserializing(reader, contract, list); JsonContract contractSafe = GetContractSafe(contract.CollectionItemType); JsonConverter converter = GetConverter(contractSafe, null, contract, containerProperty); int? num = null; Stack stack = new Stack(); stack.Push(list); IList list2 = list; bool flag = false; do { int depth = reader.Depth; if (stack.Count == arrayRank) { try { if (reader.ReadForType(contractSafe, converter != null)) { switch (reader.TokenType) { case JsonToken.EndArray: stack.Pop(); list2 = stack.Peek(); num = null; break; default: { object value = ((converter == null || !converter.CanRead) ? CreateValueInternal(reader, contract.CollectionItemType, contractSafe, null, contract, containerProperty, null) : DeserializeConvertable(converter, reader, contract.CollectionItemType, null)); list2.Add(value); break; } case JsonToken.Comment: break; } continue; } } catch (Exception ex) { JsonPosition position = reader.GetPosition(depth); if (IsErrorHandled(list, contract, position.Position, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: true, depth + 1); if (num.HasValue && num == position.Position) { throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex); } num = position.Position; continue; } throw; } break; } if (!reader.Read()) { break; } switch (reader.TokenType) { case JsonToken.StartArray: { IList list3 = new List(); list2.Add(list3); stack.Push(list3); list2 = list3; break; } case JsonToken.EndArray: stack.Pop(); if (stack.Count > 0) { list2 = stack.Peek(); } else { flag = true; } break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing multidimensional array: " + reader.TokenType); case JsonToken.Comment: break; } } while (!flag); if (!flag) { ThrowUnexpectedEndException(reader, contract, list, "Unexpected end when deserializing array."); } OnDeserialized(reader, contract, list); return list; } private void ThrowUnexpectedEndException(JsonReader reader, JsonContract contract, object? currentObject, string message) { try { throw JsonSerializationException.Create(reader, message); } catch (Exception ex) { if (IsErrorHandled(currentObject, contract, null, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: false, 0); return; } throw; } } private object PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty? containerProperty, string? id) { object obj = ((list is IWrappedCollection wrappedCollection) ? wrappedCollection.UnderlyingCollection : list); if (id != null) { AddReference(reader, id, obj); } if (list.IsFixedSize) { reader.Skip(); return obj; } OnDeserializing(reader, contract, obj); int depth = reader.Depth; if (contract.ItemContract == null) { contract.ItemContract = GetContractSafe(contract.CollectionItemType); } JsonConverter converter = GetConverter(contract.ItemContract, null, contract, containerProperty); int? num = null; bool flag = false; do { try { if (reader.ReadForType(contract.ItemContract, converter != null)) { switch (reader.TokenType) { case JsonToken.EndArray: flag = true; break; default: { object value = ((converter == null || !converter.CanRead) ? CreateValueInternal(reader, contract.CollectionItemType, contract.ItemContract, null, contract, containerProperty, null) : DeserializeConvertable(converter, reader, contract.CollectionItemType, null)); list.Add(value); break; } case JsonToken.Comment: break; } continue; } } catch (Exception ex) { JsonPosition position = reader.GetPosition(depth); if (IsErrorHandled(obj, contract, position.Position, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: true, depth + 1); if (num.HasValue && num == position.Position) { throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex); } num = position.Position; continue; } throw; } break; } while (!flag); if (!flag) { ThrowUnexpectedEndException(reader, contract, obj, "Unexpected end when deserializing array."); } OnDeserialized(reader, contract, obj); return obj; } private object CreateISerializable(JsonReader reader, JsonISerializableContract contract, JsonProperty? member, string? id) { Type underlyingType = contract.UnderlyingType; if (!JsonTypeReflector.FullyTrusted) { string format = "Type '{0}' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine + "To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine; format = format.FormatWith(CultureInfo.InvariantCulture, underlyingType); throw JsonSerializationException.Create(reader, format); } if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using ISerializable constructor.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); } SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new JsonFormatterConverter(this, contract, member)); bool flag = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: { string text = reader.Value.ToString(); if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } serializationInfo.AddValue(text, JToken.ReadFrom(reader)); break; } case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); case JsonToken.Comment: break; } } while (!flag && reader.Read()); if (!flag) { ThrowUnexpectedEndException(reader, contract, serializationInfo, "Unexpected end when deserializing object."); } if (!contract.IsInstantiable) { throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.ISerializableCreator == null) { throw JsonSerializationException.Create(reader, "ISerializable type '{0}' does not have a valid constructor. To correctly implement ISerializable a constructor that takes SerializationInfo and StreamingContext parameters should be present.".FormatWith(CultureInfo.InvariantCulture, underlyingType)); } object obj = contract.ISerializableCreator(serializationInfo, Serializer._context); if (id != null) { AddReference(reader, id, obj); } OnDeserializing(reader, contract, obj); OnDeserialized(reader, contract, obj); return obj; } internal object? CreateISerializableItem(JToken token, Type type, JsonISerializableContract contract, JsonProperty? member) { JsonContract contractSafe = GetContractSafe(type); JsonConverter converter = GetConverter(contractSafe, null, contract, member); JsonReader jsonReader = token.CreateReader(); jsonReader.MaxDepth = Serializer.MaxDepth; jsonReader.ReadAndAssert(); if (converter != null && converter.CanRead) { return DeserializeConvertable(converter, jsonReader, type, null); } return CreateValueInternal(jsonReader, type, contractSafe, null, contract, member, null); } private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, JsonProperty? member, string? id) { if (!contract.IsInstantiable) { throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) { IDynamicMetaObjectProvider dynamicMetaObjectProvider = (IDynamicMetaObjectProvider)contract.DefaultCreator(); if (id != null) { AddReference(reader, id, dynamicMetaObjectProvider); } OnDeserializing(reader, contract, dynamicMetaObjectProvider); int depth = reader.Depth; bool flag = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: { string text = reader.Value.ToString(); try { if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } JsonProperty closestMatchProperty = contract.Properties.GetClosestMatchProperty(text); if (closestMatchProperty != null && closestMatchProperty.Writable && !closestMatchProperty.Ignored) { if (closestMatchProperty.PropertyContract == null) { closestMatchProperty.PropertyContract = GetContractSafe(closestMatchProperty.PropertyType); } JsonConverter converter = GetConverter(closestMatchProperty.PropertyContract, closestMatchProperty.Converter, null, null); if (!SetPropertyValue(closestMatchProperty, converter, null, member, reader, dynamicMetaObjectProvider)) { reader.Skip(); } } else { Type type = (JsonTokenUtils.IsPrimitiveToken(reader.TokenType) ? reader.ValueType : typeof(IDynamicMetaObjectProvider)); JsonContract contractSafe = GetContractSafe(type); JsonConverter converter2 = GetConverter(contractSafe, null, null, member); object value = ((converter2 == null || !converter2.CanRead) ? CreateValueInternal(reader, type, contractSafe, null, null, member, null) : DeserializeConvertable(converter2, reader, type, null)); contract.TrySetMember(dynamicMetaObjectProvider, text, value); } } catch (Exception ex) { if (IsErrorHandled(dynamicMetaObjectProvider, contract, text, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: true, depth); break; } throw; } break; } case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); } } while (!flag && reader.Read()); if (!flag) { ThrowUnexpectedEndException(reader, contract, dynamicMetaObjectProvider, "Unexpected end when deserializing object."); } OnDeserialized(reader, contract, dynamicMetaObjectProvider); return dynamicMetaObjectProvider; } throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty? containerProperty, ObjectConstructor creator, string? id) { ValidationUtils.ArgumentNotNull(creator, "creator"); bool flag = contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate); Type underlyingType = contract.UnderlyingType; if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { string arg = string.Join(", ", contract.CreatorParameters.Select((JsonProperty p) => p.PropertyName)); TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using creator with parameters: {1}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, arg)), null); } List list = ResolvePropertyAndCreatorValues(contract, containerProperty, reader, underlyingType); if (flag) { foreach (JsonProperty property in contract.Properties) { if (!property.Ignored && list.All((CreatorPropertyContext p) => p.Property != property)) { list.Add(new CreatorPropertyContext(property.PropertyName) { Property = property, Presence = PropertyPresence.None }); } } } object[] array = new object[contract.CreatorParameters.Count]; foreach (CreatorPropertyContext item in list) { if (flag && item.Property != null && !item.Presence.HasValue) { object value = item.Value; PropertyPresence value2 = ((value == null) ? PropertyPresence.Null : ((!(value is string s)) ? PropertyPresence.Value : (CoerceEmptyStringToNull(item.Property.PropertyType, item.Property.PropertyContract, s) ? PropertyPresence.Null : PropertyPresence.Value))); item.Presence = value2; } JsonProperty jsonProperty = item.ConstructorProperty; if (jsonProperty == null && item.Property != null) { jsonProperty = contract.CreatorParameters.ForgivingCaseSensitiveFind((JsonProperty p) => p.PropertyName, item.Property.UnderlyingName); } if (jsonProperty == null || jsonProperty.Ignored) { continue; } if (flag && (item.Presence == PropertyPresence.None || item.Presence == PropertyPresence.Null)) { if (jsonProperty.PropertyContract == null) { jsonProperty.PropertyContract = GetContractSafe(jsonProperty.PropertyType); } if (HasFlag(jsonProperty.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate)) { item.Value = EnsureType(reader, jsonProperty.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, jsonProperty.PropertyContract, jsonProperty.PropertyType); } } int num = contract.CreatorParameters.IndexOf(jsonProperty); array[num] = item.Value; item.Used = true; } object obj = creator(array); if (id != null) { AddReference(reader, id, obj); } OnDeserializing(reader, contract, obj); foreach (CreatorPropertyContext item2 in list) { if (item2.Used || item2.Property == null || item2.Property.Ignored || item2.Presence == PropertyPresence.None) { continue; } JsonProperty property2 = item2.Property; object value3 = item2.Value; if (ShouldSetPropertyValue(property2, contract, value3)) { property2.ValueProvider.SetValue(obj, value3); item2.Used = true; } else { if (property2.Writable || value3 == null) { continue; } JsonContract jsonContract = Serializer._contractResolver.ResolveContract(property2.PropertyType); if (jsonContract.ContractType == JsonContractType.Array) { JsonArrayContract jsonArrayContract = (JsonArrayContract)jsonContract; if (jsonArrayContract.CanDeserialize && !jsonArrayContract.IsReadOnlyOrFixedSize) { object value4 = property2.ValueProvider.GetValue(obj); if (value4 != null) { jsonArrayContract = (JsonArrayContract)GetContract(value4.GetType()); object obj2; if (!jsonArrayContract.ShouldCreateWrapper) { obj2 = (IList)value4; } else { IList list2 = jsonArrayContract.CreateWrapper(value4); obj2 = list2; } IList list3 = (IList)obj2; if (!list3.IsFixedSize) { object obj3; if (!jsonArrayContract.ShouldCreateWrapper) { obj3 = (IList)value3; } else { IList list2 = jsonArrayContract.CreateWrapper(value3); obj3 = list2; } foreach (object item3 in (IEnumerable)obj3) { list3.Add(item3); } } } } } else if (jsonContract.ContractType == JsonContractType.Dictionary) { JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)jsonContract; if (!jsonDictionaryContract.IsReadOnlyOrFixedSize) { object value5 = property2.ValueProvider.GetValue(obj); if (value5 != null) { object obj4; if (!jsonDictionaryContract.ShouldCreateWrapper) { obj4 = (IDictionary)value5; } else { IDictionary dictionary = jsonDictionaryContract.CreateWrapper(value5); obj4 = dictionary; } IDictionary dictionary2 = (IDictionary)obj4; object obj5; if (!jsonDictionaryContract.ShouldCreateWrapper) { obj5 = (IDictionary)value3; } else { IDictionary dictionary = jsonDictionaryContract.CreateWrapper(value3); obj5 = dictionary; } foreach (DictionaryEntry item4 in (IDictionary)obj5) { dictionary2[item4.Key] = item4.Value; } } } } item2.Used = true; } } if (contract.ExtensionDataSetter != null) { foreach (CreatorPropertyContext item5 in list) { if (!item5.Used && item5.Presence != PropertyPresence.None) { contract.ExtensionDataSetter(obj, item5.Name, item5.Value); } } } if (flag) { foreach (CreatorPropertyContext item6 in list) { if (item6.Property != null) { EndProcessProperty(obj, reader, contract, reader.Depth, item6.Property, item6.Presence.GetValueOrDefault(), !item6.Used); } } } OnDeserialized(reader, contract, obj); return obj; } private object? DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, object? existingValue) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), null); } object? result = converter.ReadJson(reader, objectType, existingValue, GetInternalSerializer()); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Finished deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), null); } return result; } private List ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty? containerProperty, JsonReader reader, Type objectType) { List list = new List(); bool flag = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: { string text = reader.Value.ToString(); CreatorPropertyContext creatorPropertyContext = new CreatorPropertyContext(text) { ConstructorProperty = contract.CreatorParameters.GetClosestMatchProperty(text), Property = contract.Properties.GetClosestMatchProperty(text) }; list.Add(creatorPropertyContext); JsonProperty jsonProperty = creatorPropertyContext.ConstructorProperty ?? creatorPropertyContext.Property; if (jsonProperty != null) { if (!jsonProperty.Ignored) { if (jsonProperty.PropertyContract == null) { jsonProperty.PropertyContract = GetContractSafe(jsonProperty.PropertyType); } JsonConverter converter = GetConverter(jsonProperty.PropertyContract, jsonProperty.Converter, contract, containerProperty); if (!reader.ReadForType(jsonProperty.PropertyContract, converter != null)) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } if (converter != null && converter.CanRead) { creatorPropertyContext.Value = DeserializeConvertable(converter, reader, jsonProperty.PropertyType, null); } else { creatorPropertyContext.Value = CreateValueInternal(reader, jsonProperty.PropertyType, jsonProperty.PropertyContract, jsonProperty, contract, containerProperty, null); } break; } if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } } else { if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}.".FormatWith(CultureInfo.InvariantCulture, text, contract.UnderlyingType)), null); } if ((contract.MissingMemberHandling ?? Serializer._missingMemberHandling) == MissingMemberHandling.Error) { throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, text, objectType.Name)); } } if (contract.ExtensionDataSetter != null) { creatorPropertyContext.Value = ReadExtensionDataValue(contract, containerProperty, reader); } else { reader.Skip(); } break; } case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); case JsonToken.Comment: break; } } while (!flag && reader.Read()); if (!flag) { ThrowUnexpectedEndException(reader, contract, null, "Unexpected end when deserializing object."); } return list; } public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty? containerMember, JsonProperty? containerProperty, string? id, out bool createdFromNonDefaultCreator) { object obj = null; if (objectContract.OverrideCreator != null) { if (objectContract.CreatorParameters.Count > 0) { createdFromNonDefaultCreator = true; return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.OverrideCreator, id); } obj = objectContract.OverrideCreator(CollectionUtils.ArrayEmpty()); } else if (objectContract.DefaultCreator != null && (!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParameterizedCreator == null)) { obj = objectContract.DefaultCreator(); } else if (objectContract.ParameterizedCreator != null) { createdFromNonDefaultCreator = true; return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.ParameterizedCreator, id); } if (obj == null) { if (!objectContract.IsInstantiable) { throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType)); } throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType)); } createdFromNonDefaultCreator = false; return obj; } private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty? member, string? id) { OnDeserializing(reader, contract, newObject); Dictionary dictionary = ((contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate)) ? contract.Properties.ToDictionary((JsonProperty m) => m, (JsonProperty m) => PropertyPresence.None) : null); if (id != null) { AddReference(reader, id, newObject); } int depth = reader.Depth; bool flag = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: { string text = reader.Value.ToString(); if (CheckPropertyName(reader, text)) { break; } try { JsonProperty closestMatchProperty = contract.Properties.GetClosestMatchProperty(text); if (closestMatchProperty == null) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}".FormatWith(CultureInfo.InvariantCulture, text, contract.UnderlyingType)), null); } if ((contract.MissingMemberHandling ?? Serializer._missingMemberHandling) == MissingMemberHandling.Error) { throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, text, contract.UnderlyingType.Name)); } if (reader.Read()) { SetExtensionData(contract, member, reader, text, newObject); } break; } if (closestMatchProperty.Ignored || !ShouldDeserialize(reader, closestMatchProperty, newObject)) { if (reader.Read()) { SetPropertyPresence(reader, closestMatchProperty, dictionary); SetExtensionData(contract, member, reader, text, newObject); } break; } if (closestMatchProperty.PropertyContract == null) { closestMatchProperty.PropertyContract = GetContractSafe(closestMatchProperty.PropertyType); } JsonConverter converter = GetConverter(closestMatchProperty.PropertyContract, closestMatchProperty.Converter, contract, member); if (!reader.ReadForType(closestMatchProperty.PropertyContract, converter != null)) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } SetPropertyPresence(reader, closestMatchProperty, dictionary); if (!SetPropertyValue(closestMatchProperty, converter, contract, member, reader, newObject)) { SetExtensionData(contract, member, reader, text, newObject); } } catch (Exception ex) { if (IsErrorHandled(newObject, contract, text, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: true, depth); break; } throw; } break; } case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); case JsonToken.Comment: break; } } while (!flag && reader.Read()); if (!flag) { ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object."); } if (dictionary != null) { foreach (KeyValuePair item in dictionary) { JsonProperty key = item.Key; PropertyPresence value = item.Value; EndProcessProperty(newObject, reader, contract, depth, key, value, setDefaultValue: true); } } OnDeserialized(reader, contract, newObject); return newObject; } private bool ShouldDeserialize(JsonReader reader, JsonProperty property, object target) { if (property.ShouldDeserialize == null) { return true; } bool flag = property.ShouldDeserialize(target); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, reader.Path, "ShouldDeserialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, flag)), null); } return flag; } private bool CheckPropertyName(JsonReader reader, string memberName) { if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead) { switch (memberName) { case "$id": case "$ref": case "$type": case "$values": reader.Skip(); return true; } } return false; } private void SetExtensionData(JsonObjectContract contract, JsonProperty? member, JsonReader reader, string memberName, object o) { if (contract.ExtensionDataSetter != null) { try { object value = ReadExtensionDataValue(contract, member, reader); contract.ExtensionDataSetter(o, memberName, value); return; } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error setting value in extension data for type '{0}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType), ex); } } reader.Skip(); } private object? ReadExtensionDataValue(JsonObjectContract contract, JsonProperty? member, JsonReader reader) { if (contract.ExtensionDataIsJToken) { return JToken.ReadFrom(reader); } return CreateValueInternal(reader, null, null, null, contract, member, null); } private void EndProcessProperty(object newObject, JsonReader reader, JsonObjectContract contract, int initialDepth, JsonProperty property, PropertyPresence presence, bool setDefaultValue) { if (presence != 0 && presence != PropertyPresence.Null) { return; } try { Required required = ((!property.Ignored) ? (property._required ?? contract.ItemRequired.GetValueOrDefault()) : Required.Default); switch (presence) { case PropertyPresence.None: if (required == Required.AllowNull || required == Required.Always) { throw JsonSerializationException.Create(reader, "Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName)); } if (setDefaultValue && !property.Ignored) { if (property.PropertyContract == null) { property.PropertyContract = GetContractSafe(property.PropertyType); } if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && property.Writable) { property.ValueProvider.SetValue(newObject, EnsureType(reader, property.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType)); } } break; case PropertyPresence.Null: switch (required) { case Required.Always: throw JsonSerializationException.Create(reader, "Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName)); case Required.DisallowNull: throw JsonSerializationException.Create(reader, "Required property '{0}' expects a non-null value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName)); } break; } } catch (Exception ex) { if (IsErrorHandled(newObject, contract, property.PropertyName, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: true, initialDepth); return; } throw; } } private void SetPropertyPresence(JsonReader reader, JsonProperty property, Dictionary? requiredProperties) { if (property != null && requiredProperties != null) { PropertyPresence value; switch (reader.TokenType) { case JsonToken.String: value = (CoerceEmptyStringToNull(property.PropertyType, property.PropertyContract, (string)reader.Value) ? PropertyPresence.Null : PropertyPresence.Value); break; case JsonToken.Null: case JsonToken.Undefined: value = PropertyPresence.Null; break; default: value = PropertyPresence.Value; break; } requiredProperties[property] = value; } } private void HandleError(JsonReader reader, bool readPastError, int initialDepth) { ClearErrorContext(); if (readPastError) { reader.Skip(); while (reader.Depth > initialDepth && reader.Read()) { } } } } internal class JsonSerializerInternalWriter : JsonSerializerInternalBase { private Type? _rootType; private int _rootLevel; private readonly List _serializeStack = new List(); public JsonSerializerInternalWriter(JsonSerializer serializer) : base(serializer) { } public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) { if (jsonWriter == null) { throw new ArgumentNullException("jsonWriter"); } _rootType = objectType; _rootLevel = _serializeStack.Count + 1; JsonContract contractSafe = GetContractSafe(value); try { if (ShouldWriteReference(value, null, contractSafe, null, null)) { WriteReference(jsonWriter, value); } else { SerializeValue(jsonWriter, value, contractSafe, null, null, null); } } catch (Exception ex) { if (IsErrorHandled(null, contractSafe, null, null, jsonWriter.Path, ex)) { HandleError(jsonWriter, 0); return; } ClearErrorContext(); throw; } finally { _rootType = null; } } private JsonSerializerProxy GetInternalSerializer() { if (InternalSerializer == null) { InternalSerializer = new JsonSerializerProxy(this); } return InternalSerializer; } private JsonContract? GetContractSafe(object? value) { if (value == null) { return null; } return GetContract(value); } private JsonContract GetContract(object value) { return Serializer._contractResolver.ResolveContract(value.GetType()); } private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { if (contract.TypeCode == PrimitiveTypeCode.Bytes && ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty)) { writer.WriteStartObject(); WriteTypeProperty(writer, contract.CreatedType); writer.WritePropertyName("$value", escape: false); JsonWriter.WriteValue(writer, contract.TypeCode, value); writer.WriteEndObject(); } else { JsonWriter.WriteValue(writer, contract.TypeCode, value); } } private void SerializeValue(JsonWriter writer, object? value, JsonContract? valueContract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { if (value == null) { writer.WriteNull(); return; } JsonConverter jsonConverter = member?.Converter ?? containerProperty?.ItemConverter ?? containerContract?.ItemConverter ?? valueContract.Converter ?? Serializer.GetMatchingConverter(valueContract.UnderlyingType) ?? valueContract.InternalConverter; if (jsonConverter != null && jsonConverter.CanWrite) { SerializeConvertable(writer, jsonConverter, value, valueContract, containerContract, containerProperty); return; } switch (valueContract.ContractType) { case JsonContractType.Object: SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.Array: { JsonArrayContract jsonArrayContract = (JsonArrayContract)valueContract; if (!jsonArrayContract.IsMultidimensionalArray) { SerializeList(writer, (IEnumerable)value, jsonArrayContract, member, containerContract, containerProperty); } else { SerializeMultidimensionalArray(writer, (Array)value, jsonArrayContract, member, containerContract, containerProperty); } break; } case JsonContractType.Primitive: SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.String: SerializeString(writer, value, (JsonStringContract)valueContract); break; case JsonContractType.Dictionary: { JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)valueContract; IDictionary values; if (!(value is IDictionary dictionary)) { IDictionary dictionary2 = jsonDictionaryContract.CreateWrapper(value); values = dictionary2; } else { values = dictionary; } SerializeDictionary(writer, values, jsonDictionaryContract, member, containerContract, containerProperty); break; } case JsonContractType.Dynamic: SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.Serializable: SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.Linq: ((JToken)value).WriteTo(writer, Serializer.Converters.ToArray()); break; } } private bool? ResolveIsReference(JsonContract contract, JsonProperty? property, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { bool? result = null; if (property != null) { result = property.IsReference; } if (!result.HasValue && containerProperty != null) { result = containerProperty.ItemIsReference; } if (!result.HasValue && collectionContract != null) { result = collectionContract.ItemIsReference; } if (!result.HasValue) { result = contract.IsReference; } return result; } private bool ShouldWriteReference(object? value, JsonProperty? property, JsonContract? valueContract, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { if (value == null) { return false; } if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String) { return false; } bool? flag = ResolveIsReference(valueContract, property, collectionContract, containerProperty); if (!flag.HasValue) { flag = ((valueContract.ContractType != JsonContractType.Array) ? new bool?(HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects)) : new bool?(HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays))); } if (!flag.GetValueOrDefault()) { return false; } return Serializer.GetReferenceResolver().IsReferenced(this, value); } private bool ShouldWriteProperty(object? memberValue, JsonObjectContract? containerContract, JsonProperty property) { if (memberValue == null && ResolvedNullValueHandling(containerContract, property) == NullValueHandling.Ignore) { return false; } if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) && MiscellaneousUtils.ValueEquals(memberValue, property.GetResolvedDefaultValue())) { return false; } return true; } private bool CheckForCircularReference(JsonWriter writer, object? value, JsonProperty? property, JsonContract? contract, JsonContainerContract? containerContract, JsonProperty? containerProperty) { if (value == null) { return true; } if (contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String) { return true; } ReferenceLoopHandling? referenceLoopHandling = null; if (property != null) { referenceLoopHandling = property.ReferenceLoopHandling; } if (!referenceLoopHandling.HasValue && containerProperty != null) { referenceLoopHandling = containerProperty.ItemReferenceLoopHandling; } if (!referenceLoopHandling.HasValue && containerContract != null) { referenceLoopHandling = containerContract.ItemReferenceLoopHandling; } if ((Serializer._equalityComparer != null) ? _serializeStack.Contains(value, Serializer._equalityComparer) : _serializeStack.Contains(value)) { string text = "Self referencing loop detected"; if (property != null) { text += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName); } text += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()); switch (referenceLoopHandling.GetValueOrDefault(Serializer._referenceLoopHandling)) { case ReferenceLoopHandling.Error: throw JsonSerializationException.Create(null, writer.ContainerPath, text, null); case ReferenceLoopHandling.Ignore: if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, text + ". Skipping serializing self referenced value."), null); } return false; case ReferenceLoopHandling.Serialize: if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, text + ". Serializing self referenced value."), null); } return true; } } return true; } private void WriteReference(JsonWriter writer, object value) { string reference = GetReference(writer, value); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Writing object reference to Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, value.GetType())), null); } writer.WriteStartObject(); writer.WritePropertyName("$ref", escape: false); writer.WriteValue(reference); writer.WriteEndObject(); } private string GetReference(JsonWriter writer, object value) { try { return Serializer.GetReferenceResolver().GetReference(this, value); } catch (Exception ex) { throw JsonSerializationException.Create(null, writer.ContainerPath, "Error writing object reference for '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), ex); } } internal static bool TryConvertToString(object value, Type type, [NotNullWhen(true)] out string? s) { if (value is DateOnly dateOnly) { s = dateOnly.ToString("yyyy'-'MM'-'dd", CultureInfo.InvariantCulture); return true; } if (value is TimeOnly timeOnly) { s = timeOnly.ToString("HH':'mm':'ss.FFFFFFF", CultureInfo.InvariantCulture); return true; } if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out TypeConverter typeConverter)) { s = typeConverter.ConvertToInvariantString(value); return true; } if (value is Type type2) { s = type2.AssemblyQualifiedName; return true; } s = null; return false; } private void SerializeString(JsonWriter writer, object value, JsonStringContract contract) { OnSerializing(writer, contract, value); TryConvertToString(value, contract.UnderlyingType, out string s); writer.WriteValue(s); OnSerialized(writer, contract, value); } private void OnSerializing(JsonWriter writer, JsonContract contract, object value) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); } contract.InvokeOnSerializing(value, Serializer._context); } private void OnSerialized(JsonWriter writer, JsonContract contract, object value) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); } contract.InvokeOnSerialized(value, Serializer._context); } private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { OnSerializing(writer, contract, value); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); int top = writer.Top; for (int i = 0; i < contract.Properties.Count; i++) { JsonProperty jsonProperty = contract.Properties[i]; try { if (CalculatePropertyValues(writer, value, contract, member, jsonProperty, out JsonContract memberContract, out object memberValue)) { jsonProperty.WritePropertyName(writer); SerializeValue(writer, memberValue, memberContract, jsonProperty, contract, member); } } catch (Exception ex) { if (IsErrorHandled(value, contract, jsonProperty.PropertyName, null, writer.ContainerPath, ex)) { HandleError(writer, top); continue; } throw; } } IEnumerable> enumerable = contract.ExtensionDataGetter?.Invoke(value); if (enumerable != null) { foreach (KeyValuePair item in enumerable) { JsonContract contract2 = GetContract(item.Key); JsonContract contractSafe = GetContractSafe(item.Value); string propertyName = GetPropertyName(writer, item.Key, contract2, out var _); propertyName = ((contract.ExtensionDataNameResolver != null) ? contract.ExtensionDataNameResolver(propertyName) : propertyName); if (ShouldWriteReference(item.Value, null, contractSafe, contract, member)) { writer.WritePropertyName(propertyName); WriteReference(writer, item.Value); } else if (CheckForCircularReference(writer, item.Value, null, contractSafe, contract, member)) { writer.WritePropertyName(propertyName); SerializeValue(writer, item.Value, contractSafe, null, contract, member); } } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); } private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty? member, JsonProperty property, [NotNullWhen(true)] out JsonContract? memberContract, out object? memberValue) { if (!property.Ignored && property.Readable && ShouldSerialize(writer, property, value) && IsSpecified(writer, property, value)) { if (property.PropertyContract == null) { property.PropertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType); } memberValue = property.ValueProvider.GetValue(value); memberContract = (property.PropertyContract.IsSealed ? property.PropertyContract : GetContractSafe(memberValue)); if (ShouldWriteProperty(memberValue, contract as JsonObjectContract, property)) { if (ShouldWriteReference(memberValue, property, memberContract, contract, member)) { property.WritePropertyName(writer); WriteReference(writer, memberValue); return false; } if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member)) { return false; } if (memberValue == null) { JsonObjectContract jsonObjectContract = contract as JsonObjectContract; switch (property._required ?? (jsonObjectContract?.ItemRequired).GetValueOrDefault()) { case Required.Always: throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null); case Required.DisallowNull: throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a non-null value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null); } } return true; } } memberContract = null; memberValue = null; return false; } private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { writer.WriteStartObject(); if ((ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects)) && (member == null || member.Writable || HasCreatorParameter(collectionContract, member))) { WriteReferenceIdProperty(writer, contract.UnderlyingType, value); } if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty)) { WriteTypeProperty(writer, contract.UnderlyingType); } } private bool HasCreatorParameter(JsonContainerContract? contract, JsonProperty property) { if (!(contract is JsonObjectContract jsonObjectContract)) { return false; } return jsonObjectContract.CreatorParameters.Contains(property.PropertyName); } private void WriteReferenceIdProperty(JsonWriter writer, Type type, object value) { string reference = GetReference(writer, value); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "Writing object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, type)), null); } writer.WritePropertyName("$id", escape: false); writer.WriteValue(reference); } private void WriteTypeProperty(JsonWriter writer, Type type) { string typeName = ReflectionUtils.GetTypeName(type, Serializer._typeNameAssemblyFormatHandling, Serializer._serializationBinder); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "Writing type name '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, typeName, type)), null); } writer.WritePropertyName("$type", escape: false); writer.WriteValue(typeName); } private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag) { return (value & flag) == flag; } private bool HasFlag(PreserveReferencesHandling value, PreserveReferencesHandling flag) { return (value & flag) == flag; } private bool HasFlag(TypeNameHandling value, TypeNameHandling flag) { return (value & flag) == flag; } private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty)) { WriteReference(writer, value); } else if (CheckForCircularReference(writer, value, null, contract, collectionContract, containerProperty)) { _serializeStack.Add(value); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null); } converter.WriteJson(writer, value, GetInternalSerializer()); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null); } _serializeStack.RemoveAt(_serializeStack.Count - 1); } } private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { object obj = ((values is IWrappedCollection wrappedCollection) ? wrappedCollection.UnderlyingCollection : values); OnSerializing(writer, contract, obj); _serializeStack.Add(obj); bool flag = WriteStartArray(writer, obj, contract, member, collectionContract, containerProperty); writer.WriteStartArray(); int top = writer.Top; int num = 0; foreach (object value in values) { try { JsonContract jsonContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, jsonContract, contract, member)) { WriteReference(writer, value); } else if (CheckForCircularReference(writer, value, null, jsonContract, contract, member)) { SerializeValue(writer, value, jsonContract, null, contract, member); } } catch (Exception ex) { if (IsErrorHandled(obj, contract, num, null, writer.ContainerPath, ex)) { HandleError(writer, top); continue; } throw; } finally { num++; } } writer.WriteEndArray(); if (flag) { writer.WriteEndObject(); } _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, obj); } private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { OnSerializing(writer, contract, values); _serializeStack.Add(values); bool num = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty); SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, CollectionUtils.ArrayEmpty()); if (num) { writer.WriteEndObject(); } _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, values); } private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty? member, int initialDepth, int[] indices) { int num = indices.Length; int[] array = new int[num + 1]; for (int i = 0; i < num; i++) { array[i] = indices[i]; } writer.WriteStartArray(); for (int j = values.GetLowerBound(num); j <= values.GetUpperBound(num); j++) { array[num] = j; if (array.Length == values.Rank) { object value = values.GetValue(array); try { JsonContract jsonContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, jsonContract, contract, member)) { WriteReference(writer, value); } else if (CheckForCircularReference(writer, value, null, jsonContract, contract, member)) { SerializeValue(writer, value, jsonContract, null, contract, member); } } catch (Exception ex) { if (IsErrorHandled(values, contract, j, null, writer.ContainerPath, ex)) { HandleError(writer, initialDepth + 1); continue; } throw; } } else { SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, array); } } writer.WriteEndArray(); } private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { bool flag = (ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays)) && (member == null || member.Writable || HasCreatorParameter(containerContract, member)); bool flag2 = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty); bool num = flag || flag2; if (num) { writer.WriteStartObject(); if (flag) { WriteReferenceIdProperty(writer, contract.UnderlyingType, values); } if (flag2) { WriteTypeProperty(writer, values.GetType()); } writer.WritePropertyName("$values", escape: false); } if (contract.ItemContract == null) { contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object)); } return num; } [SecuritySafeCritical] private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { if (!JsonTypeReflector.FullyTrusted) { string format = "Type '{0}' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine + "To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine; format = format.FormatWith(CultureInfo.InvariantCulture, value.GetType()); throw JsonSerializationException.Create(null, writer.ContainerPath, format, null); } OnSerializing(writer, contract, value); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter()); value.GetObjectData(serializationInfo, Serializer._context); SerializationInfoEnumerator enumerator = serializationInfo.GetEnumerator(); while (enumerator.MoveNext()) { SerializationEntry current = enumerator.Current; JsonContract contractSafe = GetContractSafe(current.Value); if (ShouldWriteReference(current.Value, null, contractSafe, contract, member)) { writer.WritePropertyName(current.Name); WriteReference(writer, current.Value); } else if (CheckForCircularReference(writer, current.Value, null, contractSafe, contract, member)) { writer.WritePropertyName(current.Name); SerializeValue(writer, current.Value, contractSafe, null, contract, member); } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); } private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { OnSerializing(writer, contract, value); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); int top = writer.Top; for (int i = 0; i < contract.Properties.Count; i++) { JsonProperty jsonProperty = contract.Properties[i]; if (!jsonProperty.HasMemberAttribute) { continue; } try { if (CalculatePropertyValues(writer, value, contract, member, jsonProperty, out JsonContract memberContract, out object memberValue)) { jsonProperty.WritePropertyName(writer); SerializeValue(writer, memberValue, memberContract, jsonProperty, contract, member); } } catch (Exception ex) { if (IsErrorHandled(value, contract, jsonProperty.PropertyName, null, writer.ContainerPath, ex)) { HandleError(writer, top); continue; } throw; } } foreach (string dynamicMemberName in value.GetDynamicMemberNames()) { if (!contract.TryGetMember(value, dynamicMemberName, out object value2)) { continue; } try { JsonContract contractSafe = GetContractSafe(value2); if (ShouldWriteDynamicProperty(value2) && CheckForCircularReference(writer, value2, null, contractSafe, contract, member)) { string name = ((contract.PropertyNameResolver != null) ? contract.PropertyNameResolver(dynamicMemberName) : dynamicMemberName); writer.WritePropertyName(name); SerializeValue(writer, value2, contractSafe, null, contract, member); } } catch (Exception ex2) { if (IsErrorHandled(value, contract, dynamicMemberName, null, writer.ContainerPath, ex2)) { HandleError(writer, top); continue; } throw; } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); } private bool ShouldWriteDynamicProperty(object? memberValue) { if (Serializer._nullValueHandling == NullValueHandling.Ignore && memberValue == null) { return false; } if (HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Ignore) && (memberValue == null || MiscellaneousUtils.ValueEquals(memberValue, ReflectionUtils.GetDefaultValue(memberValue.GetType())))) { return false; } return true; } private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { TypeNameHandling value = member?.TypeNameHandling ?? containerProperty?.ItemTypeNameHandling ?? containerContract?.ItemTypeNameHandling ?? Serializer._typeNameHandling; if (HasFlag(value, typeNameHandlingFlag)) { return true; } if (HasFlag(value, TypeNameHandling.Auto)) { if (member != null) { if (contract.NonNullableUnderlyingType != member.PropertyContract.CreatedType) { return true; } } else if (containerContract != null) { if (containerContract.ItemContract == null || contract.NonNullableUnderlyingType != containerContract.ItemContract.CreatedType) { return true; } } else if (_rootType != null && _serializeStack.Count == _rootLevel) { JsonContract jsonContract = Serializer._contractResolver.ResolveContract(_rootType); if (contract.NonNullableUnderlyingType != jsonContract.CreatedType) { return true; } } } return false; } private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { object obj = ((values is IWrappedDictionary wrappedDictionary) ? wrappedDictionary.UnderlyingDictionary : values); OnSerializing(writer, contract, obj); _serializeStack.Add(obj); WriteObjectStart(writer, obj, contract, member, collectionContract, containerProperty); if (contract.ItemContract == null) { contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object)); } if (contract.KeyContract == null) { contract.KeyContract = Serializer._contractResolver.ResolveContract(contract.DictionaryKeyType ?? typeof(object)); } int top = writer.Top; foreach (DictionaryEntry value2 in values) { string propertyName = GetPropertyName(writer, value2.Key, contract.KeyContract, out var escape); propertyName = ((contract.DictionaryKeyResolver != null) ? contract.DictionaryKeyResolver(propertyName) : propertyName); try { object value = value2.Value; JsonContract jsonContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, jsonContract, contract, member)) { writer.WritePropertyName(propertyName, escape); WriteReference(writer, value); } else if (CheckForCircularReference(writer, value, null, jsonContract, contract, member)) { writer.WritePropertyName(propertyName, escape); SerializeValue(writer, value, jsonContract, null, contract, member); } } catch (Exception ex) { if (IsErrorHandled(obj, contract, propertyName, null, writer.ContainerPath, ex)) { HandleError(writer, top); continue; } throw; } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, obj); } private string GetPropertyName(JsonWriter writer, object name, JsonContract contract, out bool escape) { if (contract.ContractType == JsonContractType.Primitive) { JsonPrimitiveContract jsonPrimitiveContract = (JsonPrimitiveContract)contract; switch (jsonPrimitiveContract.TypeCode) { case PrimitiveTypeCode.DateTime: case PrimitiveTypeCode.DateTimeNullable: { DateTime value = DateTimeUtils.EnsureDateTime((DateTime)name, writer.DateTimeZoneHandling); escape = false; StringWriter stringWriter2 = new StringWriter(CultureInfo.InvariantCulture); DateTimeUtils.WriteDateTimeString(stringWriter2, value, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); return stringWriter2.ToString(); } case PrimitiveTypeCode.DateTimeOffset: case PrimitiveTypeCode.DateTimeOffsetNullable: { escape = false; StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, (DateTimeOffset)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); return stringWriter.ToString(); } case PrimitiveTypeCode.Double: case PrimitiveTypeCode.DoubleNullable: { double num = (double)name; escape = false; return num.ToString("R", CultureInfo.InvariantCulture); } case PrimitiveTypeCode.Single: case PrimitiveTypeCode.SingleNullable: { float num2 = (float)name; escape = false; return num2.ToString("R", CultureInfo.InvariantCulture); } default: { escape = true; if (jsonPrimitiveContract.IsEnum && EnumUtils.TryToString(jsonPrimitiveContract.NonNullableUnderlyingType, name, null, out string name2)) { return name2; } return Convert.ToString(name, CultureInfo.InvariantCulture); } } } if (TryConvertToString(name, name.GetType(), out string s)) { escape = true; return s; } escape = true; return name.ToString(); } private void HandleError(JsonWriter writer, int initialDepth) { ClearErrorContext(); if (writer.WriteState == WriteState.Property) { writer.WriteNull(); } while (writer.Top > initialDepth) { writer.WriteEnd(); } } private bool ShouldSerialize(JsonWriter writer, JsonProperty property, object target) { if (property.ShouldSerialize == null) { return true; } bool flag = property.ShouldSerialize(target); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "ShouldSerialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, flag)), null); } return flag; } private bool IsSpecified(JsonWriter writer, JsonProperty property, object target) { if (property.GetIsSpecified == null) { return true; } bool flag = property.GetIsSpecified(target); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "IsSpecified result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, flag)), null); } return flag; } } internal class JsonSerializerProxy : JsonSerializer { private readonly JsonSerializerInternalReader? _serializerReader; private readonly JsonSerializerInternalWriter? _serializerWriter; internal readonly JsonSerializer _serializer; public override IReferenceResolver? ReferenceResolver { get { return _serializer.ReferenceResolver; } set { _serializer.ReferenceResolver = value; } } public override ITraceWriter? TraceWriter { get { return _serializer.TraceWriter; } set { _serializer.TraceWriter = value; } } public override IEqualityComparer? EqualityComparer { get { return _serializer.EqualityComparer; } set { _serializer.EqualityComparer = value; } } public override JsonConverterCollection Converters => _serializer.Converters; public override DefaultValueHandling DefaultValueHandling { get { return _serializer.DefaultValueHandling; } set { _serializer.DefaultValueHandling = value; } } public override IContractResolver ContractResolver { get { return _serializer.ContractResolver; } set { _serializer.ContractResolver = value; } } public override MissingMemberHandling MissingMemberHandling { get { return _serializer.MissingMemberHandling; } set { _serializer.MissingMemberHandling = value; } } public override NullValueHandling NullValueHandling { get { return _serializer.NullValueHandling; } set { _serializer.NullValueHandling = value; } } public override ObjectCreationHandling ObjectCreationHandling { get { return _serializer.ObjectCreationHandling; } set { _serializer.ObjectCreationHandling = value; } } public override ReferenceLoopHandling ReferenceLoopHandling { get { return _serializer.ReferenceLoopHandling; } set { _serializer.ReferenceLoopHandling = value; } } public override PreserveReferencesHandling PreserveReferencesHandling { get { return _serializer.PreserveReferencesHandling; } set { _serializer.PreserveReferencesHandling = value; } } public override TypeNameHandling TypeNameHandling { get { return _serializer.TypeNameHandling; } set { _serializer.TypeNameHandling = value; } } public override MetadataPropertyHandling MetadataPropertyHandling { get { return _serializer.MetadataPropertyHandling; } set { _serializer.MetadataPropertyHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public override FormatterAssemblyStyle TypeNameAssemblyFormat { get { return _serializer.TypeNameAssemblyFormat; } set { _serializer.TypeNameAssemblyFormat = value; } } public override TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _serializer.TypeNameAssemblyFormatHandling; } set { _serializer.TypeNameAssemblyFormatHandling = value; } } public override ConstructorHandling ConstructorHandling { get { return _serializer.ConstructorHandling; } set { _serializer.ConstructorHandling = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public override SerializationBinder Binder { get { return _serializer.Binder; } set { _serializer.Binder = value; } } public override ISerializationBinder SerializationBinder { get { return _serializer.SerializationBinder; } set { _serializer.SerializationBinder = value; } } public override StreamingContext Context { get { return _serializer.Context; } set { _serializer.Context = value; } } public override Formatting Formatting { get { return _serializer.Formatting; } set { _serializer.Formatting = value; } } public override DateFormatHandling DateFormatHandling { get { return _serializer.DateFormatHandling; } set { _serializer.DateFormatHandling = value; } } public override DateTimeZoneHandling DateTimeZoneHandling { get { return _serializer.DateTimeZoneHandling; } set { _serializer.DateTimeZoneHandling = value; } } public override DateParseHandling DateParseHandling { get { return _serializer.DateParseHandling; } set { _serializer.DateParseHandling = value; } } public override FloatFormatHandling FloatFormatHandling { get { return _serializer.FloatFormatHandling; } set { _serializer.FloatFormatHandling = value; } } public override FloatParseHandling FloatParseHandling { get { return _serializer.FloatParseHandling; } set { _serializer.FloatParseHandling = value; } } public override StringEscapeHandling StringEscapeHandling { get { return _serializer.StringEscapeHandling; } set { _serializer.StringEscapeHandling = value; } } public override string DateFormatString { get { return _serializer.DateFormatString; } set { _serializer.DateFormatString = value; } } public override CultureInfo Culture { get { return _serializer.Culture; } set { _serializer.Culture = value; } } public override int? MaxDepth { get { return _serializer.MaxDepth; } set { _serializer.MaxDepth = value; } } public override bool CheckAdditionalContent { get { return _serializer.CheckAdditionalContent; } set { _serializer.CheckAdditionalContent = value; } } public override event EventHandler? Error { add { _serializer.Error += value; } remove { _serializer.Error -= value; } } internal JsonSerializerInternalBase GetInternalSerializer() { if (_serializerReader != null) { return _serializerReader; } return _serializerWriter; } public JsonSerializerProxy(JsonSerializerInternalReader serializerReader) { ValidationUtils.ArgumentNotNull(serializerReader, "serializerReader"); _serializerReader = serializerReader; _serializer = serializerReader.Serializer; } public JsonSerializerProxy(JsonSerializerInternalWriter serializerWriter) { ValidationUtils.ArgumentNotNull(serializerWriter, "serializerWriter"); _serializerWriter = serializerWriter; _serializer = serializerWriter.Serializer; } internal override object? DeserializeInternal(JsonReader reader, Type? objectType) { if (_serializerReader != null) { return _serializerReader.Deserialize(reader, objectType, checkAdditionalContent: false); } return _serializer.Deserialize(reader, objectType); } internal override void PopulateInternal(JsonReader reader, object target) { if (_serializerReader != null) { _serializerReader.Populate(reader, target); } else { _serializer.Populate(reader, target); } } internal override void SerializeInternal(JsonWriter jsonWriter, object? value, Type? rootType) { if (_serializerWriter != null) { _serializerWriter.Serialize(jsonWriter, value, rootType); } else { _serializer.Serialize(jsonWriter, value); } } } internal class JsonStringContract : JsonPrimitiveContract { public JsonStringContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.String; } } internal static class JsonTypeReflector { private static bool? _dynamicCodeGeneration; private static bool? _fullyTrusted; public const string IdPropertyName = "$id"; public const string RefPropertyName = "$ref"; public const string TypePropertyName = "$type"; public const string ValuePropertyName = "$value"; public const string ArrayValuesPropertyName = "$values"; public const string ShouldSerializePrefix = "ShouldSerialize"; public const string SpecifiedPostfix = "Specified"; public const string ConcurrentDictionaryTypeName = "System.Collections.Concurrent.ConcurrentDictionary`2"; private static readonly ThreadSafeStore> CreatorCache = new ThreadSafeStore>(GetCreator); private static readonly ThreadSafeStore AssociatedMetadataTypesCache = new ThreadSafeStore(GetAssociateMetadataTypeFromAttribute); private static ReflectionObject? _metadataTypeAttributeReflectionObject; public static bool DynamicCodeGeneration { [SecuritySafeCritical] get { if (!_dynamicCodeGeneration.HasValue) { _dynamicCodeGeneration = RuntimeFeature.IsDynamicCodeCompiled; } return _dynamicCodeGeneration.GetValueOrDefault(); } } public static bool FullyTrusted { get { if (!_fullyTrusted.HasValue) { AppDomain currentDomain = AppDomain.CurrentDomain; _fullyTrusted = currentDomain.IsHomogenous && currentDomain.IsFullyTrusted; } return _fullyTrusted.GetValueOrDefault(); } } public static ReflectionDelegateFactory ReflectionDelegateFactory { get { if (DynamicCodeGeneration) { return DynamicReflectionDelegateFactory.Instance; } return LateBoundReflectionDelegateFactory.Instance; } } public static T? GetCachedAttribute(object attributeProvider) where T : Attribute { return CachedAttributeGetter.GetAttribute(attributeProvider); } public static bool CanTypeDescriptorConvertString(Type type, out TypeConverter typeConverter) { typeConverter = TypeDescriptor.GetConverter(type); if (typeConverter != null) { Type type2 = typeConverter.GetType(); if (!string.Equals(type2.FullName, "System.ComponentModel.ComponentConverter", StringComparison.Ordinal) && !string.Equals(type2.FullName, "System.ComponentModel.ReferenceConverter", StringComparison.Ordinal) && !string.Equals(type2.FullName, "System.Windows.Forms.Design.DataSourceConverter", StringComparison.Ordinal) && type2 != typeof(TypeConverter)) { return typeConverter.CanConvertTo(typeof(string)); } } return false; } public static DataContractAttribute? GetDataContractAttribute(Type type) { Type type2 = type; while (type2 != null) { DataContractAttribute attribute = CachedAttributeGetter.GetAttribute(type2); if (attribute != null) { return attribute; } type2 = type2.BaseType(); } return null; } public static DataMemberAttribute? GetDataMemberAttribute(MemberInfo memberInfo) { if (memberInfo.MemberType() == MemberTypes.Field) { return CachedAttributeGetter.GetAttribute(memberInfo); } PropertyInfo propertyInfo = (PropertyInfo)memberInfo; DataMemberAttribute attribute = CachedAttributeGetter.GetAttribute(propertyInfo); if (attribute == null && propertyInfo.IsVirtual()) { Type type = propertyInfo.DeclaringType; while (attribute == null && type != null) { PropertyInfo propertyInfo2 = (PropertyInfo)ReflectionUtils.GetMemberInfoFromType(type, propertyInfo); if (propertyInfo2 != null && propertyInfo2.IsVirtual()) { attribute = CachedAttributeGetter.GetAttribute(propertyInfo2); } type = type.BaseType(); } } return attribute; } public static MemberSerialization GetObjectMemberSerialization(Type objectType, bool ignoreSerializableAttribute) { JsonObjectAttribute cachedAttribute = GetCachedAttribute(objectType); if (cachedAttribute != null) { return cachedAttribute.MemberSerialization; } if (GetDataContractAttribute(objectType) != null) { return MemberSerialization.OptIn; } if (!ignoreSerializableAttribute && IsSerializable(objectType)) { return MemberSerialization.Fields; } return MemberSerialization.OptOut; } public static JsonConverter? GetJsonConverter(object attributeProvider) { JsonConverterAttribute cachedAttribute = GetCachedAttribute(attributeProvider); if (cachedAttribute != null) { Func func = CreatorCache.Get(cachedAttribute.ConverterType); if (func != null) { return (JsonConverter)func(cachedAttribute.ConverterParameters); } } return null; } public static JsonConverter CreateJsonConverterInstance(Type converterType, object[]? args) { return (JsonConverter)CreatorCache.Get(converterType)(args); } public static NamingStrategy CreateNamingStrategyInstance(Type namingStrategyType, object[]? args) { return (NamingStrategy)CreatorCache.Get(namingStrategyType)(args); } public static NamingStrategy? GetContainerNamingStrategy(JsonContainerAttribute containerAttribute) { if (containerAttribute.NamingStrategyInstance == null) { if (containerAttribute.NamingStrategyType == null) { return null; } containerAttribute.NamingStrategyInstance = CreateNamingStrategyInstance(containerAttribute.NamingStrategyType, containerAttribute.NamingStrategyParameters); } return containerAttribute.NamingStrategyInstance; } private static Func GetCreator(Type type) { Type type2 = type; Func defaultConstructor = (ReflectionUtils.HasDefaultConstructor(type2, nonPublic: false) ? ReflectionDelegateFactory.CreateDefaultConstructor(type2) : null); return delegate(object[]? parameters) { try { if (parameters != null) { Type[] types = parameters.Select(delegate(object param) { if (param == null) { throw new InvalidOperationException("Cannot pass a null parameter to the constructor."); } return param.GetType(); }).ToArray(); ConstructorInfo constructor = type2.GetConstructor(types); if (!(constructor != null)) { throw new JsonException("No matching parameterized constructor found for '{0}'.".FormatWith(CultureInfo.InvariantCulture, type2)); } return ReflectionDelegateFactory.CreateParameterizedConstructor(constructor)(parameters); } if (defaultConstructor == null) { throw new JsonException("No parameterless constructor defined for '{0}'.".FormatWith(CultureInfo.InvariantCulture, type2)); } return defaultConstructor(); } catch (Exception innerException) { throw new JsonException("Error creating '{0}'.".FormatWith(CultureInfo.InvariantCulture, type2), innerException); } }; } private static Type? GetAssociatedMetadataType(Type type) { return AssociatedMetadataTypesCache.Get(type); } private static Type? GetAssociateMetadataTypeFromAttribute(Type type) { Attribute[] attributes = ReflectionUtils.GetAttributes(type, null, inherit: true); foreach (Attribute attribute in attributes) { Type type2 = attribute.GetType(); if (string.Equals(type2.FullName, "System.ComponentModel.DataAnnotations.MetadataTypeAttribute", StringComparison.Ordinal)) { if (_metadataTypeAttributeReflectionObject == null) { _metadataTypeAttributeReflectionObject = ReflectionObject.Create(type2, "MetadataClassType"); } return (Type)_metadataTypeAttributeReflectionObject.GetValue(attribute, "MetadataClassType"); } } return null; } private static T? GetAttribute(Type type) where T : Attribute { Type associatedMetadataType = GetAssociatedMetadataType(type); T attribute; if (associatedMetadataType != null) { attribute = ReflectionUtils.GetAttribute(associatedMetadataType, inherit: true); if (attribute != null) { return attribute; } } attribute = ReflectionUtils.GetAttribute(type, inherit: true); if (attribute != null) { return attribute; } Type[] interfaces = type.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { attribute = ReflectionUtils.GetAttribute(interfaces[i], inherit: true); if (attribute != null) { return attribute; } } return null; } private static T? GetAttribute(MemberInfo memberInfo) where T : Attribute { Type associatedMetadataType = GetAssociatedMetadataType(memberInfo.DeclaringType); T attribute; if (associatedMetadataType != null) { MemberInfo memberInfoFromType = ReflectionUtils.GetMemberInfoFromType(associatedMetadataType, memberInfo); if (memberInfoFromType != null) { attribute = ReflectionUtils.GetAttribute(memberInfoFromType, inherit: true); if (attribute != null) { return attribute; } } } attribute = ReflectionUtils.GetAttribute(memberInfo, inherit: true); if (attribute != null) { return attribute; } if (memberInfo.DeclaringType != null) { Type[] interfaces = memberInfo.DeclaringType.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { MemberInfo memberInfoFromType2 = ReflectionUtils.GetMemberInfoFromType(interfaces[i], memberInfo); if (memberInfoFromType2 != null) { attribute = ReflectionUtils.GetAttribute(memberInfoFromType2, inherit: true); if (attribute != null) { return attribute; } } } } return null; } public static bool IsNonSerializable(object provider) { return ReflectionUtils.GetAttribute(provider, inherit: false) != null; } public static bool IsSerializable(object provider) { return ReflectionUtils.GetAttribute(provider, inherit: false) != null; } public static T? GetAttribute(object provider) where T : Attribute { if (provider is Type type) { return GetAttribute(type); } if (provider is MemberInfo memberInfo) { return GetAttribute(memberInfo); } return ReflectionUtils.GetAttribute(provider, inherit: true); } } internal class KebabCaseNamingStrategy : NamingStrategy { public KebabCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames) { base.ProcessDictionaryKeys = processDictionaryKeys; base.OverrideSpecifiedNames = overrideSpecifiedNames; } public KebabCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) : this(processDictionaryKeys, overrideSpecifiedNames) { base.ProcessExtensionDataNames = processExtensionDataNames; } public KebabCaseNamingStrategy() { } protected override string ResolvePropertyName(string name) { return StringUtils.ToKebabCase(name); } } internal class MemoryTraceWriter : ITraceWriter { private readonly Queue _traceMessages; private readonly object _lock; public TraceLevel LevelFilter { get; set; } public MemoryTraceWriter() { LevelFilter = TraceLevel.Verbose; _traceMessages = new Queue(); _lock = new object(); } public void Trace(TraceLevel level, string message, Exception? ex) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff", CultureInfo.InvariantCulture)); stringBuilder.Append(" "); stringBuilder.Append(level.ToString("g")); stringBuilder.Append(" "); stringBuilder.Append(message); string item = stringBuilder.ToString(); lock (_lock) { if (_traceMessages.Count >= 1000) { _traceMessages.Dequeue(); } _traceMessages.Enqueue(item); } } public IEnumerable GetTraceMessages() { return _traceMessages; } public override string ToString() { lock (_lock) { StringBuilder stringBuilder = new StringBuilder(); foreach (string traceMessage in _traceMessages) { if (stringBuilder.Length > 0) { stringBuilder.AppendLine(); } stringBuilder.Append(traceMessage); } return stringBuilder.ToString(); } } } internal abstract class NamingStrategy { public bool ProcessDictionaryKeys { get; set; } public bool ProcessExtensionDataNames { get; set; } public bool OverrideSpecifiedNames { get; set; } public virtual string GetPropertyName(string name, bool hasSpecifiedName) { if (hasSpecifiedName && !OverrideSpecifiedNames) { return name; } return ResolvePropertyName(name); } public virtual string GetExtensionDataName(string name) { if (!ProcessExtensionDataNames) { return name; } return ResolvePropertyName(name); } public virtual string GetDictionaryKey(string key) { if (!ProcessDictionaryKeys) { return key; } return ResolvePropertyName(key); } protected abstract string ResolvePropertyName(string name); public override int GetHashCode() { return (((((GetType().GetHashCode() * 397) ^ ProcessDictionaryKeys.GetHashCode()) * 397) ^ ProcessExtensionDataNames.GetHashCode()) * 397) ^ OverrideSpecifiedNames.GetHashCode(); } public override bool Equals(object? obj) { return Equals(obj as NamingStrategy); } protected bool Equals(NamingStrategy? other) { if (other == null) { return false; } if (GetType() == other.GetType() && ProcessDictionaryKeys == other.ProcessDictionaryKeys && ProcessExtensionDataNames == other.ProcessExtensionDataNames) { return OverrideSpecifiedNames == other.OverrideSpecifiedNames; } return false; } } internal delegate object ObjectConstructor(params object?[] args); [AttributeUsage(AttributeTargets.Method, Inherited = false)] internal sealed class OnErrorAttribute : Attribute { } internal class ReflectionAttributeProvider : IAttributeProvider { private readonly object _attributeProvider; public ReflectionAttributeProvider(object attributeProvider) { ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider"); _attributeProvider = attributeProvider; } public IList GetAttributes(bool inherit) { return ReflectionUtils.GetAttributes(_attributeProvider, null, inherit); } public IList GetAttributes(Type attributeType, bool inherit) { return ReflectionUtils.GetAttributes(_attributeProvider, attributeType, inherit); } } internal class ReflectionValueProvider : IValueProvider { private readonly MemberInfo _memberInfo; public ReflectionValueProvider(MemberInfo memberInfo) { ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo"); _memberInfo = memberInfo; } public void SetValue(object target, object? value) { try { ReflectionUtils.SetMemberValue(_memberInfo, target, value); } catch (Exception innerException) { throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } public object? GetValue(object target) { try { if (_memberInfo is PropertyInfo propertyInfo && propertyInfo.PropertyType.IsByRef) { throw new InvalidOperationException("Could not create getter for {0}. ByRef return values are not supported.".FormatWith(CultureInfo.InvariantCulture, propertyInfo)); } return ReflectionUtils.GetMemberValue(_memberInfo, target); } catch (Exception innerException) { throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } } internal class SerializationBinderAdapter : ISerializationBinder { public readonly SerializationBinder SerializationBinder; public SerializationBinderAdapter(SerializationBinder serializationBinder) { SerializationBinder = serializationBinder; } public Type BindToType(string? assemblyName, string typeName) { return SerializationBinder.BindToType(assemblyName, typeName); } public void BindToName(Type serializedType, out string? assemblyName, out string? typeName) { SerializationBinder.BindToName(serializedType, out assemblyName, out typeName); } } internal class SnakeCaseNamingStrategy : NamingStrategy { public SnakeCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames) { base.ProcessDictionaryKeys = processDictionaryKeys; base.OverrideSpecifiedNames = overrideSpecifiedNames; } public SnakeCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) : this(processDictionaryKeys, overrideSpecifiedNames) { base.ProcessExtensionDataNames = processExtensionDataNames; } public SnakeCaseNamingStrategy() { } protected override string ResolvePropertyName(string name) { return StringUtils.ToSnakeCase(name); } } internal class TraceJsonReader : JsonReader, IJsonLineInfo { private readonly JsonReader _innerReader; private readonly JsonTextWriter _textWriter; private readonly StringWriter _sw; public override int Depth => _innerReader.Depth; public override string Path => _innerReader.Path; public override char QuoteChar { get { return _innerReader.QuoteChar; } protected internal set { _innerReader.QuoteChar = value; } } public override JsonToken TokenType => _innerReader.TokenType; public override object? Value => _innerReader.Value; public override Type? ValueType => _innerReader.ValueType; int IJsonLineInfo.LineNumber { get { if (!(_innerReader is IJsonLineInfo jsonLineInfo)) { return 0; } return jsonLineInfo.LineNumber; } } int IJsonLineInfo.LinePosition { get { if (!(_innerReader is IJsonLineInfo jsonLineInfo)) { return 0; } return jsonLineInfo.LinePosition; } } public TraceJsonReader(JsonReader innerReader) { _innerReader = innerReader; _sw = new StringWriter(CultureInfo.InvariantCulture); _sw.Write("Deserialized JSON: " + Environment.NewLine); _textWriter = new JsonTextWriter(_sw); _textWriter.Formatting = Formatting.Indented; } public string GetDeserializedJsonMessage() { return _sw.ToString(); } public override bool Read() { bool result = _innerReader.Read(); WriteCurrentToken(); return result; } public override int? ReadAsInt32() { int? result = _innerReader.ReadAsInt32(); WriteCurrentToken(); return result; } public override string? ReadAsString() { string? result = _innerReader.ReadAsString(); WriteCurrentToken(); return result; } public override byte[]? ReadAsBytes() { byte[]? result = _innerReader.ReadAsBytes(); WriteCurrentToken(); return result; } public override decimal? ReadAsDecimal() { decimal? result = _innerReader.ReadAsDecimal(); WriteCurrentToken(); return result; } public override double? ReadAsDouble() { double? result = _innerReader.ReadAsDouble(); WriteCurrentToken(); return result; } public override bool? ReadAsBoolean() { bool? result = _innerReader.ReadAsBoolean(); WriteCurrentToken(); return result; } public override DateTime? ReadAsDateTime() { DateTime? result = _innerReader.ReadAsDateTime(); WriteCurrentToken(); return result; } public override DateTimeOffset? ReadAsDateTimeOffset() { DateTimeOffset? result = _innerReader.ReadAsDateTimeOffset(); WriteCurrentToken(); return result; } public void WriteCurrentToken() { _textWriter.WriteToken(_innerReader, writeChildren: false, writeDateConstructorAsDate: false, writeComments: true); } public override void Close() { _innerReader.Close(); } bool IJsonLineInfo.HasLineInfo() { if (_innerReader is IJsonLineInfo jsonLineInfo) { return jsonLineInfo.HasLineInfo(); } return false; } } internal class TraceJsonWriter : JsonWriter { private readonly JsonWriter _innerWriter; private readonly JsonTextWriter _textWriter; private readonly StringWriter _sw; public TraceJsonWriter(JsonWriter innerWriter) { _innerWriter = innerWriter; _sw = new StringWriter(CultureInfo.InvariantCulture); _sw.Write("Serialized JSON: " + Environment.NewLine); _textWriter = new JsonTextWriter(_sw); _textWriter.Formatting = Formatting.Indented; _textWriter.Culture = innerWriter.Culture; _textWriter.DateFormatHandling = innerWriter.DateFormatHandling; _textWriter.DateFormatString = innerWriter.DateFormatString; _textWriter.DateTimeZoneHandling = innerWriter.DateTimeZoneHandling; _textWriter.FloatFormatHandling = innerWriter.FloatFormatHandling; } public string GetSerializedJsonMessage() { return _sw.ToString(); } public override void WriteValue(decimal value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(decimal? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(bool value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(bool? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(byte value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(byte? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(char value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(char? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(byte[]? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value == null) { base.WriteUndefined(); } else { base.WriteValue(value); } } public override void WriteValue(DateTime value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(DateTime? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(DateTimeOffset value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(DateTimeOffset? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(double value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(double? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteUndefined() { _textWriter.WriteUndefined(); _innerWriter.WriteUndefined(); base.WriteUndefined(); } public override void WriteNull() { _textWriter.WriteNull(); _innerWriter.WriteNull(); base.WriteUndefined(); } public override void WriteValue(float value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(float? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(Guid value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(Guid? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(int value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(int? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(long value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(long? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(object? value) { if (value is BigInteger) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); InternalWriteValue(JsonToken.Integer); return; } _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value == null) { base.WriteUndefined(); } else { InternalWriteValue(JsonToken.String); } } public override void WriteValue(sbyte value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(sbyte? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(short value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(short? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(string? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(TimeSpan value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(TimeSpan? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(uint value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(uint? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(ulong value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(ulong? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(Uri? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value == null) { base.WriteUndefined(); } else { base.WriteValue(value); } } public override void WriteValue(ushort value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(ushort? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteWhitespace(string ws) { _textWriter.WriteWhitespace(ws); _innerWriter.WriteWhitespace(ws); base.WriteWhitespace(ws); } public override void WriteComment(string? text) { _textWriter.WriteComment(text); _innerWriter.WriteComment(text); base.WriteComment(text); } public override void WriteStartArray() { _textWriter.WriteStartArray(); _innerWriter.WriteStartArray(); base.WriteStartArray(); } public override void WriteEndArray() { _textWriter.WriteEndArray(); _innerWriter.WriteEndArray(); base.WriteEndArray(); } public override void WriteStartConstructor(string name) { _textWriter.WriteStartConstructor(name); _innerWriter.WriteStartConstructor(name); base.WriteStartConstructor(name); } public override void WriteEndConstructor() { _textWriter.WriteEndConstructor(); _innerWriter.WriteEndConstructor(); base.WriteEndConstructor(); } public override void WritePropertyName(string name) { _textWriter.WritePropertyName(name); _innerWriter.WritePropertyName(name); base.WritePropertyName(name); } public override void WritePropertyName(string name, bool escape) { _textWriter.WritePropertyName(name, escape); _innerWriter.WritePropertyName(name, escape); base.WritePropertyName(name); } public override void WriteStartObject() { _textWriter.WriteStartObject(); _innerWriter.WriteStartObject(); base.WriteStartObject(); } public override void WriteEndObject() { _textWriter.WriteEndObject(); _innerWriter.WriteEndObject(); base.WriteEndObject(); } public override void WriteRawValue(string? json) { _textWriter.WriteRawValue(json); _innerWriter.WriteRawValue(json); InternalWriteValue(JsonToken.Undefined); } public override void WriteRaw(string? json) { _textWriter.WriteRaw(json); _innerWriter.WriteRaw(json); base.WriteRaw(json); } public override void Close() { _textWriter.Close(); _innerWriter.Close(); base.Close(); } public override void Flush() { _textWriter.Flush(); _innerWriter.Flush(); } } } namespace Newtonsoft.Json.Schema { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal static class Extensions { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] public static bool IsValid(this JToken source, JsonSchema schema) { bool valid = true; source.Validate(schema, delegate { valid = false; }); return valid; } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] public static bool IsValid(this JToken source, JsonSchema schema, out IList errorMessages) { IList errors = new List(); source.Validate(schema, delegate(object sender, ValidationEventArgs args) { errors.Add(args.Message); }); errorMessages = errors; return errorMessages.Count == 0; } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] public static void Validate(this JToken source, JsonSchema schema) { source.Validate(schema, null); } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] public static void Validate(this JToken source, JsonSchema schema, ValidationEventHandler validationEventHandler) { ValidationUtils.ArgumentNotNull(source, "source"); ValidationUtils.ArgumentNotNull(schema, "schema"); using JsonValidatingReader jsonValidatingReader = new JsonValidatingReader(source.CreateReader()); jsonValidatingReader.Schema = schema; if (validationEventHandler != null) { jsonValidatingReader.ValidationEventHandler += validationEventHandler; } while (jsonValidatingReader.Read()) { } } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchema { private readonly string _internalId = Guid.NewGuid().ToString("N"); public string Id { get; set; } public string Title { get; set; } public bool? Required { get; set; } public bool? ReadOnly { get; set; } public bool? Hidden { get; set; } public bool? Transient { get; set; } public string Description { get; set; } public JsonSchemaType? Type { get; set; } public string Pattern { get; set; } public int? MinimumLength { get; set; } public int? MaximumLength { get; set; } public double? DivisibleBy { get; set; } public double? Minimum { get; set; } public double? Maximum { get; set; } public bool? ExclusiveMinimum { get; set; } public bool? ExclusiveMaximum { get; set; } public int? MinimumItems { get; set; } public int? MaximumItems { get; set; } public IList Items { get; set; } public bool PositionalItemsValidation { get; set; } public JsonSchema AdditionalItems { get; set; } public bool AllowAdditionalItems { get; set; } public bool UniqueItems { get; set; } public IDictionary Properties { get; set; } public JsonSchema AdditionalProperties { get; set; } public IDictionary PatternProperties { get; set; } public bool AllowAdditionalProperties { get; set; } public string Requires { get; set; } public IList Enum { get; set; } public JsonSchemaType? Disallow { get; set; } public JToken Default { get; set; } public IList Extends { get; set; } public string Format { get; set; } internal string Location { get; set; } internal string InternalId => _internalId; internal string DeferredReference { get; set; } internal bool ReferencesResolved { get; set; } public JsonSchema() { AllowAdditionalProperties = true; AllowAdditionalItems = true; } public static JsonSchema Read(JsonReader reader) { return Read(reader, new JsonSchemaResolver()); } public static JsonSchema Read(JsonReader reader, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(resolver, "resolver"); return new JsonSchemaBuilder(resolver).Read(reader); } public static JsonSchema Parse(string json) { return Parse(json, new JsonSchemaResolver()); } public static JsonSchema Parse(string json, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(json, "json"); using JsonReader reader = new JsonTextReader(new StringReader(json)); return Read(reader, resolver); } public void WriteTo(JsonWriter writer) { WriteTo(writer, new JsonSchemaResolver()); } public void WriteTo(JsonWriter writer, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(writer, "writer"); ValidationUtils.ArgumentNotNull(resolver, "resolver"); new JsonSchemaWriter(writer, resolver).WriteSchema(this); } public override string ToString() { StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); WriteTo(new JsonTextWriter(stringWriter) { Formatting = Formatting.Indented }); return stringWriter.ToString(); } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaBuilder { private readonly IList _stack; private readonly JsonSchemaResolver _resolver; private readonly IDictionary _documentSchemas; private JsonSchema _currentSchema; private JObject _rootSchema; private JsonSchema CurrentSchema => _currentSchema; public JsonSchemaBuilder(JsonSchemaResolver resolver) { _stack = new List(); _documentSchemas = new Dictionary(); _resolver = resolver; } private void Push(JsonSchema value) { _currentSchema = value; _stack.Add(value); _resolver.LoadedSchemas.Add(value); _documentSchemas.Add(value.Location, value); } private JsonSchema Pop() { JsonSchema currentSchema = _currentSchema; _stack.RemoveAt(_stack.Count - 1); _currentSchema = _stack.LastOrDefault(); return currentSchema; } internal JsonSchema Read(JsonReader reader) { JToken jToken = JToken.ReadFrom(reader); _rootSchema = jToken as JObject; JsonSchema jsonSchema = BuildSchema(jToken); ResolveReferences(jsonSchema); return jsonSchema; } private string UnescapeReference(string reference) { return StringUtils.Replace(StringUtils.Replace(Uri.UnescapeDataString(reference), "~1", "/"), "~0", "~"); } private JsonSchema ResolveReferences(JsonSchema schema) { if (schema.DeferredReference != null) { string text = schema.DeferredReference; bool flag = text.StartsWith("#", StringComparison.Ordinal); if (flag) { text = UnescapeReference(text); } JsonSchema jsonSchema = _resolver.GetSchema(text); if (jsonSchema == null) { if (flag) { string[] array = schema.DeferredReference.TrimStart('#').Split(new char[1] { '/' }, StringSplitOptions.RemoveEmptyEntries); JToken jToken = _rootSchema; string[] array2 = array; foreach (string reference in array2) { string text2 = UnescapeReference(reference); if (jToken.Type == JTokenType.Object) { jToken = jToken[text2]; } else if (jToken.Type == JTokenType.Array || jToken.Type == JTokenType.Constructor) { jToken = ((!int.TryParse(text2, out var result) || result < 0 || result >= jToken.Count()) ? null : jToken[result]); } if (jToken == null) { break; } } if (jToken != null) { jsonSchema = BuildSchema(jToken); } } if (jsonSchema == null) { throw new JsonException("Could not resolve schema reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, schema.DeferredReference)); } } schema = jsonSchema; } if (schema.ReferencesResolved) { return schema; } schema.ReferencesResolved = true; if (schema.Extends != null) { for (int j = 0; j < schema.Extends.Count; j++) { schema.Extends[j] = ResolveReferences(schema.Extends[j]); } } if (schema.Items != null) { for (int k = 0; k < schema.Items.Count; k++) { schema.Items[k] = ResolveReferences(schema.Items[k]); } } if (schema.AdditionalItems != null) { schema.AdditionalItems = ResolveReferences(schema.AdditionalItems); } if (schema.PatternProperties != null) { foreach (KeyValuePair item in schema.PatternProperties.ToList()) { schema.PatternProperties[item.Key] = ResolveReferences(item.Value); } } if (schema.Properties != null) { foreach (KeyValuePair item2 in schema.Properties.ToList()) { schema.Properties[item2.Key] = ResolveReferences(item2.Value); } } if (schema.AdditionalProperties != null) { schema.AdditionalProperties = ResolveReferences(schema.AdditionalProperties); } return schema; } private JsonSchema BuildSchema(JToken token) { if (!(token is JObject jObject)) { throw JsonException.Create(token, token.Path, "Expected object while parsing schema object, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } if (jObject.TryGetValue("$ref", out JToken value)) { return new JsonSchema { DeferredReference = (string?)value }; } string path = token.Path; path = StringUtils.Replace(path, ".", "/"); path = StringUtils.Replace(path, "[", "/"); path = StringUtils.Replace(path, "]", string.Empty); if (!StringUtils.IsNullOrEmpty(path)) { path = "/" + path; } path = "#" + path; if (_documentSchemas.TryGetValue(path, out var value2)) { return value2; } Push(new JsonSchema { Location = path }); ProcessSchemaProperties(jObject); return Pop(); } private void ProcessSchemaProperties(JObject schemaObject) { foreach (KeyValuePair item in schemaObject) { switch (item.Key) { case "type": CurrentSchema.Type = ProcessType(item.Value); break; case "id": CurrentSchema.Id = (string?)item.Value; break; case "title": CurrentSchema.Title = (string?)item.Value; break; case "description": CurrentSchema.Description = (string?)item.Value; break; case "properties": CurrentSchema.Properties = ProcessProperties(item.Value); break; case "items": ProcessItems(item.Value); break; case "additionalProperties": ProcessAdditionalProperties(item.Value); break; case "additionalItems": ProcessAdditionalItems(item.Value); break; case "patternProperties": CurrentSchema.PatternProperties = ProcessProperties(item.Value); break; case "required": CurrentSchema.Required = (bool)item.Value; break; case "requires": CurrentSchema.Requires = (string?)item.Value; break; case "minimum": CurrentSchema.Minimum = (double)item.Value; break; case "maximum": CurrentSchema.Maximum = (double)item.Value; break; case "exclusiveMinimum": CurrentSchema.ExclusiveMinimum = (bool)item.Value; break; case "exclusiveMaximum": CurrentSchema.ExclusiveMaximum = (bool)item.Value; break; case "maxLength": CurrentSchema.MaximumLength = (int)item.Value; break; case "minLength": CurrentSchema.MinimumLength = (int)item.Value; break; case "maxItems": CurrentSchema.MaximumItems = (int)item.Value; break; case "minItems": CurrentSchema.MinimumItems = (int)item.Value; break; case "divisibleBy": CurrentSchema.DivisibleBy = (double)item.Value; break; case "disallow": CurrentSchema.Disallow = ProcessType(item.Value); break; case "default": CurrentSchema.Default = item.Value.DeepClone(); break; case "hidden": CurrentSchema.Hidden = (bool)item.Value; break; case "readonly": CurrentSchema.ReadOnly = (bool)item.Value; break; case "format": CurrentSchema.Format = (string?)item.Value; break; case "pattern": CurrentSchema.Pattern = (string?)item.Value; break; case "enum": ProcessEnum(item.Value); break; case "extends": ProcessExtends(item.Value); break; case "uniqueItems": CurrentSchema.UniqueItems = (bool)item.Value; break; } } } private void ProcessExtends(JToken token) { IList list = new List(); if (token.Type == JTokenType.Array) { foreach (JToken item in (IEnumerable)token) { list.Add(BuildSchema(item)); } } else { JsonSchema jsonSchema = BuildSchema(token); if (jsonSchema != null) { list.Add(jsonSchema); } } if (list.Count > 0) { CurrentSchema.Extends = list; } } private void ProcessEnum(JToken token) { if (token.Type != JTokenType.Array) { throw JsonException.Create(token, token.Path, "Expected Array token while parsing enum values, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } CurrentSchema.Enum = new List(); foreach (JToken item in (IEnumerable)token) { CurrentSchema.Enum.Add(item.DeepClone()); } } private void ProcessAdditionalProperties(JToken token) { if (token.Type == JTokenType.Boolean) { CurrentSchema.AllowAdditionalProperties = (bool)token; } else { CurrentSchema.AdditionalProperties = BuildSchema(token); } } private void ProcessAdditionalItems(JToken token) { if (token.Type == JTokenType.Boolean) { CurrentSchema.AllowAdditionalItems = (bool)token; } else { CurrentSchema.AdditionalItems = BuildSchema(token); } } private IDictionary ProcessProperties(JToken token) { IDictionary dictionary = new Dictionary(); if (token.Type != JTokenType.Object) { throw JsonException.Create(token, token.Path, "Expected Object token while parsing schema properties, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } foreach (JProperty item in (IEnumerable)token) { if (dictionary.ContainsKey(item.Name)) { throw new JsonException("Property {0} has already been defined in schema.".FormatWith(CultureInfo.InvariantCulture, item.Name)); } dictionary.Add(item.Name, BuildSchema(item.Value)); } return dictionary; } private void ProcessItems(JToken token) { CurrentSchema.Items = new List(); switch (token.Type) { case JTokenType.Object: CurrentSchema.Items.Add(BuildSchema(token)); CurrentSchema.PositionalItemsValidation = false; break; case JTokenType.Array: CurrentSchema.PositionalItemsValidation = true; { foreach (JToken item in (IEnumerable)token) { CurrentSchema.Items.Add(BuildSchema(item)); } break; } default: throw JsonException.Create(token, token.Path, "Expected array or JSON schema object, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } } private JsonSchemaType? ProcessType(JToken token) { switch (token.Type) { case JTokenType.Array: { JsonSchemaType? jsonSchemaType = JsonSchemaType.None; { foreach (JToken item in (IEnumerable)token) { if (item.Type != JTokenType.String) { throw JsonException.Create(item, item.Path, "Expected JSON schema type string token, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } jsonSchemaType |= MapType((string?)item); } return jsonSchemaType; } } case JTokenType.String: return MapType((string?)token); default: throw JsonException.Create(token, token.Path, "Expected array or JSON schema type string token, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } } internal static JsonSchemaType MapType(string type) { if (!JsonSchemaConstants.JsonSchemaTypeMapping.TryGetValue(type, out var value)) { throw new JsonException("Invalid JSON schema type: {0}".FormatWith(CultureInfo.InvariantCulture, type)); } return value; } internal static string MapType(JsonSchemaType type) { return JsonSchemaConstants.JsonSchemaTypeMapping.Single((KeyValuePair kv) => kv.Value == type).Key; } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal static class JsonSchemaConstants { public const string TypePropertyName = "type"; public const string PropertiesPropertyName = "properties"; public const string ItemsPropertyName = "items"; public const string AdditionalItemsPropertyName = "additionalItems"; public const string RequiredPropertyName = "required"; public const string PatternPropertiesPropertyName = "patternProperties"; public const string AdditionalPropertiesPropertyName = "additionalProperties"; public const string RequiresPropertyName = "requires"; public const string MinimumPropertyName = "minimum"; public const string MaximumPropertyName = "maximum"; public const string ExclusiveMinimumPropertyName = "exclusiveMinimum"; public const string ExclusiveMaximumPropertyName = "exclusiveMaximum"; public const string MinimumItemsPropertyName = "minItems"; public const string MaximumItemsPropertyName = "maxItems"; public const string PatternPropertyName = "pattern"; public const string MaximumLengthPropertyName = "maxLength"; public const string MinimumLengthPropertyName = "minLength"; public const string EnumPropertyName = "enum"; public const string ReadOnlyPropertyName = "readonly"; public const string TitlePropertyName = "title"; public const string DescriptionPropertyName = "description"; public const string FormatPropertyName = "format"; public const string DefaultPropertyName = "default"; public const string TransientPropertyName = "transient"; public const string DivisibleByPropertyName = "divisibleBy"; public const string HiddenPropertyName = "hidden"; public const string DisallowPropertyName = "disallow"; public const string ExtendsPropertyName = "extends"; public const string IdPropertyName = "id"; public const string UniqueItemsPropertyName = "uniqueItems"; public const string OptionValuePropertyName = "value"; public const string OptionLabelPropertyName = "label"; public static readonly IDictionary JsonSchemaTypeMapping = new Dictionary { { "string", JsonSchemaType.String }, { "object", JsonSchemaType.Object }, { "integer", JsonSchemaType.Integer }, { "number", JsonSchemaType.Float }, { "null", JsonSchemaType.Null }, { "boolean", JsonSchemaType.Boolean }, { "array", JsonSchemaType.Array }, { "any", JsonSchemaType.Any } }; } [Serializable] [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string Path { get; } public JsonSchemaException() { } public JsonSchemaException(string message) : base(message) { } public JsonSchemaException(string message, Exception innerException) : base(message, innerException) { } public JsonSchemaException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal JsonSchemaException(string message, Exception innerException, string path, int lineNumber, int linePosition) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaGenerator { private class TypeSchema { public Type Type { get; } public JsonSchema Schema { get; } public TypeSchema(Type type, JsonSchema schema) { ValidationUtils.ArgumentNotNull(type, "type"); ValidationUtils.ArgumentNotNull(schema, "schema"); Type = type; Schema = schema; } } private IContractResolver _contractResolver; private JsonSchemaResolver _resolver; private readonly IList _stack = new List(); private JsonSchema _currentSchema; public UndefinedSchemaIdHandling UndefinedSchemaIdHandling { get; set; } public IContractResolver ContractResolver { get { if (_contractResolver == null) { return DefaultContractResolver.Instance; } return _contractResolver; } set { _contractResolver = value; } } private JsonSchema CurrentSchema => _currentSchema; private void Push(TypeSchema typeSchema) { _currentSchema = typeSchema.Schema; _stack.Add(typeSchema); _resolver.LoadedSchemas.Add(typeSchema.Schema); } private TypeSchema Pop() { TypeSchema result = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); TypeSchema typeSchema = _stack.LastOrDefault(); if (typeSchema != null) { _currentSchema = typeSchema.Schema; return result; } _currentSchema = null; return result; } public JsonSchema Generate(Type type) { return Generate(type, new JsonSchemaResolver(), rootSchemaNullable: false); } public JsonSchema Generate(Type type, JsonSchemaResolver resolver) { return Generate(type, resolver, rootSchemaNullable: false); } public JsonSchema Generate(Type type, bool rootSchemaNullable) { return Generate(type, new JsonSchemaResolver(), rootSchemaNullable); } public JsonSchema Generate(Type type, JsonSchemaResolver resolver, bool rootSchemaNullable) { ValidationUtils.ArgumentNotNull(type, "type"); ValidationUtils.ArgumentNotNull(resolver, "resolver"); _resolver = resolver; return GenerateInternal(type, (!rootSchemaNullable) ? Required.Always : Required.Default, required: false); } private string GetTitle(Type type) { JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(type); if (!StringUtils.IsNullOrEmpty(cachedAttribute?.Title)) { return cachedAttribute.Title; } return null; } private string GetDescription(Type type) { JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(type); if (!StringUtils.IsNullOrEmpty(cachedAttribute?.Description)) { return cachedAttribute.Description; } return ReflectionUtils.GetAttribute(type)?.Description; } private string GetTypeId(Type type, bool explicitOnly) { JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(type); if (!StringUtils.IsNullOrEmpty(cachedAttribute?.Id)) { return cachedAttribute.Id; } if (explicitOnly) { return null; } return UndefinedSchemaIdHandling switch { UndefinedSchemaIdHandling.UseTypeName => type.FullName, UndefinedSchemaIdHandling.UseAssemblyQualifiedName => type.AssemblyQualifiedName, _ => null, }; } private JsonSchema GenerateInternal(Type type, Required valueRequired, bool required) { ValidationUtils.ArgumentNotNull(type, "type"); string typeId = GetTypeId(type, explicitOnly: false); string typeId2 = GetTypeId(type, explicitOnly: true); if (!StringUtils.IsNullOrEmpty(typeId)) { JsonSchema schema = _resolver.GetSchema(typeId); if (schema != null) { if (valueRequired != Required.Always && !HasFlag(schema.Type, JsonSchemaType.Null)) { schema.Type |= JsonSchemaType.Null; } if (required && schema.Required != true) { schema.Required = true; } return schema; } } if (_stack.Any((TypeSchema tc) => tc.Type == type)) { throw new JsonException("Unresolved circular reference for type '{0}'. Explicitly define an Id for the type using a JsonObject/JsonArray attribute or automatically generate a type Id using the UndefinedSchemaIdHandling property.".FormatWith(CultureInfo.InvariantCulture, type)); } JsonContract jsonContract = ContractResolver.ResolveContract(type); JsonConverter? obj = jsonContract.Converter ?? jsonContract.InternalConverter; Push(new TypeSchema(type, new JsonSchema())); if (typeId2 != null) { CurrentSchema.Id = typeId2; } if (required) { CurrentSchema.Required = true; } CurrentSchema.Title = GetTitle(type); CurrentSchema.Description = GetDescription(type); if (obj != null) { CurrentSchema.Type = JsonSchemaType.Any; } else { switch (jsonContract.ContractType) { case JsonContractType.Object: CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired); CurrentSchema.Id = GetTypeId(type, explicitOnly: false); GenerateObjectSchema(type, (JsonObjectContract)jsonContract); break; case JsonContractType.Array: { CurrentSchema.Type = AddNullType(JsonSchemaType.Array, valueRequired); CurrentSchema.Id = GetTypeId(type, explicitOnly: false); bool flag = JsonTypeReflector.GetCachedAttribute(type)?.AllowNullItems ?? true; Type collectionItemType = ReflectionUtils.GetCollectionItemType(type); if (collectionItemType != null) { CurrentSchema.Items = new List(); CurrentSchema.Items.Add(GenerateInternal(collectionItemType, (!flag) ? Required.Always : Required.Default, required: false)); } break; } case JsonContractType.Primitive: CurrentSchema.Type = GetJsonSchemaType(type, valueRequired); if (CurrentSchema.Type == JsonSchemaType.Integer && type.IsEnum() && !type.IsDefined(typeof(FlagsAttribute), inherit: true)) { CurrentSchema.Enum = new List(); EnumInfo enumValuesAndNames = EnumUtils.GetEnumValuesAndNames(type); for (int i = 0; i < enumValuesAndNames.Names.Length; i++) { ulong value = enumValuesAndNames.Values[i]; JToken item = JToken.FromObject(Enum.ToObject(type, value)); CurrentSchema.Enum.Add(item); } } break; case JsonContractType.String: { JsonSchemaType value2 = ((!ReflectionUtils.IsNullable(jsonContract.UnderlyingType)) ? JsonSchemaType.String : AddNullType(JsonSchemaType.String, valueRequired)); CurrentSchema.Type = value2; break; } case JsonContractType.Dictionary: { CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired); ReflectionUtils.GetDictionaryKeyValueTypes(type, out Type keyType, out Type valueType); if (keyType != null && ContractResolver.ResolveContract(keyType).ContractType == JsonContractType.Primitive) { CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, required: false); } break; } case JsonContractType.Serializable: CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired); CurrentSchema.Id = GetTypeId(type, explicitOnly: false); GenerateISerializableContract(type, (JsonISerializableContract)jsonContract); break; case JsonContractType.Dynamic: case JsonContractType.Linq: CurrentSchema.Type = JsonSchemaType.Any; break; default: throw new JsonException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContract)); } } return Pop().Schema; } private JsonSchemaType AddNullType(JsonSchemaType type, Required valueRequired) { if (valueRequired != Required.Always) { return type | JsonSchemaType.Null; } return type; } private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag) { return (value & flag) == flag; } private void GenerateObjectSchema(Type type, JsonObjectContract contract) { CurrentSchema.Properties = new Dictionary(); foreach (Newtonsoft.Json.Serialization.JsonProperty property in contract.Properties) { if (!property.Ignored) { bool flag = property.NullValueHandling == NullValueHandling.Ignore || HasFlag(property.DefaultValueHandling.GetValueOrDefault(), DefaultValueHandling.Ignore) || property.ShouldSerialize != null || property.GetIsSpecified != null; JsonSchema jsonSchema = GenerateInternal(property.PropertyType, property.Required, !flag); if (property.DefaultValue != null) { jsonSchema.Default = JToken.FromObject(property.DefaultValue); } CurrentSchema.Properties.Add(property.PropertyName, jsonSchema); } } if (type.IsSealed()) { CurrentSchema.AllowAdditionalProperties = false; } } private void GenerateISerializableContract(Type type, JsonISerializableContract contract) { CurrentSchema.AllowAdditionalProperties = true; } internal static bool HasFlag(JsonSchemaType? value, JsonSchemaType flag) { if (!value.HasValue) { return true; } if ((value & flag) == flag) { return true; } if (flag == JsonSchemaType.Integer && ((uint?)value & 2u) == 2) { return true; } return false; } private JsonSchemaType GetJsonSchemaType(Type type, Required valueRequired) { JsonSchemaType jsonSchemaType = JsonSchemaType.None; if (valueRequired != Required.Always && ReflectionUtils.IsNullable(type)) { jsonSchemaType = JsonSchemaType.Null; if (ReflectionUtils.IsNullableType(type)) { type = Nullable.GetUnderlyingType(type); } } PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(type); switch (typeCode) { case PrimitiveTypeCode.Empty: case PrimitiveTypeCode.Object: return jsonSchemaType | JsonSchemaType.String; case PrimitiveTypeCode.DBNull: return jsonSchemaType | JsonSchemaType.Null; case PrimitiveTypeCode.Boolean: return jsonSchemaType | JsonSchemaType.Boolean; case PrimitiveTypeCode.Char: return jsonSchemaType | JsonSchemaType.String; case PrimitiveTypeCode.SByte: case PrimitiveTypeCode.Int16: case PrimitiveTypeCode.UInt16: case PrimitiveTypeCode.Int32: case PrimitiveTypeCode.Byte: case PrimitiveTypeCode.UInt32: case PrimitiveTypeCode.Int64: case PrimitiveTypeCode.UInt64: case PrimitiveTypeCode.BigInteger: return jsonSchemaType | JsonSchemaType.Integer; case PrimitiveTypeCode.Single: case PrimitiveTypeCode.Double: case PrimitiveTypeCode.Decimal: return jsonSchemaType | JsonSchemaType.Float; case PrimitiveTypeCode.DateTime: case PrimitiveTypeCode.DateTimeOffset: return jsonSchemaType | JsonSchemaType.String; case PrimitiveTypeCode.Guid: case PrimitiveTypeCode.TimeSpan: case PrimitiveTypeCode.Uri: case PrimitiveTypeCode.String: case PrimitiveTypeCode.Bytes: return jsonSchemaType | JsonSchemaType.String; default: throw new JsonException("Unexpected type code '{0}' for type '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeCode, type)); } } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaModel { public bool Required { get; set; } public JsonSchemaType Type { get; set; } public int? MinimumLength { get; set; } public int? MaximumLength { get; set; } public double? DivisibleBy { get; set; } public double? Minimum { get; set; } public double? Maximum { get; set; } public bool ExclusiveMinimum { get; set; } public bool ExclusiveMaximum { get; set; } public int? MinimumItems { get; set; } public int? MaximumItems { get; set; } public IList Patterns { get; set; } public IList Items { get; set; } public IDictionary Properties { get; set; } public IDictionary PatternProperties { get; set; } public JsonSchemaModel AdditionalProperties { get; set; } public JsonSchemaModel AdditionalItems { get; set; } public bool PositionalItemsValidation { get; set; } public bool AllowAdditionalProperties { get; set; } public bool AllowAdditionalItems { get; set; } public bool UniqueItems { get; set; } public IList Enum { get; set; } public JsonSchemaType Disallow { get; set; } public JsonSchemaModel() { Type = JsonSchemaType.Any; AllowAdditionalProperties = true; AllowAdditionalItems = true; Required = false; } public static JsonSchemaModel Create(IList schemata) { JsonSchemaModel jsonSchemaModel = new JsonSchemaModel(); foreach (JsonSchema schematum in schemata) { Combine(jsonSchemaModel, schematum); } return jsonSchemaModel; } private static void Combine(JsonSchemaModel model, JsonSchema schema) { model.Required = model.Required || schema.Required.GetValueOrDefault(); model.Type &= schema.Type ?? JsonSchemaType.Any; model.MinimumLength = MathUtils.Max(model.MinimumLength, schema.MinimumLength); model.MaximumLength = MathUtils.Min(model.MaximumLength, schema.MaximumLength); model.DivisibleBy = MathUtils.Max(model.DivisibleBy, schema.DivisibleBy); model.Minimum = MathUtils.Max(model.Minimum, schema.Minimum); model.Maximum = MathUtils.Max(model.Maximum, schema.Maximum); model.ExclusiveMinimum = model.ExclusiveMinimum || schema.ExclusiveMinimum.GetValueOrDefault(); model.ExclusiveMaximum = model.ExclusiveMaximum || schema.ExclusiveMaximum.GetValueOrDefault(); model.MinimumItems = MathUtils.Max(model.MinimumItems, schema.MinimumItems); model.MaximumItems = MathUtils.Min(model.MaximumItems, schema.MaximumItems); model.PositionalItemsValidation = model.PositionalItemsValidation || schema.PositionalItemsValidation; model.AllowAdditionalProperties = model.AllowAdditionalProperties && schema.AllowAdditionalProperties; model.AllowAdditionalItems = model.AllowAdditionalItems && schema.AllowAdditionalItems; model.UniqueItems = model.UniqueItems || schema.UniqueItems; if (schema.Enum != null) { if (model.Enum == null) { model.Enum = new List(); } model.Enum.AddRangeDistinct(schema.Enum, JToken.EqualityComparer); } model.Disallow |= schema.Disallow.GetValueOrDefault(); if (schema.Pattern != null) { if (model.Patterns == null) { model.Patterns = new List(); } model.Patterns.AddDistinct(schema.Pattern); } } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaModelBuilder { private JsonSchemaNodeCollection _nodes = new JsonSchemaNodeCollection(); private Dictionary _nodeModels = new Dictionary(); private JsonSchemaNode _node; public JsonSchemaModel Build(JsonSchema schema) { _nodes = new JsonSchemaNodeCollection(); _node = AddSchema(null, schema); _nodeModels = new Dictionary(); return BuildNodeModel(_node); } public JsonSchemaNode AddSchema(JsonSchemaNode existingNode, JsonSchema schema) { string id; if (existingNode != null) { if (existingNode.Schemas.Contains(schema)) { return existingNode; } id = JsonSchemaNode.GetId(existingNode.Schemas.Union(new JsonSchema[1] { schema })); } else { id = JsonSchemaNode.GetId(new JsonSchema[1] { schema }); } if (_nodes.Contains(id)) { return _nodes[id]; } JsonSchemaNode jsonSchemaNode = ((existingNode != null) ? existingNode.Combine(schema) : new JsonSchemaNode(schema)); _nodes.Add(jsonSchemaNode); AddProperties(schema.Properties, jsonSchemaNode.Properties); AddProperties(schema.PatternProperties, jsonSchemaNode.PatternProperties); if (schema.Items != null) { for (int i = 0; i < schema.Items.Count; i++) { AddItem(jsonSchemaNode, i, schema.Items[i]); } } if (schema.AdditionalItems != null) { AddAdditionalItems(jsonSchemaNode, schema.AdditionalItems); } if (schema.AdditionalProperties != null) { AddAdditionalProperties(jsonSchemaNode, schema.AdditionalProperties); } if (schema.Extends != null) { foreach (JsonSchema extend in schema.Extends) { jsonSchemaNode = AddSchema(jsonSchemaNode, extend); } } return jsonSchemaNode; } public void AddProperties(IDictionary source, IDictionary target) { if (source == null) { return; } foreach (KeyValuePair item in source) { AddProperty(target, item.Key, item.Value); } } public void AddProperty(IDictionary target, string propertyName, JsonSchema schema) { target.TryGetValue(propertyName, out var value); target[propertyName] = AddSchema(value, schema); } public void AddItem(JsonSchemaNode parentNode, int index, JsonSchema schema) { JsonSchemaNode existingNode = ((parentNode.Items.Count > index) ? parentNode.Items[index] : null); JsonSchemaNode jsonSchemaNode = AddSchema(existingNode, schema); if (parentNode.Items.Count <= index) { parentNode.Items.Add(jsonSchemaNode); } else { parentNode.Items[index] = jsonSchemaNode; } } public void AddAdditionalProperties(JsonSchemaNode parentNode, JsonSchema schema) { parentNode.AdditionalProperties = AddSchema(parentNode.AdditionalProperties, schema); } public void AddAdditionalItems(JsonSchemaNode parentNode, JsonSchema schema) { parentNode.AdditionalItems = AddSchema(parentNode.AdditionalItems, schema); } private JsonSchemaModel BuildNodeModel(JsonSchemaNode node) { if (_nodeModels.TryGetValue(node, out var value)) { return value; } value = JsonSchemaModel.Create(node.Schemas); _nodeModels[node] = value; foreach (KeyValuePair property in node.Properties) { if (value.Properties == null) { value.Properties = new Dictionary(); } value.Properties[property.Key] = BuildNodeModel(property.Value); } foreach (KeyValuePair patternProperty in node.PatternProperties) { if (value.PatternProperties == null) { value.PatternProperties = new Dictionary(); } value.PatternProperties[patternProperty.Key] = BuildNodeModel(patternProperty.Value); } foreach (JsonSchemaNode item in node.Items) { if (value.Items == null) { value.Items = new List(); } value.Items.Add(BuildNodeModel(item)); } if (node.AdditionalProperties != null) { value.AdditionalProperties = BuildNodeModel(node.AdditionalProperties); } if (node.AdditionalItems != null) { value.AdditionalItems = BuildNodeModel(node.AdditionalItems); } return value; } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaNode { public string Id { get; } public ReadOnlyCollection Schemas { get; } public Dictionary Properties { get; } public Dictionary PatternProperties { get; } public List Items { get; } public JsonSchemaNode AdditionalProperties { get; set; } public JsonSchemaNode AdditionalItems { get; set; } public JsonSchemaNode(JsonSchema schema) { Schemas = new ReadOnlyCollection(new JsonSchema[1] { schema }); Properties = new Dictionary(); PatternProperties = new Dictionary(); Items = new List(); Id = GetId(Schemas); } private JsonSchemaNode(JsonSchemaNode source, JsonSchema schema) { Schemas = new ReadOnlyCollection(source.Schemas.Union(new JsonSchema[1] { schema }).ToList()); Properties = new Dictionary(source.Properties); PatternProperties = new Dictionary(source.PatternProperties); Items = new List(source.Items); AdditionalProperties = source.AdditionalProperties; AdditionalItems = source.AdditionalItems; Id = GetId(Schemas); } public JsonSchemaNode Combine(JsonSchema schema) { return new JsonSchemaNode(this, schema); } public static string GetId(IEnumerable schemata) { return string.Join("-", schemata.Select((JsonSchema s) => s.InternalId).OrderBy((string id) => id, StringComparer.Ordinal)); } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaNodeCollection : KeyedCollection { protected override string GetKeyForItem(JsonSchemaNode item) { return item.Id; } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaResolver { public IList LoadedSchemas { get; protected set; } public JsonSchemaResolver() { LoadedSchemas = new List(); } public virtual JsonSchema GetSchema(string reference) { JsonSchema jsonSchema = LoadedSchemas.SingleOrDefault((JsonSchema s) => string.Equals(s.Id, reference, StringComparison.Ordinal)); if (jsonSchema == null) { jsonSchema = LoadedSchemas.SingleOrDefault((JsonSchema s) => string.Equals(s.Location, reference, StringComparison.Ordinal)); } return jsonSchema; } } [Flags] [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal enum JsonSchemaType { None = 0, String = 1, Float = 2, Integer = 4, Boolean = 8, Object = 0x10, Array = 0x20, Null = 0x40, Any = 0x7F } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaWriter { private readonly JsonWriter _writer; private readonly JsonSchemaResolver _resolver; public JsonSchemaWriter(JsonWriter writer, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(writer, "writer"); _writer = writer; _resolver = resolver; } private void ReferenceOrWriteSchema(JsonSchema schema) { if (schema.Id != null && _resolver.GetSchema(schema.Id) != null) { _writer.WriteStartObject(); _writer.WritePropertyName("$ref"); _writer.WriteValue(schema.Id); _writer.WriteEndObject(); } else { WriteSchema(schema); } } public void WriteSchema(JsonSchema schema) { ValidationUtils.ArgumentNotNull(schema, "schema"); if (!_resolver.LoadedSchemas.Contains(schema)) { _resolver.LoadedSchemas.Add(schema); } _writer.WriteStartObject(); WritePropertyIfNotNull(_writer, "id", schema.Id); WritePropertyIfNotNull(_writer, "title", schema.Title); WritePropertyIfNotNull(_writer, "description", schema.Description); WritePropertyIfNotNull(_writer, "required", schema.Required); WritePropertyIfNotNull(_writer, "readonly", schema.ReadOnly); WritePropertyIfNotNull(_writer, "hidden", schema.Hidden); WritePropertyIfNotNull(_writer, "transient", schema.Transient); if (schema.Type.HasValue) { WriteType("type", _writer, schema.Type.GetValueOrDefault()); } if (!schema.AllowAdditionalProperties) { _writer.WritePropertyName("additionalProperties"); _writer.WriteValue(schema.AllowAdditionalProperties); } else if (schema.AdditionalProperties != null) { _writer.WritePropertyName("additionalProperties"); ReferenceOrWriteSchema(schema.AdditionalProperties); } if (!schema.AllowAdditionalItems) { _writer.WritePropertyName("additionalItems"); _writer.WriteValue(schema.AllowAdditionalItems); } else if (schema.AdditionalItems != null) { _writer.WritePropertyName("additionalItems"); ReferenceOrWriteSchema(schema.AdditionalItems); } WriteSchemaDictionaryIfNotNull(_writer, "properties", schema.Properties); WriteSchemaDictionaryIfNotNull(_writer, "patternProperties", schema.PatternProperties); WriteItems(schema); WritePropertyIfNotNull(_writer, "minimum", schema.Minimum); WritePropertyIfNotNull(_writer, "maximum", schema.Maximum); WritePropertyIfNotNull(_writer, "exclusiveMinimum", schema.ExclusiveMinimum); WritePropertyIfNotNull(_writer, "exclusiveMaximum", schema.ExclusiveMaximum); WritePropertyIfNotNull(_writer, "minLength", schema.MinimumLength); WritePropertyIfNotNull(_writer, "maxLength", schema.MaximumLength); WritePropertyIfNotNull(_writer, "minItems", schema.MinimumItems); WritePropertyIfNotNull(_writer, "maxItems", schema.MaximumItems); WritePropertyIfNotNull(_writer, "divisibleBy", schema.DivisibleBy); WritePropertyIfNotNull(_writer, "format", schema.Format); WritePropertyIfNotNull(_writer, "pattern", schema.Pattern); if (schema.Enum != null) { _writer.WritePropertyName("enum"); _writer.WriteStartArray(); foreach (JToken item in schema.Enum) { item.WriteTo(_writer); } _writer.WriteEndArray(); } if (schema.Default != null) { _writer.WritePropertyName("default"); schema.Default.WriteTo(_writer); } if (schema.Disallow.HasValue) { WriteType("disallow", _writer, schema.Disallow.GetValueOrDefault()); } if (schema.Extends != null && schema.Extends.Count > 0) { _writer.WritePropertyName("extends"); if (schema.Extends.Count == 1) { ReferenceOrWriteSchema(schema.Extends[0]); } else { _writer.WriteStartArray(); foreach (JsonSchema extend in schema.Extends) { ReferenceOrWriteSchema(extend); } _writer.WriteEndArray(); } } _writer.WriteEndObject(); } private void WriteSchemaDictionaryIfNotNull(JsonWriter writer, string propertyName, IDictionary properties) { if (properties == null) { return; } writer.WritePropertyName(propertyName); writer.WriteStartObject(); foreach (KeyValuePair property in properties) { writer.WritePropertyName(property.Key); ReferenceOrWriteSchema(property.Value); } writer.WriteEndObject(); } private void WriteItems(JsonSchema schema) { if (schema.Items == null && !schema.PositionalItemsValidation) { return; } _writer.WritePropertyName("items"); if (!schema.PositionalItemsValidation) { if (schema.Items != null && schema.Items.Count > 0) { ReferenceOrWriteSchema(schema.Items[0]); return; } _writer.WriteStartObject(); _writer.WriteEndObject(); return; } _writer.WriteStartArray(); if (schema.Items != null) { foreach (JsonSchema item in schema.Items) { ReferenceOrWriteSchema(item); } } _writer.WriteEndArray(); } private void WriteType(string propertyName, JsonWriter writer, JsonSchemaType type) { if (Enum.IsDefined(typeof(JsonSchemaType), type)) { writer.WritePropertyName(propertyName); writer.WriteValue(JsonSchemaBuilder.MapType(type)); return; } IEnumerator enumerator = (from v in EnumUtils.GetFlagsValues(type) where v != JsonSchemaType.None select v).GetEnumerator(); if (!enumerator.MoveNext()) { return; } writer.WritePropertyName(propertyName); JsonSchemaType current = enumerator.Current; if (enumerator.MoveNext()) { writer.WriteStartArray(); writer.WriteValue(JsonSchemaBuilder.MapType(current)); do { writer.WriteValue(JsonSchemaBuilder.MapType(enumerator.Current)); } while (enumerator.MoveNext()); writer.WriteEndArray(); } else { writer.WriteValue(JsonSchemaBuilder.MapType(current)); } } private void WritePropertyIfNotNull(JsonWriter writer, string propertyName, object value) { if (value != null) { writer.WritePropertyName(propertyName); writer.WriteValue(value); } } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal enum UndefinedSchemaIdHandling { None, UseTypeName, UseAssemblyQualifiedName } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class ValidationEventArgs : EventArgs { private readonly JsonSchemaException _ex; public JsonSchemaException Exception => _ex; public string Path => _ex.Path; public string Message => _ex.Message; internal ValidationEventArgs(JsonSchemaException ex) { ValidationUtils.ArgumentNotNull(ex, "ex"); _ex = ex; } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal delegate void ValidationEventHandler(object sender, ValidationEventArgs e); } namespace Newtonsoft.Json.Linq { internal enum CommentHandling { Ignore, Load } internal enum DuplicatePropertyNameHandling { Replace, Ignore, Error } internal static class Extensions { public static IJEnumerable Ancestors(this IEnumerable source) where T : JToken { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((T j) => j.Ancestors()).AsJEnumerable(); } public static IJEnumerable AncestorsAndSelf(this IEnumerable source) where T : JToken { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((T j) => j.AncestorsAndSelf()).AsJEnumerable(); } public static IJEnumerable Descendants(this IEnumerable source) where T : JContainer { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((T j) => j.Descendants()).AsJEnumerable(); } public static IJEnumerable DescendantsAndSelf(this IEnumerable source) where T : JContainer { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((T j) => j.DescendantsAndSelf()).AsJEnumerable(); } public static IJEnumerable Properties(this IEnumerable source) { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((JObject d) => d.Properties()).AsJEnumerable(); } public static IJEnumerable Values(this IEnumerable source, object? key) { return source.Values(key).AsJEnumerable(); } public static IJEnumerable Values(this IEnumerable source) { return source.Values(null); } public static IEnumerable Values(this IEnumerable source, object key) { return source.Values(key); } public static IEnumerable Values(this IEnumerable source) { return source.Values(null); } public static U? Value(this IEnumerable value) { return value.Value(); } public static U? Value(this IEnumerable value) where T : JToken { ValidationUtils.ArgumentNotNull(value, "value"); return ((value as JToken) ?? throw new ArgumentException("Source value must be a JToken.")).Convert(); } internal static IEnumerable Values(this IEnumerable source, object? key) where T : JToken { ValidationUtils.ArgumentNotNull(source, "source"); if (key == null) { foreach (T item in source) { if (item is JValue token) { yield return token.Convert(); continue; } foreach (JToken item2 in item.Children()) { yield return item2.Convert(); } } yield break; } foreach (T item3 in source) { JToken jToken = item3[key]; if (jToken != null) { yield return jToken.Convert(); } } } public static IJEnumerable Children(this IEnumerable source) where T : JToken { return source.Children().AsJEnumerable(); } public static IEnumerable Children(this IEnumerable source) where T : JToken { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((T c) => c.Children()).Convert(); } internal static IEnumerable Convert(this IEnumerable source) where T : JToken { ValidationUtils.ArgumentNotNull(source, "source"); foreach (T item in source) { yield return item.Convert(); } } internal static U? Convert(this T token) where T : JToken? { if (token == null) { return default(U); } if (token is U) { U result = (U)(object)((token is U) ? token : null); if (typeof(U) != typeof(IComparable) && typeof(U) != typeof(IFormattable)) { return result; } } if (!(token is JValue jValue)) { throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(T))); } object value = jValue.Value; if (value is U) { return (U)value; } Type type = typeof(U); if (ReflectionUtils.IsNullableType(type)) { if (jValue.Value == null) { return default(U); } type = Nullable.GetUnderlyingType(type); } return (U)System.Convert.ChangeType(jValue.Value, type, CultureInfo.InvariantCulture); } public static IJEnumerable AsJEnumerable(this IEnumerable source) { return source.AsJEnumerable(); } public static IJEnumerable AsJEnumerable(this IEnumerable source) where T : JToken { if (source == null) { return null; } if (source is IJEnumerable result) { return result; } return new JEnumerable(source); } } internal interface IJEnumerable : IEnumerable, IEnumerable where T : JToken { IJEnumerable this[object key] { get; } } internal class JArray : JContainer, IList, ICollection, IEnumerable, IEnumerable { private readonly List _values = new List(); protected override IList ChildrenTokens => _values; public override JTokenType Type => JTokenType.Array; public override JToken? this[object key] { get { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is int)) { throw new ArgumentException("Accessed JArray values with invalid key value: {0}. Int32 array index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } return GetItem((int)key); } set { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is int)) { throw new ArgumentException("Set JArray values with invalid key value: {0}. Int32 array index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } SetItem((int)key, value); } } public JToken this[int index] { get { return GetItem(index); } set { SetItem(index, value); } } public bool IsReadOnly => false; public override async Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { await writer.WriteStartArrayAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); for (int i = 0; i < _values.Count; i++) { await _values[i].WriteToAsync(writer, cancellationToken, converters).ConfigureAwait(continueOnCapturedContext: false); } await writer.WriteEndArrayAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return LoadAsync(reader, null, cancellationToken); } public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { if (reader.TokenType == JsonToken.None && !(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader."); } await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (reader.TokenType != JsonToken.StartArray) { throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JArray a = new JArray(); a.SetLineInfo(reader as IJsonLineInfo, settings); await a.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return a; } public JArray() { } public JArray(JArray other) : base(other, null) { } internal JArray(JArray other, JsonCloneSettings? settings) : base(other, settings) { } public JArray(params object[] content) : this((object)content) { } public JArray(object content) { Add(content); } internal override bool DeepEquals(JToken node) { if (node is JArray container) { return ContentsEqual(container); } return false; } internal override JToken CloneToken(JsonCloneSettings? settings = null) { return new JArray(this, settings); } public new static JArray Load(JsonReader reader) { return Load(reader, null); } public new static JArray Load(JsonReader reader, JsonLoadSettings? settings) { if (reader.TokenType == JsonToken.None && !reader.Read()) { throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader."); } reader.MoveToContent(); if (reader.TokenType != JsonToken.StartArray) { throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JArray jArray = new JArray(); jArray.SetLineInfo(reader as IJsonLineInfo, settings); jArray.ReadTokenFrom(reader, settings); return jArray; } public new static JArray Parse(string json) { return Parse(json, null); } public new static JArray Parse(string json, JsonLoadSettings? settings) { using JsonReader jsonReader = new JsonTextReader(new StringReader(json)); JArray result = Load(jsonReader, settings); while (jsonReader.Read()) { } return result; } public new static JArray FromObject(object o) { return FromObject(o, JsonSerializer.CreateDefault()); } public new static JArray FromObject(object o, JsonSerializer jsonSerializer) { JToken jToken = JToken.FromObjectInternal(o, jsonSerializer); if (jToken.Type != JTokenType.Array) { throw new ArgumentException("Object serialized to {0}. JArray instance expected.".FormatWith(CultureInfo.InvariantCulture, jToken.Type)); } return (JArray)jToken; } public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { writer.WriteStartArray(); for (int i = 0; i < _values.Count; i++) { _values[i].WriteTo(writer, converters); } writer.WriteEndArray(); } internal override int IndexOfItem(JToken? item) { if (item == null) { return -1; } return _values.IndexOfReference(item); } internal override void MergeItem(object content, JsonMergeSettings? settings) { IEnumerable enumerable = ((IsMultiContent(content) || content is JArray) ? ((IEnumerable)content) : null); if (enumerable != null) { JContainer.MergeEnumerableContent(this, enumerable, settings); } } public int IndexOf(JToken item) { return IndexOfItem(item); } public void Insert(int index, JToken item) { InsertItem(index, item, skipParentCheck: false, copyAnnotations: true); } public void RemoveAt(int index) { RemoveItemAt(index); } public IEnumerator GetEnumerator() { return Children().GetEnumerator(); } public void Add(JToken item) { Add((object?)item); } public void Clear() { ClearItems(); } public bool Contains(JToken item) { return ContainsItem(item); } public void CopyTo(JToken[] array, int arrayIndex) { CopyItemsTo(array, arrayIndex); } public bool Remove(JToken item) { return RemoveItem(item); } internal override int GetDeepHashCode() { return ContentsHashCode(); } } internal class JConstructor : JContainer { private string? _name; private readonly List _values = new List(); protected override IList ChildrenTokens => _values; public string? Name { get { return _name; } set { _name = value; } } public override JTokenType Type => JTokenType.Constructor; public override JToken? this[object key] { get { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is int index)) { throw new ArgumentException("Accessed JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } return GetItem(index); } set { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is int index)) { throw new ArgumentException("Set JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } SetItem(index, value); } } public override async Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { await writer.WriteStartConstructorAsync(_name ?? string.Empty, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); for (int i = 0; i < _values.Count; i++) { await _values[i].WriteToAsync(writer, cancellationToken, converters).ConfigureAwait(continueOnCapturedContext: false); } await writer.WriteEndConstructorAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return LoadAsync(reader, null, cancellationToken); } public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { if (reader.TokenType == JsonToken.None && !(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader."); } await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (reader.TokenType != JsonToken.StartConstructor) { throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JConstructor c = new JConstructor((string)reader.Value); c.SetLineInfo(reader as IJsonLineInfo, settings); await c.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return c; } internal override int IndexOfItem(JToken? item) { if (item == null) { return -1; } return _values.IndexOfReference(item); } internal override void MergeItem(object content, JsonMergeSettings? settings) { if (content is JConstructor jConstructor) { if (jConstructor.Name != null) { Name = jConstructor.Name; } JContainer.MergeEnumerableContent(this, jConstructor, settings); } } public JConstructor() { } public JConstructor(JConstructor other) : base(other, null) { _name = other.Name; } internal JConstructor(JConstructor other, JsonCloneSettings? settings) : base(other, settings) { _name = other.Name; } public JConstructor(string name, params object[] content) : this(name, (object)content) { } public JConstructor(string name, object content) : this(name) { Add(content); } public JConstructor(string name) { if (name == null) { throw new ArgumentNullException("name"); } if (name.Length == 0) { throw new ArgumentException("Constructor name cannot be empty.", "name"); } _name = name; } internal override bool DeepEquals(JToken node) { if (node is JConstructor jConstructor && _name == jConstructor.Name) { return ContentsEqual(jConstructor); } return false; } internal override JToken CloneToken(JsonCloneSettings? settings = null) { return new JConstructor(this, settings); } public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { writer.WriteStartConstructor(_name); int count = _values.Count; for (int i = 0; i < count; i++) { _values[i].WriteTo(writer, converters); } writer.WriteEndConstructor(); } internal override int GetDeepHashCode() { return (_name?.GetHashCode(StringComparison.Ordinal) ?? 0) ^ ContentsHashCode(); } public new static JConstructor Load(JsonReader reader) { return Load(reader, null); } public new static JConstructor Load(JsonReader reader, JsonLoadSettings? settings) { if (reader.TokenType == JsonToken.None && !reader.Read()) { throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader."); } reader.MoveToContent(); if (reader.TokenType != JsonToken.StartConstructor) { throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JConstructor jConstructor = new JConstructor((string)reader.Value); jConstructor.SetLineInfo(reader as IJsonLineInfo, settings); jConstructor.ReadTokenFrom(reader, settings); return jConstructor; } } internal abstract class JContainer : JToken, IList, ICollection, IEnumerable, IEnumerable, ITypedList, IBindingList, ICollection, IList, INotifyCollectionChanged { internal ListChangedEventHandler? _listChanged; internal AddingNewEventHandler? _addingNew; internal NotifyCollectionChangedEventHandler? _collectionChanged; private object? _syncRoot; private bool _busy; protected abstract IList ChildrenTokens { get; } public override bool HasValues => ChildrenTokens.Count > 0; public override JToken? First { get { IList childrenTokens = ChildrenTokens; if (childrenTokens.Count <= 0) { return null; } return childrenTokens[0]; } } public override JToken? Last { get { IList childrenTokens = ChildrenTokens; int count = childrenTokens.Count; if (count <= 0) { return null; } return childrenTokens[count - 1]; } } JToken IList.this[int index] { get { return GetItem(index); } set { SetItem(index, value); } } bool ICollection.IsReadOnly => false; bool IList.IsFixedSize => false; bool IList.IsReadOnly => false; object? IList.this[int index] { get { return GetItem(index); } set { SetItem(index, EnsureValue(value)); } } public int Count => ChildrenTokens.Count; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), null); } return _syncRoot; } } bool IBindingList.AllowEdit => true; bool IBindingList.AllowNew => true; bool IBindingList.AllowRemove => true; bool IBindingList.IsSorted => false; ListSortDirection IBindingList.SortDirection => ListSortDirection.Ascending; PropertyDescriptor? IBindingList.SortProperty => null; bool IBindingList.SupportsChangeNotification => true; bool IBindingList.SupportsSearching => false; bool IBindingList.SupportsSorting => false; public event ListChangedEventHandler ListChanged { add { _listChanged = (ListChangedEventHandler)Delegate.Combine(_listChanged, value); } remove { _listChanged = (ListChangedEventHandler)Delegate.Remove(_listChanged, value); } } public event AddingNewEventHandler AddingNew { add { _addingNew = (AddingNewEventHandler)Delegate.Combine(_addingNew, value); } remove { _addingNew = (AddingNewEventHandler)Delegate.Remove(_addingNew, value); } } public event NotifyCollectionChangedEventHandler? CollectionChanged { add { _collectionChanged = (NotifyCollectionChangedEventHandler)Delegate.Combine(_collectionChanged, value); } remove { _collectionChanged = (NotifyCollectionChangedEventHandler)Delegate.Remove(_collectionChanged, value); } } internal async Task ReadTokenFromAsync(JsonReader reader, JsonLoadSettings? options, CancellationToken cancellationToken = default(CancellationToken)) { ValidationUtils.ArgumentNotNull(reader, "reader"); int startDepth = reader.Depth; if (!(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); } await ReadContentFromAsync(reader, options, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (reader.Depth > startDepth) { throw JsonReaderException.Create(reader, "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); } } private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { IJsonLineInfo lineInfo = reader as IJsonLineInfo; JContainer parent = this; do { if (parent is JProperty jProperty && jProperty.Value != null) { if (parent == this) { break; } parent = parent.Parent; } switch (reader.TokenType) { case JsonToken.StartArray: { JArray jArray = new JArray(); jArray.SetLineInfo(lineInfo, settings); parent.Add(jArray); parent = jArray; break; } case JsonToken.EndArray: if (parent == this) { return; } parent = parent.Parent; break; case JsonToken.StartObject: { JObject jObject = new JObject(); jObject.SetLineInfo(lineInfo, settings); parent.Add(jObject); parent = jObject; break; } case JsonToken.EndObject: if (parent == this) { return; } parent = parent.Parent; break; case JsonToken.StartConstructor: { JConstructor jConstructor = new JConstructor(reader.Value.ToString()); jConstructor.SetLineInfo(lineInfo, settings); parent.Add(jConstructor); parent = jConstructor; break; } case JsonToken.EndConstructor: if (parent == this) { return; } parent = parent.Parent; break; case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { JValue jValue = new JValue(reader.Value); jValue.SetLineInfo(lineInfo, settings); parent.Add(jValue); break; } case JsonToken.Comment: if (settings != null && settings.CommentHandling == CommentHandling.Load) { JValue jValue = JValue.CreateComment(reader.Value.ToString()); jValue.SetLineInfo(lineInfo, settings); parent.Add(jValue); } break; case JsonToken.Null: { JValue jValue = JValue.CreateNull(); jValue.SetLineInfo(lineInfo, settings); parent.Add(jValue); break; } case JsonToken.Undefined: { JValue jValue = JValue.CreateUndefined(); jValue.SetLineInfo(lineInfo, settings); parent.Add(jValue); break; } case JsonToken.PropertyName: { JProperty jProperty2 = ReadProperty(reader, settings, lineInfo, parent); if (jProperty2 != null) { parent = jProperty2; } else { await reader.SkipAsync().ConfigureAwait(continueOnCapturedContext: false); } break; } default: throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); case JsonToken.None: break; } } while (await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } internal JContainer() { } internal JContainer(JContainer other, JsonCloneSettings? settings) : this() { ValidationUtils.ArgumentNotNull(other, "other"); bool flag = settings?.CopyAnnotations ?? true; if (flag) { CopyAnnotations(this, other); } int num = 0; foreach (JToken item in (IEnumerable)other) { TryAddInternal(num, item, skipParentCheck: false, flag); num++; } } internal void CheckReentrancy() { if (_busy) { throw new InvalidOperationException("Cannot change {0} during a collection change event.".FormatWith(CultureInfo.InvariantCulture, GetType())); } } internal virtual IList CreateChildrenCollection() { return new List(); } protected virtual void OnAddingNew(AddingNewEventArgs e) { _addingNew?.Invoke(this, e); } protected virtual void OnListChanged(ListChangedEventArgs e) { ListChangedEventHandler listChanged = _listChanged; if (listChanged != null) { _busy = true; try { listChanged(this, e); } finally { _busy = false; } } } protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { NotifyCollectionChangedEventHandler collectionChanged = _collectionChanged; if (collectionChanged != null) { _busy = true; try { collectionChanged(this, e); } finally { _busy = false; } } } internal bool ContentsEqual(JContainer container) { if (container == this) { return true; } IList childrenTokens = ChildrenTokens; IList childrenTokens2 = container.ChildrenTokens; if (childrenTokens.Count != childrenTokens2.Count) { return false; } for (int i = 0; i < childrenTokens.Count; i++) { if (!childrenTokens[i].DeepEquals(childrenTokens2[i])) { return false; } } return true; } public override JEnumerable Children() { return new JEnumerable(ChildrenTokens); } public override IEnumerable Values() { return ChildrenTokens.Convert(); } public IEnumerable Descendants() { return GetDescendants(self: false); } public IEnumerable DescendantsAndSelf() { return GetDescendants(self: true); } internal IEnumerable GetDescendants(bool self) { if (self) { yield return this; } foreach (JToken o in ChildrenTokens) { yield return o; if (!(o is JContainer jContainer)) { continue; } foreach (JToken item in jContainer.Descendants()) { yield return item; } } } internal bool IsMultiContent([NotNullWhen(true)] object? content) { if (content is IEnumerable && !(content is string) && !(content is JToken)) { return !(content is byte[]); } return false; } internal JToken EnsureParentToken(JToken? item, bool skipParentCheck, bool copyAnnotations) { if (item == null) { return JValue.CreateNull(); } if (skipParentCheck) { return item; } if (item.Parent != null || item == this || (item.HasValues && base.Root == item)) { JsonCloneSettings settings = (copyAnnotations ? null : JsonCloneSettings.SkipCopyAnnotations); item = item.CloneToken(settings); } return item; } internal abstract int IndexOfItem(JToken? item); internal virtual bool InsertItem(int index, JToken? item, bool skipParentCheck, bool copyAnnotations) { IList childrenTokens = ChildrenTokens; if (index > childrenTokens.Count) { throw new ArgumentOutOfRangeException("index", "Index must be within the bounds of the List."); } CheckReentrancy(); item = EnsureParentToken(item, skipParentCheck, copyAnnotations); JToken jToken = ((index == 0) ? null : childrenTokens[index - 1]); JToken jToken2 = ((index == childrenTokens.Count) ? null : childrenTokens[index]); ValidateToken(item, null); item.Parent = this; item.Previous = jToken; if (jToken != null) { jToken.Next = item; } item.Next = jToken2; if (jToken2 != null) { jToken2.Previous = item; } childrenTokens.Insert(index, item); if (_listChanged != null) { OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index)); } if (_collectionChanged != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index)); } return true; } internal virtual void RemoveItemAt(int index) { IList childrenTokens = ChildrenTokens; if (index < 0) { throw new ArgumentOutOfRangeException("index", "Index is less than 0."); } if (index >= childrenTokens.Count) { throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count."); } CheckReentrancy(); JToken jToken = childrenTokens[index]; JToken jToken2 = ((index == 0) ? null : childrenTokens[index - 1]); JToken jToken3 = ((index == childrenTokens.Count - 1) ? null : childrenTokens[index + 1]); if (jToken2 != null) { jToken2.Next = jToken3; } if (jToken3 != null) { jToken3.Previous = jToken2; } jToken.Parent = null; jToken.Previous = null; jToken.Next = null; childrenTokens.RemoveAt(index); if (_listChanged != null) { OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index)); } if (_collectionChanged != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, jToken, index)); } } internal virtual bool RemoveItem(JToken? item) { if (item != null) { int num = IndexOfItem(item); if (num >= 0) { RemoveItemAt(num); return true; } } return false; } internal virtual JToken GetItem(int index) { return ChildrenTokens[index]; } internal virtual void SetItem(int index, JToken? item) { IList childrenTokens = ChildrenTokens; if (index < 0) { throw new ArgumentOutOfRangeException("index", "Index is less than 0."); } if (index >= childrenTokens.Count) { throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count."); } JToken jToken = childrenTokens[index]; if (!IsTokenUnchanged(jToken, item)) { CheckReentrancy(); item = EnsureParentToken(item, skipParentCheck: false, copyAnnotations: true); ValidateToken(item, jToken); JToken jToken2 = ((index == 0) ? null : childrenTokens[index - 1]); JToken jToken3 = ((index == childrenTokens.Count - 1) ? null : childrenTokens[index + 1]); item.Parent = this; item.Previous = jToken2; if (jToken2 != null) { jToken2.Next = item; } item.Next = jToken3; if (jToken3 != null) { jToken3.Previous = item; } childrenTokens[index] = item; jToken.Parent = null; jToken.Previous = null; jToken.Next = null; if (_listChanged != null) { OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index)); } if (_collectionChanged != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, jToken, index)); } } } internal virtual void ClearItems() { CheckReentrancy(); IList childrenTokens = ChildrenTokens; foreach (JToken item in childrenTokens) { item.Parent = null; item.Previous = null; item.Next = null; } childrenTokens.Clear(); if (_listChanged != null) { OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); } if (_collectionChanged != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } } internal virtual void ReplaceItem(JToken existing, JToken replacement) { if (existing != null && existing.Parent == this) { int index = IndexOfItem(existing); SetItem(index, replacement); } } internal virtual bool ContainsItem(JToken? item) { return IndexOfItem(item) != -1; } internal virtual void CopyItemsTo(Array array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0) { throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0."); } if (arrayIndex >= array.Length && arrayIndex != 0) { throw new ArgumentException("arrayIndex is equal to or greater than the length of array."); } if (Count > array.Length - arrayIndex) { throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array."); } int num = 0; foreach (JToken childrenToken in ChildrenTokens) { array.SetValue(childrenToken, arrayIndex + num); num++; } } internal static bool IsTokenUnchanged(JToken currentValue, JToken? newValue) { if (currentValue is JValue jValue) { if (newValue == null) { return jValue.Type == JTokenType.Null; } return jValue.Equals(newValue); } return false; } internal virtual void ValidateToken(JToken o, JToken? existing) { ValidationUtils.ArgumentNotNull(o, "o"); if (o.Type == JTokenType.Property) { throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType())); } } public virtual void Add(object? content) { TryAddInternal(ChildrenTokens.Count, content, skipParentCheck: false, copyAnnotations: true); } internal bool TryAdd(object? content) { return TryAddInternal(ChildrenTokens.Count, content, skipParentCheck: false, copyAnnotations: true); } internal void AddAndSkipParentCheck(JToken token) { TryAddInternal(ChildrenTokens.Count, token, skipParentCheck: true, copyAnnotations: true); } public void AddFirst(object? content) { TryAddInternal(0, content, skipParentCheck: false, copyAnnotations: true); } internal bool TryAddInternal(int index, object? content, bool skipParentCheck, bool copyAnnotations) { if (IsMultiContent(content)) { IEnumerable obj = (IEnumerable)content; int num = index; foreach (object item2 in obj) { TryAddInternal(num, item2, skipParentCheck, copyAnnotations); num++; } return true; } JToken item = CreateFromContent(content); return InsertItem(index, item, skipParentCheck, copyAnnotations); } internal static JToken CreateFromContent(object? content) { if (content is JToken result) { return result; } return new JValue(content); } public JsonWriter CreateWriter() { return new JTokenWriter(this); } public void ReplaceAll(object content) { ClearItems(); Add(content); } public void RemoveAll() { ClearItems(); } internal abstract void MergeItem(object content, JsonMergeSettings? settings); public void Merge(object? content) { if (content != null) { ValidateContent(content); MergeItem(content, null); } } public void Merge(object? content, JsonMergeSettings? settings) { if (content != null) { ValidateContent(content); MergeItem(content, settings); } } private void ValidateContent(object content) { if (content.GetType().IsSubclassOf(typeof(JToken)) || IsMultiContent(content)) { return; } throw new ArgumentException("Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, content.GetType()), "content"); } internal void ReadTokenFrom(JsonReader reader, JsonLoadSettings? options) { int depth = reader.Depth; if (!reader.Read()) { throw JsonReaderException.Create(reader, "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); } ReadContentFrom(reader, options); if (reader.Depth > depth) { throw JsonReaderException.Create(reader, "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); } } internal void ReadContentFrom(JsonReader r, JsonLoadSettings? settings) { ValidationUtils.ArgumentNotNull(r, "r"); IJsonLineInfo lineInfo = r as IJsonLineInfo; JContainer jContainer = this; do { if (jContainer is JProperty jProperty && jProperty.Value != null) { if (jContainer == this) { break; } jContainer = jContainer.Parent; } switch (r.TokenType) { case JsonToken.StartArray: { JArray jArray = new JArray(); jArray.SetLineInfo(lineInfo, settings); jContainer.Add(jArray); jContainer = jArray; break; } case JsonToken.EndArray: if (jContainer == this) { return; } jContainer = jContainer.Parent; break; case JsonToken.StartObject: { JObject jObject = new JObject(); jObject.SetLineInfo(lineInfo, settings); jContainer.Add(jObject); jContainer = jObject; break; } case JsonToken.EndObject: if (jContainer == this) { return; } jContainer = jContainer.Parent; break; case JsonToken.StartConstructor: { JConstructor jConstructor = new JConstructor(r.Value.ToString()); jConstructor.SetLineInfo(lineInfo, settings); jContainer.Add(jConstructor); jContainer = jConstructor; break; } case JsonToken.EndConstructor: if (jContainer == this) { return; } jContainer = jContainer.Parent; break; case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { JValue jValue = new JValue(r.Value); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); break; } case JsonToken.Comment: if (settings != null && settings.CommentHandling == CommentHandling.Load) { JValue jValue = JValue.CreateComment(r.Value.ToString()); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); } break; case JsonToken.Null: { JValue jValue = JValue.CreateNull(); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); break; } case JsonToken.Undefined: { JValue jValue = JValue.CreateUndefined(); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); break; } case JsonToken.PropertyName: { JProperty jProperty2 = ReadProperty(r, settings, lineInfo, jContainer); if (jProperty2 != null) { jContainer = jProperty2; } else { r.Skip(); } break; } default: throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, r.TokenType)); case JsonToken.None: break; } } while (r.Read()); } private static JProperty? ReadProperty(JsonReader r, JsonLoadSettings? settings, IJsonLineInfo? lineInfo, JContainer parent) { DuplicatePropertyNameHandling duplicatePropertyNameHandling = settings?.DuplicatePropertyNameHandling ?? DuplicatePropertyNameHandling.Replace; JObject obj = (JObject)parent; string text = r.Value.ToString(); JProperty jProperty = obj.Property(text, StringComparison.Ordinal); if (jProperty != null) { switch (duplicatePropertyNameHandling) { case DuplicatePropertyNameHandling.Ignore: return null; case DuplicatePropertyNameHandling.Error: throw JsonReaderException.Create(r, "Property with the name '{0}' already exists in the current JSON object.".FormatWith(CultureInfo.InvariantCulture, text)); } } JProperty jProperty2 = new JProperty(text); jProperty2.SetLineInfo(lineInfo, settings); if (jProperty == null) { parent.Add(jProperty2); } else { jProperty.Replace(jProperty2); } return jProperty2; } internal int ContentsHashCode() { int num = 0; foreach (JToken childrenToken in ChildrenTokens) { num ^= childrenToken.GetDeepHashCode(); } return num; } string ITypedList.GetListName(PropertyDescriptor[] listAccessors) { return string.Empty; } PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) { return (First as ICustomTypeDescriptor)?.GetProperties() ?? new PropertyDescriptorCollection(CollectionUtils.ArrayEmpty()); } int IList.IndexOf(JToken item) { return IndexOfItem(item); } void IList.Insert(int index, JToken item) { InsertItem(index, item, skipParentCheck: false, copyAnnotations: true); } void IList.RemoveAt(int index) { RemoveItemAt(index); } void ICollection.Add(JToken item) { Add(item); } void ICollection.Clear() { ClearItems(); } bool ICollection.Contains(JToken item) { return ContainsItem(item); } void ICollection.CopyTo(JToken[] array, int arrayIndex) { CopyItemsTo(array, arrayIndex); } bool ICollection.Remove(JToken item) { return RemoveItem(item); } private JToken? EnsureValue(object? value) { if (value == null) { return null; } if (value is JToken result) { return result; } throw new ArgumentException("Argument is not a JToken."); } int IList.Add(object? value) { Add(EnsureValue(value)); return Count - 1; } void IList.Clear() { ClearItems(); } bool IList.Contains(object? value) { return ContainsItem(EnsureValue(value)); } int IList.IndexOf(object? value) { return IndexOfItem(EnsureValue(value)); } void IList.Insert(int index, object? value) { InsertItem(index, EnsureValue(value), skipParentCheck: false, copyAnnotations: false); } void IList.Remove(object? value) { RemoveItem(EnsureValue(value)); } void IList.RemoveAt(int index) { RemoveItemAt(index); } void ICollection.CopyTo(Array array, int index) { CopyItemsTo(array, index); } void IBindingList.AddIndex(PropertyDescriptor property) { } object IBindingList.AddNew() { AddingNewEventArgs addingNewEventArgs = new AddingNewEventArgs(); OnAddingNew(addingNewEventArgs); if (addingNewEventArgs.NewObject == null) { throw new JsonException("Could not determine new value to add to '{0}'.".FormatWith(CultureInfo.InvariantCulture, GetType())); } if (!(addingNewEventArgs.NewObject is JToken jToken)) { throw new JsonException("New item to be added to collection must be compatible with {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JToken))); } Add(jToken); return jToken; } void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) { throw new NotSupportedException(); } int IBindingList.Find(PropertyDescriptor property, object key) { throw new NotSupportedException(); } void IBindingList.RemoveIndex(PropertyDescriptor property) { } void IBindingList.RemoveSort() { throw new NotSupportedException(); } internal static void MergeEnumerableContent(JContainer target, IEnumerable content, JsonMergeSettings? settings) { switch (settings?.MergeArrayHandling ?? MergeArrayHandling.Concat) { case MergeArrayHandling.Concat: { foreach (object item in content) { target.Add(CreateFromContent(item)); } break; } case MergeArrayHandling.Union: { HashSet hashSet = new HashSet(target, JToken.EqualityComparer); { foreach (object item2 in content) { JToken jToken2 = CreateFromContent(item2); if (hashSet.Add(jToken2)) { target.Add(jToken2); } } break; } } case MergeArrayHandling.Replace: if (target == content) { break; } target.ClearItems(); { foreach (object item3 in content) { target.Add(CreateFromContent(item3)); } break; } case MergeArrayHandling.Merge: { int num = 0; { foreach (object item4 in content) { if (num < target.Count) { if (target[num] is JContainer jContainer) { jContainer.Merge(item4, settings); } else if (item4 != null) { JToken jToken = CreateFromContent(item4); if (jToken.Type != JTokenType.Null) { target[num] = jToken; } } } else { target.Add(CreateFromContent(item4)); } num++; } break; } } default: throw new ArgumentOutOfRangeException("settings", "Unexpected merge array handling when merging JSON."); } } } internal readonly struct JEnumerable : IJEnumerable, IEnumerable, IEnumerable, IEquatable> where T : JToken { public static readonly JEnumerable Empty = new JEnumerable(Enumerable.Empty()); private readonly IEnumerable _enumerable; public IJEnumerable this[object key] { get { if (_enumerable == null) { return JEnumerable.Empty; } return new JEnumerable(_enumerable.Values(key)); } } public JEnumerable(IEnumerable enumerable) { ValidationUtils.ArgumentNotNull(enumerable, "enumerable"); _enumerable = enumerable; } public IEnumerator GetEnumerator() { return ((IEnumerable)(_enumerable ?? ((object)Empty))).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public bool Equals(JEnumerable other) { return object.Equals(_enumerable, other._enumerable); } public override bool Equals(object? obj) { if (obj is JEnumerable other) { return Equals(other); } return false; } public override int GetHashCode() { if (_enumerable == null) { return 0; } return _enumerable.GetHashCode(); } } internal class JObject : JContainer, IDictionary, ICollection>, IEnumerable>, IEnumerable, INotifyPropertyChanged, ICustomTypeDescriptor, INotifyPropertyChanging { private class JObjectDynamicProxy : DynamicProxy { public override bool TryGetMember(JObject instance, GetMemberBinder binder, out object? result) { result = instance[binder.Name]; return true; } public override bool TrySetMember(JObject instance, SetMemberBinder binder, object value) { JToken jToken = value as JToken; if (jToken == null) { jToken = new JValue(value); } instance[binder.Name] = jToken; return true; } public override IEnumerable GetDynamicMemberNames(JObject instance) { return from p in instance.Properties() select p.Name; } } private readonly JPropertyKeyedCollection _properties = new JPropertyKeyedCollection(); protected override IList ChildrenTokens => _properties; public override JTokenType Type => JTokenType.Object; public override JToken? this[object key] { get { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is string propertyName)) { throw new ArgumentException("Accessed JObject values with invalid key value: {0}. Object property name expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } return this[propertyName]; } set { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is string propertyName)) { throw new ArgumentException("Set JObject values with invalid key value: {0}. Object property name expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } this[propertyName] = value; } } public JToken? this[string propertyName] { get { ValidationUtils.ArgumentNotNull(propertyName, "propertyName"); return Property(propertyName, StringComparison.Ordinal)?.Value; } set { JProperty jProperty = Property(propertyName, StringComparison.Ordinal); if (jProperty != null) { jProperty.Value = value; return; } OnPropertyChanging(propertyName); Add(propertyName, value); OnPropertyChanged(propertyName); } } ICollection IDictionary.Keys => _properties.Keys; ICollection IDictionary.Values { get { throw new NotImplementedException(); } } bool ICollection>.IsReadOnly => false; public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangingEventHandler? PropertyChanging; public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { Task task2 = writer.WriteStartObjectAsync(cancellationToken); if (!task2.IsCompletedSuccessfully()) { return AwaitProperties(task2, 0, writer, cancellationToken, converters); } for (int j = 0; j < _properties.Count; j++) { task2 = _properties[j].WriteToAsync(writer, cancellationToken, converters); if (!task2.IsCompletedSuccessfully()) { return AwaitProperties(task2, j + 1, writer, cancellationToken, converters); } } return writer.WriteEndObjectAsync(cancellationToken); async Task AwaitProperties(Task task, int i, JsonWriter Writer, CancellationToken CancellationToken, JsonConverter[] Converters) { await task.ConfigureAwait(continueOnCapturedContext: false); while (i < _properties.Count) { await _properties[i].WriteToAsync(Writer, CancellationToken, Converters).ConfigureAwait(continueOnCapturedContext: false); i++; } await Writer.WriteEndObjectAsync(CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return LoadAsync(reader, null, cancellationToken); } public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (reader.TokenType == JsonToken.None && !(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader."); } await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (reader.TokenType != JsonToken.StartObject) { throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JObject o = new JObject(); o.SetLineInfo(reader as IJsonLineInfo, settings); await o.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return o; } public JObject() { } public JObject(JObject other) : base(other, null) { } internal JObject(JObject other, JsonCloneSettings? settings) : base(other, settings) { } public JObject(params object[] content) : this((object)content) { } public JObject(object content) { Add(content); } internal override bool DeepEquals(JToken node) { if (!(node is JObject jObject)) { return false; } return _properties.Compare(jObject._properties); } internal override int IndexOfItem(JToken? item) { if (item == null) { return -1; } return _properties.IndexOfReference(item); } internal override bool InsertItem(int index, JToken? item, bool skipParentCheck, bool copyAnnotations) { if (item != null && item.Type == JTokenType.Comment) { return false; } return base.InsertItem(index, item, skipParentCheck, copyAnnotations); } internal override void ValidateToken(JToken o, JToken? existing) { ValidationUtils.ArgumentNotNull(o, "o"); if (o.Type != JTokenType.Property) { throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType())); } JProperty jProperty = (JProperty)o; if (existing != null) { JProperty jProperty2 = (JProperty)existing; if (jProperty.Name == jProperty2.Name) { return; } } if (_properties.TryGetValue(jProperty.Name, out existing)) { throw new ArgumentException("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, jProperty.Name, GetType())); } } internal override void MergeItem(object content, JsonMergeSettings? settings) { if (!(content is JObject jObject)) { return; } foreach (KeyValuePair item in jObject) { JProperty jProperty = Property(item.Key, settings?.PropertyNameComparison ?? StringComparison.Ordinal); if (jProperty == null) { Add(item.Key, item.Value); } else { if (item.Value == null) { continue; } if (!(jProperty.Value is JContainer jContainer) || jContainer.Type != item.Value.Type) { if (!IsNull(item.Value) || (settings != null && settings.MergeNullValueHandling == MergeNullValueHandling.Merge)) { jProperty.Value = item.Value; } } else { jContainer.Merge(item.Value, settings); } } } } private static bool IsNull(JToken token) { if (token.Type == JTokenType.Null) { return true; } if (token is JValue jValue && jValue.Value == null) { return true; } return false; } internal void InternalPropertyChanged(JProperty childProperty) { OnPropertyChanged(childProperty.Name); if (_listChanged != null) { OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, IndexOfItem(childProperty))); } if (_collectionChanged != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, childProperty, childProperty, IndexOfItem(childProperty))); } } internal void InternalPropertyChanging(JProperty childProperty) { OnPropertyChanging(childProperty.Name); } internal override JToken CloneToken(JsonCloneSettings? settings) { return new JObject(this, settings); } public IEnumerable Properties() { return _properties.Cast(); } public JProperty? Property(string name) { return Property(name, StringComparison.Ordinal); } public JProperty? Property(string name, StringComparison comparison) { if (name == null) { return null; } if (_properties.TryGetValue(name, out JToken value)) { return (JProperty)value; } if (comparison != StringComparison.Ordinal) { for (int i = 0; i < _properties.Count; i++) { JProperty jProperty = (JProperty)_properties[i]; if (string.Equals(jProperty.Name, name, comparison)) { return jProperty; } } } return null; } public JEnumerable PropertyValues() { return new JEnumerable(from p in Properties() select p.Value); } public new static JObject Load(JsonReader reader) { return Load(reader, null); } public new static JObject Load(JsonReader reader, JsonLoadSettings? settings) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (reader.TokenType == JsonToken.None && !reader.Read()) { throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader."); } reader.MoveToContent(); if (reader.TokenType != JsonToken.StartObject) { throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JObject jObject = new JObject(); jObject.SetLineInfo(reader as IJsonLineInfo, settings); jObject.ReadTokenFrom(reader, settings); return jObject; } public new static JObject Parse(string json) { return Parse(json, null); } public new static JObject Parse(string json, JsonLoadSettings? settings) { using JsonReader jsonReader = new JsonTextReader(new StringReader(json)); JObject result = Load(jsonReader, settings); while (jsonReader.Read()) { } return result; } public new static JObject FromObject(object o) { return FromObject(o, JsonSerializer.CreateDefault()); } public new static JObject FromObject(object o, JsonSerializer jsonSerializer) { JToken jToken = JToken.FromObjectInternal(o, jsonSerializer); if (jToken.Type != JTokenType.Object) { throw new ArgumentException("Object serialized to {0}. JObject instance expected.".FormatWith(CultureInfo.InvariantCulture, jToken.Type)); } return (JObject)jToken; } public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { writer.WriteStartObject(); for (int i = 0; i < _properties.Count; i++) { _properties[i].WriteTo(writer, converters); } writer.WriteEndObject(); } public JToken? GetValue(string? propertyName) { return GetValue(propertyName, StringComparison.Ordinal); } public JToken? GetValue(string? propertyName, StringComparison comparison) { if (propertyName == null) { return null; } return Property(propertyName, comparison)?.Value; } public bool TryGetValue(string propertyName, StringComparison comparison, [NotNullWhen(true)] out JToken? value) { value = GetValue(propertyName, comparison); return value != null; } public void Add(string propertyName, JToken? value) { Add(new JProperty(propertyName, value)); } public bool ContainsKey(string propertyName) { ValidationUtils.ArgumentNotNull(propertyName, "propertyName"); return _properties.Contains(propertyName); } public bool Remove(string propertyName) { JProperty jProperty = Property(propertyName, StringComparison.Ordinal); if (jProperty == null) { return false; } jProperty.Remove(); return true; } public bool TryGetValue(string propertyName, [NotNullWhen(true)] out JToken? value) { JProperty jProperty = Property(propertyName, StringComparison.Ordinal); if (jProperty == null) { value = null; return false; } value = jProperty.Value; return true; } void ICollection>.Add(KeyValuePair item) { Add(new JProperty(item.Key, item.Value)); } void ICollection>.Clear() { RemoveAll(); } bool ICollection>.Contains(KeyValuePair item) { JProperty jProperty = Property(item.Key, StringComparison.Ordinal); if (jProperty == null) { return false; } return jProperty.Value == item.Value; } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0) { throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0."); } if (arrayIndex >= array.Length && arrayIndex != 0) { throw new ArgumentException("arrayIndex is equal to or greater than the length of array."); } if (base.Count > array.Length - arrayIndex) { throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array."); } int num = 0; foreach (JProperty property in _properties) { array[arrayIndex + num] = new KeyValuePair(property.Name, property.Value); num++; } } bool ICollection>.Remove(KeyValuePair item) { if (!((ICollection>)this).Contains(item)) { return false; } ((IDictionary)this).Remove(item.Key); return true; } internal override int GetDeepHashCode() { return ContentsHashCode(); } public IEnumerator> GetEnumerator() { foreach (JProperty property in _properties) { yield return new KeyValuePair(property.Name, property.Value); } } protected virtual void OnPropertyChanged(string propertyName) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected virtual void OnPropertyChanging(string propertyName) { this.PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName)); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { return ((ICustomTypeDescriptor)this).GetProperties((Attribute[]?)null); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[]? attributes) { PropertyDescriptor[] array = new PropertyDescriptor[base.Count]; int num = 0; using (IEnumerator> enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { array[num] = new JPropertyDescriptor(enumerator.Current.Key); num++; } } return new PropertyDescriptorCollection(array); } AttributeCollection ICustomTypeDescriptor.GetAttributes() { return AttributeCollection.Empty; } string? ICustomTypeDescriptor.GetClassName() { return null; } string? ICustomTypeDescriptor.GetComponentName() { return null; } TypeConverter ICustomTypeDescriptor.GetConverter() { return new TypeConverter(); } EventDescriptor? ICustomTypeDescriptor.GetDefaultEvent() { return null; } PropertyDescriptor? ICustomTypeDescriptor.GetDefaultProperty() { return null; } object? ICustomTypeDescriptor.GetEditor(Type editorBaseType) { return null; } EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[]? attributes) { return EventDescriptorCollection.Empty; } EventDescriptorCollection ICustomTypeDescriptor.GetEvents() { return EventDescriptorCollection.Empty; } object? ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor? pd) { if (pd is JPropertyDescriptor) { return this; } return null; } protected override DynamicMetaObject GetMetaObject(Expression parameter) { return new DynamicProxyMetaObject(parameter, this, new JObjectDynamicProxy()); } } internal class JProperty : JContainer { private class JPropertyList : IList, ICollection, IEnumerable, IEnumerable { internal JToken? _token; public int Count { get { if (_token == null) { return 0; } return 1; } } public bool IsReadOnly => false; public JToken this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _token; } set { if (index != 0) { throw new IndexOutOfRangeException(); } _token = value; } } public IEnumerator GetEnumerator() { if (_token != null) { yield return _token; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public void Add(JToken item) { _token = item; } public void Clear() { _token = null; } public bool Contains(JToken item) { return _token == item; } public void CopyTo(JToken[] array, int arrayIndex) { if (_token != null) { array[arrayIndex] = _token; } } public bool Remove(JToken item) { if (_token == item) { _token = null; return true; } return false; } public int IndexOf(JToken item) { if (_token != item) { return -1; } return 0; } public void Insert(int index, JToken item) { if (index == 0) { _token = item; } } public void RemoveAt(int index) { if (index == 0) { _token = null; } } } private readonly JPropertyList _content = new JPropertyList(); private readonly string _name; protected override IList ChildrenTokens => _content; public string Name { [DebuggerStepThrough] get { return _name; } } public new JToken Value { [DebuggerStepThrough] get { return _content._token; } set { CheckReentrancy(); JToken item = value ?? JValue.CreateNull(); if (_content._token == null) { InsertItem(0, item, skipParentCheck: false, copyAnnotations: true); } else { SetItem(0, item); } } } public override JTokenType Type { [DebuggerStepThrough] get { return JTokenType.Property; } } public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { Task task = writer.WritePropertyNameAsync(_name, cancellationToken); if (task.IsCompletedSuccessfully()) { return WriteValueAsync(writer, cancellationToken, converters); } return WriteToAsync(task, writer, cancellationToken, converters); } private async Task WriteToAsync(Task task, JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteValueAsync(writer, cancellationToken, converters).ConfigureAwait(continueOnCapturedContext: false); } private Task WriteValueAsync(JsonWriter writer, CancellationToken cancellationToken, JsonConverter[] converters) { JToken value = Value; if (value == null) { return writer.WriteNullAsync(cancellationToken); } return value.WriteToAsync(writer, cancellationToken, converters); } public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return LoadAsync(reader, null, cancellationToken); } public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { if (reader.TokenType == JsonToken.None && !(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader."); } await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (reader.TokenType != JsonToken.PropertyName) { throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JProperty p = new JProperty((string)reader.Value); p.SetLineInfo(reader as IJsonLineInfo, settings); await p.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return p; } public JProperty(JProperty other) : base(other, null) { _name = other.Name; } internal JProperty(JProperty other, JsonCloneSettings? settings) : base(other, settings) { _name = other.Name; } internal override JToken GetItem(int index) { if (index != 0) { throw new ArgumentOutOfRangeException(); } return Value; } internal override void SetItem(int index, JToken? item) { if (index != 0) { throw new ArgumentOutOfRangeException(); } if (!JContainer.IsTokenUnchanged(Value, item)) { ((JObject)base.Parent)?.InternalPropertyChanging(this); base.SetItem(0, item); ((JObject)base.Parent)?.InternalPropertyChanged(this); } } internal override bool RemoveItem(JToken? item) { throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } internal override void RemoveItemAt(int index) { throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } internal override int IndexOfItem(JToken? item) { if (item == null) { return -1; } return _content.IndexOf(item); } internal override bool InsertItem(int index, JToken? item, bool skipParentCheck, bool copyAnnotations) { if (item != null && item.Type == JTokenType.Comment) { return false; } if (Value != null) { throw new JsonException("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } return base.InsertItem(0, item, skipParentCheck: false, copyAnnotations); } internal override bool ContainsItem(JToken? item) { return Value == item; } internal override void MergeItem(object content, JsonMergeSettings? settings) { JToken jToken = (content as JProperty)?.Value; if (jToken != null && jToken.Type != JTokenType.Null) { Value = jToken; } } internal override void ClearItems() { throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } internal override bool DeepEquals(JToken node) { if (node is JProperty jProperty && _name == jProperty.Name) { return ContentsEqual(jProperty); } return false; } internal override JToken CloneToken(JsonCloneSettings? settings) { return new JProperty(this, settings); } internal JProperty(string name) { ValidationUtils.ArgumentNotNull(name, "name"); _name = name; } public JProperty(string name, params object[] content) : this(name, (object?)content) { } public JProperty(string name, object? content) { ValidationUtils.ArgumentNotNull(name, "name"); _name = name; Value = (IsMultiContent(content) ? new JArray(content) : JContainer.CreateFromContent(content)); } public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { writer.WritePropertyName(_name); JToken value = Value; if (value != null) { value.WriteTo(writer, converters); } else { writer.WriteNull(); } } internal override int GetDeepHashCode() { return _name.GetHashCode(StringComparison.Ordinal) ^ (Value?.GetDeepHashCode() ?? 0); } public new static JProperty Load(JsonReader reader) { return Load(reader, null); } public new static JProperty Load(JsonReader reader, JsonLoadSettings? settings) { if (reader.TokenType == JsonToken.None && !reader.Read()) { throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader."); } reader.MoveToContent(); if (reader.TokenType != JsonToken.PropertyName) { throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JProperty jProperty = new JProperty((string)reader.Value); jProperty.SetLineInfo(reader as IJsonLineInfo, settings); jProperty.ReadTokenFrom(reader, settings); return jProperty; } } internal class JPropertyDescriptor : PropertyDescriptor { public override Type ComponentType => typeof(JObject); public override bool IsReadOnly => false; public override Type PropertyType => typeof(object); protected override int NameHashCode => base.NameHashCode; public JPropertyDescriptor(string name) : base(name, null) { } private static JObject CastInstance(object instance) { return (JObject)instance; } public override bool CanResetValue(object component) { return false; } public override object? GetValue(object? component) { return (component as JObject)?[Name]; } public override void ResetValue(object component) { } public override void SetValue(object? component, object? value) { if (component is JObject jObject) { JToken value2 = (value as JToken) ?? new JValue(value); jObject[Name] = value2; } } public override bool ShouldSerializeValue(object component) { return false; } } internal class JPropertyKeyedCollection : Collection { private static readonly IEqualityComparer Comparer = StringComparer.Ordinal; private Dictionary? _dictionary; public JToken this[string key] { get { if (key == null) { throw new ArgumentNullException("key"); } if (_dictionary != null) { return _dictionary[key]; } throw new KeyNotFoundException(); } } public ICollection Keys { get { EnsureDictionary(); return _dictionary.Keys; } } public ICollection Values { get { EnsureDictionary(); return _dictionary.Values; } } public JPropertyKeyedCollection() : base((IList)new List()) { } private void AddKey(string key, JToken item) { EnsureDictionary(); _dictionary[key] = item; } protected void ChangeItemKey(JToken item, string newKey) { if (!ContainsItem(item)) { throw new ArgumentException("The specified item does not exist in this KeyedCollection."); } string keyForItem = GetKeyForItem(item); if (!Comparer.Equals(keyForItem, newKey)) { if (newKey != null) { AddKey(newKey, item); } if (keyForItem != null) { RemoveKey(keyForItem); } } } protected override void ClearItems() { base.ClearItems(); _dictionary?.Clear(); } public bool Contains(string key) { if (key == null) { throw new ArgumentNullException("key"); } if (_dictionary != null) { return _dictionary.ContainsKey(key); } return false; } private bool ContainsItem(JToken item) { if (_dictionary == null) { return false; } string keyForItem = GetKeyForItem(item); JToken value; return _dictionary.TryGetValue(keyForItem, out value); } private void EnsureDictionary() { if (_dictionary == null) { _dictionary = new Dictionary(Comparer); } } private string GetKeyForItem(JToken item) { return ((JProperty)item).Name; } protected override void InsertItem(int index, JToken item) { AddKey(GetKeyForItem(item), item); base.InsertItem(index, item); } public bool Remove(string key) { if (key == null) { throw new ArgumentNullException("key"); } if (_dictionary != null) { if (_dictionary.TryGetValue(key, out JToken value)) { return Remove(value); } return false; } return false; } protected override void RemoveItem(int index) { string keyForItem = GetKeyForItem(base.Items[index]); RemoveKey(keyForItem); base.RemoveItem(index); } private void RemoveKey(string key) { _dictionary?.Remove(key); } protected override void SetItem(int index, JToken item) { string keyForItem = GetKeyForItem(item); string keyForItem2 = GetKeyForItem(base.Items[index]); if (Comparer.Equals(keyForItem2, keyForItem)) { if (_dictionary != null) { _dictionary[keyForItem] = item; } } else { AddKey(keyForItem, item); if (keyForItem2 != null) { RemoveKey(keyForItem2); } } base.SetItem(index, item); } public bool TryGetValue(string key, [NotNullWhen(true)] out JToken? value) { if (_dictionary == null) { value = null; return false; } return _dictionary.TryGetValue(key, out value); } public int IndexOfReference(JToken t) { return ((List)base.Items).IndexOfReference(t); } public bool Compare(JPropertyKeyedCollection other) { if (this == other) { return true; } Dictionary dictionary = _dictionary; Dictionary dictionary2 = other._dictionary; if (dictionary == null && dictionary2 == null) { return true; } if (dictionary == null) { return dictionary2.Count == 0; } if (dictionary2 == null) { return dictionary.Count == 0; } if (dictionary.Count != dictionary2.Count) { return false; } foreach (KeyValuePair item in dictionary) { if (!dictionary2.TryGetValue(item.Key, out var value)) { return false; } JProperty jProperty = (JProperty)item.Value; JProperty jProperty2 = (JProperty)value; if (jProperty.Value == null) { return jProperty2.Value == null; } if (!jProperty.Value.DeepEquals(jProperty2.Value)) { return false; } } return true; } } internal class JRaw : JValue { public static async Task CreateAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { using StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); using JsonTextWriter jsonWriter = new JsonTextWriter(sw); await jsonWriter.WriteTokenSyncReadingAsync(reader, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return new JRaw(sw.ToString()); } public JRaw(JRaw other) : base(other, null) { } internal JRaw(JRaw other, JsonCloneSettings? settings) : base(other, settings) { } public JRaw(object? rawJson) : base(rawJson, JTokenType.Raw) { } public static JRaw Create(JsonReader reader) { using StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); using JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter); jsonTextWriter.WriteToken(reader); return new JRaw(stringWriter.ToString()); } internal override JToken CloneToken(JsonCloneSettings? settings) { return new JRaw(this, settings); } } internal class JsonCloneSettings { internal static readonly JsonCloneSettings SkipCopyAnnotations = new JsonCloneSettings { CopyAnnotations = false }; public bool CopyAnnotations { get; set; } public JsonCloneSettings() { CopyAnnotations = true; } } internal class JsonLoadSettings { private CommentHandling _commentHandling; private LineInfoHandling _lineInfoHandling; private DuplicatePropertyNameHandling _duplicatePropertyNameHandling; public CommentHandling CommentHandling { get { return _commentHandling; } set { if (value < CommentHandling.Ignore || value > CommentHandling.Load) { throw new ArgumentOutOfRangeException("value"); } _commentHandling = value; } } public LineInfoHandling LineInfoHandling { get { return _lineInfoHandling; } set { if (value < LineInfoHandling.Ignore || value > LineInfoHandling.Load) { throw new ArgumentOutOfRangeException("value"); } _lineInfoHandling = value; } } public DuplicatePropertyNameHandling DuplicatePropertyNameHandling { get { return _duplicatePropertyNameHandling; } set { if (value < DuplicatePropertyNameHandling.Replace || value > DuplicatePropertyNameHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _duplicatePropertyNameHandling = value; } } public JsonLoadSettings() { _lineInfoHandling = LineInfoHandling.Load; _commentHandling = CommentHandling.Ignore; _duplicatePropertyNameHandling = DuplicatePropertyNameHandling.Replace; } } internal class JsonMergeSettings { private MergeArrayHandling _mergeArrayHandling; private MergeNullValueHandling _mergeNullValueHandling; private StringComparison _propertyNameComparison; public MergeArrayHandling MergeArrayHandling { get { return _mergeArrayHandling; } set { if (value < MergeArrayHandling.Concat || value > MergeArrayHandling.Merge) { throw new ArgumentOutOfRangeException("value"); } _mergeArrayHandling = value; } } public MergeNullValueHandling MergeNullValueHandling { get { return _mergeNullValueHandling; } set { if (value < MergeNullValueHandling.Ignore || value > MergeNullValueHandling.Merge) { throw new ArgumentOutOfRangeException("value"); } _mergeNullValueHandling = value; } } public StringComparison PropertyNameComparison { get { return _propertyNameComparison; } set { if (value < StringComparison.CurrentCulture || value > StringComparison.OrdinalIgnoreCase) { throw new ArgumentOutOfRangeException("value"); } _propertyNameComparison = value; } } public JsonMergeSettings() { _propertyNameComparison = StringComparison.Ordinal; } } internal class JsonSelectSettings { public TimeSpan? RegexMatchTimeout { get; set; } public bool ErrorWhenNoMatch { get; set; } } internal abstract class JToken : IJEnumerable, IEnumerable, IEnumerable, IJsonLineInfo, ICloneable, IDynamicMetaObjectProvider { private class LineInfoAnnotation { internal readonly int LineNumber; internal readonly int LinePosition; public LineInfoAnnotation(int lineNumber, int linePosition) { LineNumber = lineNumber; LinePosition = linePosition; } } private static JTokenEqualityComparer? _equalityComparer; private JContainer? _parent; private JToken? _previous; private JToken? _next; private object? _annotations; private static readonly JTokenType[] BooleanTypes = new JTokenType[6] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean }; private static readonly JTokenType[] NumberTypes = new JTokenType[6] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean }; private static readonly JTokenType[] BigIntegerTypes = new JTokenType[7] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes }; private static readonly JTokenType[] StringTypes = new JTokenType[11] { JTokenType.Date, JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes, JTokenType.Guid, JTokenType.TimeSpan, JTokenType.Uri }; private static readonly JTokenType[] GuidTypes = new JTokenType[5] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Guid, JTokenType.Bytes }; private static readonly JTokenType[] TimeSpanTypes = new JTokenType[4] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.TimeSpan }; private static readonly JTokenType[] UriTypes = new JTokenType[4] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Uri }; private static readonly JTokenType[] CharTypes = new JTokenType[5] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw }; private static readonly JTokenType[] DateTimeTypes = new JTokenType[4] { JTokenType.Date, JTokenType.String, JTokenType.Comment, JTokenType.Raw }; private static readonly JTokenType[] BytesTypes = new JTokenType[5] { JTokenType.Bytes, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Integer }; public static JTokenEqualityComparer EqualityComparer { get { if (_equalityComparer == null) { _equalityComparer = new JTokenEqualityComparer(); } return _equalityComparer; } } public JContainer? Parent { [DebuggerStepThrough] get { return _parent; } internal set { _parent = value; } } public JToken Root { get { JContainer parent = Parent; if (parent == null) { return this; } while (parent.Parent != null) { parent = parent.Parent; } return parent; } } public abstract JTokenType Type { get; } public abstract bool HasValues { get; } public JToken? Next { get { return _next; } internal set { _next = value; } } public JToken? Previous { get { return _previous; } internal set { _previous = value; } } public string Path { get { if (Parent == null) { return string.Empty; } List list = new List(); JToken jToken = null; for (JToken jToken2 = this; jToken2 != null; jToken2 = jToken2.Parent) { switch (jToken2.Type) { case JTokenType.Property: { JProperty jProperty = (JProperty)jToken2; list.Add(new JsonPosition(JsonContainerType.Object) { PropertyName = jProperty.Name }); break; } case JTokenType.Array: case JTokenType.Constructor: if (jToken != null) { int position = ((IList)jToken2).IndexOf(jToken); list.Add(new JsonPosition(JsonContainerType.Array) { Position = position }); } break; } jToken = jToken2; } list.FastReverse(); return JsonPosition.BuildPath(list, null); } } public virtual JToken? this[object key] { get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } set { throw new InvalidOperationException("Cannot set child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } } public virtual JToken? First { get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } } public virtual JToken? Last { get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } } IJEnumerable IJEnumerable.this[object key] => this[key]; int IJsonLineInfo.LineNumber => Annotation()?.LineNumber ?? 0; int IJsonLineInfo.LinePosition => Annotation()?.LinePosition ?? 0; public virtual Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { throw new NotImplementedException(); } public Task WriteToAsync(JsonWriter writer, params JsonConverter[] converters) { return WriteToAsync(writer, default(CancellationToken), converters); } public static Task ReadFromAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return ReadFromAsync(reader, null, cancellationToken); } public static async Task ReadFromAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (reader.TokenType == JsonToken.None && !(await ((settings != null && settings.CommentHandling == CommentHandling.Ignore) ? reader.ReadAndMoveToContentAsync(cancellationToken) : reader.ReadAsync(cancellationToken)).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader."); } IJsonLineInfo lineInfo = reader as IJsonLineInfo; switch (reader.TokenType) { case JsonToken.StartObject: return await JObject.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case JsonToken.StartArray: return await JArray.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case JsonToken.StartConstructor: return await JConstructor.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case JsonToken.PropertyName: return await JProperty.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { JValue jValue4 = new JValue(reader.Value); jValue4.SetLineInfo(lineInfo, settings); return jValue4; } case JsonToken.Comment: { JValue jValue3 = JValue.CreateComment(reader.Value?.ToString()); jValue3.SetLineInfo(lineInfo, settings); return jValue3; } case JsonToken.Null: { JValue jValue2 = JValue.CreateNull(); jValue2.SetLineInfo(lineInfo, settings); return jValue2; } case JsonToken.Undefined: { JValue jValue = JValue.CreateUndefined(); jValue.SetLineInfo(lineInfo, settings); return jValue; } default: throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } public static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return LoadAsync(reader, null, cancellationToken); } public static Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { return ReadFromAsync(reader, settings, cancellationToken); } internal abstract JToken CloneToken(JsonCloneSettings? settings); internal abstract bool DeepEquals(JToken node); public static bool DeepEquals(JToken? t1, JToken? t2) { if (t1 != t2) { if (t1 != null && t2 != null) { return t1.DeepEquals(t2); } return false; } return true; } internal JToken() { } public void AddAfterSelf(object? content) { if (_parent == null) { throw new InvalidOperationException("The parent is missing."); } int num = _parent.IndexOfItem(this); _parent.TryAddInternal(num + 1, content, skipParentCheck: false, copyAnnotations: true); } public void AddBeforeSelf(object? content) { if (_parent == null) { throw new InvalidOperationException("The parent is missing."); } int index = _parent.IndexOfItem(this); _parent.TryAddInternal(index, content, skipParentCheck: false, copyAnnotations: true); } public IEnumerable Ancestors() { return GetAncestors(self: false); } public IEnumerable AncestorsAndSelf() { return GetAncestors(self: true); } internal IEnumerable GetAncestors(bool self) { for (JToken current = (self ? this : Parent); current != null; current = current.Parent) { yield return current; } } public IEnumerable AfterSelf() { if (Parent != null) { for (JToken o = Next; o != null; o = o.Next) { yield return o; } } } public IEnumerable BeforeSelf() { if (Parent != null) { JToken o = Parent.First; while (o != this && o != null) { yield return o; o = o.Next; } } } public virtual T? Value(object key) { JToken jToken = this[key]; if (jToken != null) { return jToken.Convert(); } return default(T); } public virtual JEnumerable Children() { return JEnumerable.Empty; } public JEnumerable Children() where T : JToken { return new JEnumerable(Children().OfType()); } public virtual IEnumerable Values() { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } public void Remove() { if (_parent == null) { throw new InvalidOperationException("The parent is missing."); } _parent.RemoveItem(this); } public void Replace(JToken value) { if (_parent == null) { throw new InvalidOperationException("The parent is missing."); } _parent.ReplaceItem(this, value); } public abstract void WriteTo(JsonWriter writer, params JsonConverter[] converters); public override string ToString() { return ToString(Formatting.Indented); } public string ToString(Formatting formatting, params JsonConverter[] converters) { using StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter); jsonTextWriter.Formatting = formatting; WriteTo(jsonTextWriter, converters); return stringWriter.ToString(); } private static JValue? EnsureValue(JToken value) { if (value == null) { throw new ArgumentNullException("value"); } if (value is JProperty jProperty) { value = jProperty.Value; } return value as JValue; } private static string GetType(JToken token) { ValidationUtils.ArgumentNotNull(token, "token"); if (token is JProperty jProperty) { token = jProperty.Value; } return token.Type.ToString(); } private static bool ValidateToken(JToken o, JTokenType[] validTypes, bool nullable) { if (Array.IndexOf(validTypes, o.Type) == -1) { if (nullable) { if (o.Type != JTokenType.Null) { return o.Type == JTokenType.Undefined; } return true; } return false; } return true; } public static explicit operator bool(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, BooleanTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return Convert.ToBoolean((int)bigInteger); } return Convert.ToBoolean(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator DateTimeOffset(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, DateTimeTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } object value2 = jValue.Value; if (value2 is DateTimeOffset) { return (DateTimeOffset)value2; } if (jValue.Value is string input) { return DateTimeOffset.Parse(input, CultureInfo.InvariantCulture); } return new DateTimeOffset(Convert.ToDateTime(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator bool?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, BooleanTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return Convert.ToBoolean((int)bigInteger); } if (jValue.Value == null) { return null; } return Convert.ToBoolean(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator long(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (long)bigInteger; } return Convert.ToInt64(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator DateTime?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, DateTimeTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is DateTimeOffset dateTimeOffset) { return dateTimeOffset.DateTime; } if (jValue.Value == null) { return null; } return Convert.ToDateTime(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator DateTimeOffset?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, DateTimeTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } object value2 = jValue.Value; if (value2 is DateTimeOffset) { return (DateTimeOffset)value2; } if (jValue.Value is string input) { return DateTimeOffset.Parse(input, CultureInfo.InvariantCulture); } return new DateTimeOffset(Convert.ToDateTime(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator decimal?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (decimal)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToDecimal(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator double?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (double)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToDouble(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator char?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, CharTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (char)(ushort)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToChar(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator int(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (int)bigInteger; } return Convert.ToInt32(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator short(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (short)bigInteger; } return Convert.ToInt16(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator ushort(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (ushort)bigInteger; } return Convert.ToUInt16(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator char(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, CharTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (char)(ushort)bigInteger; } return Convert.ToChar(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator byte(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (byte)bigInteger; } return Convert.ToByte(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator sbyte(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (sbyte)bigInteger; } return Convert.ToSByte(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator int?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (int)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToInt32(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator short?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (short)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToInt16(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator ushort?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (ushort)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToUInt16(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator byte?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (byte)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToByte(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator sbyte?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (sbyte)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToSByte(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator DateTime(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, DateTimeTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is DateTimeOffset dateTimeOffset) { return dateTimeOffset.DateTime; } return Convert.ToDateTime(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator long?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (long)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToInt64(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator float?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (float)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToSingle(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator decimal(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (decimal)bigInteger; } return Convert.ToDecimal(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator uint?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (uint)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToUInt32(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator ulong?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (ulong)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToUInt64(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator double(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (double)bigInteger; } return Convert.ToDouble(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator float(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (float)bigInteger; } return Convert.ToSingle(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator string?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, StringTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to String.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } if (jValue.Value is byte[] inArray) { return Convert.ToBase64String(inArray); } if (jValue.Value is BigInteger bigInteger) { return bigInteger.ToString(CultureInfo.InvariantCulture); } return Convert.ToString(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator uint(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (uint)bigInteger; } return Convert.ToUInt32(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator ulong(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (ulong)bigInteger; } return Convert.ToUInt64(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator byte[]?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, BytesTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is string) { return Convert.FromBase64String(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } if (jValue.Value is BigInteger bigInteger) { return bigInteger.ToByteArray(); } if (jValue.Value is byte[] result) { return result; } throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } public static explicit operator Guid(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, GuidTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is byte[] b) { return new Guid(b); } object value2 = jValue.Value; if (value2 is Guid) { return (Guid)value2; } return new Guid(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator Guid?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, GuidTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } if (jValue.Value is byte[] b) { return new Guid(b); } return (jValue.Value is Guid guid) ? guid : new Guid(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator TimeSpan(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, TimeSpanTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } object value2 = jValue.Value; if (value2 is TimeSpan) { return (TimeSpan)value2; } return ConvertUtils.ParseTimeSpan(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator TimeSpan?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, TimeSpanTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } return (jValue.Value is TimeSpan timeSpan) ? timeSpan : ConvertUtils.ParseTimeSpan(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator Uri?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, UriTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Uri.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } if (!(jValue.Value is Uri result)) { return new Uri(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } return result; } private static BigInteger ToBigInteger(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, BigIntegerTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } return ConvertUtils.ToBigInteger(jValue.Value); } private static BigInteger? ToBigIntegerNullable(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, BigIntegerTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } return ConvertUtils.ToBigInteger(jValue.Value); } public static implicit operator JToken(bool value) { return new JValue(value); } public static implicit operator JToken(DateTimeOffset value) { return new JValue(value); } public static implicit operator JToken(byte value) { return new JValue(value); } public static implicit operator JToken(byte? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(sbyte value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(sbyte? value) { return new JValue(value); } public static implicit operator JToken(bool? value) { return new JValue(value); } public static implicit operator JToken(long value) { return new JValue(value); } public static implicit operator JToken(DateTime? value) { return new JValue(value); } public static implicit operator JToken(DateTimeOffset? value) { return new JValue(value); } public static implicit operator JToken(decimal? value) { return new JValue(value); } public static implicit operator JToken(double? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(short value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(ushort value) { return new JValue(value); } public static implicit operator JToken(int value) { return new JValue(value); } public static implicit operator JToken(int? value) { return new JValue(value); } public static implicit operator JToken(DateTime value) { return new JValue(value); } public static implicit operator JToken(long? value) { return new JValue(value); } public static implicit operator JToken(float? value) { return new JValue(value); } public static implicit operator JToken(decimal value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(short? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(ushort? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(uint? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(ulong? value) { return new JValue(value); } public static implicit operator JToken(double value) { return new JValue(value); } public static implicit operator JToken(float value) { return new JValue(value); } public static implicit operator JToken(string? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(uint value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(ulong value) { return new JValue(value); } public static implicit operator JToken(byte[] value) { return new JValue(value); } public static implicit operator JToken(Uri? value) { return new JValue(value); } public static implicit operator JToken(TimeSpan value) { return new JValue(value); } public static implicit operator JToken(TimeSpan? value) { return new JValue(value); } public static implicit operator JToken(Guid value) { return new JValue(value); } public static implicit operator JToken(Guid? value) { return new JValue(value); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return Children().GetEnumerator(); } internal abstract int GetDeepHashCode(); public JsonReader CreateReader() { return new JTokenReader(this); } internal static JToken FromObjectInternal(object o, JsonSerializer jsonSerializer) { ValidationUtils.ArgumentNotNull(o, "o"); ValidationUtils.ArgumentNotNull(jsonSerializer, "jsonSerializer"); using JTokenWriter jTokenWriter = new JTokenWriter(); jsonSerializer.Serialize(jTokenWriter, o); return jTokenWriter.Token; } public static JToken FromObject(object o) { return FromObjectInternal(o, JsonSerializer.CreateDefault()); } public static JToken FromObject(object o, JsonSerializer jsonSerializer) { return FromObjectInternal(o, jsonSerializer); } public T? ToObject() { return (T)ToObject(typeof(T)); } public object? ToObject(Type objectType) { if (JsonConvert.DefaultSettings == null) { bool isEnum; PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(objectType, out isEnum); if (isEnum) { if (Type == JTokenType.String) { try { return ToObject(objectType, JsonSerializer.CreateDefault()); } catch (Exception innerException) { Type type = (objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType)); throw new ArgumentException("Could not convert '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, (string?)this, type.Name), innerException); } } if (Type == JTokenType.Integer) { return Enum.ToObject(objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType), ((JValue)this).Value); } } switch (typeCode) { case PrimitiveTypeCode.BooleanNullable: return (bool?)this; case PrimitiveTypeCode.Boolean: return (bool)this; case PrimitiveTypeCode.CharNullable: return (char?)this; case PrimitiveTypeCode.Char: return (char)this; case PrimitiveTypeCode.SByte: return (sbyte)this; case PrimitiveTypeCode.SByteNullable: return (sbyte?)this; case PrimitiveTypeCode.ByteNullable: return (byte?)this; case PrimitiveTypeCode.Byte: return (byte)this; case PrimitiveTypeCode.Int16Nullable: return (short?)this; case PrimitiveTypeCode.Int16: return (short)this; case PrimitiveTypeCode.UInt16Nullable: return (ushort?)this; case PrimitiveTypeCode.UInt16: return (ushort)this; case PrimitiveTypeCode.Int32Nullable: return (int?)this; case PrimitiveTypeCode.Int32: return (int)this; case PrimitiveTypeCode.UInt32Nullable: return (uint?)this; case PrimitiveTypeCode.UInt32: return (uint)this; case PrimitiveTypeCode.Int64Nullable: return (long?)this; case PrimitiveTypeCode.Int64: return (long)this; case PrimitiveTypeCode.UInt64Nullable: return (ulong?)this; case PrimitiveTypeCode.UInt64: return (ulong)this; case PrimitiveTypeCode.SingleNullable: return (float?)this; case PrimitiveTypeCode.Single: return (float)this; case PrimitiveTypeCode.DoubleNullable: return (double?)this; case PrimitiveTypeCode.Double: return (double)this; case PrimitiveTypeCode.DecimalNullable: return (decimal?)this; case PrimitiveTypeCode.Decimal: return (decimal)this; case PrimitiveTypeCode.DateTimeNullable: return (DateTime?)this; case PrimitiveTypeCode.DateTime: return (DateTime)this; case PrimitiveTypeCode.DateTimeOffsetNullable: return (DateTimeOffset?)this; case PrimitiveTypeCode.DateTimeOffset: return (DateTimeOffset)this; case PrimitiveTypeCode.String: return (string?)this; case PrimitiveTypeCode.GuidNullable: return (Guid?)this; case PrimitiveTypeCode.Guid: return (Guid)this; case PrimitiveTypeCode.Uri: return (Uri?)this; case PrimitiveTypeCode.TimeSpanNullable: return (TimeSpan?)this; case PrimitiveTypeCode.TimeSpan: return (TimeSpan)this; case PrimitiveTypeCode.BigIntegerNullable: return ToBigIntegerNullable(this); case PrimitiveTypeCode.BigInteger: return ToBigInteger(this); } } return ToObject(objectType, JsonSerializer.CreateDefault()); } public T? ToObject(JsonSerializer jsonSerializer) { return (T)ToObject(typeof(T), jsonSerializer); } public object? ToObject(Type? objectType, JsonSerializer jsonSerializer) { ValidationUtils.ArgumentNotNull(jsonSerializer, "jsonSerializer"); using JTokenReader reader = new JTokenReader(this); if (jsonSerializer is JsonSerializerProxy jsonSerializerProxy) { jsonSerializerProxy._serializer.SetupReader(reader, out CultureInfo _, out DateTimeZoneHandling? _, out DateParseHandling? _, out FloatParseHandling? _, out int? _, out string _); } return jsonSerializer.Deserialize(reader, objectType); } public static JToken ReadFrom(JsonReader reader) { return ReadFrom(reader, null); } public static JToken ReadFrom(JsonReader reader, JsonLoadSettings? settings) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (!((reader.TokenType == JsonToken.None) ? ((settings != null && settings.CommentHandling == CommentHandling.Ignore) ? reader.ReadAndMoveToContent() : reader.Read()) : (reader.TokenType != JsonToken.Comment || settings == null || settings.CommentHandling != 0 || reader.ReadAndMoveToContent()))) { throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader."); } IJsonLineInfo lineInfo = reader as IJsonLineInfo; switch (reader.TokenType) { case JsonToken.StartObject: return JObject.Load(reader, settings); case JsonToken.StartArray: return JArray.Load(reader, settings); case JsonToken.StartConstructor: return JConstructor.Load(reader, settings); case JsonToken.PropertyName: return JProperty.Load(reader, settings); case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { JValue jValue4 = new JValue(reader.Value); jValue4.SetLineInfo(lineInfo, settings); return jValue4; } case JsonToken.Comment: { JValue jValue3 = JValue.CreateComment(reader.Value.ToString()); jValue3.SetLineInfo(lineInfo, settings); return jValue3; } case JsonToken.Null: { JValue jValue2 = JValue.CreateNull(); jValue2.SetLineInfo(lineInfo, settings); return jValue2; } case JsonToken.Undefined: { JValue jValue = JValue.CreateUndefined(); jValue.SetLineInfo(lineInfo, settings); return jValue; } default: throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } public static JToken Parse(string json) { return Parse(json, null); } public static JToken Parse(string json, JsonLoadSettings? settings) { using JsonReader jsonReader = new JsonTextReader(new StringReader(json)); JToken result = Load(jsonReader, settings); while (jsonReader.Read()) { } return result; } public static JToken Load(JsonReader reader, JsonLoadSettings? settings) { return ReadFrom(reader, settings); } public static JToken Load(JsonReader reader) { return Load(reader, null); } internal void SetLineInfo(IJsonLineInfo? lineInfo, JsonLoadSettings? settings) { if ((settings == null || settings.LineInfoHandling == LineInfoHandling.Load) && lineInfo != null && lineInfo.HasLineInfo()) { SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition); } } internal void SetLineInfo(int lineNumber, int linePosition) { AddAnnotation(new LineInfoAnnotation(lineNumber, linePosition)); } bool IJsonLineInfo.HasLineInfo() { return Annotation() != null; } public JToken? SelectToken(string path) { return SelectToken(path, null); } public JToken? SelectToken(string path, bool errorWhenNoMatch) { JsonSelectSettings settings = (errorWhenNoMatch ? new JsonSelectSettings { ErrorWhenNoMatch = true } : null); return SelectToken(path, settings); } public JToken? SelectToken(string path, JsonSelectSettings? settings) { JPath jPath = new JPath(path); JToken jToken = null; foreach (JToken item in jPath.Evaluate(this, this, settings)) { if (jToken != null) { throw new JsonException("Path returned multiple tokens."); } jToken = item; } return jToken; } public IEnumerable SelectTokens(string path) { return SelectTokens(path, null); } public IEnumerable SelectTokens(string path, bool errorWhenNoMatch) { JsonSelectSettings settings = (errorWhenNoMatch ? new JsonSelectSettings { ErrorWhenNoMatch = true } : null); return SelectTokens(path, settings); } public IEnumerable SelectTokens(string path, JsonSelectSettings? settings) { return new JPath(path).Evaluate(this, this, settings); } protected virtual DynamicMetaObject GetMetaObject(Expression parameter) { return new DynamicProxyMetaObject(parameter, this, new DynamicProxy()); } DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) { return GetMetaObject(parameter); } object ICloneable.Clone() { return DeepClone(); } public JToken DeepClone() { return CloneToken(null); } public JToken DeepClone(JsonCloneSettings settings) { return CloneToken(settings); } public void AddAnnotation(object annotation) { if (annotation == null) { throw new ArgumentNullException("annotation"); } if (_annotations == null) { _annotations = ((!(annotation is object[])) ? annotation : new object[1] { annotation }); return; } object[] array = _annotations as object[]; if (array == null) { _annotations = new object[2] { _annotations, annotation }; return; } int i; for (i = 0; i < array.Length && array[i] != null; i++) { } if (i == array.Length) { Array.Resize(ref array, i * 2); _annotations = array; } array[i] = annotation; } public T? Annotation() where T : class { if (_annotations != null) { if (!(_annotations is object[] array)) { return _annotations as T; } foreach (object obj in array) { if (obj == null) { break; } if (obj is T result) { return result; } } } return null; } public object? Annotation(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (_annotations != null) { if (!(_annotations is object[] array)) { if (type.IsInstanceOfType(_annotations)) { return _annotations; } } else { foreach (object obj in array) { if (obj == null) { break; } if (type.IsInstanceOfType(obj)) { return obj; } } } } return null; } public IEnumerable Annotations() where T : class { if (_annotations == null) { yield break; } object annotations2 = _annotations; object[] annotations = annotations2 as object[]; if (annotations != null) { foreach (object obj in annotations) { if (obj != null) { if (obj is T val) { yield return val; } continue; } break; } } else if (_annotations is T val2) { yield return val2; } } public IEnumerable Annotations(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (_annotations == null) { yield break; } object annotations2 = _annotations; object[] annotations = annotations2 as object[]; if (annotations != null) { foreach (object obj in annotations) { if (obj != null) { if (type.IsInstanceOfType(obj)) { yield return obj; } continue; } break; } } else if (type.IsInstanceOfType(_annotations)) { yield return _annotations; } } public void RemoveAnnotations() where T : class { if (_annotations == null) { return; } if (!(_annotations is object[] array)) { if (_annotations is T) { _annotations = null; } return; } int i = 0; int num = 0; for (; i < array.Length; i++) { object obj = array[i]; if (obj == null) { break; } if (!(obj is T)) { array[num++] = obj; } } if (num != 0) { while (num < i) { array[num++] = null; } } else { _annotations = null; } } public void RemoveAnnotations(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (_annotations == null) { return; } if (!(_annotations is object[] array)) { if (type.IsInstanceOfType(_annotations)) { _annotations = null; } return; } int i = 0; int num = 0; for (; i < array.Length; i++) { object obj = array[i]; if (obj == null) { break; } if (!type.IsInstanceOfType(obj)) { array[num++] = obj; } } if (num != 0) { while (num < i) { array[num++] = null; } } else { _annotations = null; } } internal void CopyAnnotations(JToken target, JToken source) { if (source._annotations is object[] source2) { target._annotations = source2.ToArray(); } else { target._annotations = source._annotations; } } } internal class JTokenEqualityComparer : IEqualityComparer { public bool Equals(JToken? x, JToken? y) { return JToken.DeepEquals(x, y); } public int GetHashCode(JToken obj) { return obj?.GetDeepHashCode() ?? 0; } } internal class JTokenReader : JsonReader, IJsonLineInfo { private readonly JToken _root; private string? _initialPath; private JToken? _parent; private JToken? _current; public JToken? CurrentToken => _current; int IJsonLineInfo.LineNumber { get { if (base.CurrentState == State.Start) { return 0; } return ((IJsonLineInfo)_current)?.LineNumber ?? 0; } } int IJsonLineInfo.LinePosition { get { if (base.CurrentState == State.Start) { return 0; } return ((IJsonLineInfo)_current)?.LinePosition ?? 0; } } public override string Path { get { string text = base.Path; if (_initialPath == null) { _initialPath = _root.Path; } if (!StringUtils.IsNullOrEmpty(_initialPath)) { if (StringUtils.IsNullOrEmpty(text)) { return _initialPath; } text = ((!text.StartsWith('[')) ? (_initialPath + "." + text) : (_initialPath + text)); } return text; } } public JTokenReader(JToken token) { ValidationUtils.ArgumentNotNull(token, "token"); _root = token; } public JTokenReader(JToken token, string initialPath) : this(token) { _initialPath = initialPath; } public override bool Read() { if (base.CurrentState != 0) { if (_current == null) { return false; } if (_current is JContainer jContainer && _parent != jContainer) { return ReadInto(jContainer); } return ReadOver(_current); } if (_current == _root) { return false; } _current = _root; SetToken(_current); return true; } private bool ReadOver(JToken t) { if (t == _root) { return ReadToEnd(); } JToken next = t.Next; if (next == null || next == t || t == t.Parent.Last) { if (t.Parent == null) { return ReadToEnd(); } return SetEnd(t.Parent); } _current = next; SetToken(_current); return true; } private bool ReadToEnd() { _current = null; SetToken(JsonToken.None); return false; } private JsonToken? GetEndToken(JContainer c) { return c.Type switch { JTokenType.Object => JsonToken.EndObject, JTokenType.Array => JsonToken.EndArray, JTokenType.Constructor => JsonToken.EndConstructor, JTokenType.Property => null, _ => throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", c.Type, "Unexpected JContainer type."), }; } private bool ReadInto(JContainer c) { JToken first = c.First; if (first == null) { return SetEnd(c); } SetToken(first); _current = first; _parent = c; return true; } private bool SetEnd(JContainer c) { JsonToken? endToken = GetEndToken(c); if (endToken.HasValue) { SetToken(endToken.GetValueOrDefault()); _current = c; _parent = c; return true; } return ReadOver(c); } private void SetToken(JToken token) { switch (token.Type) { case JTokenType.Object: SetToken(JsonToken.StartObject); break; case JTokenType.Array: SetToken(JsonToken.StartArray); break; case JTokenType.Constructor: SetToken(JsonToken.StartConstructor, ((JConstructor)token).Name); break; case JTokenType.Property: SetToken(JsonToken.PropertyName, ((JProperty)token).Name); break; case JTokenType.Comment: SetToken(JsonToken.Comment, ((JValue)token).Value); break; case JTokenType.Integer: SetToken(JsonToken.Integer, ((JValue)token).Value); break; case JTokenType.Float: SetToken(JsonToken.Float, ((JValue)token).Value); break; case JTokenType.String: SetToken(JsonToken.String, ((JValue)token).Value); break; case JTokenType.Boolean: SetToken(JsonToken.Boolean, ((JValue)token).Value); break; case JTokenType.Null: SetToken(JsonToken.Null, ((JValue)token).Value); break; case JTokenType.Undefined: SetToken(JsonToken.Undefined, ((JValue)token).Value); break; case JTokenType.Date: { object obj = ((JValue)token).Value; if (obj is DateTime value2) { obj = DateTimeUtils.EnsureDateTime(value2, base.DateTimeZoneHandling); } SetToken(JsonToken.Date, obj); break; } case JTokenType.Raw: SetToken(JsonToken.Raw, ((JValue)token).Value); break; case JTokenType.Bytes: SetToken(JsonToken.Bytes, ((JValue)token).Value); break; case JTokenType.Guid: SetToken(JsonToken.String, SafeToString(((JValue)token).Value)); break; case JTokenType.Uri: { object value = ((JValue)token).Value; SetToken(JsonToken.String, (value is Uri uri) ? uri.OriginalString : SafeToString(value)); break; } case JTokenType.TimeSpan: SetToken(JsonToken.String, SafeToString(((JValue)token).Value)); break; default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", token.Type, "Unexpected JTokenType."); } } private string? SafeToString(object? value) { return value?.ToString(); } bool IJsonLineInfo.HasLineInfo() { if (base.CurrentState == State.Start) { return false; } return ((IJsonLineInfo)_current)?.HasLineInfo() ?? false; } } internal enum JTokenType { None, Object, Array, Constructor, Property, Comment, Integer, Float, String, Boolean, Null, Undefined, Date, Raw, Bytes, Guid, Uri, TimeSpan } internal class JTokenWriter : JsonWriter { private JContainer? _token; private JContainer? _parent; private JValue? _value; private JToken? _current; public JToken? CurrentToken => _current; public JToken? Token { get { if (_token != null) { return _token; } return _value; } } internal override Task WriteTokenAsync(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments, CancellationToken cancellationToken) { if (reader is JTokenReader) { WriteToken(reader, writeChildren, writeDateConstructorAsDate, writeComments); return AsyncUtils.CompletedTask; } return WriteTokenSyncReadingAsync(reader, cancellationToken); } public JTokenWriter(JContainer container) { ValidationUtils.ArgumentNotNull(container, "container"); _token = container; _parent = container; } public JTokenWriter() { } public override void Flush() { } public override void Close() { base.Close(); } public override void WriteStartObject() { base.WriteStartObject(); AddParent(new JObject()); } private void AddParent(JContainer container) { if (_parent == null) { _token = container; } else { _parent.AddAndSkipParentCheck(container); } _parent = container; _current = container; } private void RemoveParent() { _current = _parent; _parent = _parent.Parent; if (_parent != null && _parent.Type == JTokenType.Property) { _parent = _parent.Parent; } } public override void WriteStartArray() { base.WriteStartArray(); AddParent(new JArray()); } public override void WriteStartConstructor(string name) { base.WriteStartConstructor(name); AddParent(new JConstructor(name)); } protected override void WriteEnd(JsonToken token) { RemoveParent(); } public override void WritePropertyName(string name) { (_parent as JObject)?.Remove(name); AddParent(new JProperty(name)); base.WritePropertyName(name); } private void AddRawValue(object? value, JTokenType type, JsonToken token) { AddJValue(new JValue(value, type), token); } internal void AddJValue(JValue? value, JsonToken token) { if (_parent != null) { if (_parent.TryAdd(value)) { _current = _parent.Last; if (_parent.Type == JTokenType.Property) { _parent = _parent.Parent; } } } else { _value = value ?? JValue.CreateNull(); _current = _value; } } public override void WriteValue(object? value) { if (value is BigInteger) { InternalWriteValue(JsonToken.Integer); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } else { base.WriteValue(value); } } public override void WriteNull() { base.WriteNull(); AddJValue(JValue.CreateNull(), JsonToken.Null); } public override void WriteUndefined() { base.WriteUndefined(); AddJValue(JValue.CreateUndefined(), JsonToken.Undefined); } public override void WriteRaw(string? json) { base.WriteRaw(json); AddJValue(new JRaw(json), JsonToken.Raw); } public override void WriteComment(string? text) { base.WriteComment(text); AddJValue(JValue.CreateComment(text), JsonToken.Comment); } public override void WriteValue(string? value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.String); } public override void WriteValue(int value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } [CLSCompliant(false)] public override void WriteValue(uint value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } public override void WriteValue(long value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Integer); } [CLSCompliant(false)] public override void WriteValue(ulong value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Integer); } public override void WriteValue(float value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Float); } public override void WriteValue(double value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Float); } public override void WriteValue(bool value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Boolean); } public override void WriteValue(short value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } [CLSCompliant(false)] public override void WriteValue(ushort value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } public override void WriteValue(char value) { base.WriteValue(value); string value2 = value.ToString(CultureInfo.InvariantCulture); AddJValue(new JValue(value2), JsonToken.String); } public override void WriteValue(byte value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } [CLSCompliant(false)] public override void WriteValue(sbyte value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } public override void WriteValue(decimal value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Float); } public override void WriteValue(DateTime value) { base.WriteValue(value); value = DateTimeUtils.EnsureDateTime(value, base.DateTimeZoneHandling); AddJValue(new JValue(value), JsonToken.Date); } public override void WriteValue(DateTimeOffset value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Date); } public override void WriteValue(byte[]? value) { base.WriteValue(value); AddJValue(new JValue(value, JTokenType.Bytes), JsonToken.Bytes); } public override void WriteValue(TimeSpan value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.String); } public override void WriteValue(Guid value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.String); } public override void WriteValue(Uri? value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.String); } internal override void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments) { JTokenReader jTokenReader = reader as JTokenReader; if (jTokenReader != null && writeChildren && writeDateConstructorAsDate && writeComments) { if (jTokenReader.TokenType == JsonToken.None && !jTokenReader.Read()) { return; } JToken jToken = jTokenReader.CurrentToken.CloneToken(null); if (_parent != null) { _parent.Add(jToken); _current = _parent.Last; if (_parent.Type == JTokenType.Property) { _parent = _parent.Parent; InternalWriteValue(JsonToken.Null); } } else { _current = jToken; if (_token == null && _value == null) { _token = jToken as JContainer; _value = jToken as JValue; } } jTokenReader.Skip(); } else { base.WriteToken(reader, writeChildren, writeDateConstructorAsDate, writeComments); } } } internal class JValue : JToken, IEquatable, IFormattable, IComparable, IComparable, IConvertible { private class JValueDynamicProxy : DynamicProxy { public override bool TryConvert(JValue instance, ConvertBinder binder, [NotNullWhen(true)] out object? result) { if (binder.Type == typeof(JValue) || binder.Type == typeof(JToken)) { result = instance; return true; } object value = instance.Value; if (value == null) { result = null; return ReflectionUtils.IsNullable(binder.Type); } result = ConvertUtils.Convert(value, CultureInfo.InvariantCulture, binder.Type); return true; } public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, [NotNullWhen(true)] out object? result) { object objB = ((arg is JValue jValue) ? jValue.Value : arg); switch (binder.Operation) { case ExpressionType.Equal: result = Compare(instance.Type, instance.Value, objB) == 0; return true; case ExpressionType.NotEqual: result = Compare(instance.Type, instance.Value, objB) != 0; return true; case ExpressionType.GreaterThan: result = Compare(instance.Type, instance.Value, objB) > 0; return true; case ExpressionType.GreaterThanOrEqual: result = Compare(instance.Type, instance.Value, objB) >= 0; return true; case ExpressionType.LessThan: result = Compare(instance.Type, instance.Value, objB) < 0; return true; case ExpressionType.LessThanOrEqual: result = Compare(instance.Type, instance.Value, objB) <= 0; return true; case ExpressionType.Add: case ExpressionType.Divide: case ExpressionType.Multiply: case ExpressionType.Subtract: case ExpressionType.AddAssign: case ExpressionType.DivideAssign: case ExpressionType.MultiplyAssign: case ExpressionType.SubtractAssign: if (Operation(binder.Operation, instance.Value, objB, out result)) { result = new JValue(result); return true; } break; } result = null; return false; } } private JTokenType _valueType; private object? _value; public override bool HasValues => false; public override JTokenType Type => _valueType; public new object? Value { get { return _value; } set { Type obj = _value?.GetType(); Type type = value?.GetType(); if (obj != type) { _valueType = GetValueType(_valueType, value); } _value = value; } } public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { if (converters != null && converters.Length != 0 && _value != null) { JsonConverter matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); if (matchingConverter != null && matchingConverter.CanWrite) { matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault()); return AsyncUtils.CompletedTask; } } switch (_valueType) { case JTokenType.Comment: return writer.WriteCommentAsync(_value?.ToString(), cancellationToken); case JTokenType.Raw: return writer.WriteRawValueAsync(_value?.ToString(), cancellationToken); case JTokenType.Null: return writer.WriteNullAsync(cancellationToken); case JTokenType.Undefined: return writer.WriteUndefinedAsync(cancellationToken); case JTokenType.Integer: if (_value is int value5) { return writer.WriteValueAsync(value5, cancellationToken); } if (_value is long value6) { return writer.WriteValueAsync(value6, cancellationToken); } if (_value is ulong value7) { return writer.WriteValueAsync(value7, cancellationToken); } if (_value is BigInteger bigInteger) { return writer.WriteValueAsync(bigInteger, cancellationToken); } return writer.WriteValueAsync(Convert.ToInt64(_value, CultureInfo.InvariantCulture), cancellationToken); case JTokenType.Float: if (_value is decimal value) { return writer.WriteValueAsync(value, cancellationToken); } if (_value is double value2) { return writer.WriteValueAsync(value2, cancellationToken); } if (_value is float value3) { return writer.WriteValueAsync(value3, cancellationToken); } return writer.WriteValueAsync(Convert.ToDouble(_value, CultureInfo.InvariantCulture), cancellationToken); case JTokenType.String: return writer.WriteValueAsync(_value?.ToString(), cancellationToken); case JTokenType.Boolean: return writer.WriteValueAsync(Convert.ToBoolean(_value, CultureInfo.InvariantCulture), cancellationToken); case JTokenType.Date: if (_value is DateTimeOffset value4) { return writer.WriteValueAsync(value4, cancellationToken); } return writer.WriteValueAsync(Convert.ToDateTime(_value, CultureInfo.InvariantCulture), cancellationToken); case JTokenType.Bytes: return writer.WriteValueAsync((byte[])_value, cancellationToken); case JTokenType.Guid: return writer.WriteValueAsync((_value != null) ? ((Guid?)_value) : null, cancellationToken); case JTokenType.TimeSpan: return writer.WriteValueAsync((_value != null) ? ((TimeSpan?)_value) : null, cancellationToken); case JTokenType.Uri: return writer.WriteValueAsync((Uri)_value, cancellationToken); default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", _valueType, "Unexpected token type."); } } internal JValue(object? value, JTokenType type) { _value = value; _valueType = type; } internal JValue(JValue other, JsonCloneSettings? settings) : this(other.Value, other.Type) { if (settings == null || settings.CopyAnnotations) { CopyAnnotations(this, other); } } public JValue(JValue other) : this(other.Value, other.Type) { } public JValue(long value) : this(BoxedPrimitives.Get(value), JTokenType.Integer) { } public JValue(decimal value) : this(BoxedPrimitives.Get(value), JTokenType.Float) { } public JValue(char value) : this(value, JTokenType.String) { } [CLSCompliant(false)] public JValue(ulong value) : this(value, JTokenType.Integer) { } public JValue(double value) : this(BoxedPrimitives.Get(value), JTokenType.Float) { } public JValue(float value) : this(value, JTokenType.Float) { } public JValue(DateTime value) : this(value, JTokenType.Date) { } public JValue(DateTimeOffset value) : this(value, JTokenType.Date) { } public JValue(bool value) : this(BoxedPrimitives.Get(value), JTokenType.Boolean) { } public JValue(string? value) : this(value, JTokenType.String) { } public JValue(Guid value) : this(value, JTokenType.Guid) { } public JValue(Uri? value) : this(value, (value != null) ? JTokenType.Uri : JTokenType.Null) { } public JValue(TimeSpan value) : this(value, JTokenType.TimeSpan) { } public JValue(object? value) : this(value, GetValueType(null, value)) { } internal override bool DeepEquals(JToken node) { if (!(node is JValue jValue)) { return false; } if (jValue == this) { return true; } return ValuesEquals(this, jValue); } private static int CompareBigInteger(BigInteger i1, object i2) { int num = i1.CompareTo(ConvertUtils.ToBigInteger(i2)); if (num != 0) { return num; } if (i2 is decimal num2) { decimal num3 = 0m; return num3.CompareTo(Math.Abs(num2 - Math.Truncate(num2))); } if (i2 is double || i2 is float) { double num4 = Convert.ToDouble(i2, CultureInfo.InvariantCulture); return 0.0.CompareTo(Math.Abs(num4 - Math.Truncate(num4))); } return num; } internal static int Compare(JTokenType valueType, object? objA, object? objB) { if (objA == objB) { return 0; } if (objB == null) { return 1; } if (objA == null) { return -1; } switch (valueType) { case JTokenType.Integer: if (objA is BigInteger i3) { return CompareBigInteger(i3, objB); } if (objB is BigInteger i4) { return -CompareBigInteger(i4, objA); } if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) { return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture)); } if (objA is float || objB is float || objA is double || objB is double) { return CompareFloat(objA, objB); } return Convert.ToInt64(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToInt64(objB, CultureInfo.InvariantCulture)); case JTokenType.Float: if (objA is BigInteger i) { return CompareBigInteger(i, objB); } if (objB is BigInteger i2) { return -CompareBigInteger(i2, objA); } if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) { return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture)); } return CompareFloat(objA, objB); case JTokenType.Comment: case JTokenType.String: case JTokenType.Raw: { string? strA = Convert.ToString(objA, CultureInfo.InvariantCulture); string strB = Convert.ToString(objB, CultureInfo.InvariantCulture); return string.CompareOrdinal(strA, strB); } case JTokenType.Boolean: { bool flag = Convert.ToBoolean(objA, CultureInfo.InvariantCulture); bool value4 = Convert.ToBoolean(objB, CultureInfo.InvariantCulture); return flag.CompareTo(value4); } case JTokenType.Date: { if (objA is DateTime dateTime) { DateTime value2 = ((!(objB is DateTimeOffset dateTimeOffset)) ? Convert.ToDateTime(objB, CultureInfo.InvariantCulture) : dateTimeOffset.DateTime); return dateTime.CompareTo(value2); } DateTimeOffset dateTimeOffset2 = (DateTimeOffset)objA; DateTimeOffset other = ((!(objB is DateTimeOffset)) ? new DateTimeOffset(Convert.ToDateTime(objB, CultureInfo.InvariantCulture)) : ((DateTimeOffset)objB)); return dateTimeOffset2.CompareTo(other); } case JTokenType.Bytes: if (!(objB is byte[] a)) { throw new ArgumentException("Object must be of type byte[]."); } return MiscellaneousUtils.ByteArrayCompare(objA as byte[], a); case JTokenType.Guid: { if (!(objB is Guid)) { throw new ArgumentException("Object must be of type Guid."); } Guid guid = (Guid)objA; Guid value3 = (Guid)objB; return guid.CompareTo(value3); } case JTokenType.Uri: { Uri uri = objB as Uri; if (uri == null) { throw new ArgumentException("Object must be of type Uri."); } Uri uri2 = (Uri)objA; return Comparer.Default.Compare(uri2.ToString(), uri.ToString()); } case JTokenType.TimeSpan: { if (!(objB is TimeSpan)) { throw new ArgumentException("Object must be of type TimeSpan."); } TimeSpan timeSpan = (TimeSpan)objA; TimeSpan value = (TimeSpan)objB; return timeSpan.CompareTo(value); } default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("valueType", valueType, "Unexpected value type: {0}".FormatWith(CultureInfo.InvariantCulture, valueType)); } } private static int CompareFloat(object objA, object objB) { double d = Convert.ToDouble(objA, CultureInfo.InvariantCulture); double num = Convert.ToDouble(objB, CultureInfo.InvariantCulture); if (MathUtils.ApproxEquals(d, num)) { return 0; } return d.CompareTo(num); } private static bool Operation(ExpressionType operation, object? objA, object? objB, out object? result) { if ((objA is string || objB is string) && (operation == ExpressionType.Add || operation == ExpressionType.AddAssign)) { result = objA?.ToString() + objB; return true; } if (objA is BigInteger || objB is BigInteger) { if (objA == null || objB == null) { result = null; return true; } BigInteger bigInteger = ConvertUtils.ToBigInteger(objA); BigInteger bigInteger2 = ConvertUtils.ToBigInteger(objB); switch (operation) { case ExpressionType.Add: case ExpressionType.AddAssign: result = bigInteger + bigInteger2; return true; case ExpressionType.Subtract: case ExpressionType.SubtractAssign: result = bigInteger - bigInteger2; return true; case ExpressionType.Multiply: case ExpressionType.MultiplyAssign: result = bigInteger * bigInteger2; return true; case ExpressionType.Divide: case ExpressionType.DivideAssign: result = bigInteger / bigInteger2; return true; } } else if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) { if (objA == null || objB == null) { result = null; return true; } decimal num = Convert.ToDecimal(objA, CultureInfo.InvariantCulture); decimal num2 = Convert.ToDecimal(objB, CultureInfo.InvariantCulture); switch (operation) { case ExpressionType.Add: case ExpressionType.AddAssign: result = num + num2; return true; case ExpressionType.Subtract: case ExpressionType.SubtractAssign: result = num - num2; return true; case ExpressionType.Multiply: case ExpressionType.MultiplyAssign: result = num * num2; return true; case ExpressionType.Divide: case ExpressionType.DivideAssign: result = num / num2; return true; } } else if (objA is float || objB is float || objA is double || objB is double) { if (objA == null || objB == null) { result = null; return true; } double num3 = Convert.ToDouble(objA, CultureInfo.InvariantCulture); double num4 = Convert.ToDouble(objB, CultureInfo.InvariantCulture); switch (operation) { case ExpressionType.Add: case ExpressionType.AddAssign: result = num3 + num4; return true; case ExpressionType.Subtract: case ExpressionType.SubtractAssign: result = num3 - num4; return true; case ExpressionType.Multiply: case ExpressionType.MultiplyAssign: result = num3 * num4; return true; case ExpressionType.Divide: case ExpressionType.DivideAssign: result = num3 / num4; return true; } } else if (objA is int || objA is uint || objA is long || objA is short || objA is ushort || objA is sbyte || objA is byte || objB is int || objB is uint || objB is long || objB is short || objB is ushort || objB is sbyte || objB is byte) { if (objA == null || objB == null) { result = null; return true; } long num5 = Convert.ToInt64(objA, CultureInfo.InvariantCulture); long num6 = Convert.ToInt64(objB, CultureInfo.InvariantCulture); switch (operation) { case ExpressionType.Add: case ExpressionType.AddAssign: result = num5 + num6; return true; case ExpressionType.Subtract: case ExpressionType.SubtractAssign: result = num5 - num6; return true; case ExpressionType.Multiply: case ExpressionType.MultiplyAssign: result = num5 * num6; return true; case ExpressionType.Divide: case ExpressionType.DivideAssign: result = num5 / num6; return true; } } result = null; return false; } internal override JToken CloneToken(JsonCloneSettings? settings) { return new JValue(this, settings); } public static JValue CreateComment(string? value) { return new JValue(value, JTokenType.Comment); } public static JValue CreateString(string? value) { return new JValue(value, JTokenType.String); } public static JValue CreateNull() { return new JValue(null, JTokenType.Null); } public static JValue CreateUndefined() { return new JValue(null, JTokenType.Undefined); } private static JTokenType GetValueType(JTokenType? current, object? value) { if (value == null) { return JTokenType.Null; } if (value == DBNull.Value) { return JTokenType.Null; } if (value is string) { return GetStringValueType(current); } if (value is long || value is int || value is short || value is sbyte || value is ulong || value is uint || value is ushort || value is byte) { return JTokenType.Integer; } if (value is Enum) { return JTokenType.Integer; } if (value is BigInteger) { return JTokenType.Integer; } if (value is double || value is float || value is decimal) { return JTokenType.Float; } if (value is DateTime) { return JTokenType.Date; } if (value is DateTimeOffset) { return JTokenType.Date; } if (value is byte[]) { return JTokenType.Bytes; } if (value is bool) { return JTokenType.Boolean; } if (value is Guid) { return JTokenType.Guid; } if (value is Uri) { return JTokenType.Uri; } if (value is TimeSpan) { return JTokenType.TimeSpan; } throw new ArgumentException("Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } private static JTokenType GetStringValueType(JTokenType? current) { if (!current.HasValue) { return JTokenType.String; } JTokenType valueOrDefault = current.GetValueOrDefault(); if (valueOrDefault == JTokenType.Comment || valueOrDefault == JTokenType.String || valueOrDefault == JTokenType.Raw) { return current.GetValueOrDefault(); } return JTokenType.String; } public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { if (converters != null && converters.Length != 0 && _value != null) { JsonConverter matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); if (matchingConverter != null && matchingConverter.CanWrite) { matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault()); return; } } switch (_valueType) { case JTokenType.Comment: writer.WriteComment(_value?.ToString()); break; case JTokenType.Raw: writer.WriteRawValue(_value?.ToString()); break; case JTokenType.Null: writer.WriteNull(); break; case JTokenType.Undefined: writer.WriteUndefined(); break; case JTokenType.Integer: if (_value is int value5) { writer.WriteValue(value5); } else if (_value is long value6) { writer.WriteValue(value6); } else if (_value is ulong value7) { writer.WriteValue(value7); } else if (_value is BigInteger bigInteger) { writer.WriteValue(bigInteger); } else { writer.WriteValue(Convert.ToInt64(_value, CultureInfo.InvariantCulture)); } break; case JTokenType.Float: if (_value is decimal value) { writer.WriteValue(value); } else if (_value is double value2) { writer.WriteValue(value2); } else if (_value is float value3) { writer.WriteValue(value3); } else { writer.WriteValue(Convert.ToDouble(_value, CultureInfo.InvariantCulture)); } break; case JTokenType.String: writer.WriteValue(_value?.ToString()); break; case JTokenType.Boolean: writer.WriteValue(Convert.ToBoolean(_value, CultureInfo.InvariantCulture)); break; case JTokenType.Date: if (_value is DateTimeOffset value4) { writer.WriteValue(value4); } else { writer.WriteValue(Convert.ToDateTime(_value, CultureInfo.InvariantCulture)); } break; case JTokenType.Bytes: writer.WriteValue((byte[])_value); break; case JTokenType.Guid: writer.WriteValue((_value != null) ? ((Guid?)_value) : null); break; case JTokenType.TimeSpan: writer.WriteValue((_value != null) ? ((TimeSpan?)_value) : null); break; case JTokenType.Uri: writer.WriteValue((Uri)_value); break; default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", _valueType, "Unexpected token type."); } } internal override int GetDeepHashCode() { int num = ((_value != null) ? _value.GetHashCode() : 0); int valueType = (int)_valueType; return valueType.GetHashCode() ^ num; } private static bool ValuesEquals(JValue v1, JValue v2) { if (v1 != v2) { if (v1._valueType == v2._valueType) { return Compare(v1._valueType, v1._value, v2._value) == 0; } return false; } return true; } public bool Equals(JValue? other) { if (other == null) { return false; } return ValuesEquals(this, other); } public override bool Equals(object? obj) { if (obj is JValue other) { return Equals(other); } return false; } public override int GetHashCode() { if (_value == null) { return 0; } return _value.GetHashCode(); } public override string ToString() { if (_value == null) { return string.Empty; } return _value.ToString(); } public string ToString(string format) { return ToString(format, CultureInfo.CurrentCulture); } public string ToString(IFormatProvider? formatProvider) { return ToString(null, formatProvider); } public string ToString(string? format, IFormatProvider? formatProvider) { if (_value == null) { return string.Empty; } if (_value is IFormattable formattable) { return formattable.ToString(format, formatProvider); } return _value.ToString(); } protected override DynamicMetaObject GetMetaObject(Expression parameter) { return new DynamicProxyMetaObject(parameter, this, new JValueDynamicProxy()); } int IComparable.CompareTo(object? obj) { if (obj == null) { return 1; } object objB; JTokenType valueType; if (obj is JValue jValue) { objB = jValue.Value; valueType = ((_valueType == JTokenType.String && _valueType != jValue._valueType) ? jValue._valueType : _valueType); } else { objB = obj; valueType = _valueType; } return Compare(valueType, _value, objB); } public int CompareTo(JValue? obj) { if (obj == null) { return 1; } return Compare((_valueType == JTokenType.String && _valueType != obj._valueType) ? obj._valueType : _valueType, _value, obj._value); } TypeCode IConvertible.GetTypeCode() { if (_value == null) { return TypeCode.Empty; } if (_value is IConvertible convertible) { return convertible.GetTypeCode(); } return TypeCode.Object; } bool IConvertible.ToBoolean(IFormatProvider? provider) { return (bool)(JToken)this; } char IConvertible.ToChar(IFormatProvider? provider) { return (char)(JToken)this; } sbyte IConvertible.ToSByte(IFormatProvider? provider) { return (sbyte)(JToken)this; } byte IConvertible.ToByte(IFormatProvider? provider) { return (byte)(JToken)this; } short IConvertible.ToInt16(IFormatProvider? provider) { return (short)(JToken)this; } ushort IConvertible.ToUInt16(IFormatProvider? provider) { return (ushort)(JToken)this; } int IConvertible.ToInt32(IFormatProvider? provider) { return (int)(JToken)this; } uint IConvertible.ToUInt32(IFormatProvider? provider) { return (uint)(JToken)this; } long IConvertible.ToInt64(IFormatProvider? provider) { return (long)(JToken)this; } ulong IConvertible.ToUInt64(IFormatProvider? provider) { return (ulong)(JToken)this; } float IConvertible.ToSingle(IFormatProvider? provider) { return (float)(JToken)this; } double IConvertible.ToDouble(IFormatProvider? provider) { return (double)(JToken)this; } decimal IConvertible.ToDecimal(IFormatProvider? provider) { return (decimal)(JToken)this; } DateTime IConvertible.ToDateTime(IFormatProvider? provider) { return (DateTime)(JToken)this; } object IConvertible.ToType(Type conversionType, IFormatProvider? provider) { return ToObject(conversionType); } } internal enum LineInfoHandling { Ignore, Load } internal enum MergeArrayHandling { Concat, Union, Replace, Merge } [Flags] internal enum MergeNullValueHandling { Ignore = 0, Merge = 1 } } namespace Newtonsoft.Json.Linq.JsonPath { internal class ArrayIndexFilter : PathFilter { public int? Index { get; set; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken item in current) { if (Index.HasValue) { JToken tokenIndex = PathFilter.GetTokenIndex(item, settings, Index.GetValueOrDefault()); if (tokenIndex != null) { yield return tokenIndex; } } else if (item is JArray || item is JConstructor) { foreach (JToken item2 in (IEnumerable)item) { yield return item2; } } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Index * not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, item.GetType().Name)); } } } } internal class ArrayMultipleIndexFilter : PathFilter { internal List Indexes; public ArrayMultipleIndexFilter(List indexes) { Indexes = indexes; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken t in current) { foreach (int index in Indexes) { JToken tokenIndex = PathFilter.GetTokenIndex(t, settings, index); if (tokenIndex != null) { yield return tokenIndex; } } } } } internal class ArraySliceFilter : PathFilter { public int? Start { get; set; } public int? End { get; set; } public int? Step { get; set; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { if (Step == 0) { throw new JsonException("Step cannot be zero."); } foreach (JToken item in current) { if (item is JArray a) { int stepCount = Step ?? 1; int num = Start ?? ((stepCount <= 0) ? (a.Count - 1) : 0); int stopIndex = End ?? ((stepCount > 0) ? a.Count : (-1)); if (Start < 0) { num = a.Count + num; } if (End < 0) { stopIndex = a.Count + stopIndex; } num = Math.Max(num, (stepCount <= 0) ? int.MinValue : 0); num = Math.Min(num, (stepCount > 0) ? a.Count : (a.Count - 1)); stopIndex = Math.Max(stopIndex, -1); stopIndex = Math.Min(stopIndex, a.Count); bool positiveStep = stepCount > 0; if (IsValid(num, stopIndex, positiveStep)) { for (int i = num; IsValid(i, stopIndex, positiveStep); i += stepCount) { yield return a[i]; } } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Array slice of {0} to {1} returned no results.".FormatWith(CultureInfo.InvariantCulture, Start.HasValue ? Start.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) : "*", End.HasValue ? End.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) : "*")); } } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Array slice is not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, item.GetType().Name)); } } } private bool IsValid(int index, int stopIndex, bool positiveStep) { if (positiveStep) { return index < stopIndex; } return index > stopIndex; } } internal class FieldFilter : PathFilter { internal string? Name; public FieldFilter(string? name) { Name = name; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken item in current) { if (item is JObject jObject) { if (Name != null) { JToken jToken = jObject[Name]; if (jToken != null) { yield return jToken; } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, Name)); } continue; } foreach (KeyValuePair item2 in jObject) { yield return item2.Value; } } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, Name ?? "*", item.GetType().Name)); } } } } internal class FieldMultipleFilter : PathFilter { internal List Names; public FieldMultipleFilter(List names) { Names = names; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken item in current) { if (item is JObject o) { foreach (string name in Names) { JToken jToken = o[name]; if (jToken != null) { yield return jToken; } if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, name)); } } } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Properties {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", Names.Select((string n) => "'" + n + "'")), item.GetType().Name)); } } } } internal class JPath { private static readonly char[] FloatCharacters = new char[3] { '.', 'E', 'e' }; private readonly string _expression; private int _currentIndex; public List Filters { get; } public JPath(string expression) { ValidationUtils.ArgumentNotNull(expression, "expression"); _expression = expression; Filters = new List(); ParseMain(); } private void ParseMain() { int currentIndex = _currentIndex; EatWhitespace(); if (_expression.Length == _currentIndex) { return; } if (_expression[_currentIndex] == '$') { if (_expression.Length == 1) { return; } char c = _expression[_currentIndex + 1]; if (c == '.' || c == '[') { _currentIndex++; currentIndex = _currentIndex; } } if (!ParsePath(Filters, currentIndex, query: false)) { int currentIndex2 = _currentIndex; EatWhitespace(); if (_currentIndex < _expression.Length) { throw new JsonException("Unexpected character while parsing path: " + _expression[currentIndex2]); } } } private bool ParsePath(List filters, int currentPartStartIndex, bool query) { bool scan = false; bool flag = false; bool flag2 = false; bool flag3 = false; while (_currentIndex < _expression.Length && !flag3) { char c = _expression[_currentIndex]; switch (c) { case '(': case '[': if (_currentIndex > currentPartStartIndex) { string text = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); if (text == "*") { text = null; } filters.Add(CreatePathFilter(text, scan)); scan = false; } filters.Add(ParseIndexer(c, scan)); scan = false; _currentIndex++; currentPartStartIndex = _currentIndex; flag = true; flag2 = false; break; case ')': case ']': flag3 = true; break; case ' ': if (_currentIndex < _expression.Length) { flag3 = true; } break; case '.': if (_currentIndex > currentPartStartIndex) { string text2 = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); if (text2 == "*") { text2 = null; } filters.Add(CreatePathFilter(text2, scan)); scan = false; } if (_currentIndex + 1 < _expression.Length && _expression[_currentIndex + 1] == '.') { scan = true; _currentIndex++; } _currentIndex++; currentPartStartIndex = _currentIndex; flag = false; flag2 = true; break; default: if (query && (c == '=' || c == '<' || c == '!' || c == '>' || c == '|' || c == '&')) { flag3 = true; break; } if (flag) { throw new JsonException("Unexpected character following indexer: " + c); } _currentIndex++; break; } } bool flag4 = _currentIndex == _expression.Length; if (_currentIndex > currentPartStartIndex) { string text3 = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex).TrimEnd(); if (text3 == "*") { text3 = null; } filters.Add(CreatePathFilter(text3, scan)); } else if (flag2 && (flag4 || query)) { throw new JsonException("Unexpected end while parsing path."); } return flag4; } private static PathFilter CreatePathFilter(string? member, bool scan) { if (!scan) { return new FieldFilter(member); } return new ScanFilter(member); } private PathFilter ParseIndexer(char indexerOpenChar, bool scan) { _currentIndex++; char indexerCloseChar = ((indexerOpenChar == '[') ? ']' : ')'); EnsureLength("Path ended with open indexer."); EatWhitespace(); if (_expression[_currentIndex] == '\'') { return ParseQuotedField(indexerCloseChar, scan); } if (_expression[_currentIndex] == '?') { return ParseQuery(indexerCloseChar, scan); } return ParseArrayIndexer(indexerCloseChar); } private PathFilter ParseArrayIndexer(char indexerCloseChar) { int currentIndex = _currentIndex; int? num = null; List list = null; int num2 = 0; int? start = null; int? end = null; int? step = null; while (_currentIndex < _expression.Length) { char c = _expression[_currentIndex]; if (c == ' ') { num = _currentIndex; EatWhitespace(); continue; } if (c == indexerCloseChar) { int num3 = (num ?? _currentIndex) - currentIndex; if (list != null) { if (num3 == 0) { throw new JsonException("Array index expected."); } int item = Convert.ToInt32(_expression.Substring(currentIndex, num3), CultureInfo.InvariantCulture); list.Add(item); return new ArrayMultipleIndexFilter(list); } if (num2 > 0) { if (num3 > 0) { int value = Convert.ToInt32(_expression.Substring(currentIndex, num3), CultureInfo.InvariantCulture); if (num2 == 1) { end = value; } else { step = value; } } return new ArraySliceFilter { Start = start, End = end, Step = step }; } if (num3 == 0) { throw new JsonException("Array index expected."); } int value2 = Convert.ToInt32(_expression.Substring(currentIndex, num3), CultureInfo.InvariantCulture); return new ArrayIndexFilter { Index = value2 }; } switch (c) { case ',': { int num5 = (num ?? _currentIndex) - currentIndex; if (num5 == 0) { throw new JsonException("Array index expected."); } if (list == null) { list = new List(); } string value4 = _expression.Substring(currentIndex, num5); list.Add(Convert.ToInt32(value4, CultureInfo.InvariantCulture)); _currentIndex++; EatWhitespace(); currentIndex = _currentIndex; num = null; break; } case '*': _currentIndex++; EnsureLength("Path ended with open indexer."); EatWhitespace(); if (_expression[_currentIndex] != indexerCloseChar) { throw new JsonException("Unexpected character while parsing path indexer: " + c); } return new ArrayIndexFilter(); case ':': { int num4 = (num ?? _currentIndex) - currentIndex; if (num4 > 0) { int value3 = Convert.ToInt32(_expression.Substring(currentIndex, num4), CultureInfo.InvariantCulture); switch (num2) { case 0: start = value3; break; case 1: end = value3; break; default: step = value3; break; } } num2++; _currentIndex++; EatWhitespace(); currentIndex = _currentIndex; num = null; break; } default: if (!char.IsDigit(c) && c != '-') { throw new JsonException("Unexpected character while parsing path indexer: " + c); } if (num.HasValue) { throw new JsonException("Unexpected character while parsing path indexer: " + c); } _currentIndex++; break; } } throw new JsonException("Path ended with open indexer."); } private void EatWhitespace() { while (_currentIndex < _expression.Length && _expression[_currentIndex] == ' ') { _currentIndex++; } } private PathFilter ParseQuery(char indexerCloseChar, bool scan) { _currentIndex++; EnsureLength("Path ended with open indexer."); if (_expression[_currentIndex] != '(') { throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]); } _currentIndex++; QueryExpression expression = ParseExpression(); _currentIndex++; EnsureLength("Path ended with open indexer."); EatWhitespace(); if (_expression[_currentIndex] != indexerCloseChar) { throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]); } if (!scan) { return new QueryFilter(expression); } return new QueryScanFilter(expression); } private bool TryParseExpression(out List? expressionPath) { if (_expression[_currentIndex] == '$') { expressionPath = new List { RootFilter.Instance }; } else { if (_expression[_currentIndex] != '@') { expressionPath = null; return false; } expressionPath = new List(); } _currentIndex++; if (ParsePath(expressionPath, _currentIndex, query: true)) { throw new JsonException("Path ended with open query."); } return true; } private JsonException CreateUnexpectedCharacterException() { return new JsonException("Unexpected character while parsing path query: " + _expression[_currentIndex]); } private object ParseSide() { EatWhitespace(); if (TryParseExpression(out List expressionPath)) { EatWhitespace(); EnsureLength("Path ended with open query."); return expressionPath; } if (TryParseValue(out object value)) { EatWhitespace(); EnsureLength("Path ended with open query."); return new JValue(value); } throw CreateUnexpectedCharacterException(); } private QueryExpression ParseExpression() { QueryExpression queryExpression = null; CompositeExpression compositeExpression = null; while (_currentIndex < _expression.Length) { object left = ParseSide(); object right = null; QueryOperator @operator; if (_expression[_currentIndex] == ')' || _expression[_currentIndex] == '|' || _expression[_currentIndex] == '&') { @operator = QueryOperator.Exists; } else { @operator = ParseOperator(); right = ParseSide(); } BooleanQueryExpression booleanQueryExpression = new BooleanQueryExpression(@operator, left, right); if (_expression[_currentIndex] == ')') { if (compositeExpression != null) { compositeExpression.Expressions.Add(booleanQueryExpression); return queryExpression; } return booleanQueryExpression; } if (_expression[_currentIndex] == '&') { if (!Match("&&")) { throw CreateUnexpectedCharacterException(); } if (compositeExpression == null || compositeExpression.Operator != QueryOperator.And) { CompositeExpression compositeExpression2 = new CompositeExpression(QueryOperator.And); compositeExpression?.Expressions.Add(compositeExpression2); compositeExpression = compositeExpression2; if (queryExpression == null) { queryExpression = compositeExpression; } } compositeExpression.Expressions.Add(booleanQueryExpression); } if (_expression[_currentIndex] != '|') { continue; } if (!Match("||")) { throw CreateUnexpectedCharacterException(); } if (compositeExpression == null || compositeExpression.Operator != QueryOperator.Or) { CompositeExpression compositeExpression3 = new CompositeExpression(QueryOperator.Or); compositeExpression?.Expressions.Add(compositeExpression3); compositeExpression = compositeExpression3; if (queryExpression == null) { queryExpression = compositeExpression; } } compositeExpression.Expressions.Add(booleanQueryExpression); } throw new JsonException("Path ended with open query."); } private bool TryParseValue(out object? value) { char c = _expression[_currentIndex]; if (c == '\'') { value = ReadQuotedString(); return true; } if (char.IsDigit(c) || c == '-') { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(c); _currentIndex++; while (_currentIndex < _expression.Length) { c = _expression[_currentIndex]; if (c == ' ' || c == ')') { string text = stringBuilder.ToString(); if (text.IndexOfAny(FloatCharacters) != -1) { double result; bool result2 = double.TryParse(text, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out result); value = result; return result2; } long result3; bool result4 = long.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out result3); value = result3; return result4; } stringBuilder.Append(c); _currentIndex++; } } else { switch (c) { case 't': if (Match("true")) { value = true; return true; } break; case 'f': if (Match("false")) { value = false; return true; } break; case 'n': if (Match("null")) { value = null; return true; } break; case '/': value = ReadRegexString(); return true; } } value = null; return false; } private string ReadQuotedString() { StringBuilder stringBuilder = new StringBuilder(); _currentIndex++; while (_currentIndex < _expression.Length) { char c = _expression[_currentIndex]; if (c == '\\' && _currentIndex + 1 < _expression.Length) { _currentIndex++; c = _expression[_currentIndex]; char value; switch (c) { case 'b': value = '\b'; break; case 't': value = '\t'; break; case 'n': value = '\n'; break; case 'f': value = '\f'; break; case 'r': value = '\r'; break; case '"': case '\'': case '/': case '\\': value = c; break; default: throw new JsonException("Unknown escape character: \\" + c); } stringBuilder.Append(value); _currentIndex++; } else { if (c == '\'') { _currentIndex++; return stringBuilder.ToString(); } _currentIndex++; stringBuilder.Append(c); } } throw new JsonException("Path ended with an open string."); } private string ReadRegexString() { int currentIndex = _currentIndex; _currentIndex++; while (_currentIndex < _expression.Length) { char c = _expression[_currentIndex]; if (c == '\\' && _currentIndex + 1 < _expression.Length) { _currentIndex += 2; continue; } if (c == '/') { _currentIndex++; while (_currentIndex < _expression.Length) { c = _expression[_currentIndex]; if (!char.IsLetter(c)) { break; } _currentIndex++; } return _expression.Substring(currentIndex, _currentIndex - currentIndex); } _currentIndex++; } throw new JsonException("Path ended with an open regex."); } private bool Match(string s) { int num = _currentIndex; for (int i = 0; i < s.Length; i++) { if (num < _expression.Length && _expression[num] == s[i]) { num++; continue; } return false; } _currentIndex = num; return true; } private QueryOperator ParseOperator() { if (_currentIndex + 1 >= _expression.Length) { throw new JsonException("Path ended with open query."); } if (Match("===")) { return QueryOperator.StrictEquals; } if (Match("==")) { return QueryOperator.Equals; } if (Match("=~")) { return QueryOperator.RegexEquals; } if (Match("!==")) { return QueryOperator.StrictNotEquals; } if (Match("!=") || Match("<>")) { return QueryOperator.NotEquals; } if (Match("<=")) { return QueryOperator.LessThanOrEquals; } if (Match("<")) { return QueryOperator.LessThan; } if (Match(">=")) { return QueryOperator.GreaterThanOrEquals; } if (Match(">")) { return QueryOperator.GreaterThan; } throw new JsonException("Could not read query operator."); } private PathFilter ParseQuotedField(char indexerCloseChar, bool scan) { List list = null; while (_currentIndex < _expression.Length) { string text = ReadQuotedString(); EatWhitespace(); EnsureLength("Path ended with open indexer."); if (_expression[_currentIndex] == indexerCloseChar) { if (list != null) { list.Add(text); if (!scan) { return new FieldMultipleFilter(list); } return new ScanMultipleFilter(list); } return CreatePathFilter(text, scan); } if (_expression[_currentIndex] == ',') { _currentIndex++; EatWhitespace(); if (list == null) { list = new List(); } list.Add(text); continue; } throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]); } throw new JsonException("Path ended with open indexer."); } private void EnsureLength(string message) { if (_currentIndex >= _expression.Length) { throw new JsonException(message); } } internal IEnumerable Evaluate(JToken root, JToken t, JsonSelectSettings? settings) { return Evaluate(Filters, root, t, settings); } internal static IEnumerable Evaluate(List filters, JToken root, JToken t, JsonSelectSettings? settings) { IEnumerable enumerable = new JToken[1] { t }; foreach (PathFilter filter in filters) { enumerable = filter.ExecuteFilter(root, enumerable, settings); } return enumerable; } } internal abstract class PathFilter { public abstract IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings); protected static JToken? GetTokenIndex(JToken t, JsonSelectSettings? settings, int index) { if (t is JArray jArray) { if (jArray.Count <= index) { if (settings != null && settings.ErrorWhenNoMatch) { throw new JsonException("Index {0} outside the bounds of JArray.".FormatWith(CultureInfo.InvariantCulture, index)); } return null; } return jArray[index]; } if (t is JConstructor jConstructor) { if (jConstructor.Count <= index) { if (settings != null && settings.ErrorWhenNoMatch) { throw new JsonException("Index {0} outside the bounds of JConstructor.".FormatWith(CultureInfo.InvariantCulture, index)); } return null; } return jConstructor[index]; } if (settings != null && settings.ErrorWhenNoMatch) { throw new JsonException("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, t.GetType().Name)); } return null; } protected static JToken? GetNextScanValue(JToken originalParent, JToken? container, JToken? value) { if (container != null && container.HasValues) { value = container.First; } else { while (value != null && value != originalParent && value == value.Parent.Last) { value = value.Parent; } if (value == null || value == originalParent) { return null; } value = value.Next; } return value; } } internal enum QueryOperator { None, Equals, NotEquals, Exists, LessThan, LessThanOrEquals, GreaterThan, GreaterThanOrEquals, And, Or, RegexEquals, StrictEquals, StrictNotEquals } internal abstract class QueryExpression { internal QueryOperator Operator; public QueryExpression(QueryOperator @operator) { Operator = @operator; } public bool IsMatch(JToken root, JToken t) { return IsMatch(root, t, null); } public abstract bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings); } internal class CompositeExpression : QueryExpression { public List Expressions { get; set; } public CompositeExpression(QueryOperator @operator) : base(@operator) { Expressions = new List(); } public override bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings) { switch (Operator) { case QueryOperator.And: foreach (QueryExpression expression in Expressions) { if (!expression.IsMatch(root, t, settings)) { return false; } } return true; case QueryOperator.Or: foreach (QueryExpression expression2 in Expressions) { if (expression2.IsMatch(root, t, settings)) { return true; } } return false; default: throw new ArgumentOutOfRangeException(); } } } internal class BooleanQueryExpression : QueryExpression { public readonly object Left; public readonly object? Right; public BooleanQueryExpression(QueryOperator @operator, object left, object? right) : base(@operator) { Left = left; Right = right; } private IEnumerable GetResult(JToken root, JToken t, object? o) { if (o is JToken jToken) { return new JToken[1] { jToken }; } if (o is List filters) { return JPath.Evaluate(filters, root, t, null); } return CollectionUtils.ArrayEmpty(); } public override bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings) { if (Operator == QueryOperator.Exists) { return GetResult(root, t, Left).Any(); } using (IEnumerator enumerator = GetResult(root, t, Left).GetEnumerator()) { if (enumerator.MoveNext()) { IEnumerable result = GetResult(root, t, Right); ICollection collection = (result as ICollection) ?? result.ToList(); do { JToken current = enumerator.Current; foreach (JToken item in collection) { if (MatchTokens(current, item, settings)) { return true; } } } while (enumerator.MoveNext()); } } return false; } private bool MatchTokens(JToken leftResult, JToken rightResult, JsonSelectSettings? settings) { if (leftResult is JValue jValue && rightResult is JValue jValue2) { switch (Operator) { case QueryOperator.RegexEquals: if (RegexEquals(jValue, jValue2, settings)) { return true; } break; case QueryOperator.Equals: if (EqualsWithStringCoercion(jValue, jValue2)) { return true; } break; case QueryOperator.StrictEquals: if (EqualsWithStrictMatch(jValue, jValue2)) { return true; } break; case QueryOperator.NotEquals: if (!EqualsWithStringCoercion(jValue, jValue2)) { return true; } break; case QueryOperator.StrictNotEquals: if (!EqualsWithStrictMatch(jValue, jValue2)) { return true; } break; case QueryOperator.GreaterThan: if (jValue.CompareTo(jValue2) > 0) { return true; } break; case QueryOperator.GreaterThanOrEquals: if (jValue.CompareTo(jValue2) >= 0) { return true; } break; case QueryOperator.LessThan: if (jValue.CompareTo(jValue2) < 0) { return true; } break; case QueryOperator.LessThanOrEquals: if (jValue.CompareTo(jValue2) <= 0) { return true; } break; case QueryOperator.Exists: return true; } } else { QueryOperator @operator = Operator; if ((uint)(@operator - 2) <= 1u) { return true; } } return false; } private static bool RegexEquals(JValue input, JValue pattern, JsonSelectSettings? settings) { if (input.Type != JTokenType.String || pattern.Type != JTokenType.String) { return false; } string obj = (string)pattern.Value; int num = obj.LastIndexOf('/'); string pattern2 = obj.Substring(1, num - 1); string optionsText = obj.Substring(num + 1); TimeSpan matchTimeout = settings?.RegexMatchTimeout ?? Regex.InfiniteMatchTimeout; return Regex.IsMatch((string)input.Value, pattern2, MiscellaneousUtils.GetRegexOptions(optionsText), matchTimeout); } internal static bool EqualsWithStringCoercion(JValue value, JValue queryValue) { if (value.Equals(queryValue)) { return true; } if ((value.Type == JTokenType.Integer && queryValue.Type == JTokenType.Float) || (value.Type == JTokenType.Float && queryValue.Type == JTokenType.Integer)) { return JValue.Compare(value.Type, value.Value, queryValue.Value) == 0; } if (queryValue.Type != JTokenType.String) { return false; } string b = (string)queryValue.Value; string a; switch (value.Type) { case JTokenType.Date: { using (StringWriter stringWriter = StringUtils.CreateStringWriter(64)) { if (value.Value is DateTimeOffset value2) { DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value2, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture); } else { DateTimeUtils.WriteDateTimeString(stringWriter, (DateTime)value.Value, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture); } a = stringWriter.ToString(); } break; } case JTokenType.Bytes: a = Convert.ToBase64String((byte[])value.Value); break; case JTokenType.Guid: case JTokenType.TimeSpan: a = value.Value.ToString(); break; case JTokenType.Uri: a = ((Uri)value.Value).OriginalString; break; default: return false; } return string.Equals(a, b, StringComparison.Ordinal); } internal static bool EqualsWithStrictMatch(JValue value, JValue queryValue) { if ((value.Type == JTokenType.Integer && queryValue.Type == JTokenType.Float) || (value.Type == JTokenType.Float && queryValue.Type == JTokenType.Integer)) { return JValue.Compare(value.Type, value.Value, queryValue.Value) == 0; } if (value.Type != queryValue.Type) { return false; } return value.Equals(queryValue); } } internal class QueryFilter : PathFilter { internal QueryExpression Expression; public QueryFilter(QueryExpression expression) { Expression = expression; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken item in current) { foreach (JToken item2 in (IEnumerable)item) { if (Expression.IsMatch(root, item2, settings)) { yield return item2; } } } } } internal class QueryScanFilter : PathFilter { internal QueryExpression Expression; public QueryScanFilter(QueryExpression expression) { Expression = expression; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken item in current) { if (item is JContainer jContainer) { foreach (JToken item2 in jContainer.DescendantsAndSelf()) { if (Expression.IsMatch(root, item2, settings)) { yield return item2; } } } else if (Expression.IsMatch(root, item, settings)) { yield return item; } } } } internal class RootFilter : PathFilter { public static readonly RootFilter Instance = new RootFilter(); private RootFilter() { } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { return new JToken[1] { root }; } } internal class ScanFilter : PathFilter { internal string? Name; public ScanFilter(string? name) { Name = name; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken c in current) { if (Name == null) { yield return c; } JToken value = c; while (true) { JContainer container = value as JContainer; value = PathFilter.GetNextScanValue(c, container, value); if (value == null) { break; } if (value is JProperty jProperty) { if (jProperty.Name == Name) { yield return jProperty.Value; } } else if (Name == null) { yield return value; } } } } } internal class ScanMultipleFilter : PathFilter { private List _names; public ScanMultipleFilter(List names) { _names = names; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken c in current) { JToken value = c; while (true) { JContainer container = value as JContainer; value = PathFilter.GetNextScanValue(c, container, value); if (value == null) { break; } if (!(value is JProperty property)) { continue; } foreach (string name in _names) { if (property.Name == name) { yield return property.Value; } } } } } } } namespace Newtonsoft.Json.Converters { internal class BinaryConverter : JsonConverter { private const string BinaryTypeName = "System.Data.Linq.Binary"; private const string BinaryToArrayName = "ToArray"; private static ReflectionObject? _reflectionObject; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } byte[] byteArray = GetByteArray(value); writer.WriteValue(byteArray); } private byte[] GetByteArray(object value) { if (value.GetType().FullName == "System.Data.Linq.Binary") { EnsureReflectionObject(value.GetType()); return (byte[])_reflectionObject.GetValue(value, "ToArray"); } if (value is SqlBinary sqlBinary) { return sqlBinary.Value; } throw new JsonSerializationException("Unexpected value type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } private static void EnsureReflectionObject(Type t) { if (_reflectionObject == null) { _reflectionObject = ReflectionObject.Create(t, t.GetConstructor(new Type[1] { typeof(byte[]) }), "ToArray"); } } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { if (!ReflectionUtils.IsNullable(objectType)) { throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } return null; } byte[] array; if (reader.TokenType == JsonToken.StartArray) { array = ReadByteArray(reader); } else { if (reader.TokenType != JsonToken.String) { throw JsonSerializationException.Create(reader, "Unexpected token parsing binary. Expected String or StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } array = Convert.FromBase64String(reader.Value.ToString()); } Type type = (ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType); if (type.FullName == "System.Data.Linq.Binary") { EnsureReflectionObject(type); return _reflectionObject.Creator(array); } if (type == typeof(SqlBinary)) { return new SqlBinary(array); } throw JsonSerializationException.Create(reader, "Unexpected object type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, objectType)); } private byte[] ReadByteArray(JsonReader reader) { List list = new List(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.Integer: list.Add(Convert.ToByte(reader.Value, CultureInfo.InvariantCulture)); break; case JsonToken.EndArray: return list.ToArray(); default: throw JsonSerializationException.Create(reader, "Unexpected token when reading bytes: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); case JsonToken.Comment: break; } } throw JsonSerializationException.Create(reader, "Unexpected end when reading bytes."); } public override bool CanConvert(Type objectType) { if (objectType.FullName == "System.Data.Linq.Binary") { return true; } if (objectType == typeof(SqlBinary) || objectType == typeof(SqlBinary?)) { return true; } return false; } } [Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] internal class BsonObjectIdConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { BsonObjectId bsonObjectId = (BsonObjectId)value; if (writer is BsonWriter bsonWriter) { bsonWriter.WriteObjectId(bsonObjectId.Value); } else { writer.WriteValue(bsonObjectId.Value); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType != JsonToken.Bytes) { throw new JsonSerializationException("Expected Bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } return new BsonObjectId((byte[])reader.Value); } public override bool CanConvert(Type objectType) { return objectType == typeof(BsonObjectId); } } internal abstract class CustomCreationConverter : JsonConverter { public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { throw new NotSupportedException("CustomCreationConverter should only be used while deserializing."); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } T val = Create(objectType); if (val == null) { throw new JsonSerializationException("No object created."); } serializer.Populate(reader, val); return val; } public abstract T Create(Type objectType); public override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } internal class DataSetConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } DataSet obj = (DataSet)value; DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; DataTableConverter dataTableConverter = new DataTableConverter(); writer.WriteStartObject(); foreach (DataTable table in obj.Tables) { writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName(table.TableName) : table.TableName); dataTableConverter.WriteJson(writer, table, serializer); } writer.WriteEndObject(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } DataSet dataSet = ((objectType == typeof(DataSet)) ? new DataSet() : ((DataSet)Activator.CreateInstance(objectType))); DataTableConverter dataTableConverter = new DataTableConverter(); reader.ReadAndAssert(); while (reader.TokenType == JsonToken.PropertyName) { DataTable dataTable = dataSet.Tables[(string)reader.Value]; bool num = dataTable != null; dataTable = (DataTable)dataTableConverter.ReadJson(reader, typeof(DataTable), dataTable, serializer); if (!num) { dataSet.Tables.Add(dataTable); } reader.ReadAndAssert(); } return dataSet; } public override bool CanConvert(Type valueType) { return typeof(DataSet).IsAssignableFrom(valueType); } } internal class DataTableConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } DataTable obj = (DataTable)value; DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartArray(); foreach (DataRow row in obj.Rows) { writer.WriteStartObject(); foreach (DataColumn column in row.Table.Columns) { object obj2 = row[column]; if (serializer.NullValueHandling != NullValueHandling.Ignore || (obj2 != null && obj2 != DBNull.Value)) { writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName(column.ColumnName) : column.ColumnName); serializer.Serialize(writer, obj2); } } writer.WriteEndObject(); } writer.WriteEndArray(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } DataTable dataTable = existingValue as DataTable; if (dataTable == null) { dataTable = ((objectType == typeof(DataTable)) ? new DataTable() : ((DataTable)Activator.CreateInstance(objectType))); } if (reader.TokenType == JsonToken.PropertyName) { dataTable.TableName = (string)reader.Value; reader.ReadAndAssert(); if (reader.TokenType == JsonToken.Null) { return dataTable; } } if (reader.TokenType != JsonToken.StartArray) { throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable. Expected StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } reader.ReadAndAssert(); while (reader.TokenType != JsonToken.EndArray) { CreateRow(reader, dataTable, serializer); reader.ReadAndAssert(); } return dataTable; } private static void CreateRow(JsonReader reader, DataTable dt, JsonSerializer serializer) { DataRow dataRow = dt.NewRow(); reader.ReadAndAssert(); while (reader.TokenType == JsonToken.PropertyName) { string text = (string)reader.Value; reader.ReadAndAssert(); DataColumn dataColumn = dt.Columns[text]; if (dataColumn == null) { Type columnDataType = GetColumnDataType(reader); dataColumn = new DataColumn(text, columnDataType); dt.Columns.Add(dataColumn); } if (dataColumn.DataType == typeof(DataTable)) { if (reader.TokenType == JsonToken.StartArray) { reader.ReadAndAssert(); } DataTable dataTable = new DataTable(); while (reader.TokenType != JsonToken.EndArray) { CreateRow(reader, dataTable, serializer); reader.ReadAndAssert(); } dataRow[text] = dataTable; } else if (dataColumn.DataType.IsArray && dataColumn.DataType != typeof(byte[])) { if (reader.TokenType == JsonToken.StartArray) { reader.ReadAndAssert(); } List list = new List(); while (reader.TokenType != JsonToken.EndArray) { list.Add(reader.Value); reader.ReadAndAssert(); } Array array = Array.CreateInstance(dataColumn.DataType.GetElementType(), list.Count); ((ICollection)list).CopyTo(array, 0); dataRow[text] = array; } else { object value = ((reader.Value != null) ? (serializer.Deserialize(reader, dataColumn.DataType) ?? DBNull.Value) : DBNull.Value); dataRow[text] = value; } reader.ReadAndAssert(); } dataRow.EndEdit(); dt.Rows.Add(dataRow); } private static Type GetColumnDataType(JsonReader reader) { JsonToken tokenType = reader.TokenType; switch (tokenType) { case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: return reader.ValueType; case JsonToken.Null: case JsonToken.Undefined: case JsonToken.EndArray: return typeof(string); case JsonToken.StartArray: reader.ReadAndAssert(); if (reader.TokenType == JsonToken.StartObject) { return typeof(DataTable); } return GetColumnDataType(reader).MakeArrayType(); default: throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable: {0}".FormatWith(CultureInfo.InvariantCulture, tokenType)); } } public override bool CanConvert(Type valueType) { return typeof(DataTable).IsAssignableFrom(valueType); } } internal abstract class DateTimeConverterBase : JsonConverter { public override bool CanConvert(Type objectType) { if (objectType == typeof(DateTime) || objectType == typeof(DateTime?)) { return true; } if (objectType == typeof(DateTimeOffset) || objectType == typeof(DateTimeOffset?)) { return true; } return false; } } internal class DiscriminatedUnionConverter : JsonConverter { internal class Union { public readonly FSharpFunction TagReader; public readonly List Cases; public Union(FSharpFunction tagReader, List cases) { TagReader = tagReader; Cases = cases; } } internal class UnionCase { public readonly int Tag; public readonly string Name; public readonly PropertyInfo[] Fields; public readonly FSharpFunction FieldReader; public readonly FSharpFunction Constructor; public UnionCase(int tag, string name, PropertyInfo[] fields, FSharpFunction fieldReader, FSharpFunction constructor) { Tag = tag; Name = name; Fields = fields; FieldReader = fieldReader; Constructor = constructor; } } private const string CasePropertyName = "Case"; private const string FieldsPropertyName = "Fields"; private static readonly ThreadSafeStore UnionCache = new ThreadSafeStore(CreateUnion); private static readonly ThreadSafeStore UnionTypeLookupCache = new ThreadSafeStore(CreateUnionTypeLookup); private static Type CreateUnionTypeLookup(Type t) { object arg = ((object[])FSharpUtils.Instance.GetUnionCases(null, t, null)).First(); return (Type)FSharpUtils.Instance.GetUnionCaseInfoDeclaringType(arg); } private static Union CreateUnion(Type t) { Union union = new Union((FSharpFunction)FSharpUtils.Instance.PreComputeUnionTagReader(null, t, null), new List()); object[] array = (object[])FSharpUtils.Instance.GetUnionCases(null, t, null); foreach (object obj in array) { UnionCase item = new UnionCase((int)FSharpUtils.Instance.GetUnionCaseInfoTag(obj), (string)FSharpUtils.Instance.GetUnionCaseInfoName(obj), (PropertyInfo[])FSharpUtils.Instance.GetUnionCaseInfoFields(obj), (FSharpFunction)FSharpUtils.Instance.PreComputeUnionReader(null, obj, null), (FSharpFunction)FSharpUtils.Instance.PreComputeUnionConstructor(null, obj, null)); union.Cases.Add(item); } return union; } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; Type key = UnionTypeLookupCache.Get(value.GetType()); Union union = UnionCache.Get(key); int tag = (int)union.TagReader.Invoke(value); UnionCase unionCase = union.Cases.Single((UnionCase c) => c.Tag == tag); writer.WriteStartObject(); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Case") : "Case"); writer.WriteValue(unionCase.Name); if (unionCase.Fields != null && unionCase.Fields.Length != 0) { object[] obj = (object[])unionCase.FieldReader.Invoke(value); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Fields") : "Fields"); writer.WriteStartArray(); object[] array = obj; foreach (object value2 in array) { serializer.Serialize(writer, value2); } writer.WriteEndArray(); } writer.WriteEndObject(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } UnionCase unionCase = null; string caseName = null; JArray jArray = null; reader.ReadAndAssert(); while (reader.TokenType == JsonToken.PropertyName) { string text = reader.Value.ToString(); if (string.Equals(text, "Case", StringComparison.OrdinalIgnoreCase)) { reader.ReadAndAssert(); Union union = UnionCache.Get(objectType); caseName = reader.Value.ToString(); unionCase = union.Cases.SingleOrDefault((UnionCase c) => c.Name == caseName); if (unionCase == null) { throw JsonSerializationException.Create(reader, "No union type found with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName)); } } else { if (!string.Equals(text, "Fields", StringComparison.OrdinalIgnoreCase)) { throw JsonSerializationException.Create(reader, "Unexpected property '{0}' found when reading union.".FormatWith(CultureInfo.InvariantCulture, text)); } reader.ReadAndAssert(); if (reader.TokenType != JsonToken.StartArray) { throw JsonSerializationException.Create(reader, "Union fields must been an array."); } jArray = (JArray)JToken.ReadFrom(reader); } reader.ReadAndAssert(); } if (unionCase == null) { throw JsonSerializationException.Create(reader, "No '{0}' property with union name found.".FormatWith(CultureInfo.InvariantCulture, "Case")); } object[] array = new object[unionCase.Fields.Length]; if (unionCase.Fields.Length != 0 && jArray == null) { throw JsonSerializationException.Create(reader, "No '{0}' property with union fields found.".FormatWith(CultureInfo.InvariantCulture, "Fields")); } if (jArray != null) { if (unionCase.Fields.Length != jArray.Count) { throw JsonSerializationException.Create(reader, "The number of field values does not match the number of properties defined by union '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName)); } for (int i = 0; i < jArray.Count; i++) { JToken jToken = jArray[i]; PropertyInfo propertyInfo = unionCase.Fields[i]; array[i] = jToken.ToObject(propertyInfo.PropertyType, serializer); } } object[] args = new object[1] { array }; return unionCase.Constructor.Invoke(args); } public override bool CanConvert(Type objectType) { if (typeof(IEnumerable).IsAssignableFrom(objectType)) { return false; } object[] customAttributes = objectType.GetCustomAttributes(inherit: true); bool flag = false; object[] array = customAttributes; for (int i = 0; i < array.Length; i++) { Type type = array[i].GetType(); if (type.FullName == "Microsoft.FSharp.Core.CompilationMappingAttribute") { FSharpUtils.EnsureInitialized(type.Assembly()); flag = true; break; } } if (!flag) { return false; } return (bool)FSharpUtils.Instance.IsUnion(null, objectType, null); } } internal class EntityKeyMemberConverter : JsonConverter { private const string EntityKeyMemberFullTypeName = "System.Data.EntityKeyMember"; private const string KeyPropertyName = "Key"; private const string TypePropertyName = "Type"; private const string ValuePropertyName = "Value"; private static ReflectionObject? _reflectionObject; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } EnsureReflectionObject(value.GetType()); DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; string value2 = (string)_reflectionObject.GetValue(value, "Key"); object value3 = _reflectionObject.GetValue(value, "Value"); Type type = value3?.GetType(); writer.WriteStartObject(); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Key") : "Key"); writer.WriteValue(value2); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Type") : "Type"); writer.WriteValue(type?.FullName); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Value") : "Value"); if (type != null) { if (JsonSerializerInternalWriter.TryConvertToString(value3, type, out string s)) { writer.WriteValue(s); } else { writer.WriteValue(value3); } } else { writer.WriteNull(); } writer.WriteEndObject(); } private static void ReadAndAssertProperty(JsonReader reader, string propertyName) { reader.ReadAndAssert(); if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value?.ToString(), propertyName, StringComparison.OrdinalIgnoreCase)) { throw new JsonSerializationException("Expected JSON property '{0}'.".FormatWith(CultureInfo.InvariantCulture, propertyName)); } } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { EnsureReflectionObject(objectType); object obj = _reflectionObject.Creator(); ReadAndAssertProperty(reader, "Key"); reader.ReadAndAssert(); _reflectionObject.SetValue(obj, "Key", reader.Value?.ToString()); ReadAndAssertProperty(reader, "Type"); reader.ReadAndAssert(); Type type = Type.GetType(reader.Value?.ToString()); ReadAndAssertProperty(reader, "Value"); reader.ReadAndAssert(); _reflectionObject.SetValue(obj, "Value", serializer.Deserialize(reader, type)); reader.ReadAndAssert(); return obj; } private static void EnsureReflectionObject(Type objectType) { if (_reflectionObject == null) { _reflectionObject = ReflectionObject.Create(objectType, "Key", "Value"); } } public override bool CanConvert(Type objectType) { return objectType.AssignableToTypeName("System.Data.EntityKeyMember", searchInterfaces: false); } } internal class ExpandoObjectConverter : JsonConverter { public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { return ReadValue(reader); } private object? ReadValue(JsonReader reader) { if (!reader.MoveToContent()) { throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); } switch (reader.TokenType) { case JsonToken.StartObject: return ReadObject(reader); case JsonToken.StartArray: return ReadList(reader); default: if (JsonTokenUtils.IsPrimitiveToken(reader.TokenType)) { return reader.Value; } throw JsonSerializationException.Create(reader, "Unexpected token when converting ExpandoObject: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } private object ReadList(JsonReader reader) { IList list = new List(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.EndArray: return list; case JsonToken.Comment: continue; } object item = ReadValue(reader); list.Add(item); } throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); } private object ReadObject(JsonReader reader) { IDictionary dictionary = new ExpandoObject(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: { string key = reader.Value.ToString(); if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); } object value = ReadValue(reader); dictionary[key] = value; break; } case JsonToken.EndObject: return dictionary; } } throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); } public override bool CanConvert(Type objectType) { return objectType == typeof(ExpandoObject); } } internal class IsoDateTimeConverter : DateTimeConverterBase { private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; private string? _dateTimeFormat; private CultureInfo? _culture; public DateTimeStyles DateTimeStyles { get { return _dateTimeStyles; } set { _dateTimeStyles = value; } } public string? DateTimeFormat { get { return _dateTimeFormat ?? string.Empty; } set { _dateTimeFormat = (StringUtils.IsNullOrEmpty(value) ? null : value); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.CurrentCulture; } set { _culture = value; } } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { string value2; if (value is DateTime dateTime) { if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) { dateTime = dateTime.ToUniversalTime(); } value2 = dateTime.ToString(_dateTimeFormat ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK", Culture); } else { if (!(value is DateTimeOffset dateTimeOffset)) { throw new JsonSerializationException("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value))); } if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) { dateTimeOffset = dateTimeOffset.ToUniversalTime(); } value2 = dateTimeOffset.ToString(_dateTimeFormat ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK", Culture); } writer.WriteValue(value2); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = ReflectionUtils.IsNullableType(objectType); if (reader.TokenType == JsonToken.Null) { if (!flag) { throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } return null; } Type type = (flag ? Nullable.GetUnderlyingType(objectType) : objectType); if (reader.TokenType == JsonToken.Date) { if (type == typeof(DateTimeOffset)) { if (!(reader.Value is DateTimeOffset)) { return new DateTimeOffset((DateTime)reader.Value); } return reader.Value; } if (reader.Value is DateTimeOffset dateTimeOffset) { return dateTimeOffset.DateTime; } return reader.Value; } if (reader.TokenType != JsonToken.String) { throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } string text = reader.Value?.ToString(); if (StringUtils.IsNullOrEmpty(text) && flag) { return null; } if (type == typeof(DateTimeOffset)) { if (!StringUtils.IsNullOrEmpty(_dateTimeFormat)) { return DateTimeOffset.ParseExact(text, _dateTimeFormat, Culture, _dateTimeStyles); } return DateTimeOffset.Parse(text, Culture, _dateTimeStyles); } if (!StringUtils.IsNullOrEmpty(_dateTimeFormat)) { return DateTime.ParseExact(text, _dateTimeFormat, Culture, _dateTimeStyles); } return DateTime.Parse(text, Culture, _dateTimeStyles); } } internal class JavaScriptDateTimeConverter : DateTimeConverterBase { public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { long value2; if (value is DateTime dateTime) { value2 = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTime.ToUniversalTime()); } else { if (!(value is DateTimeOffset dateTimeOffset)) { throw new JsonSerializationException("Expected date object value."); } value2 = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTimeOffset.ToUniversalTime().UtcDateTime); } writer.WriteStartConstructor("Date"); writer.WriteValue(value2); writer.WriteEndConstructor(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { if (!ReflectionUtils.IsNullable(objectType)) { throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } return null; } if (reader.TokenType != JsonToken.StartConstructor || !string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing date. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value)); } if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime dateTime, out string errorMessage)) { throw JsonSerializationException.Create(reader, errorMessage); } if ((ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType) == typeof(DateTimeOffset)) { return new DateTimeOffset(dateTime); } return dateTime; } } internal class KeyValuePairConverter : JsonConverter { private const string KeyName = "Key"; private const string ValueName = "Value"; private static readonly ThreadSafeStore ReflectionObjectPerType = new ThreadSafeStore(InitializeReflectionObject); private static ReflectionObject InitializeReflectionObject(Type t) { Type[] genericArguments = t.GetGenericArguments(); Type type = ((IList)genericArguments)[0]; Type type2 = ((IList)genericArguments)[1]; return ReflectionObject.Create(t, t.GetConstructor(new Type[2] { type, type2 }), "Key", "Value"); } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } ReflectionObject reflectionObject = ReflectionObjectPerType.Get(value.GetType()); DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartObject(); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Key") : "Key"); serializer.Serialize(writer, reflectionObject.GetValue(value, "Key"), reflectionObject.GetType("Key")); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Value") : "Value"); serializer.Serialize(writer, reflectionObject.GetValue(value, "Value"), reflectionObject.GetType("Value")); writer.WriteEndObject(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { if (!ReflectionUtils.IsNullableType(objectType)) { throw JsonSerializationException.Create(reader, "Cannot convert null value to KeyValuePair."); } return null; } object obj = null; object obj2 = null; reader.ReadAndAssert(); Type key = (ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType); ReflectionObject reflectionObject = ReflectionObjectPerType.Get(key); JsonContract jsonContract = serializer.ContractResolver.ResolveContract(reflectionObject.GetType("Key")); JsonContract jsonContract2 = serializer.ContractResolver.ResolveContract(reflectionObject.GetType("Value")); while (reader.TokenType == JsonToken.PropertyName) { string a = reader.Value.ToString(); if (string.Equals(a, "Key", StringComparison.OrdinalIgnoreCase)) { reader.ReadForTypeAndAssert(jsonContract, hasConverter: false); obj = serializer.Deserialize(reader, jsonContract.UnderlyingType); } else if (string.Equals(a, "Value", StringComparison.OrdinalIgnoreCase)) { reader.ReadForTypeAndAssert(jsonContract2, hasConverter: false); obj2 = serializer.Deserialize(reader, jsonContract2.UnderlyingType); } else { reader.Skip(); } reader.ReadAndAssert(); } return reflectionObject.Creator(obj, obj2); } public override bool CanConvert(Type objectType) { Type type = (ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType); if (type.IsValueType() && type.IsGenericType()) { return type.GetGenericTypeDefinition() == typeof(KeyValuePair<, >); } return false; } } internal class RegexConverter : JsonConverter { private const string PatternName = "Pattern"; private const string OptionsName = "Options"; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } Regex regex = (Regex)value; if (writer is BsonWriter writer2) { WriteBson(writer2, regex); } else { WriteJson(writer, regex, serializer); } } private bool HasFlag(RegexOptions options, RegexOptions flag) { return (options & flag) == flag; } private void WriteBson(BsonWriter writer, Regex regex) { string text = null; if (HasFlag(regex.Options, RegexOptions.IgnoreCase)) { text += "i"; } if (HasFlag(regex.Options, RegexOptions.Multiline)) { text += "m"; } if (HasFlag(regex.Options, RegexOptions.Singleline)) { text += "s"; } text += "u"; if (HasFlag(regex.Options, RegexOptions.ExplicitCapture)) { text += "x"; } writer.WriteRegex(regex.ToString(), text); } private void WriteJson(JsonWriter writer, Regex regex, JsonSerializer serializer) { DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartObject(); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Pattern") : "Pattern"); writer.WriteValue(regex.ToString()); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Options") : "Options"); serializer.Serialize(writer, regex.Options); writer.WriteEndObject(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { return reader.TokenType switch { JsonToken.StartObject => ReadRegexObject(reader, serializer), JsonToken.String => ReadRegexString(reader), JsonToken.Null => null, _ => throw JsonSerializationException.Create(reader, "Unexpected token when reading Regex."), }; } private object ReadRegexString(JsonReader reader) { string text = (string)reader.Value; if (text.Length > 0 && text[0] == '/') { int num = text.LastIndexOf('/'); if (num > 0) { string pattern = text.Substring(1, num - 1); RegexOptions regexOptions = MiscellaneousUtils.GetRegexOptions(text.Substring(num + 1)); return new Regex(pattern, regexOptions); } } throw JsonSerializationException.Create(reader, "Regex pattern must be enclosed by slashes."); } private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer) { string text = null; RegexOptions? regexOptions = null; while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: { string a = reader.Value.ToString(); if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex."); } if (string.Equals(a, "Pattern", StringComparison.OrdinalIgnoreCase)) { text = (string)reader.Value; } else if (string.Equals(a, "Options", StringComparison.OrdinalIgnoreCase)) { regexOptions = serializer.Deserialize(reader); } else { reader.Skip(); } break; } case JsonToken.EndObject: if (text == null) { throw JsonSerializationException.Create(reader, "Error deserializing Regex. No pattern found."); } return new Regex(text, regexOptions.GetValueOrDefault()); } } throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex."); } public override bool CanConvert(Type objectType) { if (objectType.Name == "Regex") { return IsRegex(objectType); } return false; } [MethodImpl(MethodImplOptions.NoInlining)] private bool IsRegex(Type objectType) { return objectType == typeof(Regex); } } internal class StringEnumConverter : JsonConverter { [Obsolete("StringEnumConverter.CamelCaseText is obsolete. Set StringEnumConverter.NamingStrategy with CamelCaseNamingStrategy instead.")] public bool CamelCaseText { get { if (!(NamingStrategy is CamelCaseNamingStrategy)) { return false; } return true; } set { if (value) { if (!(NamingStrategy is CamelCaseNamingStrategy)) { NamingStrategy = new CamelCaseNamingStrategy(); } } else if (NamingStrategy is CamelCaseNamingStrategy) { NamingStrategy = null; } } } public NamingStrategy? NamingStrategy { get; set; } public bool AllowIntegerValues { get; set; } = true; public StringEnumConverter() { } [Obsolete("StringEnumConverter(bool) is obsolete. Create a converter with StringEnumConverter(NamingStrategy, bool) instead.")] public StringEnumConverter(bool camelCaseText) { if (camelCaseText) { NamingStrategy = new CamelCaseNamingStrategy(); } } public StringEnumConverter(NamingStrategy namingStrategy, bool allowIntegerValues = true) { NamingStrategy = namingStrategy; AllowIntegerValues = allowIntegerValues; } public StringEnumConverter(Type namingStrategyType) { ValidationUtils.ArgumentNotNull(namingStrategyType, "namingStrategyType"); NamingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(namingStrategyType, null); } public StringEnumConverter(Type namingStrategyType, object[] namingStrategyParameters) { ValidationUtils.ArgumentNotNull(namingStrategyType, "namingStrategyType"); NamingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(namingStrategyType, namingStrategyParameters); } public StringEnumConverter(Type namingStrategyType, object[] namingStrategyParameters, bool allowIntegerValues) { ValidationUtils.ArgumentNotNull(namingStrategyType, "namingStrategyType"); NamingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(namingStrategyType, namingStrategyParameters); AllowIntegerValues = allowIntegerValues; } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } Enum @enum = (Enum)value; if (!EnumUtils.TryToString(@enum.GetType(), value, NamingStrategy, out string name)) { if (!AllowIntegerValues) { throw JsonSerializationException.Create(null, writer.ContainerPath, "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, @enum.ToString("D")), null); } writer.WriteValue(value); } else { writer.WriteValue(name); } } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { if (!ReflectionUtils.IsNullableType(objectType)) { throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } return null; } bool flag = ReflectionUtils.IsNullableType(objectType); Type type = (flag ? Nullable.GetUnderlyingType(objectType) : objectType); try { if (reader.TokenType == JsonToken.String) { string value = reader.Value?.ToString(); if (StringUtils.IsNullOrEmpty(value) && flag) { return null; } return EnumUtils.ParseEnum(type, NamingStrategy, value, !AllowIntegerValues); } if (reader.TokenType == JsonToken.Integer) { if (!AllowIntegerValues) { throw JsonSerializationException.Create(reader, "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, reader.Value)); } return ConvertUtils.ConvertOrCast(reader.Value, CultureInfo.InvariantCulture, type); } } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(reader.Value), objectType), ex); } throw JsonSerializationException.Create(reader, "Unexpected token {0} when parsing enum.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } public override bool CanConvert(Type objectType) { return (ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType).IsEnum(); } } internal class UnixDateTimeConverter : DateTimeConverterBase { internal static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public bool AllowPreEpoch { get; set; } public UnixDateTimeConverter() : this(allowPreEpoch: false) { } public UnixDateTimeConverter(bool allowPreEpoch) { AllowPreEpoch = allowPreEpoch; } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { long num; if (value is DateTime dateTime) { num = (long)(dateTime.ToUniversalTime() - UnixEpoch).TotalSeconds; } else { if (!(value is DateTimeOffset dateTimeOffset)) { throw new JsonSerializationException("Expected date object value."); } num = (long)(dateTimeOffset.ToUniversalTime() - UnixEpoch).TotalSeconds; } if (!AllowPreEpoch && num < 0) { throw new JsonSerializationException("Cannot convert date value that is before Unix epoch of 00:00:00 UTC on 1 January 1970."); } writer.WriteValue(num); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = ReflectionUtils.IsNullable(objectType); if (reader.TokenType == JsonToken.Null) { if (!flag) { throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } return null; } long result; if (reader.TokenType == JsonToken.Integer) { result = (long)reader.Value; } else { if (reader.TokenType != JsonToken.String) { throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected Integer or String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } if (!long.TryParse((string)reader.Value, out result)) { throw JsonSerializationException.Create(reader, "Cannot convert invalid value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } } if (AllowPreEpoch || result >= 0) { DateTime dateTime = UnixEpoch.AddSeconds(result); if ((flag ? Nullable.GetUnderlyingType(objectType) : objectType) == typeof(DateTimeOffset)) { return new DateTimeOffset(dateTime, TimeSpan.Zero); } return dateTime; } throw JsonSerializationException.Create(reader, "Cannot convert value that is before Unix epoch of 00:00:00 UTC on 1 January 1970 to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } } internal class VersionConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } if (value is Version) { writer.WriteValue(value.ToString()); return; } throw new JsonSerializationException("Expected Version object value"); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } if (reader.TokenType == JsonToken.String) { try { return new Version((string)reader.Value); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error parsing version string: {0}".FormatWith(CultureInfo.InvariantCulture, reader.Value), ex); } } throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing version. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value)); } public override bool CanConvert(Type objectType) { return objectType == typeof(Version); } } internal class XmlDocumentWrapper : XmlNodeWrapper, IXmlDocument, IXmlNode { private readonly XmlDocument _document; public IXmlElement? DocumentElement { get { if (_document.DocumentElement == null) { return null; } return new XmlElementWrapper(_document.DocumentElement); } } public XmlDocumentWrapper(XmlDocument document) : base(document) { _document = document; } public IXmlNode CreateComment(string? data) { return new XmlNodeWrapper(_document.CreateComment(data)); } public IXmlNode CreateTextNode(string? text) { return new XmlNodeWrapper(_document.CreateTextNode(text)); } public IXmlNode CreateCDataSection(string? data) { return new XmlNodeWrapper(_document.CreateCDataSection(data)); } public IXmlNode CreateWhitespace(string? text) { return new XmlNodeWrapper(_document.CreateWhitespace(text)); } public IXmlNode CreateSignificantWhitespace(string? text) { return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text)); } public IXmlNode CreateXmlDeclaration(string version, string? encoding, string? standalone) { return new XmlDeclarationWrapper(_document.CreateXmlDeclaration(version, encoding, standalone)); } public IXmlNode CreateXmlDocumentType(string name, string? publicId, string? systemId, string? internalSubset) { return new XmlDocumentTypeWrapper(_document.CreateDocumentType(name, publicId, systemId, null)); } public IXmlNode CreateProcessingInstruction(string target, string data) { return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data)); } public IXmlElement CreateElement(string elementName) { return new XmlElementWrapper(_document.CreateElement(elementName)); } public IXmlElement CreateElement(string qualifiedName, string namespaceUri) { return new XmlElementWrapper(_document.CreateElement(qualifiedName, namespaceUri)); } public IXmlNode CreateAttribute(string name, string? value) { return new XmlNodeWrapper(_document.CreateAttribute(name)) { Value = value }; } public IXmlNode CreateAttribute(string qualifiedName, string? namespaceUri, string? value) { return new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceUri)) { Value = value }; } } internal class XmlElementWrapper : XmlNodeWrapper, IXmlElement, IXmlNode { private readonly XmlElement _element; public bool IsEmpty => _element.IsEmpty; public XmlElementWrapper(XmlElement element) : base(element) { _element = element; } public void SetAttributeNode(IXmlNode attribute) { XmlNodeWrapper xmlNodeWrapper = (XmlNodeWrapper)attribute; _element.SetAttributeNode((XmlAttribute)xmlNodeWrapper.WrappedNode); } public string? GetPrefixOfNamespace(string namespaceUri) { return _element.GetPrefixOfNamespace(namespaceUri); } } internal class XmlDeclarationWrapper : XmlNodeWrapper, IXmlDeclaration, IXmlNode { private readonly XmlDeclaration _declaration; public string? Version => _declaration.Version; public string? Encoding { get { return _declaration.Encoding; } set { _declaration.Encoding = value; } } public string? Standalone { get { return _declaration.Standalone; } set { _declaration.Standalone = value; } } public XmlDeclarationWrapper(XmlDeclaration declaration) : base(declaration) { _declaration = declaration; } } internal class XmlDocumentTypeWrapper : XmlNodeWrapper, IXmlDocumentType, IXmlNode { private readonly XmlDocumentType _documentType; public string Name => _documentType.Name; public string? System => _documentType.SystemId; public string? Public => _documentType.PublicId; public string? InternalSubset => _documentType.InternalSubset; public override string? LocalName => "DOCTYPE"; public XmlDocumentTypeWrapper(XmlDocumentType documentType) : base(documentType) { _documentType = documentType; } } internal class XmlNodeWrapper : IXmlNode { private readonly XmlNode _node; private List? _childNodes; private List? _attributes; public object? WrappedNode => _node; public XmlNodeType NodeType => _node.NodeType; public virtual string? LocalName => _node.LocalName; public List ChildNodes { get { if (_childNodes == null) { if (!_node.HasChildNodes) { _childNodes = XmlNodeConverter.EmptyChildNodes; } else { _childNodes = new List(_node.ChildNodes.Count); foreach (XmlNode childNode in _node.ChildNodes) { _childNodes.Add(WrapNode(childNode)); } } } return _childNodes; } } protected virtual bool HasChildNodes => _node.HasChildNodes; public List Attributes { get { if (_attributes == null) { if (!HasAttributes) { _attributes = XmlNodeConverter.EmptyChildNodes; } else { _attributes = new List(_node.Attributes.Count); foreach (XmlAttribute attribute in _node.Attributes) { _attributes.Add(WrapNode(attribute)); } } } return _attributes; } } private bool HasAttributes { get { if (_node is XmlElement xmlElement) { return xmlElement.HasAttributes; } XmlAttributeCollection? attributes = _node.Attributes; if (attributes == null) { return false; } return attributes.Count > 0; } } public IXmlNode? ParentNode { get { XmlNode xmlNode = ((_node is XmlAttribute xmlAttribute) ? xmlAttribute.OwnerElement : _node.ParentNode); if (xmlNode == null) { return null; } return WrapNode(xmlNode); } } public string? Value { get { return _node.Value; } set { _node.Value = value; } } public string? NamespaceUri => _node.NamespaceURI; public XmlNodeWrapper(XmlNode node) { _node = node; } internal static IXmlNode WrapNode(XmlNode node) { return node.NodeType switch { XmlNodeType.Element => new XmlElementWrapper((XmlElement)node), XmlNodeType.XmlDeclaration => new XmlDeclarationWrapper((XmlDeclaration)node), XmlNodeType.DocumentType => new XmlDocumentTypeWrapper((XmlDocumentType)node), _ => new XmlNodeWrapper(node), }; } public IXmlNode AppendChild(IXmlNode newChild) { XmlNodeWrapper xmlNodeWrapper = (XmlNodeWrapper)newChild; _node.AppendChild(xmlNodeWrapper._node); _childNodes = null; _attributes = null; return newChild; } } internal interface IXmlDocument : IXmlNode { IXmlElement? DocumentElement { get; } IXmlNode CreateComment(string? text); IXmlNode CreateTextNode(string? text); IXmlNode CreateCDataSection(string? data); IXmlNode CreateWhitespace(string? text); IXmlNode CreateSignificantWhitespace(string? text); IXmlNode CreateXmlDeclaration(string version, string? encoding, string? standalone); IXmlNode CreateXmlDocumentType(string name, string? publicId, string? systemId, string? internalSubset); IXmlNode CreateProcessingInstruction(string target, string data); IXmlElement CreateElement(string elementName); IXmlElement CreateElement(string qualifiedName, string namespaceUri); IXmlNode CreateAttribute(string name, string value); IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value); } internal interface IXmlDeclaration : IXmlNode { string? Version { get; } string? Encoding { get; set; } string? Standalone { get; set; } } internal interface IXmlDocumentType : IXmlNode { string Name { get; } string? System { get; } string? Public { get; } string? InternalSubset { get; } } internal interface IXmlElement : IXmlNode { bool IsEmpty { get; } void SetAttributeNode(IXmlNode attribute); string? GetPrefixOfNamespace(string namespaceUri); } internal interface IXmlNode { XmlNodeType NodeType { get; } string? LocalName { get; } List ChildNodes { get; } List Attributes { get; } IXmlNode? ParentNode { get; } string? Value { get; set; } string? NamespaceUri { get; } object? WrappedNode { get; } IXmlNode AppendChild(IXmlNode newChild); } internal class XDeclarationWrapper : XObjectWrapper, IXmlDeclaration, IXmlNode { internal XDeclaration Declaration { get; } public override XmlNodeType NodeType => XmlNodeType.XmlDeclaration; public string? Version => Declaration.Version; public string? Encoding { get { return Declaration.Encoding; } set { Declaration.Encoding = value; } } public string? Standalone { get { return Declaration.Standalone; } set { Declaration.Standalone = value; } } public XDeclarationWrapper(XDeclaration declaration) : base(null) { Declaration = declaration; } } internal class XDocumentTypeWrapper : XObjectWrapper, IXmlDocumentType, IXmlNode { private readonly XDocumentType _documentType; public string Name => _documentType.Name; public string? System => _documentType.SystemId; public string? Public => _documentType.PublicId; public string? InternalSubset => _documentType.InternalSubset; public override string? LocalName => "DOCTYPE"; public XDocumentTypeWrapper(XDocumentType documentType) : base(documentType) { _documentType = documentType; } } internal class XDocumentWrapper : XContainerWrapper, IXmlDocument, IXmlNode { private XDocument Document => (XDocument)base.WrappedNode; public override List ChildNodes { get { List childNodes = base.ChildNodes; if (Document.Declaration != null && (childNodes.Count == 0 || childNodes[0].NodeType != XmlNodeType.XmlDeclaration)) { childNodes.Insert(0, new XDeclarationWrapper(Document.Declaration)); } return childNodes; } } protected override bool HasChildNodes { get { if (base.HasChildNodes) { return true; } return Document.Declaration != null; } } public IXmlElement? DocumentElement { get { if (Document.Root == null) { return null; } return new XElementWrapper(Document.Root); } } public XDocumentWrapper(XDocument document) : base(document) { } public IXmlNode CreateComment(string? text) { return new XObjectWrapper(new XComment(text)); } public IXmlNode CreateTextNode(string? text) { return new XObjectWrapper(new XText(text)); } public IXmlNode CreateCDataSection(string? data) { return new XObjectWrapper(new XCData(data)); } public IXmlNode CreateWhitespace(string? text) { return new XObjectWrapper(new XText(text)); } public IXmlNode CreateSignificantWhitespace(string? text) { return new XObjectWrapper(new XText(text)); } public IXmlNode CreateXmlDeclaration(string version, string? encoding, string? standalone) { return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone)); } public IXmlNode CreateXmlDocumentType(string name, string? publicId, string? systemId, string? internalSubset) { return new XDocumentTypeWrapper(new XDocumentType(name, publicId, systemId, internalSubset)); } public IXmlNode CreateProcessingInstruction(string target, string data) { return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data)); } public IXmlElement CreateElement(string elementName) { return new XElementWrapper(new XElement(elementName)); } public IXmlElement CreateElement(string qualifiedName, string namespaceUri) { return new XElementWrapper(new XElement(XName.Get(MiscellaneousUtils.GetLocalName(qualifiedName), namespaceUri))); } public IXmlNode CreateAttribute(string name, string value) { return new XAttributeWrapper(new XAttribute(name, value)); } public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value) { return new XAttributeWrapper(new XAttribute(XName.Get(MiscellaneousUtils.GetLocalName(qualifiedName), namespaceUri), value)); } public override IXmlNode AppendChild(IXmlNode newChild) { if (newChild is XDeclarationWrapper xDeclarationWrapper) { Document.Declaration = xDeclarationWrapper.Declaration; return xDeclarationWrapper; } return base.AppendChild(newChild); } } internal class XTextWrapper : XObjectWrapper { private XText Text => (XText)base.WrappedNode; public override string? Value { get { return Text.Value; } set { Text.Value = value ?? string.Empty; } } public override IXmlNode? ParentNode { get { if (Text.Parent == null) { return null; } return XContainerWrapper.WrapNode(Text.Parent); } } public XTextWrapper(XText text) : base(text) { } } internal class XCommentWrapper : XObjectWrapper { private XComment Text => (XComment)base.WrappedNode; public override string? Value { get { return Text.Value; } set { Text.Value = value ?? string.Empty; } } public override IXmlNode? ParentNode { get { if (Text.Parent == null) { return null; } return XContainerWrapper.WrapNode(Text.Parent); } } public XCommentWrapper(XComment text) : base(text) { } } internal class XProcessingInstructionWrapper : XObjectWrapper { private XProcessingInstruction ProcessingInstruction => (XProcessingInstruction)base.WrappedNode; public override string? LocalName => ProcessingInstruction.Target; public override string? Value { get { return ProcessingInstruction.Data; } set { ProcessingInstruction.Data = value ?? string.Empty; } } public XProcessingInstructionWrapper(XProcessingInstruction processingInstruction) : base(processingInstruction) { } } internal class XContainerWrapper : XObjectWrapper { private List? _childNodes; private XContainer Container => (XContainer)base.WrappedNode; public override List ChildNodes { get { if (_childNodes == null) { if (!HasChildNodes) { _childNodes = XmlNodeConverter.EmptyChildNodes; } else { _childNodes = new List(); foreach (XNode item in Container.Nodes()) { _childNodes.Add(WrapNode(item)); } } } return _childNodes; } } protected virtual bool HasChildNodes => Container.LastNode != null; public override IXmlNode? ParentNode { get { if (Container.Parent == null) { return null; } return WrapNode(Container.Parent); } } public XContainerWrapper(XContainer container) : base(container) { } internal static IXmlNode WrapNode(XObject node) { if (node is XDocument document) { return new XDocumentWrapper(document); } if (node is XElement element) { return new XElementWrapper(element); } if (node is XContainer container) { return new XContainerWrapper(container); } if (node is XProcessingInstruction processingInstruction) { return new XProcessingInstructionWrapper(processingInstruction); } if (node is XText text) { return new XTextWrapper(text); } if (node is XComment text2) { return new XCommentWrapper(text2); } if (node is XAttribute attribute) { return new XAttributeWrapper(attribute); } if (node is XDocumentType documentType) { return new XDocumentTypeWrapper(documentType); } return new XObjectWrapper(node); } public override IXmlNode AppendChild(IXmlNode newChild) { Container.Add(newChild.WrappedNode); _childNodes = null; return newChild; } } internal class XObjectWrapper : IXmlNode { private readonly XObject? _xmlObject; public object? WrappedNode => _xmlObject; public virtual XmlNodeType NodeType => _xmlObject?.NodeType ?? XmlNodeType.None; public virtual string? LocalName => null; public virtual List ChildNodes => XmlNodeConverter.EmptyChildNodes; public virtual List Attributes => XmlNodeConverter.EmptyChildNodes; public virtual IXmlNode? ParentNode => null; public virtual string? Value { get { return null; } set { throw new InvalidOperationException(); } } public virtual string? NamespaceUri => null; public XObjectWrapper(XObject? xmlObject) { _xmlObject = xmlObject; } public virtual IXmlNode AppendChild(IXmlNode newChild) { throw new InvalidOperationException(); } } internal class XAttributeWrapper : XObjectWrapper { private XAttribute Attribute => (XAttribute)base.WrappedNode; public override string? Value { get { return Attribute.Value; } set { Attribute.Value = value ?? string.Empty; } } public override string? LocalName => Attribute.Name.LocalName; public override string? NamespaceUri => Attribute.Name.NamespaceName; public override IXmlNode? ParentNode { get { if (Attribute.Parent == null) { return null; } return XContainerWrapper.WrapNode(Attribute.Parent); } } public XAttributeWrapper(XAttribute attribute) : base(attribute) { } } internal class XElementWrapper : XContainerWrapper, IXmlElement, IXmlNode { private List? _attributes; private XElement Element => (XElement)base.WrappedNode; public override List Attributes { get { if (_attributes == null) { if (!Element.HasAttributes && !HasImplicitNamespaceAttribute(NamespaceUri)) { _attributes = XmlNodeConverter.EmptyChildNodes; } else { _attributes = new List(); foreach (XAttribute item in Element.Attributes()) { _attributes.Add(new XAttributeWrapper(item)); } string namespaceUri = NamespaceUri; if (HasImplicitNamespaceAttribute(namespaceUri)) { _attributes.Insert(0, new XAttributeWrapper(new XAttribute("xmlns", namespaceUri))); } } } return _attributes; } } public override string? Value { get { return Element.Value; } set { Element.Value = value ?? string.Empty; } } public override string? LocalName => Element.Name.LocalName; public override string? NamespaceUri => Element.Name.NamespaceName; public bool IsEmpty => Element.IsEmpty; public XElementWrapper(XElement element) : base(element) { } public void SetAttributeNode(IXmlNode attribute) { XObjectWrapper xObjectWrapper = (XObjectWrapper)attribute; Element.Add(xObjectWrapper.WrappedNode); _attributes = null; } private bool HasImplicitNamespaceAttribute(string namespaceUri) { if (!StringUtils.IsNullOrEmpty(namespaceUri) && namespaceUri != ParentNode?.NamespaceUri && StringUtils.IsNullOrEmpty(GetPrefixOfNamespace(namespaceUri))) { bool flag = false; if (Element.HasAttributes) { foreach (XAttribute item in Element.Attributes()) { if (item.Name.LocalName == "xmlns" && StringUtils.IsNullOrEmpty(item.Name.NamespaceName) && item.Value == namespaceUri) { flag = true; } } } if (!flag) { return true; } } return false; } public override IXmlNode AppendChild(IXmlNode newChild) { IXmlNode result = base.AppendChild(newChild); _attributes = null; return result; } public string? GetPrefixOfNamespace(string namespaceUri) { return Element.GetPrefixOfNamespace(namespaceUri); } } internal class XmlNodeConverter : JsonConverter { internal static readonly List EmptyChildNodes = new List(); private const string TextName = "#text"; private const string CommentName = "#comment"; private const string CDataName = "#cdata-section"; private const string WhitespaceName = "#whitespace"; private const string SignificantWhitespaceName = "#significant-whitespace"; private const string DeclarationName = "?xml"; private const string JsonNamespaceUri = "http://james.newtonking.com/projects/json"; public string? DeserializeRootElementName { get; set; } public bool WriteArrayAttribute { get; set; } public bool OmitRootObject { get; set; } public bool EncodeSpecialCharacters { get; set; } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } IXmlNode node = WrapXml(value); XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable()); PushParentNamespaces(node, manager); if (!OmitRootObject) { writer.WriteStartObject(); } SerializeNode(writer, node, manager, !OmitRootObject); if (!OmitRootObject) { writer.WriteEndObject(); } } private IXmlNode WrapXml(object value) { if (value is XObject node) { return XContainerWrapper.WrapNode(node); } if (value is XmlNode node2) { return XmlNodeWrapper.WrapNode(node2); } throw new ArgumentException("Value must be an XML object.", "value"); } private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager) { List list = null; IXmlNode xmlNode = node; while ((xmlNode = xmlNode.ParentNode) != null) { if (xmlNode.NodeType == XmlNodeType.Element) { if (list == null) { list = new List(); } list.Add(xmlNode); } } if (list == null) { return; } list.Reverse(); foreach (IXmlNode item in list) { manager.PushScope(); foreach (IXmlNode attribute in item.Attributes) { if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/" && attribute.LocalName != "xmlns") { manager.AddNamespace(attribute.LocalName, attribute.Value); } } } } private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager) { string text = ((node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/")) ? null : manager.LookupPrefix(node.NamespaceUri)); if (!StringUtils.IsNullOrEmpty(text)) { return text + ":" + XmlConvert.DecodeName(node.LocalName); } return XmlConvert.DecodeName(node.LocalName); } private string GetPropertyName(IXmlNode node, XmlNamespaceManager manager) { switch (node.NodeType) { case XmlNodeType.Attribute: if (node.NamespaceUri == "http://james.newtonking.com/projects/json") { return "$" + node.LocalName; } return "@" + ResolveFullName(node, manager); case XmlNodeType.CDATA: return "#cdata-section"; case XmlNodeType.Comment: return "#comment"; case XmlNodeType.Element: if (node.NamespaceUri == "http://james.newtonking.com/projects/json") { return "$" + node.LocalName; } return ResolveFullName(node, manager); case XmlNodeType.ProcessingInstruction: return "?" + ResolveFullName(node, manager); case XmlNodeType.DocumentType: return "!" + ResolveFullName(node, manager); case XmlNodeType.XmlDeclaration: return "?xml"; case XmlNodeType.SignificantWhitespace: return "#significant-whitespace"; case XmlNodeType.Text: return "#text"; case XmlNodeType.Whitespace: return "#whitespace"; default: throw new JsonSerializationException("Unexpected XmlNodeType when getting node name: " + node.NodeType); } } private bool IsArray(IXmlNode node) { foreach (IXmlNode attribute in node.Attributes) { if (attribute.LocalName == "Array" && attribute.NamespaceUri == "http://james.newtonking.com/projects/json") { return XmlConvert.ToBoolean(attribute.Value); } } return false; } private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName) { switch (node.ChildNodes.Count) { case 1: { string propertyName = GetPropertyName(node.ChildNodes[0], manager); WriteGroupedNodes(writer, manager, writePropertyName, node.ChildNodes, propertyName); return; } case 0: return; } Dictionary dictionary = null; string text = null; for (int i = 0; i < node.ChildNodes.Count; i++) { IXmlNode xmlNode = node.ChildNodes[i]; string propertyName2 = GetPropertyName(xmlNode, manager); object value; if (dictionary == null) { if (text == null) { text = propertyName2; continue; } if (propertyName2 == text) { continue; } dictionary = new Dictionary(); if (i > 1) { List list = new List(i); for (int j = 0; j < i; j++) { list.Add(node.ChildNodes[j]); } dictionary.Add(text, list); } else { dictionary.Add(text, node.ChildNodes[0]); } dictionary.Add(propertyName2, xmlNode); } else if (!dictionary.TryGetValue(propertyName2, out value)) { dictionary.Add(propertyName2, xmlNode); } else { List list2 = value as List; if (list2 == null) { list2 = (List)(dictionary[propertyName2] = new List { (IXmlNode)value }); } list2.Add(xmlNode); } } if (dictionary == null) { WriteGroupedNodes(writer, manager, writePropertyName, node.ChildNodes, text); return; } foreach (KeyValuePair item in dictionary) { if (item.Value is List groupedNodes) { WriteGroupedNodes(writer, manager, writePropertyName, groupedNodes, item.Key); } else { WriteGroupedNodes(writer, manager, writePropertyName, (IXmlNode)item.Value, item.Key); } } } private void WriteGroupedNodes(JsonWriter writer, XmlNamespaceManager manager, bool writePropertyName, List groupedNodes, string elementNames) { if (groupedNodes.Count == 1 && !IsArray(groupedNodes[0])) { SerializeNode(writer, groupedNodes[0], manager, writePropertyName); return; } if (writePropertyName) { writer.WritePropertyName(elementNames); } writer.WriteStartArray(); for (int i = 0; i < groupedNodes.Count; i++) { SerializeNode(writer, groupedNodes[i], manager, writePropertyName: false); } writer.WriteEndArray(); } private void WriteGroupedNodes(JsonWriter writer, XmlNamespaceManager manager, bool writePropertyName, IXmlNode node, string elementNames) { if (!IsArray(node)) { SerializeNode(writer, node, manager, writePropertyName); return; } if (writePropertyName) { writer.WritePropertyName(elementNames); } writer.WriteStartArray(); SerializeNode(writer, node, manager, writePropertyName: false); writer.WriteEndArray(); } private void SerializeNode(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName) { switch (node.NodeType) { case XmlNodeType.Document: case XmlNodeType.DocumentFragment: SerializeGroupedNodes(writer, node, manager, writePropertyName); break; case XmlNodeType.Element: if (IsArray(node) && AllSameName(node) && node.ChildNodes.Count > 0) { SerializeGroupedNodes(writer, node, manager, writePropertyName: false); break; } manager.PushScope(); foreach (IXmlNode attribute in node.Attributes) { if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/") { string prefix = ((attribute.LocalName != "xmlns") ? XmlConvert.DecodeName(attribute.LocalName) : string.Empty); string value = attribute.Value; if (value == null) { throw new JsonSerializationException("Namespace attribute must have a value."); } manager.AddNamespace(prefix, value); } } if (writePropertyName) { writer.WritePropertyName(GetPropertyName(node, manager)); } if (!ValueAttributes(node.Attributes) && node.ChildNodes.Count == 1 && node.ChildNodes[0].NodeType == XmlNodeType.Text) { writer.WriteValue(node.ChildNodes[0].Value); } else if (node.ChildNodes.Count == 0 && node.Attributes.Count == 0) { if (((IXmlElement)node).IsEmpty) { writer.WriteNull(); } else { writer.WriteValue(string.Empty); } } else { writer.WriteStartObject(); for (int i = 0; i < node.Attributes.Count; i++) { SerializeNode(writer, node.Attributes[i], manager, writePropertyName: true); } SerializeGroupedNodes(writer, node, manager, writePropertyName: true); writer.WriteEndObject(); } manager.PopScope(); break; case XmlNodeType.Comment: if (writePropertyName) { writer.WriteComment(node.Value); } break; case XmlNodeType.Attribute: case XmlNodeType.Text: case XmlNodeType.CDATA: case XmlNodeType.ProcessingInstruction: case XmlNodeType.Whitespace: case XmlNodeType.SignificantWhitespace: if ((!(node.NamespaceUri == "http://www.w3.org/2000/xmlns/") || !(node.Value == "http://james.newtonking.com/projects/json")) && (!(node.NamespaceUri == "http://james.newtonking.com/projects/json") || !(node.LocalName == "Array"))) { if (writePropertyName) { writer.WritePropertyName(GetPropertyName(node, manager)); } writer.WriteValue(node.Value); } break; case XmlNodeType.XmlDeclaration: { IXmlDeclaration xmlDeclaration = (IXmlDeclaration)node; writer.WritePropertyName(GetPropertyName(node, manager)); writer.WriteStartObject(); if (!StringUtils.IsNullOrEmpty(xmlDeclaration.Version)) { writer.WritePropertyName("@version"); writer.WriteValue(xmlDeclaration.Version); } if (!StringUtils.IsNullOrEmpty(xmlDeclaration.Encoding)) { writer.WritePropertyName("@encoding"); writer.WriteValue(xmlDeclaration.Encoding); } if (!StringUtils.IsNullOrEmpty(xmlDeclaration.Standalone)) { writer.WritePropertyName("@standalone"); writer.WriteValue(xmlDeclaration.Standalone); } writer.WriteEndObject(); break; } case XmlNodeType.DocumentType: { IXmlDocumentType xmlDocumentType = (IXmlDocumentType)node; writer.WritePropertyName(GetPropertyName(node, manager)); writer.WriteStartObject(); if (!StringUtils.IsNullOrEmpty(xmlDocumentType.Name)) { writer.WritePropertyName("@name"); writer.WriteValue(xmlDocumentType.Name); } if (!StringUtils.IsNullOrEmpty(xmlDocumentType.Public)) { writer.WritePropertyName("@public"); writer.WriteValue(xmlDocumentType.Public); } if (!StringUtils.IsNullOrEmpty(xmlDocumentType.System)) { writer.WritePropertyName("@system"); writer.WriteValue(xmlDocumentType.System); } if (!StringUtils.IsNullOrEmpty(xmlDocumentType.InternalSubset)) { writer.WritePropertyName("@internalSubset"); writer.WriteValue(xmlDocumentType.InternalSubset); } writer.WriteEndObject(); break; } default: throw new JsonSerializationException("Unexpected XmlNodeType when serializing nodes: " + node.NodeType); } } private static bool AllSameName(IXmlNode node) { foreach (IXmlNode childNode in node.ChildNodes) { if (childNode.LocalName != node.LocalName) { return false; } } return true; } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { switch (reader.TokenType) { case JsonToken.Null: return null; default: throw JsonSerializationException.Create(reader, "XmlNodeConverter can only convert JSON that begins with an object."); case JsonToken.StartObject: { XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable()); IXmlDocument xmlDocument = null; IXmlNode xmlNode = null; if (typeof(XObject).IsAssignableFrom(objectType)) { if (objectType != typeof(XContainer) && objectType != typeof(XDocument) && objectType != typeof(XElement) && objectType != typeof(XNode) && objectType != typeof(XObject)) { throw JsonSerializationException.Create(reader, "XmlNodeConverter only supports deserializing XDocument, XElement, XContainer, XNode or XObject."); } xmlDocument = new XDocumentWrapper(new XDocument()); xmlNode = xmlDocument; } if (typeof(XmlNode).IsAssignableFrom(objectType)) { if (objectType != typeof(XmlDocument) && objectType != typeof(XmlElement) && objectType != typeof(XmlNode)) { throw JsonSerializationException.Create(reader, "XmlNodeConverter only supports deserializing XmlDocument, XmlElement or XmlNode."); } xmlDocument = new XmlDocumentWrapper(new XmlDocument { XmlResolver = null }); xmlNode = xmlDocument; } if (xmlDocument == null || xmlNode == null) { throw JsonSerializationException.Create(reader, "Unexpected type when converting XML: " + objectType); } if (!StringUtils.IsNullOrEmpty(DeserializeRootElementName)) { ReadElement(reader, xmlDocument, xmlNode, DeserializeRootElementName, manager); } else { reader.ReadAndAssert(); DeserializeNode(reader, xmlDocument, manager, xmlNode); } if (objectType == typeof(XElement)) { XElement obj = (XElement)xmlDocument.DocumentElement.WrappedNode; obj.Remove(); return obj; } if (objectType == typeof(XmlElement)) { return xmlDocument.DocumentElement.WrappedNode; } return xmlDocument.WrappedNode; } } } private void DeserializeValue(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, string propertyName, IXmlNode currentNode) { if (!EncodeSpecialCharacters) { switch (propertyName) { case "#text": currentNode.AppendChild(document.CreateTextNode(ConvertTokenToXmlValue(reader))); return; case "#cdata-section": currentNode.AppendChild(document.CreateCDataSection(ConvertTokenToXmlValue(reader))); return; case "#whitespace": currentNode.AppendChild(document.CreateWhitespace(ConvertTokenToXmlValue(reader))); return; case "#significant-whitespace": currentNode.AppendChild(document.CreateSignificantWhitespace(ConvertTokenToXmlValue(reader))); return; } if (!StringUtils.IsNullOrEmpty(propertyName) && propertyName[0] == '?') { CreateInstruction(reader, document, currentNode, propertyName); return; } if (string.Equals(propertyName, "!DOCTYPE", StringComparison.OrdinalIgnoreCase)) { CreateDocumentType(reader, document, currentNode); return; } } if (reader.TokenType == JsonToken.StartArray) { ReadArrayElements(reader, document, propertyName, currentNode, manager); } else { ReadElement(reader, document, currentNode, propertyName, manager); } } private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager) { if (StringUtils.IsNullOrEmpty(propertyName)) { throw JsonSerializationException.Create(reader, "XmlNodeConverter cannot convert JSON with an empty property name to XML."); } Dictionary attributeNameValues = null; string elementPrefix = null; if (!EncodeSpecialCharacters) { attributeNameValues = (ShouldReadInto(reader) ? ReadAttributeElements(reader, manager) : null); elementPrefix = MiscellaneousUtils.GetPrefix(propertyName); if (propertyName.StartsWith('@')) { string text = propertyName.Substring(1); string prefix = MiscellaneousUtils.GetPrefix(text); AddAttribute(reader, document, currentNode, propertyName, text, manager, prefix); return; } if (propertyName.StartsWith('$')) { switch (propertyName) { case "$values": propertyName = propertyName.Substring(1); elementPrefix = manager.LookupPrefix("http://james.newtonking.com/projects/json"); CreateElement(reader, document, currentNode, propertyName, manager, elementPrefix, attributeNameValues); return; case "$id": case "$ref": case "$type": case "$value": { string attributeName = propertyName.Substring(1); string attributePrefix = manager.LookupPrefix("http://james.newtonking.com/projects/json"); AddAttribute(reader, document, currentNode, propertyName, attributeName, manager, attributePrefix); return; } } } } else if (ShouldReadInto(reader)) { reader.ReadAndAssert(); } CreateElement(reader, document, currentNode, propertyName, manager, elementPrefix, attributeNameValues); } private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string elementName, XmlNamespaceManager manager, string? elementPrefix, Dictionary? attributeNameValues) { IXmlElement xmlElement = CreateElement(elementName, document, elementPrefix, manager); currentNode.AppendChild(xmlElement); if (attributeNameValues != null) { foreach (KeyValuePair attributeNameValue in attributeNameValues) { string text = XmlConvert.EncodeName(attributeNameValue.Key); string prefix = MiscellaneousUtils.GetPrefix(attributeNameValue.Key); IXmlNode attributeNode = ((!StringUtils.IsNullOrEmpty(prefix)) ? document.CreateAttribute(text, manager.LookupNamespace(prefix) ?? string.Empty, attributeNameValue.Value) : document.CreateAttribute(text, attributeNameValue.Value)); xmlElement.SetAttributeNode(attributeNode); } } switch (reader.TokenType) { case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { string text2 = ConvertTokenToXmlValue(reader); if (text2 != null) { xmlElement.AppendChild(document.CreateTextNode(text2)); } break; } case JsonToken.EndObject: manager.RemoveNamespace(string.Empty, manager.DefaultNamespace); break; default: manager.PushScope(); DeserializeNode(reader, document, manager, xmlElement); manager.PopScope(); manager.RemoveNamespace(string.Empty, manager.DefaultNamespace); break; case JsonToken.Null: break; } } private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, string attributeName, XmlNamespaceManager manager, string? attributePrefix) { if (currentNode.NodeType == XmlNodeType.Document) { throw JsonSerializationException.Create(reader, "JSON root object has property '{0}' that will be converted to an attribute. A root object cannot have any attribute properties. Consider specifying a DeserializeRootElementName.".FormatWith(CultureInfo.InvariantCulture, propertyName)); } string text = XmlConvert.EncodeName(attributeName); string value = ConvertTokenToXmlValue(reader); IXmlNode attributeNode = ((!StringUtils.IsNullOrEmpty(attributePrefix)) ? document.CreateAttribute(text, manager.LookupNamespace(attributePrefix), value) : document.CreateAttribute(text, value)); ((IXmlElement)currentNode).SetAttributeNode(attributeNode); } private static string? ConvertTokenToXmlValue(JsonReader reader) { switch (reader.TokenType) { case JsonToken.String: return reader.Value?.ToString(); case JsonToken.Integer: if (reader.Value is BigInteger bigInteger) { return bigInteger.ToString(CultureInfo.InvariantCulture); } return XmlConvert.ToString(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture)); case JsonToken.Float: if (reader.Value is decimal num) { return XmlConvert.ToString(num); } if (reader.Value is float num2) { return XmlConvert.ToString(num2); } return XmlConvert.ToString(Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture)); case JsonToken.Boolean: return XmlConvert.ToString(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture)); case JsonToken.Date: { if (reader.Value is DateTimeOffset dateTimeOffset) { return XmlConvert.ToString(dateTimeOffset); } DateTime dateTime = Convert.ToDateTime(reader.Value, CultureInfo.InvariantCulture); return XmlConvert.ToString(dateTime, DateTimeUtils.ToSerializationMode(dateTime.Kind)); } case JsonToken.Bytes: return Convert.ToBase64String((byte[])reader.Value); case JsonToken.Null: return null; default: throw JsonSerializationException.Create(reader, "Cannot get an XML string value from token type '{0}'.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager) { string prefix = MiscellaneousUtils.GetPrefix(propertyName); IXmlElement xmlElement = CreateElement(propertyName, document, prefix, manager); currentNode.AppendChild(xmlElement); int num = 0; while (reader.Read() && reader.TokenType != JsonToken.EndArray) { DeserializeValue(reader, document, manager, propertyName, xmlElement); num++; } if (WriteArrayAttribute) { AddJsonArrayAttribute(xmlElement, document); } if (num != 1 || !WriteArrayAttribute) { return; } foreach (IXmlNode childNode in xmlElement.ChildNodes) { if (childNode is IXmlElement xmlElement2 && xmlElement2.LocalName == propertyName) { AddJsonArrayAttribute(xmlElement2, document); break; } } } private void AddJsonArrayAttribute(IXmlElement element, IXmlDocument document) { element.SetAttributeNode(document.CreateAttribute("json:Array", "http://james.newtonking.com/projects/json", "true")); if (element is XElementWrapper && element.GetPrefixOfNamespace("http://james.newtonking.com/projects/json") == null) { element.SetAttributeNode(document.CreateAttribute("xmlns:json", "http://www.w3.org/2000/xmlns/", "http://james.newtonking.com/projects/json")); } } private bool ShouldReadInto(JsonReader reader) { switch (reader.TokenType) { case JsonToken.StartConstructor: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Date: case JsonToken.Bytes: return false; default: return true; } } private Dictionary? ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager) { Dictionary dictionary = null; bool flag = false; while (!flag && reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: { string text = reader.Value.ToString(); if (!StringUtils.IsNullOrEmpty(text)) { switch (text[0]) { case '@': { if (dictionary == null) { dictionary = new Dictionary(); } text = text.Substring(1); reader.ReadAndAssert(); string value = ConvertTokenToXmlValue(reader); dictionary.Add(text, value); if (IsNamespaceAttribute(text, out string prefix)) { manager.AddNamespace(prefix, value); } break; } case '$': switch (text) { case "$values": case "$id": case "$ref": case "$type": case "$value": { string text2 = manager.LookupPrefix("http://james.newtonking.com/projects/json"); if (text2 == null) { if (dictionary == null) { dictionary = new Dictionary(); } int? num = null; int? num2; while (true) { num2 = num; if (manager.LookupNamespace("json" + num2) == null) { break; } num = num.GetValueOrDefault() + 1; } num2 = num; text2 = "json" + num2; dictionary.Add("xmlns:" + text2, "http://james.newtonking.com/projects/json"); manager.AddNamespace(text2, "http://james.newtonking.com/projects/json"); } if (text == "$values") { flag = true; break; } text = text.Substring(1); reader.ReadAndAssert(); if (!JsonTokenUtils.IsPrimitiveToken(reader.TokenType)) { throw JsonSerializationException.Create(reader, "Unexpected JsonToken: " + reader.TokenType); } if (dictionary == null) { dictionary = new Dictionary(); } string value = reader.Value?.ToString(); dictionary.Add(text2 + ":" + text, value); break; } default: flag = true; break; } break; default: flag = true; break; } } else { flag = true; } break; } case JsonToken.Comment: case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected JsonToken: " + reader.TokenType); } } return dictionary; } private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName) { if (propertyName == "?xml") { string text = null; string encoding = null; string standalone = null; while (reader.Read() && reader.TokenType != JsonToken.EndObject) { switch (reader.Value?.ToString()) { case "@version": reader.ReadAndAssert(); text = ConvertTokenToXmlValue(reader); break; case "@encoding": reader.ReadAndAssert(); encoding = ConvertTokenToXmlValue(reader); break; case "@standalone": reader.ReadAndAssert(); standalone = ConvertTokenToXmlValue(reader); break; default: throw JsonSerializationException.Create(reader, "Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value); } } if (text == null) { throw JsonSerializationException.Create(reader, "Version not specified for XML declaration."); } IXmlNode newChild = document.CreateXmlDeclaration(text, encoding, standalone); currentNode.AppendChild(newChild); } else { IXmlNode newChild2 = document.CreateProcessingInstruction(propertyName.Substring(1), ConvertTokenToXmlValue(reader)); currentNode.AppendChild(newChild2); } } private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNode currentNode) { string text = null; string publicId = null; string systemId = null; string internalSubset = null; while (reader.Read() && reader.TokenType != JsonToken.EndObject) { switch (reader.Value?.ToString()) { case "@name": reader.ReadAndAssert(); text = ConvertTokenToXmlValue(reader); break; case "@public": reader.ReadAndAssert(); publicId = ConvertTokenToXmlValue(reader); break; case "@system": reader.ReadAndAssert(); systemId = ConvertTokenToXmlValue(reader); break; case "@internalSubset": reader.ReadAndAssert(); internalSubset = ConvertTokenToXmlValue(reader); break; default: throw JsonSerializationException.Create(reader, "Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value); } } if (text == null) { throw JsonSerializationException.Create(reader, "Name not specified for XML document type."); } IXmlNode newChild = document.CreateXmlDocumentType(text, publicId, systemId, internalSubset); currentNode.AppendChild(newChild); } private IXmlElement CreateElement(string elementName, IXmlDocument document, string? elementPrefix, XmlNamespaceManager manager) { string text = (EncodeSpecialCharacters ? XmlConvert.EncodeLocalName(elementName) : XmlConvert.EncodeName(elementName)); string text2 = (StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix)); if (StringUtils.IsNullOrEmpty(text2)) { return document.CreateElement(text); } return document.CreateElement(text, text2); } private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, IXmlNode currentNode) { do { switch (reader.TokenType) { case JsonToken.PropertyName: { if (currentNode.NodeType == XmlNodeType.Document && document.DocumentElement != null) { throw JsonSerializationException.Create(reader, "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName."); } string text = reader.Value.ToString(); reader.ReadAndAssert(); if (reader.TokenType == JsonToken.StartArray) { int num = 0; while (reader.Read() && reader.TokenType != JsonToken.EndArray) { DeserializeValue(reader, document, manager, text, currentNode); num++; } if (num != 1 || !WriteArrayAttribute) { break; } MiscellaneousUtils.GetQualifiedNameParts(text, out string prefix, out string localName); string text2 = (StringUtils.IsNullOrEmpty(prefix) ? manager.DefaultNamespace : manager.LookupNamespace(prefix)); foreach (IXmlNode childNode in currentNode.ChildNodes) { if (childNode is IXmlElement xmlElement && xmlElement.LocalName == localName && xmlElement.NamespaceUri == text2) { AddJsonArrayAttribute(xmlElement, document); break; } } } else { DeserializeValue(reader, document, manager, text, currentNode); } break; } case JsonToken.StartConstructor: { string propertyName = reader.Value.ToString(); while (reader.Read() && reader.TokenType != JsonToken.EndConstructor) { DeserializeValue(reader, document, manager, propertyName, currentNode); } break; } case JsonToken.Comment: currentNode.AppendChild(document.CreateComment((string)reader.Value)); break; case JsonToken.EndObject: case JsonToken.EndArray: return; default: throw JsonSerializationException.Create(reader, "Unexpected JsonToken when deserializing node: " + reader.TokenType); } } while (reader.Read()); } private bool IsNamespaceAttribute(string attributeName, [NotNullWhen(true)] out string? prefix) { if (attributeName.StartsWith("xmlns", StringComparison.Ordinal)) { if (attributeName.Length == 5) { prefix = string.Empty; return true; } if (attributeName[5] == ':') { prefix = attributeName.Substring(6, attributeName.Length - 6); return true; } } prefix = null; return false; } private bool ValueAttributes(List c) { foreach (IXmlNode item in c) { if (!(item.NamespaceUri == "http://james.newtonking.com/projects/json") && (!(item.NamespaceUri == "http://www.w3.org/2000/xmlns/") || !(item.Value == "http://james.newtonking.com/projects/json"))) { return true; } } return false; } public override bool CanConvert(Type valueType) { if (valueType.AssignableToTypeName("System.Xml.Linq.XObject", searchInterfaces: false)) { return IsXObject(valueType); } if (valueType.AssignableToTypeName("System.Xml.XmlNode", searchInterfaces: false)) { return IsXmlNode(valueType); } return false; } [MethodImpl(MethodImplOptions.NoInlining)] private bool IsXObject(Type valueType) { return typeof(XObject).IsAssignableFrom(valueType); } [MethodImpl(MethodImplOptions.NoInlining)] private bool IsXmlNode(Type valueType) { return typeof(XmlNode).IsAssignableFrom(valueType); } } } namespace Newtonsoft.Json.Bson { internal enum BsonBinaryType : byte { Binary = 0, Function = 1, [Obsolete("This type has been deprecated in the BSON specification. Use Binary instead.")] BinaryOld = 2, [Obsolete("This type has been deprecated in the BSON specification. Use Uuid instead.")] UuidOld = 3, Uuid = 4, Md5 = 5, UserDefined = 128 } internal class BsonBinaryWriter { private static readonly Encoding Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); private readonly BinaryWriter _writer; private byte[] _largeByteBuffer; public DateTimeKind DateTimeKindHandling { get; set; } public BsonBinaryWriter(BinaryWriter writer) { DateTimeKindHandling = DateTimeKind.Utc; _writer = writer; } public void Flush() { _writer.Flush(); } public void Close() { _writer.Close(); } public void WriteToken(BsonToken t) { CalculateSize(t); WriteTokenInternal(t); } private void WriteTokenInternal(BsonToken t) { switch (t.Type) { case BsonType.Object: { BsonObject bsonObject = (BsonObject)t; _writer.Write(bsonObject.CalculatedSize); foreach (BsonProperty item in bsonObject) { _writer.Write((sbyte)item.Value.Type); WriteString((string)item.Name.Value, item.Name.ByteCount, null); WriteTokenInternal(item.Value); } _writer.Write((byte)0); break; } case BsonType.Array: { BsonArray bsonArray = (BsonArray)t; _writer.Write(bsonArray.CalculatedSize); ulong num2 = 0uL; foreach (BsonToken item2 in bsonArray) { _writer.Write((sbyte)item2.Type); WriteString(num2.ToString(CultureInfo.InvariantCulture), MathUtils.IntLength(num2), null); WriteTokenInternal(item2); num2++; } _writer.Write((byte)0); break; } case BsonType.Integer: { BsonValue bsonValue3 = (BsonValue)t; _writer.Write(Convert.ToInt32(bsonValue3.Value, CultureInfo.InvariantCulture)); break; } case BsonType.Long: { BsonValue bsonValue4 = (BsonValue)t; _writer.Write(Convert.ToInt64(bsonValue4.Value, CultureInfo.InvariantCulture)); break; } case BsonType.Number: { BsonValue bsonValue2 = (BsonValue)t; _writer.Write(Convert.ToDouble(bsonValue2.Value, CultureInfo.InvariantCulture)); break; } case BsonType.String: { BsonString bsonString = (BsonString)t; WriteString((string)bsonString.Value, bsonString.ByteCount, bsonString.CalculatedSize - 4); break; } case BsonType.Boolean: _writer.Write(t == BsonBoolean.True); break; case BsonType.Date: { BsonValue bsonValue = (BsonValue)t; long num = 0L; if (bsonValue.Value is DateTime dateTime) { if (DateTimeKindHandling == DateTimeKind.Utc) { dateTime = dateTime.ToUniversalTime(); } else if (DateTimeKindHandling == DateTimeKind.Local) { dateTime = dateTime.ToLocalTime(); } num = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTime, convertToUtc: false); } else { DateTimeOffset dateTimeOffset = (DateTimeOffset)bsonValue.Value; num = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTimeOffset.UtcDateTime, dateTimeOffset.Offset); } _writer.Write(num); break; } case BsonType.Binary: { BsonBinary bsonBinary = (BsonBinary)t; byte[] array = (byte[])bsonBinary.Value; _writer.Write(array.Length); _writer.Write((byte)bsonBinary.BinaryType); _writer.Write(array); break; } case BsonType.Oid: { byte[] buffer = (byte[])((BsonValue)t).Value; _writer.Write(buffer); break; } case BsonType.Regex: { BsonRegex bsonRegex = (BsonRegex)t; WriteString((string)bsonRegex.Pattern.Value, bsonRegex.Pattern.ByteCount, null); WriteString((string)bsonRegex.Options.Value, bsonRegex.Options.ByteCount, null); break; } default: throw new ArgumentOutOfRangeException("t", "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type)); case BsonType.Undefined: case BsonType.Null: break; } } private void WriteString(string s, int byteCount, int? calculatedlengthPrefix) { if (calculatedlengthPrefix.HasValue) { _writer.Write(calculatedlengthPrefix.GetValueOrDefault()); } WriteUtf8Bytes(s, byteCount); _writer.Write((byte)0); } public void WriteUtf8Bytes(string s, int byteCount) { if (s == null) { return; } if (byteCount <= 256) { if (_largeByteBuffer == null) { _largeByteBuffer = new byte[256]; } Encoding.GetBytes(s, 0, s.Length, _largeByteBuffer, 0); _writer.Write(_largeByteBuffer, 0, byteCount); } else { byte[] bytes = Encoding.GetBytes(s); _writer.Write(bytes); } } private int CalculateSize(int stringByteCount) { return stringByteCount + 1; } private int CalculateSizeWithLength(int stringByteCount, bool includeSize) { return ((!includeSize) ? 1 : 5) + stringByteCount; } private int CalculateSize(BsonToken t) { switch (t.Type) { case BsonType.Object: { BsonObject bsonObject = (BsonObject)t; int num4 = 4; foreach (BsonProperty item in bsonObject) { int num5 = 1; num5 += CalculateSize(item.Name); num5 += CalculateSize(item.Value); num4 += num5; } return bsonObject.CalculatedSize = num4 + 1; } case BsonType.Array: { BsonArray bsonArray = (BsonArray)t; int num2 = 4; ulong num3 = 0uL; foreach (BsonToken item2 in bsonArray) { num2++; num2 += CalculateSize(MathUtils.IntLength(num3)); num2 += CalculateSize(item2); num3++; } num2++; bsonArray.CalculatedSize = num2; return bsonArray.CalculatedSize; } case BsonType.Integer: return 4; case BsonType.Long: return 8; case BsonType.Number: return 8; case BsonType.String: { BsonString bsonString = (BsonString)t; string text = (string)bsonString.Value; bsonString.ByteCount = ((text != null) ? Encoding.GetByteCount(text) : 0); bsonString.CalculatedSize = CalculateSizeWithLength(bsonString.ByteCount, bsonString.IncludeLength); return bsonString.CalculatedSize; } case BsonType.Boolean: return 1; case BsonType.Undefined: case BsonType.Null: return 0; case BsonType.Date: return 8; case BsonType.Binary: { BsonBinary obj = (BsonBinary)t; byte[] array = (byte[])obj.Value; obj.CalculatedSize = 5 + array.Length; return obj.CalculatedSize; } case BsonType.Oid: return 12; case BsonType.Regex: { BsonRegex bsonRegex = (BsonRegex)t; int num = 0; num += CalculateSize(bsonRegex.Pattern); num += CalculateSize(bsonRegex.Options); bsonRegex.CalculatedSize = num; return bsonRegex.CalculatedSize; } default: throw new ArgumentOutOfRangeException("t", "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type)); } } } [Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] internal class BsonObjectId { public byte[] Value { get; } public BsonObjectId(byte[] value) { ValidationUtils.ArgumentNotNull(value, "value"); if (value.Length != 12) { throw new ArgumentException("An ObjectId must be 12 bytes", "value"); } Value = value; } } [Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] internal class BsonReader : JsonReader { private enum BsonReaderState { Normal, ReferenceStart, ReferenceRef, ReferenceId, CodeWScopeStart, CodeWScopeCode, CodeWScopeScope, CodeWScopeScopeObject, CodeWScopeScopeEnd } private class ContainerContext { public readonly BsonType Type; public int Length; public int Position; public ContainerContext(BsonType type) { Type = type; } } private const int MaxCharBytesSize = 128; private static readonly byte[] SeqRange1 = new byte[2] { 0, 127 }; private static readonly byte[] SeqRange2 = new byte[2] { 194, 223 }; private static readonly byte[] SeqRange3 = new byte[2] { 224, 239 }; private static readonly byte[] SeqRange4 = new byte[2] { 240, 244 }; private readonly BinaryReader _reader; private readonly List _stack; private byte[] _byteBuffer; private char[] _charBuffer; private BsonType _currentElementType; private BsonReaderState _bsonReaderState; private ContainerContext _currentContext; private bool _readRootValueAsArray; private bool _jsonNet35BinaryCompatibility; private DateTimeKind _dateTimeKindHandling; [Obsolete("JsonNet35BinaryCompatibility will be removed in a future version of Json.NET.")] public bool JsonNet35BinaryCompatibility { get { return _jsonNet35BinaryCompatibility; } set { _jsonNet35BinaryCompatibility = value; } } public bool ReadRootValueAsArray { get { return _readRootValueAsArray; } set { _readRootValueAsArray = value; } } public DateTimeKind DateTimeKindHandling { get { return _dateTimeKindHandling; } set { _dateTimeKindHandling = value; } } public BsonReader(Stream stream) : this(stream, readRootValueAsArray: false, DateTimeKind.Local) { } public BsonReader(BinaryReader reader) : this(reader, readRootValueAsArray: false, DateTimeKind.Local) { } public BsonReader(Stream stream, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling) { ValidationUtils.ArgumentNotNull(stream, "stream"); _reader = new BinaryReader(stream); _stack = new List(); _readRootValueAsArray = readRootValueAsArray; _dateTimeKindHandling = dateTimeKindHandling; } public BsonReader(BinaryReader reader, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling) { ValidationUtils.ArgumentNotNull(reader, "reader"); _reader = reader; _stack = new List(); _readRootValueAsArray = readRootValueAsArray; _dateTimeKindHandling = dateTimeKindHandling; } private string ReadElement() { _currentElementType = ReadType(); return ReadString(); } public override bool Read() { try { bool flag; switch (_bsonReaderState) { case BsonReaderState.Normal: flag = ReadNormal(); break; case BsonReaderState.ReferenceStart: case BsonReaderState.ReferenceRef: case BsonReaderState.ReferenceId: flag = ReadReference(); break; case BsonReaderState.CodeWScopeStart: case BsonReaderState.CodeWScopeCode: case BsonReaderState.CodeWScopeScope: case BsonReaderState.CodeWScopeScopeObject: case BsonReaderState.CodeWScopeScopeEnd: flag = ReadCodeWScope(); break; default: throw JsonReaderException.Create(this, "Unexpected state: {0}".FormatWith(CultureInfo.InvariantCulture, _bsonReaderState)); } if (!flag) { SetToken(JsonToken.None); return false; } return true; } catch (EndOfStreamException) { SetToken(JsonToken.None); return false; } } public override void Close() { base.Close(); if (base.CloseInput) { _reader?.Close(); } } private bool ReadCodeWScope() { switch (_bsonReaderState) { case BsonReaderState.CodeWScopeStart: SetToken(JsonToken.PropertyName, "$code"); _bsonReaderState = BsonReaderState.CodeWScopeCode; return true; case BsonReaderState.CodeWScopeCode: ReadInt32(); SetToken(JsonToken.String, ReadLengthString()); _bsonReaderState = BsonReaderState.CodeWScopeScope; return true; case BsonReaderState.CodeWScopeScope: { if (base.CurrentState == State.PostValue) { SetToken(JsonToken.PropertyName, "$scope"); return true; } SetToken(JsonToken.StartObject); _bsonReaderState = BsonReaderState.CodeWScopeScopeObject; ContainerContext containerContext = new ContainerContext(BsonType.Object); PushContext(containerContext); containerContext.Length = ReadInt32(); return true; } case BsonReaderState.CodeWScopeScopeObject: { bool num = ReadNormal(); if (num && TokenType == JsonToken.EndObject) { _bsonReaderState = BsonReaderState.CodeWScopeScopeEnd; } return num; } case BsonReaderState.CodeWScopeScopeEnd: SetToken(JsonToken.EndObject); _bsonReaderState = BsonReaderState.Normal; return true; default: throw new ArgumentOutOfRangeException(); } } private bool ReadReference() { switch (base.CurrentState) { case State.ObjectStart: SetToken(JsonToken.PropertyName, "$ref"); _bsonReaderState = BsonReaderState.ReferenceRef; return true; case State.Property: if (_bsonReaderState == BsonReaderState.ReferenceRef) { SetToken(JsonToken.String, ReadLengthString()); return true; } if (_bsonReaderState == BsonReaderState.ReferenceId) { SetToken(JsonToken.Bytes, ReadBytes(12)); return true; } throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState); case State.PostValue: if (_bsonReaderState == BsonReaderState.ReferenceRef) { SetToken(JsonToken.PropertyName, "$id"); _bsonReaderState = BsonReaderState.ReferenceId; return true; } if (_bsonReaderState == BsonReaderState.ReferenceId) { SetToken(JsonToken.EndObject); _bsonReaderState = BsonReaderState.Normal; return true; } throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState); default: throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + base.CurrentState); } } private bool ReadNormal() { switch (base.CurrentState) { case State.Start: { JsonToken token2 = ((!_readRootValueAsArray) ? JsonToken.StartObject : JsonToken.StartArray); int type = ((!_readRootValueAsArray) ? 3 : 4); SetToken(token2); ContainerContext containerContext = new ContainerContext((BsonType)type); PushContext(containerContext); containerContext.Length = ReadInt32(); return true; } case State.Complete: case State.Closed: return false; case State.Property: ReadType(_currentElementType); return true; case State.ObjectStart: case State.ArrayStart: case State.PostValue: { ContainerContext currentContext = _currentContext; if (currentContext == null) { if (!base.SupportMultipleContent) { return false; } goto case State.Start; } int num = currentContext.Length - 1; if (currentContext.Position < num) { if (currentContext.Type == BsonType.Array) { ReadElement(); ReadType(_currentElementType); return true; } SetToken(JsonToken.PropertyName, ReadElement()); return true; } if (currentContext.Position == num) { if (ReadByte() != 0) { throw JsonReaderException.Create(this, "Unexpected end of object byte value."); } PopContext(); if (_currentContext != null) { MovePosition(currentContext.Length); } JsonToken token = ((currentContext.Type == BsonType.Object) ? JsonToken.EndObject : JsonToken.EndArray); SetToken(token); return true; } throw JsonReaderException.Create(this, "Read past end of current container context."); } default: throw new ArgumentOutOfRangeException(); case State.ConstructorStart: case State.Constructor: case State.Error: case State.Finished: return false; } } private void PopContext() { _stack.RemoveAt(_stack.Count - 1); if (_stack.Count == 0) { _currentContext = null; } else { _currentContext = _stack[_stack.Count - 1]; } } private void PushContext(ContainerContext newContext) { _stack.Add(newContext); _currentContext = newContext; } private byte ReadByte() { MovePosition(1); return _reader.ReadByte(); } private void ReadType(BsonType type) { switch (type) { case BsonType.Number: { double num = ReadDouble(); if (_floatParseHandling == FloatParseHandling.Decimal) { SetToken(JsonToken.Float, Convert.ToDecimal(num, CultureInfo.InvariantCulture)); } else { SetToken(JsonToken.Float, num); } break; } case BsonType.String: case BsonType.Symbol: SetToken(JsonToken.String, ReadLengthString()); break; case BsonType.Object: { SetToken(JsonToken.StartObject); ContainerContext containerContext2 = new ContainerContext(BsonType.Object); PushContext(containerContext2); containerContext2.Length = ReadInt32(); break; } case BsonType.Array: { SetToken(JsonToken.StartArray); ContainerContext containerContext = new ContainerContext(BsonType.Array); PushContext(containerContext); containerContext.Length = ReadInt32(); break; } case BsonType.Binary: { BsonBinaryType binaryType; byte[] array = ReadBinary(out binaryType); object value3 = ((binaryType != BsonBinaryType.Uuid) ? array : ((object)new Guid(array))); SetToken(JsonToken.Bytes, value3); break; } case BsonType.Undefined: SetToken(JsonToken.Undefined); break; case BsonType.Oid: { byte[] value2 = ReadBytes(12); SetToken(JsonToken.Bytes, value2); break; } case BsonType.Boolean: { bool flag = Convert.ToBoolean(ReadByte()); SetToken(JsonToken.Boolean, flag); break; } case BsonType.Date: { DateTime dateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ReadInt64()); SetToken(JsonToken.Date, DateTimeKindHandling switch { DateTimeKind.Unspecified => DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified), DateTimeKind.Local => dateTime.ToLocalTime(), _ => dateTime, }); break; } case BsonType.Null: SetToken(JsonToken.Null); break; case BsonType.Regex: { string text = ReadString(); string text2 = ReadString(); string value = "/" + text + "/" + text2; SetToken(JsonToken.String, value); break; } case BsonType.Reference: SetToken(JsonToken.StartObject); _bsonReaderState = BsonReaderState.ReferenceStart; break; case BsonType.Code: SetToken(JsonToken.String, ReadLengthString()); break; case BsonType.CodeWScope: SetToken(JsonToken.StartObject); _bsonReaderState = BsonReaderState.CodeWScopeStart; break; case BsonType.Integer: SetToken(JsonToken.Integer, (long)ReadInt32()); break; case BsonType.TimeStamp: case BsonType.Long: SetToken(JsonToken.Integer, ReadInt64()); break; default: throw new ArgumentOutOfRangeException("type", "Unexpected BsonType value: " + type); } } private byte[] ReadBinary(out BsonBinaryType binaryType) { int count = ReadInt32(); binaryType = (BsonBinaryType)ReadByte(); if (binaryType == BsonBinaryType.BinaryOld && !_jsonNet35BinaryCompatibility) { count = ReadInt32(); } return ReadBytes(count); } private string ReadString() { EnsureBuffers(); StringBuilder stringBuilder = null; int num = 0; int num2 = 0; while (true) { int num3 = num2; byte b; while (num3 < 128 && (b = _reader.ReadByte()) > 0) { _byteBuffer[num3++] = b; } int num4 = num3 - num2; num += num4; if (num3 < 128 && stringBuilder == null) { int chars = Encoding.UTF8.GetChars(_byteBuffer, 0, num4, _charBuffer, 0); MovePosition(num + 1); return new string(_charBuffer, 0, chars); } int lastFullCharStop = GetLastFullCharStop(num3 - 1); int chars2 = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0); if (stringBuilder == null) { stringBuilder = new StringBuilder(256); } stringBuilder.Append(_charBuffer, 0, chars2); if (lastFullCharStop < num4 - 1) { num2 = num4 - lastFullCharStop - 1; Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, num2); continue; } if (num3 < 128) { break; } num2 = 0; } MovePosition(num + 1); return stringBuilder.ToString(); } private string ReadLengthString() { int num = ReadInt32(); MovePosition(num); string @string = GetString(num - 1); _reader.ReadByte(); return @string; } private string GetString(int length) { if (length == 0) { return string.Empty; } EnsureBuffers(); StringBuilder stringBuilder = null; int num = 0; int num2 = 0; do { int count = ((length - num > 128 - num2) ? (128 - num2) : (length - num)); int num3 = _reader.Read(_byteBuffer, num2, count); if (num3 == 0) { throw new EndOfStreamException("Unable to read beyond the end of the stream."); } num += num3; num3 += num2; if (num3 == length) { int chars = Encoding.UTF8.GetChars(_byteBuffer, 0, num3, _charBuffer, 0); return new string(_charBuffer, 0, chars); } int lastFullCharStop = GetLastFullCharStop(num3 - 1); if (stringBuilder == null) { stringBuilder = new StringBuilder(length); } int chars2 = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0); stringBuilder.Append(_charBuffer, 0, chars2); if (lastFullCharStop < num3 - 1) { num2 = num3 - lastFullCharStop - 1; Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, num2); } else { num2 = 0; } } while (num < length); return stringBuilder.ToString(); } private int GetLastFullCharStop(int start) { int num = start; int num2 = 0; for (; num >= 0; num--) { num2 = BytesInSequence(_byteBuffer[num]); switch (num2) { case 0: continue; default: num--; break; case 1: break; } break; } if (num2 == start - num) { return start; } return num; } private int BytesInSequence(byte b) { if (b <= SeqRange1[1]) { return 1; } if (b >= SeqRange2[0] && b <= SeqRange2[1]) { return 2; } if (b >= SeqRange3[0] && b <= SeqRange3[1]) { return 3; } if (b >= SeqRange4[0] && b <= SeqRange4[1]) { return 4; } return 0; } private void EnsureBuffers() { if (_byteBuffer == null) { _byteBuffer = new byte[128]; } if (_charBuffer == null) { int maxCharCount = Encoding.UTF8.GetMaxCharCount(128); _charBuffer = new char[maxCharCount]; } } private double ReadDouble() { MovePosition(8); return _reader.ReadDouble(); } private int ReadInt32() { MovePosition(4); return _reader.ReadInt32(); } private long ReadInt64() { MovePosition(8); return _reader.ReadInt64(); } private BsonType ReadType() { MovePosition(1); return (BsonType)_reader.ReadSByte(); } private void MovePosition(int count) { _currentContext.Position += count; } private byte[] ReadBytes(int count) { MovePosition(count); return _reader.ReadBytes(count); } } internal abstract class BsonToken { public abstract BsonType Type { get; } public BsonToken Parent { get; set; } public int CalculatedSize { get; set; } } internal class BsonObject : BsonToken, IEnumerable, IEnumerable { private readonly List _children = new List(); public override BsonType Type => BsonType.Object; public void Add(string name, BsonToken token) { _children.Add(new BsonProperty { Name = new BsonString(name, includeLength: false), Value = token }); token.Parent = this; } public IEnumerator GetEnumerator() { return _children.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal class BsonArray : BsonToken, IEnumerable, IEnumerable { private readonly List _children = new List(); public override BsonType Type => BsonType.Array; public void Add(BsonToken token) { _children.Add(token); token.Parent = this; } public IEnumerator GetEnumerator() { return _children.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal class BsonEmpty : BsonToken { public static readonly BsonToken Null = new BsonEmpty(BsonType.Null); public static readonly BsonToken Undefined = new BsonEmpty(BsonType.Undefined); public override BsonType Type { get; } private BsonEmpty(BsonType type) { Type = type; } } internal class BsonValue : BsonToken { private readonly object _value; private readonly BsonType _type; public object Value => _value; public override BsonType Type => _type; public BsonValue(object value, BsonType type) { _value = value; _type = type; } } internal class BsonBoolean : BsonValue { public static readonly BsonBoolean False = new BsonBoolean(value: false); public static readonly BsonBoolean True = new BsonBoolean(value: true); private BsonBoolean(bool value) : base(value, BsonType.Boolean) { } } internal class BsonString : BsonValue { public int ByteCount { get; set; } public bool IncludeLength { get; } public BsonString(object value, bool includeLength) : base(value, BsonType.String) { IncludeLength = includeLength; } } internal class BsonBinary : BsonValue { public BsonBinaryType BinaryType { get; set; } public BsonBinary(byte[] value, BsonBinaryType binaryType) : base(value, BsonType.Binary) { BinaryType = binaryType; } } internal class BsonRegex : BsonToken { public BsonString Pattern { get; set; } public BsonString Options { get; set; } public override BsonType Type => BsonType.Regex; public BsonRegex(string pattern, string options) { Pattern = new BsonString(pattern, includeLength: false); Options = new BsonString(options, includeLength: false); } } internal class BsonProperty { public BsonString Name { get; set; } public BsonToken Value { get; set; } } internal enum BsonType : sbyte { Number = 1, String = 2, Object = 3, Array = 4, Binary = 5, Undefined = 6, Oid = 7, Boolean = 8, Date = 9, Null = 10, Regex = 11, Reference = 12, Code = 13, Symbol = 14, CodeWScope = 15, Integer = 16, TimeStamp = 17, Long = 18, MinKey = -1, MaxKey = sbyte.MaxValue } [Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] internal class BsonWriter : JsonWriter { private readonly BsonBinaryWriter _writer; private BsonToken _root; private BsonToken _parent; private string _propertyName; public DateTimeKind DateTimeKindHandling { get { return _writer.DateTimeKindHandling; } set { _writer.DateTimeKindHandling = value; } } public BsonWriter(Stream stream) { ValidationUtils.ArgumentNotNull(stream, "stream"); _writer = new BsonBinaryWriter(new BinaryWriter(stream)); } public BsonWriter(BinaryWriter writer) { ValidationUtils.ArgumentNotNull(writer, "writer"); _writer = new BsonBinaryWriter(writer); } public override void Flush() { _writer.Flush(); } protected override void WriteEnd(JsonToken token) { base.WriteEnd(token); RemoveParent(); if (base.Top == 0) { _writer.WriteToken(_root); } } public override void WriteComment(string text) { throw JsonWriterException.Create(this, "Cannot write JSON comment as BSON.", null); } public override void WriteStartConstructor(string name) { throw JsonWriterException.Create(this, "Cannot write JSON constructor as BSON.", null); } public override void WriteRaw(string json) { throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null); } public override void WriteRawValue(string json) { throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null); } public override void WriteStartArray() { base.WriteStartArray(); AddParent(new BsonArray()); } public override void WriteStartObject() { base.WriteStartObject(); AddParent(new BsonObject()); } public override void WritePropertyName(string name) { base.WritePropertyName(name); _propertyName = name; } public override void Close() { base.Close(); if (base.CloseOutput) { _writer?.Close(); } } private void AddParent(BsonToken container) { AddToken(container); _parent = container; } private void RemoveParent() { _parent = _parent.Parent; } private void AddValue(object value, BsonType type) { AddToken(new BsonValue(value, type)); } internal void AddToken(BsonToken token) { if (_parent != null) { if (_parent is BsonObject bsonObject) { bsonObject.Add(_propertyName, token); _propertyName = null; } else { ((BsonArray)_parent).Add(token); } return; } if (token.Type != BsonType.Object && token.Type != BsonType.Array) { throw JsonWriterException.Create(this, "Error writing {0} value. BSON must start with an Object or Array.".FormatWith(CultureInfo.InvariantCulture, token.Type), null); } _parent = token; _root = token; } public override void WriteValue(object value) { if (value is BigInteger bigInteger) { SetWriteState(JsonToken.Integer, null); AddToken(new BsonBinary(bigInteger.ToByteArray(), BsonBinaryType.Binary)); } else { base.WriteValue(value); } } public override void WriteNull() { base.WriteNull(); AddToken(BsonEmpty.Null); } public override void WriteUndefined() { base.WriteUndefined(); AddToken(BsonEmpty.Undefined); } public override void WriteValue(string value) { base.WriteValue(value); AddToken((value == null) ? BsonEmpty.Null : new BsonString(value, includeLength: true)); } public override void WriteValue(int value) { base.WriteValue(value); AddValue(value, BsonType.Integer); } [CLSCompliant(false)] public override void WriteValue(uint value) { if (value > int.MaxValue) { throw JsonWriterException.Create(this, "Value is too large to fit in a signed 32 bit integer. BSON does not support unsigned values.", null); } base.WriteValue(value); AddValue(value, BsonType.Integer); } public override void WriteValue(long value) { base.WriteValue(value); AddValue(value, BsonType.Long); } [CLSCompliant(false)] public override void WriteValue(ulong value) { if (value > long.MaxValue) { throw JsonWriterException.Create(this, "Value is too large to fit in a signed 64 bit integer. BSON does not support unsigned values.", null); } base.WriteValue(value); AddValue(value, BsonType.Long); } public override void WriteValue(float value) { base.WriteValue(value); AddValue(value, BsonType.Number); } public override void WriteValue(double value) { base.WriteValue(value); AddValue(value, BsonType.Number); } public override void WriteValue(bool value) { base.WriteValue(value); AddToken(value ? BsonBoolean.True : BsonBoolean.False); } public override void WriteValue(short value) { base.WriteValue(value); AddValue(value, BsonType.Integer); } [CLSCompliant(false)] public override void WriteValue(ushort value) { base.WriteValue(value); AddValue(value, BsonType.Integer); } public override void WriteValue(char value) { base.WriteValue(value); string text = null; text = value.ToString(CultureInfo.InvariantCulture); AddToken(new BsonString(text, includeLength: true)); } public override void WriteValue(byte value) { base.WriteValue(value); AddValue(value, BsonType.Integer); } [CLSCompliant(false)] public override void WriteValue(sbyte value) { base.WriteValue(value); AddValue(value, BsonType.Integer); } public override void WriteValue(decimal value) { base.WriteValue(value); AddValue(value, BsonType.Number); } public override void WriteValue(DateTime value) { base.WriteValue(value); value = DateTimeUtils.EnsureDateTime(value, base.DateTimeZoneHandling); AddValue(value, BsonType.Date); } public override void WriteValue(DateTimeOffset value) { base.WriteValue(value); AddValue(value, BsonType.Date); } public override void WriteValue(byte[] value) { if (value == null) { WriteNull(); return; } base.WriteValue(value); AddToken(new BsonBinary(value, BsonBinaryType.Binary)); } public override void WriteValue(Guid value) { base.WriteValue(value); AddToken(new BsonBinary(value.ToByteArray(), BsonBinaryType.Uuid)); } public override void WriteValue(TimeSpan value) { base.WriteValue(value); AddToken(new BsonString(value.ToString(), includeLength: true)); } public override void WriteValue(Uri value) { if (value == null) { WriteNull(); return; } base.WriteValue(value); AddToken(new BsonString(value.ToString(), includeLength: true)); } public void WriteObjectId(byte[] value) { ValidationUtils.ArgumentNotNull(value, "value"); if (value.Length != 12) { throw JsonWriterException.Create(this, "An object id must be 12 bytes", null); } SetWriteState(JsonToken.Undefined, null); AddValue(value, BsonType.Oid); } public void WriteRegex(string pattern, string options) { ValidationUtils.ArgumentNotNull(pattern, "pattern"); SetWriteState(JsonToken.Undefined, null); AddToken(new BsonRegex(pattern, options)); } } } [CompilerGenerated] internal sealed class <915b4a23-253f-4570-818a-19dc2cad19c9> { [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 6)] private struct __StaticArrayInitTypeSize=6 { } [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 10)] private struct __StaticArrayInitTypeSize=10 { } [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 16)] private struct __StaticArrayInitTypeSize=16 { } [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 20)] private struct __StaticArrayInitTypeSize=20 { } [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 24)] private struct __StaticArrayInitTypeSize=24 { } [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 28)] private struct __StaticArrayInitTypeSize=28 { } [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 36)] private struct __StaticArrayInitTypeSize=36 { } [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 40)] private struct __StaticArrayInitTypeSize=40 { } [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 44)] private struct __StaticArrayInitTypeSize=44 { } [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 52)] private struct __StaticArrayInitTypeSize=52 { } internal static readonly __StaticArrayInitTypeSize=44 0698228BF899CAEAB9A53E5E6C7099E846C44F56432050D234DDF03AD772F139/* Not supported: data(0C 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 05 00 00 00 0D 00 00 00 09 00 00 00 0E 00 00 00 0F 00 00 00 11 00 00 00 10 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=10 19AE20A57B073E3E8DD45C6F6A4E9AB1076EA3EBFFF28E4AEB58B411472CF994/* Not supported: data(22 00 27 00 3C 00 3E 00 26 00) */; internal static readonly __StaticArrayInitTypeSize=40 223D6CA32241C349E421A0164F2341E20CC5B65D5A04AA021CFF71D623895570/* Not supported: data(02 00 00 00 02 00 00 00 09 00 00 00 09 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 09 00 00 00 09 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=20 33350F5DA385CE1B8749AEC68BA060CD54EE981968522B5EDF62178537A1FEEE/* Not supported: data(06 00 00 00 07 00 00 00 08 00 00 00 05 00 00 00 0D 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=40 38809B9974198671140931F729415F3FD75DF68A6398E3486AE3B58554329A63/* Not supported: data(04 00 00 00 04 00 00 00 09 00 00 00 09 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 09 00 00 00 09 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=28 499E4F5C84E20C7347E10100E0EC90C1945EA21C7C80809E4F7F474179B39DF6/* Not supported: data(FF FF FF FF 0A 00 00 00 64 00 00 00 E8 03 00 00 10 27 00 00 A0 86 01 00 40 42 0F 00) */; internal static readonly __StaticArrayInitTypeSize=16 4EDE3546F1189E450DF4D4A2739BE90BEB3B1708B3B9F406B02E0773A92A10FF/* Not supported: data(08 00 00 00 05 00 00 00 0D 00 00 00 11 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=52 5857EE4CE98BFABBD62B385C1098507DD0052FF3951043AAD6A1DABD495F18AA/* Not supported: data(00 00 00 00 1F 00 00 00 3B 00 00 00 5A 00 00 00 78 00 00 00 97 00 00 00 B5 00 00 00 D4 00 00 00 F3 00 00 00 11 01 00 00 30 01 00 00 4E 01 00 00 6D 01 00 00) */; internal static readonly __StaticArrayInitTypeSize=28 5ADB7CA81690556AB2A3201A849839FA3562604BB469382C7D6D78AB426283E2/* Not supported: data(06 00 00 00 07 00 00 00 08 00 00 00 05 00 00 00 0D 00 00 00 09 00 00 00 0E 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=24 5DDF815AC046E7D4603FA586D1BDE42118AD4FE9875D64F716BC7D2740EE52C9/* Not supported: data(06 00 00 00 07 00 00 00 08 00 00 00 05 00 00 00 0D 00 00 00 09 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=16 605A3F93AE7A97E00C156F977E942027EA532E263A5B440A4219984F803FDD04/* Not supported: data(0C 00 00 00 08 00 00 00 05 00 00 00 0D 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=36 7367A65185E4F747AA29364AB199D01646A010A62129A6BA2E35E929D7294D62/* Not supported: data(2E 00 20 00 27 00 2F 00 22 00 5B 00 5D 00 28 00 29 00 09 00 0A 00 0D 00 0C 00 08 00 5C 00 85 00 28 20 29 20) */; internal static readonly __StaticArrayInitTypeSize=40 7439A4C9E30AC42BCC55AD1A2B617E29E7129B6DDAC79C886944B17819262CC1/* Not supported: data(06 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 06 00 00 00 09 00 00 00 09 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=6 772907508FD7AA0ED404C8FC80B6B772E26D67FA3C3662C22D62B871067C28DA/* Not supported: data(2E 00 45 00 65 00) */; internal static readonly __StaticArrayInitTypeSize=40 990F3F1286CC3928725497B2745CFF7BC7C9803B4EB8271611540BA6BF6654B5/* Not supported: data(00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 07 00 00 00 07 00 00 00 09 00 00 00 09 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=16 A8636D08B42D058EFC34703DD37B6468FCE56138DF242B862C3F1CA138CB3B89/* Not supported: data(08 00 00 00 05 00 00 00 0D 00 00 00 10 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=20 B1D1BCD1D06B4A563944BE3C67D51F63DF23702E5BE760D7897C6AD1F51C6122/* Not supported: data(08 00 00 00 05 00 00 00 0D 00 00 00 0F 00 00 00 0E 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=20 CAA07D7573596B3356BD202533F0EAFDD05309981F270193A99E300D57587326/* Not supported: data(0E 00 00 00 08 00 00 00 05 00 00 00 0D 00 00 00 06 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=40 D4B3B8EBA0589FC38724A0D318B46104B07BC528744109ED69ED71604B7EEC1A/* Not supported: data(01 00 00 00 09 00 00 00 01 00 00 00 01 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=40 F6EDC1733B068F457C63E03BB041B9AB6BFAD5CD7673D3E0841968D3FBCB12C7/* Not supported: data(09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00) */; internal static readonly __StaticArrayInitTypeSize=52 FADB218011E7702BB9575D0C32A685DA10B5C72EB809BD9A955DB1C76E4D8315/* Not supported: data(00 00 00 00 1F 00 00 00 3C 00 00 00 5B 00 00 00 79 00 00 00 98 00 00 00 B6 00 00 00 D5 00 00 00 F4 00 00 00 12 01 00 00 31 01 00 00 4F 01 00 00 6E 01 00 00) */; internal static readonly __StaticArrayInitTypeSize=40 FCA56C548368F7065472C8C8EE4D63921B4F16BB51181EC202A0C252D5209E6A/* Not supported: data(00 00 00 00 03 00 00 00 09 00 00 00 09 00 00 00 05 00 00 00 05 00 00 00 07 00 00 00 07 00 00 00 09 00 00 00 09 00 00 00) */; internal static uint ComputeStringHash(string s) { uint num = default(uint); if (s != null) { num = 2166136261u; for (int i = 0; i < s.Length; i++) { num = (s[i] ^ num) * 16777619; } } return num; } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } namespace DSharpPlus { internal enum AnsiColor { Reset = 0, Bold = 1, Underline = 4, Black = 30, Red = 31, Green = 32, Yellow = 33, Blue = 34, Magenta = 35, Cyan = 36, White = 37, LightGray = 38, BlackBackground = 40, RedBackground = 41, GreenBackground = 42, YellowBackground = 43, BlueBackground = 44, MagentaBackground = 45, CyanBackground = 46, WhiteBackground = 47 } internal class AsyncManualResetEvent { private TaskCompletionSource _tsc; public bool IsSet { get { if (_tsc != null) { return _tsc.Task.IsCompleted; } return false; } } public AsyncManualResetEvent() : this(initialState: false) { } public AsyncManualResetEvent(bool initialState) { _tsc = new TaskCompletionSource(); if (initialState) { _tsc.TrySetResult(result: true); } } public Task WaitAsync() { return _tsc.Task; } public Task SetAsync() { return Task.Run(() => _tsc.TrySetResult(result: true)); } public void Reset() { TaskCompletionSource tsc; do { tsc = _tsc; } while (tsc.Task.IsCompleted && Interlocked.CompareExchange(ref _tsc, new TaskCompletionSource(), tsc) != tsc); } } internal abstract class BaseExtension : IDisposable { public DiscordClient Client { get; protected set; } public abstract void Dispose(); protected internal abstract void Setup(DiscordClient client); } internal abstract class BaseDiscordClient : IDisposable { internal Lazy> _voice_regions_lazy; protected internal DiscordApiClient ApiClient { get; } protected internal DiscordConfiguration Configuration { get; } public ILogger Logger { get; } public string VersionString { get; } public DiscordUser CurrentUser { get; internal set; } public DiscordApplication CurrentApplication { get; internal set; } public abstract IReadOnlyDictionary Guilds { get; } protected internal ConcurrentDictionary UserCache { get; } public IReadOnlyDictionary VoiceRegions => _voice_regions_lazy.Value; protected internal ConcurrentDictionary InternalVoiceRegions { get; set; } internal BaseDiscordClient(DiscordConfiguration config, RestClient restClient = null) { Configuration = new DiscordConfiguration(config); if (Configuration.LoggerFactory == null) { Configuration.LoggerFactory = new DefaultLoggerFactory(); Configuration.LoggerFactory.AddProvider(new DefaultLoggerProvider(this)); } Logger = Configuration.LoggerFactory.CreateLogger(); ApiClient = new DiscordApiClient(this, restClient); UserCache = new ConcurrentDictionary(); InternalVoiceRegions = new ConcurrentDictionary(); _voice_regions_lazy = new Lazy>(() => new ReadOnlyDictionary(InternalVoiceRegions)); Assembly assembly = typeof(DiscordClient).GetTypeInfo().Assembly; AssemblyInformationalVersionAttribute customAttribute = assembly.GetCustomAttribute(); if (customAttribute != null) { VersionString = customAttribute.InformationalVersion; return; } Version version = assembly.GetName().Version; string arg = version.ToString(3); if (version.Revision > 0) { VersionString = $"{arg}, CI build {version.Revision}"; } } public async Task GetCurrentApplicationAsync() { TransportApplication tapp = await ApiClient.GetCurrentApplicationInfoAsync().ConfigureAwait(continueOnCapturedContext: false); DiscordApplication app = new DiscordApplication { Discord = this, Id = tapp.Id, Name = tapp.Name, Description = tapp.Description, Summary = tapp.Summary, IconHash = tapp.IconHash, TermsOfServiceUrl = tapp.TermsOfServiceUrl, PrivacyPolicyUrl = tapp.PrivacyPolicyUrl, RpcOrigins = ((tapp.RpcOrigins != null) ? new ReadOnlyCollection(tapp.RpcOrigins) : null), Flags = tapp.Flags, RequiresCodeGrant = tapp.BotRequiresCodeGrant, IsPublic = tapp.IsPublicBot, CoverImageHash = null }; if (tapp.Team == null) { app.Owners = new ReadOnlyCollection(new DiscordUser[1] { new DiscordUser(tapp.Owner) }); app.Team = null; } else { app.Team = new DiscordTeam(tapp.Team); DiscordTeamMember[] array = tapp.Team.Members.Select((TransportTeamMember x) => new DiscordTeamMember(x) { Team = app.Team, User = new DiscordUser(x.User) }).ToArray(); DiscordUser[] array2 = (from x in array where x.MembershipStatus == DiscordTeamMembershipStatus.Accepted select x.User).ToArray(); app.Owners = new ReadOnlyCollection(array2); app.Team.Owner = array2.FirstOrDefault((DiscordUser x) => x.Id == tapp.Team.OwnerId); app.Team.Members = new ReadOnlyCollection(array); } return app; } public Task> ListVoiceRegionsAsync() { return ApiClient.ListVoiceRegionsAsync(); } public virtual async Task InitializeAsync() { if (CurrentUser == null) { CurrentUser = await ApiClient.GetCurrentUserAsync().ConfigureAwait(continueOnCapturedContext: false); UpdateUserCache(CurrentUser); } if (Configuration.TokenType == TokenType.Bot && CurrentApplication == null) { CurrentApplication = await GetCurrentApplicationAsync().ConfigureAwait(continueOnCapturedContext: false); } if (Configuration.TokenType == TokenType.Bearer || InternalVoiceRegions.Count != 0) { return; } foreach (DiscordVoiceRegion item in await ListVoiceRegionsAsync().ConfigureAwait(continueOnCapturedContext: false)) { InternalVoiceRegions.TryAdd(item.Id, item); } } public async Task GetGatewayInfoAsync(string token = null) { if (Configuration.TokenType != TokenType.Bot) { throw new InvalidOperationException("Only bot tokens can access this info."); } if (string.IsNullOrEmpty(Configuration.Token)) { if (string.IsNullOrEmpty(token)) { throw new InvalidOperationException("Could not locate a valid token."); } Configuration.Token = token; GatewayInfo result = await ApiClient.GetGatewayInfoAsync().ConfigureAwait(continueOnCapturedContext: false); Configuration.Token = null; return result; } return await ApiClient.GetGatewayInfoAsync().ConfigureAwait(continueOnCapturedContext: false); } internal DiscordUser GetCachedOrEmptyUserInternal(ulong user_id) { TryGetCachedUserInternal(user_id, out var user); return user; } internal bool TryGetCachedUserInternal(ulong user_id, out DiscordUser user) { if (UserCache.TryGetValue(user_id, out user)) { return true; } user = new DiscordUser { Id = user_id, Discord = this }; return false; } internal DiscordUser UpdateUserCache(DiscordUser newUser) { return UserCache.AddOrUpdate(newUser.Id, newUser, (ulong _, DiscordUser _) => newUser); } public abstract void Dispose(); } internal sealed class DiscordClient : BaseDiscordClient { internal bool _isShard; private List _extensions = new List(); private StatusUpdate _status; internal ConcurrentDictionary _privateChannels = new ConcurrentDictionary(); internal ConcurrentDictionary _guilds = new ConcurrentDictionary(); private int _ping; internal Dictionary _presences = new Dictionary(); private Lazy> _presencesLazy; private bool _disposed; private string _sessionId; private bool _guildDownloadCompleted; private AsyncEvent _socketErrored; private AsyncEvent _socketOpened; private AsyncEvent _socketClosed; private AsyncEvent _ready; private AsyncEvent _resumed; private AsyncEvent _heartbeated; private AsyncEvent _zombied; private AsyncEvent _channelCreated; private AsyncEvent _channelUpdated; private AsyncEvent _channelDeleted; private AsyncEvent _dmChannelDeleted; private AsyncEvent _channelPinsUpdated; private AsyncEvent _guildCreated; private AsyncEvent _guildAvailable; private AsyncEvent _guildUpdated; private AsyncEvent _guildDeleted; private AsyncEvent _guildUnavailable; private AsyncEvent _guildDownloadCompletedEv; private AsyncEvent _guildEmojisUpdated; private AsyncEvent _guildStickersUpdated; private AsyncEvent _guildIntegrationsUpdated; private AsyncEvent _scheduledGuildEventCreated; private AsyncEvent _scheduledGuildEventUpdated; private AsyncEvent _scheduledGuildEventDeleted; private AsyncEvent _scheduledGuildEventCompleted; private AsyncEvent _scheduledGuildEventUserAdded; private AsyncEvent _scheduledGuildEventUserRemoved; private AsyncEvent _guildBanAdded; private AsyncEvent _guildBanRemoved; private AsyncEvent _guildMemberAdded; private AsyncEvent _guildMemberRemoved; private AsyncEvent _guildMemberUpdated; private AsyncEvent _guildMembersChunked; private AsyncEvent _guildRoleCreated; private AsyncEvent _guildRoleUpdated; private AsyncEvent _guildRoleDeleted; private AsyncEvent _inviteCreated; private AsyncEvent _inviteDeleted; private AsyncEvent _messageCreated; private AsyncEvent _messageAcknowledged; private AsyncEvent _messageUpdated; private AsyncEvent _messageDeleted; private AsyncEvent _messagesBulkDeleted; private AsyncEvent _messageReactionAdded; private AsyncEvent _messageReactionRemoved; private AsyncEvent _messageReactionsCleared; private AsyncEvent _messageReactionRemovedEmoji; private AsyncEvent _presenceUpdated; private AsyncEvent _userSettingsUpdated; private AsyncEvent _userUpdated; private AsyncEvent _voiceStateUpdated; private AsyncEvent _voiceServerUpdated; private AsyncEvent _threadCreated; private AsyncEvent _threadUpdated; private AsyncEvent _threadDeleted; private AsyncEvent _threadListSynced; private AsyncEvent _threadMemberUpdated; private AsyncEvent _threadMembersUpdated; private AsyncEvent _applicationCommandCreated; private AsyncEvent _applicationCommandUpdated; private AsyncEvent _applicationCommandDeleted; private AsyncEvent _applicationCommandPermissionsUpdated; private AsyncEvent _integrationCreated; private AsyncEvent _integrationUpdated; private AsyncEvent _integrationDeleted; private AsyncEvent _stageInstanceCreated; private AsyncEvent _stageInstanceUpdated; private AsyncEvent _stageInstanceDeleted; private AsyncEvent _interactionCreated; private AsyncEvent _componentInteractionCreated; private AsyncEvent _modalSubmitted; private AsyncEvent _contextMenuInteractionCreated; private AsyncEvent _typingStarted; private AsyncEvent _unknownEvent; private AsyncEvent _webhooksUpdated; private AsyncEvent _clientErrored; private int _heartbeatInterval; private DateTimeOffset _lastHeartbeat; private Task _heartbeatTask; internal static readonly DateTimeOffset _discordEpoch = new DateTimeOffset(2015, 1, 1, 0, 0, 0, TimeSpan.Zero); private int _skippedHeartbeats; private long _lastSequence; internal IWebSocketClient _webSocketClient; private PayloadDecompressor _payloadDecompressor; private CancellationTokenSource _cancelTokenSource; private CancellationToken _cancelToken; internal RingBuffer MessageCache { get; } private ManualResetEventSlim ConnectionLock { get; } = new ManualResetEventSlim(initialState: true); public int GatewayVersion { get; internal set; } public GatewayInfo GatewayInfo { get; internal set; } public Uri GatewayUri { get; internal set; } public int ShardCount { get { if (GatewayInfo == null) { return base.Configuration.ShardCount; } return GatewayInfo.ShardCount; } } public int ShardId => base.Configuration.ShardId; public DiscordIntents Intents => base.Configuration.Intents; public IReadOnlyDictionary PrivateChannels { get; } public override IReadOnlyDictionary Guilds { get; } public int Ping => Volatile.Read(ref _ping); public IReadOnlyDictionary Presences => _presencesLazy.Value; internal static TimeSpan EventExecutionLimit { get; } = TimeSpan.FromSeconds(1.0); private static ConcurrentDictionary _socketLocks { get; } = new ConcurrentDictionary(); private ManualResetEventSlim _sessionLock { get; } = new ManualResetEventSlim(initialState: true); public event AsyncEventHandler SocketErrored { add { _socketErrored.Register(value); } remove { _socketErrored.Unregister(value); } } public event AsyncEventHandler SocketOpened { add { _socketOpened.Register(value); } remove { _socketOpened.Unregister(value); } } public event AsyncEventHandler SocketClosed { add { _socketClosed.Register(value); } remove { _socketClosed.Unregister(value); } } public event AsyncEventHandler Ready { add { _ready.Register(value); } remove { _ready.Unregister(value); } } public event AsyncEventHandler Resumed { add { _resumed.Register(value); } remove { _resumed.Unregister(value); } } public event AsyncEventHandler Heartbeated { add { _heartbeated.Register(value); } remove { _heartbeated.Unregister(value); } } public event AsyncEventHandler Zombied { add { _zombied.Register(value); } remove { _zombied.Unregister(value); } } public event AsyncEventHandler ChannelCreated { add { _channelCreated.Register(value); } remove { _channelCreated.Unregister(value); } } public event AsyncEventHandler ChannelUpdated { add { _channelUpdated.Register(value); } remove { _channelUpdated.Unregister(value); } } public event AsyncEventHandler ChannelDeleted { add { _channelDeleted.Register(value); } remove { _channelDeleted.Unregister(value); } } public event AsyncEventHandler DmChannelDeleted { add { _dmChannelDeleted.Register(value); } remove { _dmChannelDeleted.Unregister(value); } } public event AsyncEventHandler ChannelPinsUpdated { add { _channelPinsUpdated.Register(value); } remove { _channelPinsUpdated.Unregister(value); } } public event AsyncEventHandler GuildCreated { add { _guildCreated.Register(value); } remove { _guildCreated.Unregister(value); } } public event AsyncEventHandler GuildAvailable { add { _guildAvailable.Register(value); } remove { _guildAvailable.Unregister(value); } } public event AsyncEventHandler GuildUpdated { add { _guildUpdated.Register(value); } remove { _guildUpdated.Unregister(value); } } public event AsyncEventHandler GuildDeleted { add { _guildDeleted.Register(value); } remove { _guildDeleted.Unregister(value); } } public event AsyncEventHandler GuildUnavailable { add { _guildUnavailable.Register(value); } remove { _guildUnavailable.Unregister(value); } } public event AsyncEventHandler GuildDownloadCompleted { add { _guildDownloadCompletedEv.Register(value); } remove { _guildDownloadCompletedEv.Unregister(value); } } public event AsyncEventHandler GuildEmojisUpdated { add { _guildEmojisUpdated.Register(value); } remove { _guildEmojisUpdated.Unregister(value); } } public event AsyncEventHandler GuildStickersUpdated { add { _guildStickersUpdated.Register(value); } remove { _guildStickersUpdated.Unregister(value); } } public event AsyncEventHandler GuildIntegrationsUpdated { add { _guildIntegrationsUpdated.Register(value); } remove { _guildIntegrationsUpdated.Unregister(value); } } public event AsyncEventHandler ScheduledGuildEventCreated { add { _scheduledGuildEventCreated.Register(value); } remove { _scheduledGuildEventCreated.Unregister(value); } } public event AsyncEventHandler ScheduledGuildEventUpdated { add { _scheduledGuildEventUpdated.Register(value); } remove { _scheduledGuildEventUpdated.Unregister(value); } } public event AsyncEventHandler ScheduledGuildEventDeleted { add { _scheduledGuildEventDeleted.Register(value); } remove { _scheduledGuildEventDeleted.Unregister(value); } } public event AsyncEventHandler ScheduledGuildEventCompleted { add { _scheduledGuildEventCompleted.Register(value); } remove { _scheduledGuildEventCompleted.Unregister(value); } } public event AsyncEventHandler ScheduledGuildEventUserAdded { add { _scheduledGuildEventUserAdded.Register(value); } remove { _scheduledGuildEventUserAdded.Unregister(value); } } public event AsyncEventHandler ScheduledGuildEventUserRemoved { add { _scheduledGuildEventUserRemoved.Register(value); } remove { _scheduledGuildEventUserRemoved.Unregister(value); } } public event AsyncEventHandler GuildBanAdded { add { _guildBanAdded.Register(value); } remove { _guildBanAdded.Unregister(value); } } public event AsyncEventHandler GuildBanRemoved { add { _guildBanRemoved.Register(value); } remove { _guildBanRemoved.Unregister(value); } } public event AsyncEventHandler GuildMemberAdded { add { _guildMemberAdded.Register(value); } remove { _guildMemberAdded.Unregister(value); } } public event AsyncEventHandler GuildMemberRemoved { add { _guildMemberRemoved.Register(value); } remove { _guildMemberRemoved.Unregister(value); } } public event AsyncEventHandler GuildMemberUpdated { add { _guildMemberUpdated.Register(value); } remove { _guildMemberUpdated.Unregister(value); } } public event AsyncEventHandler GuildMembersChunked { add { _guildMembersChunked.Register(value); } remove { _guildMembersChunked.Unregister(value); } } public event AsyncEventHandler GuildRoleCreated { add { _guildRoleCreated.Register(value); } remove { _guildRoleCreated.Unregister(value); } } public event AsyncEventHandler GuildRoleUpdated { add { _guildRoleUpdated.Register(value); } remove { _guildRoleUpdated.Unregister(value); } } public event AsyncEventHandler GuildRoleDeleted { add { _guildRoleDeleted.Register(value); } remove { _guildRoleDeleted.Unregister(value); } } public event AsyncEventHandler InviteCreated { add { _inviteCreated.Register(value); } remove { _inviteCreated.Unregister(value); } } public event AsyncEventHandler InviteDeleted { add { _inviteDeleted.Register(value); } remove { _inviteDeleted.Unregister(value); } } public event AsyncEventHandler MessageCreated { add { _messageCreated.Register(value); } remove { _messageCreated.Unregister(value); } } public event AsyncEventHandler MessageAcknowledged { add { _messageAcknowledged.Register(value); } remove { _messageAcknowledged.Unregister(value); } } public event AsyncEventHandler MessageUpdated { add { _messageUpdated.Register(value); } remove { _messageUpdated.Unregister(value); } } public event AsyncEventHandler MessageDeleted { add { _messageDeleted.Register(value); } remove { _messageDeleted.Unregister(value); } } public event AsyncEventHandler MessagesBulkDeleted { add { _messagesBulkDeleted.Register(value); } remove { _messagesBulkDeleted.Unregister(value); } } public event AsyncEventHandler MessageReactionAdded { add { _messageReactionAdded.Register(value); } remove { _messageReactionAdded.Unregister(value); } } public event AsyncEventHandler MessageReactionRemoved { add { _messageReactionRemoved.Register(value); } remove { _messageReactionRemoved.Unregister(value); } } public event AsyncEventHandler MessageReactionsCleared { add { _messageReactionsCleared.Register(value); } remove { _messageReactionsCleared.Unregister(value); } } public event AsyncEventHandler MessageReactionRemovedEmoji { add { _messageReactionRemovedEmoji.Register(value); } remove { _messageReactionRemovedEmoji.Unregister(value); } } public event AsyncEventHandler PresenceUpdated { add { _presenceUpdated.Register(value); } remove { _presenceUpdated.Unregister(value); } } public event AsyncEventHandler UserSettingsUpdated { add { _userSettingsUpdated.Register(value); } remove { _userSettingsUpdated.Unregister(value); } } public event AsyncEventHandler UserUpdated { add { _userUpdated.Register(value); } remove { _userUpdated.Unregister(value); } } public event AsyncEventHandler VoiceStateUpdated { add { _voiceStateUpdated.Register(value); } remove { _voiceStateUpdated.Unregister(value); } } public event AsyncEventHandler VoiceServerUpdated { add { _voiceServerUpdated.Register(value); } remove { _voiceServerUpdated.Unregister(value); } } public event AsyncEventHandler ThreadCreated { add { _threadCreated.Register(value); } remove { _threadCreated.Unregister(value); } } public event AsyncEventHandler ThreadUpdated { add { _threadUpdated.Register(value); } remove { _threadUpdated.Unregister(value); } } public event AsyncEventHandler ThreadDeleted { add { _threadDeleted.Register(value); } remove { _threadDeleted.Unregister(value); } } public event AsyncEventHandler ThreadListSynced { add { _threadListSynced.Register(value); } remove { _threadListSynced.Unregister(value); } } public event AsyncEventHandler ThreadMemberUpdated { add { _threadMemberUpdated.Register(value); } remove { _threadMemberUpdated.Unregister(value); } } public event AsyncEventHandler ThreadMembersUpdated { add { _threadMembersUpdated.Register(value); } remove { _threadMembersUpdated.Unregister(value); } } [Obsolete("This event has been removed by discord and does not fire anymore.", false)] public event AsyncEventHandler ApplicationCommandCreated { add { _applicationCommandCreated.Register(value); } remove { _applicationCommandCreated.Unregister(value); } } [Obsolete("This event has been removed by discord and does not fire anymore.", false)] public event AsyncEventHandler ApplicationCommandUpdated { add { _applicationCommandUpdated.Register(value); } remove { _applicationCommandUpdated.Unregister(value); } } [Obsolete("This event has been removed by discord and does not fire anymore.", false)] public event AsyncEventHandler ApplicationCommandDeleted { add { _applicationCommandDeleted.Register(value); } remove { _applicationCommandDeleted.Unregister(value); } } [Obsolete("This event may be removed by discord and may not fire anymore.", false)] public event AsyncEventHandler ApplicationCommandPermissionsUpdated { add { _applicationCommandPermissionsUpdated.Register(value); } remove { _applicationCommandPermissionsUpdated.Unregister(value); } } public event AsyncEventHandler IntegrationCreated { add { _integrationCreated.Register(value); } remove { _integrationCreated.Unregister(value); } } public event AsyncEventHandler IntegrationUpdated { add { _integrationUpdated.Register(value); } remove { _integrationUpdated.Unregister(value); } } public event AsyncEventHandler IntegrationDeleted { add { _integrationDeleted.Register(value); } remove { _integrationDeleted.Unregister(value); } } public event AsyncEventHandler StageInstanceCreated { add { _stageInstanceCreated.Register(value); } remove { _stageInstanceCreated.Unregister(value); } } public event AsyncEventHandler StageInstanceUpdated { add { _stageInstanceUpdated.Register(value); } remove { _stageInstanceUpdated.Unregister(value); } } public event AsyncEventHandler StageInstanceDeleted { add { _stageInstanceDeleted.Register(value); } remove { _stageInstanceDeleted.Unregister(value); } } public event AsyncEventHandler InteractionCreated { add { _interactionCreated.Register(value); } remove { _interactionCreated.Unregister(value); } } public event AsyncEventHandler ComponentInteractionCreated { add { _componentInteractionCreated.Register(value); } remove { _componentInteractionCreated.Unregister(value); } } public event AsyncEventHandler ModalSubmitted { add { _modalSubmitted.Register(value); } remove { _modalSubmitted.Unregister(value); } } public event AsyncEventHandler ContextMenuInteractionCreated { add { _contextMenuInteractionCreated.Register(value); } remove { _contextMenuInteractionCreated.Unregister(value); } } public event AsyncEventHandler TypingStarted { add { _typingStarted.Register(value); } remove { _typingStarted.Unregister(value); } } public event AsyncEventHandler UnknownEvent { add { _unknownEvent.Register(value); } remove { _unknownEvent.Unregister(value); } } public event AsyncEventHandler WebhooksUpdated { add { _webhooksUpdated.Register(value); } remove { _webhooksUpdated.Unregister(value); } } public event AsyncEventHandler ClientErrored { add { _clientErrored.Register(value); } remove { _clientErrored.Unregister(value); } } public DiscordClient(DiscordConfiguration config) : base(config) { if (base.Configuration.MessageCacheSize > 0) { DiscordIntents intents = base.Configuration.Intents; MessageCache = ((intents.HasIntent(DiscordIntents.GuildMessages) || intents.HasIntent(DiscordIntents.DirectMessages)) ? new RingBuffer(base.Configuration.MessageCacheSize) : null); } InternalSetup(); Guilds = new ReadOnlyConcurrentDictionary(_guilds); PrivateChannels = new ReadOnlyConcurrentDictionary(_privateChannels); } internal DiscordClient(DiscordConfiguration config, RestClient restClient) : base(config, restClient) { if (base.Configuration.MessageCacheSize > 0) { DiscordIntents intents = base.Configuration.Intents; MessageCache = ((intents.HasIntent(DiscordIntents.GuildMessages) || intents.HasIntent(DiscordIntents.DirectMessages)) ? new RingBuffer(base.Configuration.MessageCacheSize) : null); } InternalSetup(); Guilds = new ReadOnlyConcurrentDictionary(_guilds); PrivateChannels = new ReadOnlyConcurrentDictionary(_privateChannels); } internal void InternalSetup() { _clientErrored = new AsyncEvent("CLIENT_ERRORED", Goof); _socketErrored = new AsyncEvent("SOCKET_ERRORED", Goof); _socketOpened = new AsyncEvent("SOCKET_OPENED", EventErrorHandler); _socketClosed = new AsyncEvent("SOCKET_CLOSED", EventErrorHandler); _ready = new AsyncEvent("READY", EventErrorHandler); _resumed = new AsyncEvent("RESUMED", EventErrorHandler); _channelCreated = new AsyncEvent("CHANNEL_CREATED", EventErrorHandler); _channelUpdated = new AsyncEvent("CHANNEL_UPDATED", EventErrorHandler); _channelDeleted = new AsyncEvent("CHANNEL_DELETED", EventErrorHandler); _dmChannelDeleted = new AsyncEvent("DM_CHANNEL_DELETED", EventErrorHandler); _channelPinsUpdated = new AsyncEvent("CHANNEL_PINS_UPDATED", EventErrorHandler); _guildCreated = new AsyncEvent("GUILD_CREATED", EventErrorHandler); _guildAvailable = new AsyncEvent("GUILD_AVAILABLE", EventErrorHandler); _guildUpdated = new AsyncEvent("GUILD_UPDATED", EventErrorHandler); _guildDeleted = new AsyncEvent("GUILD_DELETED", EventErrorHandler); _guildUnavailable = new AsyncEvent("GUILD_UNAVAILABLE", EventErrorHandler); _guildDownloadCompletedEv = new AsyncEvent("GUILD_DOWNLOAD_COMPLETED", EventErrorHandler); _inviteCreated = new AsyncEvent("INVITE_CREATED", EventErrorHandler); _inviteDeleted = new AsyncEvent("INVITE_DELETED", EventErrorHandler); _messageCreated = new AsyncEvent("MESSAGE_CREATED", EventErrorHandler); _presenceUpdated = new AsyncEvent("PRESENCE_UPDATED", EventErrorHandler); _scheduledGuildEventCreated = new AsyncEvent("SCHEDULED_GUILD_EVENT_CREATED", EventErrorHandler); _scheduledGuildEventDeleted = new AsyncEvent("SCHEDULED_GUILD_EVENT_DELETED", EventErrorHandler); _scheduledGuildEventUpdated = new AsyncEvent("SCHEDULED_GUILD_EVENT_UPDATED", EventErrorHandler); _scheduledGuildEventCompleted = new AsyncEvent("SCHEDULED_GUILD_EVENT_COMPLETED", EventErrorHandler); _scheduledGuildEventUserAdded = new AsyncEvent("SCHEDULED_GUILD_EVENT_USER_ADDED", EventErrorHandler); _scheduledGuildEventUserRemoved = new AsyncEvent("SCHEDULED_GUILD_EVENT_USER_REMOVED", EventErrorHandler); _guildBanAdded = new AsyncEvent("GUILD_BAN_ADD", EventErrorHandler); _guildBanRemoved = new AsyncEvent("GUILD_BAN_REMOVED", EventErrorHandler); _guildEmojisUpdated = new AsyncEvent("GUILD_EMOJI_UPDATED", EventErrorHandler); _guildStickersUpdated = new AsyncEvent("GUILD_STICKER_UPDATED", EventErrorHandler); _guildIntegrationsUpdated = new AsyncEvent("GUILD_INTEGRATIONS_UPDATED", EventErrorHandler); _guildMemberAdded = new AsyncEvent("GUILD_MEMBER_ADD", EventErrorHandler); _guildMemberRemoved = new AsyncEvent("GUILD_MEMBER_REMOVED", EventErrorHandler); _guildMemberUpdated = new AsyncEvent("GUILD_MEMBER_UPDATED", EventErrorHandler); _guildRoleCreated = new AsyncEvent("GUILD_ROLE_CREATED", EventErrorHandler); _guildRoleUpdated = new AsyncEvent("GUILD_ROLE_UPDATED", EventErrorHandler); _guildRoleDeleted = new AsyncEvent("GUILD_ROLE_DELETED", EventErrorHandler); _messageAcknowledged = new AsyncEvent("MESSAGE_ACKNOWLEDGED", EventErrorHandler); _messageUpdated = new AsyncEvent("MESSAGE_UPDATED", EventErrorHandler); _messageDeleted = new AsyncEvent("MESSAGE_DELETED", EventErrorHandler); _messagesBulkDeleted = new AsyncEvent("MESSAGE_BULK_DELETED", EventErrorHandler); _interactionCreated = new AsyncEvent("INTERACTION_CREATED", EventErrorHandler); _componentInteractionCreated = new AsyncEvent("COMPONENT_INTERACTED", EventErrorHandler); _modalSubmitted = new AsyncEvent("MODAL_SUBMITTED", EventErrorHandler); _contextMenuInteractionCreated = new AsyncEvent("CONTEXT_MENU_INTERACTED", EventErrorHandler); _typingStarted = new AsyncEvent("TYPING_STARTED", EventErrorHandler); _userSettingsUpdated = new AsyncEvent("USER_SETTINGS_UPDATED", EventErrorHandler); _userUpdated = new AsyncEvent("USER_UPDATED", EventErrorHandler); _voiceStateUpdated = new AsyncEvent("VOICE_STATE_UPDATED", EventErrorHandler); _voiceServerUpdated = new AsyncEvent("VOICE_SERVER_UPDATED", EventErrorHandler); _guildMembersChunked = new AsyncEvent("GUILD_MEMBERS_CHUNKED", EventErrorHandler); _unknownEvent = new AsyncEvent("UNKNOWN_EVENT", EventErrorHandler); _messageReactionAdded = new AsyncEvent("MESSAGE_REACTION_ADDED", EventErrorHandler); _messageReactionRemoved = new AsyncEvent("MESSAGE_REACTION_REMOVED", EventErrorHandler); _messageReactionsCleared = new AsyncEvent("MESSAGE_REACTIONS_CLEARED", EventErrorHandler); _messageReactionRemovedEmoji = new AsyncEvent("MESSAGE_REACTION_REMOVED_EMOJI", EventErrorHandler); _webhooksUpdated = new AsyncEvent("WEBHOOKS_UPDATED", EventErrorHandler); _heartbeated = new AsyncEvent("HEARTBEATED", EventErrorHandler); _zombied = new AsyncEvent("ZOMBIED", EventErrorHandler); _applicationCommandCreated = new AsyncEvent("APPLICATION_COMMAND_CREATED", EventErrorHandler); _applicationCommandUpdated = new AsyncEvent("APPLICATION_COMMAND_UPDATED", EventErrorHandler); _applicationCommandDeleted = new AsyncEvent("APPLICATION_COMMAND_DELETED", EventErrorHandler); _applicationCommandPermissionsUpdated = new AsyncEvent("APPLICATION_COMMAND_PERMISSIONS_UPDATED", EventErrorHandler); _integrationCreated = new AsyncEvent("INTEGRATION_CREATED", EventErrorHandler); _integrationUpdated = new AsyncEvent("INTEGRATION_UPDATED", EventErrorHandler); _integrationDeleted = new AsyncEvent("INTEGRATION_DELETED", EventErrorHandler); _stageInstanceCreated = new AsyncEvent("STAGE_INSTANCE_CREATED", EventErrorHandler); _stageInstanceUpdated = new AsyncEvent("STAGE_INSTANCE_UPDATED", EventErrorHandler); _stageInstanceDeleted = new AsyncEvent("STAGE_INSTANCE_DELETED", EventErrorHandler); _threadCreated = new AsyncEvent("THREAD_CREATED", EventErrorHandler); _threadUpdated = new AsyncEvent("THREAD_UPDATED", EventErrorHandler); _threadDeleted = new AsyncEvent("THREAD_DELETED", EventErrorHandler); _threadListSynced = new AsyncEvent("THREAD_LIST_SYNCED", EventErrorHandler); _threadMemberUpdated = new AsyncEvent("THREAD_MEMBER_UPDATED", EventErrorHandler); _threadMembersUpdated = new AsyncEvent("THREAD_MEMBERS_UPDATED", EventErrorHandler); _guilds.Clear(); _presencesLazy = new Lazy>(() => new ReadOnlyDictionary(_presences)); } public void AddExtension(BaseExtension ext) { ext.Setup(this); _extensions.Add(ext); } public T GetExtension() where T : BaseExtension { return _extensions.FirstOrDefault((BaseExtension x) => x.GetType() == typeof(T)) as T; } public async Task ConnectAsync(DiscordActivity activity = null, UserStatus? status = null, DateTimeOffset? idlesince = null) { if (!ConnectionLock.Wait(0)) { throw new InvalidOperationException("This client is already connected."); } ConnectionLock.Set(); int w = 7500; int i = 5; bool s = false; Exception cex = null; if (activity == null && !status.HasValue && !idlesince.HasValue) { _status = null; } else { long? idleSince = (idlesince.HasValue ? new long?(Utilities.GetUnixTime(idlesince.Value)) : null); _status = new StatusUpdate { Activity = new TransportActivity(activity), Status = status.GetValueOrDefault(UserStatus.Online), IdleSince = idleSince, IsAFK = idlesince.HasValue, _activity = activity }; } if (!_isShard) { if (base.Configuration.TokenType != TokenType.Bot) { base.Logger.LogWarning(LoggerEvents.Misc, "You are logging in with a token that is not a bot token. This is not officially supported by Discord, and can result in your account being terminated if you aren't careful."); } base.Logger.LogInformation(LoggerEvents.Startup, "DSharpPlus, version {Version}", base.VersionString); } while (i-- > 0 || base.Configuration.ReconnectIndefinitely) { try { await InternalConnectAsync().ConfigureAwait(continueOnCapturedContext: false); s = true; } catch (UnauthorizedException innerException) { FailConnection(ConnectionLock); throw new Exception("Authentication failed. Check your token and try again.", innerException); } catch (PlatformNotSupportedException) { FailConnection(ConnectionLock); throw; } catch (NotImplementedException) { FailConnection(ConnectionLock); throw; } catch (Exception ex3) { FailConnection(null); cex = ex3; if (i > 0 || base.Configuration.ReconnectIndefinitely) { base.Logger.LogError(LoggerEvents.ConnectionFailure, ex3, "Connection attempt failed, retrying in {Seconds}s", w / 1000); await Task.Delay(w).ConfigureAwait(continueOnCapturedContext: false); if (i > 0) { w *= 2; } continue; } } break; } if (!s && cex != null) { ConnectionLock.Set(); throw new Exception("Could not connect to Discord.", cex); } static void FailConnection(ManualResetEventSlim cl) { cl?.Set(); } } public Task ReconnectAsync(bool startNewSession = false) { return InternalReconnectAsync(startNewSession, startNewSession ? 1000 : 4002); } public async Task DisconnectAsync() { base.Configuration.AutoReconnect = false; if (_webSocketClient != null) { await _webSocketClient.DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false); } } public Task GetStickerAsync(ulong stickerId) { return base.ApiClient.GetStickerAsync(stickerId); } public Task> GetStickerPacksAsync() { return base.ApiClient.GetStickerPacksAsync(); } public async Task GetUserAsync(ulong userId, bool updateCache = false) { if (!updateCache && TryGetCachedUserInternal(userId, out var usr)) { return usr; } usr = await base.ApiClient.GetUserAsync(userId).ConfigureAwait(continueOnCapturedContext: false); base.UserCache.AddOrUpdate(userId, usr, (ulong _, DiscordUser _) => usr); return usr; } public async Task GetChannelAsync(ulong id) { DiscordChannel discordChannel = InternalGetCachedThread(id); if ((object)discordChannel == null) { DiscordChannel discordChannel2 = InternalGetCachedChannel(id); if ((object)discordChannel2 == null) { discordChannel2 = await base.ApiClient.GetChannelAsync(id).ConfigureAwait(continueOnCapturedContext: false); } discordChannel = discordChannel2; } return discordChannel; } public Task SendMessageAsync(DiscordChannel channel, string content) { return base.ApiClient.CreateMessageAsync(channel.Id, content, null, null, mentionReply: false, failOnInvalidReply: false, suppressNotifications: false); } public Task SendMessageAsync(DiscordChannel channel, DiscordEmbed embed) { return base.ApiClient.CreateMessageAsync(channel.Id, null, (embed == null) ? null : new DiscordEmbed[1] { embed }, null, mentionReply: false, failOnInvalidReply: false, suppressNotifications: false); } public Task SendMessageAsync(DiscordChannel channel, string content, DiscordEmbed embed) { return base.ApiClient.CreateMessageAsync(channel.Id, content, (embed == null) ? null : new DiscordEmbed[1] { embed }, null, mentionReply: false, failOnInvalidReply: false, suppressNotifications: false); } public Task SendMessageAsync(DiscordChannel channel, DiscordMessageBuilder builder) { return base.ApiClient.CreateMessageAsync(channel.Id, builder); } public Task SendMessageAsync(DiscordChannel channel, Action action) { DiscordMessageBuilder discordMessageBuilder = new DiscordMessageBuilder(); action(discordMessageBuilder); return base.ApiClient.CreateMessageAsync(channel.Id, discordMessageBuilder); } public Task CreateGuildAsync(string name, string region = null, Optional icon = default(Optional), VerificationLevel? verificationLevel = null, DefaultMessageNotifications? defaultMessageNotifications = null, SystemChannelFlags? systemChannelFlags = null) { Optional iconb = Optional.FromNoValue(); if (icon.HasValue && icon.Value != null) { using ImageTool imageTool = new ImageTool(icon.Value); iconb = imageTool.GetBase64(); } else if (icon.HasValue) { iconb = null; } return base.ApiClient.CreateGuildAsync(name, region, iconb, verificationLevel, defaultMessageNotifications, systemChannelFlags); } public Task CreateGuildFromTemplateAsync(string code, string name, Optional icon = default(Optional)) { Optional iconb = Optional.FromNoValue(); if (icon.HasValue && icon.Value != null) { using ImageTool imageTool = new ImageTool(icon.Value); iconb = imageTool.GetBase64(); } else if (icon.HasValue) { iconb = null; } return base.ApiClient.CreateGuildFromTemplateAsync(code, name, iconb); } public async Task GetGuildAsync(ulong id, bool? withCounts = null) { if (_guilds.TryGetValue(id, out var guild) && (!withCounts.HasValue || !withCounts.Value)) { return guild; } guild = await base.ApiClient.GetGuildAsync(id, withCounts).ConfigureAwait(continueOnCapturedContext: false); foreach (DiscordChannel item in await base.ApiClient.GetGuildChannelsAsync(guild.Id).ConfigureAwait(continueOnCapturedContext: false)) { guild._channels[item.Id] = item; } return guild; } public Task GetGuildPreviewAsync(ulong id) { return base.ApiClient.GetGuildPreviewAsync(id); } public Task GetInviteByCodeAsync(string code, bool? withCounts = null, bool? withExpiration = null) { return base.ApiClient.GetInviteAsync(code, withCounts, withExpiration); } public Task> GetConnectionsAsync() { return base.ApiClient.GetUsersConnectionsAsync(); } public Task GetWebhookAsync(ulong id) { return base.ApiClient.GetWebhookAsync(id); } public Task GetWebhookWithTokenAsync(ulong id, string token) { return base.ApiClient.GetWebhookWithTokenAsync(id, token); } public Task UpdateStatusAsync(DiscordActivity activity = null, UserStatus? userStatus = null, DateTimeOffset? idleSince = null) { return InternalUpdateStatusAsync(activity, userStatus, idleSince); } public async Task UpdateCurrentUserAsync(string username = null, Optional avatar = default(Optional)) { Optional base64_avatar = Optional.FromNoValue(); if (avatar.HasValue && avatar.Value != null) { using ImageTool imageTool = new ImageTool(avatar.Value); base64_avatar = imageTool.GetBase64(); } else if (avatar.HasValue) { base64_avatar = null; } TransportUser transportUser = await base.ApiClient.ModifyCurrentUserAsync(username, base64_avatar).ConfigureAwait(continueOnCapturedContext: false); base.CurrentUser.Username = transportUser.Username; base.CurrentUser.Discriminator = transportUser.Discriminator; base.CurrentUser.AvatarHash = transportUser.AvatarHash; return base.CurrentUser; } public Task GetTemplateAsync(string code) { return base.ApiClient.GetTemplateAsync(code); } public Task> GetGlobalApplicationCommandsAsync() { return base.ApiClient.GetGlobalApplicationCommandsAsync(base.CurrentApplication.Id); } public Task> BulkOverwriteGlobalApplicationCommandsAsync(IEnumerable commands) { return base.ApiClient.BulkOverwriteGlobalApplicationCommandsAsync(base.CurrentApplication.Id, commands); } public Task CreateGlobalApplicationCommandAsync(DiscordApplicationCommand command) { return base.ApiClient.CreateGlobalApplicationCommandAsync(base.CurrentApplication.Id, command); } public Task GetGlobalApplicationCommandAsync(ulong commandId) { return base.ApiClient.GetGlobalApplicationCommandAsync(base.CurrentApplication.Id, commandId); } public async Task GetGlobalApplicationCommandAsync(string commandName) { foreach (DiscordApplicationCommand item in await base.ApiClient.GetGlobalApplicationCommandsAsync(base.CurrentApplication.Id)) { if (item.Name == commandName) { return item; } } return null; } public async Task EditGlobalApplicationCommandAsync(ulong commandId, Action action) { ApplicationCommandEditModel mdl = new ApplicationCommandEditModel(); action(mdl); ulong num = base.CurrentApplication?.Id ?? (await GetCurrentApplicationAsync().ConfigureAwait(continueOnCapturedContext: false)).Id; ulong application_id = num; return await base.ApiClient.EditGlobalApplicationCommandAsync(application_id, commandId, mdl.Name, mdl.Description, mdl.Options, mdl.DefaultPermission, null, null, mdl.AllowDMUsage, mdl.DefaultMemberPermissions).ConfigureAwait(continueOnCapturedContext: false); } public Task DeleteGlobalApplicationCommandAsync(ulong commandId) { return base.ApiClient.DeleteGlobalApplicationCommandAsync(base.CurrentApplication.Id, commandId); } public Task> GetGuildApplicationCommandsAsync(ulong guildId) { return base.ApiClient.GetGuildApplicationCommandsAsync(base.CurrentApplication.Id, guildId); } public Task> BulkOverwriteGuildApplicationCommandsAsync(ulong guildId, IEnumerable commands) { return base.ApiClient.BulkOverwriteGuildApplicationCommandsAsync(base.CurrentApplication.Id, guildId, commands); } public Task CreateGuildApplicationCommandAsync(ulong guildId, DiscordApplicationCommand command) { return base.ApiClient.CreateGuildApplicationCommandAsync(base.CurrentApplication.Id, guildId, command); } public Task GetGuildApplicationCommandAsync(ulong guildId, ulong commandId) { return base.ApiClient.GetGuildApplicationCommandAsync(base.CurrentApplication.Id, guildId, commandId); } public async Task EditGuildApplicationCommandAsync(ulong guildId, ulong commandId, Action action) { ApplicationCommandEditModel mdl = new ApplicationCommandEditModel(); action(mdl); ulong num = base.CurrentApplication?.Id ?? (await GetCurrentApplicationAsync().ConfigureAwait(continueOnCapturedContext: false)).Id; ulong application_id = num; return await base.ApiClient.EditGuildApplicationCommandAsync(application_id, guildId, commandId, mdl.Name, mdl.Description, mdl.Options, mdl.DefaultPermission, null, null, mdl.AllowDMUsage, mdl.DefaultMemberPermissions).ConfigureAwait(continueOnCapturedContext: false); } public Task DeleteGuildApplicationCommandAsync(ulong guildId, ulong commandId) { return base.ApiClient.DeleteGuildApplicationCommandAsync(base.CurrentApplication.Id, guildId, commandId); } internal DiscordThreadChannel InternalGetCachedThread(ulong threadId) { foreach (DiscordGuild value2 in Guilds.Values) { if (value2.Threads.TryGetValue(threadId, out var value)) { return value; } } return null; } internal DiscordChannel InternalGetCachedChannel(ulong channelId) { DiscordDmChannel value = null; ConcurrentDictionary privateChannels = _privateChannels; if (privateChannels != null && privateChannels.TryGetValue(channelId, out value)) { return value; } foreach (DiscordGuild value3 in Guilds.Values) { if (value3.Channels.TryGetValue(channelId, out var value2)) { return value2; } } return null; } internal DiscordGuild InternalGetCachedGuild(ulong? guildId) { if (_guilds != null && guildId.HasValue && _guilds.TryGetValue(guildId.Value, out var value)) { return value; } return null; } private void UpdateMessage(DiscordMessage message, TransportUser author, DiscordGuild guild, TransportMember member) { if (author != null) { DiscordUser usr = new DiscordUser(author) { Discord = this }; if (member != null) { member.User = author; } message.Author = UpdateUser(usr, guild?.Id, guild, member); } DiscordChannel discordChannel = InternalGetCachedChannel(message.ChannelId) ?? InternalGetCachedThread(message.ChannelId); if (!(discordChannel != null)) { object obj; if (message._guildId.HasValue) { obj = new DiscordChannel { Id = message.ChannelId, GuildId = guild.Id, Discord = this }; } else { DiscordDmChannel discordDmChannel = new DiscordDmChannel(); discordDmChannel.Id = message.ChannelId; discordDmChannel.Discord = this; discordDmChannel.Type = ChannelType.Private; discordDmChannel.Recipients = new DiscordUser[1] { message.Author }; obj = discordDmChannel; } discordChannel = (DiscordChannel)obj; message.Channel = discordChannel; } } private DiscordUser UpdateUser(DiscordUser usr, ulong? guildId, DiscordGuild guild, TransportMember mbr) { if (mbr != null) { if (mbr.User != null) { usr = new DiscordUser(mbr.User) { Discord = this }; UpdateUserCache(usr); usr = new DiscordMember(mbr) { Discord = this, _guild_id = guildId.Value }; } DiscordIntents intents = base.Configuration.Intents; DiscordMember value = null; if (!intents.HasAllPrivilegedIntents() || guild.IsLarge) { if ((object)guild != null && !guild._members.TryGetValue(usr.Id, out value)) { if (intents.HasIntent(DiscordIntents.GuildMembers) || base.Configuration.AlwaysCacheMembers) { guild._members.TryAdd(usr.Id, (DiscordMember)usr); } } else if ((intents.HasIntent(DiscordIntents.GuildPresences) || base.Configuration.AlwaysCacheMembers) && !intents.HasIntent(DiscordIntents.GuildMembers)) { guild._members.TryUpdate(usr.Id, (DiscordMember)usr, value); } } } else if (usr.Username != null) { UpdateUserCache(usr); } return usr; } private void UpdateCachedGuild(DiscordGuild newGuild, JArray rawMembers) { if (_disposed) { return; } if (!_guilds.ContainsKey(newGuild.Id)) { _guilds[newGuild.Id] = newGuild; } DiscordGuild discordGuild = _guilds[newGuild.Id]; if (newGuild._channels != null && newGuild._channels.Count > 0) { foreach (DiscordChannel value4 in newGuild._channels.Values) { if (discordGuild._channels.TryGetValue(value4.Id, out var _)) { continue; } foreach (DiscordOverwrite permissionOverwrite in value4._permissionOverwrites) { permissionOverwrite.Discord = this; permissionOverwrite._channel_id = value4.Id; } discordGuild._channels[value4.Id] = value4; } } if (newGuild._threads != null && newGuild._threads.Count > 0) { foreach (DiscordThreadChannel value5 in newGuild._threads.Values) { if (!discordGuild._threads.TryGetValue(value5.Id, out var _)) { discordGuild._threads[value5.Id] = value5; } } } foreach (DiscordEmoji newEmoji in newGuild._emojis.Values) { discordGuild._emojis.GetOrAdd(newEmoji.Id, (ulong _) => newEmoji); } foreach (DiscordMessageSticker newSticker in newGuild._stickers.Values) { discordGuild._stickers.GetOrAdd(newSticker.Id, (ulong _) => newSticker); } if (rawMembers != null) { discordGuild._members.Clear(); foreach (JToken rawMember in rawMembers) { TransportMember transportMember = rawMember.ToDiscordObject(); DiscordUser newUser = new DiscordUser(transportMember.User) { Discord = this }; UpdateUserCache(newUser); discordGuild._members[transportMember.User.Id] = new DiscordMember(transportMember) { Discord = this, _guild_id = discordGuild.Id }; } } foreach (DiscordRole value6 in newGuild._roles.Values) { if (!discordGuild._roles.TryGetValue(value6.Id, out var _)) { value6._guild_id = discordGuild.Id; discordGuild._roles[value6.Id] = value6; } } if (newGuild._stageInstances != null) { foreach (DiscordStageInstance newStageInstance in newGuild._stageInstances.Values) { discordGuild._stageInstances.GetOrAdd(newStageInstance.Id, (ulong _) => newStageInstance); } } discordGuild.Name = newGuild.Name; discordGuild._afkChannelId = newGuild._afkChannelId; discordGuild.AfkTimeout = newGuild.AfkTimeout; discordGuild.DefaultMessageNotifications = newGuild.DefaultMessageNotifications; discordGuild.Features = newGuild.Features; discordGuild.IconHash = newGuild.IconHash; discordGuild.MfaLevel = newGuild.MfaLevel; discordGuild.OwnerId = newGuild.OwnerId; discordGuild._voiceRegionId = newGuild._voiceRegionId; discordGuild.SplashHash = newGuild.SplashHash; discordGuild.VerificationLevel = newGuild.VerificationLevel; discordGuild.WidgetEnabled = newGuild.WidgetEnabled; discordGuild._widgetChannelId = newGuild._widgetChannelId; discordGuild.ExplicitContentFilter = newGuild.ExplicitContentFilter; discordGuild.PremiumTier = newGuild.PremiumTier; discordGuild.PremiumSubscriptionCount = newGuild.PremiumSubscriptionCount; discordGuild.Banner = newGuild.Banner; discordGuild.Description = newGuild.Description; discordGuild.VanityUrlCode = newGuild.VanityUrlCode; discordGuild.Banner = newGuild.Banner; discordGuild._systemChannelId = newGuild._systemChannelId; discordGuild.SystemChannelFlags = newGuild.SystemChannelFlags; discordGuild.DiscoverySplashHash = newGuild.DiscoverySplashHash; discordGuild.MaxMembers = newGuild.MaxMembers; discordGuild.MaxPresences = newGuild.MaxPresences; discordGuild.ApproximateMemberCount = newGuild.ApproximateMemberCount; discordGuild.ApproximatePresenceCount = newGuild.ApproximatePresenceCount; discordGuild.MaxVideoChannelUsers = newGuild.MaxVideoChannelUsers; discordGuild.PreferredLocale = newGuild.PreferredLocale; discordGuild._rulesChannelId = newGuild._rulesChannelId; discordGuild._publicUpdatesChannelId = newGuild._publicUpdatesChannelId; discordGuild.PremiumProgressBarEnabled = newGuild.PremiumProgressBarEnabled; } private void PopulateMessageReactionsAndCache(DiscordMessage message, TransportUser author, TransportMember member) { DiscordGuild guild = message.Channel?.Guild ?? InternalGetCachedGuild(message._guildId); UpdateMessage(message, author, guild, member); if (message._reactions == null) { message._reactions = new List(); } foreach (DiscordReaction reaction in message._reactions) { reaction.Emoji.Discord = this; } if (base.Configuration.MessageCacheSize > 0 && message.Channel != null) { MessageCache?.Add(message); } } public override void Dispose() { if (_disposed) { return; } _disposed = true; DisconnectAsync().GetAwaiter().GetResult(); base.ApiClient?._rest?.Dispose(); base.CurrentUser = null; List extensions = _extensions; _extensions = null; foreach (BaseExtension item in extensions) { ((IDisposable)item)?.Dispose(); } try { _cancelTokenSource?.Cancel(); _cancelTokenSource?.Dispose(); } catch { } _guilds = null; _heartbeatTask = null; _privateChannels = null; } internal async Task HandleDispatchAsync(GatewayPayload payload) { if (!(payload.Data is JObject jObject)) { base.Logger.LogWarning(LoggerEvents.WebSocketReceive, "Invalid payload body (this message is probably safe to ignore); opcode: {Op} event: {Event}; payload: {Payload}", payload.OpCode, payload.EventName, payload.Data); return; } TransportMember transportMember = null; TransportUser referenceAuthor = null; TransportMember referenceMember = null; JToken jToken = jObject["referenced_message"]; switch (payload.EventName.ToLowerInvariant()) { case "ready": { JArray rawGuilds = (JArray)jObject["guilds"]; JArray rawDmChannels = (JArray)jObject["private_channels"]; jObject.Remove("guilds"); jObject.Remove("private_channels"); await OnReadyEventAsync(jObject.ToDiscordObject(), rawGuilds, rawDmChannels).ConfigureAwait(continueOnCapturedContext: false); break; } case "resumed": await OnResumedAsync().ConfigureAwait(continueOnCapturedContext: false); break; case "channel_create": { DiscordChannel channel = jObject.ToDiscordObject(); await OnChannelCreateEventAsync(channel).ConfigureAwait(continueOnCapturedContext: false); break; } case "channel_update": await OnChannelUpdateEventAsync(jObject.ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; case "channel_delete": { DiscordChannel channel = ((jObject["is_private"]?.ToObject() ?? false) ? jObject.ToDiscordObject() : jObject.ToDiscordObject()); await OnChannelDeleteEventAsync(channel).ConfigureAwait(continueOnCapturedContext: false); break; } case "channel_pins_update": { ulong channelId = (ulong)jObject["channel_id"]; string text = (string?)jObject["last_pin_timestamp"]; await OnChannelPinsUpdateAsync((ulong?)jObject["guild_id"], channelId, (text != null) ? new DateTimeOffset?(DateTimeOffset.Parse(text, CultureInfo.InvariantCulture)) : null).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_scheduled_event_create": { DiscordScheduledGuildEvent evt = jObject.ToDiscordObject(); await OnScheduledGuildEventCreateEventAsync(evt).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_scheduled_event_delete": { DiscordScheduledGuildEvent evt3 = jObject.ToDiscordObject(); await OnScheduledGuildEventDeleteEventAsync(evt3).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_scheduled_event_update": { DiscordScheduledGuildEvent evt2 = jObject.ToDiscordObject(); await OnScheduledGuildEventUpdateEventAsync(evt2).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_scheduled_event_user_add": { ulong key = (ulong)jObject["guild_id"]; ulong userId = (ulong)jObject["user_id"]; ulong eventId = (ulong)jObject["guild_scheduled_event_id"]; await OnScheduledGuildEventUserAddEventAsync(key, eventId, userId).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_scheduled_event_user_remove": { ulong key = (ulong)jObject["guild_id"]; ulong userId = (ulong)jObject["user_id"]; ulong eventId = (ulong)jObject["guild_scheduled_event_id"]; await OnScheduledGuildEventUserRemoveEventAsync(key, eventId, userId).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_create": { JArray rawMembers = (JArray)jObject["members"]; JArray token = (JArray)jObject["presences"]; jObject.Remove("members"); jObject.Remove("presences"); await OnGuildCreateEventAsync(jObject.ToDiscordObject(), rawMembers, token.ToDiscordObject>()).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_update": { JArray rawMembers = (JArray)jObject["members"]; jObject.Remove("members"); await OnGuildUpdateEventAsync(jObject.ToDiscordObject(), rawMembers).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_delete": { JArray rawMembers = (JArray)jObject["members"]; jObject.Remove("members"); await OnGuildDeleteEventAsync(jObject.ToDiscordObject(), rawMembers).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_sync": { ulong key = (ulong)jObject["id"]; JArray rawMembers = (JArray)jObject["members"]; JArray token = (JArray)jObject["presences"]; jObject.Remove("members"); jObject.Remove("presences"); await OnGuildSyncEventAsync(_guilds[key], (bool)jObject["large"], rawMembers, token.ToDiscordObject>()).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_emojis_update": { ulong key = (ulong)jObject["guild_id"]; IEnumerable newEmojis = jObject["emojis"].ToDiscordObject>(); await OnGuildEmojisUpdateEventAsync(_guilds[key], newEmojis).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_integrations_update": { ulong key = (ulong)jObject["guild_id"]; if (_guilds.ContainsKey(key)) { await OnGuildIntegrationsUpdateEventAsync(_guilds[key]).ConfigureAwait(continueOnCapturedContext: false); } break; } case "guild_ban_add": { TransportUser user = jObject["user"].ToDiscordObject(); ulong key = (ulong)jObject["guild_id"]; await OnGuildBanAddEventAsync(user, _guilds[key]).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_ban_remove": { TransportUser user = jObject["user"].ToDiscordObject(); ulong key = (ulong)jObject["guild_id"]; await OnGuildBanRemoveEventAsync(user, _guilds[key]).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_member_add": { ulong key = (ulong)jObject["guild_id"]; await OnGuildMemberAddEventAsync(jObject.ToDiscordObject(), _guilds[key]).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_member_remove": { ulong key = (ulong)jObject["guild_id"]; TransportUser user = jObject["user"].ToDiscordObject(); if (!_guilds.ContainsKey(key)) { if (user.Id != base.CurrentUser.Id) { base.Logger.LogError(LoggerEvents.WebSocketReceive, "Could not find {Guild} in guild cache", key); } } else { await OnGuildMemberRemoveEventAsync(user, _guilds[key]).ConfigureAwait(continueOnCapturedContext: false); } break; } case "guild_member_update": { ulong key = (ulong)jObject["guild_id"]; await OnGuildMemberUpdateEventAsync(jObject.ToDiscordObject(), _guilds[key]).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_members_chunk": await OnGuildMembersChunkEventAsync(jObject).ConfigureAwait(continueOnCapturedContext: false); break; case "guild_role_create": { ulong key = (ulong)jObject["guild_id"]; await OnGuildRoleCreateEventAsync(jObject["role"].ToDiscordObject(), _guilds[key]).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_role_update": { ulong key = (ulong)jObject["guild_id"]; await OnGuildRoleUpdateEventAsync(jObject["role"].ToDiscordObject(), _guilds[key]).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_role_delete": { ulong key = (ulong)jObject["guild_id"]; await OnGuildRoleDeleteEventAsync((ulong)jObject["role_id"], _guilds[key]).ConfigureAwait(continueOnCapturedContext: false); break; } case "invite_create": { ulong key = (ulong)jObject["guild_id"]; ulong channelId = (ulong)jObject["channel_id"]; await OnInviteCreateEventAsync(channelId, key, jObject.ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; } case "invite_delete": { ulong key = (ulong)jObject["guild_id"]; ulong channelId = (ulong)jObject["channel_id"]; await OnInviteDeleteEventAsync(channelId, key, jObject).ConfigureAwait(continueOnCapturedContext: false); break; } case "message_ack": { ulong channelId = (ulong)jObject["channel_id"]; ulong messageId = (ulong)jObject["message_id"]; await OnMessageAckEventAsync(InternalGetCachedChannel(channelId), messageId).ConfigureAwait(continueOnCapturedContext: false); break; } case "message_create": { JToken jToken2 = jObject["member"]; if (jToken2 != null) { transportMember = jToken2.ToDiscordObject(); } if (jToken != null && jToken.HasValues) { if (jToken.SelectToken("author") != null) { referenceAuthor = jToken.SelectToken("author").ToDiscordObject(); } if (jToken.SelectToken("member") != null) { referenceMember = jToken.SelectToken("member").ToDiscordObject(); } } TransportUser author = jObject["author"].ToDiscordObject(); jObject.Remove("author"); jObject.Remove("member"); await OnMessageCreateEventAsync(jObject.ToDiscordObject(), author, transportMember, referenceAuthor, referenceMember).ConfigureAwait(continueOnCapturedContext: false); break; } case "message_update": { JToken jToken2 = jObject["member"]; if (jToken2 != null) { transportMember = jToken2.ToDiscordObject(); } if (jToken != null && jToken.HasValues) { if (jToken.SelectToken("author") != null) { referenceAuthor = jToken.SelectToken("author").ToDiscordObject(); } if (jToken.SelectToken("member") != null) { referenceMember = jToken.SelectToken("member").ToDiscordObject(); } } await OnMessageUpdateEventAsync(jObject.ToDiscordObject(), jObject["author"]?.ToDiscordObject(), transportMember, referenceAuthor, referenceMember).ConfigureAwait(continueOnCapturedContext: false); break; } case "message_delete": await OnMessageDeleteEventAsync((ulong)jObject["id"], (ulong)jObject["channel_id"], (ulong?)jObject["guild_id"]).ConfigureAwait(continueOnCapturedContext: false); break; case "message_delete_bulk": await OnMessageBulkDeleteEventAsync(jObject["ids"].ToDiscordObject(), (ulong)jObject["channel_id"], (ulong?)jObject["guild_id"]).ConfigureAwait(continueOnCapturedContext: false); break; case "message_reaction_add": { JToken jToken2 = jObject["member"]; if (jToken2 != null) { transportMember = jToken2.ToDiscordObject(); } await OnMessageReactionAddAsync((ulong)jObject["user_id"], (ulong)jObject["message_id"], (ulong)jObject["channel_id"], (ulong?)jObject["guild_id"], transportMember, jObject["emoji"].ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; } case "message_reaction_remove": await OnMessageReactionRemoveAsync((ulong)jObject["user_id"], (ulong)jObject["message_id"], (ulong)jObject["channel_id"], (ulong?)jObject["guild_id"], jObject["emoji"].ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; case "message_reaction_remove_all": await OnMessageReactionRemoveAllAsync((ulong)jObject["message_id"], (ulong)jObject["channel_id"], (ulong?)jObject["guild_id"]).ConfigureAwait(continueOnCapturedContext: false); break; case "message_reaction_remove_emoji": await OnMessageReactionRemoveEmojiAsync((ulong)jObject["message_id"], (ulong)jObject["channel_id"], (ulong)jObject["guild_id"], jObject["emoji"]).ConfigureAwait(continueOnCapturedContext: false); break; case "presence_update": await OnPresenceUpdateEventAsync(jObject, (JObject)jObject["user"]).ConfigureAwait(continueOnCapturedContext: false); break; case "user_settings_update": await OnUserSettingsUpdateEventAsync(jObject.ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; case "user_update": await OnUserUpdateEventAsync(jObject.ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; case "voice_state_update": await OnVoiceStateUpdateEventAsync(jObject).ConfigureAwait(continueOnCapturedContext: false); break; case "voice_server_update": { ulong key = (ulong)jObject["guild_id"]; await OnVoiceServerUpdateEventAsync((string?)jObject["endpoint"], (string?)jObject["token"], _guilds[key]).ConfigureAwait(continueOnCapturedContext: false); break; } case "thread_create": { DiscordThreadChannel thread = jObject.ToDiscordObject(); await OnThreadCreateEventAsync(thread, thread.IsNew).ConfigureAwait(continueOnCapturedContext: false); break; } case "thread_update": { DiscordThreadChannel thread = jObject.ToDiscordObject(); await OnThreadUpdateEventAsync(thread).ConfigureAwait(continueOnCapturedContext: false); break; } case "thread_delete": { DiscordThreadChannel thread = jObject.ToDiscordObject(); await OnThreadDeleteEventAsync(thread).ConfigureAwait(continueOnCapturedContext: false); break; } case "thread_list_sync": { ulong key = (ulong)jObject["guild_id"]; await OnThreadListSyncEventAsync(_guilds[key], jObject["channel_ids"].ToDiscordObject>(), jObject["threads"].ToDiscordObject>(), jObject["members"].ToDiscordObject>()).ConfigureAwait(continueOnCapturedContext: false); break; } case "thread_member_update": await OnThreadMemberUpdateEventAsync(jObject.ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; case "thread_members_update": { ulong key = (ulong)jObject["guild_id"]; await OnThreadMembersUpdateEventAsync(_guilds[key], (ulong)jObject["id"], jObject["added_members"]?.ToDiscordObject>(), jObject["removed_member_ids"]?.ToDiscordObject>(), (int)jObject["member_count"]).ConfigureAwait(continueOnCapturedContext: false); break; } case "interaction_create": { JToken jToken2 = jObject["member"]; TransportUser user; if (jToken2 != null) { transportMember = jObject["member"].ToDiscordObject(); user = transportMember.User; } else { user = jObject["user"].ToDiscordObject(); } ulong channelId = (ulong)jObject["channel_id"]; await OnInteractionCreateAsync((ulong?)jObject["guild_id"], channelId, user, transportMember, jObject.ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; } case "application_command_create": await OnApplicationCommandCreateAsync(jObject.ToDiscordObject(), (ulong?)jObject["guild_id"]).ConfigureAwait(continueOnCapturedContext: false); break; case "application_command_update": await OnApplicationCommandUpdateAsync(jObject.ToDiscordObject(), (ulong?)jObject["guild_id"]).ConfigureAwait(continueOnCapturedContext: false); break; case "application_command_permissions_update": await OnApplicationCommandPermissionsUpdateAsync(jObject).ConfigureAwait(continueOnCapturedContext: false); break; case "application_command_delete": await OnApplicationCommandDeleteAsync(jObject.ToDiscordObject(), (ulong?)jObject["guild_id"]).ConfigureAwait(continueOnCapturedContext: false); break; case "integration_create": await OnIntegrationCreateAsync(jObject.ToDiscordObject(), (ulong)jObject["guild_id"]).ConfigureAwait(continueOnCapturedContext: false); break; case "integration_update": await OnIntegrationUpdateAsync(jObject.ToDiscordObject(), (ulong)jObject["guild_id"]).ConfigureAwait(continueOnCapturedContext: false); break; case "integration_delete": await OnIntegrationDeleteAsync((ulong)jObject["id"], (ulong)jObject["guild_id"], (ulong?)jObject["application_id"]).ConfigureAwait(continueOnCapturedContext: false); break; case "stage_instance_create": await OnStageInstanceCreateAsync(jObject.ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; case "stage_instance_update": await OnStageInstanceUpdateAsync(jObject.ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; case "stage_instance_delete": await OnStageInstanceDeleteAsync(jObject.ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); break; case "typing_start": { ulong channelId = (ulong)jObject["channel_id"]; JToken jToken2 = jObject["member"]; if (jToken2 != null) { transportMember = jToken2.ToDiscordObject(); } await OnTypingStartEventAsync((ulong)jObject["user_id"], channelId, InternalGetCachedChannel(channelId), (ulong?)jObject["guild_id"], Utilities.GetDateTimeOffset((long)jObject["timestamp"]), transportMember).ConfigureAwait(continueOnCapturedContext: false); break; } case "webhooks_update": { ulong key = (ulong)jObject["guild_id"]; ulong channelId = (ulong)jObject["channel_id"]; await OnWebhooksUpdateAsync(_guilds[key].GetChannel(channelId), _guilds[key]).ConfigureAwait(continueOnCapturedContext: false); break; } case "guild_stickers_update": { IEnumerable newStickers = jObject["stickers"].ToDiscordObject>(); await OnStickersUpdatedAsync(newStickers, jObject).ConfigureAwait(continueOnCapturedContext: false); break; } default: await OnUnknownEventAsync(payload).ConfigureAwait(continueOnCapturedContext: false); if (base.Configuration.LogUnknownEvents) { base.Logger.LogWarning(LoggerEvents.WebSocketReceive, "Unknown event: {EventName}\npayload: {@Payload}", payload.EventName, payload.Data); } break; case "gift_code_update": break; case "embedded_activity_update": break; } } internal async Task OnReadyEventAsync(ReadyPayload ready, JArray rawGuilds, JArray rawDmChannels) { TransportUser currentUser = ready.CurrentUser; base.CurrentUser.Username = currentUser.Username; base.CurrentUser.Discriminator = currentUser.Discriminator; base.CurrentUser.AvatarHash = currentUser.AvatarHash; base.CurrentUser.MfaEnabled = currentUser.MfaEnabled; base.CurrentUser.Verified = currentUser.Verified; base.CurrentUser.IsBot = currentUser.IsBot; GatewayVersion = ready.GatewayVersion; _sessionId = ready.SessionId; Dictionary dictionary = rawGuilds.ToDictionary((JToken xt) => (ulong)xt["id"], (JToken xt) => (JObject)xt); _privateChannels.Clear(); foreach (JToken rawDmChannel in rawDmChannels) { DiscordDmChannel discordDmChannel = rawDmChannel.ToDiscordObject(); discordDmChannel.Discord = this; IEnumerable enumerable = rawDmChannel["recipients"].ToDiscordObject>(); List list = new List(); using (IEnumerator enumerator2 = enumerable.GetEnumerator()) { while (enumerator2.MoveNext()) { DiscordUser newUser = new DiscordUser(enumerator2.Current) { Discord = this }; newUser = UpdateUserCache(newUser); list.Add(newUser); } } discordDmChannel.Recipients = list; _privateChannels[discordDmChannel.Id] = discordDmChannel; } _guilds.Clear(); foreach (DiscordGuild item in rawGuilds.ToDiscordObject>()) { item.Discord = this; DiscordGuild discordGuild = item; if (discordGuild._channels == null) { discordGuild._channels = new ConcurrentDictionary(); } discordGuild = item; if (discordGuild._threads == null) { discordGuild._threads = new ConcurrentDictionary(); } foreach (DiscordChannel value in item.Channels.Values) { value.GuildId = item.Id; value.Discord = this; foreach (DiscordOverwrite permissionOverwrite in value._permissionOverwrites) { permissionOverwrite.Discord = this; permissionOverwrite._channel_id = value.Id; } } foreach (DiscordThreadChannel value2 in item.Threads.Values) { value2.GuildId = item.Id; value2.Discord = this; } discordGuild = item; if (discordGuild._roles == null) { discordGuild._roles = new ConcurrentDictionary(); } foreach (DiscordRole value3 in item.Roles.Values) { value3.Discord = this; value3._guild_id = item.Id; } JArray jArray = (JArray)dictionary[item.Id]["members"]; item._members?.Clear(); discordGuild = item; if (discordGuild._members == null) { discordGuild._members = new ConcurrentDictionary(); } if (jArray != null) { foreach (JToken item2 in jArray) { TransportMember transportMember = item2.ToDiscordObject(); DiscordUser newUser2 = new DiscordUser(transportMember.User) { Discord = this }; UpdateUserCache(newUser2); item._members[transportMember.User.Id] = new DiscordMember(transportMember) { Discord = this, _guild_id = item.Id }; } } discordGuild = item; if (discordGuild._emojis == null) { discordGuild._emojis = new ConcurrentDictionary(); } foreach (DiscordEmoji value4 in item.Emojis.Values) { value4.Discord = this; } discordGuild = item; if (discordGuild._voiceStates == null) { discordGuild._voiceStates = new ConcurrentDictionary(); } foreach (DiscordVoiceState value5 in item.VoiceStates.Values) { value5.Discord = this; } _guilds[item.Id] = item; } await _ready.InvokeAsync(this, new ReadyEventArgs()).ConfigureAwait(continueOnCapturedContext: false); } internal Task OnResumedAsync() { base.Logger.LogInformation(LoggerEvents.SessionUpdate, "Session resumed"); return _resumed.InvokeAsync(this, new ReadyEventArgs()); } internal async Task OnChannelCreateEventAsync(DiscordChannel channel) { channel.Discord = this; foreach (DiscordOverwrite permissionOverwrite in channel._permissionOverwrites) { permissionOverwrite.Discord = this; permissionOverwrite._channel_id = channel.Id; } _guilds[channel.GuildId.Value]._channels[channel.Id] = channel; await _channelCreated.InvokeAsync(this, new ChannelCreateEventArgs { Channel = channel, Guild = channel.Guild }).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnChannelUpdateEventAsync(DiscordChannel channel) { if (channel == null) { return; } channel.Discord = this; DiscordGuild guild = channel.Guild; DiscordChannel discordChannel = InternalGetCachedChannel(channel.Id); DiscordChannel channelBefore = null; if (discordChannel != null) { channelBefore = new DiscordChannel { Bitrate = discordChannel.Bitrate, Discord = this, GuildId = discordChannel.GuildId, Id = discordChannel.Id, LastMessageId = discordChannel.LastMessageId, Name = discordChannel.Name, _permissionOverwrites = new List(discordChannel._permissionOverwrites), Position = discordChannel.Position, Topic = discordChannel.Topic, Type = discordChannel.Type, UserLimit = discordChannel.UserLimit, ParentId = discordChannel.ParentId, IsNSFW = discordChannel.IsNSFW, PerUserRateLimit = discordChannel.PerUserRateLimit, RtcRegionId = discordChannel.RtcRegionId, QualityMode = discordChannel.QualityMode }; discordChannel.Bitrate = channel.Bitrate; discordChannel.Name = channel.Name; discordChannel.Position = channel.Position; discordChannel.Topic = channel.Topic; discordChannel.UserLimit = channel.UserLimit; discordChannel.ParentId = channel.ParentId; discordChannel.IsNSFW = channel.IsNSFW; discordChannel.PerUserRateLimit = channel.PerUserRateLimit; discordChannel.Type = channel.Type; discordChannel.RtcRegionId = channel.RtcRegionId; discordChannel.QualityMode = channel.QualityMode; discordChannel._permissionOverwrites.Clear(); foreach (DiscordOverwrite permissionOverwrite in channel._permissionOverwrites) { permissionOverwrite.Discord = this; permissionOverwrite._channel_id = channel.Id; } discordChannel._permissionOverwrites.AddRange(channel._permissionOverwrites); } else if (guild != null) { guild._channels[channel.Id] = channel; } await _channelUpdated.InvokeAsync(this, new ChannelUpdateEventArgs { ChannelAfter = discordChannel, Guild = guild, ChannelBefore = channelBefore }).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnChannelDeleteEventAsync(DiscordChannel channel) { if (channel == null) { return; } channel.Discord = this; if (channel.Type == ChannelType.Group || channel.Type == ChannelType.Private) { DiscordDmChannel discordDmChannel = channel as DiscordDmChannel; _privateChannels.TryRemove(discordDmChannel.Id, out var _); await _dmChannelDeleted.InvokeAsync(this, new DmChannelDeleteEventArgs { Channel = discordDmChannel }).ConfigureAwait(continueOnCapturedContext: false); return; } DiscordGuild guild = channel.Guild; if (guild._channels.TryRemove(channel.Id, out var value2)) { channel = value2; } await _channelDeleted.InvokeAsync(this, new ChannelDeleteEventArgs { Channel = channel, Guild = guild }).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnChannelPinsUpdateAsync(ulong? guildId, ulong channelId, DateTimeOffset? lastPinTimestamp) { DiscordGuild guild = InternalGetCachedGuild(guildId); DiscordChannel discordChannel = InternalGetCachedChannel(channelId) ?? InternalGetCachedThread(channelId); if (discordChannel == null) { discordChannel = new DiscordDmChannel { Id = channelId, Discord = this, Type = ChannelType.Private, Recipients = Array.Empty() }; DiscordDmChannel value = (DiscordDmChannel)discordChannel; _privateChannels[channelId] = value; } ChannelPinsUpdateEventArgs args = new ChannelPinsUpdateEventArgs { Guild = guild, Channel = discordChannel, LastPinTimestamp = lastPinTimestamp }; await _channelPinsUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } private async Task OnScheduledGuildEventCreateEventAsync(DiscordScheduledGuildEvent evt) { evt.Discord = this; if (evt.Creator != null) { evt.Creator.Discord = this; UpdateUserCache(evt.Creator); } evt.Guild._scheduledEvents[evt.Id] = evt; await _scheduledGuildEventCreated.InvokeAsync(this, new ScheduledGuildEventCreateEventArgs { Event = evt }).ConfigureAwait(continueOnCapturedContext: false); } private async Task OnScheduledGuildEventDeleteEventAsync(DiscordScheduledGuildEvent evt) { DiscordGuild discordGuild = InternalGetCachedGuild(evt.GuildId); if (!(discordGuild == null)) { discordGuild._scheduledEvents.TryRemove(evt.Id, out var _); evt.Discord = this; if (evt.Creator != null) { evt.Creator.Discord = this; UpdateUserCache(evt.Creator); } await _scheduledGuildEventDeleted.InvokeAsync(this, new ScheduledGuildEventDeleteEventArgs { Event = evt }).ConfigureAwait(continueOnCapturedContext: false); } } private async Task OnScheduledGuildEventUpdateEventAsync(DiscordScheduledGuildEvent evt) { evt.Discord = this; if (evt.Creator != null) { evt.Creator.Discord = this; UpdateUserCache(evt.Creator); } InternalGetCachedGuild(evt.GuildId)._scheduledEvents.TryGetValue(evt.GuildId, out var value); evt.Guild._scheduledEvents[evt.Id] = evt; if (evt.Status == ScheduledGuildEventStatus.Completed) { await _scheduledGuildEventCompleted.InvokeAsync(this, new ScheduledGuildEventCompletedEventArgs { Event = evt }).ConfigureAwait(continueOnCapturedContext: false); } else { await _scheduledGuildEventUpdated.InvokeAsync(this, new ScheduledGuildEventUpdateEventArgs { EventBefore = value, EventAfter = evt }).ConfigureAwait(continueOnCapturedContext: false); } } private async Task OnScheduledGuildEventUserAddEventAsync(ulong guildId, ulong eventId, ulong userId) { DiscordGuild discordGuild = InternalGetCachedGuild(guildId); DiscordScheduledGuildEvent orAdd = discordGuild._scheduledEvents.GetOrAdd(eventId, new DiscordScheduledGuildEvent { Id = eventId, GuildId = guildId, Discord = this, UserCount = 0 }); orAdd.UserCount++; DiscordMember value; DiscordUser user = (discordGuild.Members.TryGetValue(userId, out value) ? value : (GetCachedOrEmptyUserInternal(userId) ?? new DiscordUser { Id = userId, Discord = this })); await _scheduledGuildEventUserAdded.InvokeAsync(this, new ScheduledGuildEventUserAddEventArgs { Event = orAdd, User = user }).ConfigureAwait(continueOnCapturedContext: false); } private async Task OnScheduledGuildEventUserRemoveEventAsync(ulong guildId, ulong eventId, ulong userId) { DiscordGuild discordGuild = InternalGetCachedGuild(guildId); DiscordScheduledGuildEvent orAdd = discordGuild._scheduledEvents.GetOrAdd(eventId, new DiscordScheduledGuildEvent { Id = eventId, GuildId = guildId, Discord = this, UserCount = 0 }); int? userCount = orAdd.UserCount; orAdd.UserCount = ((userCount.HasValue && userCount.GetValueOrDefault() == 0) ? new int?(0) : (orAdd.UserCount - 1)); DiscordMember value; DiscordUser user = (discordGuild.Members.TryGetValue(userId, out value) ? value : (GetCachedOrEmptyUserInternal(userId) ?? new DiscordUser { Id = userId, Discord = this })); await _scheduledGuildEventUserRemoved.InvokeAsync(this, new ScheduledGuildEventUserRemoveEventArgs { Event = orAdd, User = user }).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildCreateEventAsync(DiscordGuild guild, JArray rawMembers, IEnumerable presences) { if (presences != null) { foreach (DiscordPresence presence in presences) { presence.Discord = this; presence.GuildId = guild.Id; presence.Activity = new DiscordActivity(presence.RawActivity); if (presence.RawActivities != null) { presence._internalActivities = new DiscordActivity[presence.RawActivities.Length]; for (int i = 0; i < presence.RawActivities.Length; i++) { presence._internalActivities[i] = new DiscordActivity(presence.RawActivities[i]); } } _presences[presence.User.Id] = presence; } } DiscordGuild value; bool flag = _guilds.TryGetValue(guild.Id, out value); guild.Discord = this; guild.IsUnavailable = false; DiscordGuild discordGuild = guild; if (flag) { guild = value; } DiscordGuild discordGuild2 = guild; if (discordGuild2._channels == null) { discordGuild2._channels = new ConcurrentDictionary(); } discordGuild2 = guild; if (discordGuild2._threads == null) { discordGuild2._threads = new ConcurrentDictionary(); } discordGuild2 = guild; if (discordGuild2._roles == null) { discordGuild2._roles = new ConcurrentDictionary(); } discordGuild2 = guild; if (discordGuild2._emojis == null) { discordGuild2._emojis = new ConcurrentDictionary(); } discordGuild2 = guild; if (discordGuild2._stickers == null) { discordGuild2._stickers = new ConcurrentDictionary(); } discordGuild2 = guild; if (discordGuild2._voiceStates == null) { discordGuild2._voiceStates = new ConcurrentDictionary(); } discordGuild2 = guild; if (discordGuild2._members == null) { discordGuild2._members = new ConcurrentDictionary(); } discordGuild2 = guild; if (discordGuild2._stageInstances == null) { discordGuild2._stageInstances = new ConcurrentDictionary(); } discordGuild2 = guild; if (discordGuild2._scheduledEvents == null) { discordGuild2._scheduledEvents = new ConcurrentDictionary(); } UpdateCachedGuild(discordGuild, rawMembers); guild.JoinedAt = discordGuild.JoinedAt; guild.IsLarge = discordGuild.IsLarge; guild.MemberCount = Math.Max(discordGuild.MemberCount, guild._members.Count); guild.IsUnavailable = discordGuild.IsUnavailable; guild.PremiumSubscriptionCount = discordGuild.PremiumSubscriptionCount; guild.PremiumTier = discordGuild.PremiumTier; guild.Banner = discordGuild.Banner; guild.VanityUrlCode = discordGuild.VanityUrlCode; guild.Description = discordGuild.Description; guild.IsNSFW = discordGuild.IsNSFW; discordGuild2 = discordGuild; foreach (KeyValuePair item in discordGuild2._voiceStates ?? (discordGuild2._voiceStates = new ConcurrentDictionary())) { guild._voiceStates[item.Key] = item.Value; } foreach (DiscordScheduledGuildEvent value2 in guild._scheduledEvents.Values) { value2.Discord = this; if (value2.Creator != null) { value2.Creator.Discord = this; } } foreach (DiscordChannel value3 in guild._channels.Values) { value3.GuildId = guild.Id; value3.Discord = this; foreach (DiscordOverwrite permissionOverwrite in value3._permissionOverwrites) { permissionOverwrite.Discord = this; permissionOverwrite._channel_id = value3.Id; } } foreach (DiscordThreadChannel value4 in guild._threads.Values) { value4.GuildId = guild.Id; value4.Discord = this; } foreach (DiscordEmoji value5 in guild._emojis.Values) { value5.Discord = this; } foreach (DiscordMessageSticker value6 in guild._stickers.Values) { value6.Discord = this; } foreach (DiscordVoiceState value7 in guild._voiceStates.Values) { value7.Discord = this; } foreach (DiscordRole value8 in guild._roles.Values) { value8.Discord = this; value8._guild_id = guild.Id; } foreach (DiscordStageInstance value9 in guild._stageInstances.Values) { value9.Discord = this; } bool old = Volatile.Read(ref _guildDownloadCompleted); bool dcompl = _guilds.Values.All((DiscordGuild xg) => !xg.IsUnavailable); Volatile.Write(ref _guildDownloadCompleted, dcompl); if (!flag) { await _guildCreated.InvokeAsync(this, new GuildCreateEventArgs { Guild = guild }).ConfigureAwait(continueOnCapturedContext: false); } else { await _guildAvailable.InvokeAsync(this, new GuildCreateEventArgs { Guild = guild }).ConfigureAwait(continueOnCapturedContext: false); } if (dcompl && !old) { await _guildDownloadCompletedEv.InvokeAsync(this, new GuildDownloadCompletedEventArgs(Guilds)).ConfigureAwait(continueOnCapturedContext: false); } } internal async Task OnGuildUpdateEventAsync(DiscordGuild guild, JArray rawMembers) { DiscordGuild discordGuild; if (!_guilds.ContainsKey(guild.Id)) { _guilds[guild.Id] = guild; discordGuild = null; } else { DiscordGuild discordGuild2 = _guilds[guild.Id]; discordGuild = new DiscordGuild { Discord = discordGuild2.Discord, Name = discordGuild2.Name, _afkChannelId = discordGuild2._afkChannelId, AfkTimeout = discordGuild2.AfkTimeout, DefaultMessageNotifications = discordGuild2.DefaultMessageNotifications, ExplicitContentFilter = discordGuild2.ExplicitContentFilter, Features = discordGuild2.Features, IconHash = discordGuild2.IconHash, Id = discordGuild2.Id, IsLarge = discordGuild2.IsLarge, _isSynced = discordGuild2._isSynced, IsUnavailable = discordGuild2.IsUnavailable, JoinedAt = discordGuild2.JoinedAt, MemberCount = discordGuild2.MemberCount, MaxMembers = discordGuild2.MaxMembers, MaxPresences = discordGuild2.MaxPresences, ApproximateMemberCount = discordGuild2.ApproximateMemberCount, ApproximatePresenceCount = discordGuild2.ApproximatePresenceCount, MaxVideoChannelUsers = discordGuild2.MaxVideoChannelUsers, DiscoverySplashHash = discordGuild2.DiscoverySplashHash, PreferredLocale = discordGuild2.PreferredLocale, MfaLevel = discordGuild2.MfaLevel, OwnerId = discordGuild2.OwnerId, SplashHash = discordGuild2.SplashHash, _systemChannelId = discordGuild2._systemChannelId, SystemChannelFlags = discordGuild2.SystemChannelFlags, WidgetEnabled = discordGuild2.WidgetEnabled, _widgetChannelId = discordGuild2._widgetChannelId, VerificationLevel = discordGuild2.VerificationLevel, _rulesChannelId = discordGuild2._rulesChannelId, _publicUpdatesChannelId = discordGuild2._publicUpdatesChannelId, _voiceRegionId = discordGuild2._voiceRegionId, PremiumProgressBarEnabled = discordGuild2.PremiumProgressBarEnabled, IsNSFW = discordGuild2.IsNSFW, _channels = new ConcurrentDictionary(), _threads = new ConcurrentDictionary(), _emojis = new ConcurrentDictionary(), _members = new ConcurrentDictionary(), _roles = new ConcurrentDictionary(), _voiceStates = new ConcurrentDictionary() }; DiscordGuild discordGuild3 = discordGuild2; foreach (KeyValuePair item in discordGuild3._channels ?? (discordGuild3._channels = new ConcurrentDictionary())) { discordGuild._channels[item.Key] = item.Value; } discordGuild3 = discordGuild2; foreach (KeyValuePair item2 in discordGuild3._threads ?? (discordGuild3._threads = new ConcurrentDictionary())) { discordGuild._threads[item2.Key] = item2.Value; } discordGuild3 = discordGuild2; foreach (KeyValuePair item3 in discordGuild3._emojis ?? (discordGuild3._emojis = new ConcurrentDictionary())) { discordGuild._emojis[item3.Key] = item3.Value; } discordGuild3 = discordGuild2; foreach (KeyValuePair item4 in discordGuild3._roles ?? (discordGuild3._roles = new ConcurrentDictionary())) { discordGuild._roles[item4.Key] = item4.Value; } discordGuild3 = discordGuild2; foreach (KeyValuePair item5 in discordGuild3._voiceStates ?? (discordGuild3._voiceStates = new ConcurrentDictionary())) { discordGuild._voiceStates[item5.Key] = item5.Value; } discordGuild3 = discordGuild2; foreach (KeyValuePair item6 in discordGuild3._members ?? (discordGuild3._members = new ConcurrentDictionary())) { discordGuild._members[item6.Key] = item6.Value; } } guild.Discord = this; guild.IsUnavailable = false; DiscordGuild discordGuild4 = guild; guild = _guilds[discordGuild4.Id]; if (guild._channels == null) { guild._channels = new ConcurrentDictionary(); } if (guild._threads == null) { guild._threads = new ConcurrentDictionary(); } if (guild._roles == null) { guild._roles = new ConcurrentDictionary(); } if (guild._emojis == null) { guild._emojis = new ConcurrentDictionary(); } if (guild._voiceStates == null) { guild._voiceStates = new ConcurrentDictionary(); } if (guild._members == null) { guild._members = new ConcurrentDictionary(); } UpdateCachedGuild(discordGuild4, rawMembers); foreach (DiscordChannel value in guild._channels.Values) { value.GuildId = guild.Id; value.Discord = this; foreach (DiscordOverwrite permissionOverwrite in value._permissionOverwrites) { permissionOverwrite.Discord = this; permissionOverwrite._channel_id = value.Id; } } foreach (DiscordThreadChannel value2 in guild._threads.Values) { value2.GuildId = guild.Id; value2.Discord = this; } foreach (DiscordEmoji value3 in guild._emojis.Values) { value3.Discord = this; } foreach (DiscordVoiceState value4 in guild._voiceStates.Values) { value4.Discord = this; } foreach (DiscordRole value5 in guild._roles.Values) { value5.Discord = this; value5._guild_id = guild.Id; } await _guildUpdated.InvokeAsync(this, new GuildUpdateEventArgs { GuildBefore = discordGuild, GuildAfter = guild }).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildDeleteEventAsync(DiscordGuild guild, JArray rawMembers) { DiscordGuild value2; if (guild.IsUnavailable) { if (_guilds.TryGetValue(guild.Id, out var value)) { value.IsUnavailable = true; await _guildUnavailable.InvokeAsync(this, new GuildDeleteEventArgs { Guild = guild, Unavailable = true }).ConfigureAwait(continueOnCapturedContext: false); } } else if (_guilds.TryRemove(guild.Id, out value2)) { await _guildDeleted.InvokeAsync(this, new GuildDeleteEventArgs { Guild = value2 }).ConfigureAwait(continueOnCapturedContext: false); } } internal async Task OnGuildSyncEventAsync(DiscordGuild guild, bool isLarge, JArray rawMembers, IEnumerable presences) { presences = presences.Select(delegate(DiscordPresence xp) { xp.Discord = this; xp.Activity = new DiscordActivity(xp.RawActivity); return xp; }); foreach (DiscordPresence presence in presences) { _presences[presence.InternalUser.Id] = presence; } guild._isSynced = true; guild.IsLarge = isLarge; UpdateCachedGuild(guild, rawMembers); await _guildAvailable.InvokeAsync(this, new GuildCreateEventArgs { Guild = guild }).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildEmojisUpdateEventAsync(DiscordGuild guild, IEnumerable newEmojis) { ConcurrentDictionary emojisBefore = new ConcurrentDictionary(guild._emojis); guild._emojis.Clear(); foreach (DiscordEmoji newEmoji in newEmojis) { newEmoji.Discord = this; guild._emojis[newEmoji.Id] = newEmoji; } GuildEmojisUpdateEventArgs args = new GuildEmojisUpdateEventArgs { Guild = guild, EmojisAfter = guild.Emojis, EmojisBefore = emojisBefore }; await _guildEmojisUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildIntegrationsUpdateEventAsync(DiscordGuild guild) { GuildIntegrationsUpdateEventArgs args = new GuildIntegrationsUpdateEventArgs { Guild = guild }; await _guildIntegrationsUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildBanAddEventAsync(TransportUser user, DiscordGuild guild) { DiscordUser newUser = new DiscordUser(user) { Discord = this }; newUser = UpdateUserCache(newUser); if (!guild.Members.TryGetValue(user.Id, out var value)) { value = new DiscordMember(newUser) { Discord = this, _guild_id = guild.Id }; } GuildBanAddEventArgs args = new GuildBanAddEventArgs { Guild = guild, Member = value }; await _guildBanAdded.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildBanRemoveEventAsync(TransportUser user, DiscordGuild guild) { DiscordUser newUser = new DiscordUser(user) { Discord = this }; newUser = UpdateUserCache(newUser); if (!guild.Members.TryGetValue(user.Id, out var value)) { value = new DiscordMember(newUser) { Discord = this, _guild_id = guild.Id }; } GuildBanRemoveEventArgs args = new GuildBanRemoveEventArgs { Guild = guild, Member = value }; await _guildBanRemoved.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildMemberAddEventAsync(TransportMember member, DiscordGuild guild) { DiscordUser newUser = new DiscordUser(member.User) { Discord = this }; UpdateUserCache(newUser); DiscordMember discordMember = new DiscordMember(member) { Discord = this, _guild_id = guild.Id }; guild._members[discordMember.Id] = discordMember; guild.MemberCount++; GuildMemberAddEventArgs args = new GuildMemberAddEventArgs { Guild = guild, Member = discordMember }; await _guildMemberAdded.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildMemberRemoveEventAsync(TransportUser user, DiscordGuild guild) { DiscordUser discordUser = new DiscordUser(user); if (!guild._members.TryRemove(user.Id, out var value)) { value = new DiscordMember(discordUser) { Discord = this, _guild_id = guild.Id }; } guild.MemberCount--; UpdateUserCache(discordUser); GuildMemberRemoveEventArgs args = new GuildMemberRemoveEventArgs { Guild = guild, Member = value }; await _guildMemberRemoved.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildMemberUpdateEventAsync(TransportMember member, DiscordGuild guild) { DiscordUser newUser = new DiscordUser(member.User) { Discord = this }; UpdateUserCache(newUser); DiscordMember memberAfter = new DiscordMember(member) { Discord = this, _guild_id = guild.Id }; if (!guild.Members.TryGetValue(member.User.Id, out var value)) { value = new DiscordMember(member) { Discord = this, _guild_id = guild.Id }; } guild._members.AddOrUpdate(member.User.Id, memberAfter, (ulong _, DiscordMember _) => memberAfter); GuildMemberUpdateEventArgs args = new GuildMemberUpdateEventArgs { Guild = guild, MemberAfter = memberAfter, MemberBefore = value }; await _guildMemberUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildMembersChunkEventAsync(JObject dat) { DiscordGuild discordGuild = Guilds[(ulong)dat["guild_id"]]; int chunkIndex = (int)dat["chunk_index"]; int chunkCount = (int)dat["chunk_count"]; string nonce = (string?)dat["nonce"]; HashSet hashSet = new HashSet(); HashSet hashSet2 = new HashSet(); TransportMember[] array = dat["members"].ToDiscordObject(); int num = array.Count(); for (int i = 0; i < num; i++) { DiscordMember discordMember = new DiscordMember(array[i]) { Discord = this, _guild_id = discordGuild.Id }; if (!base.UserCache.ContainsKey(discordMember.Id)) { base.UserCache[discordMember.Id] = new DiscordUser(array[i].User) { Discord = this }; } discordGuild._members[discordMember.Id] = discordMember; hashSet.Add(discordMember); } discordGuild.MemberCount = discordGuild._members.Count; GuildMembersChunkEventArgs guildMembersChunkEventArgs = new GuildMembersChunkEventArgs { Guild = discordGuild, Members = new ReadOnlySet(hashSet), ChunkIndex = chunkIndex, ChunkCount = chunkCount, Nonce = nonce }; if (dat["presences"] != null) { DiscordPresence[] array2 = dat["presences"].ToDiscordObject(); int num2 = array2.Count(); for (int j = 0; j < num2; j++) { DiscordPresence discordPresence = array2[j]; discordPresence.Discord = this; discordPresence.Activity = new DiscordActivity(discordPresence.RawActivity); if (discordPresence.RawActivities != null) { discordPresence._internalActivities = new DiscordActivity[discordPresence.RawActivities.Length]; for (int k = 0; k < discordPresence.RawActivities.Length; k++) { discordPresence._internalActivities[k] = new DiscordActivity(discordPresence.RawActivities[k]); } } hashSet2.Add(discordPresence); } guildMembersChunkEventArgs.Presences = new ReadOnlySet(hashSet2); } if (dat["not_found"] != null) { ISet sourceSet = dat["not_found"].ToDiscordObject>(); guildMembersChunkEventArgs.NotFound = new ReadOnlySet(sourceSet); } await _guildMembersChunked.InvokeAsync(this, guildMembersChunkEventArgs).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildRoleCreateEventAsync(DiscordRole role, DiscordGuild guild) { role.Discord = this; role._guild_id = guild.Id; guild._roles[role.Id] = role; GuildRoleCreateEventArgs args = new GuildRoleCreateEventArgs { Guild = guild, Role = role }; await _guildRoleCreated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildRoleUpdateEventAsync(DiscordRole role, DiscordGuild guild) { DiscordRole role2 = guild.GetRole(role.Id); DiscordRole roleBefore = new DiscordRole { _guild_id = guild.Id, _color = role2._color, Discord = this, IsHoisted = role2.IsHoisted, Id = role2.Id, IsManaged = role2.IsManaged, IsMentionable = role2.IsMentionable, Name = role2.Name, Permissions = role2.Permissions, Position = role2.Position, IconHash = role2.IconHash, _emoji = role2._emoji }; role2._guild_id = guild.Id; role2._color = role._color; role2.IsHoisted = role.IsHoisted; role2.IsManaged = role.IsManaged; role2.IsMentionable = role.IsMentionable; role2.Name = role.Name; role2.Permissions = role.Permissions; role2.Position = role.Position; role2._emoji = role._emoji; role2.IconHash = role.IconHash; GuildRoleUpdateEventArgs args = new GuildRoleUpdateEventArgs { Guild = guild, RoleAfter = role2, RoleBefore = roleBefore }; await _guildRoleUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnGuildRoleDeleteEventAsync(ulong roleId, DiscordGuild guild) { if (!guild._roles.TryRemove(roleId, out var value)) { base.Logger.LogWarning($"Attempted to delete a nonexistent role ({roleId}) from guild ({guild})."); } GuildRoleDeleteEventArgs args = new GuildRoleDeleteEventArgs { Guild = guild, Role = value }; await _guildRoleDeleted.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnInviteCreateEventAsync(ulong channelId, ulong guildId, DiscordInvite invite) { DiscordGuild discordGuild = InternalGetCachedGuild(guildId); DiscordChannel channel = InternalGetCachedChannel(channelId); invite.Discord = this; discordGuild._invites[invite.Code] = invite; InviteCreateEventArgs args = new InviteCreateEventArgs { Channel = channel, Guild = discordGuild, Invite = invite }; await _inviteCreated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnInviteDeleteEventAsync(ulong channelId, ulong guildId, JToken dat) { DiscordGuild discordGuild = InternalGetCachedGuild(guildId); DiscordChannel channel = InternalGetCachedChannel(channelId); if (!discordGuild._invites.TryRemove(dat["code"].ToString(), out var value)) { value = dat.ToDiscordObject(); value.Discord = this; } value.IsRevoked = true; InviteDeleteEventArgs args = new InviteDeleteEventArgs { Channel = channel, Guild = discordGuild, Invite = value }; await _inviteDeleted.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnMessageAckEventAsync(DiscordChannel chn, ulong messageId) { if (MessageCache == null || !MessageCache.TryGet((DiscordMessage xm) => xm.Id == messageId && xm.ChannelId == chn.Id, out var item)) { item = new DiscordMessage { Id = messageId, ChannelId = chn.Id, Discord = this }; } await _messageAcknowledged.InvokeAsync(this, new MessageAcknowledgeEventArgs { Message = item }).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnMessageCreateEventAsync(DiscordMessage message, TransportUser author, TransportMember member, TransportUser referenceAuthor, TransportMember referenceMember) { message.Discord = this; PopulateMessageReactionsAndCache(message, author, member); message.PopulateMentions(); if (message.Channel == null && message.ChannelId == 0L) { base.Logger.LogWarning(LoggerEvents.WebSocketReceive, "Channel which the last message belongs to is not in cache - cache state might be invalid!"); } if (message.ReferencedMessage != null) { message.ReferencedMessage.Discord = this; PopulateMessageReactionsAndCache(message.ReferencedMessage, referenceAuthor, referenceMember); message.ReferencedMessage.PopulateMentions(); } foreach (DiscordMessageSticker sticker in message.Stickers) { sticker.Discord = this; } MessageCreateEventArgs args = new MessageCreateEventArgs { Message = message, MentionedUsers = new ReadOnlyCollection(message._mentionedUsers), MentionedRoles = ((message._mentionedRoles != null) ? new ReadOnlyCollection(message._mentionedRoles) : null), MentionedChannels = ((message._mentionedChannels != null) ? new ReadOnlyCollection(message._mentionedChannels) : null) }; await _messageCreated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnMessageUpdateEventAsync(DiscordMessage message, TransportUser author, TransportMember member, TransportUser referenceAuthor, TransportMember referenceMember) { message.Discord = this; DiscordMessage event_message = message; DiscordMessage messageBefore = null; if (base.Configuration.MessageCacheSize == 0 || MessageCache == null || !MessageCache.TryGet((DiscordMessage xm) => xm.Id == event_message.Id && xm.ChannelId == event_message.ChannelId, out message)) { message = event_message; PopulateMessageReactionsAndCache(message, author, member); _ = message.Channel?.Guild; if (message.ReferencedMessage != null) { message.ReferencedMessage.Discord = this; PopulateMessageReactionsAndCache(message.ReferencedMessage, referenceAuthor, referenceMember); message.ReferencedMessage.PopulateMentions(); } } else { messageBefore = new DiscordMessage(message); _ = message.Channel?.Guild; message.EditedTimestamp = event_message.EditedTimestamp; if (event_message.Content != null) { message.Content = event_message.Content; } message._embeds.Clear(); message._embeds.AddRange(event_message._embeds); message._attachments.Clear(); message._attachments.AddRange(event_message._attachments); message.Pinned = event_message.Pinned; message.IsTTS = event_message.IsTTS; message._mentionedUsers.Clear(); message._mentionedUsers.AddRange(event_message._mentionedUsers ?? new List()); message._mentionedRoles.Clear(); message._mentionedRoles.AddRange(event_message._mentionedRoles ?? new List()); message._mentionedChannels.Clear(); message._mentionedChannels.AddRange(event_message._mentionedChannels ?? new List()); message.MentionEveryone = event_message.MentionEveryone; } message.PopulateMentions(); MessageUpdateEventArgs args = new MessageUpdateEventArgs { Message = message, MessageBefore = messageBefore, MentionedUsers = new ReadOnlyCollection(message._mentionedUsers), MentionedRoles = ((message._mentionedRoles != null) ? new ReadOnlyCollection(message._mentionedRoles) : null), MentionedChannels = ((message._mentionedChannels != null) ? new ReadOnlyCollection(message._mentionedChannels) : null) }; await _messageUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnMessageDeleteEventAsync(ulong messageId, ulong channelId, ulong? guildId) { DiscordGuild guild = InternalGetCachedGuild(guildId); DiscordChannel discordChannel = InternalGetCachedChannel(channelId) ?? InternalGetCachedThread(channelId); if (discordChannel == null) { discordChannel = new DiscordDmChannel { Id = channelId, Discord = this, Type = ChannelType.Private, Recipients = Array.Empty() }; _privateChannels[channelId] = (DiscordDmChannel)discordChannel; } if (discordChannel == null || base.Configuration.MessageCacheSize == 0 || MessageCache == null || !MessageCache.TryGet((DiscordMessage xm) => xm.Id == messageId && xm.ChannelId == channelId, out var msg)) { msg = new DiscordMessage { Id = messageId, ChannelId = channelId, Discord = this }; } if (base.Configuration.MessageCacheSize > 0) { MessageCache?.Remove((DiscordMessage xm) => xm.Id == msg.Id && xm.ChannelId == channelId); } MessageDeleteEventArgs args = new MessageDeleteEventArgs { Message = msg, Channel = discordChannel, Guild = guild }; await _messageDeleted.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnMessageBulkDeleteEventAsync(ulong[] messageIds, ulong channelId, ulong? guildId) { DiscordChannel discordChannel = InternalGetCachedChannel(channelId) ?? InternalGetCachedThread(channelId); List list = new List(messageIds.Length); foreach (ulong messageId in messageIds) { if (discordChannel == null || base.Configuration.MessageCacheSize == 0 || MessageCache == null || !MessageCache.TryGet((DiscordMessage xm) => xm.Id == messageId && xm.ChannelId == channelId, out var msg)) { msg = new DiscordMessage { Id = messageId, ChannelId = channelId, Discord = this }; } if (base.Configuration.MessageCacheSize > 0) { MessageCache?.Remove((DiscordMessage xm) => xm.Id == msg.Id && xm.ChannelId == channelId); } list.Add(msg); } DiscordGuild guild = InternalGetCachedGuild(guildId); MessageBulkDeleteEventArgs args = new MessageBulkDeleteEventArgs { Channel = discordChannel, Messages = new ReadOnlyCollection(list), Guild = guild }; await _messagesBulkDeleted.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnMessageReactionAddAsync(ulong userId, ulong messageId, ulong channelId, ulong? guildId, TransportMember mbr, DiscordEmoji emoji) { DiscordChannel discordChannel = InternalGetCachedChannel(channelId) ?? InternalGetCachedThread(channelId); DiscordGuild discordGuild = InternalGetCachedGuild(guildId); emoji.Discord = this; DiscordUser user = null; user = (TryGetCachedUserInternal(userId, out user) ? UpdateUser(user, discordGuild?.Id, discordGuild, mbr) : UpdateUser(new DiscordUser { Id = userId, Discord = this }, guildId, discordGuild, mbr)); if (discordChannel == null) { DiscordDmChannel discordDmChannel = new DiscordDmChannel(); discordDmChannel.Id = channelId; discordDmChannel.Discord = this; discordDmChannel.Type = ChannelType.Private; discordDmChannel.Recipients = new DiscordUser[1] { user }; discordChannel = discordDmChannel; _privateChannels[channelId] = (DiscordDmChannel)discordChannel; } if (discordChannel == null || base.Configuration.MessageCacheSize == 0 || MessageCache == null || !MessageCache.TryGet((DiscordMessage xm) => xm.Id == messageId && xm.ChannelId == channelId, out var item)) { item = new DiscordMessage { Id = messageId, ChannelId = channelId, Discord = this, _reactions = new List() }; } DiscordReaction discordReaction = item._reactions.FirstOrDefault((DiscordReaction xr) => xr.Emoji == emoji); if (discordReaction == null) { item._reactions.Add(new DiscordReaction { Count = 1, Emoji = emoji, IsMe = (base.CurrentUser.Id == userId) }); } else { discordReaction.Count++; discordReaction.IsMe |= base.CurrentUser.Id == userId; } MessageReactionAddEventArgs args = new MessageReactionAddEventArgs { Message = item, User = user, Guild = discordGuild, Emoji = emoji }; await _messageReactionAdded.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnMessageReactionRemoveAsync(ulong userId, ulong messageId, ulong channelId, ulong? guildId, DiscordEmoji emoji) { DiscordChannel discordChannel = InternalGetCachedChannel(channelId) ?? InternalGetCachedThread(channelId); emoji.Discord = this; if (!base.UserCache.TryGetValue(userId, out var value)) { value = new DiscordUser { Id = userId, Discord = this }; } if (discordChannel == null) { DiscordDmChannel discordDmChannel = new DiscordDmChannel(); discordDmChannel.Id = channelId; discordDmChannel.Discord = this; discordDmChannel.Type = ChannelType.Private; discordDmChannel.Recipients = new DiscordUser[1] { value }; discordChannel = discordDmChannel; _privateChannels[channelId] = (DiscordDmChannel)discordChannel; } if (discordChannel?.Guild != null) { value = (discordChannel.Guild.Members.TryGetValue(userId, out var value2) ? value2 : new DiscordMember(value) { Discord = this, _guild_id = discordChannel.GuildId.Value }); } if (discordChannel == null || base.Configuration.MessageCacheSize == 0 || MessageCache == null || !MessageCache.TryGet((DiscordMessage xm) => xm.Id == messageId && xm.ChannelId == channelId, out var item)) { item = new DiscordMessage { Id = messageId, ChannelId = channelId, Discord = this }; } DiscordReaction discordReaction = item._reactions?.FirstOrDefault((DiscordReaction xr) => xr.Emoji == emoji); if (discordReaction != null) { discordReaction.Count--; discordReaction.IsMe &= base.CurrentUser.Id != userId; if (item._reactions != null && discordReaction.Count <= 0) { for (int i = 0; i < item._reactions.Count; i++) { if (item._reactions[i].Emoji == emoji) { item._reactions.RemoveAt(i); break; } } } } DiscordGuild guild = InternalGetCachedGuild(guildId); MessageReactionRemoveEventArgs args = new MessageReactionRemoveEventArgs { Message = item, User = value, Guild = guild, Emoji = emoji }; await _messageReactionRemoved.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnMessageReactionRemoveAllAsync(ulong messageId, ulong channelId, ulong? guildId) { if ((InternalGetCachedChannel(channelId) ?? InternalGetCachedThread(channelId)) == null || base.Configuration.MessageCacheSize == 0 || MessageCache == null || !MessageCache.TryGet((DiscordMessage xm) => xm.Id == messageId && xm.ChannelId == channelId, out var item)) { item = new DiscordMessage { Id = messageId, ChannelId = channelId, Discord = this }; } item._reactions?.Clear(); InternalGetCachedGuild(guildId); MessageReactionsClearEventArgs args = new MessageReactionsClearEventArgs { Message = item }; await _messageReactionsCleared.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnMessageReactionRemoveEmojiAsync(ulong messageId, ulong channelId, ulong guildId, JToken dat) { DiscordGuild discordGuild = InternalGetCachedGuild(guildId); DiscordChannel discordChannel = InternalGetCachedChannel(channelId) ?? InternalGetCachedThread(channelId); if (discordChannel == null) { discordChannel = new DiscordDmChannel { Id = channelId, Discord = this, Type = ChannelType.Private, Recipients = Array.Empty() }; _privateChannels[channelId] = (DiscordDmChannel)discordChannel; } if (discordChannel == null || base.Configuration.MessageCacheSize == 0 || MessageCache == null || !MessageCache.TryGet((DiscordMessage xm) => xm.Id == messageId && xm.ChannelId == channelId, out var item)) { item = new DiscordMessage { Id = messageId, ChannelId = channelId, Discord = this }; } DiscordEmoji discordEmoji = dat.ToDiscordObject(); if (!discordGuild._emojis.TryGetValue(discordEmoji.Id, out var emoji)) { emoji = discordEmoji; emoji.Discord = this; } item._reactions?.RemoveAll((DiscordReaction r) => r.Emoji.Equals(emoji)); MessageReactionRemoveEmojiEventArgs args = new MessageReactionRemoveEmojiEventArgs { Message = item, Channel = discordChannel, Guild = discordGuild, Emoji = emoji }; await _messageReactionRemovedEmoji.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnPresenceUpdateEventAsync(JObject rawPresence, JObject rawUser) { ulong key = (ulong)rawUser["id"]; DiscordPresence discordPresence = null; if (_presences.TryGetValue(key, out var value)) { discordPresence = new DiscordPresence(value); DiscordJson.PopulateObject(rawPresence, value); } else { value = rawPresence.ToDiscordObject(); value.Discord = this; value.Activity = new DiscordActivity(value.RawActivity); _presences[value.InternalUser.Id] = value; } if (value.Activities == null || rawPresence["activities"] == null) { value._internalActivities = Array.Empty(); } else { if (value._internalActivities.Length != value.RawActivities.Length) { value._internalActivities = new DiscordActivity[value.RawActivities.Length]; } for (int i = 0; i < value._internalActivities.Length; i++) { value._internalActivities[i] = new DiscordActivity(value.RawActivities[i]); } if (value._internalActivities.Length != 0) { value.RawActivity = value.RawActivities[0]; if (value.Activity != null) { value.Activity.UpdateWith(value.RawActivity); } else { value.Activity = new DiscordActivity(value.RawActivity); } } else { value.RawActivity = null; value.Activity = null; } } base.UserCache.TryGetValue(key, out var value2); DiscordUser discordUser = value2 ?? new DiscordUser(value.InternalUser); PresenceUpdateEventArgs args = new PresenceUpdateEventArgs { Status = value.Status, Activity = value.Activity, User = value2, PresenceBefore = discordPresence, PresenceAfter = value, UserBefore = ((discordPresence != null) ? new DiscordUser(discordPresence.InternalUser) { Discord = this } : discordUser), UserAfter = discordUser }; await _presenceUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnUserSettingsUpdateEventAsync(TransportUser user) { DiscordUser user2 = new DiscordUser(user) { Discord = this }; UserSettingsUpdateEventArgs args = new UserSettingsUpdateEventArgs { User = user2 }; await _userSettingsUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnUserUpdateEventAsync(TransportUser user) { DiscordUser userBefore = new DiscordUser { AvatarHash = base.CurrentUser.AvatarHash, Discord = this, Discriminator = base.CurrentUser.Discriminator, Email = base.CurrentUser.Email, Id = base.CurrentUser.Id, IsBot = base.CurrentUser.IsBot, MfaEnabled = base.CurrentUser.MfaEnabled, Username = base.CurrentUser.Username, Verified = base.CurrentUser.Verified }; base.CurrentUser.AvatarHash = user.AvatarHash; base.CurrentUser.Discriminator = user.Discriminator; base.CurrentUser.Email = user.Email; base.CurrentUser.Id = user.Id; base.CurrentUser.IsBot = user.IsBot; base.CurrentUser.MfaEnabled = user.MfaEnabled; base.CurrentUser.Username = user.Username; base.CurrentUser.Verified = user.Verified; UserUpdateEventArgs args = new UserUpdateEventArgs { UserAfter = base.CurrentUser, UserBefore = userBefore }; await _userUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnVoiceStateUpdateEventAsync(JObject raw) { ulong num = (ulong)raw["guild_id"]; ulong key = (ulong)raw["user_id"]; DiscordGuild discordGuild = _guilds[num]; DiscordVoiceState discordVoiceState = raw.ToDiscordObject(); discordVoiceState.Discord = this; discordGuild._voiceStates.TryRemove(key, out var value); if (discordVoiceState.Channel != null) { discordGuild._voiceStates[discordVoiceState.UserId] = discordVoiceState; } if (discordGuild._members.TryGetValue(key, out var value2)) { value2.IsMuted = discordVoiceState.IsServerMuted; value2.IsDeafened = discordVoiceState.IsServerDeafened; } else { TransportMember transportMember = discordVoiceState.TransportMember; UpdateUser(new DiscordUser(transportMember.User) { Discord = this }, num, discordGuild, transportMember); } VoiceStateUpdateEventArgs args = new VoiceStateUpdateEventArgs { Guild = discordVoiceState.Guild, Channel = discordVoiceState.Channel, User = discordVoiceState.User, SessionId = discordVoiceState.SessionId, Before = value, After = discordVoiceState }; await _voiceStateUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnVoiceServerUpdateEventAsync(string endpoint, string token, DiscordGuild guild) { VoiceServerUpdateEventArgs args = new VoiceServerUpdateEventArgs { Endpoint = endpoint, VoiceToken = token, Guild = guild }; await _voiceServerUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnThreadCreateEventAsync(DiscordThreadChannel thread, bool isNew) { thread.Discord = this; InternalGetCachedGuild(thread.GuildId)._threads[thread.Id] = thread; await _threadCreated.InvokeAsync(this, new ThreadCreateEventArgs { Thread = thread, Guild = thread.Guild, Parent = thread.Parent }).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnThreadUpdateEventAsync(DiscordThreadChannel thread) { if (!(thread == null)) { thread.Discord = this; DiscordGuild guild = thread.Guild; guild.Discord = this; DiscordThreadChannel discordThreadChannel = InternalGetCachedThread(thread.Id); ThreadUpdateEventArgs args; if (discordThreadChannel != null) { DiscordThreadChannel threadBefore = new DiscordThreadChannel { Discord = this, GuildId = discordThreadChannel.GuildId, CreatorId = discordThreadChannel.CreatorId, ParentId = discordThreadChannel.ParentId, Id = discordThreadChannel.Id, Name = discordThreadChannel.Name, Type = discordThreadChannel.Type, LastMessageId = discordThreadChannel.LastMessageId, MessageCount = discordThreadChannel.MessageCount, MemberCount = discordThreadChannel.MemberCount, ThreadMetadata = discordThreadChannel.ThreadMetadata, CurrentMember = discordThreadChannel.CurrentMember }; args = new ThreadUpdateEventArgs { ThreadAfter = thread, ThreadBefore = threadBefore, Guild = thread.Guild, Parent = thread.Parent }; } else { args = new ThreadUpdateEventArgs { ThreadAfter = thread, Guild = thread.Guild, Parent = thread.Parent }; guild._threads[thread.Id] = thread; } await _threadUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } } internal async Task OnThreadDeleteEventAsync(DiscordThreadChannel thread) { if (!(thread == null)) { thread.Discord = this; if (thread.Guild._threads.TryRemove(thread.Id, out var value)) { thread = value; } await _threadDeleted.InvokeAsync(this, new ThreadDeleteEventArgs { Thread = thread, Guild = thread.Guild, Parent = thread.Parent }).ConfigureAwait(continueOnCapturedContext: false); } } internal async Task OnThreadListSyncEventAsync(DiscordGuild guild, IReadOnlyList channel_ids, IReadOnlyList threads, IReadOnlyList members) { guild.Discord = this; IEnumerable enumerable = channel_ids.Select((ulong x) => guild.GetChannel(x) ?? new DiscordChannel { Id = x, GuildId = guild.Id }); foreach (DiscordChannel item in enumerable) { item.Discord = this; } foreach (DiscordThreadChannel thread in threads) { thread.Discord = this; guild._threads[thread.Id] = thread; } foreach (DiscordThreadChannelMember member in members) { member.Discord = this; member._guild_id = guild.Id; DiscordThreadChannel discordThreadChannel = threads.SingleOrDefault((DiscordThreadChannel x) => x.Id == member.ThreadId); if (discordThreadChannel != null) { discordThreadChannel.CurrentMember = member; } } await _threadListSynced.InvokeAsync(this, new ThreadListSyncEventArgs { Guild = guild, Channels = enumerable.ToList().AsReadOnly(), Threads = threads, CurrentMembers = members.ToList().AsReadOnly() }).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnThreadMemberUpdateEventAsync(DiscordThreadChannelMember member) { member.Discord = this; DiscordThreadChannel discordThreadChannel = InternalGetCachedThread(member.ThreadId); member._guild_id = discordThreadChannel.Guild.Id; discordThreadChannel.CurrentMember = member; discordThreadChannel.Guild._threads[discordThreadChannel.Id] = discordThreadChannel; await _threadMemberUpdated.InvokeAsync(this, new ThreadMemberUpdateEventArgs { ThreadMember = member, Thread = discordThreadChannel }).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnThreadMembersUpdateEventAsync(DiscordGuild guild, ulong thread_id, IReadOnlyList addedMembers, IReadOnlyList removed_member_ids, int member_count) { DiscordThreadChannel discordThreadChannel = InternalGetCachedThread(thread_id); if (discordThreadChannel == null) { discordThreadChannel = new DiscordThreadChannel { Id = thread_id, GuildId = guild.Id }; } discordThreadChannel.Discord = this; guild.Discord = this; discordThreadChannel.MemberCount = member_count; List list = new List(); if (removed_member_ids != null) { foreach (ulong? removed_member_id in removed_member_ids) { list.Add(guild._members.TryGetValue(removed_member_id.Value, out var value) ? value : new DiscordMember { Id = removed_member_id.Value, _guild_id = guild.Id, Discord = this }); } if (removed_member_ids.Contains(base.CurrentUser.Id)) { discordThreadChannel.CurrentMember = null; } } else { removed_member_ids = Array.Empty(); } if (addedMembers != null) { foreach (DiscordThreadChannelMember addedMember in addedMembers) { addedMember.Discord = this; addedMember._guild_id = guild.Id; } if (addedMembers.Any((DiscordThreadChannelMember member) => member.Id == base.CurrentUser.Id)) { discordThreadChannel.CurrentMember = addedMembers.Single((DiscordThreadChannelMember member) => member.Id == base.CurrentUser.Id); } } else { addedMembers = Array.Empty(); } ThreadMembersUpdateEventArgs args = new ThreadMembersUpdateEventArgs { Guild = guild, Thread = discordThreadChannel, AddedMembers = addedMembers, RemovedMembers = list, MemberCount = member_count }; await _threadMembersUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnApplicationCommandCreateAsync(DiscordApplicationCommand cmd, ulong? guild_id) { cmd.Discord = this; DiscordGuild discordGuild = InternalGetCachedGuild(guild_id); if (discordGuild == null && guild_id.HasValue) { discordGuild = new DiscordGuild { Id = guild_id.Value, Discord = this }; } ApplicationCommandEventArgs args = new ApplicationCommandEventArgs { Guild = discordGuild, Command = cmd }; await _applicationCommandCreated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnApplicationCommandUpdateAsync(DiscordApplicationCommand cmd, ulong? guild_id) { cmd.Discord = this; DiscordGuild discordGuild = InternalGetCachedGuild(guild_id); if (discordGuild == null && guild_id.HasValue) { discordGuild = new DiscordGuild { Id = guild_id.Value, Discord = this }; } ApplicationCommandEventArgs args = new ApplicationCommandEventArgs { Guild = discordGuild, Command = cmd }; await _applicationCommandUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnApplicationCommandPermissionsUpdateAsync(JObject obj) { ApplicationCommandPermissionsUpdatedEventArgs args = obj.ToObject(); await _applicationCommandPermissionsUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnApplicationCommandDeleteAsync(DiscordApplicationCommand cmd, ulong? guild_id) { cmd.Discord = this; DiscordGuild discordGuild = InternalGetCachedGuild(guild_id); if (discordGuild == null && guild_id.HasValue) { discordGuild = new DiscordGuild { Id = guild_id.Value, Discord = this }; } ApplicationCommandEventArgs args = new ApplicationCommandEventArgs { Guild = discordGuild, Command = cmd }; await _applicationCommandDeleted.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnIntegrationCreateAsync(DiscordIntegration integration, ulong guild_id) { DiscordGuild discordGuild = InternalGetCachedGuild(guild_id); if (discordGuild == null) { discordGuild = new DiscordGuild { Id = guild_id, Discord = this }; } IntegrationCreateEventArgs args = new IntegrationCreateEventArgs { Guild = discordGuild, Integration = integration }; await _integrationCreated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnIntegrationUpdateAsync(DiscordIntegration integration, ulong guild_id) { DiscordGuild discordGuild = InternalGetCachedGuild(guild_id); if (discordGuild == null) { discordGuild = new DiscordGuild { Id = guild_id, Discord = this }; } IntegrationUpdateEventArgs args = new IntegrationUpdateEventArgs { Guild = discordGuild, Integration = integration }; await _integrationUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnIntegrationDeleteAsync(ulong integration_id, ulong guild_id, ulong? application_id) { DiscordGuild discordGuild = InternalGetCachedGuild(guild_id); if (discordGuild == null) { discordGuild = new DiscordGuild { Id = guild_id, Discord = this }; } IntegrationDeleteEventArgs args = new IntegrationDeleteEventArgs { Guild = discordGuild, Applicationid = application_id, IntegrationId = integration_id }; await _integrationDeleted.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnStageInstanceCreateAsync(DiscordStageInstance instance) { instance.Discord = this; InternalGetCachedGuild(instance.GuildId)._stageInstances[instance.Id] = instance; StageInstanceCreateEventArgs args = new StageInstanceCreateEventArgs { StageInstance = instance }; await _stageInstanceCreated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnStageInstanceUpdateAsync(DiscordStageInstance instance) { instance.Discord = this; DiscordGuild discordGuild = InternalGetCachedGuild(instance.GuildId); if (!discordGuild._stageInstances.TryRemove(instance.Id, out var value)) { value = new DiscordStageInstance { Id = instance.Id, GuildId = instance.GuildId, ChannelId = instance.ChannelId }; } discordGuild._stageInstances[instance.Id] = instance; StageInstanceUpdateEventArgs args = new StageInstanceUpdateEventArgs { StageInstanceBefore = value, StageInstanceAfter = instance }; await _stageInstanceUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnStageInstanceDeleteAsync(DiscordStageInstance instance) { instance.Discord = this; InternalGetCachedGuild(instance.GuildId)._stageInstances.TryRemove(instance.Id, out var _); StageInstanceDeleteEventArgs args = new StageInstanceDeleteEventArgs { StageInstance = instance }; await _stageInstanceDeleted.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnInteractionCreateAsync(ulong? guildId, ulong channelId, TransportUser user, TransportMember member, DiscordInteraction interaction) { DiscordUser discordUser = new DiscordUser(user) { Discord = this }; interaction.ChannelId = channelId; interaction.GuildId = guildId; interaction.Discord = this; interaction.Data.Discord = this; if (member != null) { discordUser = new DiscordMember(member) { _guild_id = guildId.Value, Discord = this }; UpdateUser(discordUser, guildId, interaction.Guild, member); } else { UpdateUserCache(discordUser); } interaction.User = discordUser; DiscordInteractionResolvedCollection resolved = interaction.Data.Resolved; if (resolved != null) { if (resolved.Users != null) { foreach (KeyValuePair user2 in resolved.Users) { user2.Value.Discord = this; UpdateUserCache(user2.Value); } } if (resolved.Members != null) { foreach (KeyValuePair member2 in resolved.Members) { member2.Value.Discord = this; member2.Value.Id = member2.Key; member2.Value._guild_id = guildId.Value; member2.Value.User.Discord = this; UpdateUserCache(member2.Value.User); } } if (resolved.Channels != null) { foreach (KeyValuePair channel in resolved.Channels) { channel.Value.Discord = this; if (guildId.HasValue) { channel.Value.GuildId = guildId.Value; } } } if (resolved.Roles != null) { foreach (KeyValuePair role in resolved.Roles) { role.Value.Discord = this; if (guildId.HasValue) { role.Value._guild_id = guildId.Value; } } } if (resolved.Messages != null) { foreach (KeyValuePair message in resolved.Messages) { message.Value.Discord = this; if (guildId.HasValue) { message.Value._guildId = guildId.Value; } } } } if (interaction.Type == InteractionType.Component) { interaction.Message.Discord = this; interaction.Message.ChannelId = interaction.ChannelId; ComponentInteractionCreateEventArgs args = new ComponentInteractionCreateEventArgs { Message = interaction.Message, Interaction = interaction }; await _componentInteractionCreated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } else if (interaction.Type == InteractionType.ModalSubmit) { ModalSubmitEventArgs args2 = new ModalSubmitEventArgs(interaction); await _modalSubmitted.InvokeAsync(this, args2).ConfigureAwait(continueOnCapturedContext: false); } else if (interaction.Data.Target.HasValue) { ulong value = interaction.Data.Target.Value; DiscordUser value2 = null; DiscordMember value3 = null; DiscordMessage value4 = null; interaction.Data.Resolved.Messages?.TryGetValue(value, out value4); interaction.Data.Resolved.Members?.TryGetValue(value, out value3); interaction.Data.Resolved.Users?.TryGetValue(value, out value2); ContextMenuInteractionCreateEventArgs args3 = new ContextMenuInteractionCreateEventArgs { Interaction = interaction, TargetUser = (value3 ?? value2), TargetMessage = value4, Type = interaction.Data.Type }; await _contextMenuInteractionCreated.InvokeAsync(this, args3).ConfigureAwait(continueOnCapturedContext: false); } else { InteractionCreateEventArgs args4 = new InteractionCreateEventArgs { Interaction = interaction }; await _interactionCreated.InvokeAsync(this, args4).ConfigureAwait(continueOnCapturedContext: false); } } internal async Task OnTypingStartEventAsync(ulong userId, ulong channelId, DiscordChannel channel, ulong? guildId, DateTimeOffset started, TransportMember mbr) { if (channel == null) { channel = new DiscordChannel { Discord = this, Id = channelId, GuildId = guildId.GetValueOrDefault() }; } DiscordGuild guild = InternalGetCachedGuild(guildId); DiscordUser user = UpdateUser(new DiscordUser { Id = userId, Discord = this }, guildId, guild, mbr); TypingStartEventArgs args = new TypingStartEventArgs { Channel = channel, User = user, Guild = guild, StartedAt = started }; await _typingStarted.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnWebhooksUpdateAsync(DiscordChannel channel, DiscordGuild guild) { WebhooksUpdateEventArgs args = new WebhooksUpdateEventArgs { Channel = channel, Guild = guild }; await _webhooksUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnStickersUpdatedAsync(IEnumerable newStickers, JObject raw) { DiscordGuild discordGuild = InternalGetCachedGuild((ulong)raw["guild_id"]); ConcurrentDictionary stickersBefore = new ConcurrentDictionary(discordGuild._stickers); discordGuild._stickers.Clear(); foreach (DiscordMessageSticker newSticker in newStickers) { if (newSticker.User != null) { newSticker.User.Discord = this; } newSticker.Discord = this; discordGuild._stickers[newSticker.Id] = newSticker; } GuildStickersUpdateEventArgs args = new GuildStickersUpdateEventArgs { Guild = discordGuild, StickersBefore = stickersBefore, StickersAfter = discordGuild.Stickers }; await _guildStickersUpdated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnUnknownEventAsync(GatewayPayload payload) { UnknownEventArgs args = new UnknownEventArgs { EventName = payload.EventName, Json = (payload.Data as JObject)?.ToString() }; await _unknownEvent.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal void EventErrorHandler(AsyncEvent asyncEvent, Exception ex, AsyncEventHandler handler, TSender sender, TArgs eventArgs) where TArgs : AsyncEventArgs { base.Logger.LogError(LoggerEvents.EventHandlerException, ex, "Event handler exception for event {Event} thrown from {Method} (defined in {DeclaryingType})", asyncEvent.Name, handler.Method, handler.Method.DeclaringType); _clientErrored.InvokeAsync(this, new ClientErrorEventArgs { EventName = asyncEvent.Name, Exception = ex }).ConfigureAwait(continueOnCapturedContext: false).GetAwaiter() .GetResult(); } private void Goof(AsyncEvent asyncEvent, Exception ex, AsyncEventHandler handler, TSender sender, TArgs eventArgs) where TArgs : AsyncEventArgs { base.Logger.LogCritical(LoggerEvents.EventHandlerException, ex, "Exception event handler {Method} (defined in {DeclaringType}) threw an exception", handler.Method, handler.Method.DeclaringType); } private Task InternalReconnectAsync(bool startNewSession = false, int code = 1000, string message = "") { if (startNewSession) { _sessionId = null; } _webSocketClient.DisconnectAsync(code, message); return Task.CompletedTask; } internal async Task InternalConnectAsync() { SocketLock socketLock = null; try { if (GatewayInfo == null) { await InternalUpdateGatewayAsync().ConfigureAwait(continueOnCapturedContext: false); } await InitializeAsync().ConfigureAwait(continueOnCapturedContext: false); socketLock = GetSocketLock(); await socketLock.LockAsync().ConfigureAwait(continueOnCapturedContext: false); } catch { socketLock?.UnlockAfter(TimeSpan.Zero); throw; } if (!Presences.ContainsKey(base.CurrentUser.Id)) { _presences[base.CurrentUser.Id] = new DiscordPresence { Discord = this, RawActivity = new TransportActivity(), Activity = new DiscordActivity(), Status = UserStatus.Online, InternalUser = new TransportUser { Id = base.CurrentUser.Id, Username = base.CurrentUser.Username, Discriminator = base.CurrentUser.Discriminator, AvatarHash = base.CurrentUser.AvatarHash } }; } else { DiscordPresence discordPresence = _presences[base.CurrentUser.Id]; discordPresence.RawActivity = new TransportActivity(); discordPresence.Activity = new DiscordActivity(); discordPresence.Status = UserStatus.Online; } Volatile.Write(ref _skippedHeartbeats, 0); _webSocketClient = base.Configuration.WebSocketClientFactory(base.Configuration.Proxy); _payloadDecompressor = ((base.Configuration.GatewayCompressionLevel != 0) ? new PayloadDecompressor(base.Configuration.GatewayCompressionLevel) : null); _cancelTokenSource = new CancellationTokenSource(); _cancelToken = _cancelTokenSource.Token; _webSocketClient.Connected += SocketOnConnect; _webSocketClient.Disconnected += SocketOnDisconnect; _webSocketClient.MessageReceived += SocketOnMessage; _webSocketClient.ExceptionThrown += SocketOnException; QueryUriBuilder queryUriBuilder = new QueryUriBuilder(GatewayUri).AddParameter("v", "10").AddParameter("encoding", "json"); if (base.Configuration.GatewayCompressionLevel == GatewayCompressionLevel.Stream) { queryUriBuilder.AddParameter("compress", "zlib-stream"); } await _webSocketClient.ConnectAsync(queryUriBuilder.Build()).ConfigureAwait(continueOnCapturedContext: false); Task SocketOnConnect(IWebSocketClient sender, SocketEventArgs e) { return _socketOpened.InvokeAsync(this, e); } async Task SocketOnDisconnect(IWebSocketClient sender, SocketCloseEventArgs e) { ConnectionLock.Set(); _sessionLock.Set(); if (!_disposed) { _cancelTokenSource.Cancel(); } base.Logger.LogDebug(LoggerEvents.ConnectionClose, "Connection closed ({CloseCode}, '{CloseMessage}')", e.CloseCode, e.CloseMessage); await _socketClosed.InvokeAsync(this, e).ConfigureAwait(continueOnCapturedContext: false); if (base.Configuration.AutoReconnect && (e.CloseCode < 4001 || e.CloseCode >= 5000)) { base.Logger.LogCritical(LoggerEvents.ConnectionClose, "Connection terminated ({CloseCode}, '{CloseMessage}'), reconnecting", e.CloseCode, e.CloseMessage); if (_status == null) { await ConnectAsync().ConfigureAwait(continueOnCapturedContext: false); } else if (_status.IdleSince.HasValue) { await ConnectAsync(_status._activity, _status.Status, Utilities.GetDateTimeOffsetFromMilliseconds(_status.IdleSince.Value)).ConfigureAwait(continueOnCapturedContext: false); } else { await ConnectAsync(_status._activity, _status.Status).ConfigureAwait(continueOnCapturedContext: false); } } else { base.Logger.LogInformation(LoggerEvents.ConnectionClose, "Connection terminated ({CloseCode}, '{CloseMessage}')", e.CloseCode, e.CloseMessage); } } Task SocketOnException(IWebSocketClient sender, SocketErrorEventArgs e) { return _socketErrored.InvokeAsync(this, e); } async Task SocketOnMessage(IWebSocketClient sender, SocketMessageEventArgs e) { string text = null; if (e is SocketTextMessageEventArgs socketTextMessageEventArgs) { text = socketTextMessageEventArgs.Message; } else if (e is SocketBinaryMessageEventArgs socketBinaryMessageEventArgs) { using MemoryStream ms = new MemoryStream(); if (!_payloadDecompressor.TryDecompress(new ArraySegment(socketBinaryMessageEventArgs.Message), ms)) { base.Logger.LogError(LoggerEvents.WebSocketReceiveFailure, "Payload decompression failed"); return; } ms.Position = 0L; using StreamReader sr = new StreamReader(ms, Utilities.UTF8); text = await sr.ReadToEndAsync().ConfigureAwait(continueOnCapturedContext: false); } try { base.Logger.LogTrace(LoggerEvents.GatewayWsRx, text); await HandleSocketMessageAsync(text).ConfigureAwait(continueOnCapturedContext: false); } catch (Exception exception) { base.Logger.LogError(LoggerEvents.WebSocketReceiveFailure, exception, "Socket handler suppressed an exception"); } } } internal async Task HandleSocketMessageAsync(string data) { GatewayPayload gatewayPayload = JsonConvert.DeserializeObject(data); _lastSequence = ((long?)gatewayPayload.Sequence) ?? _lastSequence; switch (gatewayPayload.OpCode) { case GatewayOpCode.Dispatch: await HandleDispatchAsync(gatewayPayload).ConfigureAwait(continueOnCapturedContext: false); return; case GatewayOpCode.Heartbeat: await OnHeartbeatAsync((long)gatewayPayload.Data).ConfigureAwait(continueOnCapturedContext: false); return; case GatewayOpCode.Reconnect: await OnReconnectAsync().ConfigureAwait(continueOnCapturedContext: false); return; case GatewayOpCode.InvalidSession: await OnInvalidateSessionAsync((bool)gatewayPayload.Data).ConfigureAwait(continueOnCapturedContext: false); return; case GatewayOpCode.Hello: await OnHelloAsync((gatewayPayload.Data as JObject).ToDiscordObject()).ConfigureAwait(continueOnCapturedContext: false); return; case GatewayOpCode.HeartbeatAck: await OnHeartbeatAckAsync().ConfigureAwait(continueOnCapturedContext: false); return; } base.Logger.LogWarning(LoggerEvents.WebSocketReceive, "Unknown Discord opcode: {Op}\nPayload: {Payload}", gatewayPayload.OpCode, gatewayPayload.Data); } internal async Task OnHeartbeatAsync(long seq) { base.Logger.LogTrace(LoggerEvents.WebSocketReceive, "Received HEARTBEAT (OP1)"); await SendHeartbeatAsync(seq).ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnReconnectAsync() { base.Logger.LogTrace(LoggerEvents.WebSocketReceive, "Received RECONNECT (OP7)"); await InternalReconnectAsync(startNewSession: false, 4000, "OP7 acknowledged").ConfigureAwait(continueOnCapturedContext: false); } internal async Task OnInvalidateSessionAsync(bool data) { if (_sessionLock.Wait(0)) { _sessionLock.Reset(); } SocketLock socketLock = GetSocketLock(); await socketLock.LockAsync().ConfigureAwait(continueOnCapturedContext: false); socketLock.UnlockAfter(TimeSpan.FromSeconds(5.0)); if (data) { base.Logger.LogTrace(LoggerEvents.WebSocketReceive, "Received INVALID_SESSION (OP9, true)"); await Task.Delay(6000).ConfigureAwait(continueOnCapturedContext: false); await SendResumeAsync().ConfigureAwait(continueOnCapturedContext: false); } else { base.Logger.LogTrace(LoggerEvents.WebSocketReceive, "Received INVALID_SESSION (OP9, false)"); _sessionId = null; await SendIdentifyAsync(_status).ConfigureAwait(continueOnCapturedContext: false); } } internal async Task OnHelloAsync(GatewayHello hello) { base.Logger.LogTrace(LoggerEvents.WebSocketReceive, "Received HELLO (OP10)"); if (_sessionLock.Wait(0)) { _sessionLock.Reset(); GetSocketLock().UnlockAfter(TimeSpan.FromSeconds(5.0)); Interlocked.CompareExchange(ref _skippedHeartbeats, 0, 0); _heartbeatInterval = hello.HeartbeatInterval; _heartbeatTask = Task.Run((Func)HeartbeatLoopAsync, _cancelToken); if (string.IsNullOrEmpty(_sessionId)) { await SendIdentifyAsync(_status).ConfigureAwait(continueOnCapturedContext: false); } else { await SendResumeAsync().ConfigureAwait(continueOnCapturedContext: false); } } else { base.Logger.LogWarning(LoggerEvents.SessionUpdate, "Attempt to start a session while another session is active"); } } internal async Task OnHeartbeatAckAsync() { Interlocked.Decrement(ref _skippedHeartbeats); int num = (int)(DateTime.Now - _lastHeartbeat).TotalMilliseconds; base.Logger.LogTrace(LoggerEvents.WebSocketReceive, "Received HEARTBEAT_ACK (OP11, {Heartbeat}ms)", num); Volatile.Write(ref _ping, num); HeartbeatEventArgs args = new HeartbeatEventArgs { Ping = Ping, Timestamp = DateTimeOffset.Now }; await _heartbeated.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); } internal async Task HeartbeatLoopAsync() { base.Logger.LogDebug(LoggerEvents.Heartbeat, "Heartbeat task started"); CancellationToken token = _cancelToken; try { while (true) { await SendHeartbeatAsync(_lastSequence).ConfigureAwait(continueOnCapturedContext: false); await Task.Delay(_heartbeatInterval, token).ConfigureAwait(continueOnCapturedContext: false); token.ThrowIfCancellationRequested(); } } catch (OperationCanceledException) { } } internal async Task InternalUpdateStatusAsync(DiscordActivity activity, UserStatus? userStatus, DateTimeOffset? idleSince) { if (activity != null && activity.Name != null && activity.Name.Length > 128) { throw new Exception("Game name can't be longer than 128 characters!"); } long? idleSince2 = (idleSince.HasValue ? new long?(Utilities.GetUnixTime(idleSince.Value)) : null); DiscordActivity act = activity ?? new DiscordActivity(); StatusUpdate data = (_status = new StatusUpdate { Activity = new TransportActivity(act), IdleSince = idleSince2, IsAFK = idleSince.HasValue, Status = userStatus.GetValueOrDefault(UserStatus.Online) }); string jsonPayload = JsonConvert.SerializeObject(new GatewayPayload { OpCode = GatewayOpCode.StatusUpdate, Data = data }); await SendRawPayloadAsync(jsonPayload).ConfigureAwait(continueOnCapturedContext: false); if (!_presences.ContainsKey(base.CurrentUser.Id)) { _presences[base.CurrentUser.Id] = new DiscordPresence { Discord = this, Activity = act, Status = userStatus.GetValueOrDefault(UserStatus.Online), InternalUser = new TransportUser { Id = base.CurrentUser.Id } }; } else { DiscordPresence discordPresence = _presences[base.CurrentUser.Id]; discordPresence.Activity = act; discordPresence.Status = userStatus ?? discordPresence.Status; } } internal async Task SendHeartbeatAsync(long seq) { bool flag = Volatile.Read(ref _skippedHeartbeats) > 5; bool flag2 = Volatile.Read(ref _guildDownloadCompleted); if (flag2 && flag) { base.Logger.LogCritical(LoggerEvents.HeartbeatFailure, "Server failed to acknowledge more than 5 heartbeats - connection is zombie"); ZombiedEventArgs args = new ZombiedEventArgs { Failures = Volatile.Read(ref _skippedHeartbeats), GuildDownloadCompleted = true }; await _zombied.InvokeAsync(this, args).ConfigureAwait(continueOnCapturedContext: false); await InternalReconnectAsync(startNewSession: false, 4001, "Too many heartbeats missed").ConfigureAwait(continueOnCapturedContext: false); return; } if (!flag2 && flag) { ZombiedEventArgs args2 = new ZombiedEventArgs { Failures = Volatile.Read(ref _skippedHeartbeats), GuildDownloadCompleted = false }; await _zombied.InvokeAsync(this, args2).ConfigureAwait(continueOnCapturedContext: false); base.Logger.LogWarning(LoggerEvents.HeartbeatFailure, "Server failed to acknowledge more than 5 heartbeats, but the guild download is still running - check your connection speed"); } Volatile.Write(ref _lastSequence, seq); base.Logger.LogTrace(LoggerEvents.Heartbeat, "Sending heartbeat"); string jsonPayload = JsonConvert.SerializeObject(new GatewayPayload { OpCode = GatewayOpCode.Heartbeat, Data = seq }); await SendRawPayloadAsync(jsonPayload).ConfigureAwait(continueOnCapturedContext: false); _lastHeartbeat = DateTimeOffset.Now; Interlocked.Increment(ref _skippedHeartbeats); } internal async Task SendIdentifyAsync(StatusUpdate status) { GatewayIdentify data = new GatewayIdentify { Token = Utilities.GetFormattedToken(this), Compress = (base.Configuration.GatewayCompressionLevel == GatewayCompressionLevel.Payload), LargeThreshold = base.Configuration.LargeThreshold, ShardInfo = new ShardInfo { ShardId = base.Configuration.ShardId, ShardCount = base.Configuration.ShardCount }, Presence = status, Intents = base.Configuration.Intents }; string jsonPayload = JsonConvert.SerializeObject(new GatewayPayload { OpCode = GatewayOpCode.Identify, Data = data }); await SendRawPayloadAsync(jsonPayload).ConfigureAwait(continueOnCapturedContext: false); base.Logger.LogDebug(LoggerEvents.Intents, "Registered gateway intents ({Intents})", base.Configuration.Intents); } internal async Task SendResumeAsync() { GatewayResume data = new GatewayResume { Token = Utilities.GetFormattedToken(this), SessionId = _sessionId, SequenceNumber = Volatile.Read(ref _lastSequence) }; string jsonPayload = JsonConvert.SerializeObject(new GatewayPayload { OpCode = GatewayOpCode.Resume, Data = data }); await SendRawPayloadAsync(jsonPayload).ConfigureAwait(continueOnCapturedContext: false); } internal async Task InternalUpdateGatewayAsync() { GatewayInfo gatewayInfo2 = (GatewayInfo = await GetGatewayInfoAsync().ConfigureAwait(continueOnCapturedContext: false)); GatewayUri = new Uri(gatewayInfo2.Url); } internal async Task SendRawPayloadAsync(string jsonPayload) { base.Logger.LogTrace(LoggerEvents.GatewayWsTx, jsonPayload); await _webSocketClient.SendMessageAsync(jsonPayload).ConfigureAwait(continueOnCapturedContext: false); } [Obsolete("This method should not be used unless you know what you're doing. Instead, look towards the other explicitly implemented methods which come with client-side validation.")] public Task SendPayloadAsync(GatewayOpCode opCode, T data) { return SendPayloadAsync(opCode, (object?)data); } [Obsolete("This method should not be used unless you know what you're doing. Instead, look towards the other explicitly implemented methods which come with client-side validation.")] public Task SendPayloadAsync(GatewayOpCode opCode, object? data = null) { string jsonPayload = DiscordJson.SerializeObject(new GatewayPayload { OpCode = opCode, Data = data }); return SendRawPayloadAsync(jsonPayload); } private SocketLock GetSocketLock() { return _socketLocks.GetOrAdd(base.CurrentApplication.Id, (ulong appId) => new SocketLock(appId, GatewayInfo.SessionBucket.MaxConcurrency)); } } internal sealed class DiscordShardedClient { private ConcurrentDictionary _internalVoiceRegions; private readonly ConcurrentDictionary _shards = new ConcurrentDictionary(); private Lazy> _voiceRegionsLazy; private bool _isStarted; private readonly bool _manuallySharding; private readonly Lazy _versionString = new Lazy(delegate { Assembly assembly = typeof(DiscordShardedClient).GetTypeInfo().Assembly; AssemblyInformationalVersionAttribute customAttribute = assembly.GetCustomAttribute(); if (customAttribute != null) { return customAttribute.InformationalVersion; } Version version = assembly.GetName().Version; string text = version.ToString(3); if (version.Revision > 0) { text = $"{text}, CI build {version.Revision}"; } return text; }); private AsyncEvent _socketErrored; private AsyncEvent _socketOpened; private AsyncEvent _socketClosed; private AsyncEvent _ready; private AsyncEvent _resumed; private AsyncEvent _heartbeated; private AsyncEvent _zombied; private AsyncEvent _channelCreated; private AsyncEvent _channelUpdated; private AsyncEvent _channelDeleted; private AsyncEvent _dmChannelDeleted; private AsyncEvent _channelPinsUpdated; private AsyncEvent _guildCreated; private AsyncEvent _guildAvailable; private AsyncEvent _guildUpdated; private AsyncEvent _guildDeleted; private AsyncEvent _guildUnavailable; private AsyncEvent _guildDownloadCompleted; private AsyncEvent _guildEmojisUpdated; private AsyncEvent _guildStickersUpdated; private AsyncEvent _guildIntegrationsUpdated; private AsyncEvent _guildBanAdded; private AsyncEvent _guildBanRemoved; private AsyncEvent _guildMemberAdded; private AsyncEvent _guildMemberRemoved; private AsyncEvent _guildMemberUpdated; private AsyncEvent _guildMembersChunk; private AsyncEvent _guildRoleCreated; private AsyncEvent _guildRoleUpdated; private AsyncEvent _guildRoleDeleted; private AsyncEvent _inviteCreated; private AsyncEvent _inviteDeleted; private AsyncEvent _messageCreated; private AsyncEvent _messageUpdated; private AsyncEvent _messageDeleted; private AsyncEvent _messageBulkDeleted; private AsyncEvent _messageReactionAdded; private AsyncEvent _messageReactionRemoved; private AsyncEvent _messageReactionsCleared; private AsyncEvent _messageReactionRemovedEmoji; private AsyncEvent _presenceUpdated; private AsyncEvent _userSettingsUpdated; private AsyncEvent _userUpdated; private AsyncEvent _voiceStateUpdated; private AsyncEvent _voiceServerUpdated; private AsyncEvent _threadCreated; private AsyncEvent _threadUpdated; private AsyncEvent _threadDeleted; private AsyncEvent _threadListSynced; private AsyncEvent _threadMemberUpdated; private AsyncEvent _threadMembersUpdated; private AsyncEvent _applicationCommandCreated; private AsyncEvent _applicationCommandUpdated; private AsyncEvent _applicationCommandDeleted; private AsyncEvent _integrationCreated; private AsyncEvent _integrationUpdated; private AsyncEvent _integrationDeleted; private AsyncEvent _stageInstanceCreated; private AsyncEvent _stageInstanceUpdated; private AsyncEvent _stageInstanceDeleted; private AsyncEvent _interactionCreated; private AsyncEvent _componentInteractionCreated; private AsyncEvent _modalSubmitted; private AsyncEvent _contextMenuInteractionCreated; private AsyncEvent _typingStarted; private AsyncEvent _unknownEvent; private AsyncEvent _webhooksUpdated; private AsyncEvent _clientErrored; public ILogger Logger { get; } public IReadOnlyDictionary ShardClients { get; } public GatewayInfo GatewayInfo { get; private set; } public DiscordUser CurrentUser { get; private set; } public DiscordApplication CurrentApplication { get; private set; } public IReadOnlyDictionary VoiceRegions => _voiceRegionsLazy?.Value; private DiscordConfiguration Configuration { get; } public event AsyncEventHandler SocketErrored { add { _socketErrored.Register(value); } remove { _socketErrored.Unregister(value); } } public event AsyncEventHandler SocketOpened { add { _socketOpened.Register(value); } remove { _socketOpened.Unregister(value); } } public event AsyncEventHandler SocketClosed { add { _socketClosed.Register(value); } remove { _socketClosed.Unregister(value); } } public event AsyncEventHandler Ready { add { _ready.Register(value); } remove { _ready.Unregister(value); } } public event AsyncEventHandler Resumed { add { _resumed.Register(value); } remove { _resumed.Unregister(value); } } public event AsyncEventHandler Heartbeated { add { _heartbeated.Register(value); } remove { _heartbeated.Unregister(value); } } public event AsyncEventHandler Zombied { add { _zombied.Register(value); } remove { _zombied.Unregister(value); } } public event AsyncEventHandler ChannelCreated { add { _channelCreated.Register(value); } remove { _channelCreated.Unregister(value); } } public event AsyncEventHandler ChannelUpdated { add { _channelUpdated.Register(value); } remove { _channelUpdated.Unregister(value); } } public event AsyncEventHandler ChannelDeleted { add { _channelDeleted.Register(value); } remove { _channelDeleted.Unregister(value); } } public event AsyncEventHandler DmChannelDeleted { add { _dmChannelDeleted.Register(value); } remove { _dmChannelDeleted.Unregister(value); } } public event AsyncEventHandler ChannelPinsUpdated { add { _channelPinsUpdated.Register(value); } remove { _channelPinsUpdated.Unregister(value); } } public event AsyncEventHandler GuildCreated { add { _guildCreated.Register(value); } remove { _guildCreated.Unregister(value); } } public event AsyncEventHandler GuildAvailable { add { _guildAvailable.Register(value); } remove { _guildAvailable.Unregister(value); } } public event AsyncEventHandler GuildUpdated { add { _guildUpdated.Register(value); } remove { _guildUpdated.Unregister(value); } } public event AsyncEventHandler GuildDeleted { add { _guildDeleted.Register(value); } remove { _guildDeleted.Unregister(value); } } public event AsyncEventHandler GuildUnavailable { add { _guildUnavailable.Register(value); } remove { _guildUnavailable.Unregister(value); } } public event AsyncEventHandler GuildDownloadCompleted { add { _guildDownloadCompleted.Register(value); } remove { _guildDownloadCompleted.Unregister(value); } } public event AsyncEventHandler GuildEmojisUpdated { add { _guildEmojisUpdated.Register(value); } remove { _guildEmojisUpdated.Unregister(value); } } public event AsyncEventHandler GuildStickersUpdated { add { _guildStickersUpdated.Register(value); } remove { _guildStickersUpdated.Unregister(value); } } public event AsyncEventHandler GuildIntegrationsUpdated { add { _guildIntegrationsUpdated.Register(value); } remove { _guildIntegrationsUpdated.Unregister(value); } } public event AsyncEventHandler GuildBanAdded { add { _guildBanAdded.Register(value); } remove { _guildBanAdded.Unregister(value); } } public event AsyncEventHandler GuildBanRemoved { add { _guildBanRemoved.Register(value); } remove { _guildBanRemoved.Unregister(value); } } public event AsyncEventHandler GuildMemberAdded { add { _guildMemberAdded.Register(value); } remove { _guildMemberAdded.Unregister(value); } } public event AsyncEventHandler GuildMemberRemoved { add { _guildMemberRemoved.Register(value); } remove { _guildMemberRemoved.Unregister(value); } } public event AsyncEventHandler GuildMemberUpdated { add { _guildMemberUpdated.Register(value); } remove { _guildMemberUpdated.Unregister(value); } } public event AsyncEventHandler GuildMembersChunked { add { _guildMembersChunk.Register(value); } remove { _guildMembersChunk.Unregister(value); } } public event AsyncEventHandler GuildRoleCreated { add { _guildRoleCreated.Register(value); } remove { _guildRoleCreated.Unregister(value); } } public event AsyncEventHandler GuildRoleUpdated { add { _guildRoleUpdated.Register(value); } remove { _guildRoleUpdated.Unregister(value); } } public event AsyncEventHandler GuildRoleDeleted { add { _guildRoleDeleted.Register(value); } remove { _guildRoleDeleted.Unregister(value); } } public event AsyncEventHandler InviteCreated { add { _inviteCreated.Register(value); } remove { _inviteCreated.Unregister(value); } } public event AsyncEventHandler InviteDeleted { add { _inviteDeleted.Register(value); } remove { _inviteDeleted.Unregister(value); } } public event AsyncEventHandler MessageCreated { add { _messageCreated.Register(value); } remove { _messageCreated.Unregister(value); } } public event AsyncEventHandler MessageUpdated { add { _messageUpdated.Register(value); } remove { _messageUpdated.Unregister(value); } } public event AsyncEventHandler MessageDeleted { add { _messageDeleted.Register(value); } remove { _messageDeleted.Unregister(value); } } public event AsyncEventHandler MessagesBulkDeleted { add { _messageBulkDeleted.Register(value); } remove { _messageBulkDeleted.Unregister(value); } } public event AsyncEventHandler MessageReactionAdded { add { _messageReactionAdded.Register(value); } remove { _messageReactionAdded.Unregister(value); } } public event AsyncEventHandler MessageReactionRemoved { add { _messageReactionRemoved.Register(value); } remove { _messageReactionRemoved.Unregister(value); } } public event AsyncEventHandler MessageReactionsCleared { add { _messageReactionsCleared.Register(value); } remove { _messageReactionsCleared.Unregister(value); } } public event AsyncEventHandler MessageReactionRemovedEmoji { add { _messageReactionRemovedEmoji.Register(value); } remove { _messageReactionRemovedEmoji.Unregister(value); } } public event AsyncEventHandler PresenceUpdated { add { _presenceUpdated.Register(value); } remove { _presenceUpdated.Unregister(value); } } public event AsyncEventHandler UserSettingsUpdated { add { _userSettingsUpdated.Register(value); } remove { _userSettingsUpdated.Unregister(value); } } public event AsyncEventHandler UserUpdated { add { _userUpdated.Register(value); } remove { _userUpdated.Unregister(value); } } public event AsyncEventHandler VoiceStateUpdated { add { _voiceStateUpdated.Register(value); } remove { _voiceStateUpdated.Unregister(value); } } public event AsyncEventHandler VoiceServerUpdated { add { _voiceServerUpdated.Register(value); } remove { _voiceServerUpdated.Unregister(value); } } public event AsyncEventHandler ThreadCreated { add { _threadCreated.Register(value); } remove { _threadCreated.Unregister(value); } } public event AsyncEventHandler ThreadUpdated { add { _threadUpdated.Register(value); } remove { _threadUpdated.Unregister(value); } } public event AsyncEventHandler ThreadDeleted { add { _threadDeleted.Register(value); } remove { _threadDeleted.Unregister(value); } } public event AsyncEventHandler ThreadListSynced { add { _threadListSynced.Register(value); } remove { _threadListSynced.Unregister(value); } } public event AsyncEventHandler ThreadMemberUpdated { add { _threadMemberUpdated.Register(value); } remove { _threadMemberUpdated.Unregister(value); } } public event AsyncEventHandler ThreadMembersUpdated { add { _threadMembersUpdated.Register(value); } remove { _threadMembersUpdated.Unregister(value); } } [Obsolete("This event has been removed by discord and does not fire anymore.", false)] public event AsyncEventHandler ApplicationCommandCreated { add { _applicationCommandCreated.Register(value); } remove { _applicationCommandCreated.Unregister(value); } } [Obsolete("This event has been removed by discord and does not fire anymore.", false)] public event AsyncEventHandler ApplicationCommandUpdated { add { _applicationCommandUpdated.Register(value); } remove { _applicationCommandUpdated.Unregister(value); } } [Obsolete("This event has been removed by discord and does not fire anymore.", false)] public event AsyncEventHandler ApplicationCommandDeleted { add { _applicationCommandDeleted.Register(value); } remove { _applicationCommandDeleted.Unregister(value); } } public event AsyncEventHandler IntegrationCreated { add { _integrationCreated.Register(value); } remove { _integrationCreated.Unregister(value); } } public event AsyncEventHandler IntegrationUpdated { add { _integrationUpdated.Register(value); } remove { _integrationUpdated.Unregister(value); } } public event AsyncEventHandler IntegrationDeleted { add { _integrationDeleted.Register(value); } remove { _integrationDeleted.Unregister(value); } } public event AsyncEventHandler StageInstanceCreated { add { _stageInstanceCreated.Register(value); } remove { _stageInstanceCreated.Unregister(value); } } public event AsyncEventHandler StageInstanceUpdated { add { _stageInstanceUpdated.Register(value); } remove { _stageInstanceUpdated.Unregister(value); } } public event AsyncEventHandler StageInstanceDeleted { add { _stageInstanceDeleted.Register(value); } remove { _stageInstanceDeleted.Unregister(value); } } public event AsyncEventHandler InteractionCreated { add { _interactionCreated.Register(value); } remove { _interactionCreated.Unregister(value); } } public event AsyncEventHandler ComponentInteractionCreated { add { _componentInteractionCreated.Register(value); } remove { _componentInteractionCreated.Unregister(value); } } public event AsyncEventHandler ModalSubmitted { add { _modalSubmitted.Register(value); } remove { _modalSubmitted.Unregister(value); } } public event AsyncEventHandler ContextMenuInteractionCreated { add { _contextMenuInteractionCreated.Register(value); } remove { _contextMenuInteractionCreated.Unregister(value); } } public event AsyncEventHandler TypingStarted { add { _typingStarted.Register(value); } remove { _typingStarted.Unregister(value); } } public event AsyncEventHandler UnknownEvent { add { _unknownEvent.Register(value); } remove { _unknownEvent.Unregister(value); } } public event AsyncEventHandler WebhooksUpdated { add { _webhooksUpdated.Register(value); } remove { _webhooksUpdated.Unregister(value); } } public event AsyncEventHandler ClientErrored { add { _clientErrored.Register(value); } remove { _clientErrored.Unregister(value); } } public DiscordShardedClient(DiscordConfiguration config) { InternalSetup(); if (config.ShardCount > 1) { _manuallySharding = true; } Configuration = config; ShardClients = new ReadOnlyConcurrentDictionary(_shards); if (Configuration.LoggerFactory == null) { Configuration.LoggerFactory = new DefaultLoggerFactory(); Configuration.LoggerFactory.AddProvider(new DefaultLoggerProvider(Configuration.MinimumLogLevel, Configuration.LogTimestampFormat)); } Logger = Configuration.LoggerFactory.CreateLogger(); } public async Task StartAsync() { if (_isStarted) { throw new InvalidOperationException("This client has already been started."); } _isStarted = true; try { if (Configuration.TokenType != TokenType.Bot) { Logger.LogWarning(LoggerEvents.Misc, "You are logging in with a token that is not a bot token. This is not officially supported by Discord, and can result in your account being terminated if you aren't careful."); } Logger.LogInformation(LoggerEvents.Startup, "DSharpPlus, version {Version}", _versionString.Value); int shardc = await InitializeShardsAsync().ConfigureAwait(continueOnCapturedContext: false); List connectTasks = new List(); Logger.LogInformation(LoggerEvents.ShardStartup, "Booting {ShardCount} shards.", shardc); for (int i = 0; i < shardc; i++) { if (GatewayInfo.SessionBucket.MaxConcurrency < 1) { GatewayInfo.SessionBucket.MaxConcurrency = 1; } if (GatewayInfo.SessionBucket.MaxConcurrency == 1) { await ConnectShardAsync(i).ConfigureAwait(continueOnCapturedContext: false); continue; } connectTasks.Add(ConnectShardAsync(i)); if (connectTasks.Count == GatewayInfo.SessionBucket.MaxConcurrency) { await Task.WhenAll(connectTasks).ConfigureAwait(continueOnCapturedContext: false); connectTasks.Clear(); } } } catch (Exception ex) { await InternalStopAsync(enableLogger: false).ConfigureAwait(continueOnCapturedContext: false); string text = "Shard initialization failed, check inner exceptions for details: "; Logger.LogCritical(LoggerEvents.ShardClientError, $"{text}\n{ex}"); throw new AggregateException(text, ex); } } public Task StopAsync() { return InternalStopAsync(); } public DiscordClient GetShard(ulong guildId) { int num = (_manuallySharding ? GetShardIdFromGuilds(guildId) : Utilities.GetShardId(guildId, ShardClients.Count)); if (num == -1) { return null; } return _shards[num]; } public DiscordClient GetShard(DiscordGuild guild) { return GetShard(guild.Id); } public async Task UpdateStatusAsync(DiscordActivity activity = null, UserStatus? userStatus = null, DateTimeOffset? idleSince = null) { List list = new List(); foreach (DiscordClient value in _shards.Values) { list.Add(value.UpdateStatusAsync(activity, userStatus, idleSince)); } await Task.WhenAll(list).ConfigureAwait(continueOnCapturedContext: false); } public async Task InitializeShardsAsync() { if (_shards.Count != 0) { return _shards.Count; } GatewayInfo = await GetGatewayInfoAsync(); int num = ((Configuration.ShardCount == 1) ? GatewayInfo.ShardCount : Configuration.ShardCount); ShardedLoggerFactory shardedLoggerFactory = new ShardedLoggerFactory(Configuration.LoggerFactory); RestClient restClient = new RestClient(Configuration, shardedLoggerFactory.CreateLogger("Rest")); for (int i = 0; i < num; i++) { DiscordClient value = new DiscordClient(new DiscordConfiguration(Configuration) { ShardId = i, ShardCount = num, LoggerFactory = shardedLoggerFactory }, restClient); if (!_shards.TryAdd(i, value)) { throw new InvalidOperationException("Could not initialize shards."); } } return num; } private async Task GetGatewayInfoAsync() { string url = Utilities.GetApiBaseUri() + "/gateway/bot"; HttpClient http = new HttpClient(); http.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", Utilities.GetUserAgent()); http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", Utilities.GetFormattedToken(Configuration)); Logger.LogDebug(LoggerEvents.ShardRest, "Obtaining gateway information from GET /gateway/bot..."); HttpResponseMessage resp = await http.GetAsync(url).ConfigureAwait(continueOnCapturedContext: false); http.Dispose(); if (!resp.IsSuccessStatusCode && await HandleHttpError(url, resp).ConfigureAwait(continueOnCapturedContext: false)) { return await GetGatewayInfoAsync().ConfigureAwait(continueOnCapturedContext: false); } Stopwatch timer = new Stopwatch(); timer.Start(); GatewayInfo gatewayInfo = JObject.Parse(await resp.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false)).ToDiscordObject(); timer.Stop(); gatewayInfo.SessionBucket.ResetAfterInternal -= (int)timer.ElapsedMilliseconds; gatewayInfo.SessionBucket.ResetAfter = DateTimeOffset.UtcNow + TimeSpan.FromMilliseconds(gatewayInfo.SessionBucket.ResetAfterInternal); return gatewayInfo; async Task HandleHttpError(string reqUrl, HttpResponseMessage msg) { int statusCode = (int)msg.StatusCode; if (statusCode == 401 || statusCode == 403) { throw new Exception($"Authentication failed, check your token and try again: {statusCode} {msg.ReasonPhrase}"); } if (statusCode == 429) { Logger.LogError(LoggerEvents.ShardClientError, "Ratelimit hit, requeuing request to " + reqUrl); Dictionary dictionary = msg.Headers.ToDictionary>, string, string>((KeyValuePair> xh) => xh.Key, (KeyValuePair> xh) => string.Join("\n", xh.Value), StringComparer.OrdinalIgnoreCase); int millisecondsDelay = 0; if (dictionary.TryGetValue("Retry-After", out var value)) { millisecondsDelay = int.Parse(value, CultureInfo.InvariantCulture); } await Task.Delay(millisecondsDelay).ConfigureAwait(continueOnCapturedContext: false); return true; } if (statusCode >= 500) { throw new Exception($"Internal Server Error: {statusCode} {msg.ReasonPhrase}"); } throw new Exception($"An unsuccessful HTTP status code was encountered: {statusCode} {msg.ReasonPhrase}"); } } private async Task ConnectShardAsync(int i) { if (!_shards.TryGetValue(i, out var client)) { throw new Exception($"Could not initialize shard {i}."); } if (GatewayInfo != null) { client.GatewayInfo = GatewayInfo; client.GatewayUri = new Uri(client.GatewayInfo.Url); } if (CurrentUser != null) { client.CurrentUser = CurrentUser; } if (CurrentApplication != null) { client.CurrentApplication = CurrentApplication; } if (_internalVoiceRegions != null) { client.InternalVoiceRegions = _internalVoiceRegions; client._voice_regions_lazy = new Lazy>(() => new ReadOnlyDictionary(client.InternalVoiceRegions)); } HookEventHandlers(client); client._isShard = true; await client.ConnectAsync().ConfigureAwait(continueOnCapturedContext: false); Logger.LogInformation(LoggerEvents.ShardStartup, "Booted shard {Shard}.", i); if (CurrentUser == null) { CurrentUser = client.CurrentUser; } if (CurrentApplication == null) { CurrentApplication = client.CurrentApplication; } if (_internalVoiceRegions == null) { _internalVoiceRegions = client.InternalVoiceRegions; _voiceRegionsLazy = new Lazy>(() => new ReadOnlyDictionary(_internalVoiceRegions)); } } private Task InternalStopAsync(bool enableLogger = true) { if (!_isStarted) { throw new InvalidOperationException("This client has not been started."); } _isStarted = false; if (enableLogger) { Logger.LogInformation(LoggerEvents.ShardShutdown, "Disposing {ShardCount} shards.", _shards.Count); } _voiceRegionsLazy = null; GatewayInfo = null; CurrentUser = null; CurrentApplication = null; for (int i = 0; i < _shards.Count; i++) { if (_shards.TryGetValue(i, out var value)) { UnhookEventHandlers(value); value.Dispose(); if (enableLogger) { Logger.LogInformation(LoggerEvents.ShardShutdown, "Disconnected shard {Shard}.", i); } } } _shards.Clear(); return Task.CompletedTask; } private void InternalSetup() { _clientErrored = new AsyncEvent("CLIENT_ERRORED", Goof); _socketErrored = new AsyncEvent("SOCKET_ERRORED", Goof); _socketOpened = new AsyncEvent("SOCKET_OPENED", EventErrorHandler); _socketClosed = new AsyncEvent("SOCKET_CLOSED", EventErrorHandler); _ready = new AsyncEvent("READY", EventErrorHandler); _resumed = new AsyncEvent("RESUMED", EventErrorHandler); _channelCreated = new AsyncEvent("CHANNEL_CREATED", EventErrorHandler); _channelUpdated = new AsyncEvent("CHANNEL_UPDATED", EventErrorHandler); _channelDeleted = new AsyncEvent("CHANNEL_DELETED", EventErrorHandler); _dmChannelDeleted = new AsyncEvent("DM_CHANNEL_DELETED", EventErrorHandler); _channelPinsUpdated = new AsyncEvent("CHANNEL_PINS_UPDATED", EventErrorHandler); _guildCreated = new AsyncEvent("GUILD_CREATED", EventErrorHandler); _guildAvailable = new AsyncEvent("GUILD_AVAILABLE", EventErrorHandler); _guildUpdated = new AsyncEvent("GUILD_UPDATED", EventErrorHandler); _guildDeleted = new AsyncEvent("GUILD_DELETED", EventErrorHandler); _guildUnavailable = new AsyncEvent("GUILD_UNAVAILABLE", EventErrorHandler); _guildDownloadCompleted = new AsyncEvent("GUILD_DOWNLOAD_COMPLETED", EventErrorHandler); _inviteCreated = new AsyncEvent("INVITE_CREATED", EventErrorHandler); _inviteDeleted = new AsyncEvent("INVITE_DELETED", EventErrorHandler); _messageCreated = new AsyncEvent("MESSAGE_CREATED", EventErrorHandler); _presenceUpdated = new AsyncEvent("PRESENCE_UPDATED", EventErrorHandler); _guildBanAdded = new AsyncEvent("GUILD_BAN_ADDED", EventErrorHandler); _guildBanRemoved = new AsyncEvent("GUILD_BAN_REMOVED", EventErrorHandler); _guildEmojisUpdated = new AsyncEvent("GUILD_EMOJI_UPDATED", EventErrorHandler); _guildStickersUpdated = new AsyncEvent("GUILD_STICKER_UPDATED", EventErrorHandler); _guildIntegrationsUpdated = new AsyncEvent("GUILD_INTEGRATIONS_UPDATED", EventErrorHandler); _guildMemberAdded = new AsyncEvent("GUILD_MEMBER_ADDED", EventErrorHandler); _guildMemberRemoved = new AsyncEvent("GUILD_MEMBER_REMOVED", EventErrorHandler); _guildMemberUpdated = new AsyncEvent("GUILD_MEMBER_UPDATED", EventErrorHandler); _guildRoleCreated = new AsyncEvent("GUILD_ROLE_CREATED", EventErrorHandler); _guildRoleUpdated = new AsyncEvent("GUILD_ROLE_UPDATED", EventErrorHandler); _guildRoleDeleted = new AsyncEvent("GUILD_ROLE_DELETED", EventErrorHandler); _messageUpdated = new AsyncEvent("MESSAGE_UPDATED", EventErrorHandler); _messageDeleted = new AsyncEvent("MESSAGE_DELETED", EventErrorHandler); _messageBulkDeleted = new AsyncEvent("MESSAGE_BULK_DELETED", EventErrorHandler); _interactionCreated = new AsyncEvent("INTERACTION_CREATED", EventErrorHandler); _componentInteractionCreated = new AsyncEvent("COMPONENT_INTERACTED", EventErrorHandler); _modalSubmitted = new AsyncEvent("MODAL_SUBMITTED", EventErrorHandler); _contextMenuInteractionCreated = new AsyncEvent("CONTEXT_MENU_INTERACTED", EventErrorHandler); _typingStarted = new AsyncEvent("TYPING_STARTED", EventErrorHandler); _userSettingsUpdated = new AsyncEvent("USER_SETTINGS_UPDATED", EventErrorHandler); _userUpdated = new AsyncEvent("USER_UPDATED", EventErrorHandler); _voiceStateUpdated = new AsyncEvent("VOICE_STATE_UPDATED", EventErrorHandler); _voiceServerUpdated = new AsyncEvent("VOICE_SERVER_UPDATED", EventErrorHandler); _guildMembersChunk = new AsyncEvent("GUILD_MEMBERS_CHUNKED", EventErrorHandler); _unknownEvent = new AsyncEvent("UNKNOWN_EVENT", EventErrorHandler); _messageReactionAdded = new AsyncEvent("MESSAGE_REACTION_ADDED", EventErrorHandler); _messageReactionRemoved = new AsyncEvent("MESSAGE_REACTION_REMOVED", EventErrorHandler); _messageReactionsCleared = new AsyncEvent("MESSAGE_REACTIONS_CLEARED", EventErrorHandler); _messageReactionRemovedEmoji = new AsyncEvent("MESSAGE_REACTION_REMOVED_EMOJI", EventErrorHandler); _webhooksUpdated = new AsyncEvent("WEBHOOKS_UPDATED", EventErrorHandler); _heartbeated = new AsyncEvent("HEARTBEATED", EventErrorHandler); _zombied = new AsyncEvent("ZOMBIED", EventErrorHandler); _applicationCommandCreated = new AsyncEvent("APPLICATION_COMMAND_CREATED", EventErrorHandler); _applicationCommandUpdated = new AsyncEvent("APPLICATION_COMMAND_UPDATED", EventErrorHandler); _applicationCommandDeleted = new AsyncEvent("APPLICATION_COMMAND_DELETED", EventErrorHandler); _integrationCreated = new AsyncEvent("INTEGRATION_CREATED", EventErrorHandler); _integrationUpdated = new AsyncEvent("INTEGRATION_UPDATED", EventErrorHandler); _integrationDeleted = new AsyncEvent("INTEGRATION_DELETED", EventErrorHandler); _stageInstanceCreated = new AsyncEvent("STAGE_INSTANCE_CREATED", EventErrorHandler); _stageInstanceUpdated = new AsyncEvent("STAGE_INSTANCE_UPDATED", EventErrorHandler); _stageInstanceDeleted = new AsyncEvent("STAGE_INSTANCE_DELETED", EventErrorHandler); _threadCreated = new AsyncEvent("THREAD_CREATED", EventErrorHandler); _threadUpdated = new AsyncEvent("THREAD_UPDATED", EventErrorHandler); _threadDeleted = new AsyncEvent("THREAD_DELETED", EventErrorHandler); _threadListSynced = new AsyncEvent("THREAD_LIST_SYNCED", EventErrorHandler); _threadMemberUpdated = new AsyncEvent("THREAD_MEMBER_UPDATED", EventErrorHandler); _threadMembersUpdated = new AsyncEvent("THREAD_MEMBERS_UPDATED", EventErrorHandler); } private void HookEventHandlers(DiscordClient client) { client.ClientErrored += Client_ClientError; client.SocketErrored += Client_SocketError; client.SocketOpened += Client_SocketOpened; client.SocketClosed += Client_SocketClosed; client.Ready += Client_Ready; client.Resumed += Client_Resumed; client.ChannelCreated += Client_ChannelCreated; client.ChannelUpdated += Client_ChannelUpdated; client.ChannelDeleted += Client_ChannelDeleted; client.DmChannelDeleted += Client_DMChannelDeleted; client.ChannelPinsUpdated += Client_ChannelPinsUpdated; client.GuildCreated += Client_GuildCreated; client.GuildAvailable += Client_GuildAvailable; client.GuildUpdated += Client_GuildUpdated; client.GuildDeleted += Client_GuildDeleted; client.GuildUnavailable += Client_GuildUnavailable; client.GuildDownloadCompleted += Client_GuildDownloadCompleted; client.InviteCreated += Client_InviteCreated; client.InviteDeleted += Client_InviteDeleted; client.MessageCreated += Client_MessageCreated; client.PresenceUpdated += Client_PresenceUpdate; client.GuildBanAdded += Client_GuildBanAdd; client.GuildBanRemoved += Client_GuildBanRemove; client.GuildEmojisUpdated += Client_GuildEmojisUpdate; client.GuildStickersUpdated += Client_GuildStickersUpdate; client.GuildIntegrationsUpdated += Client_GuildIntegrationsUpdate; client.GuildMemberAdded += Client_GuildMemberAdd; client.GuildMemberRemoved += Client_GuildMemberRemove; client.GuildMemberUpdated += Client_GuildMemberUpdate; client.GuildRoleCreated += Client_GuildRoleCreate; client.GuildRoleUpdated += Client_GuildRoleUpdate; client.GuildRoleDeleted += Client_GuildRoleDelete; client.MessageUpdated += Client_MessageUpdate; client.MessageDeleted += Client_MessageDelete; client.MessagesBulkDeleted += Client_MessageBulkDelete; client.InteractionCreated += Client_InteractionCreate; client.ComponentInteractionCreated += Client_ComponentInteractionCreate; client.ModalSubmitted += Client_ModalSubmitted; client.ContextMenuInteractionCreated += Client_ContextMenuInteractionCreate; client.TypingStarted += Client_TypingStart; client.UserSettingsUpdated += Client_UserSettingsUpdate; client.UserUpdated += Client_UserUpdate; client.VoiceStateUpdated += Client_VoiceStateUpdate; client.VoiceServerUpdated += Client_VoiceServerUpdate; client.GuildMembersChunked += Client_GuildMembersChunk; client.UnknownEvent += Client_UnknownEvent; client.MessageReactionAdded += Client_MessageReactionAdd; client.MessageReactionRemoved += Client_MessageReactionRemove; client.MessageReactionsCleared += Client_MessageReactionRemoveAll; client.MessageReactionRemovedEmoji += Client_MessageReactionRemovedEmoji; client.WebhooksUpdated += Client_WebhooksUpdate; client.Heartbeated += Client_HeartBeated; client.Zombied += Client_Zombied; client.IntegrationCreated += Client_IntegrationCreated; client.IntegrationUpdated += Client_IntegrationUpdated; client.IntegrationDeleted += Client_IntegrationDeleted; client.StageInstanceCreated += Client_StageInstanceCreated; client.StageInstanceUpdated += Client_StageInstanceUpdated; client.StageInstanceDeleted += Client_StageInstanceDeleted; client.ThreadCreated += Client_ThreadCreated; client.ThreadUpdated += Client_ThreadUpdated; client.ThreadDeleted += Client_ThreadDeleted; client.ThreadListSynced += Client_ThreadListSynced; client.ThreadMemberUpdated += Client_ThreadMemberUpdated; client.ThreadMembersUpdated += Client_ThreadMembersUpdated; } private void UnhookEventHandlers(DiscordClient client) { client.ClientErrored -= Client_ClientError; client.SocketErrored -= Client_SocketError; client.SocketOpened -= Client_SocketOpened; client.SocketClosed -= Client_SocketClosed; client.Ready -= Client_Ready; client.Resumed -= Client_Resumed; client.ChannelCreated -= Client_ChannelCreated; client.ChannelUpdated -= Client_ChannelUpdated; client.ChannelDeleted -= Client_ChannelDeleted; client.DmChannelDeleted -= Client_DMChannelDeleted; client.ChannelPinsUpdated -= Client_ChannelPinsUpdated; client.GuildCreated -= Client_GuildCreated; client.GuildAvailable -= Client_GuildAvailable; client.GuildUpdated -= Client_GuildUpdated; client.GuildDeleted -= Client_GuildDeleted; client.GuildUnavailable -= Client_GuildUnavailable; client.GuildDownloadCompleted -= Client_GuildDownloadCompleted; client.InviteCreated -= Client_InviteCreated; client.InviteDeleted -= Client_InviteDeleted; client.MessageCreated -= Client_MessageCreated; client.PresenceUpdated -= Client_PresenceUpdate; client.GuildBanAdded -= Client_GuildBanAdd; client.GuildBanRemoved -= Client_GuildBanRemove; client.GuildEmojisUpdated -= Client_GuildEmojisUpdate; client.GuildStickersUpdated -= Client_GuildStickersUpdate; client.GuildIntegrationsUpdated -= Client_GuildIntegrationsUpdate; client.GuildMemberAdded -= Client_GuildMemberAdd; client.GuildMemberRemoved -= Client_GuildMemberRemove; client.GuildMemberUpdated -= Client_GuildMemberUpdate; client.GuildRoleCreated -= Client_GuildRoleCreate; client.GuildRoleUpdated -= Client_GuildRoleUpdate; client.GuildRoleDeleted -= Client_GuildRoleDelete; client.MessageUpdated -= Client_MessageUpdate; client.MessageDeleted -= Client_MessageDelete; client.MessagesBulkDeleted -= Client_MessageBulkDelete; client.InteractionCreated -= Client_InteractionCreate; client.ComponentInteractionCreated -= Client_ComponentInteractionCreate; client.ModalSubmitted -= Client_ModalSubmitted; client.ContextMenuInteractionCreated -= Client_ContextMenuInteractionCreate; client.TypingStarted -= Client_TypingStart; client.UserSettingsUpdated -= Client_UserSettingsUpdate; client.UserUpdated -= Client_UserUpdate; client.VoiceStateUpdated -= Client_VoiceStateUpdate; client.VoiceServerUpdated -= Client_VoiceServerUpdate; client.GuildMembersChunked -= Client_GuildMembersChunk; client.UnknownEvent -= Client_UnknownEvent; client.MessageReactionAdded -= Client_MessageReactionAdd; client.MessageReactionRemoved -= Client_MessageReactionRemove; client.MessageReactionsCleared -= Client_MessageReactionRemoveAll; client.MessageReactionRemovedEmoji -= Client_MessageReactionRemovedEmoji; client.WebhooksUpdated -= Client_WebhooksUpdate; client.Heartbeated -= Client_HeartBeated; client.Zombied -= Client_Zombied; client.IntegrationCreated -= Client_IntegrationCreated; client.IntegrationUpdated -= Client_IntegrationUpdated; client.IntegrationDeleted -= Client_IntegrationDeleted; client.StageInstanceCreated -= Client_StageInstanceCreated; client.StageInstanceUpdated -= Client_StageInstanceUpdated; client.StageInstanceDeleted -= Client_StageInstanceDeleted; client.ThreadCreated -= Client_ThreadCreated; client.ThreadUpdated -= Client_ThreadUpdated; client.ThreadDeleted -= Client_ThreadDeleted; client.ThreadListSynced -= Client_ThreadListSynced; client.ThreadMemberUpdated -= Client_ThreadMemberUpdated; client.ThreadMembersUpdated -= Client_ThreadMembersUpdated; } private int GetShardIdFromGuilds(ulong id) { foreach (DiscordClient value2 in _shards.Values) { if (value2._guilds.TryGetValue(id, out var _)) { return value2.ShardId; } } return -1; } ~DiscordShardedClient() { if (_isStarted) { InternalStopAsync(enableLogger: false).GetAwaiter().GetResult(); } } internal void EventErrorHandler(AsyncEvent asyncEvent, Exception ex, AsyncEventHandler handler, DiscordClient sender, TArgs eventArgs) where TArgs : AsyncEventArgs { Logger.LogError(LoggerEvents.EventHandlerException, ex, "Event handler exception for event {Event} thrown from {Method} (defined in {DeclaringType})", asyncEvent.Name, handler.Method, handler.Method.DeclaringType); _clientErrored.InvokeAsync(sender, new ClientErrorEventArgs { EventName = asyncEvent.Name, Exception = ex }).ConfigureAwait(continueOnCapturedContext: false).GetAwaiter() .GetResult(); } private void Goof(AsyncEvent asyncEvent, Exception ex, AsyncEventHandler handler, DiscordClient sender, TArgs eventArgs) where TArgs : AsyncEventArgs { Logger.LogCritical(LoggerEvents.EventHandlerException, ex, "Exception event handler {Method} (defined in {DeclaringType}) threw an exception", handler.Method, handler.Method.DeclaringType); } private Task Client_ClientError(DiscordClient client, ClientErrorEventArgs e) { return _clientErrored.InvokeAsync(client, e); } private Task Client_SocketError(DiscordClient client, SocketErrorEventArgs e) { return _socketErrored.InvokeAsync(client, e); } private Task Client_SocketOpened(DiscordClient client, SocketEventArgs e) { return _socketOpened.InvokeAsync(client, e); } private Task Client_SocketClosed(DiscordClient client, SocketCloseEventArgs e) { return _socketClosed.InvokeAsync(client, e); } private Task Client_Ready(DiscordClient client, ReadyEventArgs e) { return _ready.InvokeAsync(client, e); } private Task Client_Resumed(DiscordClient client, ReadyEventArgs e) { return _resumed.InvokeAsync(client, e); } private Task Client_ChannelCreated(DiscordClient client, ChannelCreateEventArgs e) { return _channelCreated.InvokeAsync(client, e); } private Task Client_ChannelUpdated(DiscordClient client, ChannelUpdateEventArgs e) { return _channelUpdated.InvokeAsync(client, e); } private Task Client_ChannelDeleted(DiscordClient client, ChannelDeleteEventArgs e) { return _channelDeleted.InvokeAsync(client, e); } private Task Client_DMChannelDeleted(DiscordClient client, DmChannelDeleteEventArgs e) { return _dmChannelDeleted.InvokeAsync(client, e); } private Task Client_ChannelPinsUpdated(DiscordClient client, ChannelPinsUpdateEventArgs e) { return _channelPinsUpdated.InvokeAsync(client, e); } private Task Client_GuildCreated(DiscordClient client, GuildCreateEventArgs e) { return _guildCreated.InvokeAsync(client, e); } private Task Client_GuildAvailable(DiscordClient client, GuildCreateEventArgs e) { return _guildAvailable.InvokeAsync(client, e); } private Task Client_GuildUpdated(DiscordClient client, GuildUpdateEventArgs e) { return _guildUpdated.InvokeAsync(client, e); } private Task Client_GuildDeleted(DiscordClient client, GuildDeleteEventArgs e) { return _guildDeleted.InvokeAsync(client, e); } private Task Client_GuildUnavailable(DiscordClient client, GuildDeleteEventArgs e) { return _guildUnavailable.InvokeAsync(client, e); } private Task Client_GuildDownloadCompleted(DiscordClient client, GuildDownloadCompletedEventArgs e) { return _guildDownloadCompleted.InvokeAsync(client, e); } private Task Client_MessageCreated(DiscordClient client, MessageCreateEventArgs e) { return _messageCreated.InvokeAsync(client, e); } private Task Client_InviteCreated(DiscordClient client, InviteCreateEventArgs e) { return _inviteCreated.InvokeAsync(client, e); } private Task Client_InviteDeleted(DiscordClient client, InviteDeleteEventArgs e) { return _inviteDeleted.InvokeAsync(client, e); } private Task Client_PresenceUpdate(DiscordClient client, PresenceUpdateEventArgs e) { return _presenceUpdated.InvokeAsync(client, e); } private Task Client_GuildBanAdd(DiscordClient client, GuildBanAddEventArgs e) { return _guildBanAdded.InvokeAsync(client, e); } private Task Client_GuildBanRemove(DiscordClient client, GuildBanRemoveEventArgs e) { return _guildBanRemoved.InvokeAsync(client, e); } private Task Client_GuildEmojisUpdate(DiscordClient client, GuildEmojisUpdateEventArgs e) { return _guildEmojisUpdated.InvokeAsync(client, e); } private Task Client_GuildStickersUpdate(DiscordClient client, GuildStickersUpdateEventArgs e) { return _guildStickersUpdated.InvokeAsync(client, e); } private Task Client_GuildIntegrationsUpdate(DiscordClient client, GuildIntegrationsUpdateEventArgs e) { return _guildIntegrationsUpdated.InvokeAsync(client, e); } private Task Client_GuildMemberAdd(DiscordClient client, GuildMemberAddEventArgs e) { return _guildMemberAdded.InvokeAsync(client, e); } private Task Client_GuildMemberRemove(DiscordClient client, GuildMemberRemoveEventArgs e) { return _guildMemberRemoved.InvokeAsync(client, e); } private Task Client_GuildMemberUpdate(DiscordClient client, GuildMemberUpdateEventArgs e) { return _guildMemberUpdated.InvokeAsync(client, e); } private Task Client_GuildRoleCreate(DiscordClient client, GuildRoleCreateEventArgs e) { return _guildRoleCreated.InvokeAsync(client, e); } private Task Client_GuildRoleUpdate(DiscordClient client, GuildRoleUpdateEventArgs e) { return _guildRoleUpdated.InvokeAsync(client, e); } private Task Client_GuildRoleDelete(DiscordClient client, GuildRoleDeleteEventArgs e) { return _guildRoleDeleted.InvokeAsync(client, e); } private Task Client_MessageUpdate(DiscordClient client, MessageUpdateEventArgs e) { return _messageUpdated.InvokeAsync(client, e); } private Task Client_MessageDelete(DiscordClient client, MessageDeleteEventArgs e) { return _messageDeleted.InvokeAsync(client, e); } private Task Client_MessageBulkDelete(DiscordClient client, MessageBulkDeleteEventArgs e) { return _messageBulkDeleted.InvokeAsync(client, e); } private Task Client_TypingStart(DiscordClient client, TypingStartEventArgs e) { return _typingStarted.InvokeAsync(client, e); } private Task Client_UserSettingsUpdate(DiscordClient client, UserSettingsUpdateEventArgs e) { return _userSettingsUpdated.InvokeAsync(client, e); } private Task Client_UserUpdate(DiscordClient client, UserUpdateEventArgs e) { return _userUpdated.InvokeAsync(client, e); } private Task Client_VoiceStateUpdate(DiscordClient client, VoiceStateUpdateEventArgs e) { return _voiceStateUpdated.InvokeAsync(client, e); } private Task Client_VoiceServerUpdate(DiscordClient client, VoiceServerUpdateEventArgs e) { return _voiceServerUpdated.InvokeAsync(client, e); } private Task Client_GuildMembersChunk(DiscordClient client, GuildMembersChunkEventArgs e) { return _guildMembersChunk.InvokeAsync(client, e); } private Task Client_UnknownEvent(DiscordClient client, UnknownEventArgs e) { return _unknownEvent.InvokeAsync(client, e); } private Task Client_MessageReactionAdd(DiscordClient client, MessageReactionAddEventArgs e) { return _messageReactionAdded.InvokeAsync(client, e); } private Task Client_MessageReactionRemove(DiscordClient client, MessageReactionRemoveEventArgs e) { return _messageReactionRemoved.InvokeAsync(client, e); } private Task Client_MessageReactionRemoveAll(DiscordClient client, MessageReactionsClearEventArgs e) { return _messageReactionsCleared.InvokeAsync(client, e); } private Task Client_MessageReactionRemovedEmoji(DiscordClient client, MessageReactionRemoveEmojiEventArgs e) { return _messageReactionRemovedEmoji.InvokeAsync(client, e); } private Task Client_InteractionCreate(DiscordClient client, InteractionCreateEventArgs e) { return _interactionCreated.InvokeAsync(client, e); } private Task Client_ComponentInteractionCreate(DiscordClient client, ComponentInteractionCreateEventArgs e) { return _componentInteractionCreated.InvokeAsync(client, e); } private Task Client_ModalSubmitted(DiscordClient client, ModalSubmitEventArgs e) { return _modalSubmitted.InvokeAsync(client, e); } private Task Client_ContextMenuInteractionCreate(DiscordClient client, ContextMenuInteractionCreateEventArgs e) { return _contextMenuInteractionCreated.InvokeAsync(client, e); } private Task Client_WebhooksUpdate(DiscordClient client, WebhooksUpdateEventArgs e) { return _webhooksUpdated.InvokeAsync(client, e); } private Task Client_HeartBeated(DiscordClient client, HeartbeatEventArgs e) { return _heartbeated.InvokeAsync(client, e); } private Task Client_Zombied(DiscordClient client, ZombiedEventArgs e) { return _zombied.InvokeAsync(client, e); } private Task Client_IntegrationCreated(DiscordClient client, IntegrationCreateEventArgs e) { return _integrationCreated.InvokeAsync(client, e); } private Task Client_IntegrationUpdated(DiscordClient client, IntegrationUpdateEventArgs e) { return _integrationUpdated.InvokeAsync(client, e); } private Task Client_IntegrationDeleted(DiscordClient client, IntegrationDeleteEventArgs e) { return _integrationDeleted.InvokeAsync(client, e); } private Task Client_StageInstanceCreated(DiscordClient client, StageInstanceCreateEventArgs e) { return _stageInstanceCreated.InvokeAsync(client, e); } private Task Client_StageInstanceUpdated(DiscordClient client, StageInstanceUpdateEventArgs e) { return _stageInstanceUpdated.InvokeAsync(client, e); } private Task Client_StageInstanceDeleted(DiscordClient client, StageInstanceDeleteEventArgs e) { return _stageInstanceDeleted.InvokeAsync(client, e); } private Task Client_ThreadCreated(DiscordClient client, ThreadCreateEventArgs e) { return _threadCreated.InvokeAsync(client, e); } private Task Client_ThreadUpdated(DiscordClient client, ThreadUpdateEventArgs e) { return _threadUpdated.InvokeAsync(client, e); } private Task Client_ThreadDeleted(DiscordClient client, ThreadDeleteEventArgs e) { return _threadDeleted.InvokeAsync(client, e); } private Task Client_ThreadListSynced(DiscordClient client, ThreadListSyncEventArgs e) { return _threadListSynced.InvokeAsync(client, e); } private Task Client_ThreadMemberUpdated(DiscordClient client, ThreadMemberUpdateEventArgs e) { return _threadMemberUpdated.InvokeAsync(client, e); } private Task Client_ThreadMembersUpdated(DiscordClient client, ThreadMembersUpdateEventArgs e) { return _threadMembersUpdated.InvokeAsync(client, e); } } internal class DiscordWebhookClient { internal List _hooks; internal DiscordApiClient _apiclient; internal LogLevel _minimumLogLevel; internal string _logTimestampFormat; public ILogger Logger { get; } private static Regex WebhookRegex { get; } = new Regex("(?:https?:\\/\\/)?discord(?:app)?.com\\/api\\/(?:v\\d\\/)?webhooks\\/(?\\d+)\\/(?[A-Za-z0-9_\\-]+)", RegexOptions.ECMAScript); public IReadOnlyList Webhooks { get; } public string Username { get; set; } public string AvatarUrl { get; set; } public DiscordWebhookClient() : this(null, null, useRelativeRateLimit: true, null, LogLevel.Information, "yyyy-MM-dd HH:mm:ss zzz") { } public DiscordWebhookClient(IWebProxy proxy = null, TimeSpan? timeout = null, bool useRelativeRateLimit = true, ILoggerFactory loggerFactory = null, LogLevel minimumLogLevel = LogLevel.Information, string logTimestampFormat = "yyyy-MM-dd HH:mm:ss zzz") { _minimumLogLevel = minimumLogLevel; _logTimestampFormat = logTimestampFormat; if (loggerFactory == null) { loggerFactory = new DefaultLoggerFactory(); loggerFactory.AddProvider(new DefaultLoggerProvider(this)); } Logger = loggerFactory.CreateLogger(); _apiclient = new DiscordApiClient(proxy, timeout ?? TimeSpan.FromSeconds(10.0), useRelativeRateLimit, Logger); _hooks = new List(); Webhooks = new ReadOnlyCollection(_hooks); } public async Task AddWebhookAsync(ulong id, string token) { if (string.IsNullOrWhiteSpace(token)) { throw new ArgumentNullException("token"); } token = token.Trim(); if (_hooks.Any((DiscordWebhook x) => x.Id == id)) { throw new InvalidOperationException("This webhook is registered with this client."); } DiscordWebhook discordWebhook = await _apiclient.GetWebhookWithTokenAsync(id, token).ConfigureAwait(continueOnCapturedContext: false); _hooks.Add(discordWebhook); return discordWebhook; } public Task AddWebhookAsync(Uri url) { if (url == null) { throw new ArgumentNullException("url"); } Match match = WebhookRegex.Match(url.ToString()); if (!match.Success) { throw new ArgumentException("Invalid webhook URL supplied.", "url"); } Group group = match.Groups["id"]; Group group2 = match.Groups["token"]; if (!ulong.TryParse(group.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { throw new ArgumentException("Invalid webhook URL supplied.", "url"); } string value = group2.Value; return AddWebhookAsync(result, value); } public async Task AddWebhookAsync(ulong id, BaseDiscordClient client) { if (client == null) { throw new ArgumentNullException("client"); } if (_hooks.Any((DiscordWebhook x) => x.Id == id)) { throw new ArgumentException("This webhook is already registered with this client."); } DiscordWebhook discordWebhook = await client.ApiClient.GetWebhookAsync(id).ConfigureAwait(continueOnCapturedContext: false); _hooks.Add(discordWebhook); return discordWebhook; } public DiscordWebhook AddWebhook(DiscordWebhook webhook) { if (webhook == null) { throw new ArgumentNullException("webhook"); } if (_hooks.Any((DiscordWebhook x) => x.Id == webhook.Id)) { throw new ArgumentException("This webhook is already registered with this client."); } _hooks.Add(webhook); return webhook; } public DiscordWebhook RemoveWebhook(ulong id) { if (!_hooks.Any((DiscordWebhook x) => x.Id == id)) { throw new ArgumentException("This webhook is not registered with this client."); } DiscordWebhook registeredWebhook = GetRegisteredWebhook(id); _hooks.Remove(registeredWebhook); return registeredWebhook; } public DiscordWebhook GetRegisteredWebhook(ulong id) { return _hooks.FirstOrDefault((DiscordWebhook xw) => xw.Id == id); } public async Task> BroadcastMessageAsync(DiscordWebhookBuilder builder) { List deadhooks = new List(); Dictionary messages = new Dictionary(); foreach (DiscordWebhook hook in _hooks) { try { Dictionary dictionary = messages; DiscordWebhook key = hook; dictionary.Add(key, await hook.ExecuteAsync(builder).ConfigureAwait(continueOnCapturedContext: false)); } catch (NotFoundException) { deadhooks.Add(hook); } } foreach (DiscordWebhook item in deadhooks) { _hooks.Remove(item); } return messages; } ~DiscordWebhookClient() { _hooks?.Clear(); _hooks = null; _apiclient._rest.Dispose(); } } internal sealed class DiscordConfiguration { private string _token = ""; private WebSocketClientFactoryDelegate _webSocketClientFactory = WebSocketClient.CreateNew; private UdpClientFactoryDelegate _udpClientFactory = DspUdpClient.CreateNew; public string Token { internal get { return _token; } set { if (string.IsNullOrWhiteSpace(value)) { throw new ArgumentNullException("value", "Token cannot be null, empty, or all whitespace."); } _token = value.Trim(); } } public TokenType TokenType { internal get; set; } = TokenType.Bot; public LogLevel MinimumLogLevel { internal get; set; } = LogLevel.Information; public bool UseRelativeRatelimit { internal get; set; } = true; public string LogTimestampFormat { internal get; set; } = "yyyy-MM-dd HH:mm:ss zzz"; public int LargeThreshold { internal get; set; } = 250; public bool AutoReconnect { internal get; set; } = true; public int ShardId { internal get; set; } public int ShardCount { internal get; set; } = 1; public GatewayCompressionLevel GatewayCompressionLevel { internal get; set; } = GatewayCompressionLevel.Stream; public int MessageCacheSize { internal get; set; } = 1024; public IWebProxy Proxy { internal get; set; } public TimeSpan HttpTimeout { internal get; set; } = TimeSpan.FromSeconds(100.0); public bool ReconnectIndefinitely { internal get; set; } public bool AlwaysCacheMembers { internal get; set; } = true; public DiscordIntents Intents { internal get; set; } = DiscordIntents.AllUnprivileged; public WebSocketClientFactoryDelegate WebSocketClientFactory { internal get { return _webSocketClientFactory; } set { if (value == null) { throw new InvalidOperationException("You need to supply a valid WebSocket client factory method."); } _webSocketClientFactory = value; } } public UdpClientFactoryDelegate UdpClientFactory { internal get { return _udpClientFactory; } set { _udpClientFactory = value ?? throw new InvalidOperationException("You need to supply a valid UDP client factory method."); } } public ILoggerFactory LoggerFactory { internal get; set; } public bool LogUnknownEvents { internal get; set; } = true; public DiscordConfiguration() { } public DiscordConfiguration(DiscordConfiguration other) { Token = other.Token; TokenType = other.TokenType; MinimumLogLevel = other.MinimumLogLevel; UseRelativeRatelimit = other.UseRelativeRatelimit; LogTimestampFormat = other.LogTimestampFormat; LargeThreshold = other.LargeThreshold; AutoReconnect = other.AutoReconnect; ShardId = other.ShardId; ShardCount = other.ShardCount; GatewayCompressionLevel = other.GatewayCompressionLevel; MessageCacheSize = other.MessageCacheSize; WebSocketClientFactory = other.WebSocketClientFactory; UdpClientFactory = other.UdpClientFactory; Proxy = other.Proxy; HttpTimeout = other.HttpTimeout; ReconnectIndefinitely = other.ReconnectIndefinitely; Intents = other.Intents; LoggerFactory = other.LoggerFactory; LogUnknownEvents = other.LogUnknownEvents; } } internal static class DiscordIntentExtensions { public static bool HasIntent(this DiscordIntents intents, DiscordIntents search) { return (intents & search) == search; } public static DiscordIntents AddIntent(this DiscordIntents intents, DiscordIntents toAdd) { return intents |= toAdd; } public static DiscordIntents RemoveIntent(this DiscordIntents intents, DiscordIntents toRemove) { return intents &= ~toRemove; } internal static bool HasAllPrivilegedIntents(this DiscordIntents intents) { return intents.HasIntent(DiscordIntents.GuildMembers | DiscordIntents.GuildPresences); } } [Flags] internal enum DiscordIntents { Guilds = 1, GuildMembers = 2, GuildBans = 4, GuildEmojis = 8, GuildIntegrations = 0x10, GuildWebhooks = 0x20, GuildInvites = 0x40, GuildVoiceStates = 0x80, GuildPresences = 0x100, GuildMessages = 0x200, GuildMessageReactions = 0x400, GuildMessageTyping = 0x800, DirectMessages = 0x1000, DirectMessageReactions = 0x2000, DirectMessageTyping = 0x4000, MessageContents = 0x8000, ScheduledGuildEvents = 0x10000, AllUnprivileged = 0x17EFD, All = 0x1FFFF } internal enum ApplicationFlags { GatewayPresence = 0x1000, GatewayPresenceLimited = 0x2000, GatewayGuildMembers = 0x4000, GatewayGuildMembersLimited = 0x8000, VerificationPendingGuildLimit = 0x10000, Embedded = 0x20000, GatewayMessageContent = 0x40000, GatewayMessageContentLimited = 0x80000 } internal enum ApplicationUpdateType { Role = 1, User, Channel } internal enum AutoArchiveDuration { Hour = 60, Day = 1440, ThreeDays = 4320, Week = 10080 } internal enum ChannelType { Text = 0, Private = 1, Voice = 2, Group = 3, Category = 4, News = 5, [Obsolete("Store channels have been sunset.", true)] Store = 6, NewsThread = 10, PublicThread = 11, PrivateThread = 12, Stage = 13, Directory = 14, GuildForum = 15, Unknown = int.MaxValue } [Flags] internal enum ChannelFlags { Pinned = 2, RequiresTag = 0x10 } internal enum DefaultForumLayout { Unset, ListView, GalleryView } internal enum DefaultSortOrder { LatestActivity, CreationDate } internal enum OverwriteType { Role, Member } internal enum PrivacyLevel { Public = 1, GuildOnly } internal static class SystemChannelFlagsExtension { public static bool HasSystemChannelFlag(this SystemChannelFlags baseFlags, SystemChannelFlags flag) { return (baseFlags & flag) == flag; } } [Flags] internal enum SystemChannelFlags { SuppressJoinNotifications = 1, SuppressPremiumSubscriptions = 2, SuppressGuildReminderNotifications = 4, SuppressJoinNotificationReplies = 8 } internal enum VideoQualityMode { Auto = 1, Full } internal enum GatewayCompressionLevel : byte { None, Payload, Stream } [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))] internal enum MembershipScreeningFieldType { [EnumMember(Value = "TERMS")] Terms } internal enum NsfwLevel { Default, Explicit, Safe, AgeRestricted } internal enum PremiumTier { None = 0, Tier_1 = 1, Tier_2 = 2, Tier_3 = 3, Unknown = int.MaxValue } internal enum ApplicationCommandOptionType { SubCommand = 1, SubCommandGroup, String, Integer, Boolean, User, Channel, Role, Mentionable, Number, Attachment } internal enum ApplicationCommandPermissionType { Role = 1, User } internal enum ApplicationCommandType { SlashCommand = 1, UserContextMenu, MessageContextMenu, AutoCompleteRequest } internal enum ButtonStyle { Primary = 1, Secondary, Success, Danger } internal enum ComponentType { ActionRow = 1, Button, StringSelect, FormInput, UserSelect, RoleSelect, MentionableSelect, ChannelSelect } internal enum InteractionResponseType { Pong = 1, ChannelMessageWithSource = 4, DeferredChannelMessageWithSource = 5, DeferredMessageUpdate = 6, UpdateMessage = 7, AutoCompleteResult = 8, Modal = 9 } internal enum InteractionType { Ping = 1, ApplicationCommand, Component, AutoComplete, ModalSubmit } internal enum TextInputStyle { Short = 1, Paragraph } internal enum MentionType { None = 0, Username = 1, Nickname = 2, Channel = 4, Role = 8 } internal enum MessageActivityType { Join = 1, Spectate = 2, Listen = 3, JoinRequest = 5 } internal static class MessageFlagExtensions { public static bool HasMessageFlag(this MessageFlags baseFlags, MessageFlags flag) { return (baseFlags & flag) == flag; } } [Flags] internal enum MessageFlags { Crossposted = 1, IsCrosspost = 2, SuppressedEmbeds = 4, SourceMessageDeleted = 8, Urgent = 0x10, Ephemeral = 0x40, Loading = 0x80, FailedToMentionSomeRolesInThread = 0x100, ContainsSuspiciousThirdPartyLink = 0x400, SupressNotifications = 0x1000 } internal enum MessageType { Default = 0, RecipientAdd = 1, RecipientRemove = 2, Call = 3, ChannelNameChange = 4, ChannelIconChange = 5, ChannelPinnedMessage = 6, GuildMemberJoin = 7, UserPremiumGuildSubscription = 8, TierOneUserPremiumGuildSubscription = 9, TierTwoUserPremiumGuildSubscription = 10, TierThreeUserPremiumGuildSubscription = 11, ChannelFollowAdd = 12, GuildDiscoveryDisqualified = 14, GuildDiscoveryRequalified = 15, GuildDiscoveryGracePeriodInitialWarning = 16, GuildDiscoveryGracePeriodFinalWarning = 17, Reply = 19, ApplicationCommand = 20, GuildInviteReminder = 22, ContextMenuCommand = 23, AutoModAlert = 24 } internal static class PermissionMethods { internal static Permissions FULL_PERMS { get; } = Permissions.All; public static bool HasPermission(this Permissions p, Permissions permission) { if (!p.HasFlag(Permissions.Administrator)) { return (p & permission) == permission; } return true; } public static Permissions Grant(this Permissions p, Permissions grant) { return p | grant; } public static Permissions Revoke(this Permissions p, Permissions revoke) { return p & ~revoke; } } internal enum PermissionLevel { Allowed, Denied, Unset } [Flags] internal enum Permissions : long { [PermissionString("No permissions")] None = 0L, [PermissionString("All permissions")] All = 0x1FFFFFFFFFFL, [PermissionString("Create instant invites")] CreateInstantInvite = 1L, [PermissionString("Kick members")] KickMembers = 2L, [PermissionString("Ban members")] BanMembers = 4L, [PermissionString("Administrator")] Administrator = 8L, [PermissionString("Manage channels")] ManageChannels = 0x10L, [PermissionString("Manage guild")] ManageGuild = 0x20L, [PermissionString("Add reactions")] AddReactions = 0x40L, [PermissionString("View audit log")] ViewAuditLog = 0x80L, [PermissionString("Use priority speaker")] PrioritySpeaker = 0x100L, [PermissionString("Read messages")] AccessChannels = 0x400L, [PermissionString("Send messages")] SendMessages = 0x800L, [PermissionString("Send TTS messages")] SendTtsMessages = 0x1000L, [PermissionString("Manage messages")] ManageMessages = 0x2000L, [PermissionString("Use embeds")] EmbedLinks = 0x4000L, [PermissionString("Attach files")] AttachFiles = 0x8000L, [PermissionString("Read message history")] ReadMessageHistory = 0x10000L, [PermissionString("Mention everyone")] MentionEveryone = 0x20000L, [PermissionString("Use external emojis and stickers")] UseExternalEmojis = 0x40000L, [PermissionString("Use voice chat")] UseVoice = 0x100000L, [PermissionString("Speak")] Speak = 0x200000L, [PermissionString("Mute voice chat members")] MuteMembers = 0x400000L, [PermissionString("Deafen voice chat members")] DeafenMembers = 0x800000L, [PermissionString("Move voice chat members")] MoveMembers = 0x1000000L, [PermissionString("Use voice activity detection")] UseVoiceDetection = 0x2000000L, [PermissionString("Change own nickname")] ChangeNickname = 0x4000000L, [PermissionString("Manage nicknames")] ManageNicknames = 0x8000000L, [PermissionString("Manage roles")] ManageRoles = 0x10000000L, [PermissionString("Manage webhooks")] ManageWebhooks = 0x20000000L, [PermissionString("Manage emoji and stickers")] ManageEmojis = 0x40000000L, [PermissionString("Allow stream")] Stream = 0x200L, [Obsolete("Replaced by UseApplicationCommands", false)] [PermissionString("Use slash commands")] UseSlashCommands = 0x80000000L, [PermissionString("Use application commands")] UseApplicationCommands = 0x80000000L, [PermissionString("Request to speak")] RequestToSpeak = 0x100000000L, [PermissionString("Manage Scheduled Events")] ManageEvents = 0x200000000L, [PermissionString("Manage Threads")] ManageThreads = 0x400000000L, [Obsolete("Replaced by CreatePublicThreads and SendMessagesInThreads", false)] [PermissionString("Use Public Threads")] UsePublicThreads = 0x800000000L, [Obsolete("Replaced by CreatePrivateThreads and SendMessagesInThreads", false)] [PermissionString("Use Private Threads")] UsePrivateThreads = 0x1000000000L, [PermissionString("Create Public Threads")] CreatePublicThreads = 0x800000000L, [PermissionString("Create Private Threads")] CreatePrivateThreads = 0x1000000000L, [PermissionString("Use external Stickers")] UseExternalStickers = 0x2000000000L, [PermissionString("Send messages in Threads")] SendMessagesInThreads = 0x4000000000L, [PermissionString("Start Embedded Activities")] StartEmbeddedActivities = 0x8000000000L, [PermissionString("Moderate Members")] ModerateMembers = 0x10000000000L } [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] internal sealed class PermissionStringAttribute : Attribute { public string String { get; } public PermissionStringAttribute(string str) { String = str; } } internal enum TimestampFormat : byte { ShortDate = 100, LongDate = 68, ShortDateTime = 102, LongDateTime = 70, ShortTime = 116, LongTime = 84, RelativeTime = 82 } internal enum TokenType { [Obsolete("Logging in with a user token may result in your account being terminated, and is therefore highly unrecommended.\nIf anything goes wrong with this, we will not provide any support!", true)] User, Bot, Bearer } internal enum InviteTargetType { Stream = 1, EmbeddedApplication } internal enum PremiumType { NitroClassic = 1, Nitro } internal enum TargetUserType { Streaming = 1 } [Flags] internal enum UserFlags { None = 0, DiscordEmployee = 1, DiscordPartner = 2, HypeSquadEvents = 4, BugHunterLevelOne = 8, HouseBravery = 0x40, HouseBrilliance = 0x80, HouseBalance = 0x100, EarlySupporter = 0x200, TeamUser = 0x400, System = 0x1000, BugHunterLevelTwo = 0x4000, VerifiedBot = 0x10000, VerifiedBotDeveloper = 0x20000, DiscordCertifiedModerator = 0x40000, HttpInteractionsBot = 0x80000 } internal static class Formatter { private const string AnsiEscapeStarter = "\u001b["; private static Regex MdSanitizeRegex { get; } = new Regex("([`\\*_~<>\\[\\]\\(\\)\"@\\!\\&#:\\|])", RegexOptions.ECMAScript); private static Regex MdStripRegex { get; } = new Regex("([`\\*_~\\[\\]\\(\\)\"\\|]|<@\\!?\\d+>|<#\\d+>|<@\\&\\d+>|<:[a-zA-Z0-9_\\-]:\\d+>)", RegexOptions.ECMAScript); public static string Colorize(string text, params AnsiColor[] styles) { string text2 = styles.Select(delegate(AnsiColor s) { int num = (int)s; return num.ToString(); }).Aggregate((string a, string b) => a + ";" + b); return string.Format("{0}{1}m{2}{3}{4}m", "\u001b[", text2, text, "\u001b[", 0); } public static string BlockCode(string content, string language = "") { return "```" + language + "\n" + content + "\n```"; } public static string InlineCode(string content) { return "`" + content + "`"; } public static string Timestamp(TimeSpan time, TimestampFormat format = TimestampFormat.RelativeTime) { return Timestamp(DateTimeOffset.UtcNow + time, format); } public static string Timestamp(DateTime time, TimestampFormat format = TimestampFormat.RelativeTime) { return Timestamp(new DateTimeOffset(time.ToUniversalTime()), format); } public static string Timestamp(DateTimeOffset time, TimestampFormat format = TimestampFormat.RelativeTime) { return $""; } public static string Bold(string content) { return "**" + content + "**"; } public static string Italic(string content) { return "*" + content + "*"; } public static string Spoiler(string content) { return "||" + content + "||"; } public static string Underline(string content) { return "__" + content + "__"; } public static string Strike(string content) { return "~~" + content + "~~"; } public static string EmbedlessUrl(Uri url) { return $"<{url}>"; } public static string MaskedUrl(string text, Uri url, string alt_text = "") { return string.Format("[{0}]({1}{2})", text, url, (!string.IsNullOrWhiteSpace(alt_text)) ? (" \"" + alt_text + "\"") : ""); } public static string Sanitize(string text) { return MdSanitizeRegex.Replace(text, (Match m) => "\\" + m.Groups[1].Value); } public static string Strip(string text) { return MdStripRegex.Replace(text, (Match m) => string.Empty); } public static string Mention(DiscordUser user, bool nickname = false) { if (!nickname) { return "<@" + user.Id.ToString(CultureInfo.InvariantCulture) + ">"; } return "<@!" + user.Id.ToString(CultureInfo.InvariantCulture) + ">"; } public static string Mention(DiscordChannel channel) { return "<#" + channel.Id.ToString(CultureInfo.InvariantCulture) + ">"; } public static string Mention(DiscordRole role) { return "<@&" + role.Id.ToString(CultureInfo.InvariantCulture) + ">"; } public static string Mention(DiscordApplicationCommand command) { return ""; } public static string Emoji(DiscordEmoji emoji) { return "<:" + emoji.Name + ":" + emoji.Id.ToString(CultureInfo.InvariantCulture) + ">"; } public static string AttachedImageUrl(string filename) { return "attachment://" + filename; } } internal sealed class ImageTool : IDisposable { private const ulong PNG_MAGIC = 727905341920923785uL; private const ushort JPEG_MAGIC_1 = 55551; private const ushort JPEG_MAGIC_2 = 55807; private const ulong GIF_MAGIC_1 = 106898385160519uL; private const ulong GIF_MAGIC_2 = 106889795225927uL; private const uint WEBP_MAGIC_1 = 1179011410u; private const uint WEBP_MAGIC_2 = 1346520407u; private const ulong GIF_MASK = 281474976710655uL; private const ulong MASK32 = 4294967295uL; private const uint MASK16 = 65535u; private ImageFormat _ifcache; private string _b64cache; public Stream SourceStream { get; } public ImageTool(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead || !stream.CanSeek) { throw new ArgumentException("The stream needs to be both readable and seekable.", "stream"); } SourceStream = stream; SourceStream.Seek(0L, SeekOrigin.Begin); _ifcache = ImageFormat.Unknown; _b64cache = null; } public ImageFormat GetFormat() { if (_ifcache != 0) { return _ifcache; } ImageFormat imageFormat; using (BinaryReader binaryReader = new BinaryReader(SourceStream, Utilities.UTF8, leaveOpen: true)) { ulong num = binaryReader.ReadUInt64(); if (num == 727905341920923785L) { imageFormat = (_ifcache = ImageFormat.Png); imageFormat = imageFormat; } else { num &= 0xFFFFFFFFFFFFuL; if (num == 106898385160519L || num == 106889795225927L) { imageFormat = (_ifcache = ImageFormat.Gif); } else { uint num2 = (uint)(num & 0xFFFFFFFFu); if (num2 == 1179011410 && binaryReader.ReadUInt32() == 1346520407) { imageFormat = (_ifcache = ImageFormat.WebP); } else { if ((ushort)(num2 & 0xFFFF) != 55551) { goto IL_00e8; } SourceStream.Seek(-2L, SeekOrigin.End); if (binaryReader.ReadUInt16() != 55807) { goto IL_00e8; } imageFormat = (_ifcache = ImageFormat.Jpeg); } } } } return imageFormat; IL_00e8: throw new InvalidDataException("The data within the stream was not valid image data."); } public string GetBase64() { if (_b64cache != null) { return _b64cache; } ImageFormat format = GetFormat(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("data:image/").Append(format.ToString().ToLowerInvariant()).Append(";base64,"); SourceStream.Seek(0L, SeekOrigin.Begin); byte[] array = new byte[SourceStream.Length]; for (int i = 0; i < array.Length; i += SourceStream.Read(array, i, (int)SourceStream.Length - i)) { } stringBuilder.Append(Convert.ToBase64String(array)); return _b64cache = stringBuilder.ToString(); } public void Dispose() { if (SourceStream != null) { SourceStream.Dispose(); } } } internal enum ImageFormat { Unknown, Jpeg, Png, Gif, WebP, Auto } internal class CompositeDefaultLogger : ILogger, ILogger { private IEnumerable> Loggers { get; } public CompositeDefaultLogger(IEnumerable providers) { Loggers = providers.Select((ILoggerProvider x) => x.CreateLogger(typeof(BaseDiscordClient).FullName)).OfType>().ToList(); } public bool IsEnabled(LogLevel logLevel) { return true; } public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { foreach (ILogger logger in Loggers) { logger.Log(logLevel, eventId, state, exception, formatter); } } public IDisposable BeginScope(TState state) { throw new NotImplementedException(); } } internal class DefaultLogger : ILogger, ILogger { private static readonly object _lock = new object(); private LogLevel MinimumLevel { get; } private string TimestampFormat { get; } internal DefaultLogger(BaseDiscordClient client) : this(client.Configuration.MinimumLogLevel, client.Configuration.LogTimestampFormat) { } internal DefaultLogger(LogLevel minLevel = LogLevel.Information, string timestampFormat = "yyyy-MM-dd HH:mm:ss zzz") { MinimumLevel = minLevel; TimestampFormat = timestampFormat; } public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { if (!IsEnabled(logLevel)) { return; } lock (_lock) { string name = eventId.Name; name = ((name == null || name.Length <= 12) ? name : name?.Substring(0, 12)); Console.Write($"[{DateTimeOffset.Now.ToString(TimestampFormat)}] [{eventId.Id,-4}/{name,-12}] "); switch (logLevel) { case LogLevel.Trace: Console.ForegroundColor = ConsoleColor.Gray; break; case LogLevel.Debug: Console.ForegroundColor = ConsoleColor.DarkMagenta; break; case LogLevel.Information: Console.ForegroundColor = ConsoleColor.DarkCyan; break; case LogLevel.Warning: Console.ForegroundColor = ConsoleColor.Yellow; break; case LogLevel.Error: Console.ForegroundColor = ConsoleColor.Red; break; case LogLevel.Critical: Console.BackgroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Black; break; } Console.Write(logLevel switch { LogLevel.Trace => "[Trace] ", LogLevel.Debug => "[Debug] ", LogLevel.Information => "[Info ] ", LogLevel.Warning => "[Warn ] ", LogLevel.Error => "[Error] ", LogLevel.Critical => "[Crit ]", LogLevel.None => "[None ] ", _ => "[?????] ", }); Console.ResetColor(); if (logLevel == LogLevel.Critical) { Console.Write(" "); } Console.WriteLine(formatter(state, exception)); if (exception != null) { Console.WriteLine(exception); } } } public bool IsEnabled(LogLevel logLevel) { return logLevel >= MinimumLevel; } public IDisposable BeginScope(TState state) { throw new NotImplementedException(); } } internal class DefaultLoggerFactory : ILoggerFactory, IDisposable { private bool _isDisposed; private List Providers { get; } = new List(); public void AddProvider(ILoggerProvider provider) { Providers.Add(provider); } public ILogger CreateLogger(string categoryName) { if (!_isDisposed) { return new CompositeDefaultLogger(Providers); } throw new InvalidOperationException("This logger factory is already disposed."); } public void Dispose() { if (_isDisposed) { return; } _isDisposed = true; foreach (ILoggerProvider provider in Providers) { provider.Dispose(); } Providers.Clear(); } } internal class DefaultLoggerProvider : ILoggerProvider, IDisposable { private bool _isDisposed; private LogLevel MinimumLevel { get; } private string TimestampFormat { get; } internal DefaultLoggerProvider(BaseDiscordClient client) : this(client.Configuration.MinimumLogLevel, client.Configuration.LogTimestampFormat) { } internal DefaultLoggerProvider(DiscordWebhookClient client) : this(client._minimumLogLevel, client._logTimestampFormat) { } internal DefaultLoggerProvider(LogLevel minLevel = LogLevel.Information, string timestampFormat = "yyyy-MM-dd HH:mm:ss zzz") { MinimumLevel = minLevel; TimestampFormat = timestampFormat; } public ILogger CreateLogger(string categoryName) { if (_isDisposed) { throw new InvalidOperationException("This logger provider is already disposed."); } if (!(categoryName != typeof(BaseDiscordClient).FullName) || !(categoryName != typeof(DiscordWebhookClient).FullName)) { return new DefaultLogger(MinimumLevel, TimestampFormat); } throw new ArgumentException("This provider can only provide instances of loggers for " + typeof(BaseDiscordClient).FullName + " or " + typeof(DiscordWebhookClient).FullName + ".", "categoryName"); } public void Dispose() { _isDisposed = true; } } internal static class LoggerEvents { public static EventId Misc { get; } = new EventId(100, "DSharpPlus"); public static EventId Startup { get; } = new EventId(101, "Startup"); public static EventId ConnectionFailure { get; } = new EventId(102, "ConnectionFailure"); public static EventId SessionUpdate { get; } = new EventId(103, "SessionUpdate"); public static EventId EventHandlerException { get; } = new EventId(104, "EventHandlerException"); public static EventId WebSocketReceive { get; } = new EventId(105, "WebSocketReceive"); public static EventId WebSocketReceiveRaw { get; } = new EventId(106, "WebSocketReceiveRaw"); public static EventId WebSocketSendRaw { get; } = new EventId(107, "WebSocketSendRaw"); public static EventId WebSocketReceiveFailure { get; } = new EventId(108, "WebSocketReceiveFailure"); public static EventId Heartbeat { get; } = new EventId(109, "Heartbeat"); public static EventId HeartbeatFailure { get; } = new EventId(110, "HeartbeatFailure"); public static EventId ConnectionClose { get; } = new EventId(111, "ConnectionClose"); public static EventId RestError { get; } = new EventId(112, "RestError"); public static EventId ShardStartup { get; } = new EventId(113, "ShardStartup"); public static EventId RatelimitHit { get; } = new EventId(114, "RatelimitHit"); public static EventId RatelimitDiag { get; } = new EventId(115, "RatelimitDiag"); public static EventId RatelimitPreemptive { get; } = new EventId(116, "RatelimitPreemptive"); public static EventId AuditLog { get; } = new EventId(117, "AuditLog"); public static EventId GatewayWsRx { get; } = new EventId(118, "Gateway ↓"); public static EventId GatewayWsTx { get; } = new EventId(119, "Gateway ↑"); public static EventId Intents { get; } = new EventId(120, "Intents"); public static EventId ShardShutdown { get; } = new EventId(121, "ShardShutdown"); public static EventId ShardClientError { get; } = new EventId(122, "ShardClientError"); public static EventId RestRx { get; } = new EventId(123, "REST ↓"); public static EventId RestTx { get; } = new EventId(124, "REST ↑"); public static EventId RestCleaner { get; } = new EventId(125, "RestCleaner"); public static EventId RestHashMover { get; } = new EventId(126, "RestHashMover"); public static EventId ShardRest { get; } = new EventId(127, "ShardRest"); } internal class ShardedLoggerFactory : ILoggerFactory, IDisposable { private ConcurrentDictionary Loggers { get; } = new ConcurrentDictionary(); private ILoggerFactory Factory { get; } public ShardedLoggerFactory(ILoggerFactory factory) { Factory = factory; } public void AddProvider(ILoggerProvider provider) { throw new InvalidOperationException("This is a passthrough logger container, it cannot register new providers."); } public ILogger CreateLogger(string categoryName) { return Loggers.GetOrAdd(categoryName, Factory.CreateLogger(categoryName)); } public void Dispose() { } } internal class QueryUriBuilder { private readonly List> _queryParams = new List>(); public Uri SourceUri { get; } public IReadOnlyList> QueryParameters => _queryParams; public QueryUriBuilder(string uri) { if (uri == null) { throw new ArgumentNullException("uri"); } SourceUri = new Uri(uri); } public QueryUriBuilder(Uri uri) { if (uri == null) { throw new ArgumentNullException("uri"); } SourceUri = uri; } public QueryUriBuilder AddParameter(string key, string value) { _queryParams.Add(new KeyValuePair(key, value)); return this; } public Uri Build() { return new UriBuilder(SourceUri) { Query = string.Join("&", _queryParams.Select((KeyValuePair e) => Uri.EscapeDataString(e.Key) + "=" + Uri.EscapeDataString(e.Value))) }.Uri; } public override string ToString() { return Build().ToString(); } } internal readonly struct ReadOnlyConcurrentDictionary : IReadOnlyDictionary, IEnumerable>, IEnumerable, IReadOnlyCollection> { private readonly ConcurrentDictionary _underlyingDict; public int Count => _underlyingDict.Count; public TValue this[TKey key] => _underlyingDict[key]; public IEnumerable Keys => _underlyingDict.Keys; public IEnumerable Values => _underlyingDict.Values; public ReadOnlyConcurrentDictionary(ConcurrentDictionary underlyingDict) { _underlyingDict = underlyingDict; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public IEnumerator> GetEnumerator() { return _underlyingDict.GetEnumerator(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_underlyingDict).GetEnumerator(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool ContainsKey(TKey key) { return _underlyingDict.ContainsKey(key); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetValue(TKey key, out TValue value) { return _underlyingDict.TryGetValue(key, out value); } } internal readonly struct ReadOnlySet : IReadOnlyCollection, IEnumerable, IEnumerable { private readonly ISet _underlyingSet; public int Count => _underlyingSet.Count; public ReadOnlySet(ISet sourceSet) { _underlyingSet = sourceSet; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public IEnumerator GetEnumerator() { return _underlyingSet.GetEnumerator(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_underlyingSet).GetEnumerator(); } } internal class RingBuffer : ICollection, IEnumerable, IEnumerable { private bool _reached_end; public int CurrentIndex { get; protected set; } public int Capacity { get; protected set; } public int Count { get { if (!_reached_end) { return CurrentIndex; } return Capacity; } } public bool IsReadOnly => false; protected T[] InternalBuffer { get; set; } public RingBuffer(int size) { if (size <= 0) { throw new ArgumentOutOfRangeException("size", "Size must be positive."); } CurrentIndex = 0; Capacity = size; InternalBuffer = new T[Capacity]; } public RingBuffer(IEnumerable elements) : this(elements, 0) { } public RingBuffer(IEnumerable elements, int index) { if (elements == null || !elements.Any()) { throw new ArgumentException("elements", "The collection cannot be null or empty."); } CurrentIndex = index; InternalBuffer = elements.ToArray(); Capacity = InternalBuffer.Length; if (CurrentIndex >= InternalBuffer.Length || CurrentIndex < 0) { throw new ArgumentOutOfRangeException("index", "Index must be less than buffer capacity, and greater than zero."); } } public void Add(T item) { InternalBuffer[CurrentIndex++] = item; if (CurrentIndex == Capacity) { CurrentIndex = 0; _reached_end = true; } } public bool TryGet(Func predicate, out T item) { for (int i = CurrentIndex; i < InternalBuffer.Length; i++) { if (InternalBuffer[i] != null && predicate(InternalBuffer[i])) { item = InternalBuffer[i]; return true; } } for (int j = 0; j < CurrentIndex; j++) { if (InternalBuffer[j] != null && predicate(InternalBuffer[j])) { item = InternalBuffer[j]; return true; } } item = default(T); return false; } public void Clear() { for (int i = 0; i < InternalBuffer.Length; i++) { InternalBuffer[i] = default(T); } CurrentIndex = 0; } public bool Contains(T item) { throw new NotImplementedException("This method is not implemented. Use .Contains(predicate) instead."); } public bool Contains(Func predicate) { return InternalBuffer.Any(predicate); } public void CopyTo(T[] array, int index) { if (array.Length - index < 1) { throw new ArgumentException("Target array is too small to contain the elements from this buffer.", "array"); } int num = 0; for (int i = CurrentIndex; i < InternalBuffer.Length; i++) { array[num++] = InternalBuffer[i]; } for (int j = 0; j < CurrentIndex; j++) { array[num++] = InternalBuffer[j]; } } public bool Remove(T item) { throw new NotImplementedException("This method is not implemented. Use .Remove(predicate) instead."); } public bool Remove(Func predicate) { for (int i = 0; i < InternalBuffer.Length; i++) { if (InternalBuffer[i] != null && predicate(InternalBuffer[i])) { InternalBuffer[i] = default(T); return true; } } return false; } public IEnumerator GetEnumerator() { if (_reached_end) { return InternalBuffer.Skip(CurrentIndex).Concat(InternalBuffer.Take(CurrentIndex)).GetEnumerator(); } return InternalBuffer.AsEnumerable().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal static class Utilities { [CompilerGenerated] private sealed class d__27 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private ulong <>2__current; private int <>l__initialThreadId; private DiscordMessage message; public DiscordMessage <>3__message; private IEnumerator <>7__wrap1; ulong IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__27(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; MatchCollection matchCollection = new Regex("<#(\\d+)>", RegexOptions.ECMAScript).Matches(message.Content); <>7__wrap1 = matchCollection.GetEnumerator(); <>1__state = -3; break; } case 1: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { Match match = (Match)<>7__wrap1.Current; <>2__current = ulong.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture); <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap1 is IDisposable disposable) { disposable.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__27 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__27(0); } d__.message = <>3__message; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__28 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private ulong <>2__current; private int <>l__initialThreadId; private DiscordMessage message; public DiscordMessage <>3__message; private IEnumerator <>7__wrap1; ulong IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__28(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; MatchCollection matchCollection = new Regex("", RegexOptions.ECMAScript).Matches(message.Content); <>7__wrap1 = matchCollection.GetEnumerator(); <>1__state = -3; break; } case 1: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { Match match = (Match)<>7__wrap1.Current; <>2__current = ulong.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture); <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap1 is IDisposable disposable) { disposable.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__28 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__28(0); } d__.message = <>3__message; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__26 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private ulong <>2__current; private int <>l__initialThreadId; private DiscordMessage message; public DiscordMessage <>3__message; private IEnumerator <>7__wrap1; ulong IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__26(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; MatchCollection matchCollection = new Regex("<@&(\\d+)>", RegexOptions.ECMAScript).Matches(message.Content); <>7__wrap1 = matchCollection.GetEnumerator(); <>1__state = -3; break; } case 1: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { Match match = (Match)<>7__wrap1.Current; <>2__current = ulong.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture); <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap1 is IDisposable disposable) { disposable.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__26 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__26(0); } d__.message = <>3__message; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__25 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private ulong <>2__current; private int <>l__initialThreadId; private DiscordMessage message; public DiscordMessage <>3__message; private IEnumerator <>7__wrap1; ulong IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__25(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; MatchCollection matchCollection = new Regex("<@!?(\\d+)>", RegexOptions.ECMAScript).Matches(message.Content); <>7__wrap1 = matchCollection.GetEnumerator(); <>1__state = -3; break; } case 1: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { Match match = (Match)<>7__wrap1.Current; <>2__current = ulong.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture); <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap1 is IDisposable disposable) { disposable.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__25 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__25(0); } d__.message = <>3__message; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private static string VersionHeader { get; set; } private static Dictionary PermissionStrings { get; set; } internal static UTF8Encoding UTF8 { get; } static Utilities() { UTF8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); PermissionStrings = new Dictionary(); Type typeFromHandle = typeof(Permissions); TypeInfo typeInfo = typeFromHandle.GetTypeInfo(); foreach (Permissions item in Enum.GetValues(typeFromHandle).Cast()) { string xsv = item.ToString(); PermissionStringAttribute customAttribute = typeInfo.DeclaredMembers.FirstOrDefault((MemberInfo xm) => xm.Name == xsv).GetCustomAttribute(); PermissionStrings[item] = customAttribute.String; } Assembly assembly = typeof(DiscordClient).GetTypeInfo().Assembly; string text = ""; AssemblyInformationalVersionAttribute customAttribute2 = assembly.GetCustomAttribute(); text = ((customAttribute2 == null) ? assembly.GetName().Version.ToString(3) : customAttribute2.InformationalVersion); VersionHeader = "DiscordBot (https://github.com/DSharpPlus/DSharpPlus, v" + text + ")"; } internal static string GetApiBaseUri() { return "https://discord.com/api/v10"; } internal static Uri GetApiUriFor(string path) { return new Uri(GetApiBaseUri() + path); } internal static Uri GetApiUriFor(string path, string queryString) { return new Uri(GetApiBaseUri() + path + queryString); } internal static QueryUriBuilder GetApiUriBuilderFor(string path) { return new QueryUriBuilder(GetApiBaseUri() + path); } internal static string GetFormattedToken(BaseDiscordClient client) { return GetFormattedToken(client.Configuration); } internal static string GetFormattedToken(DiscordConfiguration config) { return config.TokenType switch { TokenType.Bearer => "Bearer " + config.Token, TokenType.Bot => "Bot " + config.Token, _ => throw new ArgumentException("Invalid token type specified.", "Token"), }; } internal static Dictionary GetBaseHeaders() { return new Dictionary(); } internal static string GetUserAgent() { return VersionHeader; } internal static bool ContainsUserMentions(string message) { return new Regex("<@(\\d+)>", RegexOptions.ECMAScript).IsMatch(message); } internal static bool ContainsNicknameMentions(string message) { return new Regex("<@!(\\d+)>", RegexOptions.ECMAScript).IsMatch(message); } internal static bool ContainsChannelMentions(string message) { return new Regex("<#(\\d+)>", RegexOptions.ECMAScript).IsMatch(message); } internal static bool ContainsRoleMentions(string message) { return new Regex("<@&(\\d+)>", RegexOptions.ECMAScript).IsMatch(message); } internal static bool ContainsEmojis(string message) { return new Regex("", RegexOptions.ECMAScript).IsMatch(message); } [IteratorStateMachine(typeof(d__25))] internal static IEnumerable GetUserMentions(DiscordMessage message) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__25(-2) { <>3__message = message }; } [IteratorStateMachine(typeof(d__26))] internal static IEnumerable GetRoleMentions(DiscordMessage message) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__26(-2) { <>3__message = message }; } [IteratorStateMachine(typeof(d__27))] internal static IEnumerable GetChannelMentions(DiscordMessage message) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__27(-2) { <>3__message = message }; } [IteratorStateMachine(typeof(d__28))] internal static IEnumerable GetEmojis(DiscordMessage message) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__28(-2) { <>3__message = message }; } internal static bool IsValidSlashCommandName(string name) { return new Regex("^[\\w-]{1,32}$").IsMatch(name); } internal static bool HasMessageIntents(DiscordIntents intents) { if (!intents.HasIntent(DiscordIntents.GuildMessages) || !intents.HasIntent(DiscordIntents.MessageContents)) { return intents.HasIntent(DiscordIntents.DirectMessages); } return true; } internal static bool HasReactionIntents(DiscordIntents intents) { if (!intents.HasIntent(DiscordIntents.GuildMessageReactions)) { return intents.HasIntent(DiscordIntents.DirectMessageReactions); } return true; } internal static bool HasTypingIntents(DiscordIntents intents) { if (!intents.HasIntent(DiscordIntents.GuildMessageTyping)) { return intents.HasIntent(DiscordIntents.DirectMessageTyping); } return true; } internal static bool IsTextableChannel(DiscordChannel channel) { return channel.Type switch { ChannelType.Text => true, ChannelType.Voice => true, ChannelType.Group => true, ChannelType.Private => true, ChannelType.PublicThread => true, ChannelType.PrivateThread => true, ChannelType.NewsThread => true, ChannelType.News => true, _ => false, }; } public static int GetShardId(ulong guildId, int shardCount) { return (int)((guildId >> 22) % (ulong)shardCount); } public static DateTimeOffset GetDateTimeOffset(long unixTime, bool shouldThrow = true) { try { return DateTimeOffset.FromUnixTimeSeconds(unixTime); } catch (Exception) { if (shouldThrow) { throw; } return DateTimeOffset.MinValue; } } public static DateTimeOffset GetDateTimeOffsetFromMilliseconds(long unixTime, bool shouldThrow = true) { try { return DateTimeOffset.FromUnixTimeMilliseconds(unixTime); } catch (Exception) { if (shouldThrow) { throw; } return DateTimeOffset.MinValue; } } public static long GetUnixTime(DateTimeOffset dto) { return dto.ToUnixTimeMilliseconds(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static DateTimeOffset GetSnowflakeTime(this ulong snowflake) { DateTimeOffset discordEpoch = DiscordClient._discordEpoch; return discordEpoch.AddMilliseconds(snowflake >> 22); } public static string ToPermissionString(this Permissions perm) { if (perm == Permissions.None) { return PermissionStrings[perm]; } perm &= PermissionMethods.FULL_PERMS; IEnumerable source = from xkvp in PermissionStrings where xkvp.Key != Permissions.None && (perm & xkvp.Key) == xkvp.Key select xkvp.Value; return string.Join(", ", source.OrderBy((string xs) => xs)); } public static bool Contains(this string str, params char[] characters) { foreach (char value in str) { if (characters.Contains(value)) { return true; } } return false; } internal static void LogTaskFault(this Task task, ILogger logger, LogLevel level, EventId eventId, string message) { if (task == null) { throw new ArgumentNullException("task"); } if (logger != null) { task.ContinueWith(delegate(Task t) { logger.Log(level, eventId, t.Exception, message); }, TaskContinuationOptions.OnlyOnFaulted); } } internal static void Deconstruct(this KeyValuePair kvp, out TKey key, out TValue value) { key = kvp.Key; value = kvp.Value; } } } namespace DSharpPlus.Exceptions { internal class BadRequestException : DiscordException { public int Code { get; internal set; } public string Errors { get; internal set; } internal BadRequestException(BaseRestRequest request, RestResponse response) : base("Bad request: " + response.ResponseCode) { WebRequest = request; WebResponse = response; try { JObject jObject = JObject.Parse(response.Response); if (jObject["code"] != null) { Code = (int)jObject["code"]; } if (jObject["message"] != null) { JsonMessage = jObject["message"].ToString(); } if (jObject["errors"] != null) { Errors = jObject["errors"].ToString(); } } catch { } } } internal abstract class DiscordException : Exception { public virtual BaseRestRequest WebRequest { get; internal set; } public virtual RestResponse WebResponse { get; internal set; } public virtual string JsonMessage { get; internal set; } public DiscordException() { } public DiscordException(string message) : base(message) { } public DiscordException(string message, Exception innerException) : base(message, innerException) { } } internal class NotFoundException : DiscordException { internal NotFoundException(BaseRestRequest request, RestResponse response) : base("Not found: " + response.ResponseCode) { WebRequest = request; WebResponse = response; try { JObject jObject = JObject.Parse(response.Response); if (jObject["message"] != null) { JsonMessage = jObject["message"].ToString(); } } catch (Exception) { } } } internal class RateLimitException : DiscordException { internal RateLimitException(BaseRestRequest request, RestResponse response) : base("Rate limited: " + response.ResponseCode) { WebRequest = request; WebResponse = response; try { JObject jObject = JObject.Parse(response.Response); if (jObject["message"] != null) { JsonMessage = jObject["message"].ToString(); } } catch (Exception) { } } } internal class RequestSizeException : DiscordException { internal RequestSizeException(BaseRestRequest request, RestResponse response) : base($"Request entity too large: {response.ResponseCode}. Make sure the data sent is within Discord's upload limit.") { WebRequest = request; WebResponse = response; try { JObject jObject = JObject.Parse(response.Response); if (jObject["message"] != null) { JsonMessage = jObject["message"].ToString(); } } catch (Exception) { } } } internal class ServerErrorException : DiscordException { internal ServerErrorException(BaseRestRequest request, RestResponse response) : base("Internal Server Error: " + response.ResponseCode) { WebRequest = request; WebResponse = response; try { JObject jObject = JObject.Parse(response.Response); if (jObject["message"] != null) { JsonMessage = jObject["message"].ToString(); } } catch (Exception) { } } } internal class UnauthorizedException : DiscordException { internal UnauthorizedException(BaseRestRequest request, RestResponse response) : base("Unauthorized: " + response.ResponseCode) { WebRequest = request; WebResponse = response; try { JObject jObject = JObject.Parse(response.Response); if (jObject["message"] != null) { JsonMessage = jObject["message"].ToString(); } } catch (Exception) { } } } } namespace DSharpPlus.EventArgs { internal sealed class ApplicationCommandEventArgs : DiscordEventArgs { public DiscordApplicationCommand Command { get; internal set; } public DiscordGuild Guild { get; internal set; } } internal class ApplicationCommandPermissionsUpdatedEventArgs : DiscordEventArgs { [JsonProperty("guild_id")] public ulong GuildId { get; internal set; } [JsonProperty("id")] public ulong CommandId { get; internal set; } [JsonProperty("application_id")] public ulong ApplicationId { get; internal set; } [JsonProperty("permissions")] public IReadOnlyList NewPermissions { get; internal set; } } internal class ApplicationCommandPermissionUpdate { [JsonProperty("id")] public ulong Id { get; internal set; } [JsonProperty("permission")] public bool Allow { get; internal set; } [JsonProperty("type")] public ApplicationCommandPermissionType Type { get; internal set; } } internal class ChannelCreateEventArgs : DiscordEventArgs { public DiscordChannel Channel { get; internal set; } public DiscordGuild Guild { get; internal set; } internal ChannelCreateEventArgs() { } } internal class ChannelDeleteEventArgs : DiscordEventArgs { public DiscordChannel Channel { get; internal set; } public DiscordGuild Guild { get; internal set; } internal ChannelDeleteEventArgs() { } } internal class ChannelPinsUpdateEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public DiscordChannel Channel { get; internal set; } public DateTimeOffset? LastPinTimestamp { get; internal set; } internal ChannelPinsUpdateEventArgs() { } } internal class ChannelUpdateEventArgs : DiscordEventArgs { public DiscordChannel ChannelAfter { get; internal set; } public DiscordChannel ChannelBefore { get; internal set; } public DiscordGuild Guild { get; internal set; } internal ChannelUpdateEventArgs() { } } internal class DmChannelDeleteEventArgs : DiscordEventArgs { public DiscordDmChannel Channel { get; internal set; } internal DmChannelDeleteEventArgs() { } } internal class ThreadCreateEventArgs : DiscordEventArgs { public bool NewlyCreated { get; internal set; } public DiscordThreadChannel Thread { get; internal set; } public DiscordChannel Parent { get; internal set; } public DiscordGuild Guild { get; internal set; } internal ThreadCreateEventArgs() { } } internal class ThreadDeleteEventArgs : DiscordEventArgs { public DiscordThreadChannel Thread { get; internal set; } public DiscordChannel Parent { get; internal set; } public DiscordGuild Guild { get; internal set; } internal ThreadDeleteEventArgs() { } } internal class ThreadListSyncEventArgs : DiscordEventArgs { public IReadOnlyList CurrentMembers { get; internal set; } public IReadOnlyList Threads { get; internal set; } public IReadOnlyList Channels { get; internal set; } public DiscordGuild Guild { get; internal set; } internal ThreadListSyncEventArgs() { } } internal class ThreadMembersUpdateEventArgs : DiscordEventArgs { public int MemberCount { get; internal set; } public IReadOnlyList RemovedMembers { get; internal set; } public IReadOnlyList AddedMembers { get; internal set; } public DiscordThreadChannel Thread { get; internal set; } public DiscordGuild Guild { get; internal set; } internal ThreadMembersUpdateEventArgs() { } } internal class ThreadMemberUpdateEventArgs : DiscordEventArgs { public DiscordThreadChannelMember ThreadMember { get; internal set; } public DiscordThreadChannel Thread { get; internal set; } internal ThreadMemberUpdateEventArgs() { } } internal class ThreadUpdateEventArgs : DiscordEventArgs { public DiscordThreadChannel ThreadAfter { get; internal set; } public DiscordThreadChannel ThreadBefore { get; internal set; } public DiscordChannel Parent { get; internal set; } public DiscordGuild Guild { get; internal set; } internal ThreadUpdateEventArgs() { } } internal class ClientErrorEventArgs : DiscordEventArgs { public Exception Exception { get; internal set; } public string EventName { get; internal set; } internal ClientErrorEventArgs() { } } internal abstract class DiscordEventArgs : AsyncEventArgs { } internal class GuildBanAddEventArgs : DiscordEventArgs { public DiscordMember Member { get; internal set; } public DiscordGuild Guild { get; internal set; } internal GuildBanAddEventArgs() { } } internal class GuildBanRemoveEventArgs : DiscordEventArgs { public DiscordMember Member { get; internal set; } public DiscordGuild Guild { get; internal set; } internal GuildBanRemoveEventArgs() { } } internal class GuildCreateEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } internal GuildCreateEventArgs() { } } internal class GuildDeleteEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public bool Unavailable { get; internal set; } internal GuildDeleteEventArgs() { } } internal class GuildDownloadCompletedEventArgs : DiscordEventArgs { public IReadOnlyDictionary Guilds { get; } internal GuildDownloadCompletedEventArgs(IReadOnlyDictionary guilds) { Guilds = guilds; } } internal class GuildEmojisUpdateEventArgs : DiscordEventArgs { public IReadOnlyDictionary EmojisAfter { get; internal set; } public IReadOnlyDictionary EmojisBefore { get; internal set; } public DiscordGuild Guild { get; internal set; } internal GuildEmojisUpdateEventArgs() { } } internal class GuildIntegrationsUpdateEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } internal GuildIntegrationsUpdateEventArgs() { } } internal class GuildStickersUpdateEventArgs : DiscordEventArgs { public IReadOnlyDictionary StickersAfter { get; internal set; } public IReadOnlyDictionary StickersBefore { get; internal set; } public DiscordGuild Guild { get; internal set; } internal GuildStickersUpdateEventArgs() { } } internal class GuildUpdateEventArgs : DiscordEventArgs { public DiscordGuild GuildBefore { get; internal set; } public DiscordGuild GuildAfter { get; internal set; } internal GuildUpdateEventArgs() { } } internal class GuildMemberAddEventArgs : DiscordEventArgs { public DiscordMember Member { get; internal set; } public DiscordGuild Guild { get; internal set; } internal GuildMemberAddEventArgs() { } } internal class GuildMemberRemoveEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public DiscordMember Member { get; internal set; } internal GuildMemberRemoveEventArgs() { } } internal class GuildMembersChunkEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public IReadOnlyCollection Members { get; internal set; } public int ChunkIndex { get; internal set; } public int ChunkCount { get; internal set; } public IReadOnlyCollection Presences { get; internal set; } public IReadOnlyCollection NotFound { get; internal set; } public string Nonce { get; set; } internal GuildMembersChunkEventArgs() { } } internal class GuildMemberUpdateEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public DiscordMember MemberAfter { get; internal set; } public DiscordMember MemberBefore { get; internal set; } public IReadOnlyList RolesAfter => new ReadOnlyCollection(new List(MemberAfter.Roles)); public IReadOnlyList RolesBefore => new ReadOnlyCollection(new List(MemberBefore.Roles)); public string NicknameAfter => MemberAfter.Nickname; public string NicknameBefore => MemberBefore.Nickname; public string GuildAvatarHashBefore => MemberBefore.GuildAvatarHash; public string GuildAvatarHashAfter => MemberAfter.GuildAvatarHash; public string UsernameBefore => MemberBefore.Username; public string UsernameAfter => MemberAfter.Username; public string AvatarHashBefore => MemberBefore.AvatarHash; public string AvatarHashAfter => MemberAfter.AvatarHash; public bool? PendingBefore => MemberBefore.IsPending; public bool? PendingAfter => MemberAfter.IsPending; public DateTimeOffset? CommunicationDisabledUntilBefore => MemberBefore.CommunicationDisabledUntil; public DateTimeOffset? CommunicationDisabledUntilAfter => MemberAfter.CommunicationDisabledUntil; public DiscordMember Member => MemberAfter; internal GuildMemberUpdateEventArgs() { } } internal class GuildRoleCreateEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public DiscordRole Role { get; internal set; } internal GuildRoleCreateEventArgs() { } } internal class GuildRoleDeleteEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public DiscordRole Role { get; internal set; } internal GuildRoleDeleteEventArgs() { } } internal class GuildRoleUpdateEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public DiscordRole RoleAfter { get; internal set; } public DiscordRole RoleBefore { get; internal set; } internal GuildRoleUpdateEventArgs() { } } internal class ScheduledGuildEventCompletedEventArgs : DiscordEventArgs { public DiscordScheduledGuildEvent Event { get; internal set; } internal ScheduledGuildEventCompletedEventArgs() { } } internal class ScheduledGuildEventCreateEventArgs : DiscordEventArgs { public DiscordGuild Guild => Event.Guild; public DiscordChannel Channel => Event.Channel; public DiscordUser Creator => Event.Creator; public DiscordScheduledGuildEvent Event { get; internal set; } internal ScheduledGuildEventCreateEventArgs() { } } internal class ScheduledGuildEventDeleteEventArgs : DiscordEventArgs { public DiscordScheduledGuildEvent Event { get; internal set; } internal ScheduledGuildEventDeleteEventArgs() { } } internal class ScheduledGuildEventUpdateEventArgs : DiscordEventArgs { public DiscordScheduledGuildEvent EventBefore { get; internal set; } public DiscordScheduledGuildEvent EventAfter { get; internal set; } internal ScheduledGuildEventUpdateEventArgs() { } } internal class ScheduledGuildEventUserAddEventArgs : DiscordEventArgs { public DiscordGuild Guild => Event.Guild; public DiscordScheduledGuildEvent Event { get; internal set; } public DiscordUser User { get; internal set; } internal ScheduledGuildEventUserAddEventArgs() { } } internal class ScheduledGuildEventUserRemoveEventArgs : ScheduledGuildEventUserAddEventArgs { public new DiscordGuild Guild => Event.Guild; public new DiscordScheduledGuildEvent Event { get; internal set; } public new DiscordUser User { get; internal set; } internal ScheduledGuildEventUserRemoveEventArgs() { } } internal class HeartbeatEventArgs : DiscordEventArgs { public int Ping { get; internal set; } public DateTimeOffset Timestamp { get; internal set; } internal HeartbeatEventArgs() { } } internal sealed class IntegrationCreateEventArgs : DiscordEventArgs { public DiscordIntegration Integration { get; internal set; } public DiscordGuild Guild { get; internal set; } } internal sealed class IntegrationDeleteEventArgs : DiscordEventArgs { public ulong IntegrationId { get; internal set; } public DiscordGuild Guild { get; internal set; } public ulong? Applicationid { get; internal set; } } internal sealed class IntegrationUpdateEventArgs : DiscordEventArgs { public DiscordIntegration Integration { get; internal set; } public DiscordGuild Guild { get; internal set; } } internal class ComponentInteractionCreateEventArgs : InteractionCreateEventArgs { public string Id => base.Interaction.Data.CustomId; public DiscordUser User => base.Interaction.User; public DiscordGuild Guild => Channel.Guild; public DiscordChannel Channel => base.Interaction.Channel; public string[] Values => base.Interaction.Data.Values; public DiscordMessage Message { get; internal set; } public string Locale => base.Interaction.Locale; public string GuildLocale => base.Interaction.GuildLocale; internal ComponentInteractionCreateEventArgs() { } } internal sealed class ContextMenuInteractionCreateEventArgs : InteractionCreateEventArgs { public ApplicationCommandType Type { get; internal set; } public DiscordUser User => base.Interaction.User; public DiscordUser TargetUser { get; internal set; } public DiscordMessage TargetMessage { get; internal set; } } internal class InteractionCreateEventArgs : DiscordEventArgs { public DiscordInteraction Interaction { get; internal set; } } internal class ModalSubmitEventArgs : InteractionCreateEventArgs { [Newtonsoft.Json.JsonIgnore] public IReadOnlyDictionary Values { get; } internal ModalSubmitEventArgs(DiscordInteraction interaction) { base.Interaction = interaction; Dictionary dictionary = new Dictionary(); foreach (DiscordComponent component in interaction.Data._components) { if ((component as DiscordActionRowComponent)?.Components.First() is TextInputComponent textInputComponent) { dictionary.Add(textInputComponent.CustomId, textInputComponent.Value); } } Values = dictionary; } } internal sealed class InviteCreateEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public DiscordChannel Channel { get; internal set; } public DiscordInvite Invite { get; internal set; } internal InviteCreateEventArgs() { } } internal sealed class InviteDeleteEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public DiscordChannel Channel { get; internal set; } public DiscordInvite Invite { get; internal set; } internal InviteDeleteEventArgs() { } } internal sealed class MessageAcknowledgeEventArgs : DiscordEventArgs { public DiscordMessage Message { get; internal set; } public DiscordChannel Channel => Message.Channel; internal MessageAcknowledgeEventArgs() { } } internal class MessageBulkDeleteEventArgs : DiscordEventArgs { public IReadOnlyList Messages { get; internal set; } public DiscordChannel Channel { get; internal set; } public DiscordGuild Guild { get; internal set; } internal MessageBulkDeleteEventArgs() { } } internal class MessageCreateEventArgs : DiscordEventArgs { public DiscordMessage Message { get; internal set; } public DiscordChannel Channel => Message.Channel; public DiscordGuild Guild => Channel.Guild; public DiscordUser Author => Message.Author; public IReadOnlyList MentionedUsers { get; internal set; } public IReadOnlyList MentionedRoles { get; internal set; } public IReadOnlyList MentionedChannels { get; internal set; } internal MessageCreateEventArgs() { } } internal class MessageDeleteEventArgs : DiscordEventArgs { public DiscordMessage Message { get; internal set; } public DiscordChannel Channel { get; internal set; } public DiscordGuild Guild { get; internal set; } internal MessageDeleteEventArgs() { } } internal class MessageUpdateEventArgs : DiscordEventArgs { public DiscordMessage Message { get; internal set; } public DiscordMessage MessageBefore { get; internal set; } public DiscordChannel Channel => Message.Channel; public DiscordGuild Guild => Channel.Guild; public DiscordUser Author => Message.Author; public IReadOnlyList MentionedUsers { get; internal set; } public IReadOnlyList MentionedRoles { get; internal set; } public IReadOnlyList MentionedChannels { get; internal set; } internal MessageUpdateEventArgs() { } } internal class MessageReactionAddEventArgs : DiscordEventArgs { public DiscordMessage Message { get; internal set; } public DiscordChannel Channel => Message.Channel; public DiscordGuild Guild { get; internal set; } public DiscordUser User { get; internal set; } public DiscordEmoji Emoji { get; internal set; } internal MessageReactionAddEventArgs() { } } internal sealed class MessageReactionRemoveEmojiEventArgs : DiscordEventArgs { public DiscordChannel Channel { get; internal set; } public DiscordGuild Guild { get; internal set; } public DiscordMessage Message { get; internal set; } public DiscordEmoji Emoji { get; internal set; } internal MessageReactionRemoveEmojiEventArgs() { } } internal class MessageReactionRemoveEventArgs : DiscordEventArgs { public DiscordMessage Message { get; internal set; } public DiscordChannel Channel => Message.Channel; public DiscordUser User { get; internal set; } public DiscordGuild Guild { get; internal set; } public DiscordEmoji Emoji { get; internal set; } internal MessageReactionRemoveEventArgs() { } } internal class MessageReactionsClearEventArgs : DiscordEventArgs { public DiscordMessage Message { get; internal set; } public DiscordChannel Channel => Message.Channel; public DiscordGuild Guild => Channel.Guild; internal MessageReactionsClearEventArgs() { } } internal sealed class ReadyEventArgs : DiscordEventArgs { internal ReadyEventArgs() { } } internal class SocketCloseEventArgs : DiscordEventArgs { public int CloseCode { get; internal set; } public string CloseMessage { get; internal set; } } internal class SocketErrorEventArgs : DiscordEventArgs { public Exception Exception { get; internal set; } } internal class SocketEventArgs : DiscordEventArgs { } internal abstract class SocketMessageEventArgs : AsyncEventArgs { } internal sealed class SocketTextMessageEventArgs : SocketMessageEventArgs { public string Message { get; } public SocketTextMessageEventArgs(string message) { Message = message; } } internal sealed class SocketBinaryMessageEventArgs : SocketMessageEventArgs { public byte[] Message { get; } public SocketBinaryMessageEventArgs(byte[] message) { Message = message; } } internal class StageInstanceCreateEventArgs : DiscordEventArgs { public DiscordStageInstance StageInstance { get; internal set; } public DiscordGuild Guild => StageInstance.Guild; public DiscordChannel Channel => StageInstance.Channel; } internal class StageInstanceDeleteEventArgs : DiscordEventArgs { public DiscordStageInstance StageInstance { get; internal set; } public DiscordGuild Guild => StageInstance.Guild; public DiscordChannel Channel => StageInstance.Channel; } internal class StageInstanceUpdateEventArgs : DiscordEventArgs { public DiscordStageInstance StageInstanceBefore { get; internal set; } public DiscordStageInstance StageInstanceAfter { get; internal set; } public DiscordGuild Guild => StageInstanceAfter.Guild; public DiscordChannel Channel => StageInstanceAfter.Channel; } internal class TypingStartEventArgs : DiscordEventArgs { public DiscordChannel Channel { get; internal set; } public DiscordUser User { get; internal set; } public DiscordGuild Guild { get; internal set; } public DateTimeOffset StartedAt { get; internal set; } internal TypingStartEventArgs() { } } internal class UnknownEventArgs : DiscordEventArgs { public string EventName { get; internal set; } public string Json { get; internal set; } internal UnknownEventArgs() { } } internal class PresenceUpdateEventArgs : DiscordEventArgs { public DiscordUser User { get; internal set; } public DiscordActivity Activity { get; internal set; } public UserStatus Status { get; internal set; } public DiscordPresence PresenceBefore { get; internal set; } public DiscordPresence PresenceAfter { get; internal set; } public DiscordUser UserBefore { get; internal set; } public DiscordUser UserAfter { get; internal set; } internal PresenceUpdateEventArgs() { } } internal class UserSettingsUpdateEventArgs : DiscordEventArgs { public DiscordUser User { get; internal set; } internal UserSettingsUpdateEventArgs() { } } internal class UserSpeakingEventArgs : DiscordEventArgs { public DiscordUser User { get; internal set; } public uint SSRC { get; internal set; } public bool Speaking { get; internal set; } internal UserSpeakingEventArgs() { } } internal class UserUpdateEventArgs : DiscordEventArgs { public DiscordUser UserAfter { get; internal set; } public DiscordUser UserBefore { get; internal set; } internal UserUpdateEventArgs() { } } internal class VoiceServerUpdateEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public string Endpoint { get; internal set; } public string VoiceToken { get; internal set; } internal VoiceServerUpdateEventArgs() { } } internal class VoiceStateUpdateEventArgs : DiscordEventArgs { public DiscordUser User { get; internal set; } public DiscordGuild Guild { get; internal set; } public DiscordChannel Channel { get; internal set; } public DiscordVoiceState Before { get; internal set; } public DiscordVoiceState After { get; internal set; } public string SessionId { get; internal set; } internal VoiceStateUpdateEventArgs() { } } internal class WebhooksUpdateEventArgs : DiscordEventArgs { public DiscordGuild Guild { get; internal set; } public DiscordChannel Channel { get; internal set; } internal WebhooksUpdateEventArgs() { } } internal class ZombiedEventArgs : DiscordEventArgs { public int Failures { get; internal set; } public bool GuildDownloadCompleted { get; internal set; } internal ZombiedEventArgs() { } } } namespace DSharpPlus.Net { [Newtonsoft.Json.JsonConverter(typeof(DiscordUriJsonConverter))] internal class DiscordUri { internal sealed class DiscordUriJsonConverter : Newtonsoft.Json.JsonConverter { public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { writer.WriteValue((value as DiscordUri)._value); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { object value = reader.Value; if (value == null) { return null; } if (value is string text) { if (!IsStandard(text)) { return new DiscordUri(text); } return new DiscordUri(new Uri(text)); } throw new JsonReaderException("DiscordUri value invalid format! This is a bug in DSharpPlus. " + $"Include the type in your bug report: [[{reader.TokenType}]]"); } public override bool CanConvert(Type objectType) { return objectType == typeof(DiscordUri); } } private readonly object _value; public DiscordUriType Type { get; } internal DiscordUri(Uri value) { _value = value ?? throw new ArgumentNullException("value"); Type = DiscordUriType.Standard; } internal DiscordUri(string value) { if (value == null) { throw new ArgumentNullException("value"); } if (IsStandard(value)) { _value = new Uri(value); Type = DiscordUriType.Standard; } else { _value = value; Type = DiscordUriType.NonStandard; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsStandard(string value) { return !value.StartsWith("attachment://"); } public override string ToString() { return _value.ToString(); } public Uri ToUri() { if (Type != 0) { throw new UriFormatException(string.Format("DiscordUri \"{0}\" would be invalid as a regular URI, please the {1} property first.", _value, "Type")); } return _value as Uri; } } internal enum DiscordUriType : byte { Standard, NonStandard } internal sealed class GatewayInfo { [JsonProperty("url")] public string Url { get; set; } [JsonProperty("shards")] public int ShardCount { get; internal set; } [JsonProperty("session_start_limit")] public SessionBucket SessionBucket { get; internal set; } } internal struct ConnectionEndpoint { public string Hostname { get; set; } public int Port { get; set; } public bool Secured { get; set; } public ConnectionEndpoint(string hostname, int port, bool secured = false) { Hostname = hostname; Port = port; Secured = secured; } public override int GetHashCode() { return 13 + 7 * Hostname.GetHashCode() + 7 * Port; } public override string ToString() { return $"{Hostname}:{Port}"; } internal string ToHttpString() { string arg = (Secured ? "s" : ""); return $"http{arg}://{this}"; } internal string ToWebSocketString() { string arg = (Secured ? "s" : ""); return $"ws{arg}://{this}/"; } } internal abstract class BaseRestRequest { protected internal BaseDiscordClient Discord { get; } protected internal TaskCompletionSource RequestTaskSource { get; } public Uri Url { get; } public RestRequestMethod Method { get; } public string Route { get; } public IReadOnlyDictionary Headers { get; } public double? RateLimitWaitOverride { get; } internal RateLimitBucket RateLimitBucket { get; } internal BaseRestRequest(BaseDiscordClient client, RateLimitBucket bucket, Uri url, RestRequestMethod method, string route, IReadOnlyDictionary headers = null, double? ratelimitWaitOverride = null) { Discord = client; RateLimitBucket = bucket; RequestTaskSource = new TaskCompletionSource(); Url = url; Method = method; Route = route; RateLimitWaitOverride = ratelimitWaitOverride; if (headers != null) { headers = headers.Select((KeyValuePair x) => new KeyValuePair(x.Key, Uri.EscapeDataString(x.Value))).ToDictionary((KeyValuePair x) => x.Key, (KeyValuePair x) => x.Value); Headers = headers; } } public Task WaitForCompletionAsync() { return RequestTaskSource.Task; } protected internal void SetCompleted(RestResponse response) { RequestTaskSource.SetResult(response); } protected internal void SetFaulted(Exception ex) { RequestTaskSource.SetException(ex); } protected internal bool TrySetFaulted(Exception ex) { return RequestTaskSource.TrySetException(ex); } } internal sealed class DiscordApiClient { private const string REASON_HEADER_NAME = "X-Audit-Log-Reason"; internal BaseDiscordClient _discord { get; } internal RestClient _rest { get; } internal DiscordApiClient(BaseDiscordClient client, RestClient rest = null) { _discord = client; _rest = rest ?? new RestClient(client.Configuration, client.Logger); } internal DiscordApiClient(IWebProxy proxy, TimeSpan timeout, bool useRelativeRateLimit, ILogger logger) { _rest = new RestClient(proxy, timeout, useRelativeRateLimit, logger); } private static string BuildQueryString(IDictionary values, bool post = false) { if (values == null || values.Count == 0) { return string.Empty; } IEnumerable values2 = values.Select((KeyValuePair xkvp) => WebUtility.UrlEncode(xkvp.Key) + "=" + WebUtility.UrlEncode(xkvp.Value)); string text = string.Join("&", values2); if (post) { return text; } return "?" + text; } private DiscordMessage PrepareMessage(JToken msg_raw) { TransportUser author = msg_raw["author"].ToDiscordObject(); DiscordMessage discordMessage = msg_raw.ToDiscordObject(); discordMessage.Discord = _discord; PopulateMessage(author, discordMessage); JToken jToken = msg_raw["referenced_message"]; if (discordMessage.MessageType.GetValueOrDefault() == MessageType.Reply && !string.IsNullOrWhiteSpace(jToken?.ToString())) { author = jToken["author"].ToDiscordObject(); discordMessage.ReferencedMessage.Discord = _discord; PopulateMessage(author, discordMessage.ReferencedMessage); } if (discordMessage.Channel != null) { return discordMessage; } DiscordChannel channel = ((!discordMessage._guildId.HasValue) ? new DiscordDmChannel { Id = discordMessage.ChannelId, Discord = _discord, Type = ChannelType.Private } : new DiscordChannel { Id = discordMessage.ChannelId, GuildId = discordMessage._guildId, Discord = _discord }); discordMessage.Channel = channel; return discordMessage; } private void PopulateMessage(TransportUser author, DiscordMessage ret) { DiscordGuild discordGuild = ret.Channel?.Guild; if (author.IsBot && int.Parse(author.Discriminator) == 0) { ret.Author = new DiscordUser(author) { Discord = _discord }; } else { if (!_discord.UserCache.TryGetValue(author.Id, out var value)) { ConcurrentDictionary userCache = _discord.UserCache; ulong id = author.Id; DiscordUser obj = new DiscordUser(author) { Discord = _discord }; value = obj; userCache[id] = obj; } if (discordGuild != null) { if (!discordGuild.Members.TryGetValue(author.Id, out var value2)) { value2 = new DiscordMember(value) { Discord = _discord, _guild_id = discordGuild.Id }; } ret.Author = value2; } else { ret.Author = value; } } ret.PopulateMentions(); if (ret._reactions == null) { ret._reactions = new List(); } foreach (DiscordReaction reaction in ret._reactions) { reaction.Emoji.Discord = _discord; } } private Task DoRequestAsync(BaseDiscordClient client, RateLimitBucket bucket, Uri url, RestRequestMethod method, string route, IReadOnlyDictionary headers = null, string payload = null, double? ratelimitWaitOverride = null) { RestRequest restRequest = new RestRequest(client, bucket, url, method, route, headers, payload, ratelimitWaitOverride); if (_discord != null) { _rest.ExecuteRequestAsync(restRequest).LogTaskFault(_discord.Logger, LogLevel.Error, LoggerEvents.RestError, "Error while executing request"); } else { _rest.ExecuteRequestAsync(restRequest); } return restRequest.WaitForCompletionAsync(); } private Task DoMultipartAsync(BaseDiscordClient client, RateLimitBucket bucket, Uri url, RestRequestMethod method, string route, IReadOnlyDictionary headers = null, IReadOnlyDictionary values = null, IReadOnlyCollection files = null, double? ratelimitWaitOverride = null, bool removeFileCount = false) { MultipartWebRequest multipartWebRequest = new MultipartWebRequest(client, bucket, url, method, route, headers, values, files, ratelimitWaitOverride) { _removeFileCount = removeFileCount }; if (_discord != null) { _rest.ExecuteRequestAsync(multipartWebRequest).LogTaskFault(_discord.Logger, LogLevel.Error, LoggerEvents.RestError, "Error while executing request"); } else { _rest.ExecuteRequestAsync(multipartWebRequest); } return multipartWebRequest.WaitForCompletionAsync(); } internal async Task> SearchMembersAsync(ulong guild_id, string name, int? limit) { string route = "/guilds/:guild_id/members/search"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Dictionary values = new Dictionary { ["query"] = name, ["limit"] = limit.ToString() }; Uri apiUriFor = Utilities.GetApiUriFor(url, BuildQueryString(values)); IReadOnlyList readOnlyList = JArray.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).ToDiscordObject>(); List list = new List(); foreach (TransportMember item in readOnlyList) { DiscordUser newUser = new DiscordUser(item.User) { Discord = _discord }; _discord.UpdateUserCache(newUser); list.Add(new DiscordMember(item) { Discord = _discord, _guild_id = guild_id }); } return list; } internal async Task GetGuildBanAsync(ulong guild_id, ulong user_id) { string route = "/guilds/:guild_id/bans/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordBan discordBan = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).ToDiscordObject(); if (!_discord.TryGetCachedUserInternal(discordBan.RawUser.Id, out var user)) { user = new DiscordUser(discordBan.RawUser) { Discord = _discord }; user = _discord.UpdateUserCache(user); } discordBan.User = user; return discordBan; } internal async Task CreateGuildAsync(string name, string region_id, Optional iconb64, VerificationLevel? verification_level, DefaultMessageNotifications? default_message_notifications, SystemChannelFlags? system_channel_flags) { RestGuildCreatePayload value = new RestGuildCreatePayload { Name = name, RegionId = region_id, DefaultMessageNotifications = default_message_notifications, VerificationLevel = verification_level, IconBase64 = iconb64, SystemChannelFlags = system_channel_flags }; string route = "/guilds"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); JObject jObject = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); JArray rawMembers = (JArray)jObject["members"]; DiscordGuild guild = jObject.ToDiscordObject(); if (_discord is DiscordClient discordClient) { await discordClient.OnGuildCreateEventAsync(guild, rawMembers, null).ConfigureAwait(continueOnCapturedContext: false); } return guild; } internal async Task CreateGuildFromTemplateAsync(string template_code, string name, Optional iconb64) { RestGuildCreateFromTemplatePayload value = new RestGuildCreateFromTemplatePayload { Name = name, IconBase64 = iconb64 }; string route = "/guilds/templates/:template_code"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { template_code }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); JObject jObject = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); JArray rawMembers = (JArray)jObject["members"]; DiscordGuild guild = jObject.ToDiscordObject(); if (_discord is DiscordClient discordClient) { await discordClient.OnGuildCreateEventAsync(guild, rawMembers, null).ConfigureAwait(continueOnCapturedContext: false); } return guild; } internal async Task DeleteGuildAsync(ulong guild_id) { string route = "/guilds/:guild_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route).ConfigureAwait(continueOnCapturedContext: false); } internal async Task ModifyGuildAsync(ulong guildId, Optional name, Optional region, Optional verificationLevel, Optional defaultMessageNotifications, Optional mfaLevel, Optional explicitContentFilter, Optional afkChannelId, Optional afkTimeout, Optional iconb64, Optional ownerId, Optional splashb64, Optional systemChannelId, Optional banner, Optional description, Optional discoverySplash, Optional> features, Optional preferredLocale, Optional publicUpdatesChannelId, Optional rulesChannelId, Optional systemChannelFlags, string reason) { RestGuildModifyPayload value = new RestGuildModifyPayload { Name = name, RegionId = region, VerificationLevel = verificationLevel, DefaultMessageNotifications = defaultMessageNotifications, MfaLevel = mfaLevel, ExplicitContentFilter = explicitContentFilter, AfkChannelId = afkChannelId, AfkTimeout = afkTimeout, IconBase64 = iconb64, SplashBase64 = splashb64, OwnerId = ownerId, SystemChannelId = systemChannelId, Banner = banner, Description = description, DiscoverySplash = discoverySplash, Features = features, PreferredLocale = preferredLocale, PublicUpdatesChannelId = publicUpdatesChannelId, RulesChannelId = rulesChannelId, SystemChannelFlags = systemChannelFlags }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id = guildId }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); JObject jObject = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); JArray rawMembers = (JArray)jObject["members"]; DiscordGuild guild = jObject.ToDiscordObject(); foreach (DiscordRole value2 in guild._roles.Values) { value2._guild_id = guild.Id; } if (_discord is DiscordClient discordClient) { await discordClient.OnGuildUpdateEventAsync(guild, rawMembers).ConfigureAwait(continueOnCapturedContext: false); } return guild; } internal async Task> GetGuildBansAsync(ulong guild_id, int? limit, ulong? before, ulong? after) { string route = "/guilds/:guild_id/bans"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Dictionary dictionary = new Dictionary(); if (limit.HasValue) { dictionary["limit"] = limit.ToString(); } if (before.HasValue) { dictionary["before"] = before.ToString(); } if (after.HasValue) { dictionary["after"] = after.ToString(); } Uri apiUriFor = Utilities.GetApiUriFor(url, BuildQueryString(dictionary)); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).Select(delegate(DiscordBan xb) { if (!_discord.TryGetCachedUserInternal(xb.RawUser.Id, out var user)) { user = new DiscordUser(xb.RawUser) { Discord = _discord }; user = _discord.UpdateUserCache(user); } xb.User = user; return xb; }))); } internal Task CreateGuildBanAsync(ulong guild_id, ulong user_id, int delete_message_days, string reason) { if (delete_message_days < 0 || delete_message_days > 7) { throw new ArgumentException("Delete message days must be a number between 0 and 7.", "delete_message_days"); } Dictionary values = new Dictionary { ["delete_message_days"] = delete_message_days.ToString(CultureInfo.InvariantCulture) }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/bans/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { guild_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, BuildQueryString(values)); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route, baseHeaders); } internal Task RemoveGuildBanAsync(ulong guild_id, ulong user_id, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/bans/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, baseHeaders); } internal Task LeaveGuildAsync(ulong guild_id) { string route = "/users/@me/guilds/:guild_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route); } internal async Task AddGuildMemberAsync(ulong guild_id, ulong user_id, string access_token, string nick, IEnumerable roles, bool muted, bool deafened) { RestGuildMemberAddPayload value = new RestGuildMemberAddPayload { AccessToken = access_token, Nickname = (nick ?? ""), Roles = (roles ?? new List()), Deaf = deafened, Mute = muted }; string route = "/guilds/:guild_id/members/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { guild_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new DiscordMember(JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response)) { Discord = _discord, _guild_id = guild_id }; } internal async Task> ListGuildMembersAsync(ulong guild_id, int? limit, ulong? after) { Dictionary dictionary = new Dictionary(); if (limit.HasValue && limit > 0) { dictionary["limit"] = limit.Value.ToString(CultureInfo.InvariantCulture); } if (after.HasValue) { dictionary["after"] = after.Value.ToString(CultureInfo.InvariantCulture); } string route = "/guilds/:guild_id/members"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, dictionary.Any() ? BuildQueryString(dictionary) : ""); return new ReadOnlyCollection(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response)); } internal Task AddGuildMemberRoleAsync(ulong guild_id, ulong user_id, ulong role_id, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/members/:user_id/roles/:role_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { guild_id, user_id, role_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route, baseHeaders); } internal Task RemoveGuildMemberRoleAsync(ulong guild_id, ulong user_id, ulong role_id, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/members/:user_id/roles/:role_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id, user_id, role_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, baseHeaders); } internal Task ModifyGuildChannelPositionAsync(ulong guild_id, IEnumerable pld, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/channels"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(pld)); } internal Task ModifyGuildRolePositionAsync(ulong guild_id, IEnumerable pld, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/roles"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(pld)); } internal async Task ModifyGuildRolePositionsAsync(ulong guild_id, IEnumerable newRolePositions, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/roles"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordRole[] array = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(newRolePositions)).ConfigureAwait(continueOnCapturedContext: false)).Response); DiscordRole[] array2 = array; foreach (DiscordRole obj in array2) { obj.Discord = _discord; obj._guild_id = guild_id; } return array; } internal async Task GetAuditLogsAsync(ulong guild_id, int limit, ulong? after, ulong? before, ulong? responsible, int? action_type) { Dictionary dictionary = new Dictionary { ["limit"] = limit.ToString(CultureInfo.InvariantCulture) }; if (after.HasValue) { dictionary["after"] = after?.ToString(CultureInfo.InvariantCulture); } if (before.HasValue) { dictionary["before"] = before?.ToString(CultureInfo.InvariantCulture); } if (responsible.HasValue) { dictionary["user_id"] = responsible?.ToString(CultureInfo.InvariantCulture); } if (action_type.HasValue) { dictionary["action_type"] = action_type?.ToString(CultureInfo.InvariantCulture); } string route = "/guilds/:guild_id/audit-logs"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, dictionary.Any() ? BuildQueryString(dictionary) : ""); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task GetGuildVanityUrlAsync(ulong guild_id) { string route = "/guilds/:guild_id/vanity-url"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task GetGuildWidgetAsync(ulong guild_id) { string route = "/guilds/:guild_id/widget.json"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); JObject jObject = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); JArray source = (JArray)jObject["channels"]; DiscordWidget ret = jObject.ToDiscordObject(); ret.Discord = _discord; ret.Guild = _discord.Guilds[guild_id]; ret.Channels = ((ret.Guild == null) ? source.Select((JToken r) => new DiscordChannel { Id = (ulong)r["id"], Name = r["name"].ToString(), Position = (int)r["position"] }).ToList() : source.Select(delegate(JToken r) { DiscordChannel channel = ret.Guild.GetChannel((ulong)r["id"]); channel.Position = (int)r["position"]; return channel; }).ToList()); return ret; } internal async Task GetGuildWidgetSettingsAsync(ulong guild_id) { string route = "/guilds/:guild_id/widget"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordWidgetSettings? discordWidgetSettings = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordWidgetSettings.Guild = _discord.Guilds[guild_id]; return discordWidgetSettings; } internal async Task ModifyGuildWidgetSettingsAsync(ulong guild_id, bool? isEnabled, ulong? channelId, string reason) { RestGuildWidgetSettingsPayload value = new RestGuildWidgetSettingsPayload { Enabled = isEnabled, ChannelId = channelId }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/widget"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordWidgetSettings? discordWidgetSettings = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordWidgetSettings.Guild = _discord.Guilds[guild_id]; return discordWidgetSettings; } internal async Task> GetGuildTemplatesAsync(ulong guild_id) { string route = "/guilds/:guild_id/templates"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response))); } internal async Task CreateGuildTemplateAsync(ulong guild_id, string name, string description) { RestGuildTemplateCreateOrModifyPayload value = new RestGuildTemplateCreateOrModifyPayload { Name = name, Description = description }; string route = "/guilds/:guild_id/templates"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task SyncGuildTemplateAsync(ulong guild_id, string template_code) { string route = "/guilds/:guild_id/templates/:template_code"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { guild_id, template_code }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task ModifyGuildTemplateAsync(ulong guild_id, string template_code, string name, string description) { RestGuildTemplateCreateOrModifyPayload value = new RestGuildTemplateCreateOrModifyPayload { Name = name, Description = description }; string route = "/guilds/:guild_id/templates/:template_code"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id, template_code }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task DeleteGuildTemplateAsync(ulong guild_id, string template_code) { string route = "/guilds/:guild_id/templates/:template_code"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id, template_code }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task GetGuildMembershipScreeningFormAsync(ulong guild_id) { string route = "/guilds/:guild_id/member-verification"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task ModifyGuildMembershipScreeningFormAsync(ulong guild_id, Optional enabled, Optional fields, Optional description) { RestGuildMembershipScreeningFormModifyPayload value = new RestGuildMembershipScreeningFormModifyPayload { Enabled = enabled, Description = description, Fields = fields }; string route = "/guilds/:guild_id/member-verification"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task GetGuildWelcomeScreenAsync(ulong guild_id) { string route = "/guilds/:guild_id/welcome-screen"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task ModifyGuildWelcomeScreenAsync(ulong guild_id, Optional enabled, Optional> welcomeChannels, Optional description, string reason) { RestGuildWelcomeScreenModifyPayload value = new RestGuildWelcomeScreenModifyPayload { Enabled = enabled, WelcomeChannels = welcomeChannels, Description = description }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/welcome-screen"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task UpdateCurrentUserVoiceStateAsync(ulong guild_id, ulong channelId, bool? suppress, DateTimeOffset? requestToSpeakTimestamp) { RestGuildUpdateCurrentUserVoiceStatePayload value = new RestGuildUpdateCurrentUserVoiceStatePayload { ChannelId = channelId, Suppress = suppress, RequestToSpeakTimestamp = requestToSpeakTimestamp }; string route = "/guilds/:guild_id/voice-states/@me"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false); } internal async Task UpdateUserVoiceStateAsync(ulong guild_id, ulong user_id, ulong channelId, bool? suppress) { RestGuildUpdateUserVoiceStatePayload value = new RestGuildUpdateUserVoiceStatePayload { ChannelId = channelId, Suppress = suppress }; string route = "/guilds/:guild_id/voice-states/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false); } internal async Task GetGuildStickerAsync(ulong guild_id, ulong sticker_id) { string route = "/guilds/:guild_id/stickers/:sticker_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id, sticker_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); JObject jObject = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); DiscordMessageSticker discordMessageSticker = jObject.ToDiscordObject(); if (jObject["user"] is JObject token) { DiscordUser user = new DiscordUser(token.ToDiscordObject()) { Discord = _discord }; discordMessageSticker.User = user; } discordMessageSticker.Discord = _discord; return discordMessageSticker; } internal async Task GetStickerAsync(ulong sticker_id) { string route = "/stickers/:sticker_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { sticker_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); JObject jObject = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); DiscordMessageSticker discordMessageSticker = jObject.ToDiscordObject(); if (jObject["user"] is JObject token) { DiscordUser user = new DiscordUser(token.ToDiscordObject()) { Discord = _discord }; discordMessageSticker.User = user; } discordMessageSticker.Discord = _discord; return discordMessageSticker; } internal async Task> GetStickerPacksAsync() { string route = "/sticker-packs"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return (JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response)["sticker_packs"] as JArray).ToDiscordObject(); } internal async Task> GetGuildStickersAsync(ulong guild_id) { string route = "/guilds/:guild_id/stickers"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); JArray jArray = JArray.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); DiscordMessageSticker[] array = jArray.ToDiscordObject(); for (int i = 0; i < array.Length; i++) { DiscordMessageSticker discordMessageSticker = array[i]; discordMessageSticker.Discord = _discord; if (jArray[i]["user"] is JObject token) { DiscordUser user = new DiscordUser(token.ToDiscordObject()) { Discord = _discord }; discordMessageSticker.User = user; } } return array; } internal async Task CreateGuildStickerAsync(ulong guild_id, string name, string description, string tags, DiscordMessageFile file, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/stickers"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); if (!string.IsNullOrEmpty(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } Dictionary values = new Dictionary { ["name"] = name, ["description"] = description, ["tags"] = tags }; JObject jObject = JObject.Parse((await DoMultipartAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, baseHeaders, values, (IReadOnlyCollection)(object)new DiscordMessageFile[1] { file }, null, removeFileCount: true).ConfigureAwait(continueOnCapturedContext: false)).Response); DiscordMessageSticker discordMessageSticker = jObject.ToDiscordObject(); if (jObject["user"] is JObject token) { DiscordUser user = new DiscordUser(token.ToDiscordObject()) { Discord = _discord }; discordMessageSticker.User = user; } discordMessageSticker.Discord = _discord; return discordMessageSticker; } internal async Task ModifyStickerAsync(ulong guild_id, ulong sticker_id, Optional name, Optional description, Optional tags, string reason) { Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/stickers/:sticker_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id, sticker_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); RestStickerModifyPayload value = new RestStickerModifyPayload { Name = name, Description = description, Tags = tags }; DiscordMessageSticker discordMessageSticker = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, dictionary, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response).ToDiscordObject(); discordMessageSticker.Discord = _discord; return discordMessageSticker; } internal async Task DeleteStickerAsync(ulong guild_id, ulong sticker_id, string reason) { Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/stickers/:sticker_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id, sticker_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, dictionary).ConfigureAwait(continueOnCapturedContext: false); } internal async Task CreateGuildChannelAsync(ulong guild_id, string name, ChannelType type, ulong? parent, Optional topic, int? bitrate, int? user_limit, IEnumerable overwrites, bool? nsfw, Optional perUserRateLimit, VideoQualityMode? qualityMode, int? position, string reason, AutoArchiveDuration? defaultAutoArchiveDuration, DefaultReaction? defaultReactionEmoji, IEnumerable forumTags, DefaultSortOrder? defaultSortOrder) { List list = new List(); if (overwrites != null) { foreach (DiscordOverwriteBuilder overwrite in overwrites) { list.Add(overwrite.Build()); } } RestChannelCreatePayload value = new RestChannelCreatePayload { Name = name, Type = type, Parent = parent, Topic = topic, Bitrate = bitrate, UserLimit = user_limit, PermissionOverwrites = list, Nsfw = nsfw, PerUserRateLimit = perUserRateLimit, QualityMode = qualityMode, Position = position, DefaultAutoArchiveDuration = defaultAutoArchiveDuration, DefaultReaction = defaultReactionEmoji, AvailableTags = forumTags, DefaultSortOrder = defaultSortOrder }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/channels"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordChannel discordChannel = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordChannel.Discord = _discord; foreach (DiscordOverwrite permissionOverwrite in discordChannel._permissionOverwrites) { permissionOverwrite.Discord = _discord; permissionOverwrite._channel_id = discordChannel.Id; } return discordChannel; } internal Task ModifyChannelAsync(ulong channel_id, string name, int? position, Optional topic, bool? nsfw, Optional parent, int? bitrate, int? user_limit, Optional perUserRateLimit, Optional rtcRegion, VideoQualityMode? qualityMode, Optional type, IEnumerable permissionOverwrites, string reason, Optional flags, IEnumerable? availableTags, Optional defaultAutoArchiveDuration, Optional defaultReactionEmoji, Optional defaultPerUserRatelimit, Optional defaultSortOrder, Optional defaultForumLayout) { List list = null; if (permissionOverwrites != null) { list = new List(); foreach (DiscordOverwriteBuilder permissionOverwrite in permissionOverwrites) { list.Add(permissionOverwrite.Build()); } } RestChannelModifyPayload value = new RestChannelModifyPayload { Name = name, Position = position, Topic = topic, Nsfw = nsfw, Parent = parent, Bitrate = bitrate, UserLimit = user_limit, PerUserRateLimit = perUserRateLimit, RtcRegion = rtcRegion, QualityMode = qualityMode, Type = type, PermissionOverwrites = list, Flags = flags, AvailableTags = availableTags, DefaultAutoArchiveDuration = defaultAutoArchiveDuration, DefaultReaction = defaultReactionEmoji, DefaultForumLayout = defaultForumLayout, DefaultSortOrder = defaultSortOrder }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/channels/:channel_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)); } internal Task ModifyThreadChannelAsync(ulong channel_id, string name, int? position, Optional topic, bool? nsfw, Optional parent, int? bitrate, int? user_limit, Optional perUserRateLimit, Optional rtcRegion, VideoQualityMode? qualityMode, Optional type, IEnumerable permissionOverwrites, bool? isArchived, AutoArchiveDuration? autoArchiveDuration, bool? locked, string reason, IEnumerable applied_tags) { List list = null; if (permissionOverwrites != null) { list = new List(); foreach (DiscordOverwriteBuilder permissionOverwrite in permissionOverwrites) { list.Add(permissionOverwrite.Build()); } } RestThreadChannelModifyPayload value = new RestThreadChannelModifyPayload { Name = name, Position = position, Topic = topic, Nsfw = nsfw, Parent = parent, Bitrate = bitrate, UserLimit = user_limit, PerUserRateLimit = perUserRateLimit, RtcRegion = rtcRegion, QualityMode = qualityMode, Type = type, PermissionOverwrites = list, IsArchived = isArchived, ArchiveDuration = autoArchiveDuration, Locked = locked, AppliedTags = applied_tags }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders.Add("X-Audit-Log-Reason", reason); } string route = "/channels/:channel_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)); } internal async Task> GetScheduledGuildEventsAsync(ulong guild_id, bool with_user_counts = false) { string route = "/guilds/:guild_id/scheduled-events"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Dictionary values = new Dictionary { { "with_user_count", with_user_counts.ToString() } }; Uri apiUriFor = Utilities.GetApiUriFor(url, BuildQueryString(values)); List list = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route, new Dictionary(), string.Empty).ConfigureAwait(continueOnCapturedContext: false)).Response).ToList(); foreach (DiscordScheduledGuildEvent item in list) { item.Discord = _discord; if (item.Creator != null) { item.Creator.Discord = _discord; } } return list.AsReadOnly(); } internal async Task CreateScheduledGuildEventAsync(ulong guild_id, string name, string description, ulong? channel_id, DateTimeOffset start_time, DateTimeOffset? end_time, ScheduledGuildEventType type, ScheduledGuildEventPrivacyLevel privacy_level, DiscordScheduledGuildEventMetadata metadata, string reason = null) { string route = "/guilds/:guild_id/scheduled-events"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { guild_id }, out url); Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } Uri apiUriFor = Utilities.GetApiUriFor(url); RestScheduledGuildEventCreatePayload value = new RestScheduledGuildEventCreatePayload { Name = name, Description = description, ChannelId = channel_id, StartTime = start_time, EndTime = end_time, Type = type, PrivacyLevel = privacy_level, Metadata = metadata }; DiscordScheduledGuildEvent discordScheduledGuildEvent = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordScheduledGuildEvent.Discord = _discord; if (discordScheduledGuildEvent.Creator != null) { discordScheduledGuildEvent.Creator.Discord = _discord; } return discordScheduledGuildEvent; } internal async Task DeleteScheduledGuildEventAsync(ulong guild_id, ulong guild_scheduled_event_id) { string route = "/guilds/:guild_id/scheduled-events/:guild_scheduled_event_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id, guild_scheduled_event_id }, out url); Dictionary baseHeaders = Utilities.GetBaseHeaders(); Uri apiUriFor = Utilities.GetApiUriFor(url); await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, baseHeaders).ConfigureAwait(continueOnCapturedContext: false); } internal async Task> GetScheduledGuildEventUsersAsync(ulong guild_id, ulong guild_scheduled_event_id, bool with_members = false, int limit = 1, ulong? before = null, ulong? after = null) { string route = "/guilds/:guild_id/scheduled-events/:guild_scheduled_event_id/users"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id, guild_scheduled_event_id }, out url); Dictionary dictionary = new Dictionary { { "with_members", with_members.ToString() } }; if (limit > 0) { dictionary.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); } if (before.HasValue) { dictionary.Add("before", before.Value.ToString(CultureInfo.InvariantCulture)); } if (after.HasValue) { dictionary.Add("after", after.Value.ToString(CultureInfo.InvariantCulture)); } Uri apiUriFor = Utilities.GetApiUriFor(url, BuildQueryString(dictionary)); JToken jToken = JToken.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route, new Dictionary(), string.Empty).ConfigureAwait(continueOnCapturedContext: false)).Response); return ((jToken as JArray) ?? (jToken["users"] as JArray)).Select((JToken j) => j.SelectToken("member")?.ToDiscordObject() ?? j.SelectToken("user").ToDiscordObject()).ToArray(); } internal async Task GetScheduledGuildEventAsync(ulong guild_id, ulong guild_scheduled_event_id) { string route = "/guilds/:guild_id/scheduled-events/:guild_scheduled_event_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id, guild_scheduled_event_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordScheduledGuildEvent discordScheduledGuildEvent = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route, Utilities.GetBaseHeaders(), string.Empty).ConfigureAwait(continueOnCapturedContext: false)).Response); discordScheduledGuildEvent.Discord = _discord; if (discordScheduledGuildEvent.Creator != null) { discordScheduledGuildEvent.Creator.Discord = _discord; } return discordScheduledGuildEvent; } internal async Task ModifyScheduledGuildEventAsync(ulong guild_id, ulong guild_scheduled_event_id, Optional name, Optional description, Optional channel_id, Optional start_time, Optional end_time, Optional type, Optional privacy_level, Optional metadata, Optional status, string reason = null) { string route = "/guilds/:guild_id/scheduled-events/:guild_scheduled_event_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id, guild_scheduled_event_id }, out url); Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } Uri apiUriFor = Utilities.GetApiUriFor(url); RestScheduledGuildEventModifyPayload value = new RestScheduledGuildEventModifyPayload { Name = name, Description = description, ChannelId = channel_id, StartTime = start_time, EndTime = end_time, Type = type, PrivacyLevel = privacy_level, Metadata = metadata, Status = status }; DiscordScheduledGuildEvent discordScheduledGuildEvent = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordScheduledGuildEvent.Discord = _discord; if (discordScheduledGuildEvent.Creator != null) { discordScheduledGuildEvent.Creator.Discord = _discord; } return discordScheduledGuildEvent; } internal async Task GetChannelAsync(ulong channel_id) { string route = "/channels/:channel_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); RestResponse restResponse = await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false); DiscordChannel discordChannel = JsonConvert.DeserializeObject(restResponse.Response); if (discordChannel.IsThread) { discordChannel = JsonConvert.DeserializeObject(restResponse.Response); } discordChannel.Discord = _discord; foreach (DiscordOverwrite permissionOverwrite in discordChannel._permissionOverwrites) { permissionOverwrite.Discord = _discord; permissionOverwrite._channel_id = discordChannel.Id; } return discordChannel; } internal Task DeleteChannelAsync(ulong channel_id, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/channels/:channel_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, baseHeaders); } internal async Task GetMessageAsync(ulong channel_id, ulong message_id) { string route = "/channels/:channel_id/messages/:message_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { channel_id, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return PrepareMessage(JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response)); } internal async Task CreateMessageAsync(ulong channel_id, string content, IEnumerable embeds, ulong? replyMessageId, bool mentionReply, bool failOnInvalidReply, bool suppressNotifications) { if (content != null && content.Length > 2000) { throw new ArgumentException("Message content length cannot exceed 2000 characters."); } if (embeds == null || !embeds.Any()) { if (content == null) { throw new ArgumentException("You must specify message content or an embed."); } if (content.Length == 0) { throw new ArgumentException("Message content must not be empty."); } } if (embeds != null) { foreach (DiscordEmbed embed in embeds) { if (embed.Timestamp.HasValue) { embed.Timestamp = embed.Timestamp.Value.ToUniversalTime(); } } } RestChannelMessageCreatePayload restChannelMessageCreatePayload = new RestChannelMessageCreatePayload { HasContent = (content != null), Content = content, IsTTS = false, HasEmbed = (embeds?.Any() ?? false), Embeds = embeds, Flags = (suppressNotifications ? MessageFlags.SupressNotifications : ((MessageFlags)0)) }; if (replyMessageId.HasValue) { restChannelMessageCreatePayload.MessageReference = new InternalDiscordMessageReference { MessageId = replyMessageId, FailIfNotExists = failOnInvalidReply }; } if (replyMessageId.HasValue) { restChannelMessageCreatePayload.Mentions = new DiscordMentions(Mentions.All, mention: true, mentionReply); } string route = "/channels/:channel_id/messages"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return PrepareMessage(JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(restChannelMessageCreatePayload)).ConfigureAwait(continueOnCapturedContext: false)).Response)); } internal async Task CreateMessageAsync(ulong channel_id, DiscordMessageBuilder builder) { builder.Validate(); if (builder.Embeds != null) { foreach (DiscordEmbed embed in builder.Embeds) { if (embed != null && embed.Timestamp.HasValue) { embed.Timestamp = embed.Timestamp.Value.ToUniversalTime(); } } } RestChannelMessageCreatePayload restChannelMessageCreatePayload = new RestChannelMessageCreatePayload { HasContent = (builder.Content != null), Content = builder.Content, StickersIds = (from s in builder._stickers?.Where((DiscordMessageSticker s) => s != null) select s.Id).ToArray(), IsTTS = builder.IsTTS, HasEmbed = (builder.Embeds != null), Embeds = builder.Embeds, Components = builder.Components }; if (builder.ReplyId.HasValue) { restChannelMessageCreatePayload.MessageReference = new InternalDiscordMessageReference { MessageId = builder.ReplyId, FailIfNotExists = builder.FailOnInvalidReply }; } IEnumerable mentions = builder.Mentions; restChannelMessageCreatePayload.Mentions = new DiscordMentions(mentions ?? Mentions.None, builder.Mentions?.Any() ?? false, builder.MentionOnReply); if (builder.Files.Count == 0) { string route = "/channels/:channel_id/messages"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return PrepareMessage(JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(restChannelMessageCreatePayload)).ConfigureAwait(continueOnCapturedContext: false)).Response)); } Dictionary values = new Dictionary { ["payload_json"] = DiscordJson.SerializeObject(restChannelMessageCreatePayload) }; string route2 = "/channels/:channel_id/messages"; string url2; RateLimitBucket bucket2 = _rest.GetBucket(RestRequestMethod.POST, route2, new { channel_id }, out url2); Uri apiUriFor2 = Utilities.GetApiUriFor(url2); DiscordMessage result = PrepareMessage(JObject.Parse((await DoMultipartAsync(_discord, bucket2, apiUriFor2, RestRequestMethod.POST, route2, null, values, builder.Files).ConfigureAwait(continueOnCapturedContext: false)).Response)); foreach (DiscordMessageFile item in builder._files.Where((DiscordMessageFile x) => x.ResetPositionTo.HasValue)) { item.Stream.Position = item.ResetPositionTo.Value; } return result; } internal async Task> GetGuildChannelsAsync(ulong guild_id) { string route = "/guilds/:guild_id/channels"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); IEnumerable enumerable = JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).Select(delegate(DiscordChannel xc) { xc.Discord = _discord; return xc; }); foreach (DiscordChannel item in enumerable) { foreach (DiscordOverwrite permissionOverwrite in item._permissionOverwrites) { permissionOverwrite.Discord = _discord; permissionOverwrite._channel_id = item.Id; } } return new ReadOnlyCollection(new List(enumerable)); } internal async Task> GetChannelMessagesAsync(ulong channel_id, int limit, ulong? before, ulong? after, ulong? around) { Dictionary dictionary = new Dictionary(); if (around.HasValue) { dictionary["around"] = around?.ToString(CultureInfo.InvariantCulture); } if (before.HasValue) { dictionary["before"] = before?.ToString(CultureInfo.InvariantCulture); } if (after.HasValue) { dictionary["after"] = after?.ToString(CultureInfo.InvariantCulture); } if (limit > 0) { dictionary["limit"] = limit.ToString(CultureInfo.InvariantCulture); } string route = "/channels/:channel_id/messages"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, dictionary.Any() ? BuildQueryString(dictionary) : ""); JArray jArray = JArray.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); List list = new List(); foreach (JToken item in jArray) { list.Add(PrepareMessage(item)); } return new ReadOnlyCollection(new List(list)); } internal async Task GetChannelMessageAsync(ulong channel_id, ulong message_id) { string route = "/channels/:channel_id/messages/:message_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { channel_id, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return PrepareMessage(JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response)); } internal async Task EditMessageAsync(ulong channel_id, ulong message_id, Optional content, Optional> embeds, Optional> mentions, IReadOnlyList components, IReadOnlyCollection files, MessageFlags? flags, IEnumerable attachments) { if (embeds.HasValue && embeds.Value != null) { foreach (DiscordEmbed item in embeds.Value) { if (item.Timestamp.HasValue) { item.Timestamp = item.Timestamp.Value.ToUniversalTime(); } } } RestChannelMessageEditPayload value = new RestChannelMessageEditPayload { HasContent = content.HasValue, Content = (content.HasValue ? ((string)content) : null), HasEmbed = (embeds.HasValue && (embeds.Value?.Any() ?? false)), Embeds = ((embeds.HasValue && (embeds.Value?.Any() ?? false)) ? embeds.Value : null), Components = components, Flags = flags, Attachments = attachments, Mentions = (mentions.HasValue ? new DiscordMentions(mentions.Value ?? Mentions.None, mention: false, mentions.Value?.OfType().Any() ?? false) : null) }; Dictionary values = new Dictionary { ["payload_json"] = DiscordJson.SerializeObject(value) }; string route = "/channels/:channel_id/messages/:message_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { channel_id, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordMessage result = PrepareMessage(JObject.Parse((await DoMultipartAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, null, values, files).ConfigureAwait(continueOnCapturedContext: false)).Response)); foreach (DiscordMessageFile item2 in files.Where((DiscordMessageFile x) => x.ResetPositionTo.HasValue)) { item2.Stream.Position = item2.ResetPositionTo.Value; } return result; } internal Task DeleteMessageAsync(ulong channel_id, ulong message_id, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/channels/:channel_id/messages/:message_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { channel_id, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, baseHeaders); } internal Task DeleteMessagesAsync(ulong channel_id, IEnumerable message_ids, string reason) { RestChannelMessageBulkDeletePayload value = new RestChannelMessageBulkDeletePayload { Messages = message_ids }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/channels/:channel_id/messages/bulk-delete"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, baseHeaders, DiscordJson.SerializeObject(value)); } internal async Task> GetChannelInvitesAsync(ulong channel_id) { string route = "/channels/:channel_id/invites"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).Select(delegate(DiscordInvite xi) { xi.Discord = _discord; return xi; }))); } internal async Task CreateChannelInviteAsync(ulong channel_id, int max_age, int max_uses, bool temporary, bool unique, string reason, InviteTargetType? targetType, ulong? targetUserId, ulong? targetApplicationId) { RestChannelInviteCreatePayload value = new RestChannelInviteCreatePayload { MaxAge = max_age, MaxUses = max_uses, Temporary = temporary, Unique = unique, TargetType = targetType, TargetUserId = targetUserId, TargetApplicationId = targetApplicationId }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/channels/:channel_id/invites"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordInvite? discordInvite = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordInvite.Discord = _discord; return discordInvite; } internal Task DeleteChannelPermissionAsync(ulong channel_id, ulong overwrite_id, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/channels/:channel_id/permissions/:overwrite_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { channel_id, overwrite_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, baseHeaders); } internal Task EditChannelPermissionsAsync(ulong channel_id, ulong overwrite_id, Permissions allow, Permissions deny, string type, string reason) { RestChannelPermissionEditPayload value = new RestChannelPermissionEditPayload { Type = type, Allow = (allow & PermissionMethods.FULL_PERMS), Deny = (deny & PermissionMethods.FULL_PERMS) }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/channels/:channel_id/permissions/:overwrite_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { channel_id, overwrite_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route, baseHeaders, DiscordJson.SerializeObject(value)); } internal Task TriggerTypingAsync(ulong channel_id) { string route = "/channels/:channel_id/typing"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route); } internal async Task> GetPinnedMessagesAsync(ulong channel_id) { string route = "/channels/:channel_id/pins"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); JArray jArray = JArray.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); List list = new List(); foreach (JToken item in jArray) { list.Add(PrepareMessage(item)); } return new ReadOnlyCollection(new List(list)); } internal Task PinMessageAsync(ulong channel_id, ulong message_id) { string route = "/channels/:channel_id/pins/:message_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { channel_id, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route); } internal Task UnpinMessageAsync(ulong channel_id, ulong message_id) { string route = "/channels/:channel_id/pins/:message_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { channel_id, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route); } internal Task AddGroupDmRecipientAsync(ulong channel_id, ulong user_id, string access_token, string nickname) { RestChannelGroupDmRecipientAddPayload value = new RestChannelGroupDmRecipientAddPayload { AccessToken = access_token, Nickname = nickname }; string route = "/users/@me/channels/:channel_id/recipients/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { channel_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route, null, DiscordJson.SerializeObject(value)); } internal Task RemoveGroupDmRecipientAsync(ulong channel_id, ulong user_id) { string route = "/users/@me/channels/:channel_id/recipients/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { channel_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route); } internal async Task CreateGroupDmAsync(IEnumerable access_tokens, IDictionary nicks) { RestUserGroupDmCreatePayload value = new RestUserGroupDmCreatePayload { AccessTokens = access_tokens, Nicknames = nicks }; string route = "/users/@me/channels"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordDmChannel? discordDmChannel = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordDmChannel.Discord = _discord; return discordDmChannel; } internal async Task CreateDmAsync(ulong recipient_id) { RestUserDmCreatePayload value = new RestUserDmCreatePayload { Recipient = recipient_id }; string route = "/users/@me/channels"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordDmChannel discordDmChannel = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordDmChannel.Discord = _discord; if (_discord is DiscordClient discordClient) { discordClient._privateChannels.TryAdd(discordDmChannel.Id, discordDmChannel); } return discordDmChannel; } internal async Task FollowChannelAsync(ulong channel_id, ulong webhook_channel_id) { FollowedChannelAddPayload value = new FollowedChannelAddPayload { WebhookChannelId = webhook_channel_id }; string route = "/channels/:channel_id/followers"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task CrosspostMessageAsync(ulong channel_id, ulong message_id) { string route = "/channels/:channel_id/messages/:message_id/crosspost"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task CreateStageInstanceAsync(ulong channelId, string topic, PrivacyLevel? privacyLevel, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } RestCreateStageInstancePayload value = new RestCreateStageInstancePayload { ChannelId = channelId, Topic = topic, PrivacyLevel = privacyLevel }; string route = "/stage-instances"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordStageInstance? discordStageInstance = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordStageInstance.Discord = _discord; return discordStageInstance; } internal async Task GetStageInstanceAsync(ulong channel_id) { string route = "/stage-instances/:channel_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordStageInstance? discordStageInstance = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordStageInstance.Discord = _discord; return discordStageInstance; } internal async Task ModifyStageInstanceAsync(ulong channel_id, Optional topic, Optional privacyLevel, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } RestModifyStageInstancePayload value = new RestModifyStageInstancePayload { Topic = topic, PrivacyLevel = privacyLevel }; string route = "/stage-instances/:channel_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordStageInstance? discordStageInstance = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordStageInstance.Discord = _discord; return discordStageInstance; } internal async Task BecomeStageInstanceSpeakerAsync(ulong guildId, ulong id, ulong? userId = null, DateTime? timestamp = null, bool? suppress = null) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); RestBecomeStageSpeakerInstancePayload value = new RestBecomeStageSpeakerInstancePayload { Suppress = suppress, ChannelId = id, RequestToSpeakTimestamp = timestamp }; string arg = userId?.ToString() ?? "@me"; string route = string.Format("/guilds/{0}{1}/{2}", guildId, "/voice-states", arg); string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false); } internal async Task DeleteStageInstanceAsync(ulong channel_id, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/stage-instances/:channel_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, baseHeaders).ConfigureAwait(continueOnCapturedContext: false); } internal async Task CreateThreadFromMessageAsync(ulong channel_id, ulong message_id, string name, AutoArchiveDuration archiveAfter, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } RestThreadCreatePayload value = new RestThreadCreatePayload { Name = name, ArchiveAfter = archiveAfter }; string route = "/channels/:channel_id/messages/:message_id/threads"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordThreadChannel? discordThreadChannel = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordThreadChannel.Discord = _discord; return discordThreadChannel; } internal async Task CreateThreadAsync(ulong channel_id, string name, AutoArchiveDuration archiveAfter, ChannelType type, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } RestThreadCreatePayload value = new RestThreadCreatePayload { Name = name, ArchiveAfter = archiveAfter, Type = type }; string route = "/channels/:channel_id/threads"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordThreadChannel? discordThreadChannel = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordThreadChannel.Discord = _discord; return discordThreadChannel; } internal Task JoinThreadAsync(ulong channel_id) { string route = "/channels/:channel_id/thread-members/@me"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route); } internal Task LeaveThreadAsync(ulong channel_id) { string route = "/channels/:channel_id/thread-members/@me"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route); } internal async Task GetThreadMemberAsync(ulong channel_id, ulong user_id) { string route = "/channels/:channel_id/thread-members/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal Task AddThreadMemberAsync(ulong channel_id, ulong user_id) { string route = "/channels/:channel_id/thread-members/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route); } internal Task RemoveThreadMemberAsync(ulong channel_id, ulong user_id) { string route = "/channels/:channel_id/thread-members/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route); } internal async Task> ListThreadMembersAsync(ulong channel_id) { string route = "/channels/:channel_id/thread-members"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response)); } internal async Task ListActiveThreadsAsync(ulong guild_id) { string route = "/guilds/:guild_id/threads/active "; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); ThreadQueryResult threadQueryResult = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); threadQueryResult.HasMore = false; foreach (DiscordThreadChannel thread in threadQueryResult.Threads) { thread.Discord = _discord; } foreach (DiscordThreadChannelMember member in threadQueryResult.Members) { member.Discord = _discord; member._guild_id = guild_id; DiscordThreadChannel discordThreadChannel = threadQueryResult.Threads.SingleOrDefault((DiscordThreadChannel x) => x.Id == member.ThreadId); if (discordThreadChannel != null) { discordThreadChannel.CurrentMember = member; } } return threadQueryResult; } internal async Task ListPublicArchivedThreadsAsync(ulong guild_id, ulong channel_id, string before, int limit) { Dictionary dictionary = new Dictionary(); if (before != null) { dictionary["before"] = before?.ToString(CultureInfo.InvariantCulture); } if (limit > 0) { dictionary["limit"] = limit.ToString(CultureInfo.InvariantCulture); } string route = "/channels/:channel_id/threads/archived/public"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, dictionary.Any() ? BuildQueryString(dictionary) : ""); ThreadQueryResult threadQueryResult = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordThreadChannel thread in threadQueryResult.Threads) { thread.Discord = _discord; } foreach (DiscordThreadChannelMember member in threadQueryResult.Members) { member.Discord = _discord; member._guild_id = guild_id; DiscordThreadChannel discordThreadChannel = threadQueryResult.Threads.SingleOrDefault((DiscordThreadChannel x) => x.Id == member.ThreadId); if (discordThreadChannel != null) { discordThreadChannel.CurrentMember = member; } } return threadQueryResult; } internal async Task ListPrivateArchivedThreadsAsync(ulong guild_id, ulong channel_id, string before, int limit) { Dictionary dictionary = new Dictionary(); if (before != null) { dictionary["before"] = before?.ToString(CultureInfo.InvariantCulture); } if (limit > 0) { dictionary["limit"] = limit.ToString(CultureInfo.InvariantCulture); } string route = "/channels/:channel_id/threads/archived/private"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, dictionary.Any() ? BuildQueryString(dictionary) : ""); ThreadQueryResult threadQueryResult = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordThreadChannel thread in threadQueryResult.Threads) { thread.Discord = _discord; } foreach (DiscordThreadChannelMember member in threadQueryResult.Members) { member.Discord = _discord; member._guild_id = guild_id; DiscordThreadChannel discordThreadChannel = threadQueryResult.Threads.SingleOrDefault((DiscordThreadChannel x) => x.Id == member.ThreadId); if (discordThreadChannel != null) { discordThreadChannel.CurrentMember = member; } } return threadQueryResult; } internal async Task ListJoinedPrivateArchivedThreadsAsync(ulong guild_id, ulong channel_id, ulong? before, int limit) { Dictionary dictionary = new Dictionary(); if (before.HasValue) { dictionary["before"] = before?.ToString(CultureInfo.InvariantCulture); } if (limit > 0) { dictionary["limit"] = limit.ToString(CultureInfo.InvariantCulture); } string route = "/channels/:channel_id/users/@me/threads/archived/public"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, dictionary.Any() ? BuildQueryString(dictionary) : ""); ThreadQueryResult threadQueryResult = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordThreadChannel thread in threadQueryResult.Threads) { thread.Discord = _discord; } foreach (DiscordThreadChannelMember member in threadQueryResult.Members) { member.Discord = _discord; member._guild_id = guild_id; DiscordThreadChannel discordThreadChannel = threadQueryResult.Threads.SingleOrDefault((DiscordThreadChannel x) => x.Id == member.ThreadId); if (discordThreadChannel != null) { discordThreadChannel.CurrentMember = member; } } return threadQueryResult; } internal Task GetCurrentUserAsync() { return GetUserAsync("@me"); } internal Task GetUserAsync(ulong user_id) { return GetUserAsync(user_id.ToString(CultureInfo.InvariantCulture)); } internal async Task GetUserAsync(string user_id) { string route = "/users/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new DiscordUser(JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response)) { Discord = _discord }; } internal async Task GetGuildMemberAsync(ulong guild_id, ulong user_id) { string route = "/guilds/:guild_id/members/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); TransportMember? transportMember = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); DiscordUser newUser = new DiscordUser(transportMember.User) { Discord = _discord }; _discord.UpdateUserCache(newUser); return new DiscordMember(transportMember) { Discord = _discord, _guild_id = guild_id }; } internal Task RemoveGuildMemberAsync(ulong guild_id, ulong user_id, string reason) { Dictionary dictionary = new Dictionary(); if (reason != null) { dictionary["reason"] = reason; } string route = "/guilds/:guild_id/members/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, BuildQueryString(dictionary)); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route); } internal async Task ModifyCurrentUserAsync(string username, Optional base64_avatar) { RestUserUpdateCurrentPayload value = new RestUserUpdateCurrentPayload { Username = username, AvatarBase64 = (base64_avatar.HasValue ? base64_avatar.Value : null), AvatarSet = base64_avatar.HasValue }; string route = "/users/@me"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task> GetCurrentUserGuildsAsync(int limit = 100, ulong? before = null, ulong? after = null) { string route = "/users/@me/guilds"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { }, out url); QueryUriBuilder queryUriBuilder = Utilities.GetApiUriBuilderFor(url).AddParameter("limit", limit.ToString(CultureInfo.InvariantCulture)); if (before.HasValue) { queryUriBuilder.AddParameter("before", before.Value.ToString(CultureInfo.InvariantCulture)); } if (after.HasValue) { queryUriBuilder.AddParameter("after", after.Value.ToString(CultureInfo.InvariantCulture)); } RestResponse restResponse = await DoRequestAsync(_discord, bucket, queryUriBuilder.Build(), RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false); if (_discord is DiscordClient) { return new ReadOnlyCollection(new List(from xug in JsonConvert.DeserializeObject>(restResponse.Response) select (_discord as DiscordClient)?._guilds[xug.Id])); } return new ReadOnlyCollection(JsonConvert.DeserializeObject>(restResponse.Response)); } internal Task ModifyGuildMemberAsync(ulong guild_id, ulong user_id, Optional nick, Optional> role_ids, Optional mute, Optional deaf, Optional voice_channel_id, Optional communication_disabled_until, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } RestGuildMemberModifyPayload value = new RestGuildMemberModifyPayload { Nickname = nick, RoleIds = role_ids, Deafen = deaf, Mute = mute, VoiceChannelId = voice_channel_id, CommunicationDisabledUntil = communication_disabled_until }; string route = "/guilds/:guild_id/members/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)); } internal Task ModifyCurrentMemberAsync(ulong guild_id, string nick, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } RestGuildMemberModifyPayload value = new RestGuildMemberModifyPayload { Nickname = nick }; string route = "/guilds/:guild_id/members/@me"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)); } internal async Task> GetGuildRolesAsync(ulong guild_id) { string route = "/guilds/:guild_id/roles"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).Select(delegate(DiscordRole xr) { xr.Discord = _discord; xr._guild_id = guild_id; return xr; }))); } internal async Task GetGuildAsync(ulong guildId, bool? with_counts) { Dictionary dictionary = new Dictionary(); if (with_counts.HasValue) { dictionary["with_counts"] = with_counts?.ToString(); } string route = "/guilds/:guild_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id = guildId }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, dictionary.Any() ? BuildQueryString(dictionary) : ""); JObject jObject = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route, dictionary).ConfigureAwait(continueOnCapturedContext: false)).Response); JArray rawMembers = (JArray)jObject["members"]; DiscordGuild guildRest = jObject.ToDiscordObject(); foreach (DiscordRole value in guildRest._roles.Values) { value._guild_id = guildRest.Id; } BaseDiscordClient discord = _discord; if (discord is DiscordClient dc) { await dc.OnGuildUpdateEventAsync(guildRest, rawMembers).ConfigureAwait(continueOnCapturedContext: false); return dc._guilds[guildRest.Id]; } guildRest.Discord = _discord; return guildRest; } internal async Task ModifyGuildRoleAsync(ulong guild_id, ulong role_id, string name, Permissions? permissions, int? color, bool? hoist, bool? mentionable, string reason, Stream icon, string emoji) { string icon2 = null; if (icon != null) { using ImageTool imageTool = new ImageTool(icon); icon2 = imageTool.GetBase64(); } RestGuildRolePayload value = new RestGuildRolePayload { Name = name, Permissions = (permissions & PermissionMethods.FULL_PERMS), Color = color, Hoist = hoist, Mentionable = mentionable, Emoji = emoji, Icon = icon2 }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/roles/:role_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id, role_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordRole? discordRole = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordRole.Discord = _discord; discordRole._guild_id = guild_id; return discordRole; } internal Task DeleteRoleAsync(ulong guild_id, ulong role_id, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/roles/:role_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id, role_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, baseHeaders); } internal async Task CreateGuildRoleAsync(ulong guild_id, string name, Permissions? permissions, int? color, bool? hoist, bool? mentionable, string reason, Stream icon, string emoji) { string icon2 = null; if (icon != null) { using ImageTool imageTool = new ImageTool(icon); icon2 = imageTool.GetBase64(); } RestGuildRolePayload value = new RestGuildRolePayload { Name = name, Permissions = (permissions & PermissionMethods.FULL_PERMS), Color = color, Hoist = hoist, Mentionable = mentionable, Emoji = emoji, Icon = icon2 }; Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/roles"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordRole? discordRole = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, baseHeaders, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordRole.Discord = _discord; discordRole._guild_id = guild_id; return discordRole; } internal async Task GetGuildPruneCountAsync(ulong guild_id, int days, IEnumerable include_roles) { if (days < 0 || days > 30) { throw new ArgumentException("Prune inactivity days must be a number between 0 and 30.", "days"); } Dictionary values = new Dictionary { ["days"] = days.ToString(CultureInfo.InvariantCulture) }; StringBuilder stringBuilder = new StringBuilder(); if (include_roles != null) { ulong[] array = include_roles.ToArray(); int num = array.Count(); for (int i = 0; i < num; i++) { stringBuilder.Append($"&include_roles={array[i]}"); } } string route = "/guilds/:guild_id/prune"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, $"{BuildQueryString(values)}{stringBuilder}"); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).Pruned.Value; } internal async Task BeginGuildPruneAsync(ulong guild_id, int days, bool compute_prune_count, IEnumerable include_roles, string reason) { if (days < 0 || days > 30) { throw new ArgumentException("Prune inactivity days must be a number between 0 and 30.", "days"); } Dictionary values = new Dictionary { ["days"] = days.ToString(CultureInfo.InvariantCulture), ["compute_prune_count"] = compute_prune_count.ToString() }; StringBuilder stringBuilder = new StringBuilder(); if (include_roles != null) { ulong[] array = include_roles.ToArray(); int num = array.Count(); for (int i = 0; i < num; i++) { stringBuilder.Append($"&include_roles={array[i]}"); } } Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/prune"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, $"{BuildQueryString(values)}{stringBuilder}"); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, baseHeaders).ConfigureAwait(continueOnCapturedContext: false)).Response).Pruned; } internal async Task GetTemplateAsync(string code) { string route = "/guilds/templates/:code"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { code }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task> GetGuildIntegrationsAsync(ulong guild_id) { string route = "/guilds/:guild_id/integrations"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).Select(delegate(DiscordIntegration xi) { xi.Discord = _discord; return xi; }))); } internal async Task GetGuildPreviewAsync(ulong guild_id) { string route = "/guilds/:guild_id/preview"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordGuildPreview? discordGuildPreview = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordGuildPreview.Discord = _discord; return discordGuildPreview; } internal async Task CreateGuildIntegrationAsync(ulong guild_id, string type, ulong id) { RestGuildIntegrationAttachPayload value = new RestGuildIntegrationAttachPayload { Type = type, Id = id }; string route = "/guilds/:guild_id/integrations"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordIntegration? discordIntegration = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordIntegration.Discord = _discord; return discordIntegration; } internal async Task ModifyGuildIntegrationAsync(ulong guild_id, ulong integration_id, int expire_behaviour, int expire_grace_period, bool enable_emoticons) { RestGuildIntegrationModifyPayload value = new RestGuildIntegrationModifyPayload { ExpireBehavior = expire_behaviour, ExpireGracePeriod = expire_grace_period, EnableEmoticons = enable_emoticons }; string route = "/guilds/:guild_id/integrations/:integration_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id, integration_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordIntegration? discordIntegration = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordIntegration.Discord = _discord; return discordIntegration; } internal Task DeleteGuildIntegrationAsync(ulong guild_id, DiscordIntegration integration, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/integrations/:integration_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id = guild_id, integration_id = integration.Id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, baseHeaders, DiscordJson.SerializeObject(integration)); } internal Task SyncGuildIntegrationAsync(ulong guild_id, ulong integration_id) { string route = "/guilds/:guild_id/integrations/:integration_id/sync"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { guild_id, integration_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route); } internal async Task> GetGuildVoiceRegionsAsync(ulong guild_id) { string route = "/guilds/:guild_id/regions"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response))); } internal async Task> GetGuildInvitesAsync(ulong guild_id) { string route = "/guilds/:guild_id/invites"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).Select(delegate(DiscordInvite xi) { xi.Discord = _discord; return xi; }))); } internal async Task GetInviteAsync(string invite_code, bool? with_counts, bool? with_expiration) { Dictionary dictionary = new Dictionary(); if (with_counts.HasValue) { dictionary["with_counts"] = with_counts?.ToString(); dictionary["with_expiration"] = with_expiration?.ToString(); } string route = "/invites/:invite_code"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { invite_code }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, dictionary.Any() ? BuildQueryString(dictionary) : ""); DiscordInvite? discordInvite = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordInvite.Discord = _discord; return discordInvite; } internal async Task DeleteInviteAsync(string invite_code, string reason) { Dictionary baseHeaders = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) { baseHeaders["X-Audit-Log-Reason"] = reason; } string route = "/invites/:invite_code"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { invite_code }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordInvite? discordInvite = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, baseHeaders).ConfigureAwait(continueOnCapturedContext: false)).Response); discordInvite.Discord = _discord; return discordInvite; } internal async Task> GetUsersConnectionsAsync() { string route = "/users/@me/connections"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).Select(delegate(DiscordConnection xc) { xc.Discord = _discord; return xc; }))); } internal async Task> ListVoiceRegionsAsync() { string route = "/voice/regions"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response))); } internal async Task CreateWebhookAsync(ulong channel_id, string name, Optional base64_avatar, string reason) { RestWebhookPayload value = new RestWebhookPayload { Name = name, AvatarBase64 = (base64_avatar.HasValue ? base64_avatar.Value : null), AvatarSet = base64_avatar.HasValue }; Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/channels/:channel_id/webhooks"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordWebhook? discordWebhook = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, dictionary, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordWebhook.Discord = _discord; discordWebhook.ApiClient = this; return discordWebhook; } internal async Task> GetChannelWebhooksAsync(ulong channel_id) { string route = "/channels/:channel_id/webhooks"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { channel_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).Select(delegate(DiscordWebhook xw) { xw.Discord = _discord; xw.ApiClient = this; return xw; }))); } internal async Task> GetGuildWebhooksAsync(ulong guild_id) { string route = "/guilds/:guild_id/webhooks"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return new ReadOnlyCollection(new List(JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response).Select(delegate(DiscordWebhook xw) { xw.Discord = _discord; xw.ApiClient = this; return xw; }))); } internal async Task GetWebhookAsync(ulong webhook_id) { string route = "/webhooks/:webhook_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { webhook_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordWebhook? discordWebhook = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordWebhook.Discord = _discord; discordWebhook.ApiClient = this; return discordWebhook; } internal async Task GetWebhookWithTokenAsync(ulong webhook_id, string webhook_token) { string route = "/webhooks/:webhook_id/:webhook_token"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { webhook_id, webhook_token }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordWebhook? discordWebhook = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordWebhook.Token = webhook_token; discordWebhook.Id = webhook_id; discordWebhook.Discord = _discord; discordWebhook.ApiClient = this; return discordWebhook; } internal async Task GetWebhookMessageAsync(ulong webhook_id, string webhook_token, ulong message_id) { string route = "/webhooks/:webhook_id/:webhook_token/messages/:message_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { webhook_id, webhook_token, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordMessage? discordMessage = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordMessage.Discord = _discord; return discordMessage; } internal async Task ModifyWebhookAsync(ulong webhook_id, ulong channelId, string name, Optional base64_avatar, string reason) { RestWebhookPayload value = new RestWebhookPayload { Name = name, AvatarBase64 = (base64_avatar.HasValue ? base64_avatar.Value : null), AvatarSet = base64_avatar.HasValue, ChannelId = channelId }; Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/webhooks/:webhook_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { webhook_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordWebhook? discordWebhook = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, dictionary, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordWebhook.Discord = _discord; discordWebhook.ApiClient = this; return discordWebhook; } internal async Task ModifyWebhookAsync(ulong webhook_id, string name, string base64_avatar, string webhook_token, string reason) { RestWebhookPayload value = new RestWebhookPayload { Name = name, AvatarBase64 = base64_avatar }; Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/webhooks/:webhook_id/:webhook_token"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { webhook_id, webhook_token }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordWebhook? discordWebhook = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, dictionary, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordWebhook.Discord = _discord; discordWebhook.ApiClient = this; return discordWebhook; } internal Task DeleteWebhookAsync(ulong webhook_id, string reason) { Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/webhooks/:webhook_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { webhook_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, dictionary); } internal Task DeleteWebhookAsync(ulong webhook_id, string webhook_token, string reason) { Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/webhooks/:webhook_id/:webhook_token"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { webhook_id, webhook_token }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, dictionary); } internal async Task ExecuteWebhookAsync(ulong webhook_id, string webhook_token, DiscordWebhookBuilder builder) { builder.Validate(); if (builder.Embeds != null) { foreach (DiscordEmbed embed in builder.Embeds) { if (embed.Timestamp.HasValue) { embed.Timestamp = embed.Timestamp.Value.ToUniversalTime(); } } } Dictionary dictionary = new Dictionary(); RestWebhookExecutePayload restWebhookExecutePayload = new RestWebhookExecutePayload { Content = builder.Content, Username = (builder.Username.HasValue ? builder.Username.Value : null), AvatarUrl = (builder.AvatarUrl.HasValue ? builder.AvatarUrl.Value : null), IsTTS = builder.IsTTS, Embeds = builder.Embeds, Components = builder.Components }; if (builder.Mentions != null) { restWebhookExecutePayload.Mentions = new DiscordMentions(builder.Mentions, builder.Mentions.Any()); } if (string.IsNullOrEmpty(builder.Content)) { IReadOnlyList embeds = builder.Embeds; if ((embeds == null || embeds.Count() <= 0) && !builder.IsTTS && builder.Mentions == null) { goto IL_01e9; } } dictionary["payload_json"] = DiscordJson.SerializeObject(restWebhookExecutePayload); goto IL_01e9; IL_01e9: string route = "/webhooks/:webhook_id/:webhook_token"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { webhook_id, webhook_token }, out url); Uri url2 = ((!builder.ThreadId.HasValue) ? Utilities.GetApiUriBuilderFor(url).AddParameter("wait", "true").Build() : Utilities.GetApiUriBuilderFor(url).AddParameter("wait", "true").AddParameter("thread_id", builder.ThreadId.ToString()) .Build()); DiscordMessage discordMessage = JsonConvert.DeserializeObject((await DoMultipartAsync(_discord, bucket, url2, RestRequestMethod.POST, route, null, dictionary, builder.Files).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordMessageFile item in builder.Files.Where((DiscordMessageFile x) => x.ResetPositionTo.HasValue)) { item.Stream.Position = item.ResetPositionTo.Value; } discordMessage.Discord = _discord; return discordMessage; } internal async Task ExecuteWebhookSlackAsync(ulong webhook_id, string webhook_token, string json_payload) { string route = "/webhooks/:webhook_id/:webhook_token/slack"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { webhook_id, webhook_token }, out url); Uri url2 = Utilities.GetApiUriBuilderFor(url).AddParameter("wait", "true").Build(); DiscordMessage? discordMessage = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, url2, RestRequestMethod.POST, route, null, json_payload).ConfigureAwait(continueOnCapturedContext: false)).Response); discordMessage.Discord = _discord; return discordMessage; } internal async Task ExecuteWebhookGithubAsync(ulong webhook_id, string webhook_token, string json_payload) { string route = "/webhooks/:webhook_id/:webhook_token/github"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { webhook_id, webhook_token }, out url); Uri url2 = Utilities.GetApiUriBuilderFor(url).AddParameter("wait", "true").Build(); DiscordMessage? discordMessage = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, url2, RestRequestMethod.POST, route, null, json_payload).ConfigureAwait(continueOnCapturedContext: false)).Response); discordMessage.Discord = _discord; return discordMessage; } internal async Task EditWebhookMessageAsync(ulong webhook_id, string webhook_token, string message_id, DiscordWebhookBuilder builder, IEnumerable attachments) { builder.Validate(isModify: true); DiscordMentions mentions = ((builder.Mentions != null) ? new DiscordMentions(builder.Mentions, builder.Mentions.Any()) : null); RestWebhookMessageEditPayload value = new RestWebhookMessageEditPayload { Content = builder.Content, Embeds = builder.Embeds, Mentions = mentions, Components = builder.Components, Attachments = attachments }; string route = "/webhooks/:webhook_id/:webhook_token/messages/:message_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { webhook_id, webhook_token, message_id }, out url); Dictionary values = new Dictionary { ["payload_json"] = DiscordJson.SerializeObject(value) }; Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordMessage discordMessage = JsonConvert.DeserializeObject((await DoMultipartAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, null, values, builder.Files).ConfigureAwait(continueOnCapturedContext: false)).Response); discordMessage.Discord = _discord; foreach (DiscordMessageFile item in builder.Files.Where((DiscordMessageFile x) => x.ResetPositionTo.HasValue)) { item.Stream.Position = item.ResetPositionTo.Value; } return discordMessage; } internal Task EditWebhookMessageAsync(ulong webhook_id, string webhook_token, ulong message_id, DiscordWebhookBuilder builder, IEnumerable attachments) { return EditWebhookMessageAsync(webhook_id, webhook_token, message_id.ToString(), builder, attachments); } internal async Task DeleteWebhookMessageAsync(ulong webhook_id, string webhook_token, string message_id) { string route = "/webhooks/:webhook_id/:webhook_token/messages/:message_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { webhook_id, webhook_token, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route).ConfigureAwait(continueOnCapturedContext: false); } internal Task DeleteWebhookMessageAsync(ulong webhook_id, string webhook_token, ulong message_id) { return DeleteWebhookMessageAsync(webhook_id, webhook_token, message_id.ToString()); } internal Task CreateReactionAsync(ulong channel_id, ulong message_id, string emoji) { string route = "/channels/:channel_id/messages/:message_id/reactions/:emoji/@me"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { channel_id, message_id, emoji }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route, null, null, _discord.Configuration.UseRelativeRatelimit ? null : new double?(0.26)); } internal Task DeleteOwnReactionAsync(ulong channel_id, ulong message_id, string emoji) { string route = "/channels/:channel_id/messages/:message_id/reactions/:emoji/@me"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { channel_id, message_id, emoji }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, null, null, _discord.Configuration.UseRelativeRatelimit ? null : new double?(0.26)); } internal Task DeleteUserReactionAsync(ulong channel_id, ulong message_id, ulong user_id, string emoji, string reason) { Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/channels/:channel_id/messages/:message_id/reactions/:emoji/:user_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { channel_id, message_id, emoji, user_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, dictionary, null, _discord.Configuration.UseRelativeRatelimit ? null : new double?(0.26)); } internal async Task> GetReactionsAsync(ulong channel_id, ulong message_id, string emoji, ulong? after_id = null, int limit = 25) { Dictionary dictionary = new Dictionary(); if (after_id.HasValue) { dictionary["after"] = after_id.Value.ToString(CultureInfo.InvariantCulture); } dictionary["limit"] = limit.ToString(CultureInfo.InvariantCulture); string route = "/channels/:channel_id/messages/:message_id/reactions/:emoji"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { channel_id, message_id, emoji }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url, BuildQueryString(dictionary)); IEnumerable? enumerable = JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); List list = new List(); using (IEnumerator enumerator = enumerable.GetEnumerator()) { while (enumerator.MoveNext()) { DiscordUser newUser = new DiscordUser(enumerator.Current) { Discord = _discord }; newUser = _discord.UpdateUserCache(newUser); list.Add(newUser); } } return new ReadOnlyCollection(new List(list)); } internal Task DeleteAllReactionsAsync(ulong channel_id, ulong message_id, string reason) { Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/channels/:channel_id/messages/:message_id/reactions"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { channel_id, message_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, dictionary, null, _discord.Configuration.UseRelativeRatelimit ? null : new double?(0.26)); } internal Task DeleteReactionsEmojiAsync(ulong channel_id, ulong message_id, string emoji) { string route = "/channels/:channel_id/messages/:message_id/reactions/:emoji"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { channel_id, message_id, emoji }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, null, null, _discord.Configuration.UseRelativeRatelimit ? null : new double?(0.26)); } internal async Task> GetGuildEmojisAsync(ulong guild_id) { string route = "/guilds/:guild_id/emojis"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); IEnumerable? enumerable = JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); _discord.Guilds.TryGetValue(guild_id, out var value); Dictionary dictionary = new Dictionary(); List list = new List(); foreach (JObject item in enumerable) { DiscordGuildEmoji discordGuildEmoji = item.ToDiscordObject(); discordGuildEmoji.Guild = value; TransportUser transportUser = item["user"]?.ToDiscordObject(); if (transportUser != null) { if (!dictionary.ContainsKey(transportUser.Id)) { DiscordMember value2; DiscordUser discordUser = ((value != null && value.Members.TryGetValue(transportUser.Id, out value2)) ? value2 : new DiscordUser(transportUser)); dictionary[discordUser.Id] = discordUser; } discordGuildEmoji.User = dictionary[transportUser.Id]; } list.Add(discordGuildEmoji); } return new ReadOnlyCollection(list); } internal async Task GetGuildEmojiAsync(ulong guild_id, ulong emoji_id) { string route = "/guilds/:guild_id/emojis/:emoji_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { guild_id, emoji_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); RestResponse obj = await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false); _discord.Guilds.TryGetValue(guild_id, out var value); JObject jObject = JObject.Parse(obj.Response); DiscordGuildEmoji discordGuildEmoji = jObject.ToDiscordObject(); discordGuildEmoji.Guild = value; TransportUser transportUser = jObject["user"]?.ToDiscordObject(); if (transportUser != null) { discordGuildEmoji.User = ((value != null && value.Members.TryGetValue(transportUser.Id, out var value2)) ? value2 : new DiscordUser(transportUser)); } return discordGuildEmoji; } internal async Task CreateGuildEmojiAsync(ulong guild_id, string name, string imageb64, IEnumerable roles, string reason) { RestGuildEmojiCreatePayload value = new RestGuildEmojiCreatePayload { Name = name, ImageB64 = imageb64, Roles = roles?.ToArray() }; Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/emojis"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); RestResponse obj = await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, dictionary, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false); _discord.Guilds.TryGetValue(guild_id, out var value2); JObject jObject = JObject.Parse(obj.Response); DiscordGuildEmoji discordGuildEmoji = jObject.ToDiscordObject(); discordGuildEmoji.Guild = value2; TransportUser transportUser = jObject["user"]?.ToDiscordObject(); discordGuildEmoji.User = ((transportUser == null) ? _discord.CurrentUser : ((value2 != null && value2.Members.TryGetValue(transportUser.Id, out var value3)) ? value3 : new DiscordUser(transportUser))); return discordGuildEmoji; } internal async Task ModifyGuildEmojiAsync(ulong guild_id, ulong emoji_id, string name, IEnumerable roles, string reason) { RestGuildEmojiModifyPayload value = new RestGuildEmojiModifyPayload { Name = name, Roles = roles?.ToArray() }; Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/emojis/:emoji_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { guild_id, emoji_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); RestResponse obj = await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, dictionary, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false); _discord.Guilds.TryGetValue(guild_id, out var value2); JObject jObject = JObject.Parse(obj.Response); DiscordGuildEmoji discordGuildEmoji = jObject.ToDiscordObject(); discordGuildEmoji.Guild = value2; TransportUser transportUser = jObject["user"]?.ToDiscordObject(); if (transportUser != null) { discordGuildEmoji.User = ((value2 != null && value2.Members.TryGetValue(transportUser.Id, out var value3)) ? value3 : new DiscordUser(transportUser)); } return discordGuildEmoji; } internal Task DeleteGuildEmojiAsync(ulong guild_id, ulong emoji_id, string reason) { Dictionary dictionary = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) { dictionary["X-Audit-Log-Reason"] = reason; } string route = "/guilds/:guild_id/emojis/:emoji_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { guild_id, emoji_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route, dictionary); } internal async Task> GetGlobalApplicationCommandsAsync(ulong application_id) { string route = "/applications/:application_id/commands"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { application_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); IEnumerable enumerable = JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordApplicationCommand item in enumerable) { item.Discord = _discord; } return enumerable.ToList(); } internal async Task> BulkOverwriteGlobalApplicationCommandsAsync(ulong application_id, IEnumerable commands) { List list = new List(); foreach (DiscordApplicationCommand command in commands) { list.Add(new RestApplicationCommandCreatePayload { Type = command.Type, Name = command.Name, Description = command.Description, Options = command.Options, DefaultPermission = command.DefaultPermission, NameLocalizations = command.NameLocalizations, DescriptionLocalizations = command.DescriptionLocalizations, AllowDMUsage = command.AllowDMUsage, DefaultMemberPermissions = command.DefaultMemberPermissions }); } string route = "/applications/:application_id/commands"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { application_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); IEnumerable enumerable = JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route, null, DiscordJson.SerializeObject(list)).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordApplicationCommand item in enumerable) { item.Discord = _discord; } return enumerable.ToList(); } internal async Task CreateGlobalApplicationCommandAsync(ulong application_id, DiscordApplicationCommand command) { RestApplicationCommandCreatePayload value = new RestApplicationCommandCreatePayload { Type = command.Type, Name = command.Name, Description = command.Description, Options = command.Options, DefaultPermission = command.DefaultPermission, NameLocalizations = command.NameLocalizations, DescriptionLocalizations = command.DescriptionLocalizations, AllowDMUsage = command.AllowDMUsage, DefaultMemberPermissions = command.DefaultMemberPermissions }; string route = "/applications/:application_id/commands"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { application_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordApplicationCommand? discordApplicationCommand = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordApplicationCommand.Discord = _discord; return discordApplicationCommand; } internal async Task GetGlobalApplicationCommandAsync(ulong application_id, ulong command_id) { string route = "/applications/:application_id/commands/:command_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { application_id, command_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordApplicationCommand? discordApplicationCommand = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordApplicationCommand.Discord = _discord; return discordApplicationCommand; } internal async Task EditGlobalApplicationCommandAsync(ulong application_id, ulong command_id, Optional name, Optional description, Optional> options, Optional defaultPermission, IReadOnlyDictionary name_localizations = null, IReadOnlyDictionary description_localizations = null, Optional allowDMUsage = default(Optional), Optional defaultMemberPermissions = default(Optional)) { RestApplicationCommandEditPayload value = new RestApplicationCommandEditPayload { Name = name, Description = description, Options = options, DefaultPermission = defaultPermission, NameLocalizations = name_localizations, DescriptionLocalizations = description_localizations, AllowDMUsage = allowDMUsage, DefaultMemberPermissions = defaultMemberPermissions }; string route = "/applications/:application_id/commands/:command_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { application_id, command_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordApplicationCommand? discordApplicationCommand = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordApplicationCommand.Discord = _discord; return discordApplicationCommand; } internal async Task DeleteGlobalApplicationCommandAsync(ulong application_id, ulong command_id) { string route = "/applications/:application_id/commands/:command_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { application_id, command_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route).ConfigureAwait(continueOnCapturedContext: false); } internal async Task> GetGuildApplicationCommandsAsync(ulong application_id, ulong guild_id) { string route = "/applications/:application_id/guilds/:guild_id/commands"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { application_id, guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); IEnumerable enumerable = JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordApplicationCommand item in enumerable) { item.Discord = _discord; } return enumerable.ToList(); } internal async Task> BulkOverwriteGuildApplicationCommandsAsync(ulong application_id, ulong guild_id, IEnumerable commands) { List list = new List(); foreach (DiscordApplicationCommand command in commands) { list.Add(new RestApplicationCommandCreatePayload { Type = command.Type, Name = command.Name, Description = command.Description, Options = command.Options, DefaultPermission = command.DefaultPermission, NameLocalizations = command.NameLocalizations, DescriptionLocalizations = command.DescriptionLocalizations, AllowDMUsage = command.AllowDMUsage, DefaultMemberPermissions = command.DefaultMemberPermissions }); } string route = "/applications/:application_id/guilds/:guild_id/commands"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { application_id, guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); IEnumerable enumerable = JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route, null, DiscordJson.SerializeObject(list)).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordApplicationCommand item in enumerable) { item.Discord = _discord; } return enumerable.ToList(); } internal async Task CreateGuildApplicationCommandAsync(ulong application_id, ulong guild_id, DiscordApplicationCommand command) { RestApplicationCommandCreatePayload value = new RestApplicationCommandCreatePayload { Type = command.Type, Name = command.Name, Description = command.Description, Options = command.Options, DefaultPermission = command.DefaultPermission, NameLocalizations = command.NameLocalizations, DescriptionLocalizations = command.DescriptionLocalizations, AllowDMUsage = command.AllowDMUsage, DefaultMemberPermissions = command.DefaultMemberPermissions }; string route = "/applications/:application_id/guilds/:guild_id/commands"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { application_id, guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordApplicationCommand? discordApplicationCommand = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordApplicationCommand.Discord = _discord; return discordApplicationCommand; } internal async Task GetGuildApplicationCommandAsync(ulong application_id, ulong guild_id, ulong command_id) { string route = "/applications/:application_id/guilds/:guild_id/commands/:command_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { application_id, guild_id, command_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordApplicationCommand? discordApplicationCommand = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordApplicationCommand.Discord = _discord; return discordApplicationCommand; } internal async Task EditGuildApplicationCommandAsync(ulong application_id, ulong guild_id, ulong command_id, Optional name, Optional description, Optional> options, Optional defaultPermission, IReadOnlyDictionary name_localizations = null, IReadOnlyDictionary description_localizations = null, Optional allowDMUsage = default(Optional), Optional defaultMemberPermissions = default(Optional)) { RestApplicationCommandEditPayload value = new RestApplicationCommandEditPayload { Name = name, Description = description, Options = options, DefaultPermission = defaultPermission, NameLocalizations = name_localizations, DescriptionLocalizations = description_localizations, AllowDMUsage = allowDMUsage, DefaultMemberPermissions = defaultMemberPermissions }; string route = "/applications/:application_id/guilds/:guild_id/commands/:command_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PATCH, route, new { application_id, guild_id, command_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordApplicationCommand? discordApplicationCommand = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PATCH, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordApplicationCommand.Discord = _discord; return discordApplicationCommand; } internal async Task DeleteGuildApplicationCommandAsync(ulong application_id, ulong guild_id, ulong command_id) { string route = "/applications/:application_id/guilds/:guild_id/commands/:command_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.DELETE, route, new { application_id, guild_id, command_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.DELETE, route).ConfigureAwait(continueOnCapturedContext: false); } internal async Task CreateInteractionResponseAsync(ulong interaction_id, string interaction_token, InteractionResponseType type, DiscordInteractionResponseBuilder builder) { if (builder?.Embeds != null) { foreach (DiscordEmbed embed in builder.Embeds) { if (embed.Timestamp.HasValue) { embed.Timestamp = embed.Timestamp.Value.ToUniversalTime(); } } } RestInteractionResponsePayload obj = new RestInteractionResponsePayload { Type = type }; object obj2; if (builder == null) { obj2 = null; } else { obj2 = new DiscordInteractionApplicationCommandCallbackData { Content = builder.Content, Title = builder.Title, CustomId = builder.CustomId, Embeds = builder.Embeds, IsTTS = builder.IsTTS }; object obj3 = obj2; IEnumerable mentions = builder.Mentions; ((DiscordInteractionApplicationCommandCallbackData)obj3).Mentions = new DiscordMentions(mentions ?? Mentions.All, builder.Mentions?.Any() ?? false); ((DiscordInteractionApplicationCommandCallbackData)obj2).Flags = builder.Flags; ((DiscordInteractionApplicationCommandCallbackData)obj2).Components = builder.Components; ((DiscordInteractionApplicationCommandCallbackData)obj2).Choices = builder.Choices; } obj.Data = (DiscordInteractionApplicationCommandCallbackData)obj2; RestInteractionResponsePayload value = obj; Dictionary dictionary = new Dictionary(); if (builder != null) { if (string.IsNullOrEmpty(builder.Content)) { IReadOnlyList embeds = builder.Embeds; if ((embeds == null || embeds.Count() <= 0) && !builder.IsTTS && builder.Mentions == null) { goto IL_01fd; } } dictionary["payload_json"] = DiscordJson.SerializeObject(value); } goto IL_01fd; IL_01fd: string route = "/interactions/:interaction_id/:interaction_token/callback"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { interaction_id, interaction_token }, out url); Uri url2 = Utilities.GetApiUriBuilderFor(url).AddParameter("wait", "true").Build(); if (builder != null) { await DoMultipartAsync(_discord, bucket, url2, RestRequestMethod.POST, route, null, dictionary, builder.Files).ConfigureAwait(continueOnCapturedContext: false); { foreach (DiscordMessageFile item in builder.Files.Where((DiscordMessageFile x) => x.ResetPositionTo.HasValue)) { item.Stream.Position = item.ResetPositionTo.Value; } return; } } await DoRequestAsync(_discord, bucket, url2, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false); } internal async Task GetOriginalInteractionResponseAsync(ulong application_id, string interaction_token) { string route = "/webhooks/:application_id/:interaction_token/messages/@original"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { application_id, interaction_token }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordMessage? discordMessage = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordMessage.Discord = _discord; return discordMessage; } internal Task EditOriginalInteractionResponseAsync(ulong application_id, string interaction_token, DiscordWebhookBuilder builder, IEnumerable attachments) { return EditWebhookMessageAsync(application_id, interaction_token, "@original", builder, attachments); } internal Task DeleteOriginalInteractionResponseAsync(ulong application_id, string interaction_token) { return DeleteWebhookMessageAsync(application_id, interaction_token, "@original"); } internal async Task CreateFollowupMessageAsync(ulong application_id, string interaction_token, DiscordFollowupMessageBuilder builder) { builder.Validate(); if (builder.Embeds != null) { foreach (DiscordEmbed embed in builder.Embeds) { if (embed.Timestamp.HasValue) { embed.Timestamp = embed.Timestamp.Value.ToUniversalTime(); } } } Dictionary dictionary = new Dictionary(); RestFollowupMessageCreatePayload restFollowupMessageCreatePayload = new RestFollowupMessageCreatePayload { Content = builder.Content, IsTTS = builder.IsTTS, Embeds = builder.Embeds, Flags = builder._flags, Components = builder.Components }; if (builder.Mentions != null) { restFollowupMessageCreatePayload.Mentions = new DiscordMentions(builder.Mentions, builder.Mentions.Any()); } if (string.IsNullOrEmpty(builder.Content)) { IReadOnlyList embeds = builder.Embeds; if ((embeds == null || embeds.Count() <= 0) && !builder.IsTTS && builder.Mentions == null) { goto IL_0191; } } dictionary["payload_json"] = DiscordJson.SerializeObject(restFollowupMessageCreatePayload); goto IL_0191; IL_0191: string route = "/webhooks/:application_id/:interaction_token"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { application_id, interaction_token }, out url); Uri url2 = Utilities.GetApiUriBuilderFor(url).AddParameter("wait", "true").Build(); DiscordMessage discordMessage = JsonConvert.DeserializeObject((await DoMultipartAsync(_discord, bucket, url2, RestRequestMethod.POST, route, null, dictionary, builder.Files).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordMessageFile item in builder.Files.Where((DiscordMessageFile x) => x.ResetPositionTo.HasValue)) { item.Stream.Position = item.ResetPositionTo.Value; } discordMessage.Discord = _discord; return discordMessage; } internal Task GetFollowupMessageAsync(ulong application_id, string interaction_token, ulong message_id) { return GetWebhookMessageAsync(application_id, interaction_token, message_id); } internal Task EditFollowupMessageAsync(ulong application_id, string interaction_token, ulong message_id, DiscordWebhookBuilder builder, IEnumerable attachments) { return EditWebhookMessageAsync(application_id, interaction_token, message_id, builder, attachments); } internal Task DeleteFollowupMessageAsync(ulong application_id, string interaction_token, ulong message_id) { return DeleteWebhookMessageAsync(application_id, interaction_token, message_id); } internal async Task> GetGuildApplicationCommandPermissionsAsync(ulong application_id, ulong guild_id) { string route = "/applications/:application_id/guilds/:guild_id/commands/permissions"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { application_id, guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); IEnumerable enumerable = JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordGuildApplicationCommandPermissions item in enumerable) { item.Discord = _discord; } return enumerable.ToList(); } internal async Task GetApplicationCommandPermissionsAsync(ulong application_id, ulong guild_id, ulong command_id) { string route = "/applications/:application_id/guilds/:guild_id/commands/:command_id/permissions"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { application_id, guild_id, command_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordGuildApplicationCommandPermissions? discordGuildApplicationCommandPermissions = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); discordGuildApplicationCommandPermissions.Discord = _discord; return discordGuildApplicationCommandPermissions; } internal async Task EditApplicationCommandPermissionsAsync(ulong application_id, ulong guild_id, ulong command_id, IEnumerable permissions) { RestEditApplicationCommandPermissionsPayload value = new RestEditApplicationCommandPermissionsPayload { Permissions = permissions }; string route = "/applications/:application_id/guilds/:guild_id/commands/:command_id/permissions"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { application_id, guild_id, command_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); DiscordGuildApplicationCommandPermissions? discordGuildApplicationCommandPermissions = JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); discordGuildApplicationCommandPermissions.Discord = _discord; return discordGuildApplicationCommandPermissions; } internal async Task> BatchEditApplicationCommandPermissionsAsync(ulong application_id, ulong guild_id, IEnumerable permissions) { string route = "/applications/:application_id/guilds/:guild_id/commands/permissions"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.PUT, route, new { application_id, guild_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); IEnumerable enumerable = JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.PUT, route, null, DiscordJson.SerializeObject(permissions)).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordGuildApplicationCommandPermissions item in enumerable) { item.Discord = _discord; } return enumerable.ToList(); } internal Task GetCurrentApplicationInfoAsync() { return GetApplicationInfoAsync("@me"); } internal Task GetApplicationInfoAsync(ulong application_id) { return GetApplicationInfoAsync(application_id.ToString(CultureInfo.InvariantCulture)); } private async Task GetApplicationInfoAsync(string application_id) { string route = "/oauth2/applications/:application_id"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { application_id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); return JsonConvert.DeserializeObject((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); } internal async Task> GetApplicationAssetsAsync(DiscordApplication application) { string route = "/oauth2/applications/:application_id/assets"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, route, new { application_id = application.Id }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); IEnumerable enumerable = JsonConvert.DeserializeObject>((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, route).ConfigureAwait(continueOnCapturedContext: false)).Response); foreach (DiscordApplicationAsset item in enumerable) { item.Discord = application.Discord; item.Application = application; } return new ReadOnlyCollection(new List(enumerable)); } internal async Task GetGatewayInfoAsync() { Dictionary baseHeaders = Utilities.GetBaseHeaders(); string text = "/gateway"; if (_discord.Configuration.TokenType == TokenType.Bot) { text += "/bot"; } string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.GET, text, new { }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); GatewayInfo gatewayInfo = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.GET, text, baseHeaders).ConfigureAwait(continueOnCapturedContext: false)).Response).ToDiscordObject(); gatewayInfo.SessionBucket.ResetAfter = DateTimeOffset.UtcNow + TimeSpan.FromMilliseconds(gatewayInfo.SessionBucket.ResetAfterInternal); return gatewayInfo; } public async Task CreateForumPostAsync(ulong channelId, string name, AutoArchiveDuration? autoArchiveDuration, int? rate_limit_per_user, DiscordMessageBuilder message, IEnumerable appliedTags) { string route = "/channels/:channel_id/threads"; string url; RateLimitBucket bucket = _rest.GetBucket(RestRequestMethod.POST, route, new { channel_id = channelId }, out url); Uri apiUriFor = Utilities.GetApiUriFor(url); RestForumPostCreatePayload value = new RestForumPostCreatePayload { Name = name, ArchiveAfter = autoArchiveDuration, RateLimitPerUser = rate_limit_per_user, Message = new RestChannelMessageCreatePayload { Content = message.Content, HasContent = !string.IsNullOrWhiteSpace(message.Content), Embeds = message.Embeds, HasEmbed = (message.Embeds.Count > 0), Mentions = new DiscordMentions(message.Mentions, message.Mentions.Any()), Components = message.Components, StickersIds = (message.Stickers?.Select((DiscordMessageSticker s) => s.Id) ?? Array.Empty()) }, AppliedTags = appliedTags }; JObject jObject; if (message.Files.Count == 0) { jObject = JObject.Parse((await DoRequestAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, DiscordJson.SerializeObject(value)).ConfigureAwait(continueOnCapturedContext: false)).Response); } else { Dictionary values = new Dictionary { ["payload_json"] = DiscordJson.SerializeObject(value) }; jObject = JObject.Parse((await DoMultipartAsync(_discord, bucket, apiUriFor, RestRequestMethod.POST, route, null, values, message.Files).ConfigureAwait(continueOnCapturedContext: false)).Response); } JToken msg_raw = jObject["message"]; jObject.Remove("message"); DiscordMessage msg = PrepareMessage(msg_raw); return new DiscordForumPostStarter(jObject.ToDiscordObject(), msg); } } internal static class Endpoints { public const string API_VERSION = "10"; public const string BASE_URI = "https://discord.com/api/v10"; public const string ORIGINAL = "/@original"; public const string OAUTH2 = "/oauth2"; public const string APPLICATIONS = "/applications"; public const string REACTIONS = "/reactions"; public const string ME = "/@me"; public const string PERMISSIONS = "/permissions"; public const string RECIPIENTS = "/recipients"; public const string BULK_DELETE = "/bulk-delete"; public const string INTEGRATIONS = "/integrations"; public const string SYNC = "/sync"; public const string PRUNE = "/prune"; public const string REGIONS = "/regions"; public const string CONNECTIONS = "/connections"; public const string ICONS = "/icons"; public const string GATEWAY = "/gateway"; public const string AUTH = "/auth"; public const string LOGIN = "/login"; public const string CHANNELS = "/channels"; public const string THREADS = "/threads"; public const string EVENTS = "/scheduled-events"; public const string THREAD_MEMBERS = "/thread-members"; public const string ACTIVE = "/active "; public const string ARCHIVED = "/archived"; public const string PUBLIC = "/public"; public const string PRIVATE = "/private"; public const string MESSAGES = "/messages"; public const string PINS = "/pins"; public const string USERS = "/users"; public const string GUILDS = "/guilds"; public const string SEARCH = "/search"; public const string INVITES = "/invites"; public const string ROLES = "/roles"; public const string MEMBERS = "/members"; public const string TYPING = "/typing"; public const string AVATARS = "/avatars"; public const string BANS = "/bans"; public const string WEBHOOKS = "/webhooks"; public const string SLACK = "/slack"; public const string GITHUB = "/github"; public const string BOT = "/bot"; public const string VOICE = "/voice"; public const string AUDIT_LOGS = "/audit-logs"; public const string ACK = "/ack"; public const string ASSETS = "/assets"; public const string EMOJIS = "/emojis"; public const string VANITY_URL = "/vanity-url"; public const string WIDGET_PNG = "/widget.png"; public const string PREVIEW = "/preview"; public const string FOLLOWERS = "/followers"; public const string CROSSPOST = "/crosspost"; public const string WIDGET = "/widget"; public const string WIDGET_JSON = "/widget.json"; public const string TEMPLATES = "/templates"; public const string MEMBER_VERIFICATION = "/member-verification"; public const string COMMANDS = "/commands"; public const string INTERACTIONS = "/interactions"; public const string CALLBACK = "/callback"; public const string WELCOME_SCREEN = "/welcome-screen"; public const string VOICE_STATES = "/voice-states"; public const string STICKERS = "/stickers"; public const string STICKERPACKS = "/sticker-packs"; public const string STAGE_INSTANCES = "/stage-instances"; } internal struct IpEndpoint { public IPAddress Address { get; set; } public int Port { get; set; } public IpEndpoint(IPAddress address, int port) { Address = address; Port = port; } } internal sealed class MultipartWebRequest : BaseRestRequest { internal bool _removeFileCount; public IReadOnlyDictionary Values { get; } public IReadOnlyCollection Files { get; } internal MultipartWebRequest(BaseDiscordClient client, RateLimitBucket bucket, Uri url, RestRequestMethod method, string route, IReadOnlyDictionary headers = null, IReadOnlyDictionary values = null, IReadOnlyCollection files = null, double? ratelimit_wait_override = null, bool removeFileCount = false) : base(client, bucket, url, method, route, headers, ratelimit_wait_override) { Values = values; Files = files; _removeFileCount = removeFileCount; } } internal class RateLimitBucket : IEquatable { public volatile string BucketId; internal string _hash; internal volatile int _remaining; internal volatile bool _isUnlimited; internal volatile int _limitTesting; internal volatile Task _limitTestFinished; internal volatile bool _limitValid; internal long _nextReset; internal volatile int _limitResetting; private const string UNLIMITED_HASH = "unlimited"; public string GuildId { get; internal set; } public string ChannelId { get; internal set; } public string WebhookId { get; internal set; } public string Hash { get { return Volatile.Read(ref _hash); } internal set { _isUnlimited = value.Contains("unlimited"); if (BucketId != null && !BucketId.StartsWith(value)) { string item = (BucketId = GenerateBucketId(value, GuildId, ChannelId, WebhookId)); RouteHashes.Add(item); } Volatile.Write(ref _hash, value); } } public ConcurrentBag RouteHashes { get; } public DateTimeOffset LastAttemptAt { get; internal set; } public int Remaining => _remaining; public int Maximum { get; set; } public DateTimeOffset Reset { get; internal set; } public TimeSpan? ResetAfter { get; internal set; } internal DateTimeOffset ResetAfterOffset { get; set; } internal RateLimitBucket(string hash, string guild_id, string channel_id, string webhook_id) { Hash = hash; ChannelId = channel_id; GuildId = guild_id; WebhookId = webhook_id; BucketId = GenerateBucketId(hash, guild_id, channel_id, webhook_id); RouteHashes = new ConcurrentBag(); } public static string GenerateBucketId(string hash, string guild_id, string channel_id, string webhook_id) { return hash + ":" + guild_id + ":" + channel_id + ":" + webhook_id; } public static string GenerateHashKey(RestRequestMethod method, string route) { return $"{method}:{route}"; } public static string GenerateUnlimitedHash(RestRequestMethod method, string route) { return GenerateHashKey(method, route) + ":unlimited"; } public override string ToString() { string text = ((GuildId != string.Empty) ? GuildId : "guild_id"); string text2 = ((ChannelId != string.Empty) ? ChannelId : "channel_id"); string text3 = ((WebhookId != string.Empty) ? WebhookId : "webhook_id"); return $"rate limit bucket [{Hash}:{text}:{text2}:{text3}] [{Remaining}/{Maximum}] {(ResetAfter.HasValue ? ResetAfterOffset : Reset)}"; } public override bool Equals(object obj) { return Equals(obj as RateLimitBucket); } public bool Equals(RateLimitBucket e) { if (e == null) { return false; } if (this != e) { return BucketId == e.BucketId; } return true; } public override int GetHashCode() { return BucketId.GetHashCode(); } internal async Task TryResetLimitAsync(DateTimeOffset now) { if (ResetAfter.HasValue) { ResetAfter = ResetAfterOffset - now; } if (_nextReset != 0L && _nextReset <= now.UtcTicks) { while (Interlocked.CompareExchange(ref _limitResetting, 1, 0) != 0) { await Task.Yield(); } if (_nextReset != 0L) { _remaining = Maximum; _nextReset = 0L; } _limitResetting = 0; } } internal void SetInitialValues(int max, int usesLeft, DateTimeOffset newReset) { Maximum = max; _remaining = usesLeft; _nextReset = newReset.UtcTicks; _limitValid = true; _limitTestFinished = null; _limitTesting = 0; } } internal sealed class RestClient : IDisposable { private CancellationTokenSource _bucketCleanerTokenSource; private TimeSpan _bucketCleanupDelay = TimeSpan.FromSeconds(60.0); private volatile bool _cleanerRunning; private Task _cleanerTask; private volatile bool _disposed; private static Regex RouteArgumentRegex { get; } = new Regex(":([a-z_]+)"); private HttpClient HttpClient { get; } private BaseDiscordClient Discord { get; } private ILogger Logger { get; } private ConcurrentDictionary RoutesToHashes { get; } private ConcurrentDictionary HashesToBuckets { get; } private ConcurrentDictionary RequestQueue { get; } private AsyncManualResetEvent GlobalRateLimitEvent { get; } private bool UseResetAfter { get; } internal RestClient(DiscordConfiguration config, ILogger logger) : this(config.Proxy, config.HttpTimeout, config.UseRelativeRatelimit, logger) { HttpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", Utilities.GetFormattedToken(config)); } internal RestClient(IWebProxy proxy, TimeSpan timeout, bool useRelativeRatelimit, ILogger logger) { Logger = logger; HttpClientHandler handler = new HttpClientHandler { UseCookies = false, AutomaticDecompression = (DecompressionMethods.GZip | DecompressionMethods.Deflate), UseProxy = (proxy != null), Proxy = proxy }; HttpClient = new HttpClient(handler) { BaseAddress = new Uri(Utilities.GetApiBaseUri()), Timeout = timeout }; HttpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", Utilities.GetUserAgent()); RoutesToHashes = new ConcurrentDictionary(); HashesToBuckets = new ConcurrentDictionary(); RequestQueue = new ConcurrentDictionary(); GlobalRateLimitEvent = new AsyncManualResetEvent(initialState: true); UseResetAfter = useRelativeRatelimit; } public RateLimitBucket GetBucket(RestRequestMethod method, string route, object route_params, out string url) { IEnumerable declaredProperties = route_params.GetType().GetTypeInfo().DeclaredProperties; Dictionary rparams = new Dictionary(); foreach (PropertyInfo item in declaredProperties) { object value = item.GetValue(route_params); if (value is string value2) { rparams[item.Name] = value2; } else if (value is DateTime dateTime) { rparams[item.Name] = dateTime.ToString("yyyy-MM-ddTHH:mm:sszzz", CultureInfo.InvariantCulture); } else if (value is DateTimeOffset dateTimeOffset) { rparams[item.Name] = dateTimeOffset.ToString("yyyy-MM-ddTHH:mm:sszzz", CultureInfo.InvariantCulture); } else { rparams[item.Name] = ((value is IFormattable formattable) ? formattable.ToString(null, CultureInfo.InvariantCulture) : value.ToString()); } } string guild_id = (rparams.ContainsKey("guild_id") ? rparams["guild_id"] : ""); string channel_id = (rparams.ContainsKey("channel_id") ? rparams["channel_id"] : ""); string webhook_id = (rparams.ContainsKey("webhook_id") ? rparams["webhook_id"] : ""); string key = RateLimitBucket.GenerateHashKey(method, route); string orAdd = RoutesToHashes.GetOrAdd(key, RateLimitBucket.GenerateUnlimitedHash(method, route)); string text = RateLimitBucket.GenerateBucketId(orAdd, guild_id, channel_id, webhook_id); RateLimitBucket orAdd2 = HashesToBuckets.GetOrAdd(text, new RateLimitBucket(orAdd, guild_id, channel_id, webhook_id)); orAdd2.LastAttemptAt = DateTimeOffset.UtcNow; if (!orAdd2.RouteHashes.Contains(text)) { orAdd2.RouteHashes.Add(text); } RequestQueue.TryGetValue(text, out var value3); RequestQueue[text] = Interlocked.Increment(ref value3); if (!_cleanerRunning) { _cleanerRunning = true; _bucketCleanerTokenSource = new CancellationTokenSource(); _cleanerTask = Task.Run((Func)CleanupBucketsAsync, _bucketCleanerTokenSource.Token); Logger.LogDebug(LoggerEvents.RestCleaner, "Bucket cleaner task started."); } url = RouteArgumentRegex.Replace(route, (Match xm) => rparams[xm.Groups[1].Value]); return orAdd2; } public Task ExecuteRequestAsync(BaseRestRequest request) { if (request != null) { return ExecuteRequestAsync(request, null, null); } throw new ArgumentNullException("request"); } private async Task ExecuteRequestAsync(BaseRestRequest request, RateLimitBucket bucket, TaskCompletionSource ratelimitTcs) { if (_disposed) { return; } HttpResponseMessage res = null; int value; try { await GlobalRateLimitEvent.WaitAsync().ConfigureAwait(continueOnCapturedContext: false); if (bucket == null) { bucket = request.RateLimitBucket; } if (ratelimitTcs == null) { ratelimitTcs = await WaitForInitialRateLimit(bucket).ConfigureAwait(continueOnCapturedContext: false); } if (ratelimitTcs == null) { DateTimeOffset now = DateTimeOffset.UtcNow; await bucket.TryResetLimitAsync(now).ConfigureAwait(continueOnCapturedContext: false); if (Interlocked.Decrement(ref bucket._remaining) < 0) { Logger.LogDebug(LoggerEvents.RatelimitDiag, "Request for {Bucket} is blocked", bucket.ToString()); TimeSpan timeSpan = bucket.Reset - now; DateTimeOffset dateTimeOffset = bucket.Reset; if (UseResetAfter) { timeSpan = bucket.ResetAfter.Value; dateTimeOffset = bucket.ResetAfterOffset; } if (timeSpan < new TimeSpan(-600000000L)) { Logger.LogError(LoggerEvents.RatelimitDiag, "Failed to retrieve ratelimits - giving up and allowing next request for bucket"); bucket._remaining = 1; } if (timeSpan < TimeSpan.Zero) { timeSpan = TimeSpan.FromMilliseconds(100.0); } Logger.LogWarning(LoggerEvents.RatelimitPreemptive, "Pre-emptive ratelimit triggered - waiting until {0:yyyy-MM-dd HH:mm:ss zzz} ({1:c}).", dateTimeOffset, timeSpan); Task.Delay(timeSpan).ContinueWith((Task _) => ExecuteRequestAsync(request, null, null)).LogTaskFault(Logger, LogLevel.Error, LoggerEvents.RestError, "Error while executing request"); return; } Logger.LogDebug(LoggerEvents.RatelimitDiag, "Request for {Bucket} is allowed", bucket.ToString()); } else { Logger.LogDebug(LoggerEvents.RatelimitDiag, "Initial request for {Bucket} is allowed", bucket.ToString()); } HttpRequestMessage request2 = BuildRequest(request); RestResponse response = new RestResponse(); try { if (_disposed) { return; } res = await HttpClient.SendAsync(request2, HttpCompletionOption.ResponseContentRead, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false); byte[] array = await res.Content.ReadAsByteArrayAsync().ConfigureAwait(continueOnCapturedContext: false); string @string = Utilities.UTF8.GetString(array, 0, array.Length); Logger.LogTrace(LoggerEvents.RestRx, @string); response.Headers = res.Headers.ToDictionary>, string, string>((KeyValuePair> xh) => xh.Key, (KeyValuePair> xh) => string.Join("\n", xh.Value), StringComparer.OrdinalIgnoreCase); response.Response = @string; response.ResponseCode = (int)res.StatusCode; } catch (HttpRequestException ex) { Logger.LogError(LoggerEvents.RestError, ex, "Request to {Url} triggered an HttpException", request.Url); request.SetFaulted(ex); FailInitialRateLimitTest(request, ratelimitTcs); return; } UpdateBucket(request, response, ratelimitTcs); Exception ex2 = null; value = response.ResponseCode; switch (value) { case 400: case 405: ex2 = new BadRequestException(request, response); break; case 401: case 403: ex2 = new UnauthorizedException(request, response); break; case 404: ex2 = new NotFoundException(request, response); break; case 413: ex2 = new RequestSizeException(request, response); break; case 429: { ex2 = new RateLimitException(request, response); Handle429(response, out var wait_task, out var global); if (wait_task == null) { break; } if (global) { Logger.LogError(LoggerEvents.RatelimitHit, "Global ratelimit hit, cooling down"); try { GlobalRateLimitEvent.Reset(); await wait_task.ConfigureAwait(continueOnCapturedContext: false); } finally { GlobalRateLimitEvent.SetAsync(); } ExecuteRequestAsync(request, bucket, ratelimitTcs).LogTaskFault(Logger, LogLevel.Error, LoggerEvents.RestError, "Error while retrying request"); } else { Logger.LogError(LoggerEvents.RatelimitHit, "Ratelimit hit, requeueing request to {Url}", request.Url); await wait_task.ConfigureAwait(continueOnCapturedContext: false); ExecuteRequestAsync(request, bucket, ratelimitTcs).LogTaskFault(Logger, LogLevel.Error, LoggerEvents.RestError, "Error while retrying request"); } return; } case 500: case 502: case 503: case 504: ex2 = new ServerErrorException(request, response); break; } if (ex2 != null) { request.SetFaulted(ex2); } else { request.SetCompleted(response); } } catch (Exception ex3) { Logger.LogError(LoggerEvents.RestError, ex3, "Request to {Url} triggered an exception", request.Url); if (bucket != null && ratelimitTcs != null && bucket._limitTesting != 0) { FailInitialRateLimitTest(request, ratelimitTcs); } if (!request.TrySetFaulted(ex3)) { throw; } } finally { res?.Dispose(); RequestQueue.TryGetValue(bucket.BucketId, out var value2); RequestQueue[bucket.BucketId] = Interlocked.Decrement(ref value2); if (value2 <= 0) { foreach (string routeHash in bucket.RouteHashes) { if (RequestQueue.ContainsKey(routeHash)) { RequestQueue.TryRemove(routeHash, out value); } } } } } private void FailInitialRateLimitTest(BaseRestRequest request, TaskCompletionSource ratelimitTcs, bool resetToInitial = false) { if (ratelimitTcs == null && !resetToInitial) { return; } RateLimitBucket rateLimitBucket = request.RateLimitBucket; rateLimitBucket._limitValid = false; rateLimitBucket._limitTestFinished = null; rateLimitBucket._limitTesting = 0; if (resetToInitial) { UpdateHashCaches(request, rateLimitBucket); rateLimitBucket.Maximum = 0; rateLimitBucket._remaining = 0; } else { Task.Run(() => ratelimitTcs.TrySetResult(result: false)); } } private async Task> WaitForInitialRateLimit(RateLimitBucket bucket) { while (!bucket._limitValid) { if (bucket._limitTesting == 0 && Interlocked.CompareExchange(ref bucket._limitTesting, 1, 0) == 0) { if (bucket._limitValid) { return null; } TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); bucket._limitTestFinished = taskCompletionSource.Task; return taskCompletionSource; } Task waitTask = null; while (bucket._limitTesting != 0) { Task limitTestFinished; waitTask = (limitTestFinished = bucket._limitTestFinished); if (limitTestFinished != null) { break; } await Task.Yield(); } if (waitTask != null) { await waitTask.ConfigureAwait(continueOnCapturedContext: false); } } return null; } private HttpRequestMessage BuildRequest(BaseRestRequest request) { HttpRequestMessage httpRequestMessage = new HttpRequestMessage(new HttpMethod(request.Method.ToString()), request.Url); if (request.Headers != null && request.Headers.Any()) { foreach (KeyValuePair header in request.Headers) { httpRequestMessage.Headers.Add(header.Key, header.Value); } } if (request is RestRequest restRequest && !string.IsNullOrWhiteSpace(restRequest.Payload)) { Logger.LogTrace(LoggerEvents.RestTx, restRequest.Payload); httpRequestMessage.Content = new StringContent(restRequest.Payload); httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); } if (request is MultipartWebRequest multipartWebRequest) { Logger.LogTrace(LoggerEvents.RestTx, ""); if (multipartWebRequest.Values.TryGetValue("payload_json", out var value)) { Logger.LogTrace(LoggerEvents.RestTx, value); } string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); httpRequestMessage.Headers.Add("Connection", "keep-alive"); httpRequestMessage.Headers.Add("Keep-Alive", "600"); MultipartFormDataContent multipartFormDataContent = new MultipartFormDataContent(boundary); if (multipartWebRequest.Values != null && multipartWebRequest.Values.Any()) { foreach (KeyValuePair value2 in multipartWebRequest.Values) { multipartFormDataContent.Add(new StringContent(value2.Value), value2.Key); } } if (multipartWebRequest.Files != null && multipartWebRequest.Files.Any()) { int num = 1; foreach (DiscordMessageFile file in multipartWebRequest.Files) { StreamContent streamContent = new StreamContent(file.Stream); if (file.ContentType != null) { streamContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType); } if (file.FileType != null) { file.FileName = file.FileName + "." + file.FileType; } string text = ((!multipartWebRequest._removeFileCount) ? num++.ToString(CultureInfo.InvariantCulture) : string.Empty); multipartFormDataContent.Add(streamContent, "file" + text, file.FileName); } } httpRequestMessage.Content = multipartFormDataContent; } return httpRequestMessage; } private void Handle429(RestResponse response, out Task wait_task, out bool global) { wait_task = null; global = false; if (response.Headers != null) { IReadOnlyDictionary headers = response.Headers; if (headers.TryGetValue("Retry-After", out var value)) { TimeSpan delay = TimeSpan.FromSeconds(int.Parse(value, CultureInfo.InvariantCulture)); wait_task = Task.Delay(delay); } if (headers.TryGetValue("X-RateLimit-Global", out var value2) && value2.Equals("true", StringComparison.InvariantCultureIgnoreCase)) { global = true; } } } private void UpdateBucket(BaseRestRequest request, RestResponse response, TaskCompletionSource ratelimitTcs) { RateLimitBucket rateLimitBucket = request.RateLimitBucket; if (response.Headers == null) { if (response.ResponseCode != 429) { FailInitialRateLimitTest(request, ratelimitTcs); } return; } IReadOnlyDictionary headers = response.Headers; if (headers.TryGetValue("X-RateLimit-Global", out var value) && value.Equals("true", StringComparison.InvariantCultureIgnoreCase)) { if (response.ResponseCode != 429) { FailInitialRateLimitTest(request, ratelimitTcs); } return; } string value2; bool flag = headers.TryGetValue("X-RateLimit-Limit", out value2); string value3; bool flag2 = headers.TryGetValue("X-RateLimit-Remaining", out value3); string value4; bool flag3 = headers.TryGetValue("X-RateLimit-Reset", out value4); string value5; bool flag4 = headers.TryGetValue("X-Ratelimit-Reset-After", out value5); headers.TryGetValue("X-Ratelimit-Bucket", out var value6); if (!flag || !flag2 || !flag3 || !flag4) { if (response.ResponseCode != 429) { FailInitialRateLimitTest(request, ratelimitTcs, ratelimitTcs == null); } return; } DateTimeOffset utcNow = DateTimeOffset.UtcNow; DateTimeOffset dateTimeOffset = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddSeconds(double.Parse(value4, CultureInfo.InvariantCulture)); DateTimeOffset dateTimeOffset2 = utcNow; if (headers.TryGetValue("Date", out var value7)) { dateTimeOffset2 = DateTimeOffset.Parse(value7, CultureInfo.InvariantCulture).ToUniversalTime(); } TimeSpan timeSpan = dateTimeOffset - dateTimeOffset2; if (request.RateLimitWaitOverride.HasValue) { timeSpan = TimeSpan.FromSeconds(request.RateLimitWaitOverride.Value); } DateTimeOffset dateTimeOffset3 = utcNow + timeSpan; if (UseResetAfter) { rateLimitBucket.ResetAfter = TimeSpan.FromSeconds(double.Parse(value5, CultureInfo.InvariantCulture)); dateTimeOffset3 = (rateLimitBucket.ResetAfterOffset = utcNow + rateLimitBucket.ResetAfter.Value + (request.RateLimitWaitOverride.HasValue ? timeSpan : TimeSpan.Zero)); } else { rateLimitBucket.Reset = dateTimeOffset3; } int max = int.Parse(value2, CultureInfo.InvariantCulture); int usesLeft = int.Parse(value3, CultureInfo.InvariantCulture); if (ratelimitTcs != null) { rateLimitBucket.SetInitialValues(max, usesLeft, dateTimeOffset3); Task.Run(() => ratelimitTcs.TrySetResult(result: true)); } else if (rateLimitBucket._nextReset == 0L) { rateLimitBucket._nextReset = dateTimeOffset3.UtcTicks; } UpdateHashCaches(request, rateLimitBucket, value6); } private void UpdateHashCaches(BaseRestRequest request, RateLimitBucket bucket, string newHash = null) { string text = RateLimitBucket.GenerateHashKey(request.Method, request.Route); if (!RoutesToHashes.TryGetValue(text, out var value)) { return; } if (newHash == null) { RoutesToHashes.TryRemove(text, out var _); HashesToBuckets.TryRemove(bucket.BucketId, out var _); } else { if (!bucket._isUnlimited || !(newHash != value)) { return; } Logger.LogDebug(LoggerEvents.RestHashMover, "Updating hash in {Hash}: \"{OldHash}\" -> \"{NewHash}\"", text, value, newHash); string bucketId = RateLimitBucket.GenerateBucketId(newHash, bucket.GuildId, bucket.ChannelId, bucket.WebhookId); RoutesToHashes.AddOrUpdate(text, newHash, delegate(string key, string oldHash) { bucket.Hash = newHash; string key2 = RateLimitBucket.GenerateBucketId(oldHash, bucket.GuildId, bucket.ChannelId, bucket.WebhookId); HashesToBuckets.TryRemove(key2, out var _); HashesToBuckets.AddOrUpdate(bucketId, bucket, (string key, RateLimitBucket oldBucket) => bucket); return newHash; }); } } private async Task CleanupBucketsAsync() { while (!_bucketCleanerTokenSource.IsCancellationRequested) { try { await Task.Delay(_bucketCleanupDelay, _bucketCleanerTokenSource.Token).ConfigureAwait(continueOnCapturedContext: false); } catch { } if (_disposed) { return; } foreach (string key in RequestQueue.Keys) { RateLimitBucket rateLimitBucket = HashesToBuckets.Values.FirstOrDefault((RateLimitBucket x) => x.RouteHashes.Contains(key)); if (rateLimitBucket == null || (rateLimitBucket != null && rateLimitBucket.LastAttemptAt.AddSeconds(5.0) < DateTimeOffset.UtcNow)) { RequestQueue.TryRemove(key, out var _); } } int num = 0; StringBuilder stringBuilder = null; foreach (KeyValuePair hashesToBucket in HashesToBuckets) { if (stringBuilder == null) { stringBuilder = new StringBuilder(); } string key2 = hashesToBucket.Key; RateLimitBucket value2 = hashesToBucket.Value; if (!RequestQueue.ContainsKey(value2.BucketId) || value2._isUnlimited) { DateTimeOffset dateTimeOffset = (UseResetAfter ? value2.ResetAfterOffset : value2.Reset); if (value2._isUnlimited || (!(dateTimeOffset > DateTimeOffset.UtcNow) && !(DateTimeOffset.UtcNow - dateTimeOffset < _bucketCleanupDelay))) { HashesToBuckets.TryRemove(key2, out var _); num++; stringBuilder.Append(value2.BucketId + ", "); } } } if (num > 0) { Logger.LogDebug(LoggerEvents.RestCleaner, "Removed {BucketCount} unused bucket{BucketPlural}: [{BucketId}]", num, (num > 1) ? "s" : string.Empty, stringBuilder.ToString().TrimEnd(',', ' ')); } if (HashesToBuckets.Count == 0) { break; } } if (!_bucketCleanerTokenSource.IsCancellationRequested) { _bucketCleanerTokenSource.Cancel(); } _cleanerRunning = false; Logger.LogDebug(LoggerEvents.RestCleaner, "Bucket cleaner task stopped."); } public void Dispose() { if (!_disposed) { _disposed = true; GlobalRateLimitEvent?.Reset(); CancellationTokenSource bucketCleanerTokenSource = _bucketCleanerTokenSource; if (bucketCleanerTokenSource != null && !bucketCleanerTokenSource.IsCancellationRequested) { _bucketCleanerTokenSource?.Cancel(); Logger.LogDebug(LoggerEvents.RestCleaner, "Bucket cleaner task stopped."); } try { _cleanerTask?.Dispose(); _bucketCleanerTokenSource?.Dispose(); HttpClient?.Dispose(); } catch { } RoutesToHashes?.Clear(); HashesToBuckets?.Clear(); RequestQueue?.Clear(); } } } internal sealed class RestRequest : BaseRestRequest { public string Payload { get; } internal RestRequest(BaseDiscordClient client, RateLimitBucket bucket, Uri url, RestRequestMethod method, string route, IReadOnlyDictionary headers = null, string payload = null, double? ratelimitWaitOverride = null) : base(client, bucket, url, method, route, headers, ratelimitWaitOverride) { Payload = payload; } } internal enum RestRequestMethod { GET, POST, DELETE, PATCH, PUT, HEAD } internal sealed class RestResponse { public int ResponseCode { get; internal set; } public IReadOnlyDictionary Headers { get; internal set; } public string Response { get; internal set; } internal RestResponse() { } } internal class SessionBucket { [JsonProperty("total")] public int Total { get; internal set; } [JsonProperty("remaining")] public int Remaining { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DateTimeOffset ResetAfter { get; internal set; } [JsonProperty("max_concurrency")] public int MaxConcurrency { get; internal set; } [JsonProperty("reset_after")] internal int ResetAfterInternal { get; set; } public override string ToString() { return $"[{Remaining}/{Total}] {ResetAfter}. {MaxConcurrency}x concurrency"; } } } namespace DSharpPlus.Net.WebSocket { internal delegate IWebSocketClient WebSocketClientFactoryDelegate(IWebProxy proxy); internal interface IWebSocketClient : IDisposable { IWebProxy Proxy { get; } IReadOnlyDictionary DefaultHeaders { get; } event AsyncEventHandler Connected; event AsyncEventHandler Disconnected; event AsyncEventHandler MessageReceived; event AsyncEventHandler ExceptionThrown; Task ConnectAsync(Uri uri); Task DisconnectAsync(int code = 1000, string message = ""); Task SendMessageAsync(string message); bool AddDefaultHeader(string name, string value); bool RemoveDefaultHeader(string name); } internal sealed class PayloadDecompressor : IDisposable { private const uint ZlibFlush = 65535u; private const byte ZlibPrefix = 120; public GatewayCompressionLevel CompressionLevel { get; } private MemoryStream CompressedStream { get; } private DeflateStream DecompressorStream { get; } public PayloadDecompressor(GatewayCompressionLevel compressionLevel) { if (compressionLevel == GatewayCompressionLevel.None) { throw new InvalidOperationException("Decompressor requires a valid compression mode."); } CompressionLevel = compressionLevel; CompressedStream = new MemoryStream(); if (CompressionLevel == GatewayCompressionLevel.Stream) { DecompressorStream = new DeflateStream(CompressedStream, CompressionMode.Decompress); } } public bool TryDecompress(ArraySegment compressed, MemoryStream decompressed) { DeflateStream deflateStream = ((CompressionLevel == GatewayCompressionLevel.Stream) ? DecompressorStream : new DeflateStream(CompressedStream, CompressionMode.Decompress, leaveOpen: true)); if (compressed.Array[0] == 120) { CompressedStream.Write(compressed.Array, compressed.Offset + 2, compressed.Count - 2); } else { CompressedStream.Write(compressed.Array, compressed.Offset, compressed.Count); } CompressedStream.Flush(); CompressedStream.Position = 0L; Span span = compressed.AsSpan(); uint num = BinaryPrimitives.ReadUInt32BigEndian(span.Slice(span.Length - 4)); if (CompressionLevel == GatewayCompressionLevel.Stream && num != 65535) { if (CompressionLevel == GatewayCompressionLevel.Payload) { deflateStream.Dispose(); } return false; } try { deflateStream.CopyTo(decompressed); return true; } catch { return false; } finally { CompressedStream.Position = 0L; CompressedStream.SetLength(0L); if (CompressionLevel == GatewayCompressionLevel.Payload) { deflateStream.Dispose(); } } } public void Dispose() { DecompressorStream?.Dispose(); CompressedStream.Dispose(); } } internal sealed class SocketLock : IDisposable { public ulong ApplicationId { get; } private SemaphoreSlim LockSemaphore { get; } private CancellationTokenSource TimeoutCancelSource { get; set; } private CancellationToken TimeoutCancel => TimeoutCancelSource.Token; private Task UnlockTask { get; set; } private int MaxConcurrency { get; set; } public SocketLock(ulong appId, int maxConcurrency) { ApplicationId = appId; TimeoutCancelSource = null; MaxConcurrency = maxConcurrency; LockSemaphore = new SemaphoreSlim(maxConcurrency); } public async Task LockAsync() { await LockSemaphore.WaitAsync().ConfigureAwait(continueOnCapturedContext: false); TimeoutCancelSource = new CancellationTokenSource(); UnlockTask = Task.Delay(TimeSpan.FromSeconds(30.0), TimeoutCancel); UnlockTask.ContinueWith(InternalUnlock, TaskContinuationOptions.NotOnCanceled); } public void UnlockAfter(TimeSpan unlockDelay) { if (TimeoutCancelSource != null && LockSemaphore.CurrentCount <= 0) { try { TimeoutCancelSource.Cancel(); TimeoutCancelSource.Dispose(); } catch { } TimeoutCancelSource = null; UnlockTask = Task.Delay(unlockDelay, CancellationToken.None); UnlockTask.ContinueWith(InternalUnlock); } } public Task WaitAsync() { return LockSemaphore.WaitAsync(); } public void Dispose() { try { TimeoutCancelSource?.Cancel(); TimeoutCancelSource?.Dispose(); } catch { } } private void InternalUnlock(Task t) { LockSemaphore.Release(MaxConcurrency); } } internal class WebSocketClient : IWebSocketClient, IDisposable { private const int OutgoingChunkSize = 8192; private const int IncomingChunkSize = 32768; private readonly Dictionary _defaultHeaders; private Task _receiverTask; private CancellationTokenSource _receiverTokenSource; private CancellationToken _receiverToken; private readonly SemaphoreSlim _senderLock; private CancellationTokenSource _socketTokenSource; private CancellationToken _socketToken; private ClientWebSocket _ws; private volatile bool _isClientClose; private volatile bool _isConnected; private bool _isDisposed; private readonly AsyncEvent _connected; private readonly AsyncEvent _disconnected; private readonly AsyncEvent _messageReceived; private readonly AsyncEvent _exceptionThrown; public IWebProxy Proxy { get; } public IReadOnlyDictionary DefaultHeaders { get; } public event AsyncEventHandler Connected { add { _connected.Register(value); } remove { _connected.Unregister(value); } } public event AsyncEventHandler Disconnected { add { _disconnected.Register(value); } remove { _disconnected.Unregister(value); } } public event AsyncEventHandler MessageReceived { add { _messageReceived.Register(value); } remove { _messageReceived.Unregister(value); } } public event AsyncEventHandler ExceptionThrown { add { _exceptionThrown.Register(value); } remove { _exceptionThrown.Unregister(value); } } private WebSocketClient(IWebProxy proxy) { _connected = new AsyncEvent("WS_CONNECT", EventErrorHandler); _disconnected = new AsyncEvent("WS_DISCONNECT", EventErrorHandler); _messageReceived = new AsyncEvent("WS_MESSAGE", EventErrorHandler); _exceptionThrown = new AsyncEvent("WS_ERROR", null); Proxy = proxy; _defaultHeaders = new Dictionary(); DefaultHeaders = new ReadOnlyDictionary(_defaultHeaders); _receiverTokenSource = null; _receiverToken = CancellationToken.None; _senderLock = new SemaphoreSlim(1); _socketTokenSource = null; _socketToken = CancellationToken.None; } public async Task ConnectAsync(Uri uri) { try { await DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false); } catch { } await _senderLock.WaitAsync().ConfigureAwait(continueOnCapturedContext: false); try { _receiverTokenSource?.Dispose(); _socketTokenSource?.Dispose(); _ws?.Dispose(); _ws = new ClientWebSocket(); _ws.Options.Proxy = Proxy; _ws.Options.KeepAliveInterval = TimeSpan.Zero; if (_defaultHeaders != null) { foreach (var (headerName, headerValue) in _defaultHeaders) { _ws.Options.SetRequestHeader(headerName, headerValue); } } _receiverTokenSource = new CancellationTokenSource(); _receiverToken = _receiverTokenSource.Token; _socketTokenSource = new CancellationTokenSource(); _socketToken = _socketTokenSource.Token; _isClientClose = false; _isDisposed = false; await _ws.ConnectAsync(uri, _socketToken).ConfigureAwait(continueOnCapturedContext: false); _receiverTask = Task.Run((Func)ReceiverLoopAsync, _receiverToken); } finally { _senderLock.Release(); } } public async Task DisconnectAsync(int code = 1000, string message = "") { await _senderLock.WaitAsync().ConfigureAwait(continueOnCapturedContext: false); try { _isClientClose = true; if (_ws != null && (_ws.State == WebSocketState.Open || _ws.State == WebSocketState.CloseReceived)) { await _ws.CloseOutputAsync((WebSocketCloseStatus)code, message, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false); } if (_receiverTask != null) { await _receiverTask.ConfigureAwait(continueOnCapturedContext: false); } if (_isConnected) { _isConnected = false; } if (!_isDisposed) { if (_socketToken.CanBeCanceled) { _socketTokenSource?.Cancel(); } _socketTokenSource?.Dispose(); if (_receiverToken.CanBeCanceled) { _receiverTokenSource?.Cancel(); } _receiverTokenSource?.Dispose(); _isDisposed = true; } } catch { } finally { _senderLock.Release(); } } public async Task SendMessageAsync(string message) { if (_ws == null || (_ws.State != WebSocketState.Open && _ws.State != WebSocketState.CloseReceived)) { return; } byte[] bytes = Utilities.UTF8.GetBytes(message); await _senderLock.WaitAsync().ConfigureAwait(continueOnCapturedContext: false); try { int len = bytes.Length; int segCount = len / 8192; if (len % 8192 != 0) { segCount++; } for (int i = 0; i < segCount; i++) { int num = 8192 * i; int count = Math.Min(8192, len - num); await _ws.SendAsync(new ArraySegment(bytes, num, count), WebSocketMessageType.Text, i == segCount - 1, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false); } } finally { _senderLock.Release(); } } public bool AddDefaultHeader(string name, string value) { _defaultHeaders[name] = value; return true; } public bool RemoveDefaultHeader(string name) { return _defaultHeaders.Remove(name); } public void Dispose() { if (!_isDisposed) { _isDisposed = true; DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false).GetAwaiter().GetResult(); _receiverTokenSource?.Dispose(); _socketTokenSource?.Dispose(); } } internal async Task ReceiverLoopAsync() { await Task.Yield(); CancellationToken token = _receiverToken; ArraySegment buffer = new ArraySegment(new byte[32768]); try { using MemoryStream bs = new MemoryStream(); while (!token.IsCancellationRequested) { WebSocketReceiveResult result; do { result = await _ws.ReceiveAsync(buffer, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false); if (result.MessageType == WebSocketMessageType.Close) { break; } bs.Write(buffer.Array, 0, result.Count); } while (!result.EndOfMessage); byte[] resultBytes = new byte[bs.Length]; bs.Position = 0L; bs.Read(resultBytes, 0, resultBytes.Length); bs.Position = 0L; bs.SetLength(0L); if (!_isConnected && result.MessageType != WebSocketMessageType.Close) { _isConnected = true; await _connected.InvokeAsync(this, new SocketEventArgs()).ConfigureAwait(continueOnCapturedContext: false); } if (result.MessageType == WebSocketMessageType.Binary) { await _messageReceived.InvokeAsync(this, new SocketBinaryMessageEventArgs(resultBytes)).ConfigureAwait(continueOnCapturedContext: false); continue; } if (result.MessageType != 0) { if (!_isClientClose) { WebSocketCloseStatus value = result.CloseStatus.Value; value = ((value == WebSocketCloseStatus.NormalClosure || value == WebSocketCloseStatus.EndpointUnavailable) ? ((WebSocketCloseStatus)4000) : value); await _ws.CloseOutputAsync(value, result.CloseStatusDescription, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false); } await _disconnected.InvokeAsync(this, new SocketCloseEventArgs { CloseCode = (int)result.CloseStatus.Value, CloseMessage = result.CloseStatusDescription }).ConfigureAwait(continueOnCapturedContext: false); break; } await _messageReceived.InvokeAsync(this, new SocketTextMessageEventArgs(Utilities.UTF8.GetString(resultBytes))).ConfigureAwait(continueOnCapturedContext: false); } } catch (Exception exception) { await _exceptionThrown.InvokeAsync(this, new SocketErrorEventArgs { Exception = exception }).ConfigureAwait(continueOnCapturedContext: false); await _disconnected.InvokeAsync(this, new SocketCloseEventArgs { CloseCode = -1, CloseMessage = "" }).ConfigureAwait(continueOnCapturedContext: false); } DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false); } public static IWebSocketClient CreateNew(IWebProxy proxy) { return new WebSocketClient(proxy); } private void EventErrorHandler(AsyncEvent asyncEvent, Exception ex, AsyncEventHandler handler, WebSocketClient sender, TArgs eventArgs) where TArgs : AsyncEventArgs { _exceptionThrown.InvokeAsync(this, new SocketErrorEventArgs { Exception = ex }).ConfigureAwait(continueOnCapturedContext: false).GetAwaiter() .GetResult(); } } } namespace DSharpPlus.Net.Udp { internal delegate BaseUdpClient UdpClientFactoryDelegate(); internal abstract class BaseUdpClient { public abstract void Setup(ConnectionEndpoint endpoint); public abstract Task SendAsync(byte[] data, int dataLength); public abstract Task ReceiveAsync(); public abstract void Close(); } internal class DspUdpClient : BaseUdpClient { private UdpClient Client { get; set; } private ConnectionEndpoint EndPoint { get; set; } private BlockingCollection PacketQueue { get; } private Task ReceiverTask { get; set; } private CancellationTokenSource TokenSource { get; } private CancellationToken Token => TokenSource.Token; public DspUdpClient() { PacketQueue = new BlockingCollection(); TokenSource = new CancellationTokenSource(); } public override void Setup(ConnectionEndpoint endpoint) { EndPoint = endpoint; Client = new UdpClient(); ReceiverTask = Task.Run((Func)ReceiverLoopAsync, Token); } public override Task SendAsync(byte[] data, int dataLength) { return Client.SendAsync(data, dataLength, EndPoint.Hostname, EndPoint.Port); } public override Task ReceiveAsync() { return Task.FromResult(PacketQueue.Take(Token)); } public override void Close() { TokenSource.Cancel(); try { Client.Close(); } catch (Exception) { } PacketQueue.Dispose(); } private async Task ReceiverLoopAsync() { while (!Token.IsCancellationRequested) { try { UdpReceiveResult udpReceiveResult = await Client.ReceiveAsync().ConfigureAwait(continueOnCapturedContext: false); PacketQueue.Add(udpReceiveResult.Buffer); } catch (Exception) { } } } public static BaseUdpClient CreateNew() { return new DspUdpClient(); } } } namespace DSharpPlus.Net.Serialization { internal sealed class DiscordComponentJsonConverter : Newtonsoft.Json.JsonConverter { public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { throw new NotImplementedException(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } JObject jObject = JObject.Load(reader); ComponentType? componentType = jObject["type"]?.ToDiscordObject(); if (!componentType.HasValue) { throw new ArgumentException($"Value {reader} does not have a component type specifier"); } DiscordComponent discordComponent = componentType switch { ComponentType.ActionRow => new DiscordActionRowComponent(), ComponentType.Button => ((int)jObject["style"] != 5) ? ((DiscordComponent)new DiscordButtonComponent()) : ((DiscordComponent)new DiscordLinkButtonComponent()), ComponentType.StringSelect => new DiscordSelectComponent(), ComponentType.FormInput => new TextInputComponent(), ComponentType.UserSelect => new DiscordUserSelectComponent(), ComponentType.RoleSelect => new DiscordRoleSelectComponent(), ComponentType.MentionableSelect => new DiscordMentionableSelectComponent(), ComponentType.ChannelSelect => new DiscordChannelSelectComponent(), _ => new DiscordComponent { Type = componentType.Value }, }; using JsonReader reader2 = jObject.CreateReader(); serializer.Populate(reader2, discordComponent); return discordComponent; } public override bool CanConvert(Type objectType) { return typeof(DiscordComponent).IsAssignableFrom(objectType); } } internal class DiscordForumChannelJsonConverter : Newtonsoft.Json.JsonConverter { public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { throw new Exception(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { JObject jObject = JObject.Load(reader); ChannelType channelType = jObject["type"].ToObject(); DiscordChannel discordChannel; if (channelType == ChannelType.GuildForum) { DiscordForumChannel discordForumChannel = new DiscordForumChannel(); serializer.Populate(jObject.CreateReader(), discordForumChannel); discordChannel = discordForumChannel; } else if ((uint)(channelType - 10) <= 2u) { DiscordThreadChannel discordThreadChannel = new DiscordThreadChannel(); serializer.Populate(jObject.CreateReader(), discordThreadChannel); discordChannel = discordThreadChannel; } else if (channelType == ChannelType.Private) { discordChannel = new DiscordDmChannel(); serializer.Populate(jObject.CreateReader(), discordChannel); } else { discordChannel = new DiscordChannel(); serializer.Populate(jObject.CreateReader(), discordChannel); } return discordChannel; } public override bool CanConvert(Type objectType) { return objectType.IsAssignableFrom(typeof(DiscordChannel)); } } internal static class DiscordJson { private static readonly Newtonsoft.Json.JsonSerializer _serializer = Newtonsoft.Json.JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = new OptionalJsonContractResolver(), DateParseHandling = DateParseHandling.None, Converters = new Newtonsoft.Json.JsonConverter[2] { new ISO8601DateTimeOffsetJsonConverter(), new DiscordPermissionsJsonConverter() } }); public static string SerializeObject(object value) { return SerializeObjectInternal(value, null, _serializer); } public static void PopulateObject(JToken value, object target) { using JsonReader reader = value.CreateReader(); _serializer.Populate(reader, target); } public static T ToDiscordObject(this JToken token) { return token.ToObject(_serializer); } private static string SerializeObjectInternal(object value, Type type, Newtonsoft.Json.JsonSerializer jsonSerializer) { StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)) { jsonTextWriter.Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize(jsonTextWriter, value, type); } return stringWriter.ToString(); } } internal class DiscordPermissionsJsonConverter : Newtonsoft.Json.JsonConverter { public override Permissions ReadJson(JsonReader reader, Type objectType, Permissions existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer) { JToken jToken = JToken.Load(reader); if (jToken == null || jToken.Type == JTokenType.Null) { return Permissions.None; } return (Permissions)(ulong)(jToken.ToObject() & ulong.MaxValue); } public override void WriteJson(JsonWriter writer, Permissions value, Newtonsoft.Json.JsonSerializer serializer) { ulong num = (ulong)value; writer.WriteValue(num.ToString(CultureInfo.InvariantCulture)); } } internal sealed class ISO8601DateTimeOffsetJsonConverter : Newtonsoft.Json.JsonConverter { public override void WriteJson(JsonWriter writer, object? value, Newtonsoft.Json.JsonSerializer serializer) { writer.WriteValue(((DateTimeOffset)value).ToString("O", CultureInfo.InvariantCulture)); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer) { return JToken.Load(reader).ToObject(); } public override bool CanConvert(Type objectType) { return objectType == typeof(DateTimeOffset); } } internal class SnowflakeArrayAsDictionaryJsonConverter : Newtonsoft.Json.JsonConverter { public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { if (value == null) { writer.WriteNull(); } else { JToken.FromObject(value.GetType().GetTypeInfo().GetDeclaredProperty("Values") .GetValue(value)).WriteTo(writer); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { object obj = objectType.GetTypeInfo().DeclaredConstructors.FirstOrDefault((ConstructorInfo e) => !e.IsStatic && e.GetParameters().Length == 0).Invoke(new object[0]); PropertyInfo declaredProperty = objectType.GetTypeInfo().GetDeclaredProperty("Item"); foreach (object item in (IEnumerable)serializer.Deserialize(reader, objectType.GenericTypeArguments[1].MakeArrayType())) { declaredProperty.SetValue(obj, item, new object[1] { (item as SnowflakeObject)?.Id ?? ((item as DiscordVoiceState) ?? throw new InvalidOperationException($"Type {item?.GetType()} is not deserializable")).UserId }); } return obj; } public override bool CanConvert(Type objectType) { Type genericTypeDefinition = objectType.GetGenericTypeDefinition(); if (genericTypeDefinition != typeof(Dictionary<, >) && genericTypeDefinition != typeof(ConcurrentDictionary<, >)) { return false; } if (objectType.GenericTypeArguments[0] != typeof(ulong)) { return false; } Type type = objectType.GenericTypeArguments[1]; if (!typeof(SnowflakeObject).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())) { return type == typeof(DiscordVoiceState); } return true; } } } namespace DSharpPlus.Net.Models { internal class ApplicationCommandEditModel { private Optional _name; private Optional _description; public Optional Name { internal get { return _name; } set { if (value.Value.Length > 32) { throw new ArgumentException("Application command name cannot exceed 32 characters.", "value"); } _name = value; } } public Optional Description { internal get { return _description; } set { if (value.Value.Length > 100) { throw new ArgumentException("Application command description cannot exceed 100 characters.", "value"); } _description = value; } } public Optional> Options { internal get; set; } public Optional DefaultPermission { internal get; set; } public Optional AllowDMUsage { internal get; set; } public Optional DefaultMemberPermissions { internal get; set; } } internal class BaseEditModel { public string AuditLogReason { internal get; set; } } internal class ChannelEditModel : BaseEditModel { public string Name { internal get; set; } public int? Position { internal get; set; } public Optional Topic { internal get; set; } public bool? Nsfw { internal get; set; } public Optional Parent { internal get; set; } public int? Bitrate { internal get; set; } public int? Userlimit { internal get; set; } public Optional PerUserRateLimit { internal get; set; } public Optional RtcRegion { internal get; set; } public VideoQualityMode? QualityMode { internal get; set; } public Optional Type { internal get; set; } public IEnumerable PermissionOverwrites { internal get; set; } public Optional DefaultAutoArchiveDuration { internal get; set; } public Optional Flags { internal get; set; } public IEnumerable AvailableTags { internal get; set; } public Optional DefaultReaction { internal get; set; } public Optional DefaultThreadRateLimit { internal get; set; } public Optional DefaultSortOrder { internal get; set; } public Optional DefaultForumLayout { internal get; set; } internal ChannelEditModel() { } } internal class GuildEditModel : BaseEditModel { public Optional Name { internal get; set; } public Optional Region { internal get; set; } public Optional Icon { internal get; set; } public Optional VerificationLevel { internal get; set; } public Optional DefaultMessageNotifications { internal get; set; } public Optional MfaLevel { internal get; set; } public Optional ExplicitContentFilter { internal get; set; } public Optional AfkChannel { internal get; set; } public Optional AfkTimeout { internal get; set; } public Optional Owner { internal get; set; } public Optional Splash { internal get; set; } public Optional SystemChannel { internal get; set; } public Optional RulesChannel { internal get; set; } public Optional PublicUpdatesChannel { internal get; set; } public Optional PreferredLocale { internal get; set; } public Optional Description { get; set; } public Optional DiscoverySplash { get; set; } public Optional> Features { get; set; } public Optional Banner { get; set; } public Optional SystemChannelFlags { get; set; } internal GuildEditModel() { } } internal class MemberEditModel : BaseEditModel { public Optional Nickname { internal get; set; } public Optional> Roles { internal get; set; } public Optional Muted { internal get; set; } public Optional Deafened { internal get; set; } public Optional VoiceChannel { internal get; set; } public Optional CommunicationDisabledUntil { internal get; set; } internal MemberEditModel() { } } internal class MembershipScreeningEditModel : BaseEditModel { public Optional Enabled { internal get; set; } public Optional Description { internal get; set; } public Optional Fields { internal get; set; } internal MembershipScreeningEditModel() { } } internal class RoleEditModel : BaseEditModel { public string Name { internal get; set; } public Permissions? Permissions { internal get; set; } public DiscordColor? Color { internal get; set; } public bool? Hoist { internal get; set; } public bool? Mentionable { internal get; set; } public DiscordEmoji Emoji { internal get; set; } public Stream Icon { internal get; set; } internal RoleEditModel() { Name = null; Permissions = null; Color = null; Hoist = null; Mentionable = null; } } internal class ScheduledGuildEventEditModel : BaseEditModel { public Optional Name { get; set; } public Optional Description { get; set; } public Optional Channel { get; set; } public Optional PrivacyLevel { get; set; } public Optional Type { get; set; } public Optional StartTime { get; set; } public Optional EndTime { get; set; } public Optional Metadata { get; set; } public Optional Status { get; set; } internal ScheduledGuildEventEditModel() { } } internal class StageInstanceEditModel : BaseEditModel { public Optional Topic { internal get; set; } public Optional PrivacyLevel { internal get; set; } } internal class StickerEditModel : BaseEditModel { public Optional Name { internal get; set; } public Optional Description { internal get; set; } public Optional Tags { internal get; set; } } internal class ThreadChannelEditModel : ChannelEditModel { public bool? IsArchived { internal get; set; } public AutoArchiveDuration? AutoArchiveDuration { internal get; set; } public bool? Locked { internal get; set; } public IEnumerable AppliedTags { internal get; set; } public new ChannelFlags? Flags { internal get; set; } internal ThreadChannelEditModel() { } } internal class WelcomeScreenEditModel { public Optional Enabled { internal get; set; } public Optional> WelcomeChannels { internal get; set; } public Optional Description { internal get; set; } } } namespace DSharpPlus.Net.Abstractions { internal sealed class AuditLogUser { [JsonProperty("username")] public string Username { get; set; } [JsonProperty("discriminator")] public string Discriminator { get; set; } [JsonProperty("id")] public ulong Id { get; set; } [JsonProperty("avatar")] public string AvatarHash { get; set; } } internal sealed class AuditLogWebhook { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("channel_id")] public ulong ChannelId { get; set; } [JsonProperty("token")] public string Token { get; set; } [JsonProperty("avatar")] public string AvatarHash { get; set; } [JsonProperty("guild_id")] public ulong GuildId { get; set; } [JsonProperty("id")] public ulong Id { get; set; } } internal sealed class AuditLogActionChange { [JsonProperty("old_value")] public object OldValue { get; set; } [Newtonsoft.Json.JsonIgnore] public IEnumerable OldValues => (OldValue as JArray)?.ToDiscordObject>(); [Newtonsoft.Json.JsonIgnore] public ulong OldValueUlong => (ulong)OldValue; [Newtonsoft.Json.JsonIgnore] public string OldValueString => (string)OldValue; [Newtonsoft.Json.JsonIgnore] public bool OldValueBool => (bool)OldValue; [Newtonsoft.Json.JsonIgnore] public long OldValueLong => (long)OldValue; [JsonProperty("new_value")] public object NewValue { get; set; } [Newtonsoft.Json.JsonIgnore] public IEnumerable NewValues => (NewValue as JArray)?.ToDiscordObject>(); [Newtonsoft.Json.JsonIgnore] public ulong NewValueUlong => (ulong)NewValue; [Newtonsoft.Json.JsonIgnore] public string NewValueString => (string)NewValue; [Newtonsoft.Json.JsonIgnore] public bool NewValueBool => (bool)NewValue; [Newtonsoft.Json.JsonIgnore] public long NewValueLong => (long)NewValue; [JsonProperty("key")] public string Key { get; set; } } internal sealed class AuditLogActionOptions { [JsonProperty("type")] public object Type { get; set; } [JsonProperty("id")] public ulong Id { get; set; } [JsonProperty("channel_id")] public ulong ChannelId { get; set; } [JsonProperty("message_id")] public ulong MessageId { get; set; } [JsonProperty("count")] public int Count { get; set; } [JsonProperty("delete_member_days")] public int DeleteMemberDays { get; set; } [JsonProperty("members_removed")] public int MembersRemoved { get; set; } } internal sealed class AuditLogAction { [JsonProperty("target_id")] public ulong? TargetId { get; set; } [JsonProperty("user_id")] public ulong UserId { get; set; } [JsonProperty("id")] public ulong Id { get; set; } [JsonProperty("action_type")] public AuditLogActionType ActionType { get; set; } [JsonProperty("changes")] public IEnumerable Changes { get; set; } [JsonProperty("options")] public AuditLogActionOptions Options { get; set; } [JsonProperty("reason")] public string Reason { get; set; } } internal sealed class AuditLog { [JsonProperty("webhooks")] public IEnumerable Webhooks { get; set; } [JsonProperty("users")] public IEnumerable Users { get; set; } [JsonProperty("audit_log_entries")] public IEnumerable Entries { get; set; } [JsonProperty("guild_scheduled_events")] public IEnumerable Events { get; set; } [JsonProperty("integrations")] public IEnumerable Integrations { get; set; } [JsonProperty("threads")] public IEnumerable Threads { get; set; } } internal sealed class ClientProperties { [JsonProperty("$os")] public string OperatingSystem { get { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return "windows"; } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return "linux"; } if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return "osx"; } string text = RuntimeInformation.OSDescription.ToLowerInvariant(); if (text.Contains("freebsd")) { return "freebsd"; } if (text.Contains("openbsd")) { return "openbsd"; } if (text.Contains("netbsd")) { return "netbsd"; } if (text.Contains("dragonfly")) { return "dragonflybsd"; } if (text.Contains("miros bsd") || text.Contains("mirbsd")) { return "miros bsd"; } if (text.Contains("desktopbsd")) { return "desktopbsd"; } if (text.Contains("darwin")) { return "osx"; } if (!text.Contains("unix")) { return "toaster (unknown)"; } return "unix"; } } [JsonProperty("$browser")] public string Browser { get { AssemblyName name = typeof(DiscordClient).GetTypeInfo().Assembly.GetName(); return "DSharpPlus " + name.Version.ToString(4); } } [JsonProperty("$device")] public string Device => Browser; [JsonProperty("$referrer")] public string Referrer => ""; [JsonProperty("$referring_domain")] public string ReferringDomain => ""; } internal sealed class FollowedChannelAddPayload { [JsonProperty("webhook_channel_id")] public ulong WebhookChannelId { get; set; } } internal sealed class GatewayHello { [JsonProperty("heartbeat_interval")] public int HeartbeatInterval { get; private set; } [JsonProperty("_trace")] public IReadOnlyList Trace { get; private set; } } internal sealed class GatewayIdentify { [JsonProperty("token")] public string Token { get; set; } [JsonProperty("properties")] public ClientProperties ClientProperties { get; } = new ClientProperties(); [JsonProperty("compress")] public bool Compress { get; set; } [JsonProperty("large_threshold")] public int LargeThreshold { get; set; } [JsonProperty("shard")] public ShardInfo ShardInfo { get; set; } [JsonProperty("presence", NullValueHandling = NullValueHandling.Ignore)] public StatusUpdate Presence { get; set; } [JsonProperty("intents")] public DiscordIntents Intents { get; set; } } internal sealed class GatewayResume { [JsonProperty("token")] public string Token { get; set; } [JsonProperty("session_id")] public string SessionId { get; set; } [JsonProperty("seq")] public long SequenceNumber { get; set; } } internal enum GatewayOpCode { Dispatch, Heartbeat, Identify, StatusUpdate, VoiceStateUpdate, VoiceServerPing, Resume, Reconnect, RequestGuildMembers, InvalidSession, Hello, HeartbeatAck, GuildSync } internal sealed class GatewayPayload { [JsonProperty("op")] public GatewayOpCode OpCode { get; set; } [JsonProperty("d")] public object Data { get; set; } [JsonProperty("s", NullValueHandling = NullValueHandling.Ignore)] public int? Sequence { get; set; } [JsonProperty("t", NullValueHandling = NullValueHandling.Ignore)] public string EventName { get; set; } } internal sealed class GatewayRequestGuildMembers { [JsonProperty("guild_id")] public ulong GuildId { get; } [JsonProperty("query", NullValueHandling = NullValueHandling.Ignore)] public string Query { get; set; } [JsonProperty("limit")] public int Limit { get; set; } [JsonProperty("presences", NullValueHandling = NullValueHandling.Ignore)] public bool? Presences { get; set; } [JsonProperty("user_ids", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable UserIds { get; set; } [JsonProperty("nonce", NullValueHandling = NullValueHandling.Ignore)] public string Nonce { get; internal set; } public GatewayRequestGuildMembers(DiscordGuild guild) { GuildId = guild.Id; } } internal interface IOAuth2Payload { string AccessToken { get; set; } } internal class ReadyPayload { [JsonProperty("v")] public int GatewayVersion { get; private set; } [JsonProperty("user")] public TransportUser CurrentUser { get; private set; } [JsonProperty("private_channels")] public IReadOnlyList DmChannels { get; private set; } [JsonProperty("guilds")] public IReadOnlyList Guilds { get; private set; } [JsonProperty("session_id")] public string SessionId { get; private set; } [JsonProperty("_trace")] public IReadOnlyList Trace { get; private set; } } internal class RestApplicationCommandCreatePayload { [JsonProperty("type")] public ApplicationCommandType Type { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; set; } [JsonProperty("options", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Options { get; set; } [JsonProperty("default_permission", NullValueHandling = NullValueHandling.Ignore)] public bool? DefaultPermission { get; set; } [JsonProperty("name_localizations")] public IReadOnlyDictionary NameLocalizations { get; set; } [JsonProperty("description_localizations")] public IReadOnlyDictionary DescriptionLocalizations { get; set; } [JsonProperty("dm_permission", NullValueHandling = NullValueHandling.Ignore)] public bool? AllowDMUsage { get; set; } [JsonProperty("default_member_permissions", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions? DefaultMemberPermissions { get; set; } } internal class RestApplicationCommandEditPayload { [JsonProperty("name")] public Optional Name { get; set; } [JsonProperty("description")] public Optional Description { get; set; } [JsonProperty("options")] public Optional> Options { get; set; } [JsonProperty("default_permission", NullValueHandling = NullValueHandling.Ignore)] public Optional DefaultPermission { get; set; } [JsonProperty("name_localizations")] public IReadOnlyDictionary NameLocalizations { get; set; } [JsonProperty("description_localizations")] public IReadOnlyDictionary DescriptionLocalizations { get; set; } [JsonProperty("dm_permission", NullValueHandling = NullValueHandling.Ignore)] public Optional AllowDMUsage { get; set; } [JsonProperty("default_member_permissions", NullValueHandling = NullValueHandling.Ignore)] public Optional DefaultMemberPermissions { get; set; } } internal class RestInteractionResponsePayload { [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public InteractionResponseType Type { get; set; } [JsonProperty("data", NullValueHandling = NullValueHandling.Ignore)] public DiscordInteractionApplicationCommandCallbackData Data { get; set; } } internal class RestFollowupMessageCreatePayload { [JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)] public string Content { get; set; } [JsonProperty("tts", NullValueHandling = NullValueHandling.Ignore)] public bool? IsTTS { get; set; } [JsonProperty("embeds", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Embeds { get; set; } [JsonProperty("allowed_mentions", NullValueHandling = NullValueHandling.Ignore)] public DiscordMentions Mentions { get; set; } [JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)] public int? Flags { get; set; } [JsonProperty("components", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyCollection Components { get; set; } } internal class RestEditApplicationCommandPermissionsPayload { [JsonProperty("permissions")] public IEnumerable Permissions { get; set; } } internal sealed class RestChannelCreatePayload { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("type")] public ChannelType Type { get; set; } [JsonProperty("parent_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? Parent { get; set; } [JsonProperty("topic")] public Optional Topic { get; set; } [JsonProperty("bitrate", NullValueHandling = NullValueHandling.Ignore)] public int? Bitrate { get; set; } [JsonProperty("user_limit", NullValueHandling = NullValueHandling.Ignore)] public int? UserLimit { get; set; } [JsonProperty("permission_overwrites", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable PermissionOverwrites { get; set; } [JsonProperty("nsfw", NullValueHandling = NullValueHandling.Ignore)] public bool? Nsfw { get; set; } [JsonProperty("rate_limit_per_user")] public Optional PerUserRateLimit { get; set; } [JsonProperty("video_quality_mode", NullValueHandling = NullValueHandling.Ignore)] public VideoQualityMode? QualityMode { get; set; } [JsonProperty("position", NullValueHandling = NullValueHandling.Ignore)] public int? Position { get; set; } [JsonProperty("default_auth_archive_duration", NullValueHandling = NullValueHandling.Ignore)] public AutoArchiveDuration? DefaultAutoArchiveDuration { get; set; } [JsonProperty("default_reaction_emoji", NullValueHandling = NullValueHandling.Ignore)] public DefaultReaction? DefaultReaction { get; set; } [JsonProperty("available_tags", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable AvailableTags { get; set; } [JsonProperty("default_sort_order", NullValueHandling = NullValueHandling.Ignore)] public DefaultSortOrder? DefaultSortOrder { get; set; } } internal sealed class RestChannelModifyPayload { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } [JsonProperty("type")] public Optional Type { get; set; } [JsonProperty("position", NullValueHandling = NullValueHandling.Ignore)] public int? Position { get; set; } [JsonProperty("topic")] public Optional Topic { get; set; } [JsonProperty("nsfw", NullValueHandling = NullValueHandling.Ignore)] public bool? Nsfw { get; set; } [JsonProperty("parent_id")] public Optional Parent { get; set; } [JsonProperty("bitrate", NullValueHandling = NullValueHandling.Ignore)] public int? Bitrate { get; set; } [JsonProperty("user_limit", NullValueHandling = NullValueHandling.Ignore)] public int? UserLimit { get; set; } [JsonProperty("permission_overwrites", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable PermissionOverwrites { get; set; } [JsonProperty("rate_limit_per_user")] public Optional PerUserRateLimit { get; set; } [JsonProperty("rtc_region")] public Optional RtcRegion { get; set; } [JsonProperty("video_quality_mode", NullValueHandling = NullValueHandling.Ignore)] public VideoQualityMode? QualityMode { get; set; } [JsonProperty("default_auto_archive_duration", NullValueHandling = NullValueHandling.Ignore)] public Optional DefaultAutoArchiveDuration { get; set; } [JsonProperty("default_sort_order", NullValueHandling = NullValueHandling.Ignore)] public Optional DefaultSortOrder { get; set; } [JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)] public Optional Flags { get; set; } [JsonProperty("default_reaction_emoji", NullValueHandling = NullValueHandling.Ignore)] public Optional DefaultReaction { get; set; } [JsonProperty("available_tags", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable AvailableTags { get; set; } [JsonProperty("default_forum_layout", NullValueHandling = NullValueHandling.Ignore)] public Optional DefaultForumLayout { get; set; } } internal sealed class RestThreadChannelModifyPayload { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } [JsonProperty("type")] public Optional Type { get; set; } [JsonProperty("position", NullValueHandling = NullValueHandling.Ignore)] public int? Position { get; set; } [JsonProperty("topic")] public Optional Topic { get; set; } [JsonProperty("nsfw", NullValueHandling = NullValueHandling.Ignore)] public bool? Nsfw { get; set; } [JsonProperty("parent_id")] public Optional Parent { get; set; } [JsonProperty("bitrate", NullValueHandling = NullValueHandling.Ignore)] public int? Bitrate { get; set; } [JsonProperty("user_limit", NullValueHandling = NullValueHandling.Ignore)] public int? UserLimit { get; set; } [JsonProperty("permission_overwrites", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable PermissionOverwrites { get; set; } [JsonProperty("rate_limit_per_user")] public Optional PerUserRateLimit { get; set; } [JsonProperty("rtc_region")] public Optional RtcRegion { get; set; } [JsonProperty("video_quality_mode", NullValueHandling = NullValueHandling.Ignore)] public VideoQualityMode? QualityMode { get; set; } [JsonProperty("archived", NullValueHandling = NullValueHandling.Ignore)] public bool? IsArchived { get; set; } [JsonProperty("auto_archive_duration", NullValueHandling = NullValueHandling.Ignore)] public AutoArchiveDuration? ArchiveDuration { get; set; } [JsonProperty("locked", NullValueHandling = NullValueHandling.Ignore)] public bool? Locked { get; set; } [JsonProperty("applied_tags", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable AppliedTags { get; set; } } internal class RestChannelMessageEditPayload { [JsonProperty("content", NullValueHandling = NullValueHandling.Include)] public string Content { get; set; } [Newtonsoft.Json.JsonIgnore] public bool HasContent { get; set; } [JsonProperty("embeds", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Embeds { get; set; } [JsonProperty("allowed_mentions", NullValueHandling = NullValueHandling.Ignore)] public DiscordMentions Mentions { get; set; } [JsonProperty("components", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyCollection Components { get; set; } [JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)] public MessageFlags? Flags { get; set; } [JsonProperty("attachments", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Attachments { get; set; } [Newtonsoft.Json.JsonIgnore] public bool HasEmbed { get; set; } public bool ShouldSerializeContent() { return HasContent; } public bool ShouldSerializeEmbed() { return HasEmbed; } } internal sealed class RestChannelMessageCreatePayload : RestChannelMessageEditPayload { [JsonProperty("tts", NullValueHandling = NullValueHandling.Ignore)] public bool? IsTTS { get; set; } [JsonProperty("sticker_ids", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable StickersIds { get; set; } [JsonProperty("message_reference", NullValueHandling = NullValueHandling.Ignore)] public InternalDiscordMessageReference? MessageReference { get; set; } } internal sealed class RestChannelMessageCreateMultipartPayload { [JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)] public string Content { get; set; } [JsonProperty("tts", NullValueHandling = NullValueHandling.Ignore)] public bool? IsTTS { get; set; } [JsonProperty("embeds", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Embeds { get; set; } [JsonProperty("allowed_mentions", NullValueHandling = NullValueHandling.Ignore)] public DiscordMentions Mentions { get; set; } [JsonProperty("message_reference", NullValueHandling = NullValueHandling.Ignore)] public InternalDiscordMessageReference? MessageReference { get; set; } } internal sealed class RestChannelMessageBulkDeletePayload { [JsonProperty("messages", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Messages { get; set; } } internal sealed class RestChannelMessageSuppressEmbedsPayload { [JsonProperty("suppress", NullValueHandling = NullValueHandling.Ignore)] public bool? Suppress { get; set; } } internal sealed class RestChannelInviteCreatePayload { [JsonProperty("max_age", NullValueHandling = NullValueHandling.Ignore)] public int MaxAge { get; set; } [JsonProperty("max_uses", NullValueHandling = NullValueHandling.Ignore)] public int MaxUses { get; set; } [JsonProperty("temporary", NullValueHandling = NullValueHandling.Ignore)] public bool Temporary { get; set; } [JsonProperty("unique", NullValueHandling = NullValueHandling.Ignore)] public bool Unique { get; set; } [JsonProperty("target_type", NullValueHandling = NullValueHandling.Ignore)] public InviteTargetType? TargetType { get; set; } [JsonProperty("target_user_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? TargetUserId { get; set; } [JsonProperty("target_application_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? TargetApplicationId { get; set; } } internal sealed class RestChannelPermissionEditPayload { [JsonProperty("allow", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions Allow { get; set; } [JsonProperty("deny", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions Deny { get; set; } [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public string Type { get; set; } } internal sealed class RestChannelGroupDmRecipientAddPayload : IOAuth2Payload { [JsonProperty("access_token")] public string AccessToken { get; set; } [JsonProperty("nick", NullValueHandling = NullValueHandling.Ignore)] public string Nickname { get; set; } } internal sealed class AcknowledgePayload { [JsonProperty("token", NullValueHandling = NullValueHandling.Include)] public string Token { get; set; } } internal sealed class RestCreateStageInstancePayload { [JsonProperty("channel_id")] public ulong ChannelId { get; set; } [JsonProperty("topic")] public string Topic { get; set; } [JsonProperty("privacy_level", NullValueHandling = NullValueHandling.Ignore)] public PrivacyLevel? PrivacyLevel { get; set; } } internal sealed class RestModifyStageInstancePayload { [JsonProperty("topic")] public Optional Topic { get; set; } [JsonProperty("privacy_level")] public Optional PrivacyLevel { get; set; } } internal sealed class RestBecomeStageSpeakerInstancePayload { [JsonProperty("channel_id")] public ulong ChannelId { get; set; } [JsonProperty("request_to_speak_timestamp", NullValueHandling = NullValueHandling.Ignore)] public DateTime? RequestToSpeakTimestamp { get; set; } [JsonProperty("suppress", NullValueHandling = NullValueHandling.Ignore)] public bool? Suppress { get; set; } } internal interface IReasonAction { string Reason { get; set; } } internal class RestGuildCreatePayload { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } [JsonProperty("region", NullValueHandling = NullValueHandling.Ignore)] public string RegionId { get; set; } [JsonProperty("icon", NullValueHandling = NullValueHandling.Include)] public Optional IconBase64 { get; set; } [JsonProperty("verification_level", NullValueHandling = NullValueHandling.Ignore)] public VerificationLevel? VerificationLevel { get; set; } [JsonProperty("default_message_notifications", NullValueHandling = NullValueHandling.Ignore)] public DefaultMessageNotifications? DefaultMessageNotifications { get; set; } [JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Roles { get; set; } [JsonProperty("channels", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Channels { get; set; } [JsonProperty("system_channel_flags", NullValueHandling = NullValueHandling.Ignore)] public SystemChannelFlags? SystemChannelFlags { get; set; } } internal sealed class RestGuildCreateFromTemplatePayload { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } [JsonProperty("icon", NullValueHandling = NullValueHandling.Include)] public Optional IconBase64 { get; set; } } internal sealed class RestGuildModifyPayload { [JsonProperty("name")] public Optional Name { get; set; } [JsonProperty("region")] public Optional RegionId { get; set; } [JsonProperty("icon")] public Optional IconBase64 { get; set; } [JsonProperty("verification_level")] public Optional VerificationLevel { get; set; } [JsonProperty("default_message_notifications")] public Optional DefaultMessageNotifications { get; set; } [JsonProperty("owner_id")] public Optional OwnerId { get; set; } [JsonProperty("splash")] public Optional SplashBase64 { get; set; } [JsonProperty("afk_channel_id")] public Optional AfkChannelId { get; set; } [JsonProperty("afk_timeout")] public Optional AfkTimeout { get; set; } [JsonProperty("mfa_level")] public Optional MfaLevel { get; set; } [JsonProperty("explicit_content_filter")] public Optional ExplicitContentFilter { get; set; } [JsonProperty("system_channel_id", NullValueHandling = NullValueHandling.Include)] public Optional SystemChannelId { get; set; } [JsonProperty("banner")] public Optional Banner { get; set; } [JsonProperty("discorvery_splash")] public Optional DiscoverySplash { get; set; } [JsonProperty("system_channel_flags")] public Optional SystemChannelFlags { get; set; } [JsonProperty("rules_channel_id")] public Optional RulesChannelId { get; set; } [JsonProperty("public_updates_channel_id")] public Optional PublicUpdatesChannelId { get; set; } [JsonProperty("preferred_locale")] public Optional PreferredLocale { get; set; } [JsonProperty("description")] public Optional Description { get; set; } [JsonProperty("features")] public Optional> Features { get; set; } } internal sealed class RestGuildMemberAddPayload : IOAuth2Payload { [JsonProperty("access_token")] public string AccessToken { get; set; } [JsonProperty("nick", NullValueHandling = NullValueHandling.Ignore)] public string Nickname { get; set; } [JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Roles { get; set; } [JsonProperty("mute", NullValueHandling = NullValueHandling.Ignore)] public bool? Mute { get; set; } [JsonProperty("deaf", NullValueHandling = NullValueHandling.Ignore)] public bool? Deaf { get; set; } } internal sealed class RestScheduledGuildEventCreatePayload { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; set; } [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? ChannelId { get; set; } [JsonProperty("privacy_level", NullValueHandling = NullValueHandling.Ignore)] public ScheduledGuildEventPrivacyLevel PrivacyLevel { get; set; } [JsonProperty("entity_type", NullValueHandling = NullValueHandling.Ignore)] public ScheduledGuildEventType Type { get; set; } [JsonProperty("scheduled_start_time", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset StartTime { get; set; } [JsonProperty("scheduled_end_time", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset? EndTime { get; set; } [JsonProperty("entity_metadata", NullValueHandling = NullValueHandling.Ignore)] public DiscordScheduledGuildEventMetadata Metadata { get; set; } } internal sealed class RestScheduledGuildEventModifyPayload { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public Optional Name { get; set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public Optional Description { get; set; } [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)] public Optional ChannelId { get; set; } [JsonProperty("privacy_level", NullValueHandling = NullValueHandling.Ignore)] public Optional PrivacyLevel { get; set; } [JsonProperty("entity_type", NullValueHandling = NullValueHandling.Ignore)] public Optional Type { get; set; } [JsonProperty("scheduled_start_time", NullValueHandling = NullValueHandling.Ignore)] public Optional StartTime { get; set; } [JsonProperty("scheduled_end_time", NullValueHandling = NullValueHandling.Ignore)] public Optional EndTime { get; set; } [JsonProperty("entity_metadata", NullValueHandling = NullValueHandling.Ignore)] public Optional Metadata { get; set; } [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] public Optional Status { get; set; } } internal sealed class RestGuildChannelReorderPayload { [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public ulong ChannelId { get; set; } [JsonProperty("position", NullValueHandling = NullValueHandling.Ignore)] public int Position { get; set; } [JsonProperty("lock_permissions", NullValueHandling = NullValueHandling.Ignore)] public bool? LockPermissions { get; set; } [JsonProperty("parent_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? ParentId { get; set; } } internal sealed class RestGuildRoleReorderPayload { [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public ulong RoleId { get; set; } [JsonProperty("position", NullValueHandling = NullValueHandling.Ignore)] public int Position { get; set; } } internal sealed class RestGuildMemberModifyPayload { [JsonProperty("nick")] public Optional Nickname { get; set; } [JsonProperty("roles")] public Optional> RoleIds { get; set; } [JsonProperty("mute")] public Optional Mute { get; set; } [JsonProperty("deaf")] public Optional Deafen { get; set; } [JsonProperty("channel_id")] public Optional VoiceChannelId { get; set; } [JsonProperty("communication_disabled_until", NullValueHandling = NullValueHandling.Include)] public Optional CommunicationDisabledUntil { get; set; } } internal sealed class RestGuildRolePayload { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } [JsonProperty("permissions", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions? Permissions { get; set; } [JsonProperty("color", NullValueHandling = NullValueHandling.Ignore)] public int? Color { get; set; } [JsonProperty("hoist", NullValueHandling = NullValueHandling.Ignore)] public bool? Hoist { get; set; } [JsonProperty("mentionable", NullValueHandling = NullValueHandling.Ignore)] public bool? Mentionable { get; set; } [JsonProperty("unicode_emoji", NullValueHandling = NullValueHandling.Ignore)] public string Emoji { get; set; } [JsonProperty("icon", NullValueHandling = NullValueHandling.Ignore)] public string Icon { get; set; } } internal sealed class RestGuildPruneResultPayload { [JsonProperty("pruned", NullValueHandling = NullValueHandling.Ignore)] public int? Pruned { get; set; } } internal sealed class RestGuildIntegrationAttachPayload { [JsonProperty("type")] public string Type { get; set; } [JsonProperty("id")] public ulong Id { get; set; } } internal sealed class RestGuildIntegrationModifyPayload { [JsonProperty("expire_behavior", NullValueHandling = NullValueHandling.Ignore)] public int? ExpireBehavior { get; set; } [JsonProperty("expire_grace_period", NullValueHandling = NullValueHandling.Ignore)] public int? ExpireGracePeriod { get; set; } [JsonProperty("enable_emoticons", NullValueHandling = NullValueHandling.Ignore)] public bool? EnableEmoticons { get; set; } } internal class RestGuildEmojiModifyPayload { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)] public ulong[] Roles { get; set; } } internal class RestGuildEmojiCreatePayload : RestGuildEmojiModifyPayload { [JsonProperty("image")] public string ImageB64 { get; set; } } internal class RestGuildWidgetSettingsPayload { [JsonProperty("enabled", NullValueHandling = NullValueHandling.Ignore)] public bool? Enabled { get; set; } [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? ChannelId { get; set; } } internal class RestGuildTemplateCreateOrModifyPayload { [JsonProperty("name", NullValueHandling = NullValueHandling.Include)] public string Name { get; set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Include)] public string Description { get; set; } } internal class RestGuildMembershipScreeningFormModifyPayload { [JsonProperty("enabled", NullValueHandling = NullValueHandling.Ignore)] public Optional Enabled { get; set; } [JsonProperty("form_fields", NullValueHandling = NullValueHandling.Ignore)] public Optional Fields { get; set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public Optional Description { get; set; } } internal class RestGuildWelcomeScreenModifyPayload { [JsonProperty("enabled", NullValueHandling = NullValueHandling.Ignore)] public Optional Enabled { get; set; } [JsonProperty("welcome_channels", NullValueHandling = NullValueHandling.Ignore)] public Optional> WelcomeChannels { get; set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public Optional Description { get; set; } } internal class RestGuildUpdateCurrentUserVoiceStatePayload { [JsonProperty("channel_id")] public ulong ChannelId { get; set; } [JsonProperty("suppress", NullValueHandling = NullValueHandling.Ignore)] public bool? Suppress { get; set; } [JsonProperty("request_to_speak_timestamp", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset? RequestToSpeakTimestamp { get; set; } } internal class RestGuildUpdateUserVoiceStatePayload { [JsonProperty("channel_id")] public ulong ChannelId { get; set; } [JsonProperty("suppress", NullValueHandling = NullValueHandling.Ignore)] public bool? Suppress { get; set; } } internal class RestStickerCreatePayload { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; set; } [JsonProperty("tags", NullValueHandling = NullValueHandling.Ignore)] public string Tags { get; set; } } internal class RestStickerModifyPayload { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public Optional Name { get; set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public Optional Description { get; set; } [JsonProperty("tags", NullValueHandling = NullValueHandling.Ignore)] public Optional Tags { get; set; } } internal sealed class RestThreadCreatePayload { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("auto_archive_duration", NullValueHandling = NullValueHandling.Ignore)] public AutoArchiveDuration ArchiveAfter { get; set; } [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public ChannelType? Type { get; set; } } internal sealed class RestForumPostCreatePayload { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("auto_archive_duration", NullValueHandling = NullValueHandling.Ignore)] public AutoArchiveDuration? ArchiveAfter { get; set; } [JsonProperty("rate_limit_per_user", NullValueHandling = NullValueHandling.Include)] public int? RateLimitPerUser { get; set; } [JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)] public RestChannelMessageCreatePayload Message { get; set; } [JsonProperty("applied_tags", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable AppliedTags { get; set; } } internal sealed class RestUserDmCreatePayload { [JsonProperty("recipient_id")] public ulong Recipient { get; set; } } internal sealed class RestUserGroupDmCreatePayload { [JsonProperty("access_tokens")] public IEnumerable AccessTokens { get; set; } [JsonProperty("nicks")] public IDictionary Nicknames { get; set; } } internal sealed class RestUserUpdateCurrentPayload { [JsonProperty("username", NullValueHandling = NullValueHandling.Ignore)] public string Username { get; set; } [JsonProperty("avatar", NullValueHandling = NullValueHandling.Include)] public string AvatarBase64 { get; set; } [Newtonsoft.Json.JsonIgnore] public bool AvatarSet { get; set; } public bool ShouldSerializeAvatarBase64() { return AvatarSet; } } internal sealed class RestUserGuild { [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] public ulong Id { get; set; } [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] public string IconHash { get; set; } [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] public bool IsOwner { get; set; } [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions Permissions { get; set; } } internal sealed class RestUserGuildListPayload { [JsonProperty("limit", NullValueHandling = NullValueHandling.Ignore)] public int Limit { get; set; } [JsonProperty("before", NullValueHandling = NullValueHandling.Ignore)] public ulong? Before { get; set; } [JsonProperty("after", NullValueHandling = NullValueHandling.Ignore)] public ulong? After { get; set; } } internal sealed class RestWebhookPayload { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("avatar", NullValueHandling = NullValueHandling.Include)] public string AvatarBase64 { get; set; } [JsonProperty("channel_id")] public ulong ChannelId { get; set; } [JsonProperty] public bool AvatarSet { get; set; } public bool ShouldSerializeAvatarBase64() { return AvatarSet; } } internal sealed class RestWebhookExecutePayload { [JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)] public string Content { get; set; } [JsonProperty("username", NullValueHandling = NullValueHandling.Ignore)] public string Username { get; set; } [JsonProperty("avatar_url", NullValueHandling = NullValueHandling.Ignore)] public string AvatarUrl { get; set; } [JsonProperty("tts", NullValueHandling = NullValueHandling.Ignore)] public bool? IsTTS { get; set; } [JsonProperty("embeds", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Embeds { get; set; } [JsonProperty("components", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Components { get; set; } [JsonProperty("allowed_mentions", NullValueHandling = NullValueHandling.Ignore)] public DiscordMentions Mentions { get; set; } } internal sealed class RestWebhookMessageEditPayload { [JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)] public Optional Content { get; set; } [JsonProperty("embeds", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Embeds { get; set; } [JsonProperty("allowed_mentions", NullValueHandling = NullValueHandling.Ignore)] public DiscordMentions Mentions { get; set; } [JsonProperty("components", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Components { get; set; } [JsonProperty("attachments", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Attachments { get; set; } } [Newtonsoft.Json.JsonConverter(typeof(ShardInfoConverter))] internal sealed class ShardInfo { public int ShardId { get; set; } public int ShardCount { get; set; } } internal sealed class ShardInfoConverter : Newtonsoft.Json.JsonConverter { public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { ShardInfo shardInfo = value as ShardInfo; object[] value2 = new object[2] { shardInfo.ShardId, shardInfo.ShardCount }; serializer.Serialize(writer, value2); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { JArray jArray = ReadArrayObject(reader, serializer); return new ShardInfo { ShardId = (int)jArray[0], ShardCount = (int)jArray[1] }; } private JArray ReadArrayObject(JsonReader reader, Newtonsoft.Json.JsonSerializer serializer) { if (serializer.Deserialize(reader) is JArray jArray && jArray.Count == 2) { return jArray; } throw new JsonSerializationException("Expected array of length 2"); } public override bool CanConvert(Type objectType) { return objectType == typeof(ShardInfo); } } internal sealed class StatusUpdate { internal DiscordActivity _activity; [JsonProperty("since", NullValueHandling = NullValueHandling.Include)] public long? IdleSince { get; set; } [JsonProperty("afk")] public bool IsAFK { get; set; } [Newtonsoft.Json.JsonIgnore] public UserStatus Status { get; set; } = UserStatus.Online; [JsonProperty("status")] internal string StatusString { get { switch (Status) { case UserStatus.Online: return "online"; case UserStatus.Idle: return "idle"; case UserStatus.DoNotDisturb: return "dnd"; case UserStatus.Offline: case UserStatus.Invisible: return "invisible"; default: return "online"; } } } [JsonProperty("game", NullValueHandling = NullValueHandling.Ignore)] public TransportActivity Activity { get; set; } } internal sealed class TransportActivity { public class PresenceAssets { [JsonProperty("large_image")] public string LargeImage { get; set; } [JsonProperty("large_text", NullValueHandling = NullValueHandling.Ignore)] public string LargeImageText { get; internal set; } [JsonProperty("small_image")] internal string SmallImage { get; set; } [JsonProperty("small_text", NullValueHandling = NullValueHandling.Ignore)] public string SmallImageText { get; internal set; } } public class GameParty { [Newtonsoft.Json.JsonConverter(typeof(GamePartySizeConverter))] public class GamePartySize { public long Current { get; internal set; } public long Maximum { get; internal set; } } [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public string Id { get; internal set; } [JsonProperty("size", NullValueHandling = NullValueHandling.Ignore)] public GamePartySize Size { get; internal set; } } public class GameTimestamps { [JsonProperty("start", NullValueHandling = NullValueHandling.Ignore)] internal long? _start; [JsonProperty("end", NullValueHandling = NullValueHandling.Ignore)] internal long? _end; [Newtonsoft.Json.JsonIgnore] public DateTimeOffset? Start { get { if (!_start.HasValue) { return null; } return Utilities.GetDateTimeOffsetFromMilliseconds(_start.Value, shouldThrow: false); } } [Newtonsoft.Json.JsonIgnore] public DateTimeOffset? End { get { if (!_end.HasValue) { return null; } return Utilities.GetDateTimeOffsetFromMilliseconds(_end.Value, shouldThrow: false); } } } public class GameSecrets { [JsonProperty("join", NullValueHandling = NullValueHandling.Ignore)] public string Join { get; internal set; } [JsonProperty("match", NullValueHandling = NullValueHandling.Ignore)] public string Match { get; internal set; } [JsonProperty("spectate", NullValueHandling = NullValueHandling.Ignore)] public string Spectate { get; internal set; } } [JsonProperty("name", NullValueHandling = NullValueHandling.Include)] public string Name { get; internal set; } [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)] public string StreamUrl { get; internal set; } [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public ActivityType ActivityType { get; internal set; } [JsonProperty("details", NullValueHandling = NullValueHandling.Ignore)] public string Details { get; internal set; } [JsonProperty("state", NullValueHandling = NullValueHandling.Ignore)] public string State { get; internal set; } [JsonProperty("emoji", NullValueHandling = NullValueHandling.Ignore)] public DiscordEmoji Emoji { get; internal set; } [Newtonsoft.Json.JsonIgnore] public ulong? ApplicationId { get { if (ApplicationIdStr == null) { return null; } return ulong.Parse(ApplicationIdStr, CultureInfo.InvariantCulture); } internal set { ApplicationIdStr = value?.ToString(CultureInfo.InvariantCulture); } } [JsonProperty("application_id", NullValueHandling = NullValueHandling.Ignore)] internal string ApplicationIdStr { get; set; } [JsonProperty("instance", NullValueHandling = NullValueHandling.Ignore)] public bool? Instance { get; internal set; } [JsonProperty("party", NullValueHandling = NullValueHandling.Ignore)] public GameParty Party { get; internal set; } [JsonProperty("assets", NullValueHandling = NullValueHandling.Ignore)] public PresenceAssets Assets { get; internal set; } [JsonProperty("timestamps", NullValueHandling = NullValueHandling.Ignore)] public GameTimestamps Timestamps { get; internal set; } [JsonProperty("secrets", NullValueHandling = NullValueHandling.Ignore)] public GameSecrets Secrets { get; internal set; } [JsonProperty("buttons", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Buttons { get; internal set; } internal TransportActivity() { } internal TransportActivity(DiscordActivity game) { if (game != null) { Name = game.Name; ActivityType = game.ActivityType; StreamUrl = game.StreamUrl; } } public bool IsRichPresence() { if (Details == null && State == null && !ApplicationId.HasValue && !Instance.HasValue && Party == null && Assets == null && Secrets == null) { return Timestamps != null; } return true; } public bool IsCustomStatus() { return Name == "Custom Status"; } } internal sealed class GamePartySizeConverter : Newtonsoft.Json.JsonConverter { public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { object[] value2 = ((!(value is TransportActivity.GameParty.GamePartySize gamePartySize)) ? null : new object[2] { gamePartySize.Current, gamePartySize.Maximum }); serializer.Serialize(writer, value2); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { JArray jArray = ReadArrayObject(reader, serializer); return new TransportActivity.GameParty.GamePartySize { Current = (long)jArray[0], Maximum = (long)jArray[1] }; } private JArray ReadArrayObject(JsonReader reader, Newtonsoft.Json.JsonSerializer serializer) { if (serializer.Deserialize(reader) is JArray jArray && jArray.Count == 2) { return jArray; } throw new JsonSerializationException("Expected array of length 2"); } public override bool CanConvert(Type objectType) { return objectType == typeof(TransportActivity.GameParty.GamePartySize); } } internal sealed class TransportApplication { [JsonProperty("id", NullValueHandling = NullValueHandling.Include)] public ulong Id { get; set; } [JsonProperty("name", NullValueHandling = NullValueHandling.Include)] public string Name { get; set; } [JsonProperty("icon", NullValueHandling = NullValueHandling.Include)] public string IconHash { get; set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Include)] public string Description { get; set; } [JsonProperty("summary", NullValueHandling = NullValueHandling.Include)] public string Summary { get; set; } [JsonProperty("bot_public", NullValueHandling = NullValueHandling.Include)] public bool IsPublicBot { get; set; } [JsonProperty("bot_require_code_grant", NullValueHandling = NullValueHandling.Include)] public bool BotRequiresCodeGrant { get; set; } [JsonProperty("terms_of_service_url", NullValueHandling = NullValueHandling.Ignore)] public string TermsOfServiceUrl { get; set; } [JsonProperty("privacy_policy_url", NullValueHandling = NullValueHandling.Ignore)] public string PrivacyPolicyUrl { get; set; } [JsonProperty("rpc_origins", NullValueHandling = NullValueHandling.Ignore)] public IList RpcOrigins { get; set; } [JsonProperty("owner", NullValueHandling = NullValueHandling.Include)] public TransportUser Owner { get; set; } [JsonProperty("team", NullValueHandling = NullValueHandling.Include)] public TransportTeam Team { get; set; } [JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)] public ApplicationFlags? Flags { get; set; } internal TransportApplication() { } } internal class TransportMember { [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] public string AvatarHash { get; internal set; } [JsonProperty("user", NullValueHandling = NullValueHandling.Ignore)] public TransportUser User { get; internal set; } [JsonProperty("nick", NullValueHandling = NullValueHandling.Ignore)] public string Nickname { get; internal set; } [JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)] public List Roles { get; internal set; } [JsonProperty("communication_disabled_until", NullValueHandling = NullValueHandling.Include)] public DateTimeOffset? CommunicationDisabledUntil { get; internal set; } [JsonProperty("joined_at", NullValueHandling = NullValueHandling.Ignore)] public DateTime JoinedAt { get; internal set; } [JsonProperty("deaf", NullValueHandling = NullValueHandling.Ignore)] public bool IsDeafened { get; internal set; } [JsonProperty("mute", NullValueHandling = NullValueHandling.Ignore)] public bool IsMuted { get; internal set; } [JsonProperty("premium_since", NullValueHandling = NullValueHandling.Ignore)] public DateTime? PremiumSince { get; internal set; } [JsonProperty("pending", NullValueHandling = NullValueHandling.Ignore)] public bool? IsPending { get; internal set; } } internal sealed class TransportTeam { [JsonProperty("id")] public ulong Id { get; set; } [JsonProperty("name", NullValueHandling = NullValueHandling.Include)] public string Name { get; set; } [JsonProperty("icon", NullValueHandling = NullValueHandling.Include)] public string IconHash { get; set; } [JsonProperty("owner_user_id")] public ulong OwnerId { get; set; } [JsonProperty("members", NullValueHandling = NullValueHandling.Include)] public IEnumerable Members { get; set; } internal TransportTeam() { } } internal sealed class TransportTeamMember { [JsonProperty("membership_state")] public int MembershipState { get; set; } [JsonProperty("role", NullValueHandling = NullValueHandling.Include)] public string Role { get; set; } [JsonProperty("team_id")] public ulong TeamId { get; set; } [JsonProperty("user", NullValueHandling = NullValueHandling.Include)] public TransportUser User { get; set; } internal TransportTeamMember() { } } internal class TransportUser { [JsonProperty("id")] public ulong Id { get; internal set; } [JsonProperty("username", NullValueHandling = NullValueHandling.Ignore)] public string Username { get; internal set; } [JsonProperty("discriminator", NullValueHandling = NullValueHandling.Ignore)] internal string Discriminator { get; set; } [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] public string AvatarHash { get; internal set; } [JsonProperty("banner", NullValueHandling = NullValueHandling.Ignore)] public string BannerHash { get; internal set; } [JsonProperty("accent_color")] public int? BannerColor { get; internal set; } [JsonProperty("bot", NullValueHandling = NullValueHandling.Ignore)] public bool IsBot { get; internal set; } [JsonProperty("mfa_enabled", NullValueHandling = NullValueHandling.Ignore)] public bool? MfaEnabled { get; internal set; } [JsonProperty("verified", NullValueHandling = NullValueHandling.Ignore)] public bool? Verified { get; internal set; } [JsonProperty("email", NullValueHandling = NullValueHandling.Ignore)] public string Email { get; internal set; } [JsonProperty("premium_type", NullValueHandling = NullValueHandling.Ignore)] public PremiumType? PremiumType { get; internal set; } [JsonProperty("locale", NullValueHandling = NullValueHandling.Ignore)] public string Locale { get; internal set; } [JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)] public UserFlags? OAuthFlags { get; internal set; } [JsonProperty("public_flags", NullValueHandling = NullValueHandling.Ignore)] public UserFlags? Flags { get; internal set; } internal TransportUser() { } internal TransportUser(TransportUser other) { Id = other.Id; Username = other.Username; Discriminator = other.Discriminator; AvatarHash = other.AvatarHash; BannerHash = other.BannerHash; BannerColor = other.BannerColor; IsBot = other.IsBot; MfaEnabled = other.MfaEnabled; Verified = other.Verified; Email = other.Email; PremiumType = other.PremiumType; Locale = other.Locale; Flags = other.Flags; OAuthFlags = other.OAuthFlags; } } internal sealed class VoiceStateUpdate { [JsonProperty("guild_id")] public ulong GuildId { get; set; } [JsonProperty("channel_id")] public ulong? ChannelId { get; set; } [JsonProperty("self_mute")] public bool Mute { get; set; } [JsonProperty("self_deaf")] public bool Deafen { get; set; } } } namespace DSharpPlus.Entities { internal sealed class DiscordApplication : DiscordMessageApplication, IEquatable { public string Summary { get; internal set; } public override string Icon { get { if (string.IsNullOrWhiteSpace(IconHash)) { return null; } return "https://cdn.discordapp.com/app-icons/" + base.Id.ToString(CultureInfo.InvariantCulture) + "/" + IconHash + ".png?size=1024"; } } public string IconHash { get; internal set; } public string TermsOfServiceUrl { get; internal set; } public string PrivacyPolicyUrl { get; internal set; } public IReadOnlyList RpcOrigins { get; internal set; } public ApplicationFlags? Flags { get; internal set; } public IEnumerable Owners { get; internal set; } public bool? RequiresCodeGrant { get; internal set; } public bool? IsPublic { get; internal set; } public string CoverImageHash { get; internal set; } public override string CoverImageUrl => "https://cdn.discordapp.com/app-icons/" + base.Id.ToString(CultureInfo.InvariantCulture) + "/" + CoverImageHash + ".png?size=1024"; public DiscordTeam Team { get; internal set; } private IReadOnlyList Assets { get; set; } internal DiscordApplication() { } public string GetAvatarUrl(ImageFormat fmt, ushort size = 1024) { if (fmt == ImageFormat.Unknown) { throw new ArgumentException("You must specify valid image format.", "fmt"); } if (size < 16 || size > 2048) { throw new ArgumentOutOfRangeException("size"); } double num = Math.Log((int)size, 2.0); if (num < 4.0 || num > 11.0 || num % 1.0 != 0.0) { throw new ArgumentOutOfRangeException("size"); } string text = ""; string text2; switch (fmt) { case ImageFormat.Gif: text2 = "gif"; break; case ImageFormat.Jpeg: text2 = "jpg"; break; case ImageFormat.Png: case ImageFormat.Auto: text2 = "png"; break; case ImageFormat.WebP: text2 = "webp"; break; default: throw new ArgumentOutOfRangeException("fmt"); } text = text2; string text3 = size.ToString(CultureInfo.InvariantCulture); if (!string.IsNullOrWhiteSpace(CoverImageHash)) { string text4 = base.Id.ToString(CultureInfo.InvariantCulture); return "https://cdn.discordapp.com/avatars/" + text4 + "/" + CoverImageHash + "." + text + "?size=" + text3; } return null; } public async Task> GetAssetsAsync(bool updateCache = false) { if (updateCache || Assets == null) { Assets = await base.Discord.ApiClient.GetApplicationAssetsAsync(this).ConfigureAwait(continueOnCapturedContext: false); } return Assets; } public string GenerateBotOAuth(Permissions permissions = Permissions.None) { permissions &= PermissionMethods.FULL_PERMS; QueryUriBuilder queryUriBuilder = new QueryUriBuilder("https://discord.com/oauth2/authorize").AddParameter("client_id", base.Id.ToString(CultureInfo.InvariantCulture)).AddParameter("scope", "bot"); long num = (long)permissions; return queryUriBuilder.AddParameter("permissions", num.ToString(CultureInfo.InvariantCulture)).ToString(); } public string GenerateOAuthUri(string redirectUri = null, Permissions? permissions = null, params OAuthScope[] scopes) { permissions &= PermissionMethods.FULL_PERMS; StringBuilder stringBuilder = new StringBuilder(); foreach (OAuthScope scope in scopes) { stringBuilder.Append(" ").Append(TranslateOAuthScope(scope)); } QueryUriBuilder queryUriBuilder = new QueryUriBuilder("https://discord.com/oauth2/authorize").AddParameter("client_id", base.Id.ToString(CultureInfo.InvariantCulture)).AddParameter("scope", stringBuilder.ToString().Trim()); if (permissions.HasValue) { queryUriBuilder.AddParameter("permissions", ((long)permissions.Value).ToString(CultureInfo.InvariantCulture)); } if (redirectUri != null) { queryUriBuilder.AddParameter("redirect_uri", redirectUri).AddParameter("response_type", "code"); } return queryUriBuilder.ToString(); } public override bool Equals(object obj) { return Equals(obj as DiscordApplication); } public bool Equals(DiscordApplication e) { if ((object)e == null) { return false; } if ((object)this != e) { return base.Id == e.Id; } return true; } public override int GetHashCode() { return base.Id.GetHashCode(); } public static bool operator ==(DiscordApplication e1, DiscordApplication e2) { if (((object)e1 == null && (object)e2 != null) || ((object)e1 != null && (object)e2 == null)) { return false; } if ((object)e1 != null || (object)e2 != null) { return e1.Id == e2.Id; } return true; } public static bool operator !=(DiscordApplication e1, DiscordApplication e2) { return !(e1 == e2); } private string TranslateOAuthScope(OAuthScope scope) { return scope switch { OAuthScope.Identify => "identify", OAuthScope.Email => "email", OAuthScope.Connections => "connections", OAuthScope.Guilds => "guilds", OAuthScope.GuildsJoin => "guilds.join", OAuthScope.GuildsMembersRead => "guilds.members.read", OAuthScope.GdmJoin => "gdm.join", OAuthScope.Rpc => "rpc", OAuthScope.RpcNotificationsRead => "rpc.notifications.read", OAuthScope.RpcVoiceRead => "rpc.voice.read", OAuthScope.RpcVoiceWrite => "rpc.voice.write", OAuthScope.RpcActivitiesWrite => "rpc.activities.write", OAuthScope.Bot => "bot", OAuthScope.WebhookIncoming => "webhook.incoming", OAuthScope.MessagesRead => "messages.read", OAuthScope.ApplicationsBuildsUpload => "applications.builds.upload", OAuthScope.ApplicationsBuildsRead => "applications.builds.read", OAuthScope.ApplicationsCommands => "applications.commands", OAuthScope.ApplicationsStoreUpdate => "applications.store.update", OAuthScope.ApplicationsEntitlements => "applications.entitlements", OAuthScope.ActivitiesRead => "activities.read", OAuthScope.ActivitiesWrite => "activities.write", OAuthScope.RelationshipsRead => "relationships.read", _ => null, }; } } internal abstract class DiscordAsset { public virtual string Id { get; set; } public abstract Uri Url { get; } } internal sealed class DiscordApplicationAsset : DiscordAsset, IEquatable { internal BaseDiscordClient Discord { get; set; } [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("type")] public ApplicationAssetType Type { get; internal set; } public DiscordApplication Application { get; internal set; } public override Uri Url => new Uri("https://cdn.discordapp.com/app-assets/" + Application.Id.ToString(CultureInfo.InvariantCulture) + "/" + Id + ".png"); internal DiscordApplicationAsset() { } internal DiscordApplicationAsset(DiscordApplication app) { Discord = app.Discord; } public override bool Equals(object obj) { return Equals(obj as DiscordApplicationAsset); } public bool Equals(DiscordApplicationAsset e) { if ((object)e == null) { return false; } if ((object)this != e) { return Id == e.Id; } return true; } public override int GetHashCode() { return Id.GetHashCode(); } public static bool operator ==(DiscordApplicationAsset e1, DiscordApplicationAsset e2) { if (((object)e1 == null && (object)e2 != null) || ((object)e1 != null && (object)e2 == null)) { return false; } if ((object)e1 != null || (object)e2 != null) { return e1.Id == e2.Id; } return true; } public static bool operator !=(DiscordApplicationAsset e1, DiscordApplicationAsset e2) { return !(e1 == e2); } } internal sealed class DiscordSpotifyAsset : DiscordAsset { private readonly Lazy _url; public override Uri Url => _url.Value; public DiscordSpotifyAsset() { _url = new Lazy(delegate { string text = Id.Split(new char[1] { ':' })[1]; return new Uri("https://i.scdn.co/image/" + text); }); } } internal enum ApplicationAssetType { Unknown, SmallImage, LargeImage } internal enum OAuthScope { Identify, Email, Connections, Guilds, GuildsJoin, GuildsMembersRead, GdmJoin, Rpc, RpcNotificationsRead, RpcVoiceRead, RpcVoiceWrite, RpcActivitiesWrite, Bot, WebhookIncoming, MessagesRead, ApplicationsBuildsUpload, ApplicationsBuildsRead, ApplicationsCommands, ApplicationsStoreUpdate, ApplicationsEntitlements, ActivitiesRead, ActivitiesWrite, RelationshipsRead } internal abstract class BaseDiscordMessageBuilder : IDiscordMessageBuilder where T : BaseDiscordMessageBuilder { internal string _content; internal List _embeds = new List(); internal List _files = new List(); internal List _mentions = new List(); internal List _components = new List(); public string Content { get { return _content; } set { if (value != null && value.Length > 2000) { throw new ArgumentException("Content length cannot exceed 2000 characters.", "value"); } _content = value; } } public MessageFlags Flags { get; internal set; } public bool IsTTS { get; set; } public IReadOnlyList Embeds => _embeds; public IReadOnlyList Files => _files; public IReadOnlyList Mentions => _mentions; public IReadOnlyList Components => _components; public T SuppressNotifications() { Flags |= MessageFlags.SupressNotifications; return this as T; } internal BaseDiscordMessageBuilder() { } protected BaseDiscordMessageBuilder(IDiscordMessageBuilder builder) { _content = builder.Content; _mentions.AddRange(builder.Mentions.ToList()); _embeds.AddRange(builder.Embeds); _components.AddRange(builder.Components); _files.AddRange(builder.Files); IsTTS = builder.IsTTS; } public T WithContent(string content) { Content = content; return this as T; } public T AddComponents(params DiscordComponent[] components) { return AddComponents((IEnumerable)components); } public T AddComponents(IEnumerable components) { DiscordActionRowComponent[] array = components.ToArray(); if (array.Length + _components.Count > 5) { throw new ArgumentException("ActionRow count exceeds maximum of five."); } DiscordActionRowComponent[] array2 = array; foreach (DiscordActionRowComponent item in array2) { _components.Add(item); } return this as T; } public T AddComponents(IEnumerable components) { DiscordComponent[] array = components.ToArray(); int num = array.Length; if (!array.Any()) { throw new ArgumentOutOfRangeException("components", "You must provide at least one component"); } if (num > 5) { throw new ArgumentException("Cannot add more than 5 components per action row!"); } DiscordActionRowComponent item = new DiscordActionRowComponent(array); _components.Add(item); return this as T; } public T WithTTS(bool isTTS) { IsTTS = isTTS; return this as T; } public T AddEmbed(DiscordEmbed embed) { if (embed == null) { return this as T; } _embeds.Add(embed); return this as T; } public T AddEmbeds(IEnumerable embeds) { _embeds.AddRange(embeds); return this as T; } public T AddFile(string fileName, Stream stream, bool resetStreamPosition = false) { if (Files.Count >= 10) { throw new ArgumentException("Cannot send more than 10 files with a single message."); } if (_files.Any((DiscordMessageFile x) => x.FileName == fileName)) { throw new ArgumentException("A File with that filename already exists"); } if (resetStreamPosition) { _files.Add(new DiscordMessageFile(fileName, stream, stream.Position)); } else { _files.Add(new DiscordMessageFile(fileName, stream, null)); } return this as T; } public T AddFile(FileStream stream, bool resetStreamPosition = false) { if (Files.Count >= 10) { throw new ArgumentException("Cannot send more than 10 files with a single message."); } if (_files.Any((DiscordMessageFile x) => x.FileName == stream.Name)) { throw new ArgumentException("A File with that filename already exists"); } if (resetStreamPosition) { _files.Add(new DiscordMessageFile(stream.Name, stream, stream.Position)); } else { _files.Add(new DiscordMessageFile(stream.Name, stream, null)); } return this as T; } public T AddFiles(IDictionary files, bool resetStreamPosition = false) { if (Files.Count + files.Count > 10) { throw new ArgumentException("Cannot send more than 10 files with a single message."); } foreach (KeyValuePair file in files) { if (_files.Any((DiscordMessageFile x) => x.FileName == file.Key)) { throw new ArgumentException("A File with that filename already exists"); } if (resetStreamPosition) { _files.Add(new DiscordMessageFile(file.Key, file.Value, file.Value.Position)); } else { _files.Add(new DiscordMessageFile(file.Key, file.Value, null)); } } return this as T; } public T AddFiles(IEnumerable files) { _files.AddRange(files); return this as T; } public T AddMention(IMention mention) { _mentions.Add(mention); return this as T; } public T AddMentions(IEnumerable mentions) { _mentions.AddRange(mentions); return this as T; } public virtual void ClearComponents() { _components.Clear(); } public virtual void Clear() { Content = ""; _embeds.Clear(); IsTTS = false; _mentions.Clear(); _files.Clear(); _components.Clear(); } IDiscordMessageBuilder IDiscordMessageBuilder.SuppressNotifications() { return SuppressNotifications(); } IDiscordMessageBuilder IDiscordMessageBuilder.WithContent(string content) { return WithContent(content); } IDiscordMessageBuilder IDiscordMessageBuilder.AddComponents(params DiscordComponent[] components) { return AddComponents(components); } IDiscordMessageBuilder IDiscordMessageBuilder.AddComponents(IEnumerable components) { return AddComponents(components); } IDiscordMessageBuilder IDiscordMessageBuilder.AddComponents(IEnumerable components) { return AddComponents(components); } IDiscordMessageBuilder IDiscordMessageBuilder.WithTTS(bool isTTS) { return WithTTS(isTTS); } IDiscordMessageBuilder IDiscordMessageBuilder.AddEmbed(DiscordEmbed embed) { return AddEmbed(embed); } IDiscordMessageBuilder IDiscordMessageBuilder.AddEmbeds(IEnumerable embeds) { return AddEmbeds(embeds); } IDiscordMessageBuilder IDiscordMessageBuilder.AddFile(string fileName, Stream stream, bool resetStream) { return AddFile(fileName, stream, resetStream); } IDiscordMessageBuilder IDiscordMessageBuilder.AddFile(FileStream stream, bool resetStream) { return AddFile(stream, resetStream); } IDiscordMessageBuilder IDiscordMessageBuilder.AddFiles(IDictionary files, bool resetStreams) { return AddFiles(files, resetStreams); } IDiscordMessageBuilder IDiscordMessageBuilder.AddFiles(IEnumerable files) { return AddFiles(files); } IDiscordMessageBuilder IDiscordMessageBuilder.AddMention(IMention mention) { return AddMention(mention); } IDiscordMessageBuilder IDiscordMessageBuilder.AddMentions(IEnumerable mentions) { return AddMentions(mentions); } } internal interface IDiscordMessageBuilder { string Content { get; set; } bool IsTTS { get; set; } IReadOnlyList Embeds { get; } IReadOnlyList Files { get; } IReadOnlyList Components { get; } IReadOnlyList Mentions { get; } MessageFlags Flags { get; } IDiscordMessageBuilder WithContent(string content); IDiscordMessageBuilder AddComponents(params DiscordComponent[] components); IDiscordMessageBuilder AddComponents(IEnumerable components); IDiscordMessageBuilder AddComponents(IEnumerable components); IDiscordMessageBuilder WithTTS(bool isTTS); IDiscordMessageBuilder AddEmbed(DiscordEmbed embed); IDiscordMessageBuilder AddEmbeds(IEnumerable embeds); IDiscordMessageBuilder AddFile(string fileName, Stream stream, bool resetStream = false); IDiscordMessageBuilder AddFile(FileStream stream, bool resetStream = false); IDiscordMessageBuilder AddFiles(IDictionary files, bool resetStreams = false); IDiscordMessageBuilder AddFiles(IEnumerable files); IDiscordMessageBuilder AddMention(IMention mention); IDiscordMessageBuilder AddMentions(IEnumerable mentions); IDiscordMessageBuilder SuppressNotifications(); void ClearComponents(); void Clear(); } [Newtonsoft.Json.JsonConverter(typeof(DiscordForumChannelJsonConverter))] internal class DiscordChannel : SnowflakeObject, IEquatable { [JsonProperty("permission_overwrites", NullValueHandling = NullValueHandling.Ignore)] internal List _permissionOverwrites = new List(); [Newtonsoft.Json.JsonIgnore] private readonly Lazy> _permissionOverwritesLazy; [JsonProperty("guild_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? GuildId { get; internal set; } [JsonProperty("parent_id", NullValueHandling = NullValueHandling.Include)] public ulong? ParentId { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DiscordChannel Parent { get { if (!ParentId.HasValue) { return null; } return Guild.GetChannel(ParentId.Value); } } [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public virtual ChannelType Type { get; internal set; } [JsonProperty("position", NullValueHandling = NullValueHandling.Ignore)] public int Position { get; internal set; } [Newtonsoft.Json.JsonIgnore] public bool IsPrivate { get { if (Type != ChannelType.Private) { return Type == ChannelType.Group; } return true; } } [Newtonsoft.Json.JsonIgnore] public bool IsCategory => Type == ChannelType.Category; [Newtonsoft.Json.JsonIgnore] public bool IsThread { get { if (Type != ChannelType.PrivateThread && Type != ChannelType.PublicThread) { return Type == ChannelType.NewsThread; } return true; } } [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild { get { if (!GuildId.HasValue || !base.Discord.Guilds.TryGetValue(GuildId.Value, out var value)) { return null; } return value; } } [Newtonsoft.Json.JsonIgnore] public IReadOnlyList PermissionOverwrites => _permissionOverwritesLazy.Value; [JsonProperty("topic", NullValueHandling = NullValueHandling.Ignore)] public string Topic { get; internal set; } [JsonProperty("last_message_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? LastMessageId { get; internal set; } [JsonProperty("bitrate", NullValueHandling = NullValueHandling.Ignore)] public int? Bitrate { get; internal set; } [JsonProperty("user_limit", NullValueHandling = NullValueHandling.Ignore)] public int? UserLimit { get; internal set; } [JsonProperty("rate_limit_per_user")] public int? PerUserRateLimit { get; internal set; } [JsonProperty("video_quality_mode", NullValueHandling = NullValueHandling.Ignore)] public VideoQualityMode? QualityMode { get; internal set; } [JsonProperty("last_pin_timestamp", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset? LastPinTimestamp { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string Mention => Formatter.Mention(this); [Newtonsoft.Json.JsonIgnore] public IReadOnlyList Children { get { if (IsCategory) { return Guild._channels.Values.Where((DiscordChannel e) => e.ParentId == base.Id).ToList(); } throw new ArgumentException("Only channel categories contain children."); } } [Newtonsoft.Json.JsonIgnore] public IReadOnlyList Threads { get { ChannelType type = Type; if ((type == ChannelType.Text || type == ChannelType.News || type == ChannelType.GuildForum) ? true : false) { return Guild._threads.Values.Where((DiscordThreadChannel e) => e.ParentId == base.Id).ToArray(); } throw new ArgumentException("Only text channels can have threads."); } } [Newtonsoft.Json.JsonIgnore] public virtual IReadOnlyList Users { get { if (Guild == null) { throw new InvalidOperationException("Cannot query users outside of guild channels."); } if (Type != ChannelType.Voice && Type != ChannelType.Stage) { return Guild.Members.Values.Where((DiscordMember x) => (PermissionsFor(x) & Permissions.AccessChannels) == Permissions.AccessChannels).ToList(); } return Guild.Members.Values.Where((DiscordMember x) => x.VoiceState?.ChannelId == base.Id).ToList(); } } [JsonProperty("nsfw")] public bool IsNSFW { get; internal set; } [JsonProperty("rtc_region", NullValueHandling = NullValueHandling.Ignore)] internal string RtcRegionId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordVoiceRegion RtcRegion { get { if (RtcRegionId == null) { return null; } return base.Discord.VoiceRegions[RtcRegionId]; } } [JsonProperty("permissions")] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions? UserPermissions { get; internal set; } internal DiscordChannel() { _permissionOverwritesLazy = new Lazy>(() => new ReadOnlyCollection(_permissionOverwrites)); } public Task SendMessageAsync(string content) { if (!Utilities.IsTextableChannel(this)) { throw new ArgumentException($"{Type} channels do not support sending text messages."); } return base.Discord.ApiClient.CreateMessageAsync(base.Id, content, null, null, mentionReply: false, failOnInvalidReply: false, suppressNotifications: false); } public Task SendMessageAsync(DiscordEmbed embed) { if (!Utilities.IsTextableChannel(this)) { throw new ArgumentException($"{Type} channels do not support sending text messages."); } return base.Discord.ApiClient.CreateMessageAsync(base.Id, null, (embed == null) ? null : new DiscordEmbed[1] { embed }, null, mentionReply: false, failOnInvalidReply: false, suppressNotifications: false); } public Task SendMessageAsync(string content, DiscordEmbed embed) { if (!Utilities.IsTextableChannel(this)) { throw new ArgumentException($"{Type} channels do not support sending text messages."); } return base.Discord.ApiClient.CreateMessageAsync(base.Id, content, (embed == null) ? null : new DiscordEmbed[1] { embed }, null, mentionReply: false, failOnInvalidReply: false, suppressNotifications: false); } public Task SendMessageAsync(DiscordMessageBuilder builder) { if (!Utilities.IsTextableChannel(this)) { throw new ArgumentException($"{Type} channels do not support sending text messages."); } return base.Discord.ApiClient.CreateMessageAsync(base.Id, builder); } public Task SendMessageAsync(Action action) { if (!Utilities.IsTextableChannel(this)) { throw new ArgumentException($"{Type} channels do not support sending text messages."); } DiscordMessageBuilder discordMessageBuilder = new DiscordMessageBuilder(); action(discordMessageBuilder); return base.Discord.ApiClient.CreateMessageAsync(base.Id, discordMessageBuilder); } public Task CreateGuildEventAsync(string name, string description, ScheduledGuildEventPrivacyLevel privacyLevel, DateTimeOffset start, DateTimeOffset? end) { ChannelType type = Type; if ((type == ChannelType.Voice || type == ChannelType.Stage) ? true : false) { return Guild.CreateEventAsync(name, description, base.Id, (Type == ChannelType.Stage) ? ScheduledGuildEventType.StageInstance : ScheduledGuildEventType.VoiceChannel, privacyLevel, start, end); } throw new InvalidOperationException("Events can only be created on voice an stage chnanels"); } public Task DeleteAsync(string reason = null) { return base.Discord.ApiClient.DeleteChannelAsync(base.Id, reason); } public async Task CloneAsync(string reason = null) { if (Guild == null) { throw new InvalidOperationException("Non-guild channels cannot be cloned."); } List ovrs = new List(); foreach (DiscordOverwrite permissionOverwrite in _permissionOverwrites) { List list = ovrs; list.Add(await new DiscordOverwriteBuilder((DiscordMember)null).FromAsync(permissionOverwrite).ConfigureAwait(continueOnCapturedContext: false)); } int? bitrate = Bitrate; int? userLimit = UserLimit; Optional perUserRateLimit = PerUserRateLimit; if (Type != ChannelType.Voice) { bitrate = null; userLimit = null; } if (Type != 0) { perUserRateLimit = Optional.FromNoValue(); } return await Guild.CreateChannelAsync(Name, Type, Parent, Topic, bitrate, userLimit, ovrs, IsNSFW, perUserRateLimit, QualityMode, Position, reason).ConfigureAwait(continueOnCapturedContext: false); } public async Task GetMessageAsync(ulong id, bool skipCache = false) { DiscordMessage item; return (skipCache || base.Discord.Configuration.MessageCacheSize <= 0 || !(base.Discord is DiscordClient discordClient) || discordClient.MessageCache == null || !discordClient.MessageCache.TryGet((DiscordMessage xm) => xm.Id == id && xm.ChannelId == base.Id, out item)) ? (await base.Discord.ApiClient.GetMessageAsync(base.Id, id).ConfigureAwait(continueOnCapturedContext: false)) : item; } public Task ModifyAsync(Action action) { ChannelEditModel channelEditModel = new ChannelEditModel(); action(channelEditModel); return base.Discord.ApiClient.ModifyChannelAsync(base.Id, channelEditModel.Name, channelEditModel.Position, channelEditModel.Topic, channelEditModel.Nsfw, channelEditModel.Parent.HasValue ? ((Optional)(channelEditModel.Parent.Value?.Id)) : default(Optional), channelEditModel.Bitrate, channelEditModel.Userlimit, channelEditModel.PerUserRateLimit, channelEditModel.RtcRegion.IfPresent((DiscordVoiceRegion r) => r?.Id), channelEditModel.QualityMode, channelEditModel.Type, channelEditModel.PermissionOverwrites, channelEditModel.AuditLogReason, channelEditModel.Flags, channelEditModel.AvailableTags, channelEditModel.DefaultAutoArchiveDuration, channelEditModel.DefaultReaction, channelEditModel.DefaultThreadRateLimit, channelEditModel.DefaultSortOrder, channelEditModel.DefaultForumLayout); } public Task ModifyPositionAsync(int position, string reason = null, bool? lockPermissions = null, ulong? parentId = null) { if (Guild == null) { throw new InvalidOperationException("Cannot modify order of non-guild channels."); } DiscordChannel[] array = (from xc in Guild._channels.Values where xc.Type == Type orderby xc.Position select xc).ToArray(); RestGuildChannelReorderPayload[] array2 = new RestGuildChannelReorderPayload[array.Length]; for (int i = 0; i < array.Length; i++) { array2[i] = new RestGuildChannelReorderPayload { ChannelId = array[i].Id }; array2[i].Position = ((array[i].Id == base.Id) ? position : ((array[i].Position >= position) ? (array[i].Position + 1) : array[i].Position)); array2[i].LockPermissions = ((array[i].Id == base.Id) ? lockPermissions : null); array2[i].ParentId = ((array[i].Id == base.Id) ? parentId : null); } return base.Discord.ApiClient.ModifyGuildChannelPositionAsync(Guild.Id, array2, reason); } public Task> GetMessagesBeforeAsync(ulong before, int limit = 100) { return GetMessagesInternalAsync(limit, before); } public Task> GetMessagesAfterAsync(ulong after, int limit = 100) { return GetMessagesInternalAsync(limit, null, after); } public Task> GetMessagesAroundAsync(ulong around, int limit = 100) { return GetMessagesInternalAsync(limit, null, null, around); } public Task> GetMessagesAsync(int limit = 100) { return GetMessagesInternalAsync(limit); } private async Task> GetMessagesInternalAsync(int limit = 100, ulong? before = null, ulong? after = null, ulong? around = null) { if (!Utilities.IsTextableChannel(this)) { throw new ArgumentException($"Cannot get the messages of a {Type} channel."); } if (limit < 0) { throw new ArgumentException("Cannot get a negative number of messages."); } if (limit == 0) { return Array.Empty(); } if (limit > 100 && around.HasValue) { throw new InvalidOperationException("Cannot get more than 100 messages around the specified ID."); } List msgs = new List(limit); int remaining = limit; ulong? num = null; bool isAfter = after.HasValue; int count; do { int limit2 = ((remaining > 100) ? 100 : remaining); IReadOnlyList readOnlyList = await base.Discord.ApiClient.GetChannelMessagesAsync(base.Id, limit2, isAfter ? null : (num ?? before), (!isAfter) ? null : (num ?? after), around).ConfigureAwait(continueOnCapturedContext: false); count = readOnlyList.Count; remaining -= count; if (!isAfter) { msgs.AddRange(readOnlyList); num = readOnlyList.LastOrDefault()?.Id; } else { msgs.InsertRange(0, readOnlyList); num = readOnlyList.FirstOrDefault()?.Id; } } while (remaining > 0 && count > 0); return new ReadOnlyCollection(msgs); } public Task ListPublicArchivedThreadsAsync(DateTimeOffset? before = null, int limit = 0) { if (Type != 0 && Type != ChannelType.News) { throw new InvalidOperationException(); } return base.Discord.ApiClient.ListPublicArchivedThreadsAsync(GuildId.Value, base.Id, before?.ToString("o"), limit); } public Task ListPrivateArchivedThreadsAsync(DateTimeOffset? before = null, int limit = 0) { if (Type != 0 && Type != ChannelType.News) { throw new InvalidOperationException(); } return base.Discord.ApiClient.ListPrivateArchivedThreadsAsync(GuildId.Value, base.Id, before?.ToString("o"), limit); } public Task ListJoinedPrivateArchivedThreadsAsync(DateTimeOffset? before = null, int limit = 0) { if (Type != 0 && Type != ChannelType.News) { throw new InvalidOperationException(); } return base.Discord.ApiClient.ListJoinedPrivateArchivedThreadsAsync(GuildId.Value, base.Id, (ulong?)before?.ToUnixTimeSeconds(), limit); } public async Task DeleteMessagesAsync(IEnumerable messages, string reason = null) { ulong[] msgs = (from x in messages where x.Channel.Id == base.Id select x.Id).ToArray(); if (messages == null || !msgs.Any()) { throw new ArgumentException("You need to specify at least one message to delete."); } if (msgs.Count() < 2) { await base.Discord.ApiClient.DeleteMessageAsync(base.Id, msgs.Single(), reason).ConfigureAwait(continueOnCapturedContext: false); return; } for (int i = 0; i < msgs.Count(); i += 100) { await base.Discord.ApiClient.DeleteMessagesAsync(base.Id, msgs.Skip(i).Take(100), reason).ConfigureAwait(continueOnCapturedContext: false); } } public Task DeleteMessageAsync(DiscordMessage message, string reason = null) { return base.Discord.ApiClient.DeleteMessageAsync(base.Id, message.Id, reason); } public Task> GetInvitesAsync() { if (!(Guild == null)) { return base.Discord.ApiClient.GetChannelInvitesAsync(base.Id); } throw new ArgumentException("Cannot get the invites of a channel that does not belong to a guild."); } public Task CreateInviteAsync(int max_age = 86400, int max_uses = 0, bool temporary = false, bool unique = false, string reason = null, InviteTargetType? targetType = null, ulong? targetUserId = null, ulong? targetApplicationId = null) { return base.Discord.ApiClient.CreateChannelInviteAsync(base.Id, max_age, max_uses, temporary, unique, reason, targetType, targetUserId, targetApplicationId); } public Task AddOverwriteAsync(DiscordMember member, Permissions allow = Permissions.None, Permissions deny = Permissions.None, string reason = null) { return base.Discord.ApiClient.EditChannelPermissionsAsync(base.Id, member.Id, allow, deny, "member", reason); } public Task AddOverwriteAsync(DiscordRole role, Permissions allow = Permissions.None, Permissions deny = Permissions.None, string reason = null) { return base.Discord.ApiClient.EditChannelPermissionsAsync(base.Id, role.Id, allow, deny, "role", reason); } public Task DeleteOverwriteAsync(DiscordMember member, string reason = null) { return base.Discord.ApiClient.DeleteChannelPermissionAsync(base.Id, member.Id, reason); } public Task DeleteOverwriteAsync(DiscordRole role, string reason = null) { return base.Discord.ApiClient.DeleteChannelPermissionAsync(base.Id, role.Id, reason); } public Task TriggerTypingAsync() { if (Utilities.IsTextableChannel(this)) { return base.Discord.ApiClient.TriggerTypingAsync(base.Id); } throw new ArgumentException("Cannot start typing in a non-text channel."); } public Task> GetPinnedMessagesAsync() { if (Utilities.IsTextableChannel(this) && Type != ChannelType.Voice) { return base.Discord.ApiClient.GetPinnedMessagesAsync(base.Id); } throw new ArgumentException("A non-text channel does not have pinned messages."); } public async Task CreateWebhookAsync(string name, Optional avatar = default(Optional), string reason = null) { Optional base64_avatar = Optional.FromNoValue(); if (avatar.HasValue && avatar.Value != null) { using ImageTool imageTool = new ImageTool(avatar.Value); base64_avatar = imageTool.GetBase64(); } else if (avatar.HasValue) { base64_avatar = null; } return await base.Discord.ApiClient.CreateWebhookAsync(base.Id, name, base64_avatar, reason).ConfigureAwait(continueOnCapturedContext: false); } public Task> GetWebhooksAsync() { return base.Discord.ApiClient.GetChannelWebhooksAsync(base.Id); } public async Task PlaceMemberAsync(DiscordMember member) { if (Type != ChannelType.Voice && Type != ChannelType.Stage) { throw new ArgumentException("Cannot place a member in a non-voice channel!"); } await base.Discord.ApiClient.ModifyGuildMemberAsync(Guild.Id, member.Id, default(Optional), default(Optional>), default(Optional), default(Optional), base.Id, default(Optional), null).ConfigureAwait(continueOnCapturedContext: false); } public Task FollowAsync(DiscordChannel targetChannel) { if (Type == ChannelType.News) { return base.Discord.ApiClient.FollowChannelAsync(base.Id, targetChannel.Id); } throw new ArgumentException("Cannot follow a non-news channel."); } public Task CrosspostMessageAsync(DiscordMessage message) { if ((message.Flags & MessageFlags.Crossposted).GetValueOrDefault() != MessageFlags.Crossposted) { return base.Discord.ApiClient.CrosspostMessageAsync(base.Id, message.Id); } throw new ArgumentException("Message is already crossposted."); } public async Task UpdateCurrentUserVoiceStateAsync(bool? suppress, DateTimeOffset? requestToSpeakTimestamp = null) { if (Type != ChannelType.Stage) { throw new ArgumentException("Voice state can only be updated in a stage channel."); } await base.Discord.ApiClient.UpdateCurrentUserVoiceStateAsync(GuildId.Value, base.Id, suppress, requestToSpeakTimestamp).ConfigureAwait(continueOnCapturedContext: false); } public async Task CreateStageInstanceAsync(string topic, PrivacyLevel? privacyLevel = null, string reason = null) { if (Type != ChannelType.Stage) { throw new ArgumentException("A stage instance can only be created in a stage channel."); } return await base.Discord.ApiClient.CreateStageInstanceAsync(base.Id, topic, privacyLevel, reason).ConfigureAwait(continueOnCapturedContext: false); } public async Task GetStageInstanceAsync() { if (Type != ChannelType.Stage) { throw new ArgumentException("A stage instance can only be created in a stage channel."); } return await base.Discord.ApiClient.GetStageInstanceAsync(base.Id).ConfigureAwait(continueOnCapturedContext: false); } public async Task ModifyStageInstanceAsync(Action action) { if (Type != ChannelType.Stage) { throw new ArgumentException("A stage instance can only be created in a stage channel."); } StageInstanceEditModel stageInstanceEditModel = new StageInstanceEditModel(); action(stageInstanceEditModel); return await base.Discord.ApiClient.ModifyStageInstanceAsync(base.Id, stageInstanceEditModel.Topic, stageInstanceEditModel.PrivacyLevel, stageInstanceEditModel.AuditLogReason).ConfigureAwait(continueOnCapturedContext: false); } public Task DeleteStageInstanceAsync(string reason = null) { return base.Discord.ApiClient.DeleteStageInstanceAsync(base.Id, reason); } public Permissions PermissionsFor(DiscordMember mbr) { if (IsThread) { return Parent.PermissionsFor(mbr); } if (IsPrivate || Guild == null) { return Permissions.None; } if (Guild.OwnerId == mbr.Id) { return PermissionMethods.FULL_PERMS; } DiscordRole everyoneRole = Guild.EveryoneRole; Permissions permissions = everyoneRole.Permissions; DiscordRole[] source = mbr.Roles.Where((DiscordRole xr) => xr.Id != everyoneRole.Id).ToArray(); permissions |= source.Aggregate(Permissions.None, (Permissions c, DiscordRole role) => c | role.Permissions); if ((permissions & Permissions.Administrator) == Permissions.Administrator) { return PermissionMethods.FULL_PERMS; } List source2 = (from xr in source select _permissionOverwrites.FirstOrDefault((DiscordOverwrite xo) => xo.Id == xr.Id) into xo where xo != null select xo).ToList(); DiscordOverwrite discordOverwrite = _permissionOverwrites.FirstOrDefault((DiscordOverwrite xo) => xo.Id == everyoneRole.Id); if (discordOverwrite != null) { permissions &= ~discordOverwrite.Denied; permissions |= discordOverwrite.Allowed; } permissions &= ~source2.Aggregate(Permissions.None, (Permissions c, DiscordOverwrite overs) => c | overs.Denied); permissions |= source2.Aggregate(Permissions.None, (Permissions c, DiscordOverwrite overs) => c | overs.Allowed); DiscordOverwrite discordOverwrite2 = _permissionOverwrites.FirstOrDefault((DiscordOverwrite xo) => xo.Id == mbr.Id); if (discordOverwrite2 == null) { return permissions; } permissions &= ~discordOverwrite2.Denied; return permissions | discordOverwrite2.Allowed; } public override string ToString() { if (Type == ChannelType.Category) { return $"Channel Category {Name} ({base.Id})"; } if (Type == ChannelType.Text || Type == ChannelType.News) { return $"Channel #{Name} ({base.Id})"; } if (string.IsNullOrWhiteSpace(Name)) { return $"Channel {base.Id}"; } return $"Channel {Name} ({base.Id})"; } public async Task CreateThreadAsync(DiscordMessage message, string name, AutoArchiveDuration archiveAfter, string reason = null) { if (Type != 0 && Type != ChannelType.News) { throw new ArgumentException("Threads can only be created within text or news channels."); } if (message.ChannelId != base.Id) { throw new ArgumentException("You must use a message from this channel to create a thread."); } DiscordThreadChannel threadChannel = await base.Discord.ApiClient.CreateThreadFromMessageAsync(base.Id, message.Id, name, archiveAfter, reason); Guild._threads.AddOrUpdate(threadChannel.Id, threadChannel, (ulong key, DiscordThreadChannel old) => threadChannel); return threadChannel; } public async Task CreateThreadAsync(string name, AutoArchiveDuration archiveAfter, ChannelType threadType, string reason = null) { if (Type != 0 && Type != ChannelType.News) { throw new InvalidOperationException("Threads can only be created within text or news channels."); } if (Type != ChannelType.News && threadType == ChannelType.NewsThread) { throw new InvalidOperationException("News threads can only be created within a news channels."); } if (threadType != ChannelType.PublicThread && threadType != ChannelType.PrivateThread && threadType != ChannelType.NewsThread) { throw new ArgumentException("Given channel type for creating a thread is not a valid type of thread."); } DiscordThreadChannel threadChannel = await base.Discord.ApiClient.CreateThreadAsync(base.Id, name, archiveAfter, threadType, reason); Guild._threads.AddOrUpdate(threadChannel.Id, threadChannel, (ulong key, DiscordThreadChannel old) => threadChannel); return threadChannel; } public override bool Equals(object obj) { return Equals(obj as DiscordChannel); } public bool Equals(DiscordChannel e) { if ((object)e == null) { return false; } if ((object)this != e) { return base.Id == e.Id; } return true; } public override int GetHashCode() { return base.Id.GetHashCode(); } public static bool operator ==(DiscordChannel e1, DiscordChannel e2) { if (((object)e1 == null && (object)e2 != null) || ((object)e1 != null && (object)e2 == null)) { return false; } if ((object)e1 != null || (object)e2 != null) { return e1.Id == e2.Id; } return true; } public static bool operator !=(DiscordChannel e1, DiscordChannel e2) { return !(e1 == e2); } } internal class DiscordDmChannel : DiscordChannel { [JsonProperty("recipients", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Recipients { get; internal set; } [JsonProperty("icon", NullValueHandling = NullValueHandling.Ignore)] public string IconHash { get; internal set; } [JsonProperty("owner_id", NullValueHandling = NullValueHandling.Ignore)] public ulong OwnerId { get; internal set; } [JsonProperty("application_id", NullValueHandling = NullValueHandling.Ignore)] public ulong ApplicationId { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string IconUrl { get { if (string.IsNullOrWhiteSpace(IconHash)) { return null; } return "https://cdn.discordapp.com/channel-icons/" + base.Id.ToString(CultureInfo.InvariantCulture) + "/" + IconHash + ".png"; } } public Task AddDmRecipientAsync(ulong user_id, string accesstoken, string nickname) { return base.Discord.ApiClient.AddGroupDmRecipientAsync(base.Id, user_id, accesstoken, nickname); } public Task RemoveDmRecipientAsync(ulong user_id, string accesstoken) { return base.Discord.ApiClient.RemoveGroupDmRecipientAsync(base.Id, user_id); } } internal class DiscordFollowedChannel { [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)] public ulong ChannelId { get; internal set; } [JsonProperty("webhook_id", NullValueHandling = NullValueHandling.Ignore)] public ulong WebhookId { get; internal set; } } internal class DiscordAttachment : SnowflakeObject { [JsonProperty("filename", NullValueHandling = NullValueHandling.Ignore)] public string FileName { get; internal set; } [JsonProperty("size", NullValueHandling = NullValueHandling.Ignore)] public int FileSize { get; internal set; } [JsonProperty("content_type", NullValueHandling = NullValueHandling.Ignore)] public string MediaType { get; internal set; } [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)] public string Url { get; internal set; } [JsonProperty("proxy_url", NullValueHandling = NullValueHandling.Ignore)] public string ProxyUrl { get; internal set; } [JsonProperty("height", NullValueHandling = NullValueHandling.Ignore)] public int? Height { get; internal set; } [JsonProperty("width", NullValueHandling = NullValueHandling.Ignore)] public int? Width { get; internal set; } [JsonProperty("ephemeral", NullValueHandling = NullValueHandling.Ignore)] public bool? Ephemeral { get; internal set; } internal DiscordAttachment() { } } internal class DiscordMentions { private const string ParseUsers = "users"; private const string ParseRoles = "roles"; private const string ParseEveryone = "everyone"; [JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Roles { get; } [JsonProperty("users", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Users { get; } [JsonProperty("parse", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Parse { get; } [JsonProperty("replied_user", NullValueHandling = NullValueHandling.Ignore)] public bool? RepliedUser { get; } internal DiscordMentions(IEnumerable mentions, bool mention = false, bool repliedUser = false) { if (mentions == null) { return; } RepliedUser = repliedUser; if (!mentions.Any()) { Parse = Array.Empty(); return; } HashSet hashSet = new HashSet(); HashSet hashSet2 = new HashSet(); HashSet hashSet3 = new HashSet(); foreach (IMention mention2 in mentions) { if (!(mention2 is UserMention userMention)) { if (!(mention2 is RoleMention roleMention)) { if (!(mention2 is EveryoneMention)) { if (!(mention2 is RepliedUserMention)) { throw new NotSupportedException("Type not supported in mentions."); } } else { hashSet3.Add("everyone"); } } else if (roleMention.Id.HasValue) { hashSet.Add(roleMention.Id.Value); } else { hashSet3.Add("roles"); } } else if (userMention.Id.HasValue) { hashSet2.Add(userMention.Id.Value); } else { hashSet3.Add("users"); } } if (!hashSet3.Contains("users") && hashSet2.Count > 0) { Users = hashSet2; } if (!hashSet3.Contains("roles") && hashSet.Count > 0) { Roles = hashSet; } if (hashSet3.Count > 0) { Parse = hashSet3; } } } internal class DiscordMessage : SnowflakeObject, IEquatable { private DiscordChannel _channel; [JsonProperty("mentions", NullValueHandling = NullValueHandling.Ignore)] internal List _mentionedUsers; [Newtonsoft.Json.JsonIgnore] internal List _mentionedRoles; [JsonProperty("mention_roles")] internal List _mentionedRoleIds; [Newtonsoft.Json.JsonIgnore] internal List _mentionedChannels; [JsonProperty("attachments", NullValueHandling = NullValueHandling.Ignore)] internal List _attachments = new List(); [JsonProperty("embeds", NullValueHandling = NullValueHandling.Ignore)] internal List _embeds = new List(); [JsonProperty("reactions", NullValueHandling = NullValueHandling.Ignore)] internal List _reactions = new List(); private readonly Lazy _jumpLink; [JsonProperty("sticker_items", NullValueHandling = NullValueHandling.Ignore)] internal List _stickers = new List(); [Newtonsoft.Json.JsonIgnore] public DiscordChannel Channel { get { return (base.Discord as DiscordClient)?.InternalGetCachedChannel(ChannelId) ?? (base.Discord as DiscordClient)?.InternalGetCachedThread(ChannelId) ?? _channel; } internal set { _channel = value; } } [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)] public ulong ChannelId { get; internal set; } [JsonProperty("components", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyCollection Components { get; internal set; } [JsonProperty("author", NullValueHandling = NullValueHandling.Ignore)] public DiscordUser Author { get; internal set; } [JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)] public string Content { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DateTimeOffset Timestamp => _timestampRaw ?? base.CreationTimestamp; [JsonProperty("timestamp", NullValueHandling = NullValueHandling.Ignore)] internal DateTimeOffset? _timestampRaw { get; set; } [JsonProperty("edited_timestamp", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset? EditedTimestamp { get; internal set; } [Newtonsoft.Json.JsonIgnore] public bool IsEdited => EditedTimestamp.HasValue; [JsonProperty("tts", NullValueHandling = NullValueHandling.Ignore)] public bool IsTTS { get; internal set; } [JsonProperty("mention_everyone", NullValueHandling = NullValueHandling.Ignore)] public bool MentionEveryone { get; internal set; } [Newtonsoft.Json.JsonIgnore] public IReadOnlyList MentionedUsers => _mentionedUsers; [Newtonsoft.Json.JsonIgnore] public IReadOnlyList MentionedRoles => _mentionedRoles; [Newtonsoft.Json.JsonIgnore] public IReadOnlyList MentionedChannels => _mentionedChannels; [Newtonsoft.Json.JsonIgnore] public IReadOnlyList Attachments => _attachments; [Newtonsoft.Json.JsonIgnore] public IReadOnlyList Embeds => _embeds; [Newtonsoft.Json.JsonIgnore] public IReadOnlyList Reactions => _reactions; [JsonProperty("pinned", NullValueHandling = NullValueHandling.Ignore)] public bool Pinned { get; internal set; } [JsonProperty("webhook_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? WebhookId { get; internal set; } [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public MessageType? MessageType { get; internal set; } [JsonProperty("activity", NullValueHandling = NullValueHandling.Ignore)] public DiscordMessageActivity Activity { get; internal set; } [JsonProperty("application", NullValueHandling = NullValueHandling.Ignore)] public DiscordMessageApplication Application { get; internal set; } [JsonProperty("message_reference", NullValueHandling = NullValueHandling.Ignore)] internal InternalDiscordMessageReference? _internalReference { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordMessageReference Reference { get { if (!_internalReference.HasValue) { return null; } return this?.InternalBuildMessageReference(); } } [JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)] public MessageFlags? Flags { get; internal set; } [Newtonsoft.Json.JsonIgnore] public bool WebhookMessage => WebhookId.HasValue; [Newtonsoft.Json.JsonIgnore] public Uri JumpLink => _jumpLink.Value; [Newtonsoft.Json.JsonIgnore] public IReadOnlyList Stickers => _stickers; [JsonProperty("guild_id", NullValueHandling = NullValueHandling.Ignore)] internal ulong? _guildId { get; set; } [JsonProperty("referenced_message", NullValueHandling = NullValueHandling.Ignore)] public DiscordMessage ReferencedMessage { get; internal set; } [JsonProperty("interaction", NullValueHandling = NullValueHandling.Ignore)] public DiscordMessageInteraction Interaction { get; internal set; } [JsonProperty("application_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? ApplicationId { get; internal set; } internal DiscordMessage() { _jumpLink = new Lazy(delegate { string text = ((Channel is DiscordDmChannel) ? "@me" : Channel.GuildId.Value.ToString(CultureInfo.InvariantCulture)); string text2 = ChannelId.ToString(CultureInfo.InvariantCulture); string text3 = base.Id.ToString(CultureInfo.InvariantCulture); return new Uri("https://discord.com/channels/" + text + "/" + text2 + "/" + text3); }); } internal DiscordMessage(DiscordMessage other) : this() { base.Discord = other.Discord; _attachments = new List(other._attachments); _embeds = new List(other._embeds); if (other._mentionedChannels != null) { _mentionedChannels = new List(other._mentionedChannels); } if (other._mentionedRoles != null) { _mentionedRoles = new List(other._mentionedRoles); } if (other._mentionedRoleIds != null) { _mentionedRoleIds = new List(other._mentionedRoleIds); } _mentionedUsers = new List(other._mentionedUsers); _reactions = new List(other._reactions); _stickers = new List(other._stickers); Author = other.Author; ChannelId = other.ChannelId; Content = other.Content; EditedTimestamp = other.EditedTimestamp; base.Id = other.Id; IsTTS = other.IsTTS; MessageType = other.MessageType; Pinned = other.Pinned; _timestampRaw = other._timestampRaw; WebhookId = other.WebhookId; ApplicationId = other.ApplicationId; } internal DiscordMessageReference InternalBuildMessageReference() { DiscordClient discordClient = base.Discord as DiscordClient; ulong? guildId = _internalReference.Value.GuildId; ulong? channelId = _internalReference.Value.ChannelId; ulong? messageId = _internalReference.Value.MessageId; DiscordMessageReference discordMessageReference = new DiscordMessageReference(); if (guildId.HasValue) { discordMessageReference.Guild = (discordClient._guilds.TryGetValue(guildId.Value, out var value) ? value : new DiscordGuild { Id = guildId.Value, Discord = discordClient }); } DiscordChannel discordChannel = discordClient.InternalGetCachedChannel(channelId.Value); if (discordChannel == null) { discordMessageReference.Channel = new DiscordChannel { Id = channelId.Value, Discord = discordClient }; if (guildId.HasValue) { discordMessageReference.Channel.GuildId = guildId.Value; } } else { discordMessageReference.Channel = discordChannel; } if (discordClient.MessageCache != null && discordClient.MessageCache.TryGet((DiscordMessage m) => m.Id == messageId.Value && m.ChannelId == channelId, out var item)) { discordMessageReference.Message = item; } else { discordMessageReference.Message = new DiscordMessage { ChannelId = ChannelId, Discord = discordClient }; if (messageId.HasValue) { discordMessageReference.Message.Id = messageId.Value; } } return discordMessageReference; } private IMention[] GetMentions() { List list = new List(); if (ReferencedMessage != null && _mentionedUsers.Any((DiscordUser r) => r.Id == ReferencedMessage.Author.Id)) { list.Add(default(RepliedUserMention)); } List mentionedUsers = _mentionedUsers; if (mentionedUsers != null && mentionedUsers.Any()) { list.AddRange(((IEnumerable)_mentionedUsers).Select((Func)((DiscordUser m) => new UserMention(m)))); } List mentionedRoleIds = _mentionedRoleIds; if (mentionedRoleIds != null && mentionedRoleIds.Any()) { list.AddRange(((IEnumerable)_mentionedRoleIds).Select((Func)((ulong r) => new RoleMention(r)))); } return list.ToArray(); } internal void PopulateMentions() { DiscordGuild guild = Channel?.Guild; if (_mentionedUsers == null) { _mentionedUsers = new List(); } if (_mentionedRoles == null) { _mentionedRoles = new List(); } if (_mentionedChannels == null) { _mentionedChannels = new List(); } HashSet hashSet = new HashSet(new DiscordUserComparer()); if (guild != null) { foreach (DiscordUser mentionedUser in _mentionedUsers) { DiscordMember discordMember = mentionedUser as DiscordMember; if (discordMember != null) { base.Discord.UpdateUserCache(new DiscordUser { Id = discordMember.Id, Username = discordMember.Username, Discriminator = discordMember.Discriminator, AvatarHash = discordMember.AvatarHash, _bannerColor = discordMember._bannerColor, BannerHash = discordMember.BannerHash, IsBot = discordMember.IsBot, MfaEnabled = discordMember.MfaEnabled, Verified = discordMember.Verified, Email = discordMember.Email, PremiumType = discordMember.PremiumType, Locale = discordMember.Locale, Flags = discordMember.Flags, OAuthFlags = discordMember.OAuthFlags, Discord = base.Discord }); } else { mentionedUser.Discord = base.Discord; base.Discord.UpdateUserCache(mentionedUser); } hashSet.Add(discordMember ?? (guild._members.TryGetValue(mentionedUser.Id, out var value) ? value : mentionedUser)); } } if (!string.IsNullOrWhiteSpace(Content) && guild != null) { _mentionedRoles = _mentionedRoles.Union(_mentionedRoleIds.Select((ulong xid) => guild.GetRole(xid))).ToList(); _mentionedChannels = _mentionedChannels.Union(from xid in Utilities.GetChannelMentions(this) select guild.GetChannel(xid)).ToList(); } _mentionedUsers = hashSet.ToList(); } public IReadOnlyList FilterComponents() where T : DiscordComponent { List list = new List(); foreach (DiscordComponent component in Components) { if (component is DiscordActionRowComponent discordActionRowComponent) { foreach (DiscordComponent component2 in discordActionRowComponent.Components) { if (component2 is T item) { list.Add(item); } } } else if (component is T item2) { list.Add(item2); } } return list; } public Task ModifyAsync(Optional content) { return base.Discord.ApiClient.EditMessageAsync(ChannelId, base.Id, content, default(Optional>), (Optional>)(IEnumerable)GetMentions(), null, (IReadOnlyCollection)(object)Array.Empty(), null, null); } public Task ModifyAsync(Optional embed = default(Optional)) { return base.Discord.ApiClient.EditMessageAsync(ChannelId, base.Id, default(Optional), (Optional>)((!embed.HasValue) ? ((IEnumerable)Array.Empty()) : ((IEnumerable)new DiscordEmbed[1] { embed.Value })), (Optional>)(IEnumerable)GetMentions(), null, (IReadOnlyCollection)(object)Array.Empty(), null, null); } public Task ModifyAsync(Optional content, Optional embed = default(Optional)) { return base.Discord.ApiClient.EditMessageAsync(ChannelId, base.Id, content, (Optional>)((!embed.HasValue) ? ((IEnumerable)Array.Empty()) : ((IEnumerable)new DiscordEmbed[1] { embed.Value })), (Optional>)(IEnumerable)GetMentions(), null, (IReadOnlyCollection)(object)Array.Empty(), null, null); } public Task ModifyAsync(Optional content, Optional> embeds = default(Optional>)) { return base.Discord.ApiClient.EditMessageAsync(ChannelId, base.Id, content, embeds, (Optional>)(IEnumerable)GetMentions(), null, (IReadOnlyCollection)(object)Array.Empty(), null, null); } public async Task ModifyAsync(DiscordMessageBuilder builder, bool suppressEmbeds = false, IEnumerable attachments = null) { builder.Validate(isModify: true); return await base.Discord.ApiClient.EditMessageAsync(ChannelId, base.Id, builder.Content, new Optional>(builder.Embeds), (Optional>)(IEnumerable)builder._mentions, builder.Components, builder.Files, suppressEmbeds ? new MessageFlags?(MessageFlags.SuppressedEmbeds) : null, attachments).ConfigureAwait(continueOnCapturedContext: false); } public async Task ModifyAsync(Action action, bool suppressEmbeds = false, IEnumerable attachments = null) { DiscordMessageBuilder discordMessageBuilder = new DiscordMessageBuilder(); action(discordMessageBuilder); discordMessageBuilder.Validate(isModify: true); return await base.Discord.ApiClient.EditMessageAsync(ChannelId, base.Id, discordMessageBuilder.Content, new Optional>(discordMessageBuilder.Embeds), (Optional>)(IEnumerable)discordMessageBuilder._mentions, discordMessageBuilder.Components, discordMessageBuilder.Files, suppressEmbeds ? new MessageFlags?(MessageFlags.SuppressedEmbeds) : null, attachments).ConfigureAwait(continueOnCapturedContext: false); } public Task ModifyEmbedSuppressionAsync(bool hideEmbeds) { return base.Discord.ApiClient.EditMessageAsync(ChannelId, base.Id, default(Optional), default(Optional>), default(Optional>), null, (IReadOnlyCollection)(object)Array.Empty(), hideEmbeds ? new MessageFlags?(MessageFlags.SuppressedEmbeds) : null, null); } public Task DeleteAsync(string reason = null) { return base.Discord.ApiClient.DeleteMessageAsync(ChannelId, base.Id, reason); } public Task PinAsync() { return base.Discord.ApiClient.PinMessageAsync(ChannelId, base.Id); } public Task UnpinAsync() { return base.Discord.ApiClient.UnpinMessageAsync(ChannelId, base.Id); } public Task RespondAsync(string content) { return base.Discord.ApiClient.CreateMessageAsync(ChannelId, content, null, base.Id, mentionReply: false, failOnInvalidReply: false, suppressNotifications: false); } public Task RespondAsync(DiscordEmbed embed) { return base.Discord.ApiClient.CreateMessageAsync(ChannelId, null, (embed == null) ? null : new DiscordEmbed[1] { embed }, base.Id, mentionReply: false, failOnInvalidReply: false, suppressNotifications: false); } public Task RespondAsync(string content, DiscordEmbed embed) { return base.Discord.ApiClient.CreateMessageAsync(ChannelId, content, (embed == null) ? null : new DiscordEmbed[1] { embed }, base.Id, mentionReply: false, failOnInvalidReply: false, suppressNotifications: false); } public Task RespondAsync(DiscordMessageBuilder builder) { return base.Discord.ApiClient.CreateMessageAsync(ChannelId, builder.WithReply(base.Id)); } public Task RespondAsync(Action action) { DiscordMessageBuilder discordMessageBuilder = new DiscordMessageBuilder(); action(discordMessageBuilder); return base.Discord.ApiClient.CreateMessageAsync(ChannelId, discordMessageBuilder.WithReply(base.Id)); } public Task CreateThreadAsync(string name, AutoArchiveDuration archiveAfter, string reason = null) { if (Channel.Type != 0 && Channel.Type != ChannelType.News) { throw new InvalidOperationException("Threads can only be created within text or news channels."); } return base.Discord.ApiClient.CreateThreadFromMessageAsync(Channel.Id, base.Id, name, archiveAfter, reason); } public Task CreateReactionAsync(DiscordEmoji emoji) { return base.Discord.ApiClient.CreateReactionAsync(ChannelId, base.Id, emoji.ToReactionString()); } public Task DeleteOwnReactionAsync(DiscordEmoji emoji) { return base.Discord.ApiClient.DeleteOwnReactionAsync(ChannelId, base.Id, emoji.ToReactionString()); } public Task DeleteReactionAsync(DiscordEmoji emoji, DiscordUser user, string reason = null) { return base.Discord.ApiClient.DeleteUserReactionAsync(ChannelId, base.Id, user.Id, emoji.ToReactionString(), reason); } public Task> GetReactionsAsync(DiscordEmoji emoji, int limit = 25, ulong? after = null) { return GetReactionsInternalAsync(emoji, limit, after); } public Task DeleteAllReactionsAsync(string reason = null) { return base.Discord.ApiClient.DeleteAllReactionsAsync(ChannelId, base.Id, reason); } public Task DeleteReactionsEmojiAsync(DiscordEmoji emoji) { return base.Discord.ApiClient.DeleteReactionsEmojiAsync(ChannelId, base.Id, emoji.ToReactionString()); } private async Task> GetReactionsInternalAsync(DiscordEmoji emoji, int limit = 25, ulong? after = null) { if (limit < 0) { throw new ArgumentException("Cannot get a negative number of reactions' users."); } if (limit == 0) { return Array.Empty(); } List users = new List(limit); int remaining = limit; ulong? after_id = after; int count; do { int limit2 = ((remaining > 100) ? 100 : remaining); IReadOnlyList readOnlyList = await base.Discord.ApiClient.GetReactionsAsync(Channel.Id, base.Id, emoji.ToReactionString(), after_id, limit2).ConfigureAwait(continueOnCapturedContext: false); count = readOnlyList.Count; remaining -= count; users.AddRange(readOnlyList); after_id = readOnlyList.LastOrDefault()?.Id; } while (remaining > 0 && count > 0); return new ReadOnlyCollection(users); } public override string ToString() { return $"Message {base.Id}; Attachment count: {_attachments.Count}; Embed count: {_embeds.Count}; Contents: {Content}"; } public override bool Equals(object obj) { return Equals(obj as DiscordMessage); } public bool Equals(DiscordMessage e) { if ((object)e == null) { return false; } if ((object)this != e) { if (base.Id == e.Id) { return ChannelId == e.ChannelId; } return false; } return true; } public override int GetHashCode() { return (13 * 7 + base.Id.GetHashCode()) * 7 + ChannelId.GetHashCode(); } public static bool operator ==(DiscordMessage e1, DiscordMessage e2) { if (((object)e1 == null && (object)e2 != null) || ((object)e1 != null && (object)e2 == null)) { return false; } if ((object)e1 != null || (object)e2 != null) { if (e1.Id == e2.Id) { return e1.ChannelId == e2.ChannelId; } return false; } return true; } public static bool operator !=(DiscordMessage e1, DiscordMessage e2) { return !(e1 == e2); } } internal class DiscordMessageActivity { [JsonProperty("type")] public MessageActivityType Type { get; internal set; } [JsonProperty("party_id")] public string PartyId { get; internal set; } internal DiscordMessageActivity() { } } internal class DiscordMessageApplication : SnowflakeObject { [JsonProperty("cover_image")] public virtual string CoverImageUrl { get; internal set; } [JsonProperty("description")] public string Description { get; internal set; } [JsonProperty("icon")] public virtual string Icon { get; internal set; } [JsonProperty("name")] public string Name { get; internal set; } internal DiscordMessageApplication() { } } internal sealed class DiscordMessageBuilder : BaseDiscordMessageBuilder { internal List _stickers = new List(); public DiscordEmbed Embed { get { if (_embeds.Count <= 0) { return null; } return _embeds[0]; } set { _embeds.Clear(); if (value != null) { _embeds.Add(value); } } } public DiscordMessageSticker Sticker { get { if (_stickers.Count <= 0) { return null; } return _stickers[0]; } set { _stickers.Clear(); if (value != null) { _stickers.Add(value); } } } public IReadOnlyList Stickers => _stickers; public ulong? ReplyId { get; private set; } public bool MentionOnReply { get; private set; } public bool FailOnInvalidReply { get; set; } public DiscordMessageBuilder() { } public DiscordMessageBuilder(DiscordMessageBuilder builder) : base((IDiscordMessageBuilder)builder) { Sticker = builder.Sticker; ReplyId = builder.ReplyId; MentionOnReply = builder.MentionOnReply; FailOnInvalidReply = builder.FailOnInvalidReply; } public DiscordMessageBuilder(IDiscordMessageBuilder builder) : base(builder) { } public DiscordMessageBuilder(DiscordMessage baseMessage) { base.IsTTS = baseMessage.IsTTS; ReplyId = baseMessage.ReferencedMessage?.Id; _components = baseMessage.Components.OfType().ToList(); _content = baseMessage.Content; _embeds = baseMessage.Embeds.ToList(); _stickers = baseMessage.Stickers.ToList(); _mentions = new List(); if (baseMessage._mentionedRoles != null) { foreach (DiscordUser mentionedUser in baseMessage._mentionedUsers) { _mentions.Add(new UserMention(mentionedUser.Id)); } } if (baseMessage._mentionedRoles == null) { return; } foreach (DiscordRole mentionedRole in baseMessage._mentionedRoles) { _mentions.Add(new RoleMention(mentionedRole.Id)); } } public DiscordMessageBuilder WithSticker(DiscordMessageSticker sticker) { Sticker = sticker; return this; } public DiscordMessageBuilder WithStickers(IEnumerable stickers) { _stickers = stickers.ToList(); return this; } public DiscordMessageBuilder WithEmbed(DiscordEmbed embed) { if (embed == null) { return this; } Embed = embed; return this; } public DiscordMessageBuilder WithAllowedMention(IMention allowedMention) { return AddMention(allowedMention); } public DiscordMessageBuilder WithAllowedMentions(IEnumerable allowedMentions) { return AddMentions(allowedMentions); } public DiscordMessageBuilder WithReply(ulong? messageId, bool mention = false, bool failOnInvalidReply = false) { ReplyId = messageId; MentionOnReply = mention; FailOnInvalidReply = failOnInvalidReply; if (mention) { if (_mentions == null) { _mentions = new List(); } _mentions.Add(default(RepliedUserMention)); } return this; } public Task SendAsync(DiscordChannel channel) { return channel.SendMessageAsync(this); } public Task ModifyAsync(DiscordMessage msg) { return msg.ModifyAsync(this); } public override void ClearComponents() { ReplyId = null; MentionOnReply = false; Sticker = null; FailOnInvalidReply = false; base.ClearComponents(); } internal void Validate(bool isModify = false) { if (_embeds.Count > 10) { throw new ArgumentException("A message can only have up to 10 embeds."); } IReadOnlyList files = base.Files; if (files != null && files.Count == 0 && string.IsNullOrEmpty(base.Content)) { IReadOnlyList embeds = base.Embeds; if ((embeds == null || !embeds.Any()) && Sticker == null) { throw new ArgumentException("You must specify content, an embed, a sticker, or at least one file."); } } if (base.Components.Count > 5) { throw new InvalidOperationException("You can only have 5 action rows per message."); } if (base.Components.Any((DiscordActionRowComponent c) => c.Components.Count > 5)) { throw new InvalidOperationException("Action rows can only have 5 components"); } IReadOnlyList stickers = Stickers; if (stickers != null && stickers.Count > 3) { throw new InvalidOperationException("You can only have 3 stickers per message."); } } } internal class DiscordMessageFile { public string FileName { get; internal set; } public Stream Stream { get; internal set; } internal string FileType { get; set; } internal string ContentType { get; set; } internal long? ResetPositionTo { get; set; } internal DiscordMessageFile(string fileName, Stream stream, long? resetPositionTo, string fileType = null, string contentType = null) { FileName = fileName ?? "file"; FileType = fileType; ContentType = contentType; Stream = stream; ResetPositionTo = resetPositionTo; } } internal class DiscordMessageInteraction : SnowflakeObject { [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public InteractionType Type { get; internal set; } [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("user", NullValueHandling = NullValueHandling.Ignore)] public DiscordUser User { get; internal set; } } internal class DiscordMessageReference { public DiscordMessage Message { get; internal set; } public DiscordChannel Channel { get; internal set; } public DiscordGuild Guild { get; internal set; } public override string ToString() { return $"Guild: {Guild.Id}, Channel: {Channel.Id}, Message: {Message.Id}"; } internal DiscordMessageReference() { } } internal struct InternalDiscordMessageReference { [JsonProperty("message_id", NullValueHandling = NullValueHandling.Ignore)] internal ulong? MessageId { get; set; } [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)] internal ulong? ChannelId { get; set; } [JsonProperty("guild_id", NullValueHandling = NullValueHandling.Ignore)] internal ulong? GuildId { get; set; } [JsonProperty("fail_if_not_exists", NullValueHandling = NullValueHandling.Ignore)] public bool FailIfNotExists { get; set; } } internal class DiscordMessageSticker : SnowflakeObject, IEquatable { [JsonProperty("pack_id")] public ulong PackId { get; internal set; } [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("description")] public string Description { get; internal set; } [JsonProperty("type")] public StickerType Type { get; internal set; } [JsonProperty("user")] public DiscordUser User { get; internal set; } public DiscordGuild Guild => (base.Discord as DiscordClient).InternalGetCachedGuild(GuildId); public string StickerUrl => $"https://cdn.discordapp.com/stickers/{base.Id}{GetFileTypeExtension()}"; [JsonProperty("guild_id")] public ulong? GuildId { get; internal set; } [JsonProperty("available")] public bool Available { get; internal set; } [JsonProperty("sort_value")] public int SortValue { get; internal set; } [Newtonsoft.Json.JsonIgnore] public IReadOnlyList Tags { get { if (InternalTags == null) { return Array.Empty(); } return InternalTags.Split(new char[1] { ',' }); } } [JsonProperty("asset")] public string Asset { get; internal set; } [JsonProperty("preview_asset", NullValueHandling = NullValueHandling.Ignore)] public string PreviewAsset { get; internal set; } [JsonProperty("format_type")] public StickerFormat FormatType { get; internal set; } [JsonProperty("tags", NullValueHandling = NullValueHandling.Ignore)] internal string InternalTags { get; set; } public string BannerUrl => $"https://cdn.discordapp.com/app-assets/710982414301790216/store/{BannerAssetId}.png?size=4096"; [JsonProperty("banner_asset_id")] internal ulong BannerAssetId { get; set; } public bool Equals(DiscordMessageSticker other) { return base.Id == other.Id; } public override string ToString() { return $"Sticker {base.Id}; {Name}; {FormatType}"; } private string GetFileTypeExtension() { switch (FormatType) { case StickerFormat.PNG: case StickerFormat.APNG: return ".png"; case StickerFormat.LOTTIE: return ".json"; default: return ".png"; } } } internal enum StickerType { Standard = 1, Guild } internal enum StickerFormat { PNG = 1, APNG, LOTTIE } internal sealed class DiscordMessageStickerPack : SnowflakeObject { [JsonProperty("stickers")] internal Dictionary _stickers = new Dictionary(); public IReadOnlyDictionary Stickers => _stickers; [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("sku_id")] public ulong SkuId { get; internal set; } [JsonProperty("cover_sticker_id")] public ulong CoverStickerId { get; internal set; } [JsonProperty("description")] public string Description { get; internal set; } [JsonProperty("banner_asset_id")] public ulong BannerAssetId { get; internal set; } internal DiscordMessageStickerPack() { } } internal class DiscordReaction { [JsonProperty("count", NullValueHandling = NullValueHandling.Ignore)] public int Count { get; internal set; } [JsonProperty("me", NullValueHandling = NullValueHandling.Ignore)] public bool IsMe { get; internal set; } [JsonProperty("emoji", NullValueHandling = NullValueHandling.Ignore)] public DiscordEmoji Emoji { get; internal set; } internal DiscordReaction() { } } internal sealed class DiscordEmbed { [JsonProperty("color", NullValueHandling = NullValueHandling.Include)] internal Optional _color; [Newtonsoft.Json.JsonIgnore] private readonly Lazy> _colorLazy; [JsonProperty("title", NullValueHandling = NullValueHandling.Ignore)] public string Title { get; internal set; } [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public string Type { get; internal set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; internal set; } [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)] public Uri Url { get; internal set; } [JsonProperty("timestamp", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset? Timestamp { get; internal set; } [Newtonsoft.Json.JsonIgnore] public Optional Color => _colorLazy.Value; [JsonProperty("footer", NullValueHandling = NullValueHandling.Ignore)] public DiscordEmbedFooter Footer { get; internal set; } [JsonProperty("image", NullValueHandling = NullValueHandling.Ignore)] public DiscordEmbedImage Image { get; internal set; } [JsonProperty("thumbnail", NullValueHandling = NullValueHandling.Ignore)] public DiscordEmbedThumbnail Thumbnail { get; internal set; } [JsonProperty("video", NullValueHandling = NullValueHandling.Ignore)] public DiscordEmbedVideo Video { get; internal set; } [JsonProperty("provider", NullValueHandling = NullValueHandling.Ignore)] public DiscordEmbedProvider Provider { get; internal set; } [JsonProperty("author", NullValueHandling = NullValueHandling.Ignore)] public DiscordEmbedAuthor Author { get; internal set; } [JsonProperty("fields", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Fields { get; internal set; } internal DiscordEmbed() { _colorLazy = new Lazy>(() => (!_color.HasValue) ? Optional.FromNoValue() : Optional.FromValue((DiscordColor)_color.Value)); } } internal sealed class DiscordEmbedAuthor { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)] public Uri Url { get; set; } [JsonProperty("icon_url", NullValueHandling = NullValueHandling.Ignore)] public DiscordUri IconUrl { get; set; } [JsonProperty("proxy_icon_url", NullValueHandling = NullValueHandling.Ignore)] public DiscordUri ProxyIconUrl { get; internal set; } internal DiscordEmbedAuthor() { } } internal sealed class DiscordEmbedBuilder { public class EmbedAuthor { private string _name; internal Uri _uri; internal DiscordUri _iconUri; public string Name { get { return _name; } set { if (value != null && value.Length > 256) { throw new ArgumentException("Author name length cannot exceed 256 characters.", "value"); } _name = value; } } public string Url { get { return _uri?.ToString(); } set { _uri = (string.IsNullOrEmpty(value) ? null : new Uri(value)); } } public string IconUrl { get { return _iconUri?.ToString(); } set { _iconUri = (string.IsNullOrEmpty(value) ? null : new DiscordUri(value)); } } } public class EmbedFooter { private string _text; internal DiscordUri _iconUri; public string Text { get { return _text; } set { if (value != null && value.Length > 2048) { throw new ArgumentException("Footer text length cannot exceed 2048 characters.", "value"); } _text = value; } } public string IconUrl { get { return _iconUri?.ToString(); } set { _iconUri = (string.IsNullOrEmpty(value) ? null : new DiscordUri(value)); } } } public class EmbedThumbnail { internal DiscordUri _uri; private int _height; private int _width; public string Url { get { return _uri?.ToString(); } set { _uri = (string.IsNullOrEmpty(value) ? null : new DiscordUri(value)); } } public int Height { get { return _height; } set { _height = ((value >= 0) ? value : 0); } } public int Width { get { return _width; } set { _width = ((value >= 0) ? value : 0); } } } private string _title; private string _description; private Uri _url; private DiscordUri _imageUri; private readonly List _fields = new List(); public string Title { get { return _title; } set { if (value != null && value.Length > 256) { throw new ArgumentException("Title length cannot exceed 256 characters.", "value"); } _title = value; } } public string Description { get { return _description; } set { if (value != null && value.Length > 4096) { throw new ArgumentException("Description length cannot exceed 4096 characters.", "value"); } _description = value; } } public string Url { get { return _url?.ToString(); } set { _url = (string.IsNullOrEmpty(value) ? null : new Uri(value)); } } public Optional Color { get; set; } public DateTimeOffset? Timestamp { get; set; } public string ImageUrl { get { return _imageUri?.ToString(); } set { _imageUri = (string.IsNullOrEmpty(value) ? null : new DiscordUri(value)); } } public EmbedAuthor Author { get; set; } public EmbedFooter Footer { get; set; } public EmbedThumbnail Thumbnail { get; set; } public IReadOnlyList Fields { get; } public DiscordEmbedBuilder() { Fields = new ReadOnlyCollection(_fields); } public DiscordEmbedBuilder(DiscordEmbed original) : this() { Title = original.Title; Description = original.Description; Url = original.Url?.ToString(); ImageUrl = original.Image?.Url?.ToString(); Color = original.Color; Timestamp = original.Timestamp; if (original.Thumbnail != null) { Thumbnail = new EmbedThumbnail { Url = original.Thumbnail.Url?.ToString(), Height = original.Thumbnail.Height, Width = original.Thumbnail.Width }; } if (original.Author != null) { Author = new EmbedAuthor { IconUrl = original.Author.IconUrl?.ToString(), Name = original.Author.Name, Url = original.Author.Url?.ToString() }; } if (original.Footer != null) { Footer = new EmbedFooter { IconUrl = original.Footer.IconUrl?.ToString(), Text = original.Footer.Text }; } IReadOnlyList fields = original.Fields; if (fields != null && fields.Any()) { _fields.AddRange(original.Fields); } while (_fields.Count > 25) { _fields.RemoveAt(_fields.Count - 1); } } public DiscordEmbedBuilder WithTitle(string title) { Title = title; return this; } public DiscordEmbedBuilder WithDescription(string description) { Description = description; return this; } public DiscordEmbedBuilder WithUrl(string url) { Url = url; return this; } public DiscordEmbedBuilder WithUrl(Uri url) { _url = url; return this; } public DiscordEmbedBuilder WithColor(DiscordColor color) { Color = color; return this; } public DiscordEmbedBuilder WithTimestamp(DateTimeOffset? timestamp) { Timestamp = timestamp; return this; } public DiscordEmbedBuilder WithTimestamp(DateTime? timestamp) { Timestamp = ((!timestamp.HasValue) ? null : new DateTimeOffset?(new DateTimeOffset(timestamp.Value))); return this; } public DiscordEmbedBuilder WithTimestamp(ulong snowflake) { Timestamp = new DateTimeOffset(2015, 1, 1, 0, 0, 0, TimeSpan.Zero).AddMilliseconds(snowflake >> 22); return this; } public DiscordEmbedBuilder WithImageUrl(string url) { ImageUrl = url; return this; } public DiscordEmbedBuilder WithImageUrl(Uri url) { _imageUri = new DiscordUri(url); return this; } public DiscordEmbedBuilder WithThumbnail(string url, int height = 0, int width = 0) { Thumbnail = new EmbedThumbnail { Url = url, Height = height, Width = width }; return this; } public DiscordEmbedBuilder WithThumbnail(Uri url, int height = 0, int width = 0) { Thumbnail = new EmbedThumbnail { _uri = new DiscordUri(url), Height = height, Width = width }; return this; } public DiscordEmbedBuilder WithAuthor(string name = null, string url = null, string iconUrl = null) { Author = ((string.IsNullOrEmpty(name) && string.IsNullOrEmpty(url) && string.IsNullOrEmpty(iconUrl)) ? null : new EmbedAuthor { Name = name, Url = url, IconUrl = iconUrl }); return this; } public DiscordEmbedBuilder WithFooter(string text = null, string iconUrl = null) { if (text != null && text.Length > 2048) { throw new ArgumentException("Footer text length cannot exceed 2048 characters.", "text"); } Footer = ((string.IsNullOrEmpty(text) && string.IsNullOrEmpty(iconUrl)) ? null : new EmbedFooter { Text = text, IconUrl = iconUrl }); return this; } public DiscordEmbedBuilder AddField(string name, string value, bool inline = false) { if (string.IsNullOrWhiteSpace(name)) { if (name == null) { throw new ArgumentNullException("name"); } throw new ArgumentException("Name cannot be empty or whitespace.", "name"); } if (string.IsNullOrWhiteSpace(value)) { if (value == null) { throw new ArgumentNullException("value"); } throw new ArgumentException("Value cannot be empty or whitespace.", "value"); } if (name.Length > 256) { throw new ArgumentException("Embed field name length cannot exceed 256 characters."); } if (value.Length > 1024) { throw new ArgumentException("Embed field value length cannot exceed 1024 characters."); } if (_fields.Count >= 25) { throw new InvalidOperationException("Cannot add more than 25 fields."); } _fields.Add(new DiscordEmbedField { Inline = inline, Name = name, Value = value }); return this; } public DiscordEmbedBuilder RemoveFieldAt(int index) { _fields.RemoveAt(index); return this; } public DiscordEmbedBuilder RemoveFieldRange(int index, int count) { _fields.RemoveRange(index, count); return this; } public DiscordEmbedBuilder ClearFields() { _fields.Clear(); return this; } public DiscordEmbed Build() { DiscordEmbed discordEmbed = new DiscordEmbed { Title = _title, Description = _description, Url = _url, _color = Color.IfPresent((DiscordColor e) => e.Value), Timestamp = Timestamp }; if (Footer != null) { discordEmbed.Footer = new DiscordEmbedFooter { Text = Footer.Text, IconUrl = Footer._iconUri }; } if (Author != null) { discordEmbed.Author = new DiscordEmbedAuthor { Name = Author.Name, Url = Author._uri, IconUrl = Author._iconUri }; } if (_imageUri != null) { discordEmbed.Image = new DiscordEmbedImage { Url = _imageUri }; } if (Thumbnail != null) { discordEmbed.Thumbnail = new DiscordEmbedThumbnail { Url = Thumbnail._uri, Height = Thumbnail.Height, Width = Thumbnail.Width }; } discordEmbed.Fields = new ReadOnlyCollection(new List(_fields)); return discordEmbed; } public static implicit operator DiscordEmbed(DiscordEmbedBuilder builder) { return builder?.Build(); } } internal sealed class DiscordEmbedField { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } [JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)] public string Value { get; set; } [JsonProperty("inline", NullValueHandling = NullValueHandling.Ignore)] public bool Inline { get; set; } internal DiscordEmbedField() { } } internal sealed class DiscordEmbedFooter { [JsonProperty("text", NullValueHandling = NullValueHandling.Ignore)] public string Text { get; internal set; } [JsonProperty("icon_url", NullValueHandling = NullValueHandling.Ignore)] public DiscordUri IconUrl { get; internal set; } [JsonProperty("proxy_icon_url", NullValueHandling = NullValueHandling.Ignore)] public DiscordUri ProxyIconUrl { get; internal set; } internal DiscordEmbedFooter() { } } internal sealed class DiscordEmbedImage { [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)] public DiscordUri Url { get; internal set; } [JsonProperty("proxy_url", NullValueHandling = NullValueHandling.Ignore)] public DiscordUri ProxyUrl { get; internal set; } [JsonProperty("height", NullValueHandling = NullValueHandling.Ignore)] public int Height { get; internal set; } [JsonProperty("width", NullValueHandling = NullValueHandling.Ignore)] public int Width { get; internal set; } internal DiscordEmbedImage() { } } internal sealed class DiscordEmbedProvider { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)] public Uri Url { get; internal set; } internal DiscordEmbedProvider() { } } internal sealed class DiscordEmbedThumbnail { [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)] public DiscordUri Url { get; internal set; } [JsonProperty("proxy_url", NullValueHandling = NullValueHandling.Ignore)] public DiscordUri ProxyUrl { get; internal set; } [JsonProperty("height", NullValueHandling = NullValueHandling.Ignore)] public int Height { get; internal set; } [JsonProperty("width", NullValueHandling = NullValueHandling.Ignore)] public int Width { get; internal set; } internal DiscordEmbedThumbnail() { } } internal sealed class DiscordEmbedVideo { [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)] public Uri Url { get; internal set; } [JsonProperty("height", NullValueHandling = NullValueHandling.Ignore)] public int Height { get; internal set; } [JsonProperty("width", NullValueHandling = NullValueHandling.Ignore)] public int Width { get; internal set; } internal DiscordEmbedVideo() { } } internal interface IMention { } [StructLayout(LayoutKind.Sequential, Size = 1)] internal readonly struct RepliedUserMention : IMention { public static readonly RepliedUserMention All; } [StructLayout(LayoutKind.Sequential, Size = 1)] internal readonly struct EveryoneMention : IMention { public static readonly EveryoneMention All; } internal readonly struct UserMention : IMention { public static readonly UserMention All; public ulong? Id { get; } public UserMention(ulong id) { Id = id; } public UserMention(DiscordUser user) : this(user.Id) { } public static implicit operator UserMention(DiscordUser user) { return new UserMention(user.Id); } } internal readonly struct RoleMention : IMention { public static readonly RoleMention All; public ulong? Id { get; } public RoleMention(ulong id) { Id = id; } public RoleMention(DiscordRole role) : this(role.Id) { } public static implicit operator RoleMention(DiscordRole role) { return new RoleMention(role.Id); } } internal static class Mentions { public static IEnumerable All { get; } = new IMention[3] { EveryoneMention.All, UserMention.All, RoleMention.All }; public static IEnumerable None { get; } = Array.Empty(); } internal class DiscordOverwrite : SnowflakeObject { [Newtonsoft.Json.JsonIgnore] internal ulong _channel_id; [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public OverwriteType Type { get; internal set; } [JsonProperty("allow", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions Allowed { get; internal set; } [JsonProperty("deny", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions Denied { get; internal set; } public Task DeleteAsync(string reason = null) { return base.Discord.ApiClient.DeleteChannelPermissionAsync(_channel_id, base.Id, reason); } public Task UpdateAsync(Permissions? allow = null, Permissions? deny = null, string reason = null) { return base.Discord.ApiClient.EditChannelPermissionsAsync(_channel_id, base.Id, allow ?? Allowed, deny ?? Denied, Type.ToString().ToLowerInvariant(), reason); } public async Task GetMemberAsync() { if (Type != OverwriteType.Member) { throw new ArgumentException("Type", "This overwrite is for a role, not a member."); } return await (await base.Discord.ApiClient.GetChannelAsync(_channel_id).ConfigureAwait(continueOnCapturedContext: false)).Guild.GetMemberAsync(base.Id).ConfigureAwait(continueOnCapturedContext: false); } public async Task GetRoleAsync() { if (Type != 0) { throw new ArgumentException("Type", "This overwrite is for a member, not a role."); } return (await base.Discord.ApiClient.GetChannelAsync(_channel_id).ConfigureAwait(continueOnCapturedContext: false)).Guild.GetRole(base.Id); } internal DiscordOverwrite() { } public PermissionLevel CheckPermission(Permissions permission) { if ((Allowed & permission) != Permissions.None) { return PermissionLevel.Allowed; } if ((Denied & permission) == Permissions.None) { return PermissionLevel.Unset; } return PermissionLevel.Denied; } } internal sealed class DiscordOverwriteBuilder { public Permissions Allowed { get; set; } public Permissions Denied { get; set; } public OverwriteType Type { get; private set; } public SnowflakeObject Target { get; private set; } public DiscordOverwriteBuilder(DiscordMember member) { Target = member; Type = OverwriteType.Member; } public DiscordOverwriteBuilder(DiscordRole role) { Target = role; Type = OverwriteType.Role; } [Obsolete("The parameterless constructor will be removed in 4.4. Use the parameterized constructors instead", false)] public DiscordOverwriteBuilder() { } public DiscordOverwriteBuilder Allow(Permissions permission) { Allowed |= permission; return this; } public DiscordOverwriteBuilder Deny(Permissions permission) { Denied |= permission; return this; } public DiscordOverwriteBuilder For(DiscordMember member) { Target = member; Type = OverwriteType.Member; return this; } public DiscordOverwriteBuilder For(DiscordRole role) { Target = role; Type = OverwriteType.Role; return this; } public async Task FromAsync(DiscordOverwrite other) { Allowed = other.Allowed; Denied = other.Denied; Type = other.Type; SnowflakeObject target = ((Type != OverwriteType.Member) ? ((SnowflakeObject)(await other.GetRoleAsync().ConfigureAwait(continueOnCapturedContext: false))) : ((SnowflakeObject)(await other.GetMemberAsync().ConfigureAwait(continueOnCapturedContext: false)))); Target = target; return this; } internal DiscordRestOverwrite Build() { DiscordRestOverwrite result = default(DiscordRestOverwrite); result.Allow = Allowed; result.Deny = Denied; result.Id = Target.Id; result.Type = Type; return result; } } internal struct DiscordRestOverwrite { [JsonProperty("allow", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] internal Permissions Allow { get; set; } [JsonProperty("deny", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] internal Permissions Deny { get; set; } [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] internal ulong Id { get; set; } [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] internal OverwriteType Type { get; set; } } internal sealed class DiscordStageInstance : SnowflakeObject { [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild { get { if (!base.Discord.Guilds.TryGetValue(GuildId, out var value)) { return null; } return value; } } [JsonProperty("guild_id")] public ulong GuildId { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DiscordChannel Channel => (base.Discord as DiscordClient)?.InternalGetCachedChannel(ChannelId) ?? null; [JsonProperty("channel_id")] public ulong ChannelId { get; internal set; } [JsonProperty("topic")] public string Topic { get; internal set; } [JsonProperty("privacy_level")] public PrivacyLevel PrivacyLevel { get; internal set; } [JsonProperty("discoverable_disabled")] public bool DiscoverableDisabled { get; internal set; } public Task BecomeSpeakerAsync() { return base.Discord.ApiClient.BecomeStageInstanceSpeakerAsync(GuildId, base.Id); } public Task SendSpeakerRequestAsync() { return base.Discord.ApiClient.BecomeStageInstanceSpeakerAsync(GuildId, base.Id, null, DateTime.Now); } public Task InviteToSpeakAsync(DiscordMember member) { return base.Discord.ApiClient.BecomeStageInstanceSpeakerAsync(GuildId, base.Id, member.Id, null, false); } } internal class DiscordThreadChannel : DiscordChannel { [JsonProperty("applied_tags")] private List _appliedTagIds; [JsonProperty("owner_id", NullValueHandling = NullValueHandling.Ignore)] public ulong CreatorId { get; internal set; } [JsonProperty("message_count", NullValueHandling = NullValueHandling.Ignore)] public int? MessageCount { get; internal set; } [JsonProperty("member_count", NullValueHandling = NullValueHandling.Ignore)] public int? MemberCount { get; internal set; } [JsonProperty("member", NullValueHandling = NullValueHandling.Ignore)] public DiscordThreadChannelMember CurrentMember { get; internal set; } [JsonProperty("thread_metadata", NullValueHandling = NullValueHandling.Ignore)] public DiscordThreadChannelMetadata ThreadMetadata { get; internal set; } [JsonProperty("newly_created", NullValueHandling = NullValueHandling.Ignore)] public bool IsNew { get; internal set; } public IReadOnlyList AppliedTags { get { if (!(base.Parent is DiscordForumChannel discordForumChannel)) { return Array.Empty(); } return discordForumChannel.AvailableTags.Where((DiscordForumTag pt) => _appliedTagIds.Contains(pt.Id)).ToArray(); } } public async Task JoinThreadAsync() { await base.Discord.ApiClient.JoinThreadAsync(base.Id); } public async Task LeaveThreadAsync() { await base.Discord.ApiClient.LeaveThreadAsync(base.Id); } public async Task> ListJoinedMembersAsync() { return await base.Discord.ApiClient.ListThreadMembersAsync(base.Id); } public async Task AddThreadMemberAsync(DiscordMember member) { if (ThreadMetadata.IsArchived) { throw new InvalidOperationException("You cannot add members to an archived thread."); } await base.Discord.ApiClient.AddThreadMemberAsync(base.Id, member.Id); } public async Task RemoveThreadMemberAsync(DiscordMember member) { if (ThreadMetadata.IsArchived) { throw new InvalidOperationException("You cannot remove members from an archived thread."); } await base.Discord.ApiClient.RemoveThreadMemberAsync(base.Id, member.Id); } public async Task ModifyAsync(Action action) { ThreadChannelEditModel mdl = new ThreadChannelEditModel(); action(mdl); await base.Discord.ApiClient.ModifyThreadChannelAsync(base.Id, mdl.Name, mdl.Position, mdl.Topic, mdl.Nsfw, mdl.Parent.HasValue ? ((Optional)(mdl.Parent.Value?.Id)) : default(Optional), mdl.Bitrate, mdl.Userlimit, mdl.PerUserRateLimit, mdl.RtcRegion.IfPresent((DiscordVoiceRegion r) => r?.Id), mdl.QualityMode, mdl.Type, mdl.PermissionOverwrites, mdl.IsArchived, mdl.AutoArchiveDuration, mdl.Locked, mdl.AuditLogReason, mdl.AppliedTags).ConfigureAwait(continueOnCapturedContext: false); if (!string.IsNullOrWhiteSpace(mdl.Name)) { base.Name = mdl.Name; } if (mdl.PerUserRateLimit.HasValue) { base.PerUserRateLimit = mdl.PerUserRateLimit.Value; } if (mdl.IsArchived.HasValue) { ThreadMetadata.IsArchived = mdl.IsArchived.Value; } if (mdl.AutoArchiveDuration.HasValue) { ThreadMetadata.AutoArchiveDuration = mdl.AutoArchiveDuration.Value; } if (mdl.Locked.HasValue) { ThreadMetadata.IsLocked = mdl.Locked.Value; } } public async Task GetThreadMemberAsync(DiscordMember member) { return await base.Discord.ApiClient.GetThreadMemberAsync(base.Id, member.Id); } internal DiscordThreadChannel() { } } internal class DiscordThreadChannelMember { [Newtonsoft.Json.JsonIgnore] internal ulong _guild_id; [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public ulong ThreadId { get; set; } [JsonProperty("user_id", NullValueHandling = NullValueHandling.Ignore)] public ulong Id { get; set; } [JsonProperty("join_timestamp", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset? JoinTimeStamp { get; internal set; } [JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)] internal int UserFlags { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordMember Member { get { if (!(Guild != null)) { return null; } if (!Guild._members.TryGetValue(Id, out var value)) { return new DiscordMember { Id = Id, _guild_id = _guild_id, Discord = Discord }; } return value; } } [Newtonsoft.Json.JsonIgnore] public DiscordChannel Thread { get { if (!(Guild != null)) { return null; } if (!Guild._threads.TryGetValue(ThreadId, out var value)) { return null; } return value; } } [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild { get { if (!Discord.Guilds.TryGetValue(_guild_id, out var value)) { return null; } return value; } } [Newtonsoft.Json.JsonIgnore] internal BaseDiscordClient Discord { get; set; } internal DiscordThreadChannelMember() { } public override bool Equals(object obj) { return Equals(obj as DiscordThreadChannelMember); } public bool Equals(DiscordThreadChannelMember e) { if ((object)e == null) { return false; } if ((object)this != e) { if (Id == e.Id) { return ThreadId == e.ThreadId; } return false; } return true; } public override int GetHashCode() { return (13 * 7 + Id.GetHashCode()) * 7 + ThreadId.GetHashCode(); } public static bool operator ==(DiscordThreadChannelMember e1, DiscordThreadChannelMember e2) { if (((object)e1 == null && (object)e2 != null) || ((object)e1 != null && (object)e2 == null)) { return false; } if ((object)e1 != null || (object)e2 != null) { if (e1.Id == e2.Id) { return e1.ThreadId == e2.ThreadId; } return false; } return true; } public static bool operator !=(DiscordThreadChannelMember e1, DiscordThreadChannelMember e2) { return !(e1 == e2); } } internal class DiscordThreadChannelMetadata { [JsonProperty("archived", NullValueHandling = NullValueHandling.Ignore)] public bool IsArchived { get; internal set; } [JsonProperty("auto_archive_duration", NullValueHandling = NullValueHandling.Ignore)] public AutoArchiveDuration AutoArchiveDuration { get; internal set; } [JsonProperty("archive_timestamp", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset? ArchiveTimestamp { get; internal set; } [JsonProperty("locked", NullValueHandling = NullValueHandling.Ignore)] public bool? IsLocked { get; internal set; } public DateTimeOffset? CreationTimestamp { get { if (string.IsNullOrWhiteSpace(CreateTimestampRaw) || !DateTimeOffset.TryParse(CreateTimestampRaw, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result)) { return null; } return result; } } [JsonProperty("create_timestamp", NullValueHandling = NullValueHandling.Ignore)] internal string CreateTimestampRaw { get; set; } internal DiscordThreadChannelMetadata() { } } internal sealed class DefaultReaction { [JsonProperty("emoji_id")] public ulong? EmojiId { get; internal set; } [JsonProperty("emoji_name")] public string EmojiName { get; internal set; } } internal sealed class DiscordForumChannel : DiscordChannel { [JsonProperty("available_tags")] private List _availableTags; [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public override ChannelType Type => ChannelType.GuildForum; [JsonProperty("topic")] public new string Topic { get; internal set; } [JsonProperty("default_thread_rate_limit_per_user")] public int? DefaultPerUserRateLimit { get; internal set; } public IReadOnlyList AvailableTags => _availableTags; [JsonProperty("default_reaction", NullValueHandling = NullValueHandling.Ignore)] public DefaultReaction? DefaultReaction { get; internal set; } [JsonProperty("default_sort_order", NullValueHandling = NullValueHandling.Ignore)] public DefaultSortOrder? DefaultSortOrder { get; internal set; } [JsonProperty("default_forum_layout", NullValueHandling = NullValueHandling.Ignore)] public DefaultForumLayout? DefaultLayout { get; internal set; } public Task CreateForumPostAsync(ForumPostBuilder builder) { return base.Discord.ApiClient.CreateForumPostAsync(base.Id, builder.Name, builder.AutoArchiveDuration, builder.SlowMode, builder.Message, builder.AppliedTags.Select((DiscordForumTag t) => t.Id)); } internal DiscordForumChannel() { } } internal sealed class DiscordForumPostStarter { public DiscordThreadChannel Channel { get; internal set; } public DiscordMessage Message { get; internal set; } internal DiscordForumPostStarter() { } internal DiscordForumPostStarter(DiscordThreadChannel chn, DiscordMessage msg) { Channel = chn; Message = msg; } } internal sealed class DiscordForumTag : SnowflakeObject { [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("moderated")] public bool Moderated { get; internal set; } [JsonProperty("emoji_id")] public ulong? EmojiId { get; internal set; } [JsonProperty("emoji_name")] public string EmojiName { get; internal set; } } internal class DiscordForumTagBuilder { [JsonProperty("name")] private string _name; [JsonProperty("moderated")] private bool _moderated; [JsonProperty("emoji_id")] private ulong? _emojiId; [JsonProperty("emoji_name")] private string _emojiName; public static DiscordForumTagBuilder FromTag(DiscordForumTag tag) { return new DiscordForumTagBuilder { _name = tag.Name, _moderated = tag.Moderated, _emojiId = tag.EmojiId, _emojiName = tag.EmojiName }; } public DiscordForumTagBuilder WithName(string name) { _name = name; return this; } public DiscordForumTagBuilder IsModerated(bool moderated = true) { _moderated = moderated; return this; } public DiscordForumTagBuilder WithEmojiId(ulong? emojiId) { _emojiId = emojiId; _emojiName = null; return this; } public DiscordForumTagBuilder WithEmoji(DiscordEmoji emoji) { _emojiId = emoji.Id; _emojiName = emoji.Name; return this; } public DiscordForumTagBuilder WithEmojiName(string emojiName) { _emojiId = null; _emojiName = emojiName; return this; } } internal class ForumPostBuilder { public string Name { get; set; } public int? SlowMode { get; set; } public DiscordMessageBuilder Message { get; set; } public IReadOnlyList AppliedTags { get; } public AutoArchiveDuration? AutoArchiveDuration { get; set; } public ForumPostBuilder() { AppliedTags = new List(); } public ForumPostBuilder WithName(string name) { Name = name; return this; } public ForumPostBuilder WithSlowMode(int slowMode) { SlowMode = slowMode; return this; } public ForumPostBuilder WithSlowMode(TimeSpan slowMode) { SlowMode = (int)slowMode.TotalSeconds; return this; } public ForumPostBuilder WithMessage(DiscordMessageBuilder message) { Message = message; return this; } public ForumPostBuilder WithAutoArchiveDuration(AutoArchiveDuration autoArchiveDuration) { AutoArchiveDuration = autoArchiveDuration; return this; } public ForumPostBuilder AddTag(DiscordForumTag tag) { ((List)AppliedTags).Add(tag); return this; } public ForumPostBuilder AddTags(IEnumerable tags) { ((List)AppliedTags).AddRange(tags); return this; } public ForumPostBuilder RemoveTag(DiscordForumTag tag) { ((List)AppliedTags).Remove(tag); return this; } } internal class ThreadQueryResult { [JsonProperty("has_more", NullValueHandling = NullValueHandling.Ignore)] public bool HasMore { get; internal set; } [JsonProperty("threads", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Threads { get; internal set; } [JsonProperty("members", NullValueHandling = NullValueHandling.Ignore)] internal IReadOnlyList Members { get; set; } } internal struct DiscordColor { private static readonly char[] _hexAlphabet = new char[16] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; public static DiscordColor None { get; } = new DiscordColor(0); public static DiscordColor Black { get; } = new DiscordColor(65793); public static DiscordColor White { get; } = new DiscordColor(16777215); public static DiscordColor Gray { get; } = new DiscordColor(8421504); public static DiscordColor DarkGray { get; } = new DiscordColor(11119017); public static DiscordColor LightGray { get; } = new DiscordColor(13882323); public static DiscordColor VeryDarkGray { get; } = new DiscordColor(6710886); public static DiscordColor Blurple { get; } = new DiscordColor(7506394); public static DiscordColor Grayple { get; } = new DiscordColor(10070709); public static DiscordColor DarkButNotBlack { get; } = new DiscordColor(2895667); public static DiscordColor NotQuiteBlack { get; } = new DiscordColor(2303786); public static DiscordColor Red { get; } = new DiscordColor(16711680); public static DiscordColor DarkRed { get; } = new DiscordColor(8323072); public static DiscordColor Green { get; } = new DiscordColor(65280); public static DiscordColor DarkGreen { get; } = new DiscordColor(32512); public static DiscordColor Blue { get; } = new DiscordColor(255); public static DiscordColor DarkBlue { get; } = new DiscordColor(127); public static DiscordColor Yellow { get; } = new DiscordColor(16776960); public static DiscordColor Cyan { get; } = new DiscordColor(65535); public static DiscordColor Magenta { get; } = new DiscordColor(16711935); public static DiscordColor Teal { get; } = new DiscordColor(32896); public static DiscordColor Aquamarine { get; } = new DiscordColor(65471); public static DiscordColor Gold { get; } = new DiscordColor(16766720); public static DiscordColor Goldenrod { get; } = new DiscordColor(14329120); public static DiscordColor Azure { get; } = new DiscordColor(32767); public static DiscordColor Rose { get; } = new DiscordColor(16711807); public static DiscordColor SpringGreen { get; } = new DiscordColor(65407); public static DiscordColor Chartreuse { get; } = new DiscordColor(8388352); public static DiscordColor Orange { get; } = new DiscordColor(16753920); public static DiscordColor Purple { get; } = new DiscordColor(8388736); public static DiscordColor Violet { get; } = new DiscordColor(15631086); public static DiscordColor Brown { get; } = new DiscordColor(10824234); public static DiscordColor HotPink { get; } = new DiscordColor(16738740); public static DiscordColor Lilac { get; } = new DiscordColor(13148872); public static DiscordColor CornflowerBlue { get; } = new DiscordColor(6591981); public static DiscordColor MidnightBlue { get; } = new DiscordColor(1644912); public static DiscordColor Wheat { get; } = new DiscordColor(16113331); public static DiscordColor IndianRed { get; } = new DiscordColor(13458524); public static DiscordColor Turquoise { get; } = new DiscordColor(3200456); public static DiscordColor SapGreen { get; } = new DiscordColor(5274922); public static DiscordColor PhthaloBlue { get; } = new DiscordColor(3977); public static DiscordColor PhthaloGreen { get; } = new DiscordColor(1193252); public static DiscordColor Sienna { get; } = new DiscordColor(8924439); public int Value { get; } public byte R => (byte)((uint)(Value >> 16) & 0xFFu); public byte G => (byte)((uint)(Value >> 8) & 0xFFu); public byte B => (byte)((uint)Value & 0xFFu); public DiscordColor(int color) { Value = color; } public DiscordColor(byte r, byte g, byte b) { Value = (r << 16) | (g << 8) | b; } public DiscordColor(float r, float g, float b) { if (r < 0f || r > 1f || g < 0f || g > 1f || b < 0f || b > 1f) { throw new ArgumentOutOfRangeException("Each component must be between 0.0 and 1.0 inclusive."); } byte b2 = (byte)(r * 255f); byte b3 = (byte)(g * 255f); byte b4 = (byte)(b * 255f); Value = (b2 << 16) | (b3 << 8) | b4; } public DiscordColor(string color) { if (string.IsNullOrWhiteSpace(color)) { throw new ArgumentNullException("color", "Null or empty values are not allowed!"); } if (color.Length != 6 && color.Length != 7) { throw new ArgumentException("color", "Color must be 6 or 7 characters in length."); } color = color.ToUpper(); if (color.Length == 7 && color[0] != '#') { throw new ArgumentException("color", "7-character colors must begin with #."); } if (color.Length == 7) { color = color.Substring(1); } if (color.Any((char xc) => !_hexAlphabet.Contains(xc))) { throw new ArgumentException("color", "Colors must consist of hexadecimal characters only."); } Value = int.Parse(color, NumberStyles.HexNumber, CultureInfo.InvariantCulture); } public override string ToString() { return $"#{Value:X6}"; } public static implicit operator DiscordColor(int value) { return new DiscordColor(value); } } internal abstract class DiscordAuditLogEntry : SnowflakeObject { public AuditLogActionType ActionType { get; internal set; } public DiscordUser UserResponsible { get; internal set; } public string Reason { get; internal set; } public AuditLogActionCategory ActionCategory { get; internal set; } } internal sealed class PropertyChange { public T Before { get; internal set; } public T After { get; internal set; } } internal sealed class DiscordAuditLogGuildEntry : DiscordAuditLogEntry { public DiscordGuild Target { get; internal set; } public PropertyChange NameChange { get; internal set; } public PropertyChange OwnerChange { get; internal set; } public PropertyChange IconChange { get; internal set; } public PropertyChange VerificationLevelChange { get; internal set; } public PropertyChange AfkChannelChange { get; internal set; } public PropertyChange EmbedChannelChange { get; internal set; } public PropertyChange NotificationSettingsChange { get; internal set; } public PropertyChange SystemChannelChange { get; internal set; } public PropertyChange ExplicitContentFilterChange { get; internal set; } public PropertyChange MfaLevelChange { get; internal set; } public PropertyChange SplashChange { get; internal set; } public PropertyChange RegionChange { get; internal set; } internal DiscordAuditLogGuildEntry() { } } internal sealed class DiscordAuditLogChannelEntry : DiscordAuditLogEntry { public DiscordChannel Target { get; internal set; } public PropertyChange NameChange { get; internal set; } public PropertyChange TypeChange { get; internal set; } public PropertyChange NsfwChange { get; internal set; } public PropertyChange BitrateChange { get; internal set; } public PropertyChange> OverwriteChange { get; internal set; } public PropertyChange TopicChange { get; internal set; } public PropertyChange PerUserRateLimitChange { get; internal set; } internal DiscordAuditLogChannelEntry() { } } internal sealed class DiscordAuditLogOverwriteEntry : DiscordAuditLogEntry { public DiscordOverwrite Target { get; internal set; } public DiscordChannel Channel { get; internal set; } public PropertyChange AllowChange { get; internal set; } public PropertyChange DenyChange { get; internal set; } public PropertyChange TypeChange { get; internal set; } public PropertyChange TargetIdChange { get; internal set; } internal DiscordAuditLogOverwriteEntry() { } } internal sealed class DiscordAuditLogKickEntry : DiscordAuditLogEntry { public DiscordMember Target { get; internal set; } internal DiscordAuditLogKickEntry() { } } internal sealed class DiscordAuditLogPruneEntry : DiscordAuditLogEntry { public int Days { get; internal set; } public int Toll { get; internal set; } internal DiscordAuditLogPruneEntry() { } } internal sealed class DiscordAuditLogBanEntry : DiscordAuditLogEntry { public DiscordMember Target { get; internal set; } internal DiscordAuditLogBanEntry() { } } internal sealed class DiscordAuditLogMemberUpdateEntry : DiscordAuditLogEntry { public DiscordMember Target { get; internal set; } public PropertyChange NicknameChange { get; internal set; } public IReadOnlyList RemovedRoles { get; internal set; } public IReadOnlyList AddedRoles { get; internal set; } public PropertyChange MuteChange { get; internal set; } public PropertyChange DeafenChange { get; internal set; } public PropertyChange TimeoutChange { get; internal set; } internal DiscordAuditLogMemberUpdateEntry() { } } internal sealed class DiscordAuditLogRoleUpdateEntry : DiscordAuditLogEntry { public DiscordRole Target { get; internal set; } public PropertyChange NameChange { get; internal set; } public PropertyChange ColorChange { get; internal set; } public PropertyChange PermissionChange { get; internal set; } public PropertyChange PositionChange { get; internal set; } public PropertyChange MentionableChange { get; internal set; } public PropertyChange HoistChange { get; internal set; } internal DiscordAuditLogRoleUpdateEntry() { } } internal sealed class DiscordAuditLogInviteEntry : DiscordAuditLogEntry { public DiscordInvite Target { get; internal set; } public PropertyChange MaxAgeChange { get; internal set; } public PropertyChange CodeChange { get; internal set; } public PropertyChange TemporaryChange { get; internal set; } public PropertyChange InviterChange { get; internal set; } public PropertyChange ChannelChange { get; internal set; } public PropertyChange UsesChange { get; internal set; } public PropertyChange MaxUsesChange { get; internal set; } internal DiscordAuditLogInviteEntry() { } } internal sealed class DiscordAuditLogWebhookEntry : DiscordAuditLogEntry { public DiscordWebhook Target { get; internal set; } public PropertyChange NameChange { get; internal set; } public PropertyChange ChannelChange { get; internal set; } public PropertyChange TypeChange { get; internal set; } public PropertyChange AvatarHashChange { get; internal set; } public PropertyChange ApplicationIdChange { get; internal set; } internal DiscordAuditLogWebhookEntry() { } } internal sealed class DiscordAuditLogEmojiEntry : DiscordAuditLogEntry { public DiscordEmoji Target { get; internal set; } public PropertyChange NameChange { get; internal set; } internal DiscordAuditLogEmojiEntry() { } } internal sealed class DiscordAuditLogStickerEntry : DiscordAuditLogEntry { public DiscordMessageSticker Target { get; internal set; } public PropertyChange NameChange { get; internal set; } public PropertyChange DescriptionChange { get; internal set; } public PropertyChange TagsChange { get; internal set; } public PropertyChange AssetChange { get; internal set; } public PropertyChange GuildIdChange { get; internal set; } public PropertyChange AvailabilityChange { get; internal set; } public PropertyChange IdChange { get; internal set; } public PropertyChange TypeChange { get; internal set; } public PropertyChange FormatChange { get; internal set; } internal DiscordAuditLogStickerEntry() { } } internal sealed class DiscordAuditLogMessageEntry : DiscordAuditLogEntry { public DiscordMessage Target { get; internal set; } public DiscordChannel Channel { get; internal set; } public int? MessageCount { get; internal set; } internal DiscordAuditLogMessageEntry() { } } internal sealed class DiscordAuditLogMessagePinEntry : DiscordAuditLogEntry { public DiscordUser Target { get; internal set; } public DiscordChannel Channel { get; internal set; } public DiscordMessage Message { get; internal set; } internal DiscordAuditLogMessagePinEntry() { } } internal sealed class DiscordAuditLogBotAddEntry : DiscordAuditLogEntry { public DiscordUser TargetBot { get; internal set; } } internal sealed class DiscordAuditLogMemberMoveEntry : DiscordAuditLogEntry { public DiscordChannel Channel { get; internal set; } public int UserCount { get; internal set; } } internal sealed class DiscordAuditLogMemberDisconnectEntry : DiscordAuditLogEntry { public int UserCount { get; internal set; } } internal sealed class DiscordAuditLogIntegrationEntry : DiscordAuditLogEntry { public PropertyChange EnableEmoticons { get; internal set; } public PropertyChange ExpireGracePeriod { get; internal set; } public PropertyChange ExpireBehavior { get; internal set; } } internal sealed class DiscordAuditLogGuildScheduledEventEntry : DiscordAuditLogEntry { public PropertyChange Name { get; internal set; } public DiscordScheduledGuildEvent Target { get; internal set; } public PropertyChange Channel { get; internal set; } public PropertyChange Description { get; internal set; } public PropertyChange Type { get; internal set; } public PropertyChange ImageHash { get; internal set; } public PropertyChange Location { get; internal set; } public PropertyChange PrivacyLevel { get; internal set; } public PropertyChange Status { get; internal set; } } internal sealed class DiscordAuditLogThreadEventEntry : DiscordAuditLogEntry { public DiscordThreadChannel Target { get; internal set; } public PropertyChange Name { get; internal set; } public PropertyChange Type { get; internal set; } public PropertyChange Archived { get; internal set; } public PropertyChange AutoArchiveDuration { get; internal set; } public PropertyChange Invitable { get; internal set; } public PropertyChange Locked { get; internal set; } public PropertyChange PerUserRateLimit { get; internal set; } internal DiscordAuditLogThreadEventEntry() { } } internal enum AuditLogActionCategory { Create, Update, Delete, Other } internal enum AuditLogActionType { GuildUpdate = 1, ChannelCreate = 10, ChannelUpdate = 11, ChannelDelete = 12, OverwriteCreate = 13, OverwriteUpdate = 14, OverwriteDelete = 15, Kick = 20, Prune = 21, Ban = 22, Unban = 23, MemberUpdate = 24, MemberRoleUpdate = 25, MemberMove = 26, MemberDisconnect = 27, BotAdd = 28, RoleCreate = 30, RoleUpdate = 31, RoleDelete = 32, InviteCreate = 40, InviteUpdate = 41, InviteDelete = 42, WebhookCreate = 50, WebhookUpdate = 51, WebhookDelete = 52, EmojiCreate = 60, EmojiUpdate = 61, EmojiDelete = 62, MessageDelete = 72, MessageBulkDelete = 73, MessagePin = 74, MessageUnpin = 75, IntegrationCreate = 80, IntegrationUpdate = 81, IntegrationDelete = 82, StickerCreate = 90, StickerUpdate = 91, StickerDelete = 92, GuildScheduledEventCreate = 100, GuildScheduledEventUpdate = 101, GuildScheduledEventDelete = 102, ThreadCreate = 110, ThreadUpdate = 111, ThreadDelete = 112 } internal class DiscordConnection { [JsonProperty("id")] public string Id { get; internal set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("type")] public string Type { get; set; } [JsonProperty("revoked")] public bool IsRevoked { get; internal set; } [JsonProperty("integrations", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Integrations { get; internal set; } [JsonProperty("verified", NullValueHandling = NullValueHandling.Ignore)] public bool? Verified { get; set; } [JsonProperty("show_activity", NullValueHandling = NullValueHandling.Ignore)] public bool? ShowActivity { get; set; } [JsonProperty("friend_sync", NullValueHandling = NullValueHandling.Ignore)] public bool? FriendSync { get; set; } [JsonProperty("visibility", NullValueHandling = NullValueHandling.Ignore)] public long? Visibility { get; set; } [Newtonsoft.Json.JsonIgnore] internal BaseDiscordClient Discord { get; set; } internal DiscordConnection() { } } internal sealed class DiscordTeam : SnowflakeObject, IEquatable { public string Name { get; internal set; } public string IconHash { get; internal set; } public string Icon { get { if (string.IsNullOrWhiteSpace(IconHash)) { return null; } return "https://cdn.discordapp.com/team-icons/" + base.Id.ToString(CultureInfo.InvariantCulture) + "/" + IconHash + ".png?size=1024"; } } public DiscordUser Owner { get; internal set; } public IReadOnlyList Members { get; internal set; } internal DiscordTeam(TransportTeam tt) { base.Id = tt.Id; Name = tt.Name; IconHash = tt.IconHash; } public override bool Equals(object obj) { if (obj is DiscordTeam discordTeam) { return this == discordTeam; } return false; } public bool Equals(DiscordTeam other) { return this == other; } public override int GetHashCode() { return base.Id.GetHashCode(); } public override string ToString() { return $"Team: {Name} ({base.Id})"; } public static bool operator ==(DiscordTeam left, DiscordTeam right) { return left?.Id == right?.Id; } public static bool operator !=(DiscordTeam left, DiscordTeam right) { return left?.Id != right?.Id; } } internal sealed class DiscordTeamMember : IEquatable { public DiscordTeamMembershipStatus MembershipStatus { get; internal set; } [Obsolete] public IReadOnlyCollection Permissions { get; internal set; } = (IReadOnlyCollection)(object)Array.Empty(); public string Role { get; internal set; } public DiscordTeam Team { get; internal set; } public DiscordUser User { get; internal set; } internal DiscordTeamMember(TransportTeamMember ttm) { MembershipStatus = (DiscordTeamMembershipStatus)ttm.MembershipState; Role = ttm.Role; } public override bool Equals(object obj) { if (obj is DiscordTeamMember discordTeamMember) { return this == discordTeamMember; } return false; } public bool Equals(DiscordTeamMember other) { return this == other; } public override int GetHashCode() { return (13 * 7 + User.GetHashCode()) * 7 + Team.GetHashCode(); } public override string ToString() { return $"Team member: {User.Username}#{User.Discriminator} ({User.Id}), part of team {Team.Name} ({Team.Id})"; } public static bool operator ==(DiscordTeamMember left, DiscordTeamMember right) { if (left?.Team?.Id == right?.Team?.Id) { return left?.User?.Id == right?.User?.Id; } return false; } public static bool operator !=(DiscordTeamMember left, DiscordTeamMember right) { if (left?.Team?.Id == right?.Team?.Id) { return left?.User?.Id != right?.User?.Id; } return true; } } internal enum DiscordTeamMembershipStatus { Invited = 1, Accepted } internal class DiscordEmoji : SnowflakeObject, IEquatable { [JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)] internal List _roles; private readonly Lazy> _rolesLazy; [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [Newtonsoft.Json.JsonIgnore] public IReadOnlyList Roles => _rolesLazy.Value; [JsonProperty("require_colons")] public bool RequiresColons { get; internal set; } [JsonProperty("managed")] public bool IsManaged { get; internal set; } [JsonProperty("animated")] public bool IsAnimated { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string Url { get { if (base.Id == 0L) { throw new InvalidOperationException("Cannot get URL of unicode emojis."); } if (!IsAnimated) { return "https://cdn.discordapp.com/emojis/" + base.Id.ToString(CultureInfo.InvariantCulture) + ".png"; } return "https://cdn.discordapp.com/emojis/" + base.Id.ToString(CultureInfo.InvariantCulture) + ".gif"; } } [JsonProperty("available", NullValueHandling = NullValueHandling.Ignore)] public bool IsAvailable { get; internal set; } private static IReadOnlyDictionary UnicodeEmojis { get; } private static IReadOnlyDictionary DiscordNameLookup { get; } internal DiscordEmoji() { _rolesLazy = new Lazy>(() => new ReadOnlyCollection(_roles)); } public string GetDiscordName() { DiscordNameLookup.TryGetValue(Name, out var value); return value ?? (":" + Name + ":"); } public override string ToString() { if (base.Id != 0L) { if (!IsAnimated) { return "<:" + Name + ":" + base.Id.ToString(CultureInfo.InvariantCulture) + ">"; } return ""; } return Name; } public override bool Equals(object obj) { return Equals(obj as DiscordEmoji); } public bool Equals(DiscordEmoji e) { if ((object)e == null) { return false; } if ((object)this != e) { if (base.Id == e.Id) { if (base.Id == 0L) { return Name == e.Name; } return true; } return false; } return true; } public override int GetHashCode() { return (13 * 7 + base.Id.GetHashCode()) * 7 + Name.GetHashCode(); } internal string ToReactionString() { if (base.Id == 0L) { return Name; } return Name + ":" + base.Id.ToString(CultureInfo.InvariantCulture); } public static bool operator ==(DiscordEmoji e1, DiscordEmoji e2) { if (((object)e1 != null) ^ ((object)e2 == null)) { if ((object)e1 != null || (object)e2 != null) { if (e1.Id == e2.Id) { if (e1.Id == 0L) { return e1.Name == e2.Name; } return true; } return false; } return true; } return false; } public static bool operator !=(DiscordEmoji e1, DiscordEmoji e2) { return !(e1 == e2); } public static implicit operator string(DiscordEmoji e1) { return e1.ToString(); } public static bool IsValidUnicode(string unicodeEntity) { return DiscordNameLookup.ContainsKey(unicodeEntity); } public static DiscordEmoji FromUnicode(BaseDiscordClient client, string unicodeEntity) { if (IsValidUnicode(unicodeEntity)) { return new DiscordEmoji { Name = unicodeEntity, Discord = client }; } throw new ArgumentException("Specified unicode entity is not a valid unicode emoji.", "unicodeEntity"); } public static DiscordEmoji FromUnicode(string unicodeEntity) { return FromUnicode(null, unicodeEntity); } public static bool TryFromUnicode(BaseDiscordClient client, string unicodeEntity, out DiscordEmoji emoji) { emoji = null; if (!DiscordNameLookup.TryGetValue(unicodeEntity, out var value)) { return false; } if (!UnicodeEmojis.TryGetValue(value, out unicodeEntity)) { return false; } emoji = new DiscordEmoji { Name = unicodeEntity, Discord = client }; return true; } public static bool TryFromUnicode(string unicodeEntity, out DiscordEmoji emoji) { return TryFromUnicode(null, unicodeEntity, out emoji); } public static DiscordEmoji FromGuildEmote(BaseDiscordClient client, ulong id) { if (client == null) { throw new ArgumentNullException("client", "Client cannot be null."); } foreach (DiscordGuild value2 in client.Guilds.Values) { if (value2.Emojis.TryGetValue(id, out var value)) { return value; } } throw new KeyNotFoundException("Given emote was not found."); } public static bool TryFromGuildEmote(BaseDiscordClient client, ulong id, out DiscordEmoji emoji) { if (client == null) { throw new ArgumentNullException("client", "Client cannot be null."); } foreach (DiscordGuild value in client.Guilds.Values) { if (value.Emojis.TryGetValue(id, out emoji)) { return true; } } emoji = null; return false; } public static DiscordEmoji FromName(BaseDiscordClient client, string name, bool includeGuilds = true) { if (client == null) { throw new ArgumentNullException("client", "Client cannot be null."); } if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException("name", "Name cannot be empty or null."); } if (name.Length < 2 || name[0] != ':' || name[name.Length - 1] != ':') { throw new ArgumentException("Invalid emoji name specified. Ensure the emoji name starts and ends with ':'", "name"); } if (UnicodeEmojis.TryGetValue(name, out var value)) { return new DiscordEmoji { Discord = client, Name = value }; } if (includeGuilds) { name = name.Substring(1, name.Length - 2); foreach (DiscordGuild value2 in client.Guilds.Values) { DiscordEmoji discordEmoji = value2.Emojis.Values.FirstOrDefault((DiscordEmoji emoji) => emoji.Name == name); if (discordEmoji != null) { return discordEmoji; } } } throw new ArgumentException("Invalid emoji name specified.", "name"); } public static bool TryFromName(BaseDiscordClient client, string name, out DiscordEmoji emoji) { return TryFromName(client, name, includeGuilds: true, out emoji); } public static bool TryFromName(BaseDiscordClient client, string name, bool includeGuilds, out DiscordEmoji emoji) { if (client == null) { throw new ArgumentNullException("client", "Client cannot be null."); } if (string.IsNullOrWhiteSpace(name) || name.Length < 2 || name[0] != ':' || name[name.Length - 1] != ':') { emoji = null; return false; } if (UnicodeEmojis.TryGetValue(name, out var value)) { emoji = new DiscordEmoji { Discord = client, Name = value }; return true; } if (includeGuilds) { name = name.Substring(1, name.Length - 2); foreach (DiscordGuild value2 in client.Guilds.Values) { emoji = value2.Emojis.Values.FirstOrDefault((DiscordEmoji emoji) => emoji.Name == name); if (emoji != null) { return true; } } } emoji = null; return false; } static DiscordEmoji() { UnicodeEmojis = new Dictionary { [":100:"] = "\ud83d\udcaf", [":1234:"] = "\ud83d\udd22", [":8ball:"] = "\ud83c\udfb1", [":a:"] = "\ud83c\udd70\ufe0f", [":ab:"] = "\ud83c\udd8e", [":abacus:"] = "\ud83e\uddee", [":abc:"] = "\ud83d\udd24", [":abcd:"] = "\ud83d\udd21", [":accept:"] = "\ud83c\ude51", [":accordion:"] = "\ud83e\ude97", [":adhesive_bandage:"] = "\ud83e\ude79", [":adult:"] = "\ud83e\uddd1", [":adult_tone1:"] = "\ud83e\uddd1\ud83c\udffb", [":adult_light_skin_tone:"] = "\ud83e\uddd1\ud83c\udffb", [":adult::skin-tone-1:"] = "\ud83e\uddd1\ud83c\udffb", [":adult_tone2:"] = "\ud83e\uddd1\ud83c\udffc", [":adult_medium_light_skin_tone:"] = "\ud83e\uddd1\ud83c\udffc", [":adult::skin-tone-2:"] = "\ud83e\uddd1\ud83c\udffc", [":adult_tone3:"] = "\ud83e\uddd1\ud83c\udffd", [":adult_medium_skin_tone:"] = "\ud83e\uddd1\ud83c\udffd", [":adult::skin-tone-3:"] = "\ud83e\uddd1\ud83c\udffd", [":adult_tone4:"] = "\ud83e\uddd1\ud83c\udffe", [":adult_medium_dark_skin_tone:"] = "\ud83e\uddd1\ud83c\udffe", [":adult::skin-tone-4:"] = "\ud83e\uddd1\ud83c\udffe", [":adult_tone5:"] = "\ud83e\uddd1\ud83c\udfff", [":adult_dark_skin_tone:"] = "\ud83e\uddd1\ud83c\udfff", [":adult::skin-tone-5:"] = "\ud83e\uddd1\ud83c\udfff", [":aerial_tramway:"] = "\ud83d\udea1", [":airplane:"] = "✈\ufe0f", [":airplane_arriving:"] = "\ud83d\udeec", [":airplane_departure:"] = "\ud83d\udeeb", [":airplane_small:"] = "\ud83d\udee9\ufe0f", [":small_airplane:"] = "\ud83d\udee9\ufe0f", [":alarm_clock:"] = "⏰", [":alembic:"] = "⚗\ufe0f", [":alien:"] = "\ud83d\udc7d", [":ambulance:"] = "\ud83d\ude91", [":amphora:"] = "\ud83c\udffa", [":anatomical_heart:"] = "\ud83e\udec0", [":anchor:"] = "⚓", [":angel:"] = "\ud83d\udc7c", [":angel_tone1:"] = "\ud83d\udc7c\ud83c\udffb", [":angel::skin-tone-1:"] = "\ud83d\udc7c\ud83c\udffb", [":angel_tone2:"] = "\ud83d\udc7c\ud83c\udffc", [":angel::skin-tone-2:"] = "\ud83d\udc7c\ud83c\udffc", [":angel_tone3:"] = "\ud83d\udc7c\ud83c\udffd", [":angel::skin-tone-3:"] = "\ud83d\udc7c\ud83c\udffd", [":angel_tone4:"] = "\ud83d\udc7c\ud83c\udffe", [":angel::skin-tone-4:"] = "\ud83d\udc7c\ud83c\udffe", [":angel_tone5:"] = "\ud83d\udc7c\ud83c\udfff", [":angel::skin-tone-5:"] = "\ud83d\udc7c\ud83c\udfff", [":anger:"] = "\ud83d\udca2", [":anger_right:"] = "\ud83d\uddef\ufe0f", [":right_anger_bubble:"] = "\ud83d\uddef\ufe0f", [":angry:"] = "\ud83d\ude20", [">:("] = "\ud83d\ude20", [">:-("] = "\ud83d\ude20", [">=("] = "\ud83d\ude20", [">=-("] = "\ud83d\ude20", [":anguished:"] = "\ud83d\ude27", [":ant:"] = "\ud83d\udc1c", [":apple:"] = "\ud83c\udf4e", [":aquarius:"] = "♒", [":aries:"] = "♈", [":arrow_backward:"] = "◀\ufe0f", [":arrow_double_down:"] = "⏬", [":arrow_double_up:"] = "⏫", [":arrow_down:"] = "⬇\ufe0f", [":arrow_down_small:"] = "\ud83d\udd3d", [":arrow_forward:"] = "▶\ufe0f", [":arrow_heading_down:"] = "⤵\ufe0f", [":arrow_heading_up:"] = "⤴\ufe0f", [":arrow_left:"] = "⬅\ufe0f", [":arrow_lower_left:"] = "↙\ufe0f", [":arrow_lower_right:"] = "↘\ufe0f", [":arrow_right:"] = "➡\ufe0f", [":arrow_right_hook:"] = "↪\ufe0f", [":arrow_up:"] = "⬆\ufe0f", [":arrow_up_down:"] = "↕\ufe0f", [":arrow_up_small:"] = "\ud83d\udd3c", [":arrow_upper_left:"] = "↖\ufe0f", [":arrow_upper_right:"] = "↗\ufe0f", [":arrows_clockwise:"] = "\ud83d\udd03", [":arrows_counterclockwise:"] = "\ud83d\udd04", [":art:"] = "\ud83c\udfa8", [":articulated_lorry:"] = "\ud83d\ude9b", [":artist:"] = "\ud83e\uddd1\u200d\ud83c\udfa8", [":artist_tone1:"] = "\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udfa8", [":artist_light_skin_tone:"] = "\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udfa8", [":artist::skin-tone-1:"] = "\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udfa8", [":artist_tone2:"] = "\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udfa8", [":artist_medium_light_skin_tone:"] = "\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udfa8", [":artist::skin-tone-2:"] = "\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udfa8", [":artist_tone3:"] = "\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udfa8", [":artist_medium_skin_tone:"] = "\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udfa8", [":artist::skin-tone-3:"] = "\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udfa8", [":artist_tone4:"] = "\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udfa8", [":artist_medium_dark_skin_tone:"] = "\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udfa8", [":artist::skin-tone-4:"] = "\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udfa8", [":artist_tone5:"] = "\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udfa8", [":artist_dark_skin_tone:"] = "\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udfa8", [":artist::skin-tone-5:"] = "\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udfa8", [":asterisk:"] = "*\ufe0f\u20e3", [":keycap_asterisk:"] = "*\ufe0f\u20e3", [":astonished:"] = "\ud83d\ude32", [":astronaut:"] = "\ud83e\uddd1\u200d\ud83d\ude80", [":astronaut_tone1:"] = "\ud83e\uddd1\ud83c\udffb\u200d\ud83d\ude80", [":astronaut_light_skin_tone:"] = "\ud83e\uddd1\ud83c\udffb\u200d\ud83d\ude80", [":astronaut::skin-tone-1:"] = "\ud83e\uddd1\ud83c\udffb\u200d\ud83d\ude80", [":astronaut_tone2:"] = "\ud83e\uddd1\ud83c\udffc\u200d\ud83d\ude80", [":astronaut_medium_light_skin_tone:"] = "\ud83e\uddd1\ud83c\udffc\u200d\ud83d\ude80", [":astronaut::skin-tone-2:"] = "\ud83e\uddd1\ud83c\udffc\u200d\ud83d\ude80", [":astronaut_tone3:"] = "\ud83e\uddd1\ud83c\udffd\u200d\ud83d\ude80", [":astronaut_medium_skin_tone:"] = "\ud83e\uddd1\ud83c\udffd\u200d\ud83d\ude80", [":astronaut::skin-tone-3:"] = "\ud83e\uddd1\ud83c\udffd\u200d\ud83d\ude80", [":astronaut_tone4:"] = "\ud83e\uddd1\ud83c\udffe\u200d\ud83d\ude80", [":astronaut_medium_dark_skin_tone:"] = "\ud83e\uddd1\ud83c\udffe\u200d\ud83d\ude80", [":astronaut::skin-tone-4:"] = "\ud83e\uddd1\ud83c\udffe\u200d\ud83d\ude80", [":astronaut_tone5:"] = "\ud83e\uddd1\ud83c\udfff\u200d\ud83d\ude80", [":astronaut_dark_skin_tone:"] = "\ud83e\uddd1\ud83c\udfff\u200d\ud83d\ude80", [":astronaut::skin-tone-5:"] = "\ud83e\uddd1\ud83c\udfff\u200d\ud83d\ude80", [":athletic_shoe:"] = "\ud83d\udc5f", [":atm:"] = "\ud83c\udfe7", [":atom:"] = "⚛\ufe0f", [":atom_symbol:"] = "⚛\ufe0f", [":auto_rickshaw:"] = "\ud83d\udefa", [":avocado:"] = "\ud83e\udd51", [":axe:"] = "\ud83e\ude93", [":b:"] = "\ud83c\udd71\ufe0f", [":baby:"] = "\ud83d\udc76", [":baby_bottle:"] = "\ud83c\udf7c", [":baby_chick:"] = "\ud83d\udc24", [":baby_symbol:"] = "\ud83d\udebc", [":baby_tone1:"] = "\ud83d\udc76\ud83c\udffb", [":baby::skin-tone-1:"] = "\ud83d\udc76\ud83c\udffb", [":baby_tone2:"] = "\ud83d\udc76\ud83c\udffc", [":baby::skin-tone-2:"] = "\ud83d\udc76\ud83c\udffc", [":baby_tone3:"] = "\ud83d\udc76\ud83c\udffd", [":baby::skin-tone-3:"] = "\ud83d\udc76\ud83c\udffd", [":baby_tone4:"] = "\ud83d\udc76\ud83c\udffe", [":baby::skin-tone-4:"] = "\ud83d\udc76\ud83c\udffe", [":baby_tone5:"] = "\ud83d\udc76\ud83c\udfff", [":baby::skin-tone-5:"] = "\ud83d\udc76\ud83c\udfff", [":back:"] = "\ud83d\udd19", [":bacon:"] = "\ud83e\udd53", [":badger:"] = "\ud83e\udda1", [":badminton:"] = "\ud83c\udff8", [":bagel:"] = "\ud83e\udd6f", [":baggage_claim:"] = "\ud83d\udec4", [":ballet_shoes:"] = "\ud83e\ude70", [":balloon:"] = "\ud83c\udf88", [":ballot_box:"] = "\ud83d\uddf3\ufe0f", [":ballot_box_with_ballot:"] = "\ud83d\uddf3\ufe0f", [":ballot_box_with_check:"] = "☑\ufe0f", [":bamboo:"] = "\ud83c\udf8d", [":banana:"] = "\ud83c\udf4c", [":bangbang:"] = "‼\ufe0f", [":banjo:"] = "\ud83e\ude95", [":bank:"] = "\ud83c\udfe6", [":bar_chart:"] = "\ud83d\udcca", [":barber:"] = "\ud83d\udc88", [":baseball:"] = "⚾", [":basket:"] = "\ud83e\uddfa", [":basketball:"] = "\ud83c\udfc0", [":bat:"] = "\ud83e\udd87", [":bath:"] = "\ud83d\udec0", [":bath_tone1:"] = "\ud83d\udec0\ud83c\udffb", [":bath::skin-tone-1:"] = "\ud83d\udec0\ud83c\udffb", [":bath_tone2:"] = "\ud83d\udec0\ud83c\udffc", [":bath::skin-tone-2:"] = "\ud83d\udec0\ud83c\udffc", [":bath_tone3:"] = "\ud83d\udec0\ud83c\udffd", [":bath::skin-tone-3:"] = "\ud83d\udec0\ud83c\udffd", [":bath_tone4:"] = "\ud83d\udec0\ud83c\udffe", [":bath::skin-tone-4:"] = "\ud83d\udec0\ud83c\udffe", [":bath_tone5:"] = "\ud83d\udec0\ud83c\udfff", [":bath::skin-tone-5:"] = "\ud83d\udec0\ud83c\udfff", [":bathtub:"] = "\ud83d\udec1", [":battery:"] = "\ud83d\udd0b", [":beach:"] = "\ud83c\udfd6\ufe0f", [":beach_with_umbrella:"] = "\ud83c\udfd6\ufe0f", [":beach_umbrella:"] = "⛱\ufe0f", [":umbrella_on_ground:"] = "⛱\ufe0f", [":beans:"] = "\ud83e\uded8", [":bear:"] = "\ud83d\udc3b", [":bearded_person:"] = "\ud83e\uddd4", [":bearded_person_tone1:"] = "\ud83e\uddd4\ud83c\udffb", [":bearded_person_light_skin_tone:"] = "\ud83e\uddd4\ud83c\udffb", [":bearded_person::skin-tone-1:"] = "\ud83e\uddd4\ud83c\udffb", [":bearded_person_tone2:"] = "\ud83e\uddd4\ud83c\udffc", [":bearded_person_medium_light_skin_tone:"] = "\ud83e\uddd4\ud83c\udffc", [":bearded_person::skin-tone-2:"] = "\ud83e\uddd4\ud83c\udffc", [":bearded_person_tone3:"] = "\ud83e\uddd4\ud83c\udffd", [":bearded_person_medium_skin_tone:"] = "\ud83e\uddd4\ud83c\udffd", [":bearded_person::skin-tone-3:"] = "\ud83e\uddd4\ud83c\udffd", [":bearded_person_tone4:"] = "\ud83e\uddd4\ud83c\udffe", [":bearded_person_medium_dark_skin_tone:"] = "\ud83e\uddd4\ud83c\udffe", [":bearded_person::skin-tone-4:"] = "\ud83e\uddd4\ud83c\udffe", [":bearded_person_tone5:"] = "\ud83e\uddd4\ud83c\udfff", [":bearded_person_dark_skin_tone:"] = "\ud83e\uddd4\ud83c\udfff", [":bearded_person::skin-tone-5:"] = "\ud83e\uddd4\ud83c\udfff", [":beaver:"] = "\ud83e\uddab", [":bed:"] = "\ud83d\udecf\ufe0f", [":bee:"] = "\ud83d\udc1d", [":beer:"] = "\ud83c\udf7a", [":beers:"] = "\ud83c\udf7b", [":beetle:"] = "\ud83e\udeb2", [":beginner:"] = "\ud83d\udd30", [":bell:"] = "\ud83d\udd14", [":bell_pepper:"] = "\ud83e\uded1", [":bellhop:"] = "\ud83d\udece\ufe0f", [":bellhop_bell:"] = "\ud83d\udece\ufe0f", [":bento:"] = "\ud83c\udf71", [":beverage_box:"] = "\ud83e\uddc3", [":bike:"] = "\ud83d\udeb2", [":bikini:"] = "\ud83d\udc59", [":billed_cap:"] = "\ud83e\udde2", [":biohazard:"] = "☣\ufe0f", [":biohazard_sign:"] = "☣\ufe0f", [":bird:"] = "\ud83d\udc26", [":birthday:"] = "\ud83c\udf82", [":bison:"] = "\ud83e\uddac", [":biting_lip:"] = "\ud83e\udee6", [":black_cat:"] = "\ud83d\udc08\u200d⬛", [":black_circle:"] = "⚫", [":black_heart:"] = "\ud83d\udda4", [":black_joker:"] = "\ud83c\udccf", [":black_large_square:"] = "⬛", [":black_medium_small_square:"] = "◾", [":black_medium_square:"] = "◼\ufe0f", [":black_nib:"] = "✒\ufe0f", [":black_small_square:"] = "▪\ufe0f", [":black_square_button:"] = "\ud83d\udd32", [":blond_haired_man:"] = "\ud83d\udc71\u200d♂\ufe0f", [":blond_haired_man_tone1:"] = "\ud83d\udc71\ud83c\udffb\u200d♂\ufe0f", [":blond_haired_man_light_skin_tone:"] = "\ud83d\udc71\ud83c\udffb\u200d♂\ufe0f", [":blond_haired_man::skin-tone-1:"] = "\ud83d\udc71\ud83c\udffb\u200d♂\ufe0f", [":blond_haired_man_tone2:"] = "\ud83d\udc71\ud83c\udffc\u200d♂\ufe0f", [":blond_haired_man_medium_light_skin_tone:"] = "\ud83d\udc71\ud83c\udffc\u200d♂\ufe0f", [":blond_haired_man::skin-tone-2:"] = "\ud83d\udc71\ud83c\udffc\u200d♂\ufe0f", [":blond_haired_man_tone3:"] = "\ud83d\udc71\ud83c\udffd\u200d♂\ufe0f", [":blond_haired_man_medium_skin_tone:"] = "\ud83d\udc71\ud83c\udffd\u200d♂\ufe0f", [":blond_haired_man::skin-tone-3:"] = "\ud83d\udc71\ud83c\udffd\u200d♂\ufe0f", [":blond_haired_man_tone4:"] = "\ud83d\udc71\ud83c\udffe\u200d♂\ufe0f", [":blond_haired_man_medium_dark_skin_tone:"] = "\ud83d\udc71\ud83c\udffe\u200d♂\ufe0f", [":blond_haired_man::skin-tone-4:"] = "\ud83d\udc71\ud83c\udffe\u200d♂\ufe0f", [":blond_haired_man_tone5:"] = "\ud83d\udc71\ud83c\udfff\u200d♂\ufe0f", [":blond_haired_man_dark_skin_tone:"] = "\ud83d\udc71\ud83c\udfff\u200d♂\ufe0f", [":blond_haired_man::skin-tone-5:"] = "\ud83d\udc71\ud83c\udfff\u200d♂\ufe0f", [":blond_haired_person:"] = "\ud83d\udc71", [":person_with_blond_hair:"] = "\ud83d\udc71", [":blond_haired_person_tone1:"] = "\ud83d\udc71\ud83c\udffb", [":person_with_blond_hair_tone1:"] = "\ud83d\udc71\ud83c\udffb", [":blond_haired_person::skin-tone-1:"] = "\ud83d\udc71\ud83c\udffb", [":person_with_blond_hair::skin-tone-1:"] = "\ud83d\udc71\ud83c\udffb", [":blond_haired_person_tone2:"] = "\ud83d\udc71\ud83c\udffc", [":person_with_blond_hair_tone2:"] = "\ud83d\udc71\ud83c\udffc", [":blond_haired_person::skin-tone-2:"] = "\ud83d\udc71\ud83c\udffc", [":person_with_blond_hair::skin-tone-2:"] = "\ud83d\udc71\ud83c\udffc", [":blond_haired_person_tone3:"] = "\ud83d\udc71\ud83c\udffd", [":person_with_blond_hair_tone3:"] = "\ud83d\udc71\ud83c\udffd", [":blond_haired_person::skin-tone-3:"] = "\ud83d\udc71\ud83c\udffd", [":person_with_blond_hair::skin-tone-3:"] = "\ud83d\udc71\ud83c\udffd", [":blond_haired_person_tone4:"] = "\ud83d\udc71\ud83c\udffe", [":person_with_blond_hair_tone4:"] = "\ud83d\udc71\ud83c\udffe", [":blond_haired_person::skin-tone-4:"] = "\ud83d\udc71\ud83c\udffe", [":person_with_blond_hair::skin-tone-4:"] = "\ud83d\udc71\ud83c\udffe", [":blond_haired_person_tone5:"] = "\ud83d\udc71\ud83c\udfff", [":person_with_blond_hair_tone5:"] = "\ud83d\udc71\ud83c\udfff", [":blond_haired_person::skin-tone-5:"] = "\ud83d\udc71\ud83c\udfff", [":person_with_blond_hair::skin-tone-5:"] = "\ud83d\udc71\ud83c\udfff", [":blond_haired_woman:"] = "\ud83d\udc71\u200d♀\ufe0f", [":blond_haired_woman_tone1:"] = "\ud83d\udc71\ud83c\udffb\u200d♀\ufe0f", [":blond_haired_woman_light_skin_tone:"] = "\ud83d\udc71\ud83c\udffb\u200d♀\ufe0f", [":blond_haired_woman::skin-tone-1:"] = "\ud83d\udc71\ud83c\udffb\u200d♀\ufe0f", [":blond_haired_woman_tone2:"] = "\ud83d\udc71\ud83c\udffc\u200d♀\ufe0f", [":blond_haired_woman_medium_light_skin_tone:"] = "\ud83d\udc71\ud83c\udffc\u200d♀\ufe0f", [":blond_haired_woman::skin-tone-2:"] = "\ud83d\udc71\ud83c\udffc\u200d♀\ufe0f", [":blond_haired_woman_tone3:"] = "\ud83d\udc71\ud83c\udffd\u200d♀\ufe0f", [":blond_haired_woman_medium_skin_tone:"] = "\ud83d\udc71\ud83c\udffd\u200d♀\ufe0f", [":blond_haired_woman::skin-tone-3:"] = "\ud83d\udc71\ud83c\udffd\u200d♀\ufe0f", [":blond_haired_woman_tone4:"] = "\ud83d\udc71\ud83c\udffe\u200d♀\ufe0f", [":blond_haired_woman_medium_dark_skin_tone:"] = "\ud83d\udc71\ud83c\udffe\u200d♀\ufe0f", [":blond_haired_woman::skin-tone-4:"] = "\ud83d\udc71\ud83c\udffe\u200d♀\ufe0f", [":blond_haired_woman_tone5:"] = "\ud83d\udc71\ud83c\udfff\u200d♀\ufe0f", [":blond_haired_woman_dark_skin_tone:"] = "\ud83d\udc71\ud83c\udfff\u200d♀\ufe0f", [":blond_haired_woman::skin-tone-5:"] = "\ud83d\udc71\ud83c\udfff\u200d♀\ufe0f", [":blossom:"] = "\ud83c\udf3c", [":blowfish:"] = "\ud83d\udc21", [":blue_book:"] = "\ud83d\udcd8", [":blue_car:"] = "\ud83d\ude99", [":blue_circle:"] = "\ud83d\udd35", [":blue_heart:"] = "\ud83d\udc99", [":blue_square:"] = "\ud83d\udfe6", [":blueberries:"] = "\ud83e\uded0", [":blush:"] = "\ud83d\ude0a", [":\")"] = "\ud83d\ude0a", [":-\")"] = "\ud83d\ude0a", ["=\")"] = "\ud83d\ude0a", ["=-\")"] = "\ud83d\ude0a", [":boar:"] = "\ud83d\udc17", [":bomb:"] = "\ud83d\udca3", [":bone:"] = "\ud83e\uddb4", [":book:"] = "\ud83d\udcd6", [":bookmark:"] = "\ud83d\udd16", [":bookmark_tabs:"] = "\ud83d\udcd1", [":books:"] = "\ud83d\udcda", [":boom:"] = "\ud83d\udca5", [":boomerang:"] = "\ud83e\ude83", [":boot:"] = "\ud83d\udc62", [":bouquet:"] = "\ud83d\udc90", [":bow_and_arrow:"] = "\ud83c\udff9", [":archery:"] = "\ud83c\udff9", [":bowl_with_spoon:"] = "\ud83e\udd63", [":bowling:"] = "\ud83c\udfb3", [":boxing_glove:"] = "\ud83e\udd4a", [":boxing_gloves:"] = "\ud83e\udd4a", [":boy:"] = "\ud83d\udc66", [":boy_tone1:"] = "\ud83d\udc66\ud83c\udffb", [":boy::skin-tone-1:"] = "\ud83d\udc66\ud83c\udffb", [":boy_tone2:"] = "\ud83d\udc66\ud83c\udffc", [":boy::skin-tone-2:"] = "\ud83d\udc66\ud83c\udffc", [":boy_tone3:"] = "\ud83d\udc66\ud83c\udffd", [":boy::skin-tone-3:"] = "\ud83d\udc66\ud83c\udffd", [":boy_tone4:"] = "\ud83d\udc66\ud83c\udffe", [":boy::skin-tone-4:"] = "\ud83d\udc66\ud83c\udffe", [":boy_tone5:"] = "\ud83d\udc66\ud83c\udfff", [":boy::skin-tone-5:"] = "\ud83d\udc66\ud83c\udfff", [":brain:"] = "\ud83e\udde0", [":bread:"] = "\ud83c\udf5e", [":breast_feeding:"] = "\ud83e\udd31", [":breast_feeding_tone1:"] = "\ud83e\udd31\ud83c\udffb", [":breast_feeding_light_skin_tone:"] = "\ud83e\udd31\ud83c\udffb", [":breast_feeding::skin-tone-1:"] = "\ud83e\udd31\ud83c\udffb", [":breast_feeding_tone2:"] = "\ud83e\udd31\ud83c\udffc", [":breast_feeding_medium_light_skin_tone:"] = "\ud83e\udd31\ud83c\udffc", [":breast_feeding::skin-tone-2:"] = "\ud83e\udd31\ud83c\udffc", [":breast_feeding_tone3:"] = "\ud83e\udd31\ud83c\udffd", [":breast_feeding_medium_skin_tone:"] = "\ud83e\udd31\ud83c\udffd", [":breast_feeding::skin-tone-3:"] = "\ud83e\udd31\ud83c\udffd", [":breast_feeding_tone4:"] = "\ud83e\udd31\ud83c\udffe", [":breast_feeding_medium_dark_skin_tone:"] = "\ud83e\udd31\ud83c\udffe", [":breast_feeding::skin-tone-4:"] = "\ud83e\udd31\ud83c\udffe", [":breast_feeding_tone5:"] = "\ud83e\udd31\ud83c\udfff", [":breast_feeding_dark_skin_tone:"] = "\ud83e\udd31\ud83c\udfff", [":breast_feeding::skin-tone-5:"] = "\ud83e\udd31\ud83c\udfff", [":bricks:"] = "\ud83e\uddf1", [":bridge_at_night:"] = "\ud83c\udf09", [":briefcase:"] = "\ud83d\udcbc", [":briefs:"] = "\ud83e\ude72", [":broccoli:"] = "\ud83e\udd66", [":broken_heart:"] = "\ud83d\udc94", [" { ["\ud83d\udcaf"] = ":100:", ["\ud83d\udd22"] = ":1234:", ["\ud83c\udfb1"] = ":8ball:", ["\ud83c\udd70\ufe0f"] = ":a:", ["\ud83c\udd70"] = ":a:", ["\ud83c\udd8e"] = ":ab:", ["\ud83e\uddee"] = ":abacus:", ["\ud83d\udd24"] = ":abc:", ["\ud83d\udd21"] = ":abcd:", ["\ud83c\ude51"] = ":accept:", ["\ud83e\ude97"] = ":accordion:", ["\ud83e\ude79"] = ":adhesive_bandage:", ["\ud83e\uddd1\ud83c\udffb"] = ":adult_tone1:", ["\ud83e\uddd1\ud83c\udffc"] = ":adult_tone2:", ["\ud83e\uddd1\ud83c\udffd"] = ":adult_tone3:", ["\ud83e\uddd1\ud83c\udffe"] = ":adult_tone4:", ["\ud83e\uddd1\ud83c\udfff"] = ":adult_tone5:", ["\ud83e\uddd1"] = ":adult:", ["\ud83d\udea1"] = ":aerial_tramway:", ["\ud83d\udeec"] = ":airplane_arriving:", ["\ud83d\udeeb"] = ":airplane_departure:", ["\ud83d\udee9\ufe0f"] = ":airplane_small:", ["\ud83d\udee9"] = ":airplane_small:", ["✈\ufe0f"] = ":airplane:", ["✈"] = ":airplane:", ["⏰"] = ":alarm_clock:", ["⚗\ufe0f"] = ":alembic:", ["⚗"] = ":alembic:", ["\ud83d\udc7d"] = ":alien:", ["\ud83d\ude91"] = ":ambulance:", ["\ud83c\udffa"] = ":amphora:", ["\ud83e\udec0"] = ":anatomical_heart:", ["⚓"] = ":anchor:", ["\ud83d\udc7c\ud83c\udffb"] = ":angel_tone1:", ["\ud83d\udc7c\ud83c\udffc"] = ":angel_tone2:", ["\ud83d\udc7c\ud83c\udffd"] = ":angel_tone3:", ["\ud83d\udc7c\ud83c\udffe"] = ":angel_tone4:", ["\ud83d\udc7c\ud83c\udfff"] = ":angel_tone5:", ["\ud83d\udc7c"] = ":angel:", ["\ud83d\uddef\ufe0f"] = ":anger_right:", ["\ud83d\uddef"] = ":anger_right:", ["\ud83d\udca2"] = ":anger:", ["\ud83d\ude20"] = ":angry:", ["\ud83d\ude27"] = ":anguished:", ["\ud83d\udc1c"] = ":ant:", ["\ud83c\udf4e"] = ":apple:", ["♒"] = ":aquarius:", ["♈"] = ":aries:", ["◀\ufe0f"] = ":arrow_backward:", ["◀"] = ":arrow_backward:", ["⏬"] = ":arrow_double_down:", ["⏫"] = ":arrow_double_up:", ["\ud83d\udd3d"] = ":arrow_down_small:", ["⬇\ufe0f"] = ":arrow_down:", ["⬇"] = ":arrow_down:", ["▶\ufe0f"] = ":arrow_forward:", ["▶"] = ":arrow_forward:", ["⤵\ufe0f"] = ":arrow_heading_down:", ["⤵"] = ":arrow_heading_down:", ["⤴\ufe0f"] = ":arrow_heading_up:", ["⤴"] = ":arrow_heading_up:", ["⬅\ufe0f"] = ":arrow_left:", ["⬅"] = ":arrow_left:", ["↙\ufe0f"] = ":arrow_lower_left:", ["↙"] = ":arrow_lower_left:", ["↘\ufe0f"] = ":arrow_lower_right:", ["↘"] = ":arrow_lower_right:", ["↪\ufe0f"] = ":arrow_right_hook:", ["↪"] = ":arrow_right_hook:", ["➡\ufe0f"] = ":arrow_right:", ["➡"] = ":arrow_right:", ["↕\ufe0f"] = ":arrow_up_down:", ["↕"] = ":arrow_up_down:", ["\ud83d\udd3c"] = ":arrow_up_small:", ["⬆\ufe0f"] = ":arrow_up:", ["⬆"] = ":arrow_up:", ["↖\ufe0f"] = ":arrow_upper_left:", ["↖"] = ":arrow_upper_left:", ["↗\ufe0f"] = ":arrow_upper_right:", ["↗"] = ":arrow_upper_right:", ["\ud83d\udd03"] = ":arrows_clockwise:", ["\ud83d\udd04"] = ":arrows_counterclockwise:", ["\ud83c\udfa8"] = ":art:", ["\ud83d\ude9b"] = ":articulated_lorry:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udfa8"] = ":artist_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udfa8"] = ":artist_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udfa8"] = ":artist_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udfa8"] = ":artist_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udfa8"] = ":artist_tone5:", ["\ud83e\uddd1\u200d\ud83c\udfa8"] = ":artist:", ["*\ufe0f\u20e3"] = ":asterisk:", ["*\u20e3"] = ":asterisk:", ["\ud83d\ude32"] = ":astonished:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83d\ude80"] = ":astronaut_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83d\ude80"] = ":astronaut_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83d\ude80"] = ":astronaut_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83d\ude80"] = ":astronaut_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83d\ude80"] = ":astronaut_tone5:", ["\ud83e\uddd1\u200d\ud83d\ude80"] = ":astronaut:", ["\ud83d\udc5f"] = ":athletic_shoe:", ["\ud83c\udfe7"] = ":atm:", ["⚛\ufe0f"] = ":atom:", ["⚛"] = ":atom:", ["\ud83d\udefa"] = ":auto_rickshaw:", ["\ud83e\udd51"] = ":avocado:", ["\ud83e\ude93"] = ":axe:", ["\ud83c\udd71\ufe0f"] = ":b:", ["\ud83c\udd71"] = ":b:", ["\ud83c\udf7c"] = ":baby_bottle:", ["\ud83d\udc24"] = ":baby_chick:", ["\ud83d\udebc"] = ":baby_symbol:", ["\ud83d\udc76\ud83c\udffb"] = ":baby_tone1:", ["\ud83d\udc76\ud83c\udffc"] = ":baby_tone2:", ["\ud83d\udc76\ud83c\udffd"] = ":baby_tone3:", ["\ud83d\udc76\ud83c\udffe"] = ":baby_tone4:", ["\ud83d\udc76\ud83c\udfff"] = ":baby_tone5:", ["\ud83d\udc76"] = ":baby:", ["\ud83d\udd19"] = ":back:", ["\ud83e\udd53"] = ":bacon:", ["\ud83e\udda1"] = ":badger:", ["\ud83c\udff8"] = ":badminton:", ["\ud83e\udd6f"] = ":bagel:", ["\ud83d\udec4"] = ":baggage_claim:", ["\ud83e\ude70"] = ":ballet_shoes:", ["\ud83c\udf88"] = ":balloon:", ["☑\ufe0f"] = ":ballot_box_with_check:", ["☑"] = ":ballot_box_with_check:", ["\ud83d\uddf3\ufe0f"] = ":ballot_box:", ["\ud83d\uddf3"] = ":ballot_box:", ["\ud83c\udf8d"] = ":bamboo:", ["\ud83c\udf4c"] = ":banana:", ["‼\ufe0f"] = ":bangbang:", ["‼"] = ":bangbang:", ["\ud83e\ude95"] = ":banjo:", ["\ud83c\udfe6"] = ":bank:", ["\ud83d\udcca"] = ":bar_chart:", ["\ud83d\udc88"] = ":barber:", ["⚾"] = ":baseball:", ["\ud83e\uddfa"] = ":basket:", ["\ud83c\udfc0"] = ":basketball:", ["\ud83e\udd87"] = ":bat:", ["\ud83d\udec0\ud83c\udffb"] = ":bath_tone1:", ["\ud83d\udec0\ud83c\udffc"] = ":bath_tone2:", ["\ud83d\udec0\ud83c\udffd"] = ":bath_tone3:", ["\ud83d\udec0\ud83c\udffe"] = ":bath_tone4:", ["\ud83d\udec0\ud83c\udfff"] = ":bath_tone5:", ["\ud83d\udec0"] = ":bath:", ["\ud83d\udec1"] = ":bathtub:", ["\ud83d\udd0b"] = ":battery:", ["⛱\ufe0f"] = ":beach_umbrella:", ["⛱"] = ":beach_umbrella:", ["\ud83c\udfd6\ufe0f"] = ":beach:", ["\ud83c\udfd6"] = ":beach:", ["\ud83e\uded8"] = ":beans:", ["\ud83d\udc3b"] = ":bear:", ["\ud83e\uddd4\ud83c\udffb"] = ":bearded_person_tone1:", ["\ud83e\uddd4\ud83c\udffc"] = ":bearded_person_tone2:", ["\ud83e\uddd4\ud83c\udffd"] = ":bearded_person_tone3:", ["\ud83e\uddd4\ud83c\udffe"] = ":bearded_person_tone4:", ["\ud83e\uddd4\ud83c\udfff"] = ":bearded_person_tone5:", ["\ud83e\uddd4"] = ":bearded_person:", ["\ud83e\uddab"] = ":beaver:", ["\ud83d\udecf\ufe0f"] = ":bed:", ["\ud83d\udecf"] = ":bed:", ["\ud83d\udc1d"] = ":bee:", ["\ud83c\udf7a"] = ":beer:", ["\ud83c\udf7b"] = ":beers:", ["\ud83e\udeb2"] = ":beetle:", ["\ud83d\udd30"] = ":beginner:", ["\ud83e\uded1"] = ":bell_pepper:", ["\ud83d\udd14"] = ":bell:", ["\ud83d\udece\ufe0f"] = ":bellhop:", ["\ud83d\udece"] = ":bellhop:", ["\ud83c\udf71"] = ":bento:", ["\ud83e\uddc3"] = ":beverage_box:", ["\ud83d\udeb2"] = ":bike:", ["\ud83d\udc59"] = ":bikini:", ["\ud83e\udde2"] = ":billed_cap:", ["☣\ufe0f"] = ":biohazard:", ["☣"] = ":biohazard:", ["\ud83d\udc26"] = ":bird:", ["\ud83c\udf82"] = ":birthday:", ["\ud83e\uddac"] = ":bison:", ["\ud83e\udee6"] = ":biting_lip:", ["\ud83d\udc08\u200d⬛"] = ":black_cat:", ["⚫"] = ":black_circle:", ["\ud83d\udda4"] = ":black_heart:", ["\ud83c\udccf"] = ":black_joker:", ["⬛"] = ":black_large_square:", ["◾"] = ":black_medium_small_square:", ["◼\ufe0f"] = ":black_medium_square:", ["◼"] = ":black_medium_square:", ["✒\ufe0f"] = ":black_nib:", ["✒"] = ":black_nib:", ["▪\ufe0f"] = ":black_small_square:", ["▪"] = ":black_small_square:", ["\ud83d\udd32"] = ":black_square_button:", ["\ud83d\udc71\ud83c\udffb\u200d♂\ufe0f"] = ":blond_haired_man_tone1:", ["\ud83d\udc71\ud83c\udffc\u200d♂\ufe0f"] = ":blond_haired_man_tone2:", ["\ud83d\udc71\ud83c\udffd\u200d♂\ufe0f"] = ":blond_haired_man_tone3:", ["\ud83d\udc71\ud83c\udffe\u200d♂\ufe0f"] = ":blond_haired_man_tone4:", ["\ud83d\udc71\ud83c\udfff\u200d♂\ufe0f"] = ":blond_haired_man_tone5:", ["\ud83d\udc71\u200d♂\ufe0f"] = ":blond_haired_man:", ["\ud83d\udc71\ud83c\udffb"] = ":blond_haired_person_tone1:", ["\ud83d\udc71\ud83c\udffc"] = ":blond_haired_person_tone2:", ["\ud83d\udc71\ud83c\udffd"] = ":blond_haired_person_tone3:", ["\ud83d\udc71\ud83c\udffe"] = ":blond_haired_person_tone4:", ["\ud83d\udc71\ud83c\udfff"] = ":blond_haired_person_tone5:", ["\ud83d\udc71"] = ":blond_haired_person:", ["\ud83d\udc71\ud83c\udffb\u200d♀\ufe0f"] = ":blond_haired_woman_tone1:", ["\ud83d\udc71\ud83c\udffc\u200d♀\ufe0f"] = ":blond_haired_woman_tone2:", ["\ud83d\udc71\ud83c\udffd\u200d♀\ufe0f"] = ":blond_haired_woman_tone3:", ["\ud83d\udc71\ud83c\udffe\u200d♀\ufe0f"] = ":blond_haired_woman_tone4:", ["\ud83d\udc71\ud83c\udfff\u200d♀\ufe0f"] = ":blond_haired_woman_tone5:", ["\ud83d\udc71\u200d♀\ufe0f"] = ":blond_haired_woman:", ["\ud83c\udf3c"] = ":blossom:", ["\ud83d\udc21"] = ":blowfish:", ["\ud83d\udcd8"] = ":blue_book:", ["\ud83d\ude99"] = ":blue_car:", ["\ud83d\udd35"] = ":blue_circle:", ["\ud83d\udc99"] = ":blue_heart:", ["\ud83d\udfe6"] = ":blue_square:", ["\ud83e\uded0"] = ":blueberries:", ["\ud83d\ude0a"] = ":blush:", ["\ud83d\udc17"] = ":boar:", ["\ud83d\udca3"] = ":bomb:", ["\ud83e\uddb4"] = ":bone:", ["\ud83d\udcd6"] = ":book:", ["\ud83d\udcd1"] = ":bookmark_tabs:", ["\ud83d\udd16"] = ":bookmark:", ["\ud83d\udcda"] = ":books:", ["\ud83d\udca5"] = ":boom:", ["\ud83e\ude83"] = ":boomerang:", ["\ud83d\udc62"] = ":boot:", ["\ud83d\udc90"] = ":bouquet:", ["\ud83c\udff9"] = ":bow_and_arrow:", ["\ud83e\udd63"] = ":bowl_with_spoon:", ["\ud83c\udfb3"] = ":bowling:", ["\ud83e\udd4a"] = ":boxing_glove:", ["\ud83d\udc66\ud83c\udffb"] = ":boy_tone1:", ["\ud83d\udc66\ud83c\udffc"] = ":boy_tone2:", ["\ud83d\udc66\ud83c\udffd"] = ":boy_tone3:", ["\ud83d\udc66\ud83c\udffe"] = ":boy_tone4:", ["\ud83d\udc66\ud83c\udfff"] = ":boy_tone5:", ["\ud83d\udc66"] = ":boy:", ["\ud83e\udde0"] = ":brain:", ["\ud83c\udf5e"] = ":bread:", ["\ud83e\udd31\ud83c\udffb"] = ":breast_feeding_tone1:", ["\ud83e\udd31\ud83c\udffc"] = ":breast_feeding_tone2:", ["\ud83e\udd31\ud83c\udffd"] = ":breast_feeding_tone3:", ["\ud83e\udd31\ud83c\udffe"] = ":breast_feeding_tone4:", ["\ud83e\udd31\ud83c\udfff"] = ":breast_feeding_tone5:", ["\ud83e\udd31"] = ":breast_feeding:", ["\ud83e\uddf1"] = ":bricks:", ["\ud83c\udf09"] = ":bridge_at_night:", ["\ud83d\udcbc"] = ":briefcase:", ["\ud83e\ude72"] = ":briefs:", ["\ud83e\udd66"] = ":broccoli:", ["\ud83d\udc94"] = ":broken_heart:", ["\ud83e\uddf9"] = ":broom:", ["\ud83d\udfe4"] = ":brown_circle:", ["\ud83e\udd0e"] = ":brown_heart:", ["\ud83d\udfeb"] = ":brown_square:", ["\ud83e\uddcb"] = ":bubble_tea:", ["\ud83e\udee7"] = ":bubbles:", ["\ud83e\udea3"] = ":bucket:", ["\ud83d\udc1b"] = ":bug:", ["\ud83d\udca1"] = ":bulb:", ["\ud83d\ude85"] = ":bullettrain_front:", ["\ud83d\ude84"] = ":bullettrain_side:", ["\ud83c\udf2f"] = ":burrito:", ["\ud83d\ude8c"] = ":bus:", ["\ud83d\ude8f"] = ":busstop:", ["\ud83d\udc64"] = ":bust_in_silhouette:", ["\ud83d\udc65"] = ":busts_in_silhouette:", ["\ud83e\uddc8"] = ":butter:", ["\ud83e\udd8b"] = ":butterfly:", ["\ud83c\udf35"] = ":cactus:", ["\ud83c\udf70"] = ":cake:", ["\ud83d\uddd3\ufe0f"] = ":calendar_spiral:", ["\ud83d\uddd3"] = ":calendar_spiral:", ["\ud83d\udcc6"] = ":calendar:", ["\ud83e\udd19\ud83c\udffb"] = ":call_me_tone1:", ["\ud83e\udd19\ud83c\udffc"] = ":call_me_tone2:", ["\ud83e\udd19\ud83c\udffd"] = ":call_me_tone3:", ["\ud83e\udd19\ud83c\udffe"] = ":call_me_tone4:", ["\ud83e\udd19\ud83c\udfff"] = ":call_me_tone5:", ["\ud83e\udd19"] = ":call_me:", ["\ud83d\udcf2"] = ":calling:", ["\ud83d\udc2b"] = ":camel:", ["\ud83d\udcf8"] = ":camera_with_flash:", ["\ud83d\udcf7"] = ":camera:", ["\ud83c\udfd5\ufe0f"] = ":camping:", ["\ud83c\udfd5"] = ":camping:", ["♋"] = ":cancer:", ["\ud83d\udd6f\ufe0f"] = ":candle:", ["\ud83d\udd6f"] = ":candle:", ["\ud83c\udf6c"] = ":candy:", ["\ud83e\udd6b"] = ":canned_food:", ["\ud83d\udef6"] = ":canoe:", ["\ud83d\udd20"] = ":capital_abcd:", ["♑"] = ":capricorn:", ["\ud83d\uddc3\ufe0f"] = ":card_box:", ["\ud83d\uddc3"] = ":card_box:", ["\ud83d\udcc7"] = ":card_index:", ["\ud83c\udfa0"] = ":carousel_horse:", ["\ud83e\ude9a"] = ":carpentry_saw:", ["\ud83e\udd55"] = ":carrot:", ["\ud83d\udc31"] = ":cat:", ["\ud83d\udc08"] = ":cat2:", ["\ud83d\udcbf"] = ":cd:", ["⛓\ufe0f"] = ":chains:", ["⛓"] = ":chains:", ["\ud83e\ude91"] = ":chair:", ["\ud83e\udd42"] = ":champagne_glass:", ["\ud83c\udf7e"] = ":champagne:", ["\ud83d\udcc9"] = ":chart_with_downwards_trend:", ["\ud83d\udcc8"] = ":chart_with_upwards_trend:", ["\ud83d\udcb9"] = ":chart:", ["\ud83c\udfc1"] = ":checkered_flag:", ["\ud83e\uddc0"] = ":cheese:", ["\ud83c\udf52"] = ":cherries:", ["\ud83c\udf38"] = ":cherry_blossom:", ["♟\ufe0f"] = ":chess_pawn:", ["♟"] = ":chess_pawn:", ["\ud83c\udf30"] = ":chestnut:", ["\ud83d\udc14"] = ":chicken:", ["\ud83e\uddd2\ud83c\udffb"] = ":child_tone1:", ["\ud83e\uddd2\ud83c\udffc"] = ":child_tone2:", ["\ud83e\uddd2\ud83c\udffd"] = ":child_tone3:", ["\ud83e\uddd2\ud83c\udffe"] = ":child_tone4:", ["\ud83e\uddd2\ud83c\udfff"] = ":child_tone5:", ["\ud83e\uddd2"] = ":child:", ["\ud83d\udeb8"] = ":children_crossing:", ["\ud83d\udc3f\ufe0f"] = ":chipmunk:", ["\ud83d\udc3f"] = ":chipmunk:", ["\ud83c\udf6b"] = ":chocolate_bar:", ["\ud83e\udd62"] = ":chopsticks:", ["\ud83c\udf84"] = ":christmas_tree:", ["⛪"] = ":church:", ["\ud83c\udfa6"] = ":cinema:", ["\ud83c\udfaa"] = ":circus_tent:", ["\ud83c\udf06"] = ":city_dusk:", ["\ud83c\udf07"] = ":city_sunset:", ["\ud83c\udfd9\ufe0f"] = ":cityscape:", ["\ud83c\udfd9"] = ":cityscape:", ["\ud83c\udd91"] = ":cl:", ["\ud83d\udc4f\ud83c\udffb"] = ":clap_tone1:", ["\ud83d\udc4f\ud83c\udffc"] = ":clap_tone2:", ["\ud83d\udc4f\ud83c\udffd"] = ":clap_tone3:", ["\ud83d\udc4f\ud83c\udffe"] = ":clap_tone4:", ["\ud83d\udc4f\ud83c\udfff"] = ":clap_tone5:", ["\ud83d\udc4f"] = ":clap:", ["\ud83c\udfac"] = ":clapper:", ["\ud83c\udfdb\ufe0f"] = ":classical_building:", ["\ud83c\udfdb"] = ":classical_building:", ["\ud83d\udccb"] = ":clipboard:", ["\ud83d\udd70\ufe0f"] = ":clock:", ["\ud83d\udd70"] = ":clock:", ["\ud83d\udd50"] = ":clock1:", ["\ud83d\udd59"] = ":clock10:", ["\ud83d\udd65"] = ":clock1030:", ["\ud83d\udd5a"] = ":clock11:", ["\ud83d\udd66"] = ":clock1130:", ["\ud83d\udd5b"] = ":clock12:", ["\ud83d\udd67"] = ":clock1230:", ["\ud83d\udd5c"] = ":clock130:", ["\ud83d\udd51"] = ":clock2:", ["\ud83d\udd5d"] = ":clock230:", ["\ud83d\udd52"] = ":clock3:", ["\ud83d\udd5e"] = ":clock330:", ["\ud83d\udd53"] = ":clock4:", ["\ud83d\udd5f"] = ":clock430:", ["\ud83d\udd54"] = ":clock5:", ["\ud83d\udd60"] = ":clock530:", ["\ud83d\udd55"] = ":clock6:", ["\ud83d\udd61"] = ":clock630:", ["\ud83d\udd56"] = ":clock7:", ["\ud83d\udd62"] = ":clock730:", ["\ud83d\udd57"] = ":clock8:", ["\ud83d\udd63"] = ":clock830:", ["\ud83d\udd58"] = ":clock9:", ["\ud83d\udd64"] = ":clock930:", ["\ud83d\udcd5"] = ":closed_book:", ["\ud83d\udd10"] = ":closed_lock_with_key:", ["\ud83c\udf02"] = ":closed_umbrella:", ["\ud83c\udf29\ufe0f"] = ":cloud_lightning:", ["\ud83c\udf29"] = ":cloud_lightning:", ["\ud83c\udf27\ufe0f"] = ":cloud_rain:", ["\ud83c\udf27"] = ":cloud_rain:", ["\ud83c\udf28\ufe0f"] = ":cloud_snow:", ["\ud83c\udf28"] = ":cloud_snow:", ["\ud83c\udf2a\ufe0f"] = ":cloud_tornado:", ["\ud83c\udf2a"] = ":cloud_tornado:", ["☁\ufe0f"] = ":cloud:", ["☁"] = ":cloud:", ["\ud83e\udd21"] = ":clown:", ["♣\ufe0f"] = ":clubs:", ["♣"] = ":clubs:", ["\ud83e\udde5"] = ":coat:", ["\ud83e\udeb3"] = ":cockroach:", ["\ud83c\udf78"] = ":cocktail:", ["\ud83e\udd65"] = ":coconut:", ["☕"] = ":coffee:", ["⚰\ufe0f"] = ":coffin:", ["⚰"] = ":coffin:", ["\ud83e\ude99"] = ":coin:", ["\ud83e\udd76"] = ":cold_face:", ["\ud83d\ude30"] = ":cold_sweat:", ["☄\ufe0f"] = ":comet:", ["☄"] = ":comet:", ["\ud83e\udded"] = ":compass:", ["\ud83d\udddc\ufe0f"] = ":compression:", ["\ud83d\udddc"] = ":compression:", ["\ud83d\udcbb"] = ":computer:", ["\ud83c\udf8a"] = ":confetti_ball:", ["\ud83d\ude16"] = ":confounded:", ["\ud83d\ude15"] = ":confused:", ["㊗\ufe0f"] = ":congratulations:", ["㊗"] = ":congratulations:", ["\ud83c\udfd7\ufe0f"] = ":construction_site:", ["\ud83c\udfd7"] = ":construction_site:", ["\ud83d\udc77\ud83c\udffb"] = ":construction_worker_tone1:", ["\ud83d\udc77\ud83c\udffc"] = ":construction_worker_tone2:", ["\ud83d\udc77\ud83c\udffd"] = ":construction_worker_tone3:", ["\ud83d\udc77\ud83c\udffe"] = ":construction_worker_tone4:", ["\ud83d\udc77\ud83c\udfff"] = ":construction_worker_tone5:", ["\ud83d\udc77"] = ":construction_worker:", ["\ud83d\udea7"] = ":construction:", ["\ud83c\udf9b\ufe0f"] = ":control_knobs:", ["\ud83c\udf9b"] = ":control_knobs:", ["\ud83c\udfea"] = ":convenience_store:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udf73"] = ":cook_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udf73"] = ":cook_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udf73"] = ":cook_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udf73"] = ":cook_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udf73"] = ":cook_tone5:", ["\ud83e\uddd1\u200d\ud83c\udf73"] = ":cook:", ["\ud83c\udf6a"] = ":cookie:", ["\ud83c\udf73"] = ":cooking:", ["\ud83c\udd92"] = ":cool:", ["©\ufe0f"] = ":copyright:", ["©"] = ":copyright:", ["\ud83e\udeb8"] = ":coral:", ["\ud83c\udf3d"] = ":corn:", ["\ud83d\udecb\ufe0f"] = ":couch:", ["\ud83d\udecb"] = ":couch:", ["\ud83d\udc68\u200d❤\ufe0f\u200d\ud83d\udc68"] = ":couple_with_heart_man_man_tone5_tone4:", ["\ud83d\udc91"] = ":couple_with_heart_tone5:", ["\ud83d\udc69\u200d❤\ufe0f\u200d\ud83d\udc68"] = ":couple_with_heart_woman_man_tone5_tone4:", ["\ud83d\udc69\u200d❤\ufe0f\u200d\ud83d\udc69"] = ":couple_ww:", ["\ud83d\udc2e"] = ":cow:", ["\ud83d\udc04"] = ":cow2:", ["\ud83e\udd20"] = ":cowboy:", ["\ud83e\udd80"] = ":crab:", ["\ud83d\udd8d\ufe0f"] = ":crayon:", ["\ud83d\udd8d"] = ":crayon:", ["\ud83d\udcb3"] = ":credit_card:", ["\ud83c\udf19"] = ":crescent_moon:", ["\ud83c\udfcf"] = ":cricket_game:", ["\ud83e\udd97"] = ":cricket:", ["\ud83d\udc0a"] = ":crocodile:", ["\ud83e\udd50"] = ":croissant:", ["✝\ufe0f"] = ":cross:", ["✝"] = ":cross:", ["\ud83c\udf8c"] = ":crossed_flags:", ["⚔\ufe0f"] = ":crossed_swords:", ["⚔"] = ":crossed_swords:", ["\ud83d\udc51"] = ":crown:", ["\ud83d\udef3\ufe0f"] = ":cruise_ship:", ["\ud83d\udef3"] = ":cruise_ship:", ["\ud83e\ude7c"] = ":crutch:", ["\ud83d\ude22"] = ":cry:", ["\ud83d\ude3f"] = ":crying_cat_face:", ["\ud83d\udd2e"] = ":crystal_ball:", ["\ud83e\udd52"] = ":cucumber:", ["\ud83e\udd64"] = ":cup_with_straw:", ["\ud83e\uddc1"] = ":cupcake:", ["\ud83d\udc98"] = ":cupid:", ["\ud83e\udd4c"] = ":curling_stone:", ["➰"] = ":curly_loop:", ["\ud83d\udcb1"] = ":currency_exchange:", ["\ud83c\udf5b"] = ":curry:", ["\ud83c\udf6e"] = ":custard:", ["\ud83d\udec3"] = ":customs:", ["\ud83e\udd69"] = ":cut_of_meat:", ["\ud83c\udf00"] = ":cyclone:", ["\ud83d\udde1\ufe0f"] = ":dagger:", ["\ud83d\udde1"] = ":dagger:", ["\ud83d\udc83\ud83c\udffb"] = ":dancer_tone1:", ["\ud83d\udc83\ud83c\udffc"] = ":dancer_tone2:", ["\ud83d\udc83\ud83c\udffd"] = ":dancer_tone3:", ["\ud83d\udc83\ud83c\udffe"] = ":dancer_tone4:", ["\ud83d\udc83\ud83c\udfff"] = ":dancer_tone5:", ["\ud83d\udc83"] = ":dancer:", ["\ud83c\udf61"] = ":dango:", ["\ud83d\udd76\ufe0f"] = ":dark_sunglasses:", ["\ud83d\udd76"] = ":dark_sunglasses:", ["\ud83c\udfaf"] = ":dart:", ["\ud83d\udca8"] = ":dash:", ["\ud83d\udcc5"] = ":date:", ["\ud83e\uddcf\ud83c\udffb\u200d♂\ufe0f"] = ":deaf_man_tone1:", ["\ud83e\uddcf\ud83c\udffc\u200d♂\ufe0f"] = ":deaf_man_tone2:", ["\ud83e\uddcf\ud83c\udffd\u200d♂\ufe0f"] = ":deaf_man_tone3:", ["\ud83e\uddcf\ud83c\udffe\u200d♂\ufe0f"] = ":deaf_man_tone4:", ["\ud83e\uddcf\ud83c\udfff\u200d♂\ufe0f"] = ":deaf_man_tone5:", ["\ud83e\uddcf\u200d♂\ufe0f"] = ":deaf_man:", ["\ud83e\uddcf\ud83c\udffb"] = ":deaf_person_tone1:", ["\ud83e\uddcf\ud83c\udffc"] = ":deaf_person_tone2:", ["\ud83e\uddcf\ud83c\udffd"] = ":deaf_person_tone3:", ["\ud83e\uddcf\ud83c\udffe"] = ":deaf_person_tone4:", ["\ud83e\uddcf\ud83c\udfff"] = ":deaf_person_tone5:", ["\ud83e\uddcf"] = ":deaf_person:", ["\ud83e\uddcf\ud83c\udffb\u200d♀\ufe0f"] = ":deaf_woman_tone1:", ["\ud83e\uddcf\ud83c\udffc\u200d♀\ufe0f"] = ":deaf_woman_tone2:", ["\ud83e\uddcf\ud83c\udffd\u200d♀\ufe0f"] = ":deaf_woman_tone3:", ["\ud83e\uddcf\ud83c\udffe\u200d♀\ufe0f"] = ":deaf_woman_tone4:", ["\ud83e\uddcf\ud83c\udfff\u200d♀\ufe0f"] = ":deaf_woman_tone5:", ["\ud83e\uddcf\u200d♀\ufe0f"] = ":deaf_woman:", ["\ud83c\udf33"] = ":deciduous_tree:", ["\ud83e\udd8c"] = ":deer:", ["\ud83c\udfec"] = ":department_store:", ["\ud83c\udfdc\ufe0f"] = ":desert:", ["\ud83c\udfdc"] = ":desert:", ["\ud83d\udda5\ufe0f"] = ":desktop:", ["\ud83d\udda5"] = ":desktop:", ["\ud83d\udd75\ud83c\udffb"] = ":detective_tone1:", ["\ud83d\udd75\ud83c\udffc"] = ":detective_tone2:", ["\ud83d\udd75\ud83c\udffd"] = ":detective_tone3:", ["\ud83d\udd75\ud83c\udffe"] = ":detective_tone4:", ["\ud83d\udd75\ud83c\udfff"] = ":detective_tone5:", ["\ud83d\udd75\ufe0f"] = ":detective:", ["\ud83d\udd75"] = ":detective:", ["\ud83d\udca0"] = ":diamond_shape_with_a_dot_inside:", ["♦\ufe0f"] = ":diamonds:", ["♦"] = ":diamonds:", ["\ud83d\ude25"] = ":disappointed_relieved:", ["\ud83d\ude1e"] = ":disappointed:", ["\ud83e\udd78"] = ":disguised_face:", ["\ud83d\uddc2\ufe0f"] = ":dividers:", ["\ud83d\uddc2"] = ":dividers:", ["\ud83e\udd3f"] = ":diving_mask:", ["\ud83e\ude94"] = ":diya_lamp:", ["\ud83d\ude35"] = ":dizzy_face:", ["\ud83d\udcab"] = ":dizzy:", ["\ud83e\uddec"] = ":dna:", ["\ud83d\udeaf"] = ":do_not_litter:", ["\ud83e\udda4"] = ":dodo:", ["\ud83d\udc36"] = ":dog:", ["\ud83d\udc15"] = ":dog2:", ["\ud83d\udcb5"] = ":dollar:", ["\ud83c\udf8e"] = ":dolls:", ["\ud83d\udc2c"] = ":dolphin:", ["\ud83d\udeaa"] = ":door:", ["\ud83e\udee5"] = ":dotted_line_face:", ["\ud83c\udf69"] = ":doughnut:", ["\ud83d\udd4a\ufe0f"] = ":dove:", ["\ud83d\udd4a"] = ":dove:", ["\ud83d\udc32"] = ":dragon_face:", ["\ud83d\udc09"] = ":dragon:", ["\ud83d\udc57"] = ":dress:", ["\ud83d\udc2a"] = ":dromedary_camel:", ["\ud83e\udd24"] = ":drooling_face:", ["\ud83e\ude78"] = ":drop_of_blood:", ["\ud83d\udca7"] = ":droplet:", ["\ud83e\udd41"] = ":drum:", ["\ud83e\udd86"] = ":duck:", ["\ud83e\udd5f"] = ":dumpling:", ["\ud83d\udcc0"] = ":dvd:", ["\ud83d\udce7"] = ":e_mail:", ["\ud83e\udd85"] = ":eagle:", ["\ud83c\udf3e"] = ":ear_of_rice:", ["\ud83d\udc42\ud83c\udffb"] = ":ear_tone1:", ["\ud83d\udc42\ud83c\udffc"] = ":ear_tone2:", ["\ud83d\udc42\ud83c\udffd"] = ":ear_tone3:", ["\ud83d\udc42\ud83c\udffe"] = ":ear_tone4:", ["\ud83d\udc42\ud83c\udfff"] = ":ear_tone5:", ["\ud83e\uddbb\ud83c\udffb"] = ":ear_with_hearing_aid_tone1:", ["\ud83e\uddbb\ud83c\udffc"] = ":ear_with_hearing_aid_tone2:", ["\ud83e\uddbb\ud83c\udffd"] = ":ear_with_hearing_aid_tone3:", ["\ud83e\uddbb\ud83c\udffe"] = ":ear_with_hearing_aid_tone4:", ["\ud83e\uddbb\ud83c\udfff"] = ":ear_with_hearing_aid_tone5:", ["\ud83e\uddbb"] = ":ear_with_hearing_aid:", ["\ud83d\udc42"] = ":ear:", ["\ud83c\udf0d"] = ":earth_africa:", ["\ud83c\udf0e"] = ":earth_americas:", ["\ud83c\udf0f"] = ":earth_asia:", ["\ud83e\udd5a"] = ":egg:", ["\ud83c\udf46"] = ":eggplant:", ["✴\ufe0f"] = ":eight_pointed_black_star:", ["✴"] = ":eight_pointed_black_star:", ["✳\ufe0f"] = ":eight_spoked_asterisk:", ["✳"] = ":eight_spoked_asterisk:", ["8\ufe0f\u20e3"] = ":eight:", ["8\u20e3"] = ":eight:", ["⏏\ufe0f"] = ":eject:", ["⏏"] = ":eject:", ["\ud83d\udd0c"] = ":electric_plug:", ["\ud83d\udc18"] = ":elephant:", ["\ud83d\uded7"] = ":elevator:", ["\ud83e\udddd\ud83c\udffb"] = ":elf_tone1:", ["\ud83e\udddd\ud83c\udffc"] = ":elf_tone2:", ["\ud83e\udddd\ud83c\udffd"] = ":elf_tone3:", ["\ud83e\udddd\ud83c\udffe"] = ":elf_tone4:", ["\ud83e\udddd\ud83c\udfff"] = ":elf_tone5:", ["\ud83e\udddd"] = ":elf:", ["\ud83e\udeb9"] = ":empty_nest:", ["\ud83d\udd1a"] = ":end:", ["\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f"] = ":england:", ["\ud83d\udce9"] = ":envelope_with_arrow:", ["✉\ufe0f"] = ":envelope:", ["✉"] = ":envelope:", ["\ud83d\udcb6"] = ":euro:", ["\ud83c\udff0"] = ":european_castle:", ["\ud83c\udfe4"] = ":european_post_office:", ["\ud83c\udf32"] = ":evergreen_tree:", ["❗"] = ":exclamation:", ["\ud83e\udd2f"] = ":exploding_head:", ["\ud83d\ude11"] = ":expressionless:", ["\ud83d\udc41\u200d\ud83d\udde8"] = ":eye_in_speech_bubble:", ["\ud83d\udc41\ufe0f"] = ":eye:", ["\ud83d\udc41"] = ":eye:", ["\ud83d\udc53"] = ":eyeglasses:", ["\ud83d\udc40"] = ":eyes:", ["\ud83d\ude2e\u200d\ud83d\udca8"] = ":face_exhaling:", ["\ud83e\udd79"] = ":face_holding_back_tears:", ["\ud83d\ude36\u200d\ud83c\udf2b\ufe0f"] = ":face_in_clouds:", ["\ud83e\udd2e"] = ":face_vomiting:", ["\ud83e\udee4"] = ":face_with_diagonal_mouth:", ["\ud83e\udd2d"] = ":face_with_hand_over_mouth:", ["\ud83e\uddd0"] = ":face_with_monocle:", ["\ud83e\udee2"] = ":face_with_open_eyes_and_hand_over_mouth:", ["\ud83e\udee3"] = ":face_with_peeking_eye:", ["\ud83e\udd28"] = ":face_with_raised_eyebrow:", ["\ud83d\ude35\u200d\ud83d\udcab"] = ":face_with_spiral_eyes:", ["\ud83e\udd2c"] = ":face_with_symbols_over_mouth:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udfed"] = ":factory_worker_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udfed"] = ":factory_worker_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udfed"] = ":factory_worker_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udfed"] = ":factory_worker_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udfed"] = ":factory_worker_tone5:", ["\ud83e\uddd1\u200d\ud83c\udfed"] = ":factory_worker:", ["\ud83c\udfed"] = ":factory:", ["\ud83e\uddda\ud83c\udffb"] = ":fairy_tone1:", ["\ud83e\uddda\ud83c\udffc"] = ":fairy_tone2:", ["\ud83e\uddda\ud83c\udffd"] = ":fairy_tone3:", ["\ud83e\uddda\ud83c\udffe"] = ":fairy_tone4:", ["\ud83e\uddda\ud83c\udfff"] = ":fairy_tone5:", ["\ud83e\uddda"] = ":fairy:", ["\ud83e\uddc6"] = ":falafel:", ["\ud83c\udf42"] = ":fallen_leaf:", ["\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66"] = ":family_man_boy_boy:", ["\ud83d\udc68\u200d\ud83d\udc66"] = ":family_man_boy:", ["\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66"] = ":family_man_girl_boy:", ["\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67"] = ":family_man_girl_girl:", ["\ud83d\udc68\u200d\ud83d\udc67"] = ":family_man_girl:", ["\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66"] = ":family_man_woman_boy:", ["\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66"] = ":family_mmb:", ["\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66"] = ":family_mmbb:", ["\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67"] = ":family_mmg:", ["\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66"] = ":family_mmgb:", ["\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67"] = ":family_mmgg:", ["\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66"] = ":family_mwbb:", ["\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67"] = ":family_mwg:", ["\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66"] = ":family_mwgb:", ["\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67"] = ":family_mwgg:", ["\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66"] = ":family_woman_boy_boy:", ["\ud83d\udc69\u200d\ud83d\udc66"] = ":family_woman_boy:", ["\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66"] = ":family_woman_girl_boy:", ["\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67"] = ":family_woman_girl_girl:", ["\ud83d\udc69\u200d\ud83d\udc67"] = ":family_woman_girl:", ["\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66"] = ":family_wwb:", ["\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66"] = ":family_wwbb:", ["\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67"] = ":family_wwg:", ["\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66"] = ":family_wwgb:", ["\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67"] = ":family_wwgg:", ["\ud83d\udc6a"] = ":family:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udf3e"] = ":farmer_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udf3e"] = ":farmer_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udf3e"] = ":farmer_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udf3e"] = ":farmer_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udf3e"] = ":farmer_tone5:", ["\ud83e\uddd1\u200d\ud83c\udf3e"] = ":farmer:", ["⏩"] = ":fast_forward:", ["\ud83d\udce0"] = ":fax:", ["\ud83d\ude28"] = ":fearful:", ["\ud83e\udeb6"] = ":feather:", ["\ud83d\udc3e"] = ":feet:", ["♀\ufe0f"] = ":female_sign:", ["♀"] = ":female_sign:", ["\ud83c\udfa1"] = ":ferris_wheel:", ["⛴\ufe0f"] = ":ferry:", ["⛴"] = ":ferry:", ["\ud83c\udfd1"] = ":field_hockey:", ["\ud83d\uddc4\ufe0f"] = ":file_cabinet:", ["\ud83d\uddc4"] = ":file_cabinet:", ["\ud83d\udcc1"] = ":file_folder:", ["\ud83c\udf9e\ufe0f"] = ":film_frames:", ["\ud83c\udf9e"] = ":film_frames:", ["\ud83e\udd1e\ud83c\udffb"] = ":fingers_crossed_tone1:", ["\ud83e\udd1e\ud83c\udffc"] = ":fingers_crossed_tone2:", ["\ud83e\udd1e\ud83c\udffd"] = ":fingers_crossed_tone3:", ["\ud83e\udd1e\ud83c\udffe"] = ":fingers_crossed_tone4:", ["\ud83e\udd1e\ud83c\udfff"] = ":fingers_crossed_tone5:", ["\ud83e\udd1e"] = ":fingers_crossed:", ["\ud83d\ude92"] = ":fire_engine:", ["\ud83e\uddef"] = ":fire_extinguisher:", ["\ud83d\udd25"] = ":fire:", ["\ud83e\udde8"] = ":firecracker:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83d\ude92"] = ":firefighter_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83d\ude92"] = ":firefighter_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83d\ude92"] = ":firefighter_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83d\ude92"] = ":firefighter_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83d\ude92"] = ":firefighter_tone5:", ["\ud83e\uddd1\u200d\ud83d\ude92"] = ":firefighter:", ["\ud83c\udf86"] = ":fireworks:", ["\ud83e\udd47"] = ":first_place:", ["\ud83c\udf1b"] = ":first_quarter_moon_with_face:", ["\ud83c\udf13"] = ":first_quarter_moon:", ["\ud83c\udf65"] = ":fish_cake:", ["\ud83d\udc1f"] = ":fish:", ["\ud83c\udfa3"] = ":fishing_pole_and_fish:", ["✊\ud83c\udffb"] = ":fist_tone1:", ["✊\ud83c\udffc"] = ":fist_tone2:", ["✊\ud83c\udffd"] = ":fist_tone3:", ["✊\ud83c\udffe"] = ":fist_tone4:", ["✊\ud83c\udfff"] = ":fist_tone5:", ["✊"] = ":fist:", ["5\ufe0f\u20e3"] = ":five:", ["5\u20e3"] = ":five:", ["\ud83c\udde6\ud83c\udde8"] = ":flag_ac:", ["\ud83c\udde6\ud83c\udde9"] = ":flag_ad:", ["\ud83c\udde6\ud83c\uddea"] = ":flag_ae:", ["\ud83c\udde6\ud83c\uddeb"] = ":flag_af:", ["\ud83c\udde6\ud83c\uddec"] = ":flag_ag:", ["\ud83c\udde6\ud83c\uddee"] = ":flag_ai:", ["\ud83c\udde6\ud83c\uddf1"] = ":flag_al:", ["\ud83c\udde6\ud83c\uddf2"] = ":flag_am:", ["\ud83c\udde6\ud83c\uddf4"] = ":flag_ao:", ["\ud83c\udde6\ud83c\uddf6"] = ":flag_aq:", ["\ud83c\udde6\ud83c\uddf7"] = ":flag_ar:", ["\ud83c\udde6\ud83c\uddf8"] = ":flag_as:", ["\ud83c\udde6\ud83c\uddf9"] = ":flag_at:", ["\ud83c\udde6\ud83c\uddfa"] = ":flag_au:", ["\ud83c\udde6\ud83c\uddfc"] = ":flag_aw:", ["\ud83c\udde6\ud83c\uddfd"] = ":flag_ax:", ["\ud83c\udde6\ud83c\uddff"] = ":flag_az:", ["\ud83c\udde7\ud83c\udde6"] = ":flag_ba:", ["\ud83c\udde7\ud83c\udde7"] = ":flag_bb:", ["\ud83c\udde7\ud83c\udde9"] = ":flag_bd:", ["\ud83c\udde7\ud83c\uddea"] = ":flag_be:", ["\ud83c\udde7\ud83c\uddeb"] = ":flag_bf:", ["\ud83c\udde7\ud83c\uddec"] = ":flag_bg:", ["\ud83c\udde7\ud83c\udded"] = ":flag_bh:", ["\ud83c\udde7\ud83c\uddee"] = ":flag_bi:", ["\ud83c\udde7\ud83c\uddef"] = ":flag_bj:", ["\ud83c\udde7\ud83c\uddf1"] = ":flag_bl:", ["\ud83c\udff4"] = ":flag_black:", ["\ud83c\udde7\ud83c\uddf2"] = ":flag_bm:", ["\ud83c\udde7\ud83c\uddf3"] = ":flag_bn:", ["\ud83c\udde7\ud83c\uddf4"] = ":flag_bo:", ["\ud83c\udde7\ud83c\uddf6"] = ":flag_bq:", ["\ud83c\udde7\ud83c\uddf7"] = ":flag_br:", ["\ud83c\udde7\ud83c\uddf8"] = ":flag_bs:", ["\ud83c\udde7\ud83c\uddf9"] = ":flag_bt:", ["\ud83c\udde7\ud83c\uddfb"] = ":flag_bv:", ["\ud83c\udde7\ud83c\uddfc"] = ":flag_bw:", ["\ud83c\udde7\ud83c\uddfe"] = ":flag_by:", ["\ud83c\udde7\ud83c\uddff"] = ":flag_bz:", ["\ud83c\udde8\ud83c\udde6"] = ":flag_ca:", ["\ud83c\udde8\ud83c\udde8"] = ":flag_cc:", ["\ud83c\udde8\ud83c\udde9"] = ":flag_cd:", ["\ud83c\udde8\ud83c\uddeb"] = ":flag_cf:", ["\ud83c\udde8\ud83c\uddec"] = ":flag_cg:", ["\ud83c\udde8\ud83c\udded"] = ":flag_ch:", ["\ud83c\udde8\ud83c\uddee"] = ":flag_ci:", ["\ud83c\udde8\ud83c\uddf0"] = ":flag_ck:", ["\ud83c\udde8\ud83c\uddf1"] = ":flag_cl:", ["\ud83c\udde8\ud83c\uddf2"] = ":flag_cm:", ["\ud83c\udde8\ud83c\uddf3"] = ":flag_cn:", ["\ud83c\udde8\ud83c\uddf4"] = ":flag_co:", ["\ud83c\udde8\ud83c\uddf5"] = ":flag_cp:", ["\ud83c\udde8\ud83c\uddf7"] = ":flag_cr:", ["\ud83c\udde8\ud83c\uddfa"] = ":flag_cu:", ["\ud83c\udde8\ud83c\uddfb"] = ":flag_cv:", ["\ud83c\udde8\ud83c\uddfc"] = ":flag_cw:", ["\ud83c\udde8\ud83c\uddfd"] = ":flag_cx:", ["\ud83c\udde8\ud83c\uddfe"] = ":flag_cy:", ["\ud83c\udde8\ud83c\uddff"] = ":flag_cz:", ["\ud83c\udde9\ud83c\uddea"] = ":flag_de:", ["\ud83c\udde9\ud83c\uddec"] = ":flag_dg:", ["\ud83c\udde9\ud83c\uddef"] = ":flag_dj:", ["\ud83c\udde9\ud83c\uddf0"] = ":flag_dk:", ["\ud83c\udde9\ud83c\uddf2"] = ":flag_dm:", ["\ud83c\udde9\ud83c\uddf4"] = ":flag_do:", ["\ud83c\udde9\ud83c\uddff"] = ":flag_dz:", ["\ud83c\uddea\ud83c\udde6"] = ":flag_ea:", ["\ud83c\uddea\ud83c\udde8"] = ":flag_ec:", ["\ud83c\uddea\ud83c\uddea"] = ":flag_ee:", ["\ud83c\uddea\ud83c\uddec"] = ":flag_eg:", ["\ud83c\uddea\ud83c\udded"] = ":flag_eh:", ["\ud83c\uddea\ud83c\uddf7"] = ":flag_er:", ["\ud83c\uddea\ud83c\uddf8"] = ":flag_es:", ["\ud83c\uddea\ud83c\uddf9"] = ":flag_et:", ["\ud83c\uddea\ud83c\uddfa"] = ":flag_eu:", ["\ud83c\uddeb\ud83c\uddee"] = ":flag_fi:", ["\ud83c\uddeb\ud83c\uddef"] = ":flag_fj:", ["\ud83c\uddeb\ud83c\uddf0"] = ":flag_fk:", ["\ud83c\uddeb\ud83c\uddf2"] = ":flag_fm:", ["\ud83c\uddeb\ud83c\uddf4"] = ":flag_fo:", ["\ud83c\uddeb\ud83c\uddf7"] = ":flag_fr:", ["\ud83c\uddec\ud83c\udde6"] = ":flag_ga:", ["\ud83c\uddec\ud83c\udde7"] = ":flag_gb:", ["\ud83c\uddec\ud83c\udde9"] = ":flag_gd:", ["\ud83c\uddec\ud83c\uddea"] = ":flag_ge:", ["\ud83c\uddec\ud83c\uddeb"] = ":flag_gf:", ["\ud83c\uddec\ud83c\uddec"] = ":flag_gg:", ["\ud83c\uddec\ud83c\udded"] = ":flag_gh:", ["\ud83c\uddec\ud83c\uddee"] = ":flag_gi:", ["\ud83c\uddec\ud83c\uddf1"] = ":flag_gl:", ["\ud83c\uddec\ud83c\uddf2"] = ":flag_gm:", ["\ud83c\uddec\ud83c\uddf3"] = ":flag_gn:", ["\ud83c\uddec\ud83c\uddf5"] = ":flag_gp:", ["\ud83c\uddec\ud83c\uddf6"] = ":flag_gq:", ["\ud83c\uddec\ud83c\uddf7"] = ":flag_gr:", ["\ud83c\uddec\ud83c\uddf8"] = ":flag_gs:", ["\ud83c\uddec\ud83c\uddf9"] = ":flag_gt:", ["\ud83c\uddec\ud83c\uddfa"] = ":flag_gu:", ["\ud83c\uddec\ud83c\uddfc"] = ":flag_gw:", ["\ud83c\uddec\ud83c\uddfe"] = ":flag_gy:", ["\ud83c\udded\ud83c\uddf0"] = ":flag_hk:", ["\ud83c\udded\ud83c\uddf2"] = ":flag_hm:", ["\ud83c\udded\ud83c\uddf3"] = ":flag_hn:", ["\ud83c\udded\ud83c\uddf7"] = ":flag_hr:", ["\ud83c\udded\ud83c\uddf9"] = ":flag_ht:", ["\ud83c\udded\ud83c\uddfa"] = ":flag_hu:", ["\ud83c\uddee\ud83c\udde8"] = ":flag_ic:", ["\ud83c\uddee\ud83c\udde9"] = ":flag_id:", ["\ud83c\uddee\ud83c\uddea"] = ":flag_ie:", ["\ud83c\uddee\ud83c\uddf1"] = ":flag_il:", ["\ud83c\uddee\ud83c\uddf2"] = ":flag_im:", ["\ud83c\uddee\ud83c\uddf3"] = ":flag_in:", ["\ud83c\uddee\ud83c\uddf4"] = ":flag_io:", ["\ud83c\uddee\ud83c\uddf6"] = ":flag_iq:", ["\ud83c\uddee\ud83c\uddf7"] = ":flag_ir:", ["\ud83c\uddee\ud83c\uddf8"] = ":flag_is:", ["\ud83c\uddee\ud83c\uddf9"] = ":flag_it:", ["\ud83c\uddef\ud83c\uddea"] = ":flag_je:", ["\ud83c\uddef\ud83c\uddf2"] = ":flag_jm:", ["\ud83c\uddef\ud83c\uddf4"] = ":flag_jo:", ["\ud83c\uddef\ud83c\uddf5"] = ":flag_jp:", ["\ud83c\uddf0\ud83c\uddea"] = ":flag_ke:", ["\ud83c\uddf0\ud83c\uddec"] = ":flag_kg:", ["\ud83c\uddf0\ud83c\udded"] = ":flag_kh:", ["\ud83c\uddf0\ud83c\uddee"] = ":flag_ki:", ["\ud83c\uddf0\ud83c\uddf2"] = ":flag_km:", ["\ud83c\uddf0\ud83c\uddf3"] = ":flag_kn:", ["\ud83c\uddf0\ud83c\uddf5"] = ":flag_kp:", ["\ud83c\uddf0\ud83c\uddf7"] = ":flag_kr:", ["\ud83c\uddf0\ud83c\uddfc"] = ":flag_kw:", ["\ud83c\uddf0\ud83c\uddfe"] = ":flag_ky:", ["\ud83c\uddf0\ud83c\uddff"] = ":flag_kz:", ["\ud83c\uddf1\ud83c\udde6"] = ":flag_la:", ["\ud83c\uddf1\ud83c\udde7"] = ":flag_lb:", ["\ud83c\uddf1\ud83c\udde8"] = ":flag_lc:", ["\ud83c\uddf1\ud83c\uddee"] = ":flag_li:", ["\ud83c\uddf1\ud83c\uddf0"] = ":flag_lk:", ["\ud83c\uddf1\ud83c\uddf7"] = ":flag_lr:", ["\ud83c\uddf1\ud83c\uddf8"] = ":flag_ls:", ["\ud83c\uddf1\ud83c\uddf9"] = ":flag_lt:", ["\ud83c\uddf1\ud83c\uddfa"] = ":flag_lu:", ["\ud83c\uddf1\ud83c\uddfb"] = ":flag_lv:", ["\ud83c\uddf1\ud83c\uddfe"] = ":flag_ly:", ["\ud83c\uddf2\ud83c\udde6"] = ":flag_ma:", ["\ud83c\uddf2\ud83c\udde8"] = ":flag_mc:", ["\ud83c\uddf2\ud83c\udde9"] = ":flag_md:", ["\ud83c\uddf2\ud83c\uddea"] = ":flag_me:", ["\ud83c\uddf2\ud83c\uddeb"] = ":flag_mf:", ["\ud83c\uddf2\ud83c\uddec"] = ":flag_mg:", ["\ud83c\uddf2\ud83c\udded"] = ":flag_mh:", ["\ud83c\uddf2\ud83c\uddf0"] = ":flag_mk:", ["\ud83c\uddf2\ud83c\uddf1"] = ":flag_ml:", ["\ud83c\uddf2\ud83c\uddf2"] = ":flag_mm:", ["\ud83c\uddf2\ud83c\uddf3"] = ":flag_mn:", ["\ud83c\uddf2\ud83c\uddf4"] = ":flag_mo:", ["\ud83c\uddf2\ud83c\uddf5"] = ":flag_mp:", ["\ud83c\uddf2\ud83c\uddf6"] = ":flag_mq:", ["\ud83c\uddf2\ud83c\uddf7"] = ":flag_mr:", ["\ud83c\uddf2\ud83c\uddf8"] = ":flag_ms:", ["\ud83c\uddf2\ud83c\uddf9"] = ":flag_mt:", ["\ud83c\uddf2\ud83c\uddfa"] = ":flag_mu:", ["\ud83c\uddf2\ud83c\uddfb"] = ":flag_mv:", ["\ud83c\uddf2\ud83c\uddfc"] = ":flag_mw:", ["\ud83c\uddf2\ud83c\uddfd"] = ":flag_mx:", ["\ud83c\uddf2\ud83c\uddfe"] = ":flag_my:", ["\ud83c\uddf2\ud83c\uddff"] = ":flag_mz:", ["\ud83c\uddf3\ud83c\udde6"] = ":flag_na:", ["\ud83c\uddf3\ud83c\udde8"] = ":flag_nc:", ["\ud83c\uddf3\ud83c\uddea"] = ":flag_ne:", ["\ud83c\uddf3\ud83c\uddeb"] = ":flag_nf:", ["\ud83c\uddf3\ud83c\uddec"] = ":flag_ng:", ["\ud83c\uddf3\ud83c\uddee"] = ":flag_ni:", ["\ud83c\uddf3\ud83c\uddf1"] = ":flag_nl:", ["\ud83c\uddf3\ud83c\uddf4"] = ":flag_no:", ["\ud83c\uddf3\ud83c\uddf5"] = ":flag_np:", ["\ud83c\uddf3\ud83c\uddf7"] = ":flag_nr:", ["\ud83c\uddf3\ud83c\uddfa"] = ":flag_nu:", ["\ud83c\uddf3\ud83c\uddff"] = ":flag_nz:", ["\ud83c\uddf4\ud83c\uddf2"] = ":flag_om:", ["\ud83c\uddf5\ud83c\udde6"] = ":flag_pa:", ["\ud83c\uddf5\ud83c\uddea"] = ":flag_pe:", ["\ud83c\uddf5\ud83c\uddeb"] = ":flag_pf:", ["\ud83c\uddf5\ud83c\uddec"] = ":flag_pg:", ["\ud83c\uddf5\ud83c\udded"] = ":flag_ph:", ["\ud83c\uddf5\ud83c\uddf0"] = ":flag_pk:", ["\ud83c\uddf5\ud83c\uddf1"] = ":flag_pl:", ["\ud83c\uddf5\ud83c\uddf2"] = ":flag_pm:", ["\ud83c\uddf5\ud83c\uddf3"] = ":flag_pn:", ["\ud83c\uddf5\ud83c\uddf7"] = ":flag_pr:", ["\ud83c\uddf5\ud83c\uddf8"] = ":flag_ps:", ["\ud83c\uddf5\ud83c\uddf9"] = ":flag_pt:", ["\ud83c\uddf5\ud83c\uddfc"] = ":flag_pw:", ["\ud83c\uddf5\ud83c\uddfe"] = ":flag_py:", ["\ud83c\uddf6\ud83c\udde6"] = ":flag_qa:", ["\ud83c\uddf7\ud83c\uddea"] = ":flag_re:", ["\ud83c\uddf7\ud83c\uddf4"] = ":flag_ro:", ["\ud83c\uddf7\ud83c\uddf8"] = ":flag_rs:", ["\ud83c\uddf7\ud83c\uddfa"] = ":flag_ru:", ["\ud83c\uddf7\ud83c\uddfc"] = ":flag_rw:", ["\ud83c\uddf8\ud83c\udde6"] = ":flag_sa:", ["\ud83c\uddf8\ud83c\udde7"] = ":flag_sb:", ["\ud83c\uddf8\ud83c\udde8"] = ":flag_sc:", ["\ud83c\uddf8\ud83c\udde9"] = ":flag_sd:", ["\ud83c\uddf8\ud83c\uddea"] = ":flag_se:", ["\ud83c\uddf8\ud83c\uddec"] = ":flag_sg:", ["\ud83c\uddf8\ud83c\udded"] = ":flag_sh:", ["\ud83c\uddf8\ud83c\uddee"] = ":flag_si:", ["\ud83c\uddf8\ud83c\uddef"] = ":flag_sj:", ["\ud83c\uddf8\ud83c\uddf0"] = ":flag_sk:", ["\ud83c\uddf8\ud83c\uddf1"] = ":flag_sl:", ["\ud83c\uddf8\ud83c\uddf2"] = ":flag_sm:", ["\ud83c\uddf8\ud83c\uddf3"] = ":flag_sn:", ["\ud83c\uddf8\ud83c\uddf4"] = ":flag_so:", ["\ud83c\uddf8\ud83c\uddf7"] = ":flag_sr:", ["\ud83c\uddf8\ud83c\uddf8"] = ":flag_ss:", ["\ud83c\uddf8\ud83c\uddf9"] = ":flag_st:", ["\ud83c\uddf8\ud83c\uddfb"] = ":flag_sv:", ["\ud83c\uddf8\ud83c\uddfd"] = ":flag_sx:", ["\ud83c\uddf8\ud83c\uddfe"] = ":flag_sy:", ["\ud83c\uddf8\ud83c\uddff"] = ":flag_sz:", ["\ud83c\uddf9\ud83c\udde6"] = ":flag_ta:", ["\ud83c\uddf9\ud83c\udde8"] = ":flag_tc:", ["\ud83c\uddf9\ud83c\udde9"] = ":flag_td:", ["\ud83c\uddf9\ud83c\uddeb"] = ":flag_tf:", ["\ud83c\uddf9\ud83c\uddec"] = ":flag_tg:", ["\ud83c\uddf9\ud83c\udded"] = ":flag_th:", ["\ud83c\uddf9\ud83c\uddef"] = ":flag_tj:", ["\ud83c\uddf9\ud83c\uddf0"] = ":flag_tk:", ["\ud83c\uddf9\ud83c\uddf1"] = ":flag_tl:", ["\ud83c\uddf9\ud83c\uddf2"] = ":flag_tm:", ["\ud83c\uddf9\ud83c\uddf3"] = ":flag_tn:", ["\ud83c\uddf9\ud83c\uddf4"] = ":flag_to:", ["\ud83c\uddf9\ud83c\uddf7"] = ":flag_tr:", ["\ud83c\uddf9\ud83c\uddf9"] = ":flag_tt:", ["\ud83c\uddf9\ud83c\uddfb"] = ":flag_tv:", ["\ud83c\uddf9\ud83c\uddfc"] = ":flag_tw:", ["\ud83c\uddf9\ud83c\uddff"] = ":flag_tz:", ["\ud83c\uddfa\ud83c\udde6"] = ":flag_ua:", ["\ud83c\uddfa\ud83c\uddec"] = ":flag_ug:", ["\ud83c\uddfa\ud83c\uddf2"] = ":flag_um:", ["\ud83c\uddfa\ud83c\uddf8"] = ":flag_us:", ["\ud83c\uddfa\ud83c\uddfe"] = ":flag_uy:", ["\ud83c\uddfa\ud83c\uddff"] = ":flag_uz:", ["\ud83c\uddfb\ud83c\udde6"] = ":flag_va:", ["\ud83c\uddfb\ud83c\udde8"] = ":flag_vc:", ["\ud83c\uddfb\ud83c\uddea"] = ":flag_ve:", ["\ud83c\uddfb\ud83c\uddec"] = ":flag_vg:", ["\ud83c\uddfb\ud83c\uddee"] = ":flag_vi:", ["\ud83c\uddfb\ud83c\uddf3"] = ":flag_vn:", ["\ud83c\uddfb\ud83c\uddfa"] = ":flag_vu:", ["\ud83c\uddfc\ud83c\uddeb"] = ":flag_wf:", ["\ud83c\udff3\ufe0f"] = ":flag_white:", ["\ud83c\udff3"] = ":flag_white:", ["\ud83c\uddfc\ud83c\uddf8"] = ":flag_ws:", ["\ud83c\uddfd\ud83c\uddf0"] = ":flag_xk:", ["\ud83c\uddfe\ud83c\uddea"] = ":flag_ye:", ["\ud83c\uddfe\ud83c\uddf9"] = ":flag_yt:", ["\ud83c\uddff\ud83c\udde6"] = ":flag_za:", ["\ud83c\uddff\ud83c\uddf2"] = ":flag_zm:", ["\ud83c\uddff\ud83c\uddfc"] = ":flag_zw:", ["\ud83c\udf8f"] = ":flags:", ["\ud83e\udda9"] = ":flamingo:", ["\ud83d\udd26"] = ":flashlight:", ["\ud83e\uded3"] = ":flatbread:", ["⚜\ufe0f"] = ":fleur_de_lis:", ["⚜"] = ":fleur_de_lis:", ["\ud83d\udcbe"] = ":floppy_disk:", ["\ud83c\udfb4"] = ":flower_playing_cards:", ["\ud83d\ude33"] = ":flushed:", ["\ud83e\udeb0"] = ":fly:", ["\ud83e\udd4f"] = ":flying_disc:", ["\ud83d\udef8"] = ":flying_saucer:", ["\ud83c\udf2b\ufe0f"] = ":fog:", ["\ud83c\udf2b"] = ":fog:", ["\ud83c\udf01"] = ":foggy:", ["\ud83e\uded5"] = ":fondue:", ["\ud83e\uddb6\ud83c\udffb"] = ":foot_tone1:", ["\ud83e\uddb6\ud83c\udffc"] = ":foot_tone2:", ["\ud83e\uddb6\ud83c\udffd"] = ":foot_tone3:", ["\ud83e\uddb6\ud83c\udffe"] = ":foot_tone4:", ["\ud83e\uddb6\ud83c\udfff"] = ":foot_tone5:", ["\ud83e\uddb6"] = ":foot:", ["\ud83c\udfc8"] = ":football:", ["\ud83d\udc63"] = ":footprints:", ["\ud83c\udf74"] = ":fork_and_knife:", ["\ud83c\udf7d\ufe0f"] = ":fork_knife_plate:", ["\ud83c\udf7d"] = ":fork_knife_plate:", ["\ud83e\udd60"] = ":fortune_cookie:", ["⛲"] = ":fountain:", ["\ud83c\udf40"] = ":four_leaf_clover:", ["4\ufe0f\u20e3"] = ":four:", ["4\u20e3"] = ":four:", ["\ud83e\udd8a"] = ":fox:", ["\ud83d\uddbc\ufe0f"] = ":frame_photo:", ["\ud83d\uddbc"] = ":frame_photo:", ["\ud83c\udd93"] = ":free:", ["\ud83e\udd56"] = ":french_bread:", ["\ud83c\udf64"] = ":fried_shrimp:", ["\ud83c\udf5f"] = ":fries:", ["\ud83d\udc38"] = ":frog:", ["\ud83d\ude26"] = ":frowning:", ["☹\ufe0f"] = ":frowning2:", ["☹"] = ":frowning2:", ["⛽"] = ":fuelpump:", ["\ud83c\udf1d"] = ":full_moon_with_face:", ["\ud83c\udf15"] = ":full_moon:", ["\ud83c\udfb2"] = ":game_die:", ["\ud83e\uddc4"] = ":garlic:", ["⚙\ufe0f"] = ":gear:", ["⚙"] = ":gear:", ["\ud83d\udc8e"] = ":gem:", ["♊"] = ":gemini:", ["\ud83e\uddde"] = ":genie:", ["\ud83d\udc7b"] = ":ghost:", ["\ud83d\udc9d"] = ":gift_heart:", ["\ud83c\udf81"] = ":gift:", ["\ud83e\udd92"] = ":giraffe:", ["\ud83d\udc67\ud83c\udffb"] = ":girl_tone1:", ["\ud83d\udc67\ud83c\udffc"] = ":girl_tone2:", ["\ud83d\udc67\ud83c\udffd"] = ":girl_tone3:", ["\ud83d\udc67\ud83c\udffe"] = ":girl_tone4:", ["\ud83d\udc67\ud83c\udfff"] = ":girl_tone5:", ["\ud83d\udc67"] = ":girl:", ["\ud83c\udf10"] = ":globe_with_meridians:", ["\ud83e\udde4"] = ":gloves:", ["\ud83e\udd45"] = ":goal:", ["\ud83d\udc10"] = ":goat:", ["\ud83e\udd7d"] = ":goggles:", ["⛳"] = ":golf:", ["\ud83e\udd8d"] = ":gorilla:", ["\ud83c\udf47"] = ":grapes:", ["\ud83c\udf4f"] = ":green_apple:", ["\ud83d\udcd7"] = ":green_book:", ["\ud83d\udfe2"] = ":green_circle:", ["\ud83d\udc9a"] = ":green_heart:", ["\ud83d\udfe9"] = ":green_square:", ["❕"] = ":grey_exclamation:", ["❔"] = ":grey_question:", ["\ud83d\ude2c"] = ":grimacing:", ["\ud83d\ude01"] = ":grin:", ["\ud83d\ude00"] = ":grinning:", ["\ud83d\udc82\ud83c\udffb"] = ":guard_tone1:", ["\ud83d\udc82\ud83c\udffc"] = ":guard_tone2:", ["\ud83d\udc82\ud83c\udffd"] = ":guard_tone3:", ["\ud83d\udc82\ud83c\udffe"] = ":guard_tone4:", ["\ud83d\udc82\ud83c\udfff"] = ":guard_tone5:", ["\ud83d\udc82"] = ":guard:", ["\ud83e\uddae"] = ":guide_dog:", ["\ud83c\udfb8"] = ":guitar:", ["\ud83d\udd2b"] = ":gun:", ["\ud83c\udf54"] = ":hamburger:", ["⚒\ufe0f"] = ":hammer_pick:", ["⚒"] = ":hammer_pick:", ["\ud83d\udd28"] = ":hammer:", ["\ud83e\udeac"] = ":hamsa:", ["\ud83d\udc39"] = ":hamster:", ["\ud83d\udd90\ud83c\udffb"] = ":hand_splayed_tone1:", ["\ud83d\udd90\ud83c\udffc"] = ":hand_splayed_tone2:", ["\ud83d\udd90\ud83c\udffd"] = ":hand_splayed_tone3:", ["\ud83d\udd90\ud83c\udffe"] = ":hand_splayed_tone4:", ["\ud83d\udd90\ud83c\udfff"] = ":hand_splayed_tone5:", ["\ud83d\udd90\ufe0f"] = ":hand_splayed:", ["\ud83d\udd90"] = ":hand_splayed:", ["\ud83e\udef0\ud83c\udffb"] = ":hand_with_index_finger_and_thumb_crossed_tone1:", ["\ud83e\udef0\ud83c\udffc"] = ":hand_with_index_finger_and_thumb_crossed_tone2:", ["\ud83e\udef0\ud83c\udffd"] = ":hand_with_index_finger_and_thumb_crossed_tone3:", ["\ud83e\udef0\ud83c\udffe"] = ":hand_with_index_finger_and_thumb_crossed_tone4:", ["\ud83e\udef0\ud83c\udfff"] = ":hand_with_index_finger_and_thumb_crossed_tone5:", ["\ud83e\udef0"] = ":hand_with_index_finger_and_thumb_crossed:", ["\ud83d\udc5c"] = ":handbag:", ["\ud83e\udd1d"] = ":handshake_tone5_tone4:", ["#\ufe0f\u20e3"] = ":hash:", ["#\u20e3"] = ":hash:", ["\ud83d\udc25"] = ":hatched_chick:", ["\ud83d\udc23"] = ":hatching_chick:", ["\ud83e\udd15"] = ":head_bandage:", ["\ud83c\udfa7"] = ":headphones:", ["\ud83e\udea6"] = ":headstone:", ["\ud83e\uddd1\ud83c\udffb\u200d⚕\ufe0f"] = ":health_worker_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d⚕\ufe0f"] = ":health_worker_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d⚕\ufe0f"] = ":health_worker_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d⚕\ufe0f"] = ":health_worker_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d⚕\ufe0f"] = ":health_worker_tone5:", ["\ud83e\uddd1\u200d⚕\ufe0f"] = ":health_worker:", ["\ud83d\ude49"] = ":hear_no_evil:", ["\ud83d\udc9f"] = ":heart_decoration:", ["❣\ufe0f"] = ":heart_exclamation:", ["❣"] = ":heart_exclamation:", ["\ud83d\ude3b"] = ":heart_eyes_cat:", ["\ud83d\ude0d"] = ":heart_eyes:", ["\ud83e\udef6\ud83c\udffb"] = ":heart_hands_tone1:", ["\ud83e\udef6\ud83c\udffc"] = ":heart_hands_tone2:", ["\ud83e\udef6\ud83c\udffd"] = ":heart_hands_tone3:", ["\ud83e\udef6\ud83c\udffe"] = ":heart_hands_tone4:", ["\ud83e\udef6\ud83c\udfff"] = ":heart_hands_tone5:", ["\ud83e\udef6"] = ":heart_hands:", ["❤\ufe0f\u200d\ud83d\udd25"] = ":heart_on_fire:", ["❤\ufe0f"] = ":heart:", ["❤"] = ":heart:", ["\ud83d\udc93"] = ":heartbeat:", ["\ud83d\udc97"] = ":heartpulse:", ["♥\ufe0f"] = ":hearts:", ["♥"] = ":hearts:", ["✔\ufe0f"] = ":heavy_check_mark:", ["✔"] = ":heavy_check_mark:", ["➗"] = ":heavy_division_sign:", ["\ud83d\udcb2"] = ":heavy_dollar_sign:", ["\ud83d\udff0"] = ":heavy_equals_sign:", ["➖"] = ":heavy_minus_sign:", ["✖\ufe0f"] = ":heavy_multiplication_x:", ["✖"] = ":heavy_multiplication_x:", ["➕"] = ":heavy_plus_sign:", ["\ud83e\udd94"] = ":hedgehog:", ["\ud83d\ude81"] = ":helicopter:", ["⛑\ufe0f"] = ":helmet_with_cross:", ["⛑"] = ":helmet_with_cross:", ["\ud83c\udf3f"] = ":herb:", ["\ud83c\udf3a"] = ":hibiscus:", ["\ud83d\udd06"] = ":high_brightness:", ["\ud83d\udc60"] = ":high_heel:", ["\ud83e\udd7e"] = ":hiking_boot:", ["\ud83d\uded5"] = ":hindu_temple:", ["\ud83e\udd9b"] = ":hippopotamus:", ["\ud83c\udfd2"] = ":hockey:", ["\ud83d\udd73\ufe0f"] = ":hole:", ["\ud83d\udd73"] = ":hole:", ["\ud83c\udfd8\ufe0f"] = ":homes:", ["\ud83c\udfd8"] = ":homes:", ["\ud83c\udf6f"] = ":honey_pot:", ["\ud83e\ude9d"] = ":hook:", ["\ud83c\udfc7\ud83c\udffb"] = ":horse_racing_tone1:", ["\ud83c\udfc7\ud83c\udffc"] = ":horse_racing_tone2:", ["\ud83c\udfc7\ud83c\udffd"] = ":horse_racing_tone3:", ["\ud83c\udfc7\ud83c\udffe"] = ":horse_racing_tone4:", ["\ud83c\udfc7\ud83c\udfff"] = ":horse_racing_tone5:", ["\ud83c\udfc7"] = ":horse_racing:", ["\ud83d\udc34"] = ":horse:", ["\ud83c\udfe5"] = ":hospital:", ["\ud83e\udd75"] = ":hot_face:", ["\ud83c\udf36\ufe0f"] = ":hot_pepper:", ["\ud83c\udf36"] = ":hot_pepper:", ["\ud83c\udf2d"] = ":hotdog:", ["\ud83c\udfe8"] = ":hotel:", ["♨\ufe0f"] = ":hotsprings:", ["♨"] = ":hotsprings:", ["⏳"] = ":hourglass_flowing_sand:", ["⌛"] = ":hourglass:", ["\ud83c\udfda\ufe0f"] = ":house_abandoned:", ["\ud83c\udfda"] = ":house_abandoned:", ["\ud83c\udfe1"] = ":house_with_garden:", ["\ud83c\udfe0"] = ":house:", ["\ud83e\udd17"] = ":hugging:", ["\ud83d\ude2f"] = ":hushed:", ["\ud83d\uded6"] = ":hut:", ["\ud83c\udf68"] = ":ice_cream:", ["\ud83e\uddca"] = ":ice_cube:", ["⛸\ufe0f"] = ":ice_skate:", ["⛸"] = ":ice_skate:", ["\ud83c\udf66"] = ":icecream:", ["\ud83c\udd94"] = ":id:", ["\ud83e\udeaa"] = ":identification_card:", ["\ud83c\ude50"] = ":ideograph_advantage:", ["\ud83d\udc7f"] = ":imp:", ["\ud83d\udce5"] = ":inbox_tray:", ["\ud83d\udce8"] = ":incoming_envelope:", ["\ud83e\udef5\ud83c\udffb"] = ":index_pointing_at_the_viewer_tone1:", ["\ud83e\udef5\ud83c\udffc"] = ":index_pointing_at_the_viewer_tone2:", ["\ud83e\udef5\ud83c\udffd"] = ":index_pointing_at_the_viewer_tone3:", ["\ud83e\udef5\ud83c\udffe"] = ":index_pointing_at_the_viewer_tone4:", ["\ud83e\udef5\ud83c\udfff"] = ":index_pointing_at_the_viewer_tone5:", ["\ud83e\udef5"] = ":index_pointing_at_the_viewer:", ["♾\ufe0f"] = ":infinity:", ["♾"] = ":infinity:", ["ℹ\ufe0f"] = ":information_source:", ["ℹ"] = ":information_source:", ["\ud83d\ude07"] = ":innocent:", ["⁉\ufe0f"] = ":interrobang:", ["⁉"] = ":interrobang:", ["\ud83c\udfdd\ufe0f"] = ":island:", ["\ud83c\udfdd"] = ":island:", ["\ud83c\udfee"] = ":izakaya_lantern:", ["\ud83c\udf83"] = ":jack_o_lantern:", ["\ud83d\uddfe"] = ":japan:", ["\ud83c\udfef"] = ":japanese_castle:", ["\ud83d\udc7a"] = ":japanese_goblin:", ["\ud83d\udc79"] = ":japanese_ogre:", ["\ud83e\uded9"] = ":jar:", ["\ud83d\udc56"] = ":jeans:", ["\ud83e\udde9"] = ":jigsaw:", ["\ud83d\ude39"] = ":joy_cat:", ["\ud83d\ude02"] = ":joy:", ["\ud83d\udd79\ufe0f"] = ":joystick:", ["\ud83d\udd79"] = ":joystick:", ["\ud83e\uddd1\ud83c\udffb\u200d⚖\ufe0f"] = ":judge_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d⚖\ufe0f"] = ":judge_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d⚖\ufe0f"] = ":judge_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d⚖\ufe0f"] = ":judge_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d⚖\ufe0f"] = ":judge_tone5:", ["\ud83e\uddd1\u200d⚖\ufe0f"] = ":judge:", ["\ud83d\udd4b"] = ":kaaba:", ["\ud83e\udd98"] = ":kangaroo:", ["\ud83d\udd11"] = ":key:", ["\ud83d\udddd\ufe0f"] = ":key2:", ["\ud83d\udddd"] = ":key2:", ["⌨\ufe0f"] = ":keyboard:", ["⌨"] = ":keyboard:", ["\ud83d\udd1f"] = ":keycap_ten:", ["\ud83d\udc58"] = ":kimono:", ["\ud83d\udc68\u200d❤\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68"] = ":kiss_mm:", ["\ud83d\udc8f"] = ":kiss_tone5:", ["\ud83d\udc69\u200d❤\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68"] = ":kiss_woman_man_tone5_tone4:", ["\ud83d\udc69\u200d❤\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69"] = ":kiss_ww:", ["\ud83d\udc8b"] = ":kiss:", ["\ud83d\ude3d"] = ":kissing_cat:", ["\ud83d\ude1a"] = ":kissing_closed_eyes:", ["\ud83d\ude18"] = ":kissing_heart:", ["\ud83d\ude19"] = ":kissing_smiling_eyes:", ["\ud83d\ude17"] = ":kissing:", ["\ud83e\ude81"] = ":kite:", ["\ud83e\udd5d"] = ":kiwi:", ["\ud83d\udd2a"] = ":knife:", ["\ud83e\udea2"] = ":knot:", ["\ud83d\udc28"] = ":koala:", ["\ud83c\ude01"] = ":koko:", ["\ud83e\udd7c"] = ":lab_coat:", ["\ud83c\udff7\ufe0f"] = ":label:", ["\ud83c\udff7"] = ":label:", ["\ud83e\udd4d"] = ":lacrosse:", ["\ud83e\ude9c"] = ":ladder:", ["\ud83d\udc1e"] = ":lady_beetle:", ["\ud83d\udd37"] = ":large_blue_diamond:", ["\ud83d\udd36"] = ":large_orange_diamond:", ["\ud83c\udf1c"] = ":last_quarter_moon_with_face:", ["\ud83c\udf17"] = ":last_quarter_moon:", ["\ud83d\ude06"] = ":laughing:", ["\ud83e\udd6c"] = ":leafy_green:", ["\ud83c\udf43"] = ":leaves:", ["\ud83d\udcd2"] = ":ledger:", ["\ud83e\udd1b\ud83c\udffb"] = ":left_facing_fist_tone1:", ["\ud83e\udd1b\ud83c\udffc"] = ":left_facing_fist_tone2:", ["\ud83e\udd1b\ud83c\udffd"] = ":left_facing_fist_tone3:", ["\ud83e\udd1b\ud83c\udffe"] = ":left_facing_fist_tone4:", ["\ud83e\udd1b\ud83c\udfff"] = ":left_facing_fist_tone5:", ["\ud83e\udd1b"] = ":left_facing_fist:", ["\ud83d\udec5"] = ":left_luggage:", ["↔\ufe0f"] = ":left_right_arrow:", ["↔"] = ":left_right_arrow:", ["↩\ufe0f"] = ":leftwards_arrow_with_hook:", ["↩"] = ":leftwards_arrow_with_hook:", ["\ud83e\udef2\ud83c\udffb"] = ":leftwards_hand_tone1:", ["\ud83e\udef2\ud83c\udffc"] = ":leftwards_hand_tone2:", ["\ud83e\udef2\ud83c\udffd"] = ":leftwards_hand_tone3:", ["\ud83e\udef2\ud83c\udffe"] = ":leftwards_hand_tone4:", ["\ud83e\udef2\ud83c\udfff"] = ":leftwards_hand_tone5:", ["\ud83e\udef2"] = ":leftwards_hand:", ["\ud83e\uddb5\ud83c\udffb"] = ":leg_tone1:", ["\ud83e\uddb5\ud83c\udffc"] = ":leg_tone2:", ["\ud83e\uddb5\ud83c\udffd"] = ":leg_tone3:", ["\ud83e\uddb5\ud83c\udffe"] = ":leg_tone4:", ["\ud83e\uddb5\ud83c\udfff"] = ":leg_tone5:", ["\ud83e\uddb5"] = ":leg:", ["\ud83c\udf4b"] = ":lemon:", ["♌"] = ":leo:", ["\ud83d\udc06"] = ":leopard:", ["\ud83c\udf9a\ufe0f"] = ":level_slider:", ["\ud83c\udf9a"] = ":level_slider:", ["\ud83d\udd74\ud83c\udffb"] = ":levitate_tone1:", ["\ud83d\udd74\ud83c\udffc"] = ":levitate_tone2:", ["\ud83d\udd74\ud83c\udffd"] = ":levitate_tone3:", ["\ud83d\udd74\ud83c\udffe"] = ":levitate_tone4:", ["\ud83d\udd74\ud83c\udfff"] = ":levitate_tone5:", ["\ud83d\udd74\ufe0f"] = ":levitate:", ["\ud83d\udd74"] = ":levitate:", ["♎"] = ":libra:", ["\ud83d\ude88"] = ":light_rail:", ["\ud83d\udd17"] = ":link:", ["\ud83e\udd81"] = ":lion_face:", ["\ud83d\udc44"] = ":lips:", ["\ud83d\udc84"] = ":lipstick:", ["\ud83e\udd8e"] = ":lizard:", ["\ud83e\udd99"] = ":llama:", ["\ud83e\udd9e"] = ":lobster:", ["\ud83d\udd0f"] = ":lock_with_ink_pen:", ["\ud83d\udd12"] = ":lock:", ["\ud83c\udf6d"] = ":lollipop:", ["\ud83e\ude98"] = ":long_drum:", ["➿"] = ":loop:", ["\ud83e\udeb7"] = ":lotus:", ["\ud83d\udd0a"] = ":loud_sound:", ["\ud83d\udce2"] = ":loudspeaker:", ["\ud83c\udfe9"] = ":love_hotel:", ["\ud83d\udc8c"] = ":love_letter:", ["\ud83e\udd1f\ud83c\udffb"] = ":love_you_gesture_tone1:", ["\ud83e\udd1f\ud83c\udffc"] = ":love_you_gesture_tone2:", ["\ud83e\udd1f\ud83c\udffd"] = ":love_you_gesture_tone3:", ["\ud83e\udd1f\ud83c\udffe"] = ":love_you_gesture_tone4:", ["\ud83e\udd1f\ud83c\udfff"] = ":love_you_gesture_tone5:", ["\ud83e\udd1f"] = ":love_you_gesture:", ["\ud83e\udeab"] = ":low_battery:", ["\ud83d\udd05"] = ":low_brightness:", ["\ud83e\uddf3"] = ":luggage:", ["\ud83e\udec1"] = ":lungs:", ["\ud83e\udd25"] = ":lying_face:", ["Ⓜ\ufe0f"] = ":m:", ["Ⓜ"] = ":m:", ["\ud83d\udd0e"] = ":mag_right:", ["\ud83d\udd0d"] = ":mag:", ["\ud83e\uddd9\ud83c\udffb"] = ":mage_tone1:", ["\ud83e\uddd9\ud83c\udffc"] = ":mage_tone2:", ["\ud83e\uddd9\ud83c\udffd"] = ":mage_tone3:", ["\ud83e\uddd9\ud83c\udffe"] = ":mage_tone4:", ["\ud83e\uddd9\ud83c\udfff"] = ":mage_tone5:", ["\ud83e\uddd9"] = ":mage:", ["\ud83e\ude84"] = ":magic_wand:", ["\ud83e\uddf2"] = ":magnet:", ["\ud83c\udc04"] = ":mahjong:", ["\ud83d\udcea"] = ":mailbox_closed:", ["\ud83d\udcec"] = ":mailbox_with_mail:", ["\ud83d\udced"] = ":mailbox_with_no_mail:", ["\ud83d\udceb"] = ":mailbox:", ["♂\ufe0f"] = ":male_sign:", ["♂"] = ":male_sign:", ["\ud83e\udda3"] = ":mammoth:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83c\udfa8"] = ":man_artist_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83c\udfa8"] = ":man_artist_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83c\udfa8"] = ":man_artist_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83c\udfa8"] = ":man_artist_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83c\udfa8"] = ":man_artist_tone5:", ["\ud83d\udc68\u200d\ud83c\udfa8"] = ":man_artist:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83d\ude80"] = ":man_astronaut_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83d\ude80"] = ":man_astronaut_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83d\ude80"] = ":man_astronaut_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83d\ude80"] = ":man_astronaut_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83d\ude80"] = ":man_astronaut_tone5:", ["\ud83d\udc68\u200d\ud83d\ude80"] = ":man_astronaut:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83e\uddb2"] = ":man_bald_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83e\uddb2"] = ":man_bald_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83e\uddb2"] = ":man_bald_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83e\uddb2"] = ":man_bald_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83e\uddb2"] = ":man_bald_tone5:", ["\ud83d\udc68\u200d\ud83e\uddb2"] = ":man_bald:", ["\ud83e\uddd4\u200d♂\ufe0f"] = ":man_beard:", ["\ud83d\udeb4\ud83c\udffb\u200d♂\ufe0f"] = ":man_biking_tone1:", ["\ud83d\udeb4\ud83c\udffc\u200d♂\ufe0f"] = ":man_biking_tone2:", ["\ud83d\udeb4\ud83c\udffd\u200d♂\ufe0f"] = ":man_biking_tone3:", ["\ud83d\udeb4\ud83c\udffe\u200d♂\ufe0f"] = ":man_biking_tone4:", ["\ud83d\udeb4\ud83c\udfff\u200d♂\ufe0f"] = ":man_biking_tone5:", ["\ud83d\udeb4\u200d♂\ufe0f"] = ":man_biking:", ["⛹\ud83c\udffb\u200d♂\ufe0f"] = ":man_bouncing_ball_tone1:", ["⛹\ud83c\udffc\u200d♂\ufe0f"] = ":man_bouncing_ball_tone2:", ["⛹\ud83c\udffd\u200d♂\ufe0f"] = ":man_bouncing_ball_tone3:", ["⛹\ud83c\udffe\u200d♂\ufe0f"] = ":man_bouncing_ball_tone4:", ["⛹\ud83c\udfff\u200d♂\ufe0f"] = ":man_bouncing_ball_tone5:", ["⛹\ufe0f\u200d♂\ufe0f"] = ":man_bouncing_ball:", ["\ud83d\ude47\ud83c\udffb\u200d♂\ufe0f"] = ":man_bowing_tone1:", ["\ud83d\ude47\ud83c\udffc\u200d♂\ufe0f"] = ":man_bowing_tone2:", ["\ud83d\ude47\ud83c\udffd\u200d♂\ufe0f"] = ":man_bowing_tone3:", ["\ud83d\ude47\ud83c\udffe\u200d♂\ufe0f"] = ":man_bowing_tone4:", ["\ud83d\ude47\ud83c\udfff\u200d♂\ufe0f"] = ":man_bowing_tone5:", ["\ud83d\ude47\u200d♂\ufe0f"] = ":man_bowing:", ["\ud83e\udd38\ud83c\udffb\u200d♂\ufe0f"] = ":man_cartwheeling_tone1:", ["\ud83e\udd38\ud83c\udffc\u200d♂\ufe0f"] = ":man_cartwheeling_tone2:", ["\ud83e\udd38\ud83c\udffd\u200d♂\ufe0f"] = ":man_cartwheeling_tone3:", ["\ud83e\udd38\ud83c\udffe\u200d♂\ufe0f"] = ":man_cartwheeling_tone4:", ["\ud83e\udd38\ud83c\udfff\u200d♂\ufe0f"] = ":man_cartwheeling_tone5:", ["\ud83e\udd38\u200d♂\ufe0f"] = ":man_cartwheeling:", ["\ud83e\uddd7\ud83c\udffb\u200d♂\ufe0f"] = ":man_climbing_tone1:", ["\ud83e\uddd7\ud83c\udffc\u200d♂\ufe0f"] = ":man_climbing_tone2:", ["\ud83e\uddd7\ud83c\udffd\u200d♂\ufe0f"] = ":man_climbing_tone3:", ["\ud83e\uddd7\ud83c\udffe\u200d♂\ufe0f"] = ":man_climbing_tone4:", ["\ud83e\uddd7\ud83c\udfff\u200d♂\ufe0f"] = ":man_climbing_tone5:", ["\ud83e\uddd7\u200d♂\ufe0f"] = ":man_climbing:", ["\ud83d\udc77\ud83c\udffb\u200d♂\ufe0f"] = ":man_construction_worker_tone1:", ["\ud83d\udc77\ud83c\udffc\u200d♂\ufe0f"] = ":man_construction_worker_tone2:", ["\ud83d\udc77\ud83c\udffd\u200d♂\ufe0f"] = ":man_construction_worker_tone3:", ["\ud83d\udc77\ud83c\udffe\u200d♂\ufe0f"] = ":man_construction_worker_tone4:", ["\ud83d\udc77\ud83c\udfff\u200d♂\ufe0f"] = ":man_construction_worker_tone5:", ["\ud83d\udc77\u200d♂\ufe0f"] = ":man_construction_worker:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83c\udf73"] = ":man_cook_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83c\udf73"] = ":man_cook_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83c\udf73"] = ":man_cook_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83c\udf73"] = ":man_cook_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83c\udf73"] = ":man_cook_tone5:", ["\ud83d\udc68\u200d\ud83c\udf73"] = ":man_cook:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83e\uddb1"] = ":man_curly_haired_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83e\uddb1"] = ":man_curly_haired_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83e\uddb1"] = ":man_curly_haired_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83e\uddb1"] = ":man_curly_haired_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83e\uddb1"] = ":man_curly_haired_tone5:", ["\ud83d\udc68\u200d\ud83e\uddb1"] = ":man_curly_haired:", ["\ud83d\udd7a\ud83c\udffb"] = ":man_dancing_tone1:", ["\ud83d\udd7a\ud83c\udffc"] = ":man_dancing_tone2:", ["\ud83d\udd7a\ud83c\udffd"] = ":man_dancing_tone3:", ["\ud83d\udd7a\ud83c\udffe"] = ":man_dancing_tone4:", ["\ud83d\udd7a\ud83c\udfff"] = ":man_dancing_tone5:", ["\ud83d\udd7a"] = ":man_dancing:", ["\ud83d\udd75\ud83c\udffb\u200d♂\ufe0f"] = ":man_detective_tone1:", ["\ud83d\udd75\ud83c\udffc\u200d♂\ufe0f"] = ":man_detective_tone2:", ["\ud83d\udd75\ud83c\udffd\u200d♂\ufe0f"] = ":man_detective_tone3:", ["\ud83d\udd75\ud83c\udffe\u200d♂\ufe0f"] = ":man_detective_tone4:", ["\ud83d\udd75\ud83c\udfff\u200d♂\ufe0f"] = ":man_detective_tone5:", ["\ud83d\udd75\ufe0f\u200d♂\ufe0f"] = ":man_detective:", ["\ud83e\udddd\ud83c\udffb\u200d♂\ufe0f"] = ":man_elf_tone1:", ["\ud83e\udddd\ud83c\udffc\u200d♂\ufe0f"] = ":man_elf_tone2:", ["\ud83e\udddd\ud83c\udffd\u200d♂\ufe0f"] = ":man_elf_tone3:", ["\ud83e\udddd\ud83c\udffe\u200d♂\ufe0f"] = ":man_elf_tone4:", ["\ud83e\udddd\ud83c\udfff\u200d♂\ufe0f"] = ":man_elf_tone5:", ["\ud83e\udddd\u200d♂\ufe0f"] = ":man_elf:", ["\ud83e\udd26\ud83c\udffb\u200d♂\ufe0f"] = ":man_facepalming_tone1:", ["\ud83e\udd26\ud83c\udffc\u200d♂\ufe0f"] = ":man_facepalming_tone2:", ["\ud83e\udd26\ud83c\udffd\u200d♂\ufe0f"] = ":man_facepalming_tone3:", ["\ud83e\udd26\ud83c\udffe\u200d♂\ufe0f"] = ":man_facepalming_tone4:", ["\ud83e\udd26\ud83c\udfff\u200d♂\ufe0f"] = ":man_facepalming_tone5:", ["\ud83e\udd26\u200d♂\ufe0f"] = ":man_facepalming:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83c\udfed"] = ":man_factory_worker_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83c\udfed"] = ":man_factory_worker_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83c\udfed"] = ":man_factory_worker_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83c\udfed"] = ":man_factory_worker_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83c\udfed"] = ":man_factory_worker_tone5:", ["\ud83d\udc68\u200d\ud83c\udfed"] = ":man_factory_worker:", ["\ud83e\uddda\ud83c\udffb\u200d♂\ufe0f"] = ":man_fairy_tone1:", ["\ud83e\uddda\ud83c\udffc\u200d♂\ufe0f"] = ":man_fairy_tone2:", ["\ud83e\uddda\ud83c\udffd\u200d♂\ufe0f"] = ":man_fairy_tone3:", ["\ud83e\uddda\ud83c\udffe\u200d♂\ufe0f"] = ":man_fairy_tone4:", ["\ud83e\uddda\ud83c\udfff\u200d♂\ufe0f"] = ":man_fairy_tone5:", ["\ud83e\uddda\u200d♂\ufe0f"] = ":man_fairy:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83c\udf3e"] = ":man_farmer_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83c\udf3e"] = ":man_farmer_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83c\udf3e"] = ":man_farmer_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83c\udf3e"] = ":man_farmer_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83c\udf3e"] = ":man_farmer_tone5:", ["\ud83d\udc68\u200d\ud83c\udf3e"] = ":man_farmer:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83c\udf7c"] = ":man_feeding_baby_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83c\udf7c"] = ":man_feeding_baby_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83c\udf7c"] = ":man_feeding_baby_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83c\udf7c"] = ":man_feeding_baby_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83c\udf7c"] = ":man_feeding_baby_tone5:", ["\ud83d\udc68\u200d\ud83c\udf7c"] = ":man_feeding_baby:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83d\ude92"] = ":man_firefighter_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83d\ude92"] = ":man_firefighter_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83d\ude92"] = ":man_firefighter_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83d\ude92"] = ":man_firefighter_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83d\ude92"] = ":man_firefighter_tone5:", ["\ud83d\udc68\u200d\ud83d\ude92"] = ":man_firefighter:", ["\ud83d\ude4d\ud83c\udffb\u200d♂\ufe0f"] = ":man_frowning_tone1:", ["\ud83d\ude4d\ud83c\udffc\u200d♂\ufe0f"] = ":man_frowning_tone2:", ["\ud83d\ude4d\ud83c\udffd\u200d♂\ufe0f"] = ":man_frowning_tone3:", ["\ud83d\ude4d\ud83c\udffe\u200d♂\ufe0f"] = ":man_frowning_tone4:", ["\ud83d\ude4d\ud83c\udfff\u200d♂\ufe0f"] = ":man_frowning_tone5:", ["\ud83d\ude4d\u200d♂\ufe0f"] = ":man_frowning:", ["\ud83e\uddde\u200d♂\ufe0f"] = ":man_genie:", ["\ud83d\ude45\ud83c\udffb\u200d♂\ufe0f"] = ":man_gesturing_no_tone1:", ["\ud83d\ude45\ud83c\udffc\u200d♂\ufe0f"] = ":man_gesturing_no_tone2:", ["\ud83d\ude45\ud83c\udffd\u200d♂\ufe0f"] = ":man_gesturing_no_tone3:", ["\ud83d\ude45\ud83c\udffe\u200d♂\ufe0f"] = ":man_gesturing_no_tone4:", ["\ud83d\ude45\ud83c\udfff\u200d♂\ufe0f"] = ":man_gesturing_no_tone5:", ["\ud83d\ude45\u200d♂\ufe0f"] = ":man_gesturing_no:", ["\ud83d\ude46\ud83c\udffb\u200d♂\ufe0f"] = ":man_gesturing_ok_tone1:", ["\ud83d\ude46\ud83c\udffc\u200d♂\ufe0f"] = ":man_gesturing_ok_tone2:", ["\ud83d\ude46\ud83c\udffd\u200d♂\ufe0f"] = ":man_gesturing_ok_tone3:", ["\ud83d\ude46\ud83c\udffe\u200d♂\ufe0f"] = ":man_gesturing_ok_tone4:", ["\ud83d\ude46\ud83c\udfff\u200d♂\ufe0f"] = ":man_gesturing_ok_tone5:", ["\ud83d\ude46\u200d♂\ufe0f"] = ":man_gesturing_ok:", ["\ud83d\udc86\ud83c\udffb\u200d♂\ufe0f"] = ":man_getting_face_massage_tone1:", ["\ud83d\udc86\ud83c\udffc\u200d♂\ufe0f"] = ":man_getting_face_massage_tone2:", ["\ud83d\udc86\ud83c\udffd\u200d♂\ufe0f"] = ":man_getting_face_massage_tone3:", ["\ud83d\udc86\ud83c\udffe\u200d♂\ufe0f"] = ":man_getting_face_massage_tone4:", ["\ud83d\udc86\ud83c\udfff\u200d♂\ufe0f"] = ":man_getting_face_massage_tone5:", ["\ud83d\udc86\u200d♂\ufe0f"] = ":man_getting_face_massage:", ["\ud83d\udc87\ud83c\udffb\u200d♂\ufe0f"] = ":man_getting_haircut_tone1:", ["\ud83d\udc87\ud83c\udffc\u200d♂\ufe0f"] = ":man_getting_haircut_tone2:", ["\ud83d\udc87\ud83c\udffd\u200d♂\ufe0f"] = ":man_getting_haircut_tone3:", ["\ud83d\udc87\ud83c\udffe\u200d♂\ufe0f"] = ":man_getting_haircut_tone4:", ["\ud83d\udc87\ud83c\udfff\u200d♂\ufe0f"] = ":man_getting_haircut_tone5:", ["\ud83d\udc87\u200d♂\ufe0f"] = ":man_getting_haircut:", ["\ud83c\udfcc\ud83c\udffb\u200d♂\ufe0f"] = ":man_golfing_tone1:", ["\ud83c\udfcc\ud83c\udffc\u200d♂\ufe0f"] = ":man_golfing_tone2:", ["\ud83c\udfcc\ud83c\udffd\u200d♂\ufe0f"] = ":man_golfing_tone3:", ["\ud83c\udfcc\ud83c\udffe\u200d♂\ufe0f"] = ":man_golfing_tone4:", ["\ud83c\udfcc\ud83c\udfff\u200d♂\ufe0f"] = ":man_golfing_tone5:", ["\ud83c\udfcc\ufe0f\u200d♂\ufe0f"] = ":man_golfing:", ["\ud83d\udc82\ud83c\udffb\u200d♂\ufe0f"] = ":man_guard_tone1:", ["\ud83d\udc82\ud83c\udffc\u200d♂\ufe0f"] = ":man_guard_tone2:", ["\ud83d\udc82\ud83c\udffd\u200d♂\ufe0f"] = ":man_guard_tone3:", ["\ud83d\udc82\ud83c\udffe\u200d♂\ufe0f"] = ":man_guard_tone4:", ["\ud83d\udc82\ud83c\udfff\u200d♂\ufe0f"] = ":man_guard_tone5:", ["\ud83d\udc82\u200d♂\ufe0f"] = ":man_guard:", ["\ud83d\udc68\ud83c\udffb\u200d⚕\ufe0f"] = ":man_health_worker_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d⚕\ufe0f"] = ":man_health_worker_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d⚕\ufe0f"] = ":man_health_worker_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d⚕\ufe0f"] = ":man_health_worker_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d⚕\ufe0f"] = ":man_health_worker_tone5:", ["\ud83d\udc68\u200d⚕\ufe0f"] = ":man_health_worker:", ["\ud83e\uddd8\ud83c\udffb\u200d♂\ufe0f"] = ":man_in_lotus_position_tone1:", ["\ud83e\uddd8\ud83c\udffc\u200d♂\ufe0f"] = ":man_in_lotus_position_tone2:", ["\ud83e\uddd8\ud83c\udffd\u200d♂\ufe0f"] = ":man_in_lotus_position_tone3:", ["\ud83e\uddd8\ud83c\udffe\u200d♂\ufe0f"] = ":man_in_lotus_position_tone4:", ["\ud83e\uddd8\ud83c\udfff\u200d♂\ufe0f"] = ":man_in_lotus_position_tone5:", ["\ud83e\uddd8\u200d♂\ufe0f"] = ":man_in_lotus_position:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83e\uddbd"] = ":man_in_manual_wheelchair_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83e\uddbd"] = ":man_in_manual_wheelchair_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83e\uddbd"] = ":man_in_manual_wheelchair_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83e\uddbd"] = ":man_in_manual_wheelchair_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83e\uddbd"] = ":man_in_manual_wheelchair_tone5:", ["\ud83d\udc68\u200d\ud83e\uddbd"] = ":man_in_manual_wheelchair:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83e\uddbc"] = ":man_in_motorized_wheelchair_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83e\uddbc"] = ":man_in_motorized_wheelchair_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83e\uddbc"] = ":man_in_motorized_wheelchair_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83e\uddbc"] = ":man_in_motorized_wheelchair_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83e\uddbc"] = ":man_in_motorized_wheelchair_tone5:", ["\ud83d\udc68\u200d\ud83e\uddbc"] = ":man_in_motorized_wheelchair:", ["\ud83e\uddd6\ud83c\udffb\u200d♂\ufe0f"] = ":man_in_steamy_room_tone1:", ["\ud83e\uddd6\ud83c\udffc\u200d♂\ufe0f"] = ":man_in_steamy_room_tone2:", ["\ud83e\uddd6\ud83c\udffd\u200d♂\ufe0f"] = ":man_in_steamy_room_tone3:", ["\ud83e\uddd6\ud83c\udffe\u200d♂\ufe0f"] = ":man_in_steamy_room_tone4:", ["\ud83e\uddd6\ud83c\udfff\u200d♂\ufe0f"] = ":man_in_steamy_room_tone5:", ["\ud83e\uddd6\u200d♂\ufe0f"] = ":man_in_steamy_room:", ["\ud83e\udd35\ud83c\udffb\u200d♂\ufe0f"] = ":man_in_tuxedo_tone1:", ["\ud83e\udd35\ud83c\udffc\u200d♂\ufe0f"] = ":man_in_tuxedo_tone2:", ["\ud83e\udd35\ud83c\udffd\u200d♂\ufe0f"] = ":man_in_tuxedo_tone3:", ["\ud83e\udd35\ud83c\udffe\u200d♂\ufe0f"] = ":man_in_tuxedo_tone4:", ["\ud83e\udd35\ud83c\udfff\u200d♂\ufe0f"] = ":man_in_tuxedo_tone5:", ["\ud83e\udd35\u200d♂\ufe0f"] = ":man_in_tuxedo:", ["\ud83d\udc68\ud83c\udffb\u200d⚖\ufe0f"] = ":man_judge_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d⚖\ufe0f"] = ":man_judge_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d⚖\ufe0f"] = ":man_judge_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d⚖\ufe0f"] = ":man_judge_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d⚖\ufe0f"] = ":man_judge_tone5:", ["\ud83d\udc68\u200d⚖\ufe0f"] = ":man_judge:", ["\ud83e\udd39\ud83c\udffb\u200d♂\ufe0f"] = ":man_juggling_tone1:", ["\ud83e\udd39\ud83c\udffc\u200d♂\ufe0f"] = ":man_juggling_tone2:", ["\ud83e\udd39\ud83c\udffd\u200d♂\ufe0f"] = ":man_juggling_tone3:", ["\ud83e\udd39\ud83c\udffe\u200d♂\ufe0f"] = ":man_juggling_tone4:", ["\ud83e\udd39\ud83c\udfff\u200d♂\ufe0f"] = ":man_juggling_tone5:", ["\ud83e\udd39\u200d♂\ufe0f"] = ":man_juggling:", ["\ud83e\uddce\ud83c\udffb\u200d♂\ufe0f"] = ":man_kneeling_tone1:", ["\ud83e\uddce\ud83c\udffc\u200d♂\ufe0f"] = ":man_kneeling_tone2:", ["\ud83e\uddce\ud83c\udffd\u200d♂\ufe0f"] = ":man_kneeling_tone3:", ["\ud83e\uddce\ud83c\udffe\u200d♂\ufe0f"] = ":man_kneeling_tone4:", ["\ud83e\uddce\ud83c\udfff\u200d♂\ufe0f"] = ":man_kneeling_tone5:", ["\ud83e\uddce\u200d♂\ufe0f"] = ":man_kneeling:", ["\ud83c\udfcb\ud83c\udffb\u200d♂\ufe0f"] = ":man_lifting_weights_tone1:", ["\ud83c\udfcb\ud83c\udffc\u200d♂\ufe0f"] = ":man_lifting_weights_tone2:", ["\ud83c\udfcb\ud83c\udffd\u200d♂\ufe0f"] = ":man_lifting_weights_tone3:", ["\ud83c\udfcb\ud83c\udffe\u200d♂\ufe0f"] = ":man_lifting_weights_tone4:", ["\ud83c\udfcb\ud83c\udfff\u200d♂\ufe0f"] = ":man_lifting_weights_tone5:", ["\ud83c\udfcb\ufe0f\u200d♂\ufe0f"] = ":man_lifting_weights:", ["\ud83e\uddd9\ud83c\udffb\u200d♂\ufe0f"] = ":man_mage_tone1:", ["\ud83e\uddd9\ud83c\udffc\u200d♂\ufe0f"] = ":man_mage_tone2:", ["\ud83e\uddd9\ud83c\udffd\u200d♂\ufe0f"] = ":man_mage_tone3:", ["\ud83e\uddd9\ud83c\udffe\u200d♂\ufe0f"] = ":man_mage_tone4:", ["\ud83e\uddd9\ud83c\udfff\u200d♂\ufe0f"] = ":man_mage_tone5:", ["\ud83e\uddd9\u200d♂\ufe0f"] = ":man_mage:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83d\udd27"] = ":man_mechanic_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83d\udd27"] = ":man_mechanic_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83d\udd27"] = ":man_mechanic_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83d\udd27"] = ":man_mechanic_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83d\udd27"] = ":man_mechanic_tone5:", ["\ud83d\udc68\u200d\ud83d\udd27"] = ":man_mechanic:", ["\ud83d\udeb5\ud83c\udffb\u200d♂\ufe0f"] = ":man_mountain_biking_tone1:", ["\ud83d\udeb5\ud83c\udffc\u200d♂\ufe0f"] = ":man_mountain_biking_tone2:", ["\ud83d\udeb5\ud83c\udffd\u200d♂\ufe0f"] = ":man_mountain_biking_tone3:", ["\ud83d\udeb5\ud83c\udffe\u200d♂\ufe0f"] = ":man_mountain_biking_tone4:", ["\ud83d\udeb5\ud83c\udfff\u200d♂\ufe0f"] = ":man_mountain_biking_tone5:", ["\ud83d\udeb5\u200d♂\ufe0f"] = ":man_mountain_biking:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83d\udcbc"] = ":man_office_worker_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83d\udcbc"] = ":man_office_worker_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83d\udcbc"] = ":man_office_worker_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83d\udcbc"] = ":man_office_worker_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83d\udcbc"] = ":man_office_worker_tone5:", ["\ud83d\udc68\u200d\ud83d\udcbc"] = ":man_office_worker:", ["\ud83d\udc68\ud83c\udffb\u200d✈\ufe0f"] = ":man_pilot_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d✈\ufe0f"] = ":man_pilot_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d✈\ufe0f"] = ":man_pilot_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d✈\ufe0f"] = ":man_pilot_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d✈\ufe0f"] = ":man_pilot_tone5:", ["\ud83d\udc68\u200d✈\ufe0f"] = ":man_pilot:", ["\ud83e\udd3e\ud83c\udffb\u200d♂\ufe0f"] = ":man_playing_handball_tone1:", ["\ud83e\udd3e\ud83c\udffc\u200d♂\ufe0f"] = ":man_playing_handball_tone2:", ["\ud83e\udd3e\ud83c\udffd\u200d♂\ufe0f"] = ":man_playing_handball_tone3:", ["\ud83e\udd3e\ud83c\udffe\u200d♂\ufe0f"] = ":man_playing_handball_tone4:", ["\ud83e\udd3e\ud83c\udfff\u200d♂\ufe0f"] = ":man_playing_handball_tone5:", ["\ud83e\udd3e\u200d♂\ufe0f"] = ":man_playing_handball:", ["\ud83e\udd3d\ud83c\udffb\u200d♂\ufe0f"] = ":man_playing_water_polo_tone1:", ["\ud83e\udd3d\ud83c\udffc\u200d♂\ufe0f"] = ":man_playing_water_polo_tone2:", ["\ud83e\udd3d\ud83c\udffd\u200d♂\ufe0f"] = ":man_playing_water_polo_tone3:", ["\ud83e\udd3d\ud83c\udffe\u200d♂\ufe0f"] = ":man_playing_water_polo_tone4:", ["\ud83e\udd3d\ud83c\udfff\u200d♂\ufe0f"] = ":man_playing_water_polo_tone5:", ["\ud83e\udd3d\u200d♂\ufe0f"] = ":man_playing_water_polo:", ["\ud83d\udc6e\ud83c\udffb\u200d♂\ufe0f"] = ":man_police_officer_tone1:", ["\ud83d\udc6e\ud83c\udffc\u200d♂\ufe0f"] = ":man_police_officer_tone2:", ["\ud83d\udc6e\ud83c\udffd\u200d♂\ufe0f"] = ":man_police_officer_tone3:", ["\ud83d\udc6e\ud83c\udffe\u200d♂\ufe0f"] = ":man_police_officer_tone4:", ["\ud83d\udc6e\ud83c\udfff\u200d♂\ufe0f"] = ":man_police_officer_tone5:", ["\ud83d\udc6e\u200d♂\ufe0f"] = ":man_police_officer:", ["\ud83d\ude4e\ud83c\udffb\u200d♂\ufe0f"] = ":man_pouting_tone1:", ["\ud83d\ude4e\ud83c\udffc\u200d♂\ufe0f"] = ":man_pouting_tone2:", ["\ud83d\ude4e\ud83c\udffd\u200d♂\ufe0f"] = ":man_pouting_tone3:", ["\ud83d\ude4e\ud83c\udffe\u200d♂\ufe0f"] = ":man_pouting_tone4:", ["\ud83d\ude4e\ud83c\udfff\u200d♂\ufe0f"] = ":man_pouting_tone5:", ["\ud83d\ude4e\u200d♂\ufe0f"] = ":man_pouting:", ["\ud83d\ude4b\ud83c\udffb\u200d♂\ufe0f"] = ":man_raising_hand_tone1:", ["\ud83d\ude4b\ud83c\udffc\u200d♂\ufe0f"] = ":man_raising_hand_tone2:", ["\ud83d\ude4b\ud83c\udffd\u200d♂\ufe0f"] = ":man_raising_hand_tone3:", ["\ud83d\ude4b\ud83c\udffe\u200d♂\ufe0f"] = ":man_raising_hand_tone4:", ["\ud83d\ude4b\ud83c\udfff\u200d♂\ufe0f"] = ":man_raising_hand_tone5:", ["\ud83d\ude4b\u200d♂\ufe0f"] = ":man_raising_hand:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83e\uddb0"] = ":man_red_haired_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83e\uddb0"] = ":man_red_haired_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83e\uddb0"] = ":man_red_haired_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83e\uddb0"] = ":man_red_haired_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83e\uddb0"] = ":man_red_haired_tone5:", ["\ud83d\udc68\u200d\ud83e\uddb0"] = ":man_red_haired:", ["\ud83d\udea3\ud83c\udffb\u200d♂\ufe0f"] = ":man_rowing_boat_tone1:", ["\ud83d\udea3\ud83c\udffc\u200d♂\ufe0f"] = ":man_rowing_boat_tone2:", ["\ud83d\udea3\ud83c\udffd\u200d♂\ufe0f"] = ":man_rowing_boat_tone3:", ["\ud83d\udea3\ud83c\udffe\u200d♂\ufe0f"] = ":man_rowing_boat_tone4:", ["\ud83d\udea3\ud83c\udfff\u200d♂\ufe0f"] = ":man_rowing_boat_tone5:", ["\ud83d\udea3\u200d♂\ufe0f"] = ":man_rowing_boat:", ["\ud83c\udfc3\ud83c\udffb\u200d♂\ufe0f"] = ":man_running_tone1:", ["\ud83c\udfc3\ud83c\udffc\u200d♂\ufe0f"] = ":man_running_tone2:", ["\ud83c\udfc3\ud83c\udffd\u200d♂\ufe0f"] = ":man_running_tone3:", ["\ud83c\udfc3\ud83c\udffe\u200d♂\ufe0f"] = ":man_running_tone4:", ["\ud83c\udfc3\ud83c\udfff\u200d♂\ufe0f"] = ":man_running_tone5:", ["\ud83c\udfc3\u200d♂\ufe0f"] = ":man_running:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83d\udd2c"] = ":man_scientist_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83d\udd2c"] = ":man_scientist_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83d\udd2c"] = ":man_scientist_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83d\udd2c"] = ":man_scientist_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83d\udd2c"] = ":man_scientist_tone5:", ["\ud83d\udc68\u200d\ud83d\udd2c"] = ":man_scientist:", ["\ud83e\udd37\ud83c\udffb\u200d♂\ufe0f"] = ":man_shrugging_tone1:", ["\ud83e\udd37\ud83c\udffc\u200d♂\ufe0f"] = ":man_shrugging_tone2:", ["\ud83e\udd37\ud83c\udffd\u200d♂\ufe0f"] = ":man_shrugging_tone3:", ["\ud83e\udd37\ud83c\udffe\u200d♂\ufe0f"] = ":man_shrugging_tone4:", ["\ud83e\udd37\ud83c\udfff\u200d♂\ufe0f"] = ":man_shrugging_tone5:", ["\ud83e\udd37\u200d♂\ufe0f"] = ":man_shrugging:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83c\udfa4"] = ":man_singer_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83c\udfa4"] = ":man_singer_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83c\udfa4"] = ":man_singer_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83c\udfa4"] = ":man_singer_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83c\udfa4"] = ":man_singer_tone5:", ["\ud83d\udc68\u200d\ud83c\udfa4"] = ":man_singer:", ["\ud83e\uddcd\ud83c\udffb\u200d♂\ufe0f"] = ":man_standing_tone1:", ["\ud83e\uddcd\ud83c\udffc\u200d♂\ufe0f"] = ":man_standing_tone2:", ["\ud83e\uddcd\ud83c\udffd\u200d♂\ufe0f"] = ":man_standing_tone3:", ["\ud83e\uddcd\ud83c\udffe\u200d♂\ufe0f"] = ":man_standing_tone4:", ["\ud83e\uddcd\ud83c\udfff\u200d♂\ufe0f"] = ":man_standing_tone5:", ["\ud83e\uddcd\u200d♂\ufe0f"] = ":man_standing:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83c\udf93"] = ":man_student_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83c\udf93"] = ":man_student_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83c\udf93"] = ":man_student_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83c\udf93"] = ":man_student_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83c\udf93"] = ":man_student_tone5:", ["\ud83d\udc68\u200d\ud83c\udf93"] = ":man_student:", ["\ud83e\uddb8\ud83c\udffb\u200d♂\ufe0f"] = ":man_superhero_tone1:", ["\ud83e\uddb8\ud83c\udffc\u200d♂\ufe0f"] = ":man_superhero_tone2:", ["\ud83e\uddb8\ud83c\udffd\u200d♂\ufe0f"] = ":man_superhero_tone3:", ["\ud83e\uddb8\ud83c\udffe\u200d♂\ufe0f"] = ":man_superhero_tone4:", ["\ud83e\uddb8\ud83c\udfff\u200d♂\ufe0f"] = ":man_superhero_tone5:", ["\ud83e\uddb8\u200d♂\ufe0f"] = ":man_superhero:", ["\ud83e\uddb9\ud83c\udffb\u200d♂\ufe0f"] = ":man_supervillain_tone1:", ["\ud83e\uddb9\ud83c\udffc\u200d♂\ufe0f"] = ":man_supervillain_tone2:", ["\ud83e\uddb9\ud83c\udffd\u200d♂\ufe0f"] = ":man_supervillain_tone3:", ["\ud83e\uddb9\ud83c\udffe\u200d♂\ufe0f"] = ":man_supervillain_tone4:", ["\ud83e\uddb9\ud83c\udfff\u200d♂\ufe0f"] = ":man_supervillain_tone5:", ["\ud83e\uddb9\u200d♂\ufe0f"] = ":man_supervillain:", ["\ud83c\udfc4\ud83c\udffb\u200d♂\ufe0f"] = ":man_surfing_tone1:", ["\ud83c\udfc4\ud83c\udffc\u200d♂\ufe0f"] = ":man_surfing_tone2:", ["\ud83c\udfc4\ud83c\udffd\u200d♂\ufe0f"] = ":man_surfing_tone3:", ["\ud83c\udfc4\ud83c\udffe\u200d♂\ufe0f"] = ":man_surfing_tone4:", ["\ud83c\udfc4\ud83c\udfff\u200d♂\ufe0f"] = ":man_surfing_tone5:", ["\ud83c\udfc4\u200d♂\ufe0f"] = ":man_surfing:", ["\ud83c\udfca\ud83c\udffb\u200d♂\ufe0f"] = ":man_swimming_tone1:", ["\ud83c\udfca\ud83c\udffc\u200d♂\ufe0f"] = ":man_swimming_tone2:", ["\ud83c\udfca\ud83c\udffd\u200d♂\ufe0f"] = ":man_swimming_tone3:", ["\ud83c\udfca\ud83c\udffe\u200d♂\ufe0f"] = ":man_swimming_tone4:", ["\ud83c\udfca\ud83c\udfff\u200d♂\ufe0f"] = ":man_swimming_tone5:", ["\ud83c\udfca\u200d♂\ufe0f"] = ":man_swimming:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83c\udfeb"] = ":man_teacher_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83c\udfeb"] = ":man_teacher_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83c\udfeb"] = ":man_teacher_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83c\udfeb"] = ":man_teacher_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83c\udfeb"] = ":man_teacher_tone5:", ["\ud83d\udc68\u200d\ud83c\udfeb"] = ":man_teacher:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83d\udcbb"] = ":man_technologist_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83d\udcbb"] = ":man_technologist_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83d\udcbb"] = ":man_technologist_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83d\udcbb"] = ":man_technologist_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83d\udcbb"] = ":man_technologist_tone5:", ["\ud83d\udc68\u200d\ud83d\udcbb"] = ":man_technologist:", ["\ud83d\udc81\ud83c\udffb\u200d♂\ufe0f"] = ":man_tipping_hand_tone1:", ["\ud83d\udc81\ud83c\udffc\u200d♂\ufe0f"] = ":man_tipping_hand_tone2:", ["\ud83d\udc81\ud83c\udffd\u200d♂\ufe0f"] = ":man_tipping_hand_tone3:", ["\ud83d\udc81\ud83c\udffe\u200d♂\ufe0f"] = ":man_tipping_hand_tone4:", ["\ud83d\udc81\ud83c\udfff\u200d♂\ufe0f"] = ":man_tipping_hand_tone5:", ["\ud83d\udc81\u200d♂\ufe0f"] = ":man_tipping_hand:", ["\ud83e\uddd4\ud83c\udffb\u200d♂\ufe0f"] = ":man_tone1_beard:", ["\ud83d\udc68\ud83c\udffb"] = ":man_tone1:", ["\ud83e\uddd4\ud83c\udffc\u200d♂\ufe0f"] = ":man_tone2_beard:", ["\ud83d\udc68\ud83c\udffc"] = ":man_tone2:", ["\ud83e\uddd4\ud83c\udffd\u200d♂\ufe0f"] = ":man_tone3_beard:", ["\ud83d\udc68\ud83c\udffd"] = ":man_tone3:", ["\ud83e\uddd4\ud83c\udffe\u200d♂\ufe0f"] = ":man_tone4_beard:", ["\ud83d\udc68\ud83c\udffe"] = ":man_tone4:", ["\ud83e\uddd4\ud83c\udfff\u200d♂\ufe0f"] = ":man_tone5_beard:", ["\ud83d\udc68\ud83c\udfff"] = ":man_tone5:", ["\ud83e\udddb\ud83c\udffb\u200d♂\ufe0f"] = ":man_vampire_tone1:", ["\ud83e\udddb\ud83c\udffc\u200d♂\ufe0f"] = ":man_vampire_tone2:", ["\ud83e\udddb\ud83c\udffd\u200d♂\ufe0f"] = ":man_vampire_tone3:", ["\ud83e\udddb\ud83c\udffe\u200d♂\ufe0f"] = ":man_vampire_tone4:", ["\ud83e\udddb\ud83c\udfff\u200d♂\ufe0f"] = ":man_vampire_tone5:", ["\ud83e\udddb\u200d♂\ufe0f"] = ":man_vampire:", ["\ud83d\udeb6\ud83c\udffb\u200d♂\ufe0f"] = ":man_walking_tone1:", ["\ud83d\udeb6\ud83c\udffc\u200d♂\ufe0f"] = ":man_walking_tone2:", ["\ud83d\udeb6\ud83c\udffd\u200d♂\ufe0f"] = ":man_walking_tone3:", ["\ud83d\udeb6\ud83c\udffe\u200d♂\ufe0f"] = ":man_walking_tone4:", ["\ud83d\udeb6\ud83c\udfff\u200d♂\ufe0f"] = ":man_walking_tone5:", ["\ud83d\udeb6\u200d♂\ufe0f"] = ":man_walking:", ["\ud83d\udc73\ud83c\udffb\u200d♂\ufe0f"] = ":man_wearing_turban_tone1:", ["\ud83d\udc73\ud83c\udffc\u200d♂\ufe0f"] = ":man_wearing_turban_tone2:", ["\ud83d\udc73\ud83c\udffd\u200d♂\ufe0f"] = ":man_wearing_turban_tone3:", ["\ud83d\udc73\ud83c\udffe\u200d♂\ufe0f"] = ":man_wearing_turban_tone4:", ["\ud83d\udc73\ud83c\udfff\u200d♂\ufe0f"] = ":man_wearing_turban_tone5:", ["\ud83d\udc73\u200d♂\ufe0f"] = ":man_wearing_turban:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83e\uddb3"] = ":man_white_haired_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83e\uddb3"] = ":man_white_haired_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83e\uddb3"] = ":man_white_haired_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83e\uddb3"] = ":man_white_haired_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83e\uddb3"] = ":man_white_haired_tone5:", ["\ud83d\udc68\u200d\ud83e\uddb3"] = ":man_white_haired:", ["\ud83d\udc72\ud83c\udffb"] = ":man_with_chinese_cap_tone1:", ["\ud83d\udc72\ud83c\udffc"] = ":man_with_chinese_cap_tone2:", ["\ud83d\udc72\ud83c\udffd"] = ":man_with_chinese_cap_tone3:", ["\ud83d\udc72\ud83c\udffe"] = ":man_with_chinese_cap_tone4:", ["\ud83d\udc72\ud83c\udfff"] = ":man_with_chinese_cap_tone5:", ["\ud83d\udc72"] = ":man_with_chinese_cap:", ["\ud83d\udc68\ud83c\udffb\u200d\ud83e\uddaf"] = ":man_with_probing_cane_tone1:", ["\ud83d\udc68\ud83c\udffc\u200d\ud83e\uddaf"] = ":man_with_probing_cane_tone2:", ["\ud83d\udc68\ud83c\udffd\u200d\ud83e\uddaf"] = ":man_with_probing_cane_tone3:", ["\ud83d\udc68\ud83c\udffe\u200d\ud83e\uddaf"] = ":man_with_probing_cane_tone4:", ["\ud83d\udc68\ud83c\udfff\u200d\ud83e\uddaf"] = ":man_with_probing_cane_tone5:", ["\ud83d\udc68\u200d\ud83e\uddaf"] = ":man_with_probing_cane:", ["\ud83d\udc70\ud83c\udffb\u200d♂\ufe0f"] = ":man_with_veil_tone1:", ["\ud83d\udc70\ud83c\udffc\u200d♂\ufe0f"] = ":man_with_veil_tone2:", ["\ud83d\udc70\ud83c\udffd\u200d♂\ufe0f"] = ":man_with_veil_tone3:", ["\ud83d\udc70\ud83c\udffe\u200d♂\ufe0f"] = ":man_with_veil_tone4:", ["\ud83d\udc70\ud83c\udfff\u200d♂\ufe0f"] = ":man_with_veil_tone5:", ["\ud83d\udc70\u200d♂\ufe0f"] = ":man_with_veil:", ["\ud83e\udddf\u200d♂\ufe0f"] = ":man_zombie:", ["\ud83d\udc68"] = ":man:", ["\ud83e\udd6d"] = ":mango:", ["\ud83d\udc5e"] = ":mans_shoe:", ["\ud83e\uddbd"] = ":manual_wheelchair:", ["\ud83d\uddfa\ufe0f"] = ":map:", ["\ud83d\uddfa"] = ":map:", ["\ud83c\udf41"] = ":maple_leaf:", ["\ud83e\udd4b"] = ":martial_arts_uniform:", ["\ud83d\ude37"] = ":mask:", ["\ud83e\uddc9"] = ":mate:", ["\ud83c\udf56"] = ":meat_on_bone:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83d\udd27"] = ":mechanic_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83d\udd27"] = ":mechanic_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83d\udd27"] = ":mechanic_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83d\udd27"] = ":mechanic_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83d\udd27"] = ":mechanic_tone5:", ["\ud83e\uddd1\u200d\ud83d\udd27"] = ":mechanic:", ["\ud83e\uddbe"] = ":mechanical_arm:", ["\ud83e\uddbf"] = ":mechanical_leg:", ["\ud83c\udfc5"] = ":medal:", ["⚕\ufe0f"] = ":medical_symbol:", ["⚕"] = ":medical_symbol:", ["\ud83d\udce3"] = ":mega:", ["\ud83c\udf48"] = ":melon:", ["\ud83e\udee0"] = ":melting_face:", ["\ud83d\udc6f\u200d♂\ufe0f"] = ":men_with_bunny_ears_partying:", ["\ud83e\udd3c\u200d♂\ufe0f"] = ":men_wrestling:", ["❤\ufe0f\u200d\ud83e\ude79"] = ":mending_heart:", ["\ud83d\udd4e"] = ":menorah:", ["\ud83d\udeb9"] = ":mens:", ["\ud83e\udddc\ud83c\udffb\u200d♀\ufe0f"] = ":mermaid_tone1:", ["\ud83e\udddc\ud83c\udffc\u200d♀\ufe0f"] = ":mermaid_tone2:", ["\ud83e\udddc\ud83c\udffd\u200d♀\ufe0f"] = ":mermaid_tone3:", ["\ud83e\udddc\ud83c\udffe\u200d♀\ufe0f"] = ":mermaid_tone4:", ["\ud83e\udddc\ud83c\udfff\u200d♀\ufe0f"] = ":mermaid_tone5:", ["\ud83e\udddc\u200d♀\ufe0f"] = ":mermaid:", ["\ud83e\udddc\ud83c\udffb\u200d♂\ufe0f"] = ":merman_tone1:", ["\ud83e\udddc\ud83c\udffc\u200d♂\ufe0f"] = ":merman_tone2:", ["\ud83e\udddc\ud83c\udffd\u200d♂\ufe0f"] = ":merman_tone3:", ["\ud83e\udddc\ud83c\udffe\u200d♂\ufe0f"] = ":merman_tone4:", ["\ud83e\udddc\ud83c\udfff\u200d♂\ufe0f"] = ":merman_tone5:", ["\ud83e\udddc\u200d♂\ufe0f"] = ":merman:", ["\ud83e\udddc\ud83c\udffb"] = ":merperson_tone1:", ["\ud83e\udddc\ud83c\udffc"] = ":merperson_tone2:", ["\ud83e\udddc\ud83c\udffd"] = ":merperson_tone3:", ["\ud83e\udddc\ud83c\udffe"] = ":merperson_tone4:", ["\ud83e\udddc\ud83c\udfff"] = ":merperson_tone5:", ["\ud83e\udddc"] = ":merperson:", ["\ud83e\udd18\ud83c\udffb"] = ":metal_tone1:", ["\ud83e\udd18\ud83c\udffc"] = ":metal_tone2:", ["\ud83e\udd18\ud83c\udffd"] = ":metal_tone3:", ["\ud83e\udd18\ud83c\udffe"] = ":metal_tone4:", ["\ud83e\udd18\ud83c\udfff"] = ":metal_tone5:", ["\ud83e\udd18"] = ":metal:", ["\ud83d\ude87"] = ":metro:", ["\ud83e\udda0"] = ":microbe:", ["\ud83c\udfa4"] = ":microphone:", ["\ud83c\udf99\ufe0f"] = ":microphone2:", ["\ud83c\udf99"] = ":microphone2:", ["\ud83d\udd2c"] = ":microscope:", ["\ud83d\udd95\ud83c\udffb"] = ":middle_finger_tone1:", ["\ud83d\udd95\ud83c\udffc"] = ":middle_finger_tone2:", ["\ud83d\udd95\ud83c\udffd"] = ":middle_finger_tone3:", ["\ud83d\udd95\ud83c\udffe"] = ":middle_finger_tone4:", ["\ud83d\udd95\ud83c\udfff"] = ":middle_finger_tone5:", ["\ud83d\udd95"] = ":middle_finger:", ["\ud83e\ude96"] = ":military_helmet:", ["\ud83c\udf96\ufe0f"] = ":military_medal:", ["\ud83c\udf96"] = ":military_medal:", ["\ud83e\udd5b"] = ":milk:", ["\ud83c\udf0c"] = ":milky_way:", ["\ud83d\ude90"] = ":minibus:", ["\ud83d\udcbd"] = ":minidisc:", ["\ud83e\udea9"] = ":mirror_ball:", ["\ud83e\ude9e"] = ":mirror:", ["\ud83d\udcf4"] = ":mobile_phone_off:", ["\ud83d\udcf1"] = ":mobile_phone:", ["\ud83e\udd11"] = ":money_mouth:", ["\ud83d\udcb8"] = ":money_with_wings:", ["\ud83d\udcb0"] = ":moneybag:", ["\ud83d\udc35"] = ":monkey_face:", ["\ud83d\udc12"] = ":monkey:", ["\ud83d\ude9d"] = ":monorail:", ["\ud83e\udd6e"] = ":moon_cake:", ["\ud83c\udf93"] = ":mortar_board:", ["\ud83d\udd4c"] = ":mosque:", ["\ud83e\udd9f"] = ":mosquito:", ["\ud83d\udef5"] = ":motor_scooter:", ["\ud83d\udee5\ufe0f"] = ":motorboat:", ["\ud83d\udee5"] = ":motorboat:", ["\ud83c\udfcd\ufe0f"] = ":motorcycle:", ["\ud83c\udfcd"] = ":motorcycle:", ["\ud83e\uddbc"] = ":motorized_wheelchair:", ["\ud83d\udee3\ufe0f"] = ":motorway:", ["\ud83d\udee3"] = ":motorway:", ["\ud83d\uddfb"] = ":mount_fuji:", ["\ud83d\udea0"] = ":mountain_cableway:", ["\ud83d\ude9e"] = ":mountain_railway:", ["\ud83c\udfd4\ufe0f"] = ":mountain_snow:", ["\ud83c\udfd4"] = ":mountain_snow:", ["⛰\ufe0f"] = ":mountain:", ["⛰"] = ":mountain:", ["\ud83d\uddb1\ufe0f"] = ":mouse_three_button:", ["\ud83d\uddb1"] = ":mouse_three_button:", ["\ud83e\udea4"] = ":mouse_trap:", ["\ud83d\udc2d"] = ":mouse:", ["\ud83d\udc01"] = ":mouse2:", ["\ud83c\udfa5"] = ":movie_camera:", ["\ud83d\uddff"] = ":moyai:", ["\ud83e\udd36\ud83c\udffb"] = ":mrs_claus_tone1:", ["\ud83e\udd36\ud83c\udffc"] = ":mrs_claus_tone2:", ["\ud83e\udd36\ud83c\udffd"] = ":mrs_claus_tone3:", ["\ud83e\udd36\ud83c\udffe"] = ":mrs_claus_tone4:", ["\ud83e\udd36\ud83c\udfff"] = ":mrs_claus_tone5:", ["\ud83e\udd36"] = ":mrs_claus:", ["\ud83d\udcaa\ud83c\udffb"] = ":muscle_tone1:", ["\ud83d\udcaa\ud83c\udffc"] = ":muscle_tone2:", ["\ud83d\udcaa\ud83c\udffd"] = ":muscle_tone3:", ["\ud83d\udcaa\ud83c\udffe"] = ":muscle_tone4:", ["\ud83d\udcaa\ud83c\udfff"] = ":muscle_tone5:", ["\ud83d\udcaa"] = ":muscle:", ["\ud83c\udf44"] = ":mushroom:", ["\ud83c\udfb9"] = ":musical_keyboard:", ["\ud83c\udfb5"] = ":musical_note:", ["\ud83c\udfbc"] = ":musical_score:", ["\ud83d\udd07"] = ":mute:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udf84"] = ":mx_claus_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udf84"] = ":mx_claus_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udf84"] = ":mx_claus_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udf84"] = ":mx_claus_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udf84"] = ":mx_claus_tone5:", ["\ud83e\uddd1\u200d\ud83c\udf84"] = ":mx_claus:", ["\ud83d\udc85\ud83c\udffb"] = ":nail_care_tone1:", ["\ud83d\udc85\ud83c\udffc"] = ":nail_care_tone2:", ["\ud83d\udc85\ud83c\udffd"] = ":nail_care_tone3:", ["\ud83d\udc85\ud83c\udffe"] = ":nail_care_tone4:", ["\ud83d\udc85\ud83c\udfff"] = ":nail_care_tone5:", ["\ud83d\udc85"] = ":nail_care:", ["\ud83d\udcdb"] = ":name_badge:", ["\ud83e\udd22"] = ":nauseated_face:", ["\ud83e\uddff"] = ":nazar_amulet:", ["\ud83d\udc54"] = ":necktie:", ["❎"] = ":negative_squared_cross_mark:", ["\ud83e\udd13"] = ":nerd:", ["\ud83e\udeba"] = ":nest_with_eggs:", ["\ud83e\ude86"] = ":nesting_dolls:", ["\ud83d\ude10"] = ":neutral_face:", ["\ud83c\udf1a"] = ":new_moon_with_face:", ["\ud83c\udf11"] = ":new_moon:", ["\ud83c\udd95"] = ":new:", ["\ud83d\udcf0"] = ":newspaper:", ["\ud83d\uddde\ufe0f"] = ":newspaper2:", ["\ud83d\uddde"] = ":newspaper2:", ["\ud83c\udd96"] = ":ng:", ["\ud83c\udf03"] = ":night_with_stars:", ["9\ufe0f\u20e3"] = ":nine:", ["9\u20e3"] = ":nine:", ["\ud83e\udd77\ud83c\udffb"] = ":ninja_tone1:", ["\ud83e\udd77\ud83c\udffc"] = ":ninja_tone2:", ["\ud83e\udd77\ud83c\udffd"] = ":ninja_tone3:", ["\ud83e\udd77\ud83c\udffe"] = ":ninja_tone4:", ["\ud83e\udd77\ud83c\udfff"] = ":ninja_tone5:", ["\ud83e\udd77"] = ":ninja:", ["\ud83d\udd15"] = ":no_bell:", ["\ud83d\udeb3"] = ":no_bicycles:", ["\ud83d\udeab"] = ":no_entry_sign:", ["⛔"] = ":no_entry:", ["\ud83d\udcf5"] = ":no_mobile_phones:", ["\ud83d\ude36"] = ":no_mouth:", ["\ud83d\udeb7"] = ":no_pedestrians:", ["\ud83d\udead"] = ":no_smoking:", ["\ud83d\udeb1"] = ":non_potable_water:", ["\ud83d\udc43\ud83c\udffb"] = ":nose_tone1:", ["\ud83d\udc43\ud83c\udffc"] = ":nose_tone2:", ["\ud83d\udc43\ud83c\udffd"] = ":nose_tone3:", ["\ud83d\udc43\ud83c\udffe"] = ":nose_tone4:", ["\ud83d\udc43\ud83c\udfff"] = ":nose_tone5:", ["\ud83d\udc43"] = ":nose:", ["\ud83d\udcd4"] = ":notebook_with_decorative_cover:", ["\ud83d\udcd3"] = ":notebook:", ["\ud83d\uddd2\ufe0f"] = ":notepad_spiral:", ["\ud83d\uddd2"] = ":notepad_spiral:", ["\ud83c\udfb6"] = ":notes:", ["\ud83d\udd29"] = ":nut_and_bolt:", ["⭕"] = ":o:", ["\ud83c\udd7e\ufe0f"] = ":o2:", ["\ud83c\udd7e"] = ":o2:", ["\ud83c\udf0a"] = ":ocean:", ["\ud83d\uded1"] = ":octagonal_sign:", ["\ud83d\udc19"] = ":octopus:", ["\ud83c\udf62"] = ":oden:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83d\udcbc"] = ":office_worker_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83d\udcbc"] = ":office_worker_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83d\udcbc"] = ":office_worker_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83d\udcbc"] = ":office_worker_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83d\udcbc"] = ":office_worker_tone5:", ["\ud83e\uddd1\u200d\ud83d\udcbc"] = ":office_worker:", ["\ud83c\udfe2"] = ":office:", ["\ud83d\udee2\ufe0f"] = ":oil:", ["\ud83d\udee2"] = ":oil:", ["\ud83d\udc4c\ud83c\udffb"] = ":ok_hand_tone1:", ["\ud83d\udc4c\ud83c\udffc"] = ":ok_hand_tone2:", ["\ud83d\udc4c\ud83c\udffd"] = ":ok_hand_tone3:", ["\ud83d\udc4c\ud83c\udffe"] = ":ok_hand_tone4:", ["\ud83d\udc4c\ud83c\udfff"] = ":ok_hand_tone5:", ["\ud83d\udc4c"] = ":ok_hand:", ["\ud83c\udd97"] = ":ok:", ["\ud83e\uddd3\ud83c\udffb"] = ":older_adult_tone1:", ["\ud83e\uddd3\ud83c\udffc"] = ":older_adult_tone2:", ["\ud83e\uddd3\ud83c\udffd"] = ":older_adult_tone3:", ["\ud83e\uddd3\ud83c\udffe"] = ":older_adult_tone4:", ["\ud83e\uddd3\ud83c\udfff"] = ":older_adult_tone5:", ["\ud83e\uddd3"] = ":older_adult:", ["\ud83d\udc74\ud83c\udffb"] = ":older_man_tone1:", ["\ud83d\udc74\ud83c\udffc"] = ":older_man_tone2:", ["\ud83d\udc74\ud83c\udffd"] = ":older_man_tone3:", ["\ud83d\udc74\ud83c\udffe"] = ":older_man_tone4:", ["\ud83d\udc74\ud83c\udfff"] = ":older_man_tone5:", ["\ud83d\udc74"] = ":older_man:", ["\ud83d\udc75\ud83c\udffb"] = ":older_woman_tone1:", ["\ud83d\udc75\ud83c\udffc"] = ":older_woman_tone2:", ["\ud83d\udc75\ud83c\udffd"] = ":older_woman_tone3:", ["\ud83d\udc75\ud83c\udffe"] = ":older_woman_tone4:", ["\ud83d\udc75\ud83c\udfff"] = ":older_woman_tone5:", ["\ud83d\udc75"] = ":older_woman:", ["\ud83e\uded2"] = ":olive:", ["\ud83d\udd49\ufe0f"] = ":om_symbol:", ["\ud83d\udd49"] = ":om_symbol:", ["\ud83d\udd1b"] = ":on:", ["\ud83d\ude98"] = ":oncoming_automobile:", ["\ud83d\ude8d"] = ":oncoming_bus:", ["\ud83d\ude94"] = ":oncoming_police_car:", ["\ud83d\ude96"] = ":oncoming_taxi:", ["\ud83e\ude71"] = ":one_piece_swimsuit:", ["1\ufe0f\u20e3"] = ":one:", ["1\u20e3"] = ":one:", ["\ud83e\uddc5"] = ":onion:", ["\ud83d\udcc2"] = ":open_file_folder:", ["\ud83d\udc50\ud83c\udffb"] = ":open_hands_tone1:", ["\ud83d\udc50\ud83c\udffc"] = ":open_hands_tone2:", ["\ud83d\udc50\ud83c\udffd"] = ":open_hands_tone3:", ["\ud83d\udc50\ud83c\udffe"] = ":open_hands_tone4:", ["\ud83d\udc50\ud83c\udfff"] = ":open_hands_tone5:", ["\ud83d\udc50"] = ":open_hands:", ["\ud83d\ude2e"] = ":open_mouth:", ["⛎"] = ":ophiuchus:", ["\ud83d\udcd9"] = ":orange_book:", ["\ud83d\udfe0"] = ":orange_circle:", ["\ud83e\udde1"] = ":orange_heart:", ["\ud83d\udfe7"] = ":orange_square:", ["\ud83e\udda7"] = ":orangutan:", ["☦\ufe0f"] = ":orthodox_cross:", ["☦"] = ":orthodox_cross:", ["\ud83e\udda6"] = ":otter:", ["\ud83d\udce4"] = ":outbox_tray:", ["\ud83e\udd89"] = ":owl:", ["\ud83d\udc02"] = ":ox:", ["\ud83e\uddaa"] = ":oyster:", ["\ud83d\udce6"] = ":package:", ["\ud83d\udcc4"] = ":page_facing_up:", ["\ud83d\udcc3"] = ":page_with_curl:", ["\ud83d\udcdf"] = ":pager:", ["\ud83d\udd8c\ufe0f"] = ":paintbrush:", ["\ud83d\udd8c"] = ":paintbrush:", ["\ud83e\udef3\ud83c\udffb"] = ":palm_down_hand_tone1:", ["\ud83e\udef3\ud83c\udffc"] = ":palm_down_hand_tone2:", ["\ud83e\udef3\ud83c\udffd"] = ":palm_down_hand_tone3:", ["\ud83e\udef3\ud83c\udffe"] = ":palm_down_hand_tone4:", ["\ud83e\udef3\ud83c\udfff"] = ":palm_down_hand_tone5:", ["\ud83e\udef3"] = ":palm_down_hand:", ["\ud83c\udf34"] = ":palm_tree:", ["\ud83e\udef4\ud83c\udffb"] = ":palm_up_hand_tone1:", ["\ud83e\udef4\ud83c\udffc"] = ":palm_up_hand_tone2:", ["\ud83e\udef4\ud83c\udffd"] = ":palm_up_hand_tone3:", ["\ud83e\udef4\ud83c\udffe"] = ":palm_up_hand_tone4:", ["\ud83e\udef4\ud83c\udfff"] = ":palm_up_hand_tone5:", ["\ud83e\udef4"] = ":palm_up_hand:", ["\ud83e\udd32\ud83c\udffb"] = ":palms_up_together_tone1:", ["\ud83e\udd32\ud83c\udffc"] = ":palms_up_together_tone2:", ["\ud83e\udd32\ud83c\udffd"] = ":palms_up_together_tone3:", ["\ud83e\udd32\ud83c\udffe"] = ":palms_up_together_tone4:", ["\ud83e\udd32\ud83c\udfff"] = ":palms_up_together_tone5:", ["\ud83e\udd32"] = ":palms_up_together:", ["\ud83e\udd5e"] = ":pancakes:", ["\ud83d\udc3c"] = ":panda_face:", ["\ud83d\udcce"] = ":paperclip:", ["\ud83d\udd87\ufe0f"] = ":paperclips:", ["\ud83d\udd87"] = ":paperclips:", ["\ud83e\ude82"] = ":parachute:", ["\ud83c\udfde\ufe0f"] = ":park:", ["\ud83c\udfde"] = ":park:", ["\ud83c\udd7f\ufe0f"] = ":parking:", ["\ud83c\udd7f"] = ":parking:", ["\ud83e\udd9c"] = ":parrot:", ["〽\ufe0f"] = ":part_alternation_mark:", ["〽"] = ":part_alternation_mark:", ["⛅"] = ":partly_sunny:", ["\ud83e\udd73"] = ":partying_face:", ["\ud83d\udec2"] = ":passport_control:", ["⏸\ufe0f"] = ":pause_button:", ["⏸"] = ":pause_button:", ["☮\ufe0f"] = ":peace:", ["☮"] = ":peace:", ["\ud83c\udf51"] = ":peach:", ["\ud83e\udd9a"] = ":peacock:", ["\ud83e\udd5c"] = ":peanuts:", ["\ud83c\udf50"] = ":pear:", ["\ud83d\udd8a\ufe0f"] = ":pen_ballpoint:", ["\ud83d\udd8a"] = ":pen_ballpoint:", ["\ud83d\udd8b\ufe0f"] = ":pen_fountain:", ["\ud83d\udd8b"] = ":pen_fountain:", ["\ud83d\udcdd"] = ":pencil:", ["✏\ufe0f"] = ":pencil2:", ["✏"] = ":pencil2:", ["\ud83d\udc27"] = ":penguin:", ["\ud83d\ude14"] = ":pensive:", ["\ud83e\uddd1\u200d\ud83e\udd1d\u200d\ud83e\uddd1"] = ":people_holding_hands_tone5_tone4:", ["\ud83e\udec2"] = ":people_hugging:", ["\ud83d\udc6f"] = ":people_with_bunny_ears_partying:", ["\ud83e\udd3c"] = ":people_wrestling:", ["\ud83c\udfad"] = ":performing_arts:", ["\ud83d\ude23"] = ":persevere:", ["\ud83e\uddd1\u200d\ud83e\uddb2"] = ":person_bald:", ["\ud83d\udeb4\ud83c\udffb"] = ":person_biking_tone1:", ["\ud83d\udeb4\ud83c\udffc"] = ":person_biking_tone2:", ["\ud83d\udeb4\ud83c\udffd"] = ":person_biking_tone3:", ["\ud83d\udeb4\ud83c\udffe"] = ":person_biking_tone4:", ["\ud83d\udeb4\ud83c\udfff"] = ":person_biking_tone5:", ["\ud83d\udeb4"] = ":person_biking:", ["⛹\ud83c\udffb"] = ":person_bouncing_ball_tone1:", ["⛹\ud83c\udffc"] = ":person_bouncing_ball_tone2:", ["⛹\ud83c\udffd"] = ":person_bouncing_ball_tone3:", ["⛹\ud83c\udffe"] = ":person_bouncing_ball_tone4:", ["⛹\ud83c\udfff"] = ":person_bouncing_ball_tone5:", ["⛹\ufe0f"] = ":person_bouncing_ball:", ["⛹"] = ":person_bouncing_ball:", ["\ud83d\ude47\ud83c\udffb"] = ":person_bowing_tone1:", ["\ud83d\ude47\ud83c\udffc"] = ":person_bowing_tone2:", ["\ud83d\ude47\ud83c\udffd"] = ":person_bowing_tone3:", ["\ud83d\ude47\ud83c\udffe"] = ":person_bowing_tone4:", ["\ud83d\ude47\ud83c\udfff"] = ":person_bowing_tone5:", ["\ud83d\ude47"] = ":person_bowing:", ["\ud83e\uddd7\ud83c\udffb"] = ":person_climbing_tone1:", ["\ud83e\uddd7\ud83c\udffc"] = ":person_climbing_tone2:", ["\ud83e\uddd7\ud83c\udffd"] = ":person_climbing_tone3:", ["\ud83e\uddd7\ud83c\udffe"] = ":person_climbing_tone4:", ["\ud83e\uddd7\ud83c\udfff"] = ":person_climbing_tone5:", ["\ud83e\uddd7"] = ":person_climbing:", ["\ud83e\uddd1\u200d\ud83e\uddb1"] = ":person_curly_hair:", ["\ud83e\udd38\ud83c\udffb"] = ":person_doing_cartwheel_tone1:", ["\ud83e\udd38\ud83c\udffc"] = ":person_doing_cartwheel_tone2:", ["\ud83e\udd38\ud83c\udffd"] = ":person_doing_cartwheel_tone3:", ["\ud83e\udd38\ud83c\udffe"] = ":person_doing_cartwheel_tone4:", ["\ud83e\udd38\ud83c\udfff"] = ":person_doing_cartwheel_tone5:", ["\ud83e\udd38"] = ":person_doing_cartwheel:", ["\ud83e\udd26\ud83c\udffb"] = ":person_facepalming_tone1:", ["\ud83e\udd26\ud83c\udffc"] = ":person_facepalming_tone2:", ["\ud83e\udd26\ud83c\udffd"] = ":person_facepalming_tone3:", ["\ud83e\udd26\ud83c\udffe"] = ":person_facepalming_tone4:", ["\ud83e\udd26\ud83c\udfff"] = ":person_facepalming_tone5:", ["\ud83e\udd26"] = ":person_facepalming:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udf7c"] = ":person_feeding_baby_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udf7c"] = ":person_feeding_baby_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udf7c"] = ":person_feeding_baby_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udf7c"] = ":person_feeding_baby_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udf7c"] = ":person_feeding_baby_tone5:", ["\ud83e\uddd1\u200d\ud83c\udf7c"] = ":person_feeding_baby:", ["\ud83e\udd3a"] = ":person_fencing:", ["\ud83d\ude4d\ud83c\udffb"] = ":person_frowning_tone1:", ["\ud83d\ude4d\ud83c\udffc"] = ":person_frowning_tone2:", ["\ud83d\ude4d\ud83c\udffd"] = ":person_frowning_tone3:", ["\ud83d\ude4d\ud83c\udffe"] = ":person_frowning_tone4:", ["\ud83d\ude4d\ud83c\udfff"] = ":person_frowning_tone5:", ["\ud83d\ude4d"] = ":person_frowning:", ["\ud83d\ude45\ud83c\udffb"] = ":person_gesturing_no_tone1:", ["\ud83d\ude45\ud83c\udffc"] = ":person_gesturing_no_tone2:", ["\ud83d\ude45\ud83c\udffd"] = ":person_gesturing_no_tone3:", ["\ud83d\ude45\ud83c\udffe"] = ":person_gesturing_no_tone4:", ["\ud83d\ude45\ud83c\udfff"] = ":person_gesturing_no_tone5:", ["\ud83d\ude45"] = ":person_gesturing_no:", ["\ud83d\ude46\ud83c\udffb"] = ":person_gesturing_ok_tone1:", ["\ud83d\ude46\ud83c\udffc"] = ":person_gesturing_ok_tone2:", ["\ud83d\ude46\ud83c\udffd"] = ":person_gesturing_ok_tone3:", ["\ud83d\ude46\ud83c\udffe"] = ":person_gesturing_ok_tone4:", ["\ud83d\ude46\ud83c\udfff"] = ":person_gesturing_ok_tone5:", ["\ud83d\ude46"] = ":person_gesturing_ok:", ["\ud83d\udc87\ud83c\udffb"] = ":person_getting_haircut_tone1:", ["\ud83d\udc87\ud83c\udffc"] = ":person_getting_haircut_tone2:", ["\ud83d\udc87\ud83c\udffd"] = ":person_getting_haircut_tone3:", ["\ud83d\udc87\ud83c\udffe"] = ":person_getting_haircut_tone4:", ["\ud83d\udc87\ud83c\udfff"] = ":person_getting_haircut_tone5:", ["\ud83d\udc87"] = ":person_getting_haircut:", ["\ud83d\udc86\ud83c\udffb"] = ":person_getting_massage_tone1:", ["\ud83d\udc86\ud83c\udffc"] = ":person_getting_massage_tone2:", ["\ud83d\udc86\ud83c\udffd"] = ":person_getting_massage_tone3:", ["\ud83d\udc86\ud83c\udffe"] = ":person_getting_massage_tone4:", ["\ud83d\udc86\ud83c\udfff"] = ":person_getting_massage_tone5:", ["\ud83d\udc86"] = ":person_getting_massage:", ["\ud83c\udfcc\ud83c\udffb"] = ":person_golfing_tone1:", ["\ud83c\udfcc\ud83c\udffc"] = ":person_golfing_tone2:", ["\ud83c\udfcc\ud83c\udffd"] = ":person_golfing_tone3:", ["\ud83c\udfcc\ud83c\udffe"] = ":person_golfing_tone4:", ["\ud83c\udfcc\ud83c\udfff"] = ":person_golfing_tone5:", ["\ud83c\udfcc\ufe0f"] = ":person_golfing:", ["\ud83c\udfcc"] = ":person_golfing:", ["\ud83d\udecc\ud83c\udffb"] = ":person_in_bed_tone1:", ["\ud83d\udecc\ud83c\udffc"] = ":person_in_bed_tone2:", ["\ud83d\udecc\ud83c\udffd"] = ":person_in_bed_tone3:", ["\ud83d\udecc\ud83c\udffe"] = ":person_in_bed_tone4:", ["\ud83d\udecc\ud83c\udfff"] = ":person_in_bed_tone5:", ["\ud83e\uddd8\ud83c\udffb"] = ":person_in_lotus_position_tone1:", ["\ud83e\uddd8\ud83c\udffc"] = ":person_in_lotus_position_tone2:", ["\ud83e\uddd8\ud83c\udffd"] = ":person_in_lotus_position_tone3:", ["\ud83e\uddd8\ud83c\udffe"] = ":person_in_lotus_position_tone4:", ["\ud83e\uddd8\ud83c\udfff"] = ":person_in_lotus_position_tone5:", ["\ud83e\uddd8"] = ":person_in_lotus_position:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83e\uddbd"] = ":person_in_manual_wheelchair_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83e\uddbd"] = ":person_in_manual_wheelchair_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83e\uddbd"] = ":person_in_manual_wheelchair_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83e\uddbd"] = ":person_in_manual_wheelchair_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83e\uddbd"] = ":person_in_manual_wheelchair_tone5:", ["\ud83e\uddd1\u200d\ud83e\uddbd"] = ":person_in_manual_wheelchair:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83e\uddbc"] = ":person_in_motorized_wheelchair_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83e\uddbc"] = ":person_in_motorized_wheelchair_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83e\uddbc"] = ":person_in_motorized_wheelchair_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83e\uddbc"] = ":person_in_motorized_wheelchair_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83e\uddbc"] = ":person_in_motorized_wheelchair_tone5:", ["\ud83e\uddd1\u200d\ud83e\uddbc"] = ":person_in_motorized_wheelchair:", ["\ud83e\uddd6\ud83c\udffb"] = ":person_in_steamy_room_tone1:", ["\ud83e\uddd6\ud83c\udffc"] = ":person_in_steamy_room_tone2:", ["\ud83e\uddd6\ud83c\udffd"] = ":person_in_steamy_room_tone3:", ["\ud83e\uddd6\ud83c\udffe"] = ":person_in_steamy_room_tone4:", ["\ud83e\uddd6\ud83c\udfff"] = ":person_in_steamy_room_tone5:", ["\ud83e\uddd6"] = ":person_in_steamy_room:", ["\ud83e\udd35\ud83c\udffb"] = ":person_in_tuxedo_tone1:", ["\ud83e\udd35\ud83c\udffc"] = ":person_in_tuxedo_tone2:", ["\ud83e\udd35\ud83c\udffd"] = ":person_in_tuxedo_tone3:", ["\ud83e\udd35\ud83c\udffe"] = ":person_in_tuxedo_tone4:", ["\ud83e\udd35\ud83c\udfff"] = ":person_in_tuxedo_tone5:", ["\ud83e\udd35"] = ":person_in_tuxedo:", ["\ud83e\udd39\ud83c\udffb"] = ":person_juggling_tone1:", ["\ud83e\udd39\ud83c\udffc"] = ":person_juggling_tone2:", ["\ud83e\udd39\ud83c\udffd"] = ":person_juggling_tone3:", ["\ud83e\udd39\ud83c\udffe"] = ":person_juggling_tone4:", ["\ud83e\udd39\ud83c\udfff"] = ":person_juggling_tone5:", ["\ud83e\udd39"] = ":person_juggling:", ["\ud83e\uddce\ud83c\udffb"] = ":person_kneeling_tone1:", ["\ud83e\uddce\ud83c\udffc"] = ":person_kneeling_tone2:", ["\ud83e\uddce\ud83c\udffd"] = ":person_kneeling_tone3:", ["\ud83e\uddce\ud83c\udffe"] = ":person_kneeling_tone4:", ["\ud83e\uddce\ud83c\udfff"] = ":person_kneeling_tone5:", ["\ud83e\uddce"] = ":person_kneeling:", ["\ud83c\udfcb\ud83c\udffb"] = ":person_lifting_weights_tone1:", ["\ud83c\udfcb\ud83c\udffc"] = ":person_lifting_weights_tone2:", ["\ud83c\udfcb\ud83c\udffd"] = ":person_lifting_weights_tone3:", ["\ud83c\udfcb\ud83c\udffe"] = ":person_lifting_weights_tone4:", ["\ud83c\udfcb\ud83c\udfff"] = ":person_lifting_weights_tone5:", ["\ud83c\udfcb\ufe0f"] = ":person_lifting_weights:", ["\ud83c\udfcb"] = ":person_lifting_weights:", ["\ud83d\udeb5\ud83c\udffb"] = ":person_mountain_biking_tone1:", ["\ud83d\udeb5\ud83c\udffc"] = ":person_mountain_biking_tone2:", ["\ud83d\udeb5\ud83c\udffd"] = ":person_mountain_biking_tone3:", ["\ud83d\udeb5\ud83c\udffe"] = ":person_mountain_biking_tone4:", ["\ud83d\udeb5\ud83c\udfff"] = ":person_mountain_biking_tone5:", ["\ud83d\udeb5"] = ":person_mountain_biking:", ["\ud83e\udd3e\ud83c\udffb"] = ":person_playing_handball_tone1:", ["\ud83e\udd3e\ud83c\udffc"] = ":person_playing_handball_tone2:", ["\ud83e\udd3e\ud83c\udffd"] = ":person_playing_handball_tone3:", ["\ud83e\udd3e\ud83c\udffe"] = ":person_playing_handball_tone4:", ["\ud83e\udd3e\ud83c\udfff"] = ":person_playing_handball_tone5:", ["\ud83e\udd3e"] = ":person_playing_handball:", ["\ud83e\udd3d\ud83c\udffb"] = ":person_playing_water_polo_tone1:", ["\ud83e\udd3d\ud83c\udffc"] = ":person_playing_water_polo_tone2:", ["\ud83e\udd3d\ud83c\udffd"] = ":person_playing_water_polo_tone3:", ["\ud83e\udd3d\ud83c\udffe"] = ":person_playing_water_polo_tone4:", ["\ud83e\udd3d\ud83c\udfff"] = ":person_playing_water_polo_tone5:", ["\ud83e\udd3d"] = ":person_playing_water_polo:", ["\ud83d\ude4e\ud83c\udffb"] = ":person_pouting_tone1:", ["\ud83d\ude4e\ud83c\udffc"] = ":person_pouting_tone2:", ["\ud83d\ude4e\ud83c\udffd"] = ":person_pouting_tone3:", ["\ud83d\ude4e\ud83c\udffe"] = ":person_pouting_tone4:", ["\ud83d\ude4e\ud83c\udfff"] = ":person_pouting_tone5:", ["\ud83d\ude4e"] = ":person_pouting:", ["\ud83d\ude4b\ud83c\udffb"] = ":person_raising_hand_tone1:", ["\ud83d\ude4b\ud83c\udffc"] = ":person_raising_hand_tone2:", ["\ud83d\ude4b\ud83c\udffd"] = ":person_raising_hand_tone3:", ["\ud83d\ude4b\ud83c\udffe"] = ":person_raising_hand_tone4:", ["\ud83d\ude4b\ud83c\udfff"] = ":person_raising_hand_tone5:", ["\ud83d\ude4b"] = ":person_raising_hand:", ["\ud83e\uddd1\u200d\ud83e\uddb0"] = ":person_red_hair:", ["\ud83d\udea3\ud83c\udffb"] = ":person_rowing_boat_tone1:", ["\ud83d\udea3\ud83c\udffc"] = ":person_rowing_boat_tone2:", ["\ud83d\udea3\ud83c\udffd"] = ":person_rowing_boat_tone3:", ["\ud83d\udea3\ud83c\udffe"] = ":person_rowing_boat_tone4:", ["\ud83d\udea3\ud83c\udfff"] = ":person_rowing_boat_tone5:", ["\ud83d\udea3"] = ":person_rowing_boat:", ["\ud83c\udfc3\ud83c\udffb"] = ":person_running_tone1:", ["\ud83c\udfc3\ud83c\udffc"] = ":person_running_tone2:", ["\ud83c\udfc3\ud83c\udffd"] = ":person_running_tone3:", ["\ud83c\udfc3\ud83c\udffe"] = ":person_running_tone4:", ["\ud83c\udfc3\ud83c\udfff"] = ":person_running_tone5:", ["\ud83c\udfc3"] = ":person_running:", ["\ud83e\udd37\ud83c\udffb"] = ":person_shrugging_tone1:", ["\ud83e\udd37\ud83c\udffc"] = ":person_shrugging_tone2:", ["\ud83e\udd37\ud83c\udffd"] = ":person_shrugging_tone3:", ["\ud83e\udd37\ud83c\udffe"] = ":person_shrugging_tone4:", ["\ud83e\udd37\ud83c\udfff"] = ":person_shrugging_tone5:", ["\ud83e\udd37"] = ":person_shrugging:", ["\ud83e\uddcd\ud83c\udffb"] = ":person_standing_tone1:", ["\ud83e\uddcd\ud83c\udffc"] = ":person_standing_tone2:", ["\ud83e\uddcd\ud83c\udffd"] = ":person_standing_tone3:", ["\ud83e\uddcd\ud83c\udffe"] = ":person_standing_tone4:", ["\ud83e\uddcd\ud83c\udfff"] = ":person_standing_tone5:", ["\ud83e\uddcd"] = ":person_standing:", ["\ud83c\udfc4\ud83c\udffb"] = ":person_surfing_tone1:", ["\ud83c\udfc4\ud83c\udffc"] = ":person_surfing_tone2:", ["\ud83c\udfc4\ud83c\udffd"] = ":person_surfing_tone3:", ["\ud83c\udfc4\ud83c\udffe"] = ":person_surfing_tone4:", ["\ud83c\udfc4\ud83c\udfff"] = ":person_surfing_tone5:", ["\ud83c\udfc4"] = ":person_surfing:", ["\ud83c\udfca\ud83c\udffb"] = ":person_swimming_tone1:", ["\ud83c\udfca\ud83c\udffc"] = ":person_swimming_tone2:", ["\ud83c\udfca\ud83c\udffd"] = ":person_swimming_tone3:", ["\ud83c\udfca\ud83c\udffe"] = ":person_swimming_tone4:", ["\ud83c\udfca\ud83c\udfff"] = ":person_swimming_tone5:", ["\ud83c\udfca"] = ":person_swimming:", ["\ud83d\udc81\ud83c\udffb"] = ":person_tipping_hand_tone1:", ["\ud83d\udc81\ud83c\udffc"] = ":person_tipping_hand_tone2:", ["\ud83d\udc81\ud83c\udffd"] = ":person_tipping_hand_tone3:", ["\ud83d\udc81\ud83c\udffe"] = ":person_tipping_hand_tone4:", ["\ud83d\udc81\ud83c\udfff"] = ":person_tipping_hand_tone5:", ["\ud83d\udc81"] = ":person_tipping_hand:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83e\uddb2"] = ":person_tone1_bald:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83e\uddb1"] = ":person_tone1_curly_hair:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83e\uddb0"] = ":person_tone1_red_hair:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83e\uddb3"] = ":person_tone1_white_hair:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83e\uddb2"] = ":person_tone2_bald:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83e\uddb1"] = ":person_tone2_curly_hair:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83e\uddb0"] = ":person_tone2_red_hair:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83e\uddb3"] = ":person_tone2_white_hair:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83e\uddb2"] = ":person_tone3_bald:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83e\uddb1"] = ":person_tone3_curly_hair:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83e\uddb0"] = ":person_tone3_red_hair:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83e\uddb3"] = ":person_tone3_white_hair:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83e\uddb2"] = ":person_tone4_bald:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83e\uddb1"] = ":person_tone4_curly_hair:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83e\uddb0"] = ":person_tone4_red_hair:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83e\uddb3"] = ":person_tone4_white_hair:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83e\uddb2"] = ":person_tone5_bald:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83e\uddb1"] = ":person_tone5_curly_hair:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83e\uddb0"] = ":person_tone5_red_hair:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83e\uddb3"] = ":person_tone5_white_hair:", ["\ud83d\udeb6\ud83c\udffb"] = ":person_walking_tone1:", ["\ud83d\udeb6\ud83c\udffc"] = ":person_walking_tone2:", ["\ud83d\udeb6\ud83c\udffd"] = ":person_walking_tone3:", ["\ud83d\udeb6\ud83c\udffe"] = ":person_walking_tone4:", ["\ud83d\udeb6\ud83c\udfff"] = ":person_walking_tone5:", ["\ud83d\udeb6"] = ":person_walking:", ["\ud83d\udc73\ud83c\udffb"] = ":person_wearing_turban_tone1:", ["\ud83d\udc73\ud83c\udffc"] = ":person_wearing_turban_tone2:", ["\ud83d\udc73\ud83c\udffd"] = ":person_wearing_turban_tone3:", ["\ud83d\udc73\ud83c\udffe"] = ":person_wearing_turban_tone4:", ["\ud83d\udc73\ud83c\udfff"] = ":person_wearing_turban_tone5:", ["\ud83d\udc73"] = ":person_wearing_turban:", ["\ud83e\uddd1\u200d\ud83e\uddb3"] = ":person_white_hair:", ["\ud83e\udec5\ud83c\udffb"] = ":person_with_crown_tone1:", ["\ud83e\udec5\ud83c\udffc"] = ":person_with_crown_tone2:", ["\ud83e\udec5\ud83c\udffd"] = ":person_with_crown_tone3:", ["\ud83e\udec5\ud83c\udffe"] = ":person_with_crown_tone4:", ["\ud83e\udec5\ud83c\udfff"] = ":person_with_crown_tone5:", ["\ud83e\udec5"] = ":person_with_crown:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83e\uddaf"] = ":person_with_probing_cane_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83e\uddaf"] = ":person_with_probing_cane_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83e\uddaf"] = ":person_with_probing_cane_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83e\uddaf"] = ":person_with_probing_cane_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83e\uddaf"] = ":person_with_probing_cane_tone5:", ["\ud83e\uddd1\u200d\ud83e\uddaf"] = ":person_with_probing_cane:", ["\ud83d\udc70\ud83c\udffb"] = ":person_with_veil_tone1:", ["\ud83d\udc70\ud83c\udffc"] = ":person_with_veil_tone2:", ["\ud83d\udc70\ud83c\udffd"] = ":person_with_veil_tone3:", ["\ud83d\udc70\ud83c\udffe"] = ":person_with_veil_tone4:", ["\ud83d\udc70\ud83c\udfff"] = ":person_with_veil_tone5:", ["\ud83d\udc70"] = ":person_with_veil:", ["\ud83e\uddeb"] = ":petri_dish:", ["⛏\ufe0f"] = ":pick:", ["⛏"] = ":pick:", ["\ud83d\udefb"] = ":pickup_truck:", ["\ud83e\udd67"] = ":pie:", ["\ud83d\udc3d"] = ":pig_nose:", ["\ud83d\udc37"] = ":pig:", ["\ud83d\udc16"] = ":pig2:", ["\ud83d\udc8a"] = ":pill:", ["\ud83e\uddd1\ud83c\udffb\u200d✈\ufe0f"] = ":pilot_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d✈\ufe0f"] = ":pilot_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d✈\ufe0f"] = ":pilot_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d✈\ufe0f"] = ":pilot_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d✈\ufe0f"] = ":pilot_tone5:", ["\ud83e\uddd1\u200d✈\ufe0f"] = ":pilot:", ["\ud83e\ude85"] = ":piñata:", ["\ud83e\udd0c\ud83c\udffb"] = ":pinched_fingers_tone1:", ["\ud83e\udd0c\ud83c\udffc"] = ":pinched_fingers_tone2:", ["\ud83e\udd0c\ud83c\udffd"] = ":pinched_fingers_tone3:", ["\ud83e\udd0c\ud83c\udffe"] = ":pinched_fingers_tone4:", ["\ud83e\udd0c\ud83c\udfff"] = ":pinched_fingers_tone5:", ["\ud83e\udd0c"] = ":pinched_fingers:", ["\ud83e\udd0f\ud83c\udffb"] = ":pinching_hand_tone1:", ["\ud83e\udd0f\ud83c\udffc"] = ":pinching_hand_tone2:", ["\ud83e\udd0f\ud83c\udffd"] = ":pinching_hand_tone3:", ["\ud83e\udd0f\ud83c\udffe"] = ":pinching_hand_tone4:", ["\ud83e\udd0f\ud83c\udfff"] = ":pinching_hand_tone5:", ["\ud83e\udd0f"] = ":pinching_hand:", ["\ud83c\udf4d"] = ":pineapple:", ["\ud83c\udfd3"] = ":ping_pong:", ["\ud83c\udff4\u200d☠\ufe0f"] = ":pirate_flag:", ["♓"] = ":pisces:", ["\ud83c\udf55"] = ":pizza:", ["\ud83e\udea7"] = ":placard:", ["\ud83d\uded0"] = ":place_of_worship:", ["⏯\ufe0f"] = ":play_pause:", ["⏯"] = ":play_pause:", ["\ud83d\udedd"] = ":playground_slide:", ["\ud83e\udd7a"] = ":pleading_face:", ["\ud83e\udea0"] = ":plunger:", ["\ud83d\udc47\ud83c\udffb"] = ":point_down_tone1:", ["\ud83d\udc47\ud83c\udffc"] = ":point_down_tone2:", ["\ud83d\udc47\ud83c\udffd"] = ":point_down_tone3:", ["\ud83d\udc47\ud83c\udffe"] = ":point_down_tone4:", ["\ud83d\udc47\ud83c\udfff"] = ":point_down_tone5:", ["\ud83d\udc47"] = ":point_down:", ["\ud83d\udc48\ud83c\udffb"] = ":point_left_tone1:", ["\ud83d\udc48\ud83c\udffc"] = ":point_left_tone2:", ["\ud83d\udc48\ud83c\udffd"] = ":point_left_tone3:", ["\ud83d\udc48\ud83c\udffe"] = ":point_left_tone4:", ["\ud83d\udc48\ud83c\udfff"] = ":point_left_tone5:", ["\ud83d\udc48"] = ":point_left:", ["\ud83d\udc49\ud83c\udffb"] = ":point_right_tone1:", ["\ud83d\udc49\ud83c\udffc"] = ":point_right_tone2:", ["\ud83d\udc49\ud83c\udffd"] = ":point_right_tone3:", ["\ud83d\udc49\ud83c\udffe"] = ":point_right_tone4:", ["\ud83d\udc49\ud83c\udfff"] = ":point_right_tone5:", ["\ud83d\udc49"] = ":point_right:", ["\ud83d\udc46\ud83c\udffb"] = ":point_up_2_tone1:", ["\ud83d\udc46\ud83c\udffc"] = ":point_up_2_tone2:", ["\ud83d\udc46\ud83c\udffd"] = ":point_up_2_tone3:", ["\ud83d\udc46\ud83c\udffe"] = ":point_up_2_tone4:", ["\ud83d\udc46\ud83c\udfff"] = ":point_up_2_tone5:", ["\ud83d\udc46"] = ":point_up_2:", ["☝\ud83c\udffb"] = ":point_up_tone1:", ["☝\ud83c\udffc"] = ":point_up_tone2:", ["☝\ud83c\udffd"] = ":point_up_tone3:", ["☝\ud83c\udffe"] = ":point_up_tone4:", ["☝\ud83c\udfff"] = ":point_up_tone5:", ["☝\ufe0f"] = ":point_up:", ["☝"] = ":point_up:", ["\ud83d\udc3b\u200d❄\ufe0f"] = ":polar_bear:", ["\ud83d\ude93"] = ":police_car:", ["\ud83d\udc6e\ud83c\udffb"] = ":police_officer_tone1:", ["\ud83d\udc6e\ud83c\udffc"] = ":police_officer_tone2:", ["\ud83d\udc6e\ud83c\udffd"] = ":police_officer_tone3:", ["\ud83d\udc6e\ud83c\udffe"] = ":police_officer_tone4:", ["\ud83d\udc6e\ud83c\udfff"] = ":police_officer_tone5:", ["\ud83d\udc6e"] = ":police_officer:", ["\ud83d\udc29"] = ":poodle:", ["\ud83d\udca9"] = ":poop:", ["\ud83c\udf7f"] = ":popcorn:", ["\ud83c\udfe3"] = ":post_office:", ["\ud83d\udcef"] = ":postal_horn:", ["\ud83d\udcee"] = ":postbox:", ["\ud83d\udeb0"] = ":potable_water:", ["\ud83e\udd54"] = ":potato:", ["\ud83e\udeb4"] = ":potted_plant:", ["\ud83d\udc5d"] = ":pouch:", ["\ud83c\udf57"] = ":poultry_leg:", ["\ud83d\udcb7"] = ":pound:", ["\ud83e\uded7"] = ":pouring_liquid:", ["\ud83d\ude3e"] = ":pouting_cat:", ["\ud83d\ude4f\ud83c\udffb"] = ":pray_tone1:", ["\ud83d\ude4f\ud83c\udffc"] = ":pray_tone2:", ["\ud83d\ude4f\ud83c\udffd"] = ":pray_tone3:", ["\ud83d\ude4f\ud83c\udffe"] = ":pray_tone4:", ["\ud83d\ude4f\ud83c\udfff"] = ":pray_tone5:", ["\ud83d\ude4f"] = ":pray:", ["\ud83d\udcff"] = ":prayer_beads:", ["\ud83e\udec3\ud83c\udffb"] = ":pregnant_man_tone1:", ["\ud83e\udec3\ud83c\udffc"] = ":pregnant_man_tone2:", ["\ud83e\udec3\ud83c\udffd"] = ":pregnant_man_tone3:", ["\ud83e\udec3\ud83c\udffe"] = ":pregnant_man_tone4:", ["\ud83e\udec3\ud83c\udfff"] = ":pregnant_man_tone5:", ["\ud83e\udec3"] = ":pregnant_man:", ["\ud83e\udec4\ud83c\udffb"] = ":pregnant_person_tone1:", ["\ud83e\udec4\ud83c\udffc"] = ":pregnant_person_tone2:", ["\ud83e\udec4\ud83c\udffd"] = ":pregnant_person_tone3:", ["\ud83e\udec4\ud83c\udffe"] = ":pregnant_person_tone4:", ["\ud83e\udec4\ud83c\udfff"] = ":pregnant_person_tone5:", ["\ud83e\udec4"] = ":pregnant_person:", ["\ud83e\udd30\ud83c\udffb"] = ":pregnant_woman_tone1:", ["\ud83e\udd30\ud83c\udffc"] = ":pregnant_woman_tone2:", ["\ud83e\udd30\ud83c\udffd"] = ":pregnant_woman_tone3:", ["\ud83e\udd30\ud83c\udffe"] = ":pregnant_woman_tone4:", ["\ud83e\udd30\ud83c\udfff"] = ":pregnant_woman_tone5:", ["\ud83e\udd30"] = ":pregnant_woman:", ["\ud83e\udd68"] = ":pretzel:", ["\ud83e\udd34\ud83c\udffb"] = ":prince_tone1:", ["\ud83e\udd34\ud83c\udffc"] = ":prince_tone2:", ["\ud83e\udd34\ud83c\udffd"] = ":prince_tone3:", ["\ud83e\udd34\ud83c\udffe"] = ":prince_tone4:", ["\ud83e\udd34\ud83c\udfff"] = ":prince_tone5:", ["\ud83e\udd34"] = ":prince:", ["\ud83d\udc78\ud83c\udffb"] = ":princess_tone1:", ["\ud83d\udc78\ud83c\udffc"] = ":princess_tone2:", ["\ud83d\udc78\ud83c\udffd"] = ":princess_tone3:", ["\ud83d\udc78\ud83c\udffe"] = ":princess_tone4:", ["\ud83d\udc78\ud83c\udfff"] = ":princess_tone5:", ["\ud83d\udc78"] = ":princess:", ["\ud83d\udda8\ufe0f"] = ":printer:", ["\ud83d\udda8"] = ":printer:", ["\ud83e\uddaf"] = ":probing_cane:", ["\ud83d\udcfd\ufe0f"] = ":projector:", ["\ud83d\udcfd"] = ":projector:", ["\ud83d\udc4a\ud83c\udffb"] = ":punch_tone1:", ["\ud83d\udc4a\ud83c\udffc"] = ":punch_tone2:", ["\ud83d\udc4a\ud83c\udffd"] = ":punch_tone3:", ["\ud83d\udc4a\ud83c\udffe"] = ":punch_tone4:", ["\ud83d\udc4a\ud83c\udfff"] = ":punch_tone5:", ["\ud83d\udc4a"] = ":punch:", ["\ud83d\udfe3"] = ":purple_circle:", ["\ud83d\udc9c"] = ":purple_heart:", ["\ud83d\udfea"] = ":purple_square:", ["\ud83d\udc5b"] = ":purse:", ["\ud83d\udccc"] = ":pushpin:", ["\ud83d\udeae"] = ":put_litter_in_its_place:", ["❓"] = ":question:", ["\ud83d\udc30"] = ":rabbit:", ["\ud83d\udc07"] = ":rabbit2:", ["\ud83e\udd9d"] = ":raccoon:", ["\ud83c\udfce\ufe0f"] = ":race_car:", ["\ud83c\udfce"] = ":race_car:", ["\ud83d\udc0e"] = ":racehorse:", ["\ud83d\udd18"] = ":radio_button:", ["\ud83d\udcfb"] = ":radio:", ["☢\ufe0f"] = ":radioactive:", ["☢"] = ":radioactive:", ["\ud83d\ude21"] = ":rage:", ["\ud83d\ude83"] = ":railway_car:", ["\ud83d\udee4\ufe0f"] = ":railway_track:", ["\ud83d\udee4"] = ":railway_track:", ["\ud83c\udff3\ufe0f\u200d\ud83c\udf08"] = ":rainbow_flag:", ["\ud83c\udf08"] = ":rainbow:", ["\ud83e\udd1a\ud83c\udffb"] = ":raised_back_of_hand_tone1:", ["\ud83e\udd1a\ud83c\udffc"] = ":raised_back_of_hand_tone2:", ["\ud83e\udd1a\ud83c\udffd"] = ":raised_back_of_hand_tone3:", ["\ud83e\udd1a\ud83c\udffe"] = ":raised_back_of_hand_tone4:", ["\ud83e\udd1a\ud83c\udfff"] = ":raised_back_of_hand_tone5:", ["\ud83e\udd1a"] = ":raised_back_of_hand:", ["✋\ud83c\udffb"] = ":raised_hand_tone1:", ["✋\ud83c\udffc"] = ":raised_hand_tone2:", ["✋\ud83c\udffd"] = ":raised_hand_tone3:", ["✋\ud83c\udffe"] = ":raised_hand_tone4:", ["✋\ud83c\udfff"] = ":raised_hand_tone5:", ["✋"] = ":raised_hand:", ["\ud83d\ude4c\ud83c\udffb"] = ":raised_hands_tone1:", ["\ud83d\ude4c\ud83c\udffc"] = ":raised_hands_tone2:", ["\ud83d\ude4c\ud83c\udffd"] = ":raised_hands_tone3:", ["\ud83d\ude4c\ud83c\udffe"] = ":raised_hands_tone4:", ["\ud83d\ude4c\ud83c\udfff"] = ":raised_hands_tone5:", ["\ud83d\ude4c"] = ":raised_hands:", ["\ud83d\udc0f"] = ":ram:", ["\ud83c\udf5c"] = ":ramen:", ["\ud83d\udc00"] = ":rat:", ["\ud83e\ude92"] = ":razor:", ["\ud83e\uddfe"] = ":receipt:", ["⏺\ufe0f"] = ":record_button:", ["⏺"] = ":record_button:", ["♻\ufe0f"] = ":recycle:", ["♻"] = ":recycle:", ["\ud83d\ude97"] = ":red_car:", ["\ud83d\udd34"] = ":red_circle:", ["\ud83e\udde7"] = ":red_envelope:", ["\ud83d\udfe5"] = ":red_square:", ["\ud83c\udde6"] = ":regional_indicator_a:", ["\ud83c\udde7"] = ":regional_indicator_b:", ["\ud83c\udde8"] = ":regional_indicator_c:", ["\ud83c\udde9"] = ":regional_indicator_d:", ["\ud83c\uddea"] = ":regional_indicator_e:", ["\ud83c\uddeb"] = ":regional_indicator_f:", ["\ud83c\uddec"] = ":regional_indicator_g:", ["\ud83c\udded"] = ":regional_indicator_h:", ["\ud83c\uddee"] = ":regional_indicator_i:", ["\ud83c\uddef"] = ":regional_indicator_j:", ["\ud83c\uddf0"] = ":regional_indicator_k:", ["\ud83c\uddf1"] = ":regional_indicator_l:", ["\ud83c\uddf2"] = ":regional_indicator_m:", ["\ud83c\uddf3"] = ":regional_indicator_n:", ["\ud83c\uddf4"] = ":regional_indicator_o:", ["\ud83c\uddf5"] = ":regional_indicator_p:", ["\ud83c\uddf6"] = ":regional_indicator_q:", ["\ud83c\uddf7"] = ":regional_indicator_r:", ["\ud83c\uddf8"] = ":regional_indicator_s:", ["\ud83c\uddf9"] = ":regional_indicator_t:", ["\ud83c\uddfa"] = ":regional_indicator_u:", ["\ud83c\uddfb"] = ":regional_indicator_v:", ["\ud83c\uddfc"] = ":regional_indicator_w:", ["\ud83c\uddfd"] = ":regional_indicator_x:", ["\ud83c\uddfe"] = ":regional_indicator_y:", ["\ud83c\uddff"] = ":regional_indicator_z:", ["®\ufe0f"] = ":registered:", ["®"] = ":registered:", ["☺\ufe0f"] = ":relaxed:", ["☺"] = ":relaxed:", ["\ud83d\ude0c"] = ":relieved:", ["\ud83c\udf97\ufe0f"] = ":reminder_ribbon:", ["\ud83c\udf97"] = ":reminder_ribbon:", ["\ud83d\udd02"] = ":repeat_one:", ["\ud83d\udd01"] = ":repeat:", ["\ud83d\udebb"] = ":restroom:", ["\ud83d\udc9e"] = ":revolving_hearts:", ["⏪"] = ":rewind:", ["\ud83e\udd8f"] = ":rhino:", ["\ud83c\udf80"] = ":ribbon:", ["\ud83c\udf59"] = ":rice_ball:", ["\ud83c\udf58"] = ":rice_cracker:", ["\ud83c\udf91"] = ":rice_scene:", ["\ud83c\udf5a"] = ":rice:", ["\ud83e\udd1c\ud83c\udffb"] = ":right_facing_fist_tone1:", ["\ud83e\udd1c\ud83c\udffc"] = ":right_facing_fist_tone2:", ["\ud83e\udd1c\ud83c\udffd"] = ":right_facing_fist_tone3:", ["\ud83e\udd1c\ud83c\udffe"] = ":right_facing_fist_tone4:", ["\ud83e\udd1c\ud83c\udfff"] = ":right_facing_fist_tone5:", ["\ud83e\udd1c"] = ":right_facing_fist:", ["\ud83e\udef1\ud83c\udffb"] = ":rightwards_hand_tone1:", ["\ud83e\udef1\ud83c\udffc"] = ":rightwards_hand_tone2:", ["\ud83e\udef1\ud83c\udffd"] = ":rightwards_hand_tone3:", ["\ud83e\udef1\ud83c\udffe"] = ":rightwards_hand_tone4:", ["\ud83e\udef1\ud83c\udfff"] = ":rightwards_hand_tone5:", ["\ud83e\udef1"] = ":rightwards_hand:", ["\ud83d\udedf"] = ":ring_buoy:", ["\ud83d\udc8d"] = ":ring:", ["\ud83e\ude90"] = ":ringed_planet:", ["\ud83e\udd16"] = ":robot:", ["\ud83e\udea8"] = ":rock:", ["\ud83d\ude80"] = ":rocket:", ["\ud83e\udd23"] = ":rofl:", ["\ud83e\uddfb"] = ":roll_of_paper:", ["\ud83c\udfa2"] = ":roller_coaster:", ["\ud83d\udefc"] = ":roller_skate:", ["\ud83d\ude44"] = ":rolling_eyes:", ["\ud83d\udc13"] = ":rooster:", ["\ud83c\udf39"] = ":rose:", ["\ud83c\udff5\ufe0f"] = ":rosette:", ["\ud83c\udff5"] = ":rosette:", ["\ud83d\udea8"] = ":rotating_light:", ["\ud83d\udccd"] = ":round_pushpin:", ["\ud83c\udfc9"] = ":rugby_football:", ["\ud83c\udfbd"] = ":running_shirt_with_sash:", ["\ud83c\ude02\ufe0f"] = ":sa:", ["\ud83c\ude02"] = ":sa:", ["\ud83e\uddf7"] = ":safety_pin:", ["\ud83e\uddba"] = ":safety_vest:", ["♐"] = ":sagittarius:", ["⛵"] = ":sailboat:", ["\ud83c\udf76"] = ":sake:", ["\ud83e\udd57"] = ":salad:", ["\ud83e\uddc2"] = ":salt:", ["\ud83e\udee1"] = ":saluting_face:", ["\ud83d\udc61"] = ":sandal:", ["\ud83e\udd6a"] = ":sandwich:", ["\ud83c\udf85\ud83c\udffb"] = ":santa_tone1:", ["\ud83c\udf85\ud83c\udffc"] = ":santa_tone2:", ["\ud83c\udf85\ud83c\udffd"] = ":santa_tone3:", ["\ud83c\udf85\ud83c\udffe"] = ":santa_tone4:", ["\ud83c\udf85\ud83c\udfff"] = ":santa_tone5:", ["\ud83c\udf85"] = ":santa:", ["\ud83e\udd7b"] = ":sari:", ["\ud83d\udef0\ufe0f"] = ":satellite_orbital:", ["\ud83d\udef0"] = ":satellite_orbital:", ["\ud83d\udce1"] = ":satellite:", ["\ud83e\udd95"] = ":sauropod:", ["\ud83c\udfb7"] = ":saxophone:", ["⚖\ufe0f"] = ":scales:", ["⚖"] = ":scales:", ["\ud83e\udde3"] = ":scarf:", ["\ud83c\udf92"] = ":school_satchel:", ["\ud83c\udfeb"] = ":school:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83d\udd2c"] = ":scientist_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83d\udd2c"] = ":scientist_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83d\udd2c"] = ":scientist_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83d\udd2c"] = ":scientist_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83d\udd2c"] = ":scientist_tone5:", ["\ud83e\uddd1\u200d\ud83d\udd2c"] = ":scientist:", ["✂\ufe0f"] = ":scissors:", ["✂"] = ":scissors:", ["\ud83d\udef4"] = ":scooter:", ["\ud83e\udd82"] = ":scorpion:", ["♏"] = ":scorpius:", ["\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f"] = ":scotland:", ["\ud83d\ude40"] = ":scream_cat:", ["\ud83d\ude31"] = ":scream:", ["\ud83e\ude9b"] = ":screwdriver:", ["\ud83d\udcdc"] = ":scroll:", ["\ud83e\uddad"] = ":seal:", ["\ud83d\udcba"] = ":seat:", ["\ud83e\udd48"] = ":second_place:", ["㊙\ufe0f"] = ":secret:", ["㊙"] = ":secret:", ["\ud83d\ude48"] = ":see_no_evil:", ["\ud83c\udf31"] = ":seedling:", ["\ud83e\udd33\ud83c\udffb"] = ":selfie_tone1:", ["\ud83e\udd33\ud83c\udffc"] = ":selfie_tone2:", ["\ud83e\udd33\ud83c\udffd"] = ":selfie_tone3:", ["\ud83e\udd33\ud83c\udffe"] = ":selfie_tone4:", ["\ud83e\udd33\ud83c\udfff"] = ":selfie_tone5:", ["\ud83e\udd33"] = ":selfie:", ["\ud83d\udc15\u200d\ud83e\uddba"] = ":service_dog:", ["7\ufe0f\u20e3"] = ":seven:", ["7\u20e3"] = ":seven:", ["\ud83e\udea1"] = ":sewing_needle:", ["\ud83e\udd58"] = ":shallow_pan_of_food:", ["☘\ufe0f"] = ":shamrock:", ["☘"] = ":shamrock:", ["\ud83e\udd88"] = ":shark:", ["\ud83c\udf67"] = ":shaved_ice:", ["\ud83d\udc11"] = ":sheep:", ["\ud83d\udc1a"] = ":shell:", ["\ud83d\udee1\ufe0f"] = ":shield:", ["\ud83d\udee1"] = ":shield:", ["⛩\ufe0f"] = ":shinto_shrine:", ["⛩"] = ":shinto_shrine:", ["\ud83d\udea2"] = ":ship:", ["\ud83d\udc55"] = ":shirt:", ["\ud83d\udecd\ufe0f"] = ":shopping_bags:", ["\ud83d\udecd"] = ":shopping_bags:", ["\ud83d\uded2"] = ":shopping_cart:", ["\ud83e\ude73"] = ":shorts:", ["\ud83d\udebf"] = ":shower:", ["\ud83e\udd90"] = ":shrimp:", ["\ud83e\udd2b"] = ":shushing_face:", ["\ud83d\udcf6"] = ":signal_strength:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udfa4"] = ":singer_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udfa4"] = ":singer_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udfa4"] = ":singer_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udfa4"] = ":singer_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udfa4"] = ":singer_tone5:", ["\ud83e\uddd1\u200d\ud83c\udfa4"] = ":singer:", ["\ud83d\udd2f"] = ":six_pointed_star:", ["6\ufe0f\u20e3"] = ":six:", ["6\u20e3"] = ":six:", ["\ud83d\udef9"] = ":skateboard:", ["\ud83c\udfbf"] = ":ski:", ["⛷\ufe0f"] = ":skier:", ["⛷"] = ":skier:", ["☠\ufe0f"] = ":skull_crossbones:", ["☠"] = ":skull_crossbones:", ["\ud83d\udc80"] = ":skull:", ["\ud83e\udda8"] = ":skunk:", ["\ud83d\udef7"] = ":sled:", ["\ud83d\udecc"] = ":sleeping_accommodation:", ["\ud83d\ude34"] = ":sleeping:", ["\ud83d\ude2a"] = ":sleepy:", ["\ud83d\ude41"] = ":slight_frown:", ["\ud83d\ude42"] = ":slight_smile:", ["\ud83c\udfb0"] = ":slot_machine:", ["\ud83e\udda5"] = ":sloth:", ["\ud83d\udd39"] = ":small_blue_diamond:", ["\ud83d\udd38"] = ":small_orange_diamond:", ["\ud83d\udd3b"] = ":small_red_triangle_down:", ["\ud83d\udd3a"] = ":small_red_triangle:", ["\ud83d\ude38"] = ":smile_cat:", ["\ud83d\ude04"] = ":smile:", ["\ud83d\ude3a"] = ":smiley_cat:", ["\ud83d\ude03"] = ":smiley:", ["\ud83e\udd70"] = ":smiling_face_with_3_hearts:", ["\ud83e\udd72"] = ":smiling_face_with_tear:", ["\ud83d\ude08"] = ":smiling_imp:", ["\ud83d\ude3c"] = ":smirk_cat:", ["\ud83d\ude0f"] = ":smirk:", ["\ud83d\udeac"] = ":smoking:", ["\ud83d\udc0c"] = ":snail:", ["\ud83d\udc0d"] = ":snake:", ["\ud83e\udd27"] = ":sneezing_face:", ["\ud83c\udfc2\ud83c\udffb"] = ":snowboarder_tone1:", ["\ud83c\udfc2\ud83c\udffc"] = ":snowboarder_tone2:", ["\ud83c\udfc2\ud83c\udffd"] = ":snowboarder_tone3:", ["\ud83c\udfc2\ud83c\udffe"] = ":snowboarder_tone4:", ["\ud83c\udfc2\ud83c\udfff"] = ":snowboarder_tone5:", ["\ud83c\udfc2"] = ":snowboarder:", ["❄\ufe0f"] = ":snowflake:", ["❄"] = ":snowflake:", ["⛄"] = ":snowman:", ["☃\ufe0f"] = ":snowman2:", ["☃"] = ":snowman2:", ["\ud83e\uddfc"] = ":soap:", ["\ud83d\ude2d"] = ":sob:", ["⚽"] = ":soccer:", ["\ud83e\udde6"] = ":socks:", ["\ud83e\udd4e"] = ":softball:", ["\ud83d\udd1c"] = ":soon:", ["\ud83c\udd98"] = ":sos:", ["\ud83d\udd09"] = ":sound:", ["\ud83d\udc7e"] = ":space_invader:", ["♠\ufe0f"] = ":spades:", ["♠"] = ":spades:", ["\ud83c\udf5d"] = ":spaghetti:", ["❇\ufe0f"] = ":sparkle:", ["❇"] = ":sparkle:", ["\ud83c\udf87"] = ":sparkler:", ["✨"] = ":sparkles:", ["\ud83d\udc96"] = ":sparkling_heart:", ["\ud83d\ude4a"] = ":speak_no_evil:", ["\ud83d\udd08"] = ":speaker:", ["\ud83d\udde3\ufe0f"] = ":speaking_head:", ["\ud83d\udde3"] = ":speaking_head:", ["\ud83d\udcac"] = ":speech_balloon:", ["\ud83d\udde8\ufe0f"] = ":speech_left:", ["\ud83d\udde8"] = ":speech_left:", ["\ud83d\udea4"] = ":speedboat:", ["\ud83d\udd78\ufe0f"] = ":spider_web:", ["\ud83d\udd78"] = ":spider_web:", ["\ud83d\udd77\ufe0f"] = ":spider:", ["\ud83d\udd77"] = ":spider:", ["\ud83e\uddfd"] = ":sponge:", ["\ud83e\udd44"] = ":spoon:", ["\ud83e\uddf4"] = ":squeeze_bottle:", ["\ud83e\udd91"] = ":squid:", ["\ud83c\udfdf\ufe0f"] = ":stadium:", ["\ud83c\udfdf"] = ":stadium:", ["☪\ufe0f"] = ":star_and_crescent:", ["☪"] = ":star_and_crescent:", ["✡\ufe0f"] = ":star_of_david:", ["✡"] = ":star_of_david:", ["\ud83e\udd29"] = ":star_struck:", ["⭐"] = ":star:", ["\ud83c\udf1f"] = ":star2:", ["\ud83c\udf20"] = ":stars:", ["\ud83d\ude89"] = ":station:", ["\ud83d\uddfd"] = ":statue_of_liberty:", ["\ud83d\ude82"] = ":steam_locomotive:", ["\ud83e\ude7a"] = ":stethoscope:", ["\ud83c\udf72"] = ":stew:", ["⏹\ufe0f"] = ":stop_button:", ["⏹"] = ":stop_button:", ["⏱\ufe0f"] = ":stopwatch:", ["⏱"] = ":stopwatch:", ["\ud83d\udccf"] = ":straight_ruler:", ["\ud83c\udf53"] = ":strawberry:", ["\ud83d\ude1d"] = ":stuck_out_tongue_closed_eyes:", ["\ud83d\ude1c"] = ":stuck_out_tongue_winking_eye:", ["\ud83d\ude1b"] = ":stuck_out_tongue:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udf93"] = ":student_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udf93"] = ":student_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udf93"] = ":student_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udf93"] = ":student_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udf93"] = ":student_tone5:", ["\ud83e\uddd1\u200d\ud83c\udf93"] = ":student:", ["\ud83e\udd59"] = ":stuffed_flatbread:", ["\ud83c\udf1e"] = ":sun_with_face:", ["\ud83c\udf3b"] = ":sunflower:", ["\ud83d\ude0e"] = ":sunglasses:", ["☀\ufe0f"] = ":sunny:", ["☀"] = ":sunny:", ["\ud83c\udf04"] = ":sunrise_over_mountains:", ["\ud83c\udf05"] = ":sunrise:", ["\ud83e\uddb8\ud83c\udffb"] = ":superhero_tone1:", ["\ud83e\uddb8\ud83c\udffc"] = ":superhero_tone2:", ["\ud83e\uddb8\ud83c\udffd"] = ":superhero_tone3:", ["\ud83e\uddb8\ud83c\udffe"] = ":superhero_tone4:", ["\ud83e\uddb8\ud83c\udfff"] = ":superhero_tone5:", ["\ud83e\uddb8"] = ":superhero:", ["\ud83e\uddb9\ud83c\udffb"] = ":supervillain_tone1:", ["\ud83e\uddb9\ud83c\udffc"] = ":supervillain_tone2:", ["\ud83e\uddb9\ud83c\udffd"] = ":supervillain_tone3:", ["\ud83e\uddb9\ud83c\udffe"] = ":supervillain_tone4:", ["\ud83e\uddb9\ud83c\udfff"] = ":supervillain_tone5:", ["\ud83e\uddb9"] = ":supervillain:", ["\ud83c\udf63"] = ":sushi:", ["\ud83d\ude9f"] = ":suspension_railway:", ["\ud83e\udda2"] = ":swan:", ["\ud83d\udca6"] = ":sweat_drops:", ["\ud83d\ude05"] = ":sweat_smile:", ["\ud83d\ude13"] = ":sweat:", ["\ud83c\udf60"] = ":sweet_potato:", ["\ud83d\udd23"] = ":symbols:", ["\ud83d\udd4d"] = ":synagogue:", ["\ud83d\udc89"] = ":syringe:", ["\ud83e\udd96"] = ":t_rex:", ["\ud83c\udf2e"] = ":taco:", ["\ud83c\udf89"] = ":tada:", ["\ud83e\udd61"] = ":takeout_box:", ["\ud83e\uded4"] = ":tamale:", ["\ud83c\udf8b"] = ":tanabata_tree:", ["\ud83c\udf4a"] = ":tangerine:", ["♉"] = ":taurus:", ["\ud83d\ude95"] = ":taxi:", ["\ud83c\udf75"] = ":tea:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83c\udfeb"] = ":teacher_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83c\udfeb"] = ":teacher_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83c\udfeb"] = ":teacher_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83c\udfeb"] = ":teacher_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83c\udfeb"] = ":teacher_tone5:", ["\ud83e\uddd1\u200d\ud83c\udfeb"] = ":teacher:", ["\ud83e\uded6"] = ":teapot:", ["\ud83e\uddd1\ud83c\udffb\u200d\ud83d\udcbb"] = ":technologist_tone1:", ["\ud83e\uddd1\ud83c\udffc\u200d\ud83d\udcbb"] = ":technologist_tone2:", ["\ud83e\uddd1\ud83c\udffd\u200d\ud83d\udcbb"] = ":technologist_tone3:", ["\ud83e\uddd1\ud83c\udffe\u200d\ud83d\udcbb"] = ":technologist_tone4:", ["\ud83e\uddd1\ud83c\udfff\u200d\ud83d\udcbb"] = ":technologist_tone5:", ["\ud83e\uddd1\u200d\ud83d\udcbb"] = ":technologist:", ["\ud83e\uddf8"] = ":teddy_bear:", ["\ud83d\udcde"] = ":telephone_receiver:", ["☎\ufe0f"] = ":telephone:", ["☎"] = ":telephone:", ["\ud83d\udd2d"] = ":telescope:", ["\ud83c\udfbe"] = ":tennis:", ["⛺"] = ":tent:", ["\ud83e\uddea"] = ":test_tube:", ["\ud83e\udd12"] = ":thermometer_face:", ["\ud83c\udf21\ufe0f"] = ":thermometer:", ["\ud83c\udf21"] = ":thermometer:", ["\ud83e\udd14"] = ":thinking:", ["\ud83e\udd49"] = ":third_place:", ["\ud83e\ude74"] = ":thong_sandal:", ["\ud83d\udcad"] = ":thought_balloon:", ["\ud83e\uddf5"] = ":thread:", ["3\ufe0f\u20e3"] = ":three:", ["3\u20e3"] = ":three:", ["\ud83d\udc4e\ud83c\udffb"] = ":thumbsdown_tone1:", ["\ud83d\udc4e\ud83c\udffc"] = ":thumbsdown_tone2:", ["\ud83d\udc4e\ud83c\udffd"] = ":thumbsdown_tone3:", ["\ud83d\udc4e\ud83c\udffe"] = ":thumbsdown_tone4:", ["\ud83d\udc4e\ud83c\udfff"] = ":thumbsdown_tone5:", ["\ud83d\udc4e"] = ":thumbsdown:", ["\ud83d\udc4d\ud83c\udffb"] = ":thumbsup_tone1:", ["\ud83d\udc4d\ud83c\udffc"] = ":thumbsup_tone2:", ["\ud83d\udc4d\ud83c\udffd"] = ":thumbsup_tone3:", ["\ud83d\udc4d\ud83c\udffe"] = ":thumbsup_tone4:", ["\ud83d\udc4d\ud83c\udfff"] = ":thumbsup_tone5:", ["\ud83d\udc4d"] = ":thumbsup:", ["⛈\ufe0f"] = ":thunder_cloud_rain:", ["⛈"] = ":thunder_cloud_rain:", ["\ud83c\udfab"] = ":ticket:", ["\ud83c\udf9f\ufe0f"] = ":tickets:", ["\ud83c\udf9f"] = ":tickets:", ["\ud83d\udc2f"] = ":tiger:", ["\ud83d\udc05"] = ":tiger2:", ["⏲\ufe0f"] = ":timer:", ["⏲"] = ":timer:", ["\ud83d\ude2b"] = ":tired_face:", ["™\ufe0f"] = ":tm:", ["™"] = ":tm:", ["\ud83d\udebd"] = ":toilet:", ["\ud83d\uddfc"] = ":tokyo_tower:", ["\ud83c\udf45"] = ":tomato:", ["\ud83d\udc45"] = ":tongue:", ["\ud83e\uddf0"] = ":toolbox:", ["\ud83d\udee0\ufe0f"] = ":tools:", ["\ud83d\udee0"] = ":tools:", ["\ud83e\uddb7"] = ":tooth:", ["\ud83e\udea5"] = ":toothbrush:", ["\ud83d\udd1d"] = ":top:", ["\ud83c\udfa9"] = ":tophat:", ["⏭\ufe0f"] = ":track_next:", ["⏭"] = ":track_next:", ["⏮\ufe0f"] = ":track_previous:", ["⏮"] = ":track_previous:", ["\ud83d\uddb2\ufe0f"] = ":trackball:", ["\ud83d\uddb2"] = ":trackball:", ["\ud83d\ude9c"] = ":tractor:", ["\ud83d\udea5"] = ":traffic_light:", ["\ud83d\ude8b"] = ":train:", ["\ud83d\ude86"] = ":train2:", ["\ud83d\ude8a"] = ":tram:", ["\ud83c\udff3\ufe0f\u200d⚧\ufe0f"] = ":transgender_flag:", ["⚧"] = ":transgender_symbol:", ["\ud83d\udea9"] = ":triangular_flag_on_post:", ["\ud83d\udcd0"] = ":triangular_ruler:", ["\ud83d\udd31"] = ":trident:", ["\ud83d\ude24"] = ":triumph:", ["\ud83e\uddcc"] = ":troll:", ["\ud83d\ude8e"] = ":trolleybus:", ["\ud83c\udfc6"] = ":trophy:", ["\ud83c\udf79"] = ":tropical_drink:", ["\ud83d\udc20"] = ":tropical_fish:", ["\ud83d\ude9a"] = ":truck:", ["\ud83c\udfba"] = ":trumpet:", ["\ud83c\udf37"] = ":tulip:", ["\ud83e\udd43"] = ":tumbler_glass:", ["\ud83e\udd83"] = ":turkey:", ["\ud83d\udc22"] = ":turtle:", ["\ud83d\udcfa"] = ":tv:", ["\ud83d\udd00"] = ":twisted_rightwards_arrows:", ["\ud83d\udc95"] = ":two_hearts:", ["\ud83d\udc6c"] = ":two_men_holding_hands:", ["2\ufe0f\u20e3"] = ":two:", ["2\u20e3"] = ":two:", ["\ud83c\ude39"] = ":u5272:", ["\ud83c\ude34"] = ":u5408:", ["\ud83c\ude3a"] = ":u55b6:", ["\ud83c\ude2f"] = ":u6307:", ["\ud83c\ude37\ufe0f"] = ":u6708:", ["\ud83c\ude37"] = ":u6708:", ["\ud83c\ude36"] = ":u6709:", ["\ud83c\ude35"] = ":u6e80:", ["\ud83c\ude1a"] = ":u7121:", ["\ud83c\ude38"] = ":u7533:", ["\ud83c\ude32"] = ":u7981:", ["\ud83c\ude33"] = ":u7a7a:", ["☔"] = ":umbrella:", ["☂\ufe0f"] = ":umbrella2:", ["☂"] = ":umbrella2:", ["\ud83d\ude12"] = ":unamused:", ["\ud83d\udd1e"] = ":underage:", ["\ud83e\udd84"] = ":unicorn:", ["\ud83c\uddfa\ud83c\uddf3"] = ":united_nations:", ["\ud83d\udd13"] = ":unlock:", ["\ud83c\udd99"] = ":up:", ["\ud83d\ude43"] = ":upside_down:", ["⚱\ufe0f"] = ":urn:", ["⚱"] = ":urn:", ["✌\ud83c\udffb"] = ":v_tone1:", ["✌\ud83c\udffc"] = ":v_tone2:", ["✌\ud83c\udffd"] = ":v_tone3:", ["✌\ud83c\udffe"] = ":v_tone4:", ["✌\ud83c\udfff"] = ":v_tone5:", ["✌\ufe0f"] = ":v:", ["✌"] = ":v:", ["\ud83e\udddb\ud83c\udffb"] = ":vampire_tone1:", ["\ud83e\udddb\ud83c\udffc"] = ":vampire_tone2:", ["\ud83e\udddb\ud83c\udffd"] = ":vampire_tone3:", ["\ud83e\udddb\ud83c\udffe"] = ":vampire_tone4:", ["\ud83e\udddb\ud83c\udfff"] = ":vampire_tone5:", ["\ud83e\udddb"] = ":vampire:", ["\ud83d\udea6"] = ":vertical_traffic_light:", ["\ud83d\udcfc"] = ":vhs:", ["\ud83d\udcf3"] = ":vibration_mode:", ["\ud83d\udcf9"] = ":video_camera:", ["\ud83c\udfae"] = ":video_game:", ["\ud83c\udfbb"] = ":violin:", ["♍"] = ":virgo:", ["\ud83c\udf0b"] = ":volcano:", ["\ud83c\udfd0"] = ":volleyball:", ["\ud83c\udd9a"] = ":vs:", ["\ud83d\udd96\ud83c\udffb"] = ":vulcan_tone1:", ["\ud83d\udd96\ud83c\udffc"] = ":vulcan_tone2:", ["\ud83d\udd96\ud83c\udffd"] = ":vulcan_tone3:", ["\ud83d\udd96\ud83c\udffe"] = ":vulcan_tone4:", ["\ud83d\udd96\ud83c\udfff"] = ":vulcan_tone5:", ["\ud83d\udd96"] = ":vulcan:", ["\ud83e\uddc7"] = ":waffle:", ["\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f"] = ":wales:", ["\ud83c\udf18"] = ":waning_crescent_moon:", ["\ud83c\udf16"] = ":waning_gibbous_moon:", ["⚠\ufe0f"] = ":warning:", ["⚠"] = ":warning:", ["\ud83d\uddd1\ufe0f"] = ":wastebasket:", ["\ud83d\uddd1"] = ":wastebasket:", ["⌚"] = ":watch:", ["\ud83d\udc03"] = ":water_buffalo:", ["\ud83c\udf49"] = ":watermelon:", ["\ud83d\udc4b\ud83c\udffb"] = ":wave_tone1:", ["\ud83d\udc4b\ud83c\udffc"] = ":wave_tone2:", ["\ud83d\udc4b\ud83c\udffd"] = ":wave_tone3:", ["\ud83d\udc4b\ud83c\udffe"] = ":wave_tone4:", ["\ud83d\udc4b\ud83c\udfff"] = ":wave_tone5:", ["\ud83d\udc4b"] = ":wave:", ["〰\ufe0f"] = ":wavy_dash:", ["〰"] = ":wavy_dash:", ["\ud83c\udf12"] = ":waxing_crescent_moon:", ["\ud83c\udf14"] = ":waxing_gibbous_moon:", ["\ud83d\udebe"] = ":wc:", ["\ud83d\ude29"] = ":weary:", ["\ud83d\udc92"] = ":wedding:", ["\ud83d\udc33"] = ":whale:", ["\ud83d\udc0b"] = ":whale2:", ["☸\ufe0f"] = ":wheel_of_dharma:", ["☸"] = ":wheel_of_dharma:", ["\ud83d\udede"] = ":wheel:", ["♿"] = ":wheelchair:", ["✅"] = ":white_check_mark:", ["⚪"] = ":white_circle:", ["\ud83d\udcae"] = ":white_flower:", ["\ud83e\udd0d"] = ":white_heart:", ["⬜"] = ":white_large_square:", ["◽"] = ":white_medium_small_square:", ["◻\ufe0f"] = ":white_medium_square:", ["◻"] = ":white_medium_square:", ["▫\ufe0f"] = ":white_small_square:", ["▫"] = ":white_small_square:", ["\ud83d\udd33"] = ":white_square_button:", ["\ud83c\udf25\ufe0f"] = ":white_sun_cloud:", ["\ud83c\udf25"] = ":white_sun_cloud:", ["\ud83c\udf26\ufe0f"] = ":white_sun_rain_cloud:", ["\ud83c\udf26"] = ":white_sun_rain_cloud:", ["\ud83c\udf24\ufe0f"] = ":white_sun_small_cloud:", ["\ud83c\udf24"] = ":white_sun_small_cloud:", ["\ud83e\udd40"] = ":wilted_rose:", ["\ud83c\udf2c\ufe0f"] = ":wind_blowing_face:", ["\ud83c\udf2c"] = ":wind_blowing_face:", ["\ud83c\udf90"] = ":wind_chime:", ["\ud83e\ude9f"] = ":window:", ["\ud83c\udf77"] = ":wine_glass:", ["\ud83d\ude09"] = ":wink:", ["\ud83d\udc3a"] = ":wolf:", ["\ud83d\udc6b"] = ":woman_and_man_holding_hands_tone5_tone4:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83c\udfa8"] = ":woman_artist_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83c\udfa8"] = ":woman_artist_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83c\udfa8"] = ":woman_artist_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83c\udfa8"] = ":woman_artist_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83c\udfa8"] = ":woman_artist_tone5:", ["\ud83d\udc69\u200d\ud83c\udfa8"] = ":woman_artist:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83d\ude80"] = ":woman_astronaut_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83d\ude80"] = ":woman_astronaut_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83d\ude80"] = ":woman_astronaut_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83d\ude80"] = ":woman_astronaut_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83d\ude80"] = ":woman_astronaut_tone5:", ["\ud83d\udc69\u200d\ud83d\ude80"] = ":woman_astronaut:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83e\uddb2"] = ":woman_bald_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83e\uddb2"] = ":woman_bald_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83e\uddb2"] = ":woman_bald_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83e\uddb2"] = ":woman_bald_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83e\uddb2"] = ":woman_bald_tone5:", ["\ud83d\udc69\u200d\ud83e\uddb2"] = ":woman_bald:", ["\ud83e\uddd4\u200d♀\ufe0f"] = ":woman_beard:", ["\ud83d\udeb4\ud83c\udffb\u200d♀\ufe0f"] = ":woman_biking_tone1:", ["\ud83d\udeb4\ud83c\udffc\u200d♀\ufe0f"] = ":woman_biking_tone2:", ["\ud83d\udeb4\ud83c\udffd\u200d♀\ufe0f"] = ":woman_biking_tone3:", ["\ud83d\udeb4\ud83c\udffe\u200d♀\ufe0f"] = ":woman_biking_tone4:", ["\ud83d\udeb4\ud83c\udfff\u200d♀\ufe0f"] = ":woman_biking_tone5:", ["\ud83d\udeb4\u200d♀\ufe0f"] = ":woman_biking:", ["⛹\ud83c\udffb\u200d♀\ufe0f"] = ":woman_bouncing_ball_tone1:", ["⛹\ud83c\udffc\u200d♀\ufe0f"] = ":woman_bouncing_ball_tone2:", ["⛹\ud83c\udffd\u200d♀\ufe0f"] = ":woman_bouncing_ball_tone3:", ["⛹\ud83c\udffe\u200d♀\ufe0f"] = ":woman_bouncing_ball_tone4:", ["⛹\ud83c\udfff\u200d♀\ufe0f"] = ":woman_bouncing_ball_tone5:", ["⛹\ufe0f\u200d♀\ufe0f"] = ":woman_bouncing_ball:", ["\ud83d\ude47\ud83c\udffb\u200d♀\ufe0f"] = ":woman_bowing_tone1:", ["\ud83d\ude47\ud83c\udffc\u200d♀\ufe0f"] = ":woman_bowing_tone2:", ["\ud83d\ude47\ud83c\udffd\u200d♀\ufe0f"] = ":woman_bowing_tone3:", ["\ud83d\ude47\ud83c\udffe\u200d♀\ufe0f"] = ":woman_bowing_tone4:", ["\ud83d\ude47\ud83c\udfff\u200d♀\ufe0f"] = ":woman_bowing_tone5:", ["\ud83d\ude47\u200d♀\ufe0f"] = ":woman_bowing:", ["\ud83e\udd38\ud83c\udffb\u200d♀\ufe0f"] = ":woman_cartwheeling_tone1:", ["\ud83e\udd38\ud83c\udffc\u200d♀\ufe0f"] = ":woman_cartwheeling_tone2:", ["\ud83e\udd38\ud83c\udffd\u200d♀\ufe0f"] = ":woman_cartwheeling_tone3:", ["\ud83e\udd38\ud83c\udffe\u200d♀\ufe0f"] = ":woman_cartwheeling_tone4:", ["\ud83e\udd38\ud83c\udfff\u200d♀\ufe0f"] = ":woman_cartwheeling_tone5:", ["\ud83e\udd38\u200d♀\ufe0f"] = ":woman_cartwheeling:", ["\ud83e\uddd7\ud83c\udffb\u200d♀\ufe0f"] = ":woman_climbing_tone1:", ["\ud83e\uddd7\ud83c\udffc\u200d♀\ufe0f"] = ":woman_climbing_tone2:", ["\ud83e\uddd7\ud83c\udffd\u200d♀\ufe0f"] = ":woman_climbing_tone3:", ["\ud83e\uddd7\ud83c\udffe\u200d♀\ufe0f"] = ":woman_climbing_tone4:", ["\ud83e\uddd7\ud83c\udfff\u200d♀\ufe0f"] = ":woman_climbing_tone5:", ["\ud83e\uddd7\u200d♀\ufe0f"] = ":woman_climbing:", ["\ud83d\udc77\ud83c\udffb\u200d♀\ufe0f"] = ":woman_construction_worker_tone1:", ["\ud83d\udc77\ud83c\udffc\u200d♀\ufe0f"] = ":woman_construction_worker_tone2:", ["\ud83d\udc77\ud83c\udffd\u200d♀\ufe0f"] = ":woman_construction_worker_tone3:", ["\ud83d\udc77\ud83c\udffe\u200d♀\ufe0f"] = ":woman_construction_worker_tone4:", ["\ud83d\udc77\ud83c\udfff\u200d♀\ufe0f"] = ":woman_construction_worker_tone5:", ["\ud83d\udc77\u200d♀\ufe0f"] = ":woman_construction_worker:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83c\udf73"] = ":woman_cook_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83c\udf73"] = ":woman_cook_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83c\udf73"] = ":woman_cook_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83c\udf73"] = ":woman_cook_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83c\udf73"] = ":woman_cook_tone5:", ["\ud83d\udc69\u200d\ud83c\udf73"] = ":woman_cook:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83e\uddb1"] = ":woman_curly_haired_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83e\uddb1"] = ":woman_curly_haired_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83e\uddb1"] = ":woman_curly_haired_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83e\uddb1"] = ":woman_curly_haired_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83e\uddb1"] = ":woman_curly_haired_tone5:", ["\ud83d\udc69\u200d\ud83e\uddb1"] = ":woman_curly_haired:", ["\ud83d\udd75\ud83c\udffb\u200d♀\ufe0f"] = ":woman_detective_tone1:", ["\ud83d\udd75\ud83c\udffc\u200d♀\ufe0f"] = ":woman_detective_tone2:", ["\ud83d\udd75\ud83c\udffd\u200d♀\ufe0f"] = ":woman_detective_tone3:", ["\ud83d\udd75\ud83c\udffe\u200d♀\ufe0f"] = ":woman_detective_tone4:", ["\ud83d\udd75\ud83c\udfff\u200d♀\ufe0f"] = ":woman_detective_tone5:", ["\ud83d\udd75\ufe0f\u200d♀\ufe0f"] = ":woman_detective:", ["\ud83e\udddd\ud83c\udffb\u200d♀\ufe0f"] = ":woman_elf_tone1:", ["\ud83e\udddd\ud83c\udffc\u200d♀\ufe0f"] = ":woman_elf_tone2:", ["\ud83e\udddd\ud83c\udffd\u200d♀\ufe0f"] = ":woman_elf_tone3:", ["\ud83e\udddd\ud83c\udffe\u200d♀\ufe0f"] = ":woman_elf_tone4:", ["\ud83e\udddd\ud83c\udfff\u200d♀\ufe0f"] = ":woman_elf_tone5:", ["\ud83e\udddd\u200d♀\ufe0f"] = ":woman_elf:", ["\ud83e\udd26\ud83c\udffb\u200d♀\ufe0f"] = ":woman_facepalming_tone1:", ["\ud83e\udd26\ud83c\udffc\u200d♀\ufe0f"] = ":woman_facepalming_tone2:", ["\ud83e\udd26\ud83c\udffd\u200d♀\ufe0f"] = ":woman_facepalming_tone3:", ["\ud83e\udd26\ud83c\udffe\u200d♀\ufe0f"] = ":woman_facepalming_tone4:", ["\ud83e\udd26\ud83c\udfff\u200d♀\ufe0f"] = ":woman_facepalming_tone5:", ["\ud83e\udd26\u200d♀\ufe0f"] = ":woman_facepalming:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83c\udfed"] = ":woman_factory_worker_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83c\udfed"] = ":woman_factory_worker_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83c\udfed"] = ":woman_factory_worker_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83c\udfed"] = ":woman_factory_worker_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83c\udfed"] = ":woman_factory_worker_tone5:", ["\ud83d\udc69\u200d\ud83c\udfed"] = ":woman_factory_worker:", ["\ud83e\uddda\ud83c\udffb\u200d♀\ufe0f"] = ":woman_fairy_tone1:", ["\ud83e\uddda\ud83c\udffc\u200d♀\ufe0f"] = ":woman_fairy_tone2:", ["\ud83e\uddda\ud83c\udffd\u200d♀\ufe0f"] = ":woman_fairy_tone3:", ["\ud83e\uddda\ud83c\udffe\u200d♀\ufe0f"] = ":woman_fairy_tone4:", ["\ud83e\uddda\ud83c\udfff\u200d♀\ufe0f"] = ":woman_fairy_tone5:", ["\ud83e\uddda\u200d♀\ufe0f"] = ":woman_fairy:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83c\udf3e"] = ":woman_farmer_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83c\udf3e"] = ":woman_farmer_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83c\udf3e"] = ":woman_farmer_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83c\udf3e"] = ":woman_farmer_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83c\udf3e"] = ":woman_farmer_tone5:", ["\ud83d\udc69\u200d\ud83c\udf3e"] = ":woman_farmer:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83c\udf7c"] = ":woman_feeding_baby_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83c\udf7c"] = ":woman_feeding_baby_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83c\udf7c"] = ":woman_feeding_baby_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83c\udf7c"] = ":woman_feeding_baby_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83c\udf7c"] = ":woman_feeding_baby_tone5:", ["\ud83d\udc69\u200d\ud83c\udf7c"] = ":woman_feeding_baby:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83d\ude92"] = ":woman_firefighter_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83d\ude92"] = ":woman_firefighter_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83d\ude92"] = ":woman_firefighter_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83d\ude92"] = ":woman_firefighter_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83d\ude92"] = ":woman_firefighter_tone5:", ["\ud83d\udc69\u200d\ud83d\ude92"] = ":woman_firefighter:", ["\ud83d\ude4d\ud83c\udffb\u200d♀\ufe0f"] = ":woman_frowning_tone1:", ["\ud83d\ude4d\ud83c\udffc\u200d♀\ufe0f"] = ":woman_frowning_tone2:", ["\ud83d\ude4d\ud83c\udffd\u200d♀\ufe0f"] = ":woman_frowning_tone3:", ["\ud83d\ude4d\ud83c\udffe\u200d♀\ufe0f"] = ":woman_frowning_tone4:", ["\ud83d\ude4d\ud83c\udfff\u200d♀\ufe0f"] = ":woman_frowning_tone5:", ["\ud83d\ude4d\u200d♀\ufe0f"] = ":woman_frowning:", ["\ud83e\uddde\u200d♀\ufe0f"] = ":woman_genie:", ["\ud83d\ude45\ud83c\udffb\u200d♀\ufe0f"] = ":woman_gesturing_no_tone1:", ["\ud83d\ude45\ud83c\udffc\u200d♀\ufe0f"] = ":woman_gesturing_no_tone2:", ["\ud83d\ude45\ud83c\udffd\u200d♀\ufe0f"] = ":woman_gesturing_no_tone3:", ["\ud83d\ude45\ud83c\udffe\u200d♀\ufe0f"] = ":woman_gesturing_no_tone4:", ["\ud83d\ude45\ud83c\udfff\u200d♀\ufe0f"] = ":woman_gesturing_no_tone5:", ["\ud83d\ude45\u200d♀\ufe0f"] = ":woman_gesturing_no:", ["\ud83d\ude46\ud83c\udffb\u200d♀\ufe0f"] = ":woman_gesturing_ok_tone1:", ["\ud83d\ude46\ud83c\udffc\u200d♀\ufe0f"] = ":woman_gesturing_ok_tone2:", ["\ud83d\ude46\ud83c\udffd\u200d♀\ufe0f"] = ":woman_gesturing_ok_tone3:", ["\ud83d\ude46\ud83c\udffe\u200d♀\ufe0f"] = ":woman_gesturing_ok_tone4:", ["\ud83d\ude46\ud83c\udfff\u200d♀\ufe0f"] = ":woman_gesturing_ok_tone5:", ["\ud83d\ude46\u200d♀\ufe0f"] = ":woman_gesturing_ok:", ["\ud83d\udc86\ud83c\udffb\u200d♀\ufe0f"] = ":woman_getting_face_massage_tone1:", ["\ud83d\udc86\ud83c\udffc\u200d♀\ufe0f"] = ":woman_getting_face_massage_tone2:", ["\ud83d\udc86\ud83c\udffd\u200d♀\ufe0f"] = ":woman_getting_face_massage_tone3:", ["\ud83d\udc86\ud83c\udffe\u200d♀\ufe0f"] = ":woman_getting_face_massage_tone4:", ["\ud83d\udc86\ud83c\udfff\u200d♀\ufe0f"] = ":woman_getting_face_massage_tone5:", ["\ud83d\udc86\u200d♀\ufe0f"] = ":woman_getting_face_massage:", ["\ud83d\udc87\ud83c\udffb\u200d♀\ufe0f"] = ":woman_getting_haircut_tone1:", ["\ud83d\udc87\ud83c\udffc\u200d♀\ufe0f"] = ":woman_getting_haircut_tone2:", ["\ud83d\udc87\ud83c\udffd\u200d♀\ufe0f"] = ":woman_getting_haircut_tone3:", ["\ud83d\udc87\ud83c\udffe\u200d♀\ufe0f"] = ":woman_getting_haircut_tone4:", ["\ud83d\udc87\ud83c\udfff\u200d♀\ufe0f"] = ":woman_getting_haircut_tone5:", ["\ud83d\udc87\u200d♀\ufe0f"] = ":woman_getting_haircut:", ["\ud83c\udfcc\ud83c\udffb\u200d♀\ufe0f"] = ":woman_golfing_tone1:", ["\ud83c\udfcc\ud83c\udffc\u200d♀\ufe0f"] = ":woman_golfing_tone2:", ["\ud83c\udfcc\ud83c\udffd\u200d♀\ufe0f"] = ":woman_golfing_tone3:", ["\ud83c\udfcc\ud83c\udffe\u200d♀\ufe0f"] = ":woman_golfing_tone4:", ["\ud83c\udfcc\ud83c\udfff\u200d♀\ufe0f"] = ":woman_golfing_tone5:", ["\ud83c\udfcc\ufe0f\u200d♀\ufe0f"] = ":woman_golfing:", ["\ud83d\udc82\ud83c\udffb\u200d♀\ufe0f"] = ":woman_guard_tone1:", ["\ud83d\udc82\ud83c\udffc\u200d♀\ufe0f"] = ":woman_guard_tone2:", ["\ud83d\udc82\ud83c\udffd\u200d♀\ufe0f"] = ":woman_guard_tone3:", ["\ud83d\udc82\ud83c\udffe\u200d♀\ufe0f"] = ":woman_guard_tone4:", ["\ud83d\udc82\ud83c\udfff\u200d♀\ufe0f"] = ":woman_guard_tone5:", ["\ud83d\udc82\u200d♀\ufe0f"] = ":woman_guard:", ["\ud83d\udc69\ud83c\udffb\u200d⚕\ufe0f"] = ":woman_health_worker_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d⚕\ufe0f"] = ":woman_health_worker_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d⚕\ufe0f"] = ":woman_health_worker_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d⚕\ufe0f"] = ":woman_health_worker_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d⚕\ufe0f"] = ":woman_health_worker_tone5:", ["\ud83d\udc69\u200d⚕\ufe0f"] = ":woman_health_worker:", ["\ud83e\uddd8\ud83c\udffb\u200d♀\ufe0f"] = ":woman_in_lotus_position_tone1:", ["\ud83e\uddd8\ud83c\udffc\u200d♀\ufe0f"] = ":woman_in_lotus_position_tone2:", ["\ud83e\uddd8\ud83c\udffd\u200d♀\ufe0f"] = ":woman_in_lotus_position_tone3:", ["\ud83e\uddd8\ud83c\udffe\u200d♀\ufe0f"] = ":woman_in_lotus_position_tone4:", ["\ud83e\uddd8\ud83c\udfff\u200d♀\ufe0f"] = ":woman_in_lotus_position_tone5:", ["\ud83e\uddd8\u200d♀\ufe0f"] = ":woman_in_lotus_position:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83e\uddbd"] = ":woman_in_manual_wheelchair_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83e\uddbd"] = ":woman_in_manual_wheelchair_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83e\uddbd"] = ":woman_in_manual_wheelchair_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83e\uddbd"] = ":woman_in_manual_wheelchair_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83e\uddbd"] = ":woman_in_manual_wheelchair_tone5:", ["\ud83d\udc69\u200d\ud83e\uddbd"] = ":woman_in_manual_wheelchair:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83e\uddbc"] = ":woman_in_motorized_wheelchair_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83e\uddbc"] = ":woman_in_motorized_wheelchair_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83e\uddbc"] = ":woman_in_motorized_wheelchair_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83e\uddbc"] = ":woman_in_motorized_wheelchair_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83e\uddbc"] = ":woman_in_motorized_wheelchair_tone5:", ["\ud83d\udc69\u200d\ud83e\uddbc"] = ":woman_in_motorized_wheelchair:", ["\ud83e\uddd6\ud83c\udffb\u200d♀\ufe0f"] = ":woman_in_steamy_room_tone1:", ["\ud83e\uddd6\ud83c\udffc\u200d♀\ufe0f"] = ":woman_in_steamy_room_tone2:", ["\ud83e\uddd6\ud83c\udffd\u200d♀\ufe0f"] = ":woman_in_steamy_room_tone3:", ["\ud83e\uddd6\ud83c\udffe\u200d♀\ufe0f"] = ":woman_in_steamy_room_tone4:", ["\ud83e\uddd6\ud83c\udfff\u200d♀\ufe0f"] = ":woman_in_steamy_room_tone5:", ["\ud83e\uddd6\u200d♀\ufe0f"] = ":woman_in_steamy_room:", ["\ud83e\udd35\ud83c\udffb\u200d♀\ufe0f"] = ":woman_in_tuxedo_tone1:", ["\ud83e\udd35\ud83c\udffc\u200d♀\ufe0f"] = ":woman_in_tuxedo_tone2:", ["\ud83e\udd35\ud83c\udffd\u200d♀\ufe0f"] = ":woman_in_tuxedo_tone3:", ["\ud83e\udd35\ud83c\udffe\u200d♀\ufe0f"] = ":woman_in_tuxedo_tone4:", ["\ud83e\udd35\ud83c\udfff\u200d♀\ufe0f"] = ":woman_in_tuxedo_tone5:", ["\ud83e\udd35\u200d♀\ufe0f"] = ":woman_in_tuxedo:", ["\ud83d\udc69\ud83c\udffb\u200d⚖\ufe0f"] = ":woman_judge_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d⚖\ufe0f"] = ":woman_judge_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d⚖\ufe0f"] = ":woman_judge_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d⚖\ufe0f"] = ":woman_judge_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d⚖\ufe0f"] = ":woman_judge_tone5:", ["\ud83d\udc69\u200d⚖\ufe0f"] = ":woman_judge:", ["\ud83e\udd39\ud83c\udffb\u200d♀\ufe0f"] = ":woman_juggling_tone1:", ["\ud83e\udd39\ud83c\udffc\u200d♀\ufe0f"] = ":woman_juggling_tone2:", ["\ud83e\udd39\ud83c\udffd\u200d♀\ufe0f"] = ":woman_juggling_tone3:", ["\ud83e\udd39\ud83c\udffe\u200d♀\ufe0f"] = ":woman_juggling_tone4:", ["\ud83e\udd39\ud83c\udfff\u200d♀\ufe0f"] = ":woman_juggling_tone5:", ["\ud83e\udd39\u200d♀\ufe0f"] = ":woman_juggling:", ["\ud83e\uddce\ud83c\udffb\u200d♀\ufe0f"] = ":woman_kneeling_tone1:", ["\ud83e\uddce\ud83c\udffc\u200d♀\ufe0f"] = ":woman_kneeling_tone2:", ["\ud83e\uddce\ud83c\udffd\u200d♀\ufe0f"] = ":woman_kneeling_tone3:", ["\ud83e\uddce\ud83c\udffe\u200d♀\ufe0f"] = ":woman_kneeling_tone4:", ["\ud83e\uddce\ud83c\udfff\u200d♀\ufe0f"] = ":woman_kneeling_tone5:", ["\ud83e\uddce\u200d♀\ufe0f"] = ":woman_kneeling:", ["\ud83c\udfcb\ud83c\udffb\u200d♀\ufe0f"] = ":woman_lifting_weights_tone1:", ["\ud83c\udfcb\ud83c\udffc\u200d♀\ufe0f"] = ":woman_lifting_weights_tone2:", ["\ud83c\udfcb\ud83c\udffd\u200d♀\ufe0f"] = ":woman_lifting_weights_tone3:", ["\ud83c\udfcb\ud83c\udffe\u200d♀\ufe0f"] = ":woman_lifting_weights_tone4:", ["\ud83c\udfcb\ud83c\udfff\u200d♀\ufe0f"] = ":woman_lifting_weights_tone5:", ["\ud83c\udfcb\ufe0f\u200d♀\ufe0f"] = ":woman_lifting_weights:", ["\ud83e\uddd9\ud83c\udffb\u200d♀\ufe0f"] = ":woman_mage_tone1:", ["\ud83e\uddd9\ud83c\udffc\u200d♀\ufe0f"] = ":woman_mage_tone2:", ["\ud83e\uddd9\ud83c\udffd\u200d♀\ufe0f"] = ":woman_mage_tone3:", ["\ud83e\uddd9\ud83c\udffe\u200d♀\ufe0f"] = ":woman_mage_tone4:", ["\ud83e\uddd9\ud83c\udfff\u200d♀\ufe0f"] = ":woman_mage_tone5:", ["\ud83e\uddd9\u200d♀\ufe0f"] = ":woman_mage:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83d\udd27"] = ":woman_mechanic_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83d\udd27"] = ":woman_mechanic_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83d\udd27"] = ":woman_mechanic_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83d\udd27"] = ":woman_mechanic_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83d\udd27"] = ":woman_mechanic_tone5:", ["\ud83d\udc69\u200d\ud83d\udd27"] = ":woman_mechanic:", ["\ud83d\udeb5\ud83c\udffb\u200d♀\ufe0f"] = ":woman_mountain_biking_tone1:", ["\ud83d\udeb5\ud83c\udffc\u200d♀\ufe0f"] = ":woman_mountain_biking_tone2:", ["\ud83d\udeb5\ud83c\udffd\u200d♀\ufe0f"] = ":woman_mountain_biking_tone3:", ["\ud83d\udeb5\ud83c\udffe\u200d♀\ufe0f"] = ":woman_mountain_biking_tone4:", ["\ud83d\udeb5\ud83c\udfff\u200d♀\ufe0f"] = ":woman_mountain_biking_tone5:", ["\ud83d\udeb5\u200d♀\ufe0f"] = ":woman_mountain_biking:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83d\udcbc"] = ":woman_office_worker_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83d\udcbc"] = ":woman_office_worker_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83d\udcbc"] = ":woman_office_worker_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83d\udcbc"] = ":woman_office_worker_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83d\udcbc"] = ":woman_office_worker_tone5:", ["\ud83d\udc69\u200d\ud83d\udcbc"] = ":woman_office_worker:", ["\ud83d\udc69\ud83c\udffb\u200d✈\ufe0f"] = ":woman_pilot_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d✈\ufe0f"] = ":woman_pilot_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d✈\ufe0f"] = ":woman_pilot_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d✈\ufe0f"] = ":woman_pilot_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d✈\ufe0f"] = ":woman_pilot_tone5:", ["\ud83d\udc69\u200d✈\ufe0f"] = ":woman_pilot:", ["\ud83e\udd3e\ud83c\udffb\u200d♀\ufe0f"] = ":woman_playing_handball_tone1:", ["\ud83e\udd3e\ud83c\udffc\u200d♀\ufe0f"] = ":woman_playing_handball_tone2:", ["\ud83e\udd3e\ud83c\udffd\u200d♀\ufe0f"] = ":woman_playing_handball_tone3:", ["\ud83e\udd3e\ud83c\udffe\u200d♀\ufe0f"] = ":woman_playing_handball_tone4:", ["\ud83e\udd3e\ud83c\udfff\u200d♀\ufe0f"] = ":woman_playing_handball_tone5:", ["\ud83e\udd3e\u200d♀\ufe0f"] = ":woman_playing_handball:", ["\ud83e\udd3d\ud83c\udffb\u200d♀\ufe0f"] = ":woman_playing_water_polo_tone1:", ["\ud83e\udd3d\ud83c\udffc\u200d♀\ufe0f"] = ":woman_playing_water_polo_tone2:", ["\ud83e\udd3d\ud83c\udffd\u200d♀\ufe0f"] = ":woman_playing_water_polo_tone3:", ["\ud83e\udd3d\ud83c\udffe\u200d♀\ufe0f"] = ":woman_playing_water_polo_tone4:", ["\ud83e\udd3d\ud83c\udfff\u200d♀\ufe0f"] = ":woman_playing_water_polo_tone5:", ["\ud83e\udd3d\u200d♀\ufe0f"] = ":woman_playing_water_polo:", ["\ud83d\udc6e\ud83c\udffb\u200d♀\ufe0f"] = ":woman_police_officer_tone1:", ["\ud83d\udc6e\ud83c\udffc\u200d♀\ufe0f"] = ":woman_police_officer_tone2:", ["\ud83d\udc6e\ud83c\udffd\u200d♀\ufe0f"] = ":woman_police_officer_tone3:", ["\ud83d\udc6e\ud83c\udffe\u200d♀\ufe0f"] = ":woman_police_officer_tone4:", ["\ud83d\udc6e\ud83c\udfff\u200d♀\ufe0f"] = ":woman_police_officer_tone5:", ["\ud83d\udc6e\u200d♀\ufe0f"] = ":woman_police_officer:", ["\ud83d\ude4e\ud83c\udffb\u200d♀\ufe0f"] = ":woman_pouting_tone1:", ["\ud83d\ude4e\ud83c\udffc\u200d♀\ufe0f"] = ":woman_pouting_tone2:", ["\ud83d\ude4e\ud83c\udffd\u200d♀\ufe0f"] = ":woman_pouting_tone3:", ["\ud83d\ude4e\ud83c\udffe\u200d♀\ufe0f"] = ":woman_pouting_tone4:", ["\ud83d\ude4e\ud83c\udfff\u200d♀\ufe0f"] = ":woman_pouting_tone5:", ["\ud83d\ude4e\u200d♀\ufe0f"] = ":woman_pouting:", ["\ud83d\ude4b\ud83c\udffb\u200d♀\ufe0f"] = ":woman_raising_hand_tone1:", ["\ud83d\ude4b\ud83c\udffc\u200d♀\ufe0f"] = ":woman_raising_hand_tone2:", ["\ud83d\ude4b\ud83c\udffd\u200d♀\ufe0f"] = ":woman_raising_hand_tone3:", ["\ud83d\ude4b\ud83c\udffe\u200d♀\ufe0f"] = ":woman_raising_hand_tone4:", ["\ud83d\ude4b\ud83c\udfff\u200d♀\ufe0f"] = ":woman_raising_hand_tone5:", ["\ud83d\ude4b\u200d♀\ufe0f"] = ":woman_raising_hand:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83e\uddb0"] = ":woman_red_haired_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83e\uddb0"] = ":woman_red_haired_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83e\uddb0"] = ":woman_red_haired_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83e\uddb0"] = ":woman_red_haired_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83e\uddb0"] = ":woman_red_haired_tone5:", ["\ud83d\udc69\u200d\ud83e\uddb0"] = ":woman_red_haired:", ["\ud83d\udea3\ud83c\udffb\u200d♀\ufe0f"] = ":woman_rowing_boat_tone1:", ["\ud83d\udea3\ud83c\udffc\u200d♀\ufe0f"] = ":woman_rowing_boat_tone2:", ["\ud83d\udea3\ud83c\udffd\u200d♀\ufe0f"] = ":woman_rowing_boat_tone3:", ["\ud83d\udea3\ud83c\udffe\u200d♀\ufe0f"] = ":woman_rowing_boat_tone4:", ["\ud83d\udea3\ud83c\udfff\u200d♀\ufe0f"] = ":woman_rowing_boat_tone5:", ["\ud83d\udea3\u200d♀\ufe0f"] = ":woman_rowing_boat:", ["\ud83c\udfc3\ud83c\udffb\u200d♀\ufe0f"] = ":woman_running_tone1:", ["\ud83c\udfc3\ud83c\udffc\u200d♀\ufe0f"] = ":woman_running_tone2:", ["\ud83c\udfc3\ud83c\udffd\u200d♀\ufe0f"] = ":woman_running_tone3:", ["\ud83c\udfc3\ud83c\udffe\u200d♀\ufe0f"] = ":woman_running_tone4:", ["\ud83c\udfc3\ud83c\udfff\u200d♀\ufe0f"] = ":woman_running_tone5:", ["\ud83c\udfc3\u200d♀\ufe0f"] = ":woman_running:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83d\udd2c"] = ":woman_scientist_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83d\udd2c"] = ":woman_scientist_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83d\udd2c"] = ":woman_scientist_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83d\udd2c"] = ":woman_scientist_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83d\udd2c"] = ":woman_scientist_tone5:", ["\ud83d\udc69\u200d\ud83d\udd2c"] = ":woman_scientist:", ["\ud83e\udd37\ud83c\udffb\u200d♀\ufe0f"] = ":woman_shrugging_tone1:", ["\ud83e\udd37\ud83c\udffc\u200d♀\ufe0f"] = ":woman_shrugging_tone2:", ["\ud83e\udd37\ud83c\udffd\u200d♀\ufe0f"] = ":woman_shrugging_tone3:", ["\ud83e\udd37\ud83c\udffe\u200d♀\ufe0f"] = ":woman_shrugging_tone4:", ["\ud83e\udd37\ud83c\udfff\u200d♀\ufe0f"] = ":woman_shrugging_tone5:", ["\ud83e\udd37\u200d♀\ufe0f"] = ":woman_shrugging:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83c\udfa4"] = ":woman_singer_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83c\udfa4"] = ":woman_singer_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83c\udfa4"] = ":woman_singer_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83c\udfa4"] = ":woman_singer_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83c\udfa4"] = ":woman_singer_tone5:", ["\ud83d\udc69\u200d\ud83c\udfa4"] = ":woman_singer:", ["\ud83e\uddcd\ud83c\udffb\u200d♀\ufe0f"] = ":woman_standing_tone1:", ["\ud83e\uddcd\ud83c\udffc\u200d♀\ufe0f"] = ":woman_standing_tone2:", ["\ud83e\uddcd\ud83c\udffd\u200d♀\ufe0f"] = ":woman_standing_tone3:", ["\ud83e\uddcd\ud83c\udffe\u200d♀\ufe0f"] = ":woman_standing_tone4:", ["\ud83e\uddcd\ud83c\udfff\u200d♀\ufe0f"] = ":woman_standing_tone5:", ["\ud83e\uddcd\u200d♀\ufe0f"] = ":woman_standing:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83c\udf93"] = ":woman_student_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83c\udf93"] = ":woman_student_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83c\udf93"] = ":woman_student_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83c\udf93"] = ":woman_student_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83c\udf93"] = ":woman_student_tone5:", ["\ud83d\udc69\u200d\ud83c\udf93"] = ":woman_student:", ["\ud83e\uddb8\ud83c\udffb\u200d♀\ufe0f"] = ":woman_superhero_tone1:", ["\ud83e\uddb8\ud83c\udffc\u200d♀\ufe0f"] = ":woman_superhero_tone2:", ["\ud83e\uddb8\ud83c\udffd\u200d♀\ufe0f"] = ":woman_superhero_tone3:", ["\ud83e\uddb8\ud83c\udffe\u200d♀\ufe0f"] = ":woman_superhero_tone4:", ["\ud83e\uddb8\ud83c\udfff\u200d♀\ufe0f"] = ":woman_superhero_tone5:", ["\ud83e\uddb8\u200d♀\ufe0f"] = ":woman_superhero:", ["\ud83e\uddb9\ud83c\udffb\u200d♀\ufe0f"] = ":woman_supervillain_tone1:", ["\ud83e\uddb9\ud83c\udffc\u200d♀\ufe0f"] = ":woman_supervillain_tone2:", ["\ud83e\uddb9\ud83c\udffd\u200d♀\ufe0f"] = ":woman_supervillain_tone3:", ["\ud83e\uddb9\ud83c\udffe\u200d♀\ufe0f"] = ":woman_supervillain_tone4:", ["\ud83e\uddb9\ud83c\udfff\u200d♀\ufe0f"] = ":woman_supervillain_tone5:", ["\ud83e\uddb9\u200d♀\ufe0f"] = ":woman_supervillain:", ["\ud83c\udfc4\ud83c\udffb\u200d♀\ufe0f"] = ":woman_surfing_tone1:", ["\ud83c\udfc4\ud83c\udffc\u200d♀\ufe0f"] = ":woman_surfing_tone2:", ["\ud83c\udfc4\ud83c\udffd\u200d♀\ufe0f"] = ":woman_surfing_tone3:", ["\ud83c\udfc4\ud83c\udffe\u200d♀\ufe0f"] = ":woman_surfing_tone4:", ["\ud83c\udfc4\ud83c\udfff\u200d♀\ufe0f"] = ":woman_surfing_tone5:", ["\ud83c\udfc4\u200d♀\ufe0f"] = ":woman_surfing:", ["\ud83c\udfca\ud83c\udffb\u200d♀\ufe0f"] = ":woman_swimming_tone1:", ["\ud83c\udfca\ud83c\udffc\u200d♀\ufe0f"] = ":woman_swimming_tone2:", ["\ud83c\udfca\ud83c\udffd\u200d♀\ufe0f"] = ":woman_swimming_tone3:", ["\ud83c\udfca\ud83c\udffe\u200d♀\ufe0f"] = ":woman_swimming_tone4:", ["\ud83c\udfca\ud83c\udfff\u200d♀\ufe0f"] = ":woman_swimming_tone5:", ["\ud83c\udfca\u200d♀\ufe0f"] = ":woman_swimming:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83c\udfeb"] = ":woman_teacher_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83c\udfeb"] = ":woman_teacher_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83c\udfeb"] = ":woman_teacher_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83c\udfeb"] = ":woman_teacher_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83c\udfeb"] = ":woman_teacher_tone5:", ["\ud83d\udc69\u200d\ud83c\udfeb"] = ":woman_teacher:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83d\udcbb"] = ":woman_technologist_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83d\udcbb"] = ":woman_technologist_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83d\udcbb"] = ":woman_technologist_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83d\udcbb"] = ":woman_technologist_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83d\udcbb"] = ":woman_technologist_tone5:", ["\ud83d\udc69\u200d\ud83d\udcbb"] = ":woman_technologist:", ["\ud83d\udc81\ud83c\udffb\u200d♀\ufe0f"] = ":woman_tipping_hand_tone1:", ["\ud83d\udc81\ud83c\udffc\u200d♀\ufe0f"] = ":woman_tipping_hand_tone2:", ["\ud83d\udc81\ud83c\udffd\u200d♀\ufe0f"] = ":woman_tipping_hand_tone3:", ["\ud83d\udc81\ud83c\udffe\u200d♀\ufe0f"] = ":woman_tipping_hand_tone4:", ["\ud83d\udc81\ud83c\udfff\u200d♀\ufe0f"] = ":woman_tipping_hand_tone5:", ["\ud83d\udc81\u200d♀\ufe0f"] = ":woman_tipping_hand:", ["\ud83e\uddd4\ud83c\udffb\u200d♀\ufe0f"] = ":woman_tone1_beard:", ["\ud83d\udc69\ud83c\udffb"] = ":woman_tone1:", ["\ud83e\uddd4\ud83c\udffc\u200d♀\ufe0f"] = ":woman_tone2_beard:", ["\ud83d\udc69\ud83c\udffc"] = ":woman_tone2:", ["\ud83e\uddd4\ud83c\udffd\u200d♀\ufe0f"] = ":woman_tone3_beard:", ["\ud83d\udc69\ud83c\udffd"] = ":woman_tone3:", ["\ud83e\uddd4\ud83c\udffe\u200d♀\ufe0f"] = ":woman_tone4_beard:", ["\ud83d\udc69\ud83c\udffe"] = ":woman_tone4:", ["\ud83e\uddd4\ud83c\udfff\u200d♀\ufe0f"] = ":woman_tone5_beard:", ["\ud83d\udc69\ud83c\udfff"] = ":woman_tone5:", ["\ud83e\udddb\ud83c\udffb\u200d♀\ufe0f"] = ":woman_vampire_tone1:", ["\ud83e\udddb\ud83c\udffc\u200d♀\ufe0f"] = ":woman_vampire_tone2:", ["\ud83e\udddb\ud83c\udffd\u200d♀\ufe0f"] = ":woman_vampire_tone3:", ["\ud83e\udddb\ud83c\udffe\u200d♀\ufe0f"] = ":woman_vampire_tone4:", ["\ud83e\udddb\ud83c\udfff\u200d♀\ufe0f"] = ":woman_vampire_tone5:", ["\ud83e\udddb\u200d♀\ufe0f"] = ":woman_vampire:", ["\ud83d\udeb6\ud83c\udffb\u200d♀\ufe0f"] = ":woman_walking_tone1:", ["\ud83d\udeb6\ud83c\udffc\u200d♀\ufe0f"] = ":woman_walking_tone2:", ["\ud83d\udeb6\ud83c\udffd\u200d♀\ufe0f"] = ":woman_walking_tone3:", ["\ud83d\udeb6\ud83c\udffe\u200d♀\ufe0f"] = ":woman_walking_tone4:", ["\ud83d\udeb6\ud83c\udfff\u200d♀\ufe0f"] = ":woman_walking_tone5:", ["\ud83d\udeb6\u200d♀\ufe0f"] = ":woman_walking:", ["\ud83d\udc73\ud83c\udffb\u200d♀\ufe0f"] = ":woman_wearing_turban_tone1:", ["\ud83d\udc73\ud83c\udffc\u200d♀\ufe0f"] = ":woman_wearing_turban_tone2:", ["\ud83d\udc73\ud83c\udffd\u200d♀\ufe0f"] = ":woman_wearing_turban_tone3:", ["\ud83d\udc73\ud83c\udffe\u200d♀\ufe0f"] = ":woman_wearing_turban_tone4:", ["\ud83d\udc73\ud83c\udfff\u200d♀\ufe0f"] = ":woman_wearing_turban_tone5:", ["\ud83d\udc73\u200d♀\ufe0f"] = ":woman_wearing_turban:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83e\uddb3"] = ":woman_white_haired_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83e\uddb3"] = ":woman_white_haired_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83e\uddb3"] = ":woman_white_haired_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83e\uddb3"] = ":woman_white_haired_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83e\uddb3"] = ":woman_white_haired_tone5:", ["\ud83d\udc69\u200d\ud83e\uddb3"] = ":woman_white_haired:", ["\ud83e\uddd5\ud83c\udffb"] = ":woman_with_headscarf_tone1:", ["\ud83e\uddd5\ud83c\udffc"] = ":woman_with_headscarf_tone2:", ["\ud83e\uddd5\ud83c\udffd"] = ":woman_with_headscarf_tone3:", ["\ud83e\uddd5\ud83c\udffe"] = ":woman_with_headscarf_tone4:", ["\ud83e\uddd5\ud83c\udfff"] = ":woman_with_headscarf_tone5:", ["\ud83e\uddd5"] = ":woman_with_headscarf:", ["\ud83d\udc69\ud83c\udffb\u200d\ud83e\uddaf"] = ":woman_with_probing_cane_tone1:", ["\ud83d\udc69\ud83c\udffc\u200d\ud83e\uddaf"] = ":woman_with_probing_cane_tone2:", ["\ud83d\udc69\ud83c\udffd\u200d\ud83e\uddaf"] = ":woman_with_probing_cane_tone3:", ["\ud83d\udc69\ud83c\udffe\u200d\ud83e\uddaf"] = ":woman_with_probing_cane_tone4:", ["\ud83d\udc69\ud83c\udfff\u200d\ud83e\uddaf"] = ":woman_with_probing_cane_tone5:", ["\ud83d\udc69\u200d\ud83e\uddaf"] = ":woman_with_probing_cane:", ["\ud83d\udc70\ud83c\udffb\u200d♀\ufe0f"] = ":woman_with_veil_tone1:", ["\ud83d\udc70\ud83c\udffc\u200d♀\ufe0f"] = ":woman_with_veil_tone2:", ["\ud83d\udc70\ud83c\udffd\u200d♀\ufe0f"] = ":woman_with_veil_tone3:", ["\ud83d\udc70\ud83c\udffe\u200d♀\ufe0f"] = ":woman_with_veil_tone4:", ["\ud83d\udc70\ud83c\udfff\u200d♀\ufe0f"] = ":woman_with_veil_tone5:", ["\ud83d\udc70\u200d♀\ufe0f"] = ":woman_with_veil:", ["\ud83e\udddf\u200d♀\ufe0f"] = ":woman_zombie:", ["\ud83d\udc69"] = ":woman:", ["\ud83d\udc5a"] = ":womans_clothes:", ["\ud83e\udd7f"] = ":womans_flat_shoe:", ["\ud83d\udc52"] = ":womans_hat:", ["\ud83d\udc6d"] = ":women_holding_hands_tone5_tone4:", ["\ud83d\udc6f\u200d♀\ufe0f"] = ":women_with_bunny_ears_partying:", ["\ud83e\udd3c\u200d♀\ufe0f"] = ":women_wrestling:", ["\ud83d\udeba"] = ":womens:", ["\ud83e\udeb5"] = ":wood:", ["\ud83e\udd74"] = ":woozy_face:", ["\ud83e\udeb1"] = ":worm:", ["\ud83d\ude1f"] = ":worried:", ["\ud83d\udd27"] = ":wrench:", ["✍\ud83c\udffb"] = ":writing_hand_tone1:", ["✍\ud83c\udffc"] = ":writing_hand_tone2:", ["✍\ud83c\udffd"] = ":writing_hand_tone3:", ["✍\ud83c\udffe"] = ":writing_hand_tone4:", ["✍\ud83c\udfff"] = ":writing_hand_tone5:", ["✍\ufe0f"] = ":writing_hand:", ["✍"] = ":writing_hand:", ["\ud83e\ude7b"] = ":x_ray:", ["❌"] = ":x:", ["\ud83e\uddf6"] = ":yarn:", ["\ud83e\udd71"] = ":yawning_face:", ["\ud83d\udfe1"] = ":yellow_circle:", ["\ud83d\udc9b"] = ":yellow_heart:", ["\ud83d\udfe8"] = ":yellow_square:", ["\ud83d\udcb4"] = ":yen:", ["☯\ufe0f"] = ":yin_yang:", ["☯"] = ":yin_yang:", ["\ud83e\ude80"] = ":yo_yo:", ["\ud83d\ude0b"] = ":yum:", ["\ud83e\udd2a"] = ":zany_face:", ["⚡"] = ":zap:", ["\ud83e\udd93"] = ":zebra:", ["0\ufe0f\u20e3"] = ":zero:", ["0\u20e3"] = ":zero:", ["\ud83e\udd10"] = ":zipper_mouth:", ["\ud83e\udddf"] = ":zombie:", ["\ud83d\udca4"] = ":zzz:" }; } } internal class DiscordBan { [JsonProperty("reason", NullValueHandling = NullValueHandling.Ignore)] public string Reason { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DiscordUser User { get; internal set; } [JsonProperty("user", NullValueHandling = NullValueHandling.Ignore)] internal TransportUser RawUser { get; set; } internal DiscordBan() { } } internal class DiscordGuild : SnowflakeObject, IEquatable { [JsonProperty("guild_scheduled_events")] [Newtonsoft.Json.JsonConverter(typeof(SnowflakeArrayAsDictionaryJsonConverter))] internal ConcurrentDictionary _scheduledEvents = new ConcurrentDictionary(); [JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(SnowflakeArrayAsDictionaryJsonConverter))] internal ConcurrentDictionary _roles; [JsonProperty("stickers", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(SnowflakeArrayAsDictionaryJsonConverter))] internal ConcurrentDictionary _stickers = new ConcurrentDictionary(); [JsonProperty("emojis", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(SnowflakeArrayAsDictionaryJsonConverter))] internal ConcurrentDictionary _emojis; [JsonProperty("voice_states", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(SnowflakeArrayAsDictionaryJsonConverter))] internal ConcurrentDictionary _voiceStates; [JsonProperty("members", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(SnowflakeArrayAsDictionaryJsonConverter))] internal ConcurrentDictionary _members; [JsonProperty("channels", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(SnowflakeArrayAsDictionaryJsonConverter))] internal ConcurrentDictionary _channels; [JsonProperty("threads", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(SnowflakeArrayAsDictionaryJsonConverter))] internal ConcurrentDictionary _threads = new ConcurrentDictionary(); internal ConcurrentDictionary _invites; [Newtonsoft.Json.JsonIgnore] private readonly Lazy _current_member_lazy; [Newtonsoft.Json.JsonIgnore] internal bool _isOwner; [JsonProperty("stage_instances", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(SnowflakeArrayAsDictionaryJsonConverter))] internal ConcurrentDictionary _stageInstances; [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("icon", NullValueHandling = NullValueHandling.Ignore)] public string IconHash { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string IconUrl => GetIconUrl(ImageFormat.Auto, 1024); [JsonProperty("splash", NullValueHandling = NullValueHandling.Ignore)] public string SplashHash { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string SplashUrl { get { if (string.IsNullOrWhiteSpace(SplashHash)) { return null; } return "https://cdn.discordapp.com/splashes/" + base.Id.ToString(CultureInfo.InvariantCulture) + "/" + SplashHash + ".jpg"; } } [JsonProperty("discovery_splash", NullValueHandling = NullValueHandling.Ignore)] public string DiscoverySplashHash { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string DiscoverySplashUrl { get { if (string.IsNullOrWhiteSpace(DiscoverySplashHash)) { return null; } return "https://cdn.discordapp.com/discovery-splashes/" + base.Id.ToString(CultureInfo.InvariantCulture) + "/" + DiscoverySplashHash + ".jpg"; } } [JsonProperty("preferred_locale", NullValueHandling = NullValueHandling.Ignore)] public string PreferredLocale { get; internal set; } [JsonProperty("owner_id", NullValueHandling = NullValueHandling.Ignore)] public ulong OwnerId { get; internal set; } [JsonProperty("permissions", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions? Permissions { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordMember Owner { get { if (!Members.TryGetValue(OwnerId, out var value)) { return base.Discord.ApiClient.GetGuildMemberAsync(base.Id, OwnerId).ConfigureAwait(continueOnCapturedContext: false).GetAwaiter() .GetResult(); } return value; } } [JsonProperty("region", NullValueHandling = NullValueHandling.Ignore)] internal string _voiceRegionId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordVoiceRegion VoiceRegion => base.Discord.VoiceRegions[_voiceRegionId]; [JsonProperty("afk_channel_id", NullValueHandling = NullValueHandling.Ignore)] internal ulong _afkChannelId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordChannel AfkChannel => GetChannel(_afkChannelId); [JsonProperty("afk_timeout", NullValueHandling = NullValueHandling.Ignore)] public int AfkTimeout { get; internal set; } [JsonProperty("verification_level", NullValueHandling = NullValueHandling.Ignore)] public VerificationLevel VerificationLevel { get; internal set; } [JsonProperty("default_message_notifications", NullValueHandling = NullValueHandling.Ignore)] public DefaultMessageNotifications DefaultMessageNotifications { get; internal set; } [JsonProperty("explicit_content_filter")] public ExplicitContentFilter ExplicitContentFilter { get; internal set; } [JsonProperty("nsfw_level")] public NsfwLevel NsfwLevel { get; internal set; } [JsonProperty("system_channel_id", NullValueHandling = NullValueHandling.Include)] internal ulong? _systemChannelId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordChannel SystemChannel { get { if (!_systemChannelId.HasValue) { return null; } return GetChannel(_systemChannelId.Value); } } [JsonProperty("system_channel_flags")] public SystemChannelFlags SystemChannelFlags { get; internal set; } [JsonProperty("widget_enabled", NullValueHandling = NullValueHandling.Ignore)] public bool? WidgetEnabled { get; internal set; } [JsonProperty("widget_channel_id", NullValueHandling = NullValueHandling.Ignore)] internal ulong? _widgetChannelId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordChannel WidgetChannel { get { if (!_widgetChannelId.HasValue) { return null; } return GetChannel(_widgetChannelId.Value); } } [JsonProperty("rules_channel_id")] internal ulong? _rulesChannelId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordChannel RulesChannel { get { if (!_rulesChannelId.HasValue) { return null; } return GetChannel(_rulesChannelId.Value); } } [JsonProperty("public_updates_channel_id")] internal ulong? _publicUpdatesChannelId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordChannel PublicUpdatesChannel { get { if (!_publicUpdatesChannelId.HasValue) { return null; } return GetChannel(_publicUpdatesChannelId.Value); } } [JsonProperty("application_id")] public ulong? ApplicationId { get; internal set; } public IReadOnlyDictionary ScheduledEvents => new ReadOnlyConcurrentDictionary(_scheduledEvents); [Newtonsoft.Json.JsonIgnore] public IReadOnlyDictionary Roles => new ReadOnlyConcurrentDictionary(_roles); [Newtonsoft.Json.JsonIgnore] public IReadOnlyDictionary Stickers => new ReadOnlyConcurrentDictionary(_stickers); [Newtonsoft.Json.JsonIgnore] public IReadOnlyDictionary Emojis => new ReadOnlyConcurrentDictionary(_emojis); [JsonProperty("features", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Features { get; internal set; } [JsonProperty("mfa_level", NullValueHandling = NullValueHandling.Ignore)] public MfaLevel MfaLevel { get; internal set; } [JsonProperty("joined_at", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset JoinedAt { get; internal set; } [JsonProperty("large", NullValueHandling = NullValueHandling.Ignore)] public bool IsLarge { get; internal set; } [JsonProperty("unavailable", NullValueHandling = NullValueHandling.Ignore)] public bool IsUnavailable { get; internal set; } [JsonProperty("member_count", NullValueHandling = NullValueHandling.Ignore)] public int MemberCount { get; internal set; } [JsonProperty("max_members")] public int? MaxMembers { get; internal set; } [JsonProperty("max_presences")] public int? MaxPresences { get; internal set; } [JsonProperty("approximate_member_count", NullValueHandling = NullValueHandling.Ignore)] public int? ApproximateMemberCount { get; internal set; } [JsonProperty("approximate_presence_count", NullValueHandling = NullValueHandling.Ignore)] public int? ApproximatePresenceCount { get; internal set; } [JsonProperty("max_video_channel_users", NullValueHandling = NullValueHandling.Ignore)] public int? MaxVideoChannelUsers { get; internal set; } [Newtonsoft.Json.JsonIgnore] public IReadOnlyDictionary VoiceStates => new ReadOnlyConcurrentDictionary(_voiceStates); [Newtonsoft.Json.JsonIgnore] public IReadOnlyDictionary Members => new ReadOnlyConcurrentDictionary(_members); [Newtonsoft.Json.JsonIgnore] public IReadOnlyDictionary Channels => new ReadOnlyConcurrentDictionary(_channels); [Newtonsoft.Json.JsonIgnore] public IReadOnlyDictionary Threads => new ReadOnlyConcurrentDictionary(_threads); [Newtonsoft.Json.JsonIgnore] public DiscordMember CurrentMember => _current_member_lazy.Value; [Newtonsoft.Json.JsonIgnore] public DiscordRole EveryoneRole => GetRole(base.Id); [JsonProperty("owner", NullValueHandling = NullValueHandling.Ignore)] public bool IsOwner { get { if (!_isOwner) { return OwnerId == base.Discord.CurrentUser.Id; } return true; } internal set { _isOwner = value; } } [JsonProperty("vanity_url_code")] public string VanityUrlCode { get; internal set; } [JsonProperty("description")] public string Description { get; internal set; } [JsonProperty("banner")] public string Banner { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string BannerUrl { get { if (string.IsNullOrWhiteSpace(Banner)) { return null; } return $"https://cdn.discordapp.com/banners/{base.Id}/{Banner}"; } } [JsonProperty("premium_tier")] public PremiumTier PremiumTier { get; internal set; } [JsonProperty("premium_subscription_count", NullValueHandling = NullValueHandling.Ignore)] public int? PremiumSubscriptionCount { get; internal set; } [JsonProperty("premium_progress_bar_enabled", NullValueHandling = NullValueHandling.Ignore)] public bool PremiumProgressBarEnabled { get; internal set; } [JsonProperty("nsfw", NullValueHandling = NullValueHandling.Ignore)] public bool IsNSFW { get; internal set; } [Newtonsoft.Json.JsonIgnore] public IReadOnlyDictionary StageInstances => new ReadOnlyConcurrentDictionary(_stageInstances); [Newtonsoft.Json.JsonIgnore] public IEnumerable OrderedChannels => (from channel in _channels.Values group channel by (!channel.IsCategory) ? channel.ParentId : new ulong?(channel.Id) into channels orderby channels.FirstOrDefault((DiscordChannel channel) => channel.IsCategory)?.Position select channels into channel select channel.OrderBy(delegate(DiscordChannel channel) { ChannelType type = channel.Type; return (type == ChannelType.Voice || type == ChannelType.Stage) ? true : false; }).ThenBy((DiscordChannel channel) => channel.Position)).SelectMany((IOrderedEnumerable channel) => channel); [Newtonsoft.Json.JsonIgnore] internal bool _isSynced { get; set; } internal DiscordGuild() { _current_member_lazy = new Lazy(() => (_members == null || !_members.TryGetValue(base.Discord.CurrentUser.Id, out var value)) ? null : value); _invites = new ConcurrentDictionary(); } public string GetIconUrl(ImageFormat imageFormat, ushort imageSize = 1024) { if (string.IsNullOrWhiteSpace(IconHash)) { return null; } if (imageFormat == ImageFormat.Unknown) { throw new ArgumentException("You must specify valid image format.", "imageFormat"); } if (imageSize < 16 || imageSize > 4096) { throw new ArgumentOutOfRangeException("imageSize", imageSize, "Image Size is not in between 16 and 4096."); } if (imageSize == 0 || (imageSize & (imageSize - 1)) != 0) { throw new ArgumentOutOfRangeException("imageSize", imageSize, "Image size is not a power of two."); } string text = imageFormat switch { ImageFormat.Gif => "gif", ImageFormat.Jpeg => "jpg", ImageFormat.Png => "png", ImageFormat.WebP => "webp", ImageFormat.Auto => string.IsNullOrWhiteSpace(IconHash) ? "png" : (IconHash.StartsWith("a_") ? "gif" : "png"), _ => throw new ArgumentOutOfRangeException("imageFormat"), }; string text2 = imageSize.ToString(CultureInfo.InvariantCulture); return string.Format("https://cdn.discordapp.com{0}/{1}/{2}.{3}?size={4}", "/icons", base.Id, IconHash, text, text2); } public Task CreateEventAsync(string name, string description, ulong? channelId, ScheduledGuildEventType type, ScheduledGuildEventPrivacyLevel privacyLevel, DateTimeOffset start, DateTimeOffset? end, string location = null, string reason = null) { if (start <= DateTimeOffset.Now) { throw new ArgumentOutOfRangeException("The start time for an event must be in the future."); } if (end.HasValue && end <= start) { throw new ArgumentOutOfRangeException("The end time for an event must be after the start time."); } DiscordScheduledGuildEventMetadata metadata = null; switch (type) { case ScheduledGuildEventType.StageInstance: case ScheduledGuildEventType.VoiceChannel: if (!channelId.HasValue) { throw new ArgumentException(string.Format("{0} must not be null when type is {1}", "channelId", type), "channelId"); } break; case ScheduledGuildEventType.External: if (channelId.HasValue) { throw new ArgumentException("channelId must be null when using external event type", "channelId"); } if (location == null) { throw new ArgumentException("location must not be null when using external event type", "location"); } if (!end.HasValue) { throw new ArgumentException("end must not be null when using external event type", "end"); } break; } if (!string.IsNullOrEmpty(location)) { metadata = new DiscordScheduledGuildEventMetadata { Location = location }; } return base.Discord.ApiClient.CreateScheduledGuildEventAsync(base.Id, name, description, channelId, start, end, type, privacyLevel, metadata, reason); } public Task StartEventAsync(DiscordScheduledGuildEvent guildEvent) { if (guildEvent.Status != ScheduledGuildEventStatus.Scheduled) { throw new InvalidOperationException("The event must be scheduled for it to be started."); } return ModifyEventAsync(guildEvent, delegate(ScheduledGuildEventEditModel m) { m.Status = ScheduledGuildEventStatus.Active; }); } public Task CancelEventAsync(DiscordScheduledGuildEvent guildEvent) { if (guildEvent.Status != ScheduledGuildEventStatus.Scheduled) { throw new InvalidOperationException("The event must be scheduled for it to be cancelled."); } return ModifyEventAsync(guildEvent, delegate(ScheduledGuildEventEditModel m) { m.Status = ScheduledGuildEventStatus.Cancelled; }); } public async Task ModifyEventAsync(DiscordScheduledGuildEvent guildEvent, Action mdl, string reason = null) { ScheduledGuildEventEditModel scheduledGuildEventEditModel = new ScheduledGuildEventEditModel(); mdl(scheduledGuildEventEditModel); if (scheduledGuildEventEditModel.Type.HasValue && scheduledGuildEventEditModel.Type.Value != ScheduledGuildEventType.External) { if (!scheduledGuildEventEditModel.Channel.HasValue) { throw new ArgumentException("Channel must be supplied if the event is a stage instance or voice channel event."); } if (scheduledGuildEventEditModel.Type.Value == ScheduledGuildEventType.StageInstance && scheduledGuildEventEditModel.Channel.Value.Type != ChannelType.Stage) { throw new ArgumentException("Channel must be a stage channel if the event is a stage instance event."); } if (scheduledGuildEventEditModel.Type.Value == ScheduledGuildEventType.VoiceChannel && scheduledGuildEventEditModel.Channel.Value.Type != ChannelType.Voice) { throw new ArgumentException("Channel must be a voice channel if the event is a voice channel event."); } if (scheduledGuildEventEditModel.EndTime.HasValue && scheduledGuildEventEditModel.EndTime.Value < guildEvent.StartTime) { throw new ArgumentException("End time must be after the start time."); } } if (scheduledGuildEventEditModel.Type.HasValue && scheduledGuildEventEditModel.Type.Value == ScheduledGuildEventType.External) { if (!scheduledGuildEventEditModel.EndTime.HasValue) { throw new ArgumentException("End must be supplied if the event is an external event."); } if (!scheduledGuildEventEditModel.Metadata.HasValue || string.IsNullOrEmpty(scheduledGuildEventEditModel.Metadata.Value.Location)) { throw new ArgumentException("Location must be supplied if the event is an external event."); } if (scheduledGuildEventEditModel.Channel.HasValue && scheduledGuildEventEditModel.Channel.Value != null) { throw new ArgumentException("Channel must not be supplied if the event is an external event."); } } if (guildEvent.Status == ScheduledGuildEventStatus.Completed) { throw new ArgumentException("The event must not be completed for it to be modified."); } if (guildEvent.Status == ScheduledGuildEventStatus.Cancelled) { throw new ArgumentException("The event must not be cancelled for it to be modified."); } if (scheduledGuildEventEditModel.Status.HasValue) { switch (scheduledGuildEventEditModel.Status.Value) { case ScheduledGuildEventStatus.Scheduled: throw new ArgumentException("Status must not be set to scheduled."); case ScheduledGuildEventStatus.Active: if (guildEvent.Status != ScheduledGuildEventStatus.Scheduled) { throw new ArgumentException("Event status must be scheduled to progress to active."); } break; case ScheduledGuildEventStatus.Completed: if (guildEvent.Status != ScheduledGuildEventStatus.Active) { throw new ArgumentException("Event status must be active to progress to completed."); } break; case ScheduledGuildEventStatus.Cancelled: if (guildEvent.Status != ScheduledGuildEventStatus.Scheduled) { throw new ArgumentException("Event status must be scheduled to progress to cancelled."); } break; } } DiscordScheduledGuildEvent discordScheduledGuildEvent = await base.Discord.ApiClient.ModifyScheduledGuildEventAsync(base.Id, guildEvent.Id, scheduledGuildEventEditModel.Name, scheduledGuildEventEditModel.Description, scheduledGuildEventEditModel.Channel.IfPresent((DiscordChannel? c) => c?.Id), scheduledGuildEventEditModel.StartTime, scheduledGuildEventEditModel.EndTime, scheduledGuildEventEditModel.Type, scheduledGuildEventEditModel.PrivacyLevel, scheduledGuildEventEditModel.Metadata, scheduledGuildEventEditModel.Status, reason).ConfigureAwait(continueOnCapturedContext: false); _scheduledEvents[discordScheduledGuildEvent.Id] = discordScheduledGuildEvent; } public Task DeleteEventAsync(DiscordScheduledGuildEvent guildEvent, string reason = null) { _scheduledEvents.TryRemove(guildEvent.Id, out var _); return base.Discord.ApiClient.DeleteScheduledGuildEventAsync(base.Id, guildEvent.Id); } public async Task> GetEventsAsync(bool withUserCounts = false) { IReadOnlyList readOnlyList = await base.Discord.ApiClient.GetScheduledGuildEventsAsync(base.Id, withUserCounts); foreach (DiscordScheduledGuildEvent item in readOnlyList) { _scheduledEvents[item.Id] = item; } return readOnlyList; } public async Task> GetEventUsersAsync(DiscordScheduledGuildEvent guildEvent, int limit = 100, ulong? after = null, ulong? before = null) { int remaining = limit; ulong? num = null; bool isAfter = after.HasValue; List users = new List(); int count; do { int limit2 = ((remaining > 100) ? 100 : remaining); IReadOnlyList readOnlyList = await base.Discord.ApiClient.GetScheduledGuildEventUsersAsync(base.Id, guildEvent.Id, with_members: true, limit2, isAfter ? null : (num ?? before), (!isAfter) ? null : (num ?? after)); count = readOnlyList.Count; remaining -= count; if (!isAfter) { users.AddRange(readOnlyList); num = readOnlyList.LastOrDefault()?.Id; } else { users.InsertRange(0, readOnlyList); num = readOnlyList.FirstOrDefault()?.Id; } } while (remaining > 0 && count > 0); return users.AsReadOnly(); } public Task> SearchMembersAsync(string name, int? limit = 1) { return base.Discord.ApiClient.SearchMembersAsync(base.Id, name, limit); } public Task AddMemberAsync(DiscordUser user, string access_token, string nickname = null, IEnumerable roles = null, bool muted = false, bool deaf = false) { return base.Discord.ApiClient.AddGuildMemberAsync(base.Id, user.Id, access_token, nickname, roles, muted, deaf); } public Task DeleteAsync() { return base.Discord.ApiClient.DeleteGuildAsync(base.Id); } public async Task ModifyAsync(Action action) { GuildEditModel guildEditModel = new GuildEditModel(); action(guildEditModel); if (guildEditModel.AfkChannel.HasValue && guildEditModel.AfkChannel.Value.Type != ChannelType.Voice) { throw new ArgumentException("AFK channel needs to be a voice channel."); } Optional iconb = Optional.FromNoValue(); if (guildEditModel.Icon.HasValue && guildEditModel.Icon.Value != null) { using ImageTool imageTool = new ImageTool(guildEditModel.Icon.Value); iconb = imageTool.GetBase64(); } else if (guildEditModel.Icon.HasValue) { iconb = null; } Optional splashb = Optional.FromNoValue(); if (guildEditModel.Splash.HasValue && guildEditModel.Splash.Value != null) { using ImageTool imageTool2 = new ImageTool(guildEditModel.Splash.Value); splashb = imageTool2.GetBase64(); } else if (guildEditModel.Splash.HasValue) { splashb = null; } Optional banner = Optional.FromNoValue(); if (guildEditModel.Banner.HasValue) { if (guildEditModel.Banner.Value == null) { banner = null; } else { using ImageTool imageTool3 = new ImageTool(guildEditModel.Banner.Value); banner = imageTool3.GetBase64(); } } return await base.Discord.ApiClient.ModifyGuildAsync(base.Id, guildEditModel.Name, guildEditModel.Region.IfPresent((DiscordVoiceRegion e) => e.Id), guildEditModel.VerificationLevel, guildEditModel.DefaultMessageNotifications, guildEditModel.MfaLevel, guildEditModel.ExplicitContentFilter, guildEditModel.AfkChannel.IfPresent((DiscordChannel e) => e?.Id), guildEditModel.AfkTimeout, iconb, guildEditModel.Owner.IfPresent((DiscordMember e) => e.Id), splashb, guildEditModel.SystemChannel.IfPresent((DiscordChannel e) => e?.Id), banner, guildEditModel.Description, guildEditModel.DiscoverySplash, guildEditModel.Features, guildEditModel.PreferredLocale, guildEditModel.PublicUpdatesChannel.IfPresent((DiscordChannel e) => e?.Id), guildEditModel.RulesChannel.IfPresent((DiscordChannel e) => e?.Id), guildEditModel.SystemChannelFlags, guildEditModel.AuditLogReason).ConfigureAwait(continueOnCapturedContext: false); } public async Task> ModifyRolePositionsAsync(IDictionary roles, string reason = null) { if (roles.Count == 0) { throw new ArgumentException("Roles cannot be empty.", "roles"); } DiscordRole[] array = await base.Discord.ApiClient.ModifyGuildRolePositionsAsync(base.Id, roles.Select((KeyValuePair x) => new RestGuildRoleReorderPayload { RoleId = x.Value.Id, Position = x.Key }), reason).ConfigureAwait(continueOnCapturedContext: false); _roles = new ConcurrentDictionary(array.Select((DiscordRole x) => new KeyValuePair(x.Id, x))); return array; } public Task BanMemberAsync(DiscordMember member, int delete_message_days = 0, string reason = null) { return base.Discord.ApiClient.CreateGuildBanAsync(base.Id, member.Id, delete_message_days, reason); } public Task BanMemberAsync(ulong user_id, int delete_message_days = 0, string reason = null) { return base.Discord.ApiClient.CreateGuildBanAsync(base.Id, user_id, delete_message_days, reason); } public Task UnbanMemberAsync(DiscordUser user, string reason = null) { return base.Discord.ApiClient.RemoveGuildBanAsync(base.Id, user.Id, reason); } public Task UnbanMemberAsync(ulong user_id, string reason = null) { return base.Discord.ApiClient.RemoveGuildBanAsync(base.Id, user_id, reason); } public Task LeaveAsync() { return base.Discord.ApiClient.LeaveGuildAsync(base.Id); } public Task> GetBansAsync(int? limit = null, ulong? before = null, ulong? after = null) { return base.Discord.ApiClient.GetGuildBansAsync(base.Id, limit, before, after); } public Task GetBanAsync(ulong userId) { return base.Discord.ApiClient.GetGuildBanAsync(base.Id, userId); } public Task GetBanAsync(DiscordUser user) { return GetBanAsync(user.Id); } public Task CreateTextChannelAsync(string name, DiscordChannel parent = null, Optional topic = default(Optional), IEnumerable overwrites = null, bool? nsfw = null, Optional perUserRateLimit = default(Optional), int? position = null, string reason = null) { return CreateChannelAsync(name, ChannelType.Text, parent, topic, null, null, overwrites, nsfw, perUserRateLimit, null, position, reason); } public Task CreateChannelCategoryAsync(string name, IEnumerable overwrites = null, int? position = null, string reason = null) { return CreateChannelAsync(name, ChannelType.Category, null, Optional.FromNoValue(), null, null, overwrites, null, Optional.FromNoValue(), null, position, reason); } public Task CreateVoiceChannelAsync(string name, DiscordChannel parent = null, int? bitrate = null, int? user_limit = null, IEnumerable overwrites = null, VideoQualityMode? qualityMode = null, int? position = null, string reason = null) { return CreateChannelAsync(name, ChannelType.Voice, parent, Optional.FromNoValue(), bitrate, user_limit, overwrites, null, Optional.FromNoValue(), qualityMode, position, reason); } public Task CreateChannelAsync(string name, ChannelType type, DiscordChannel parent = null, Optional topic = default(Optional), int? bitrate = null, int? userLimit = null, IEnumerable overwrites = null, bool? nsfw = null, Optional perUserRateLimit = default(Optional), VideoQualityMode? qualityMode = null, int? position = null, string reason = null, AutoArchiveDuration? defaultAutoArchiveDuration = null, DefaultReaction? defaultReactionEmoji = null, IEnumerable availableTags = null, DefaultSortOrder? defaultSortOrder = null) { bool flag; switch (type) { case ChannelType.Text: case ChannelType.Voice: case ChannelType.Category: case ChannelType.News: case ChannelType.Stage: case ChannelType.GuildForum: flag = true; break; default: flag = false; break; } if (!flag) { throw new ArgumentException("Channel type must be text, voice, stage, category, or a forum.", "type"); } if (type != ChannelType.Category || !(parent != null)) { return base.Discord.ApiClient.CreateGuildChannelAsync(base.Id, name, type, parent?.Id, topic, bitrate, userLimit, overwrites, nsfw, perUserRateLimit, qualityMode, position, reason, defaultAutoArchiveDuration, defaultReactionEmoji, availableTags, defaultSortOrder); } throw new ArgumentException("Cannot specify parent of a channel category.", "parent"); } public Task DeleteAllChannelsAsync() { return Task.WhenAll(Channels.Values.Select((DiscordChannel xc) => xc.DeleteAsync())); } public Task GetPruneCountAsync(int days = 7, IEnumerable includedRoles = null) { if (includedRoles != null) { includedRoles = includedRoles.Where((DiscordRole r) => r != null); int num = includedRoles.Count(); DiscordRole[] array = includedRoles.ToArray(); List list = new List(); for (int i = 0; i < num; i++) { if (_roles.ContainsKey(array[i].Id)) { list.Add(array[i].Id); } } return base.Discord.ApiClient.GetGuildPruneCountAsync(base.Id, days, list); } return base.Discord.ApiClient.GetGuildPruneCountAsync(base.Id, days, null); } public Task PruneAsync(int days = 7, bool computePruneCount = true, IEnumerable includedRoles = null, string reason = null) { if (includedRoles != null) { includedRoles = includedRoles.Where((DiscordRole r) => r != null); int num = includedRoles.Count(); DiscordRole[] array = includedRoles.ToArray(); List list = new List(); for (int i = 0; i < num; i++) { if (_roles.ContainsKey(array[i].Id)) { list.Add(array[i].Id); } } return base.Discord.ApiClient.BeginGuildPruneAsync(base.Id, days, computePruneCount, list, reason); } return base.Discord.ApiClient.BeginGuildPruneAsync(base.Id, days, computePruneCount, null, reason); } public Task> GetIntegrationsAsync() { return base.Discord.ApiClient.GetGuildIntegrationsAsync(base.Id); } public Task AttachUserIntegrationAsync(DiscordIntegration integration) { return base.Discord.ApiClient.CreateGuildIntegrationAsync(base.Id, integration.Type, integration.Id); } public Task ModifyIntegrationAsync(DiscordIntegration integration, int expire_behaviour, int expire_grace_period, bool enable_emoticons) { return base.Discord.ApiClient.ModifyGuildIntegrationAsync(base.Id, integration.Id, expire_behaviour, expire_grace_period, enable_emoticons); } public Task DeleteIntegrationAsync(DiscordIntegration integration, string reason = null) { return base.Discord.ApiClient.DeleteGuildIntegrationAsync(base.Id, integration, reason); } public Task SyncIntegrationAsync(DiscordIntegration integration) { return base.Discord.ApiClient.SyncGuildIntegrationAsync(base.Id, integration.Id); } public async Task> ListVoiceRegionsAsync() { IReadOnlyList readOnlyList = await base.Discord.ApiClient.GetGuildVoiceRegionsAsync(base.Id).ConfigureAwait(continueOnCapturedContext: false); foreach (DiscordVoiceRegion item in readOnlyList) { base.Discord.InternalVoiceRegions.TryAdd(item.Id, item); } return readOnlyList; } public async Task ListActiveThreadsAsync() { return await base.Discord.ApiClient.ListActiveThreadsAsync(base.Id); } public DiscordInvite GetInvite(string code) { if (!_invites.TryGetValue(code, out var value)) { return null; } return value; } public async Task> GetInvitesAsync() { IReadOnlyList readOnlyList = await base.Discord.ApiClient.GetGuildInvitesAsync(base.Id).ConfigureAwait(continueOnCapturedContext: false); if (!base.Discord.Configuration.Intents.HasIntent(DiscordIntents.GuildInvites)) { for (int i = 0; i < readOnlyList.Count; i++) { _invites[readOnlyList[i].Code] = readOnlyList[i]; } } return readOnlyList; } public Task GetVanityInviteAsync() { return base.Discord.ApiClient.GetGuildVanityUrlAsync(base.Id); } public Task> GetWebhooksAsync() { return base.Discord.ApiClient.GetGuildWebhooksAsync(base.Id); } public string GetWidgetImage(WidgetType bannerType = WidgetType.Shield) { string text = bannerType switch { WidgetType.Banner1 => "banner1", WidgetType.Banner2 => "banner2", WidgetType.Banner3 => "banner3", WidgetType.Banner4 => "banner4", _ => "shield", }; return string.Format("{0}{1}/{2}{3}?style={4}", "https://discord.com/api/v10", "/guilds", base.Id, "/widget.png", text); } public async Task GetMemberAsync(ulong userId, bool updateCache = false) { if (!updateCache && _members != null && _members.TryGetValue(userId, out var value)) { return value; } value = await base.Discord.ApiClient.GetGuildMemberAsync(base.Id, userId).ConfigureAwait(continueOnCapturedContext: false); if (base.Discord.Configuration.Intents.HasIntent(DiscordIntents.GuildMembers) && _members != null) { _members[userId] = value; } return value; } public async Task> GetAllMembersAsync() { HashSet recmbr = new HashSet(); int num = 1000; ulong num2 = 0uL; while (num > 0) { IReadOnlyList readOnlyList = await base.Discord.ApiClient.ListGuildMembersAsync(base.Id, 1000, (num2 == 0L) ? null : new ulong?(num2)).ConfigureAwait(continueOnCapturedContext: false); num = readOnlyList.Count; foreach (TransportMember item in readOnlyList) { DiscordUser newUser = new DiscordUser(item.User) { Discord = base.Discord }; base.Discord.UpdateUserCache(newUser); recmbr.Add(new DiscordMember(item) { Discord = base.Discord, _guild_id = base.Id }); } num2 = readOnlyList.LastOrDefault()?.User.Id ?? 0; } return new ReadOnlySet(recmbr); } public async Task RequestMembersAsync(string query = "", int limit = 0, bool? presences = null, IEnumerable userIds = null, string nonce = null) { DiscordClient obj = (base.Discord as DiscordClient) ?? throw new InvalidOperationException("This operation is only valid for regular Discord clients."); if (query == null && userIds == null) { throw new ArgumentException("The query and user IDs cannot both be null."); } if (query != null && userIds != null) { query = null; } GatewayRequestGuildMembers data = new GatewayRequestGuildMembers(this) { Query = query, Limit = ((limit >= 0) ? limit : 0), Presences = presences, UserIds = userIds, Nonce = nonce }; string jsonPayload = JsonConvert.SerializeObject(new GatewayPayload { OpCode = GatewayOpCode.RequestGuildMembers, Data = data }, Newtonsoft.Json.Formatting.None); await obj.SendRawPayloadAsync(jsonPayload).ConfigureAwait(continueOnCapturedContext: false); } public Task> GetChannelsAsync() { return base.Discord.ApiClient.GetGuildChannelsAsync(base.Id); } public Task CreateRoleAsync(string name = null, Permissions? permissions = null, DiscordColor? color = null, bool? hoist = null, bool? mentionable = null, string reason = null, Stream icon = null, DiscordEmoji emoji = null) { return base.Discord.ApiClient.CreateGuildRoleAsync(base.Id, name, permissions, color?.Value, hoist, mentionable, reason, icon, emoji?.ToString()); } public DiscordRole GetRole(ulong id) { if (!_roles.TryGetValue(id, out var value)) { return null; } return value; } public DiscordChannel GetChannel(ulong id) { if (_channels == null || !_channels.TryGetValue(id, out var value)) { return null; } return value; } public async Task> GetAuditLogsAsync(int? limit = null, DiscordMember by_member = null, AuditLogActionType? action_type = null) { List alrs = new List(); int num = 1; int tc = 0; ulong last = 0uL; while (num > 0) { int val = (limit.HasValue ? (limit.Value - tc) : 100); val = Math.Min(100, val); if (val <= 0) { break; } AuditLog auditLog = await base.Discord.ApiClient.GetAuditLogsAsync(base.Id, val, null, (last == 0L) ? null : new ulong?(last), by_member?.Id, (int?)action_type).ConfigureAwait(continueOnCapturedContext: false); num = auditLog.Entries.Count(); tc += num; if (num > 0) { last = auditLog.Entries.Last().Id; alrs.Add(auditLog); } } IEnumerable amr = from xu in alrs.SelectMany((AuditLog xa) => xa.Users) group xu by xu.Id into xgu select xgu.First(); foreach (AuditLogUser item3 in amr) { if (!base.Discord.UserCache.ContainsKey(item3.Id)) { DiscordUser newUser = new DiscordUser(new TransportUser { Id = item3.Id, Username = item3.Username, Discriminator = item3.Discriminator, AvatarHash = item3.AvatarHash }) { Discord = base.Discord }; base.Discord.UpdateUserCache(newUser); } } IEnumerable ahr = from xh in alrs.SelectMany((AuditLog xa) => xa.Webhooks) group xh by xh.Id into xgh select xgh.First(); IEnumerable eve = from xa in alrs.SelectMany((AuditLog xr) => xr.Events) group xa by xa.Id into xu select xu.First(); IEnumerable thr = from xa in alrs.SelectMany((AuditLog xr) => xr.Threads) group xa by xa.Id into xu select xu.First(); Dictionary ahd = null; if (ahr.Any()) { Dictionary whs = (await GetWebhooksAsync().ConfigureAwait(continueOnCapturedContext: false)).ToDictionary((DiscordWebhook xh) => xh.Id, (DiscordWebhook xh) => xh); DiscordWebhook value17; IEnumerable source = ahr.Select((AuditLogWebhook xah) => (!whs.TryGetValue(xah.Id, out value17)) ? new DiscordWebhook { Discord = base.Discord, Name = xah.Name, Id = xah.Id, AvatarHash = xah.AvatarHash, ChannelId = xah.ChannelId, GuildId = xah.GuildId, Token = xah.Token } : value17); ahd = source.ToDictionary((DiscordWebhook xh) => xh.Id, (DiscordWebhook xh) => xh); } Dictionary events = null; if (eve.Any()) { ConcurrentDictionary evb = _scheduledEvents; DiscordScheduledGuildEvent value16; IEnumerable source2 = eve.Select((DiscordScheduledGuildEvent xa) => (!evb.TryGetValue(xa.Id, out value16)) ? new DiscordScheduledGuildEvent { Discord = base.Discord, Name = xa.Name, Id = xa.Id, ChannelId = xa.ChannelId, GuildId = xa.GuildId, Creator = xa.Creator, Description = xa.Description, EndTime = xa.EndTime, Metadata = xa.Metadata, PrivacyLevel = xa.PrivacyLevel, StartTime = xa.StartTime, Status = xa.Status, Type = xa.Type, UserCount = xa.UserCount } : value16); events = source2.ToDictionary((DiscordScheduledGuildEvent xb) => xb.Id, (DiscordScheduledGuildEvent xb) => xb); } if (thr.Any()) { thr.Select((DiscordThreadChannel xr) => xr ?? new DiscordThreadChannel { Discord = base.Discord, Id = xr.Id, Name = xr.Name, GuildId = xr.GuildId }).ToDictionary((DiscordThreadChannel xa) => xa.Id, (DiscordThreadChannel xa) => xa); } DiscordMember value15; IEnumerable source3 = amr.Select((AuditLogUser xau) => (_members == null || !_members.TryGetValue(xau.Id, out value15)) ? new DiscordMember { Discord = base.Discord, Id = xau.Id, _guild_id = base.Id } : value15); Dictionary amd = source3.ToDictionary((DiscordMember xm) => xm.Id, (DiscordMember xm) => xm); IOrderedEnumerable orderedEnumerable = from xa in alrs.SelectMany((AuditLog xa) => xa.Entries) orderby xa.Id descending select xa; List entries = new List(); foreach (AuditLogAction xac in orderedEnumerable) { DiscordAuditLogEntry entry = null; ulong result7; ulong result8; int result9; int result10; switch (xac.ActionType) { case AuditLogActionType.GuildUpdate: { entry = new DiscordAuditLogGuildEntry { Target = this }; DiscordAuditLogGuildEntry entrygld = entry as DiscordAuditLogGuildEntry; foreach (AuditLogActionChange xc in xac.Changes) { switch (xc.Key.ToLowerInvariant()) { case "name": entrygld.NameChange = new PropertyChange { Before = xc.OldValueString, After = xc.NewValueString }; break; case "owner_id": { DiscordAuditLogGuildEntry discordAuditLogGuildEntry = entrygld; PropertyChange propertyChange = new PropertyChange(); PropertyChange propertyChange2 = propertyChange; DiscordMember value11; DiscordMember before = ((_members == null || !_members.TryGetValue(xc.OldValueUlong, out value11)) ? (await GetMemberAsync(xc.OldValueUlong).ConfigureAwait(continueOnCapturedContext: false)) : value11); propertyChange2.Before = before; PropertyChange propertyChange3 = propertyChange; DiscordMember value12; DiscordMember after = ((_members == null || !_members.TryGetValue(xc.NewValueUlong, out value12)) ? (await GetMemberAsync(xc.NewValueUlong).ConfigureAwait(continueOnCapturedContext: false)) : value12); propertyChange3.After = after; discordAuditLogGuildEntry.OwnerChange = propertyChange; break; } case "icon_hash": entrygld.IconChange = new PropertyChange { Before = ((xc.OldValueString != null) ? $"https://cdn.discordapp.com/icons/{base.Id}/{xc.OldValueString}.webp" : null), After = ((xc.OldValueString != null) ? $"https://cdn.discordapp.com/icons/{base.Id}/{xc.NewValueString}.webp" : null) }; break; case "verification_level": entrygld.VerificationLevelChange = new PropertyChange { Before = (VerificationLevel)(long)xc.OldValue, After = (VerificationLevel)(long)xc.NewValue }; break; case "afk_channel_id": ulong.TryParse(xc.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); ulong.TryParse(xc.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); entrygld.AfkChannelChange = new PropertyChange { Before = (GetChannel(result7) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }), After = (GetChannel(result8) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }) }; break; case "widget_channel_id": ulong.TryParse(xc.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); ulong.TryParse(xc.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); entrygld.EmbedChannelChange = new PropertyChange { Before = (GetChannel(result7) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }), After = (GetChannel(result8) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }) }; break; case "splash_hash": entrygld.SplashChange = new PropertyChange { Before = ((xc.OldValueString != null) ? $"https://cdn.discordapp.com/splashes/{base.Id}/{xc.OldValueString}.webp?size=2048" : null), After = ((xc.NewValueString != null) ? $"https://cdn.discordapp.com/splashes/{base.Id}/{xc.NewValueString}.webp?size=2048" : null) }; break; case "default_message_notifications": entrygld.NotificationSettingsChange = new PropertyChange { Before = (DefaultMessageNotifications)(long)xc.OldValue, After = (DefaultMessageNotifications)(long)xc.NewValue }; break; case "system_channel_id": ulong.TryParse(xc.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); ulong.TryParse(xc.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); entrygld.SystemChannelChange = new PropertyChange { Before = (GetChannel(result7) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }), After = (GetChannel(result8) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }) }; break; case "explicit_content_filter": entrygld.ExplicitContentFilterChange = new PropertyChange { Before = (ExplicitContentFilter)(long)xc.OldValue, After = (ExplicitContentFilter)(long)xc.NewValue }; break; case "mfa_level": entrygld.MfaLevelChange = new PropertyChange { Before = (MfaLevel)(long)xc.OldValue, After = (MfaLevel)(long)xc.NewValue }; break; case "region": entrygld.RegionChange = new PropertyChange { Before = xc.OldValueString, After = xc.NewValueString }; break; default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in guild update: {Key} - this should be reported to library developers", xc.Key); break; } } break; } case AuditLogActionType.ChannelCreate: case AuditLogActionType.ChannelUpdate: case AuditLogActionType.ChannelDelete: { entry = new DiscordAuditLogChannelEntry { Target = (GetChannel(xac.TargetId.Value) ?? new DiscordChannel { Id = xac.TargetId.Value, Discord = base.Discord, GuildId = base.Id }) }; DiscordAuditLogChannelEntry discordAuditLogChannelEntry = entry as DiscordAuditLogChannelEntry; foreach (AuditLogActionChange change in xac.Changes) { switch (change.Key.ToLowerInvariant()) { case "name": discordAuditLogChannelEntry.NameChange = new PropertyChange { Before = ((change.OldValue != null) ? change.OldValueString : null), After = ((change.NewValue != null) ? change.NewValueString : null) }; break; case "type": { bool flag = ulong.TryParse(change.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); bool flag2 = ulong.TryParse(change.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); discordAuditLogChannelEntry.TypeChange = new PropertyChange { Before = (flag ? new ChannelType?((ChannelType)result7) : null), After = (flag2 ? new ChannelType?((ChannelType)result8) : null) }; break; } case "permission_overwrites": { IEnumerable enumerable = change.OldValues?.OfType()?.Select((JObject xjo) => xjo.ToDiscordObject())?.Select(delegate(DiscordOverwrite xo) { xo.Discord = base.Discord; return xo; }); IEnumerable enumerable2 = change.NewValues?.OfType()?.Select((JObject xjo) => xjo.ToDiscordObject())?.Select(delegate(DiscordOverwrite xo) { xo.Discord = base.Discord; return xo; }); discordAuditLogChannelEntry.OverwriteChange = new PropertyChange> { Before = ((enumerable != null) ? new ReadOnlyCollection(new List(enumerable)) : null), After = ((enumerable2 != null) ? new ReadOnlyCollection(new List(enumerable2)) : null) }; break; } case "topic": discordAuditLogChannelEntry.TopicChange = new PropertyChange { Before = change.OldValueString, After = change.NewValueString }; break; case "nsfw": discordAuditLogChannelEntry.NsfwChange = new PropertyChange { Before = (bool?)change.OldValue, After = (bool?)change.NewValue }; break; case "bitrate": discordAuditLogChannelEntry.BitrateChange = new PropertyChange { Before = (int?)(long?)change.OldValue, After = (int?)(long?)change.NewValue }; break; case "rate_limit_per_user": discordAuditLogChannelEntry.PerUserRateLimitChange = new PropertyChange { Before = (int?)(long?)change.OldValue, After = (int?)(long?)change.NewValue }; break; default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in channel update: {Key} - this should be reported to library developers", change.Key); break; } } break; } case AuditLogActionType.OverwriteCreate: case AuditLogActionType.OverwriteUpdate: case AuditLogActionType.OverwriteDelete: { entry = new DiscordAuditLogOverwriteEntry { Target = GetChannel(xac.TargetId.Value)?.PermissionOverwrites.FirstOrDefault((DiscordOverwrite xo) => xo.Id == xac.Options.Id), Channel = GetChannel(xac.TargetId.Value) }; DiscordAuditLogOverwriteEntry discordAuditLogOverwriteEntry = entry as DiscordAuditLogOverwriteEntry; foreach (AuditLogActionChange change2 in xac.Changes) { switch (change2.Key.ToLowerInvariant()) { case "deny": { bool flag = ulong.TryParse(change2.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); bool flag2 = ulong.TryParse(change2.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); discordAuditLogOverwriteEntry.DenyChange = new PropertyChange { Before = (flag ? new Permissions?((Permissions)result7) : null), After = (flag2 ? new Permissions?((Permissions)result8) : null) }; break; } case "allow": { bool flag = ulong.TryParse(change2.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); bool flag2 = ulong.TryParse(change2.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); discordAuditLogOverwriteEntry.AllowChange = new PropertyChange { Before = (flag ? new Permissions?((Permissions)result7) : null), After = (flag2 ? new Permissions?((Permissions)result8) : null) }; break; } case "type": discordAuditLogOverwriteEntry.TypeChange = new PropertyChange { Before = change2.OldValueString, After = change2.NewValueString }; break; case "id": { bool flag = ulong.TryParse(change2.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); bool flag2 = ulong.TryParse(change2.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); discordAuditLogOverwriteEntry.TargetIdChange = new PropertyChange { Before = (flag ? new ulong?(result7) : null), After = (flag2 ? new ulong?(result8) : null) }; break; } default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in overwrite update: {Key} - this should be reported to library developers", change2.Key); break; } } break; } case AuditLogActionType.Kick: { entry = new DiscordAuditLogKickEntry { Target = (amd.TryGetValue(xac.TargetId.Value, out var value9) ? value9 : new DiscordMember { Id = xac.TargetId.Value, Discord = base.Discord, _guild_id = base.Id }) }; break; } case AuditLogActionType.Prune: entry = new DiscordAuditLogPruneEntry { Days = xac.Options.DeleteMemberDays, Toll = xac.Options.MembersRemoved }; break; case AuditLogActionType.Ban: case AuditLogActionType.Unban: { entry = new DiscordAuditLogBanEntry { Target = (amd.TryGetValue(xac.TargetId.Value, out var value14) ? value14 : new DiscordMember { Id = xac.TargetId.Value, Discord = base.Discord, _guild_id = base.Id }) }; break; } case AuditLogActionType.MemberUpdate: case AuditLogActionType.MemberRoleUpdate: { entry = new DiscordAuditLogMemberUpdateEntry { Target = (amd.TryGetValue(xac.TargetId.Value, out var value6) ? value6 : new DiscordMember { Id = xac.TargetId.Value, Discord = base.Discord, _guild_id = base.Id }) }; DiscordAuditLogMemberUpdateEntry discordAuditLogMemberUpdateEntry = entry as DiscordAuditLogMemberUpdateEntry; foreach (AuditLogActionChange change3 in xac.Changes) { switch (change3.Key.ToLowerInvariant()) { case "nick": discordAuditLogMemberUpdateEntry.NicknameChange = new PropertyChange { Before = change3.OldValueString, After = change3.NewValueString }; break; case "deaf": discordAuditLogMemberUpdateEntry.DeafenChange = new PropertyChange { Before = (bool?)change3.OldValue, After = (bool?)change3.NewValue }; break; case "mute": discordAuditLogMemberUpdateEntry.MuteChange = new PropertyChange { Before = (bool?)change3.OldValue, After = (bool?)change3.NewValue }; break; case "communication_disabled_until": discordAuditLogMemberUpdateEntry.TimeoutChange = new PropertyChange { Before = ((change3.OldValue != null) ? new DateTime?((DateTime)change3.OldValue) : null), After = ((change3.NewValue != null) ? new DateTime?((DateTime)change3.NewValue) : null) }; break; case "$add": discordAuditLogMemberUpdateEntry.AddedRoles = new ReadOnlyCollection(change3.NewValues.Select((JObject xo) => (ulong)xo["id"]).Select(GetRole).ToList()); break; case "$remove": discordAuditLogMemberUpdateEntry.RemovedRoles = new ReadOnlyCollection(change3.NewValues.Select((JObject xo) => (ulong)xo["id"]).Select(GetRole).ToList()); break; default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in member update: {Key} - this should be reported to library developers", change3.Key); break; } } break; } case AuditLogActionType.RoleCreate: case AuditLogActionType.RoleUpdate: case AuditLogActionType.RoleDelete: { entry = new DiscordAuditLogRoleUpdateEntry { Target = (GetRole(xac.TargetId.Value) ?? new DiscordRole { Id = xac.TargetId.Value, Discord = base.Discord }) }; DiscordAuditLogRoleUpdateEntry discordAuditLogRoleUpdateEntry = entry as DiscordAuditLogRoleUpdateEntry; foreach (AuditLogActionChange change4 in xac.Changes) { switch (change4.Key.ToLowerInvariant()) { case "name": discordAuditLogRoleUpdateEntry.NameChange = new PropertyChange { Before = change4.OldValueString, After = change4.NewValueString }; break; case "color": { bool flag = int.TryParse(change4.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result9); bool flag2 = int.TryParse(change4.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result10); discordAuditLogRoleUpdateEntry.ColorChange = new PropertyChange { Before = (flag ? new int?(result9) : null), After = (flag2 ? new int?(result10) : null) }; break; } case "permissions": discordAuditLogRoleUpdateEntry.PermissionChange = new PropertyChange { Before = ((change4.OldValue != null) ? new Permissions?((Permissions)long.Parse((string)change4.OldValue)) : null), After = ((change4.NewValue != null) ? new Permissions?((Permissions)long.Parse((string)change4.NewValue)) : null) }; break; case "position": discordAuditLogRoleUpdateEntry.PositionChange = new PropertyChange { Before = ((change4.OldValue != null) ? new int?((int)(long)change4.OldValue) : null), After = ((change4.NewValue != null) ? new int?((int)(long)change4.NewValue) : null) }; break; case "mentionable": discordAuditLogRoleUpdateEntry.MentionableChange = new PropertyChange { Before = ((change4.OldValue != null) ? ((bool?)change4.OldValue) : null), After = ((change4.NewValue != null) ? ((bool?)change4.NewValue) : null) }; break; case "hoist": discordAuditLogRoleUpdateEntry.HoistChange = new PropertyChange { Before = (bool?)change4.OldValue, After = (bool?)change4.NewValue }; break; default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in role update: {Key} - this should be reported to library developers", change4.Key); break; } } break; } case AuditLogActionType.InviteCreate: case AuditLogActionType.InviteUpdate: case AuditLogActionType.InviteDelete: { entry = new DiscordAuditLogInviteEntry(); DiscordInvite discordInvite = new DiscordInvite { Discord = base.Discord, Guild = new DiscordInviteGuild { Discord = base.Discord, Id = base.Id, Name = Name, SplashHash = SplashHash } }; DiscordAuditLogInviteEntry discordAuditLogInviteEntry = entry as DiscordAuditLogInviteEntry; foreach (AuditLogActionChange change5 in xac.Changes) { switch (change5.Key.ToLowerInvariant()) { case "max_age": { bool flag = int.TryParse(change5.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result9); bool flag2 = int.TryParse(change5.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result10); discordAuditLogInviteEntry.MaxAgeChange = new PropertyChange { Before = (flag ? new int?(result9) : null), After = (flag2 ? new int?(result10) : null) }; break; } case "code": discordInvite.Code = change5.OldValueString ?? change5.NewValueString; discordAuditLogInviteEntry.CodeChange = new PropertyChange { Before = change5.OldValueString, After = change5.NewValueString }; break; case "temporary": discordAuditLogInviteEntry.TemporaryChange = new PropertyChange { Before = ((change5.OldValue != null) ? ((bool?)change5.OldValue) : null), After = ((change5.NewValue != null) ? ((bool?)change5.NewValue) : null) }; break; case "inviter_id": { ulong.TryParse(change5.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); ulong.TryParse(change5.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); discordAuditLogInviteEntry.InviterChange = new PropertyChange { Before = (amd.TryGetValue(result7, out var value7) ? value7 : new DiscordMember { Id = result7, Discord = base.Discord, _guild_id = base.Id }), After = (amd.TryGetValue(result8, out var value8) ? value8 : new DiscordMember { Id = result7, Discord = base.Discord, _guild_id = base.Id }) }; break; } case "channel_id": { bool flag = ulong.TryParse(change5.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); bool flag2 = ulong.TryParse(change5.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); discordAuditLogInviteEntry.ChannelChange = new PropertyChange { Before = (flag ? (GetChannel(result7) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }) : null), After = (flag2 ? (GetChannel(result8) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }) : null) }; DiscordChannel discordChannel = discordAuditLogInviteEntry.ChannelChange.Before ?? discordAuditLogInviteEntry.ChannelChange.After; ChannelType? channelType = discordChannel?.Type; discordInvite.Channel = new DiscordInviteChannel { Discord = base.Discord, Id = (flag ? result7 : result8), Name = discordChannel?.Name, Type = (channelType.HasValue ? channelType.Value : ChannelType.Unknown) }; break; } case "uses": { bool flag = int.TryParse(change5.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result9); bool flag2 = int.TryParse(change5.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result10); discordAuditLogInviteEntry.UsesChange = new PropertyChange { Before = (flag ? new int?(result9) : null), After = (flag2 ? new int?(result10) : null) }; break; } case "max_uses": { bool flag = int.TryParse(change5.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result9); bool flag2 = int.TryParse(change5.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result10); discordAuditLogInviteEntry.MaxUsesChange = new PropertyChange { Before = (flag ? new int?(result9) : null), After = (flag2 ? new int?(result10) : null) }; break; } default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in invite update: {Key} - this should be reported to library developers", change5.Key); break; } } discordAuditLogInviteEntry.Target = discordInvite; break; } case AuditLogActionType.WebhookCreate: case AuditLogActionType.WebhookUpdate: case AuditLogActionType.WebhookDelete: { entry = new DiscordAuditLogWebhookEntry { Target = (ahd.TryGetValue(xac.TargetId.Value, out var value10) ? value10 : new DiscordWebhook { Id = xac.TargetId.Value, Discord = base.Discord }) }; DiscordAuditLogWebhookEntry discordAuditLogWebhookEntry = entry as DiscordAuditLogWebhookEntry; foreach (AuditLogActionChange change6 in xac.Changes) { switch (change6.Key.ToLowerInvariant()) { case "name": discordAuditLogWebhookEntry.NameChange = new PropertyChange { Before = change6.OldValueString, After = change6.NewValueString }; break; case "channel_id": { bool flag = ulong.TryParse(change6.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); bool flag2 = ulong.TryParse(change6.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); discordAuditLogWebhookEntry.ChannelChange = new PropertyChange { Before = (flag ? (GetChannel(result7) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }) : null), After = (flag2 ? (GetChannel(result8) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }) : null) }; break; } case "type": { bool flag = int.TryParse(change6.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result9); bool flag2 = int.TryParse(change6.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result10); discordAuditLogWebhookEntry.TypeChange = new PropertyChange { Before = (flag ? new int?(result9) : null), After = (flag2 ? new int?(result10) : null) }; break; } case "avatar_hash": discordAuditLogWebhookEntry.AvatarHashChange = new PropertyChange { Before = change6.OldValueString, After = change6.NewValueString }; break; case "application_id": discordAuditLogWebhookEntry.ApplicationIdChange = new PropertyChange { Before = ((change6.OldValue != null) ? new ulong?(Convert.ToUInt64(change6.OldValueString)) : null), After = ((change6.NewValue != null) ? new ulong?(Convert.ToUInt64(change6.NewValueString)) : null) }; break; default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in webhook update: {Key} - this should be reported to library developers", change6.Key); break; } } break; } case AuditLogActionType.EmojiCreate: case AuditLogActionType.EmojiUpdate: case AuditLogActionType.EmojiDelete: { entry = new DiscordAuditLogEmojiEntry { Target = (_emojis.TryGetValue(xac.TargetId.Value, out var value5) ? value5 : new DiscordEmoji { Id = xac.TargetId.Value, Discord = base.Discord }) }; DiscordAuditLogEmojiEntry discordAuditLogEmojiEntry = entry as DiscordAuditLogEmojiEntry; foreach (AuditLogActionChange change7 in xac.Changes) { if (change7.Key.ToLowerInvariant() == "name") { discordAuditLogEmojiEntry.NameChange = new PropertyChange { Before = change7.OldValueString, After = change7.NewValueString }; } else { base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in emote update: {Key} - this should be reported to library developers", change7.Key); } } break; } case AuditLogActionType.StickerCreate: case AuditLogActionType.StickerUpdate: case AuditLogActionType.StickerDelete: { entry = new DiscordAuditLogStickerEntry { Target = (_stickers.TryGetValue(xac.TargetId.Value, out var value2) ? value2 : new DiscordMessageSticker { Id = xac.TargetId.Value, Discord = base.Discord }) }; DiscordAuditLogStickerEntry discordAuditLogStickerEntry = entry as DiscordAuditLogStickerEntry; foreach (AuditLogActionChange change8 in xac.Changes) { long result; long result2; switch (change8.Key.ToLowerInvariant()) { case "name": discordAuditLogStickerEntry.NameChange = new PropertyChange { Before = change8.OldValueString, After = change8.NewValueString }; break; case "description": discordAuditLogStickerEntry.DescriptionChange = new PropertyChange { Before = change8.OldValueString, After = change8.NewValueString }; break; case "tags": discordAuditLogStickerEntry.TagsChange = new PropertyChange { Before = change8.OldValueString, After = change8.NewValueString }; break; case "guild_id": { discordAuditLogStickerEntry.GuildIdChange = new PropertyChange { Before = (ulong.TryParse(change8.OldValueString, out var result5) ? new ulong?(result5) : null), After = (ulong.TryParse(change8.NewValueString, out var result6) ? new ulong?(result6) : null) }; break; } case "available": discordAuditLogStickerEntry.AvailabilityChange = new PropertyChange { Before = (bool?)change8.OldValue, After = (bool?)change8.NewValue }; break; case "asset": discordAuditLogStickerEntry.AssetChange = new PropertyChange { Before = change8.OldValueString, After = change8.NewValueString }; break; case "id": { discordAuditLogStickerEntry.IdChange = new PropertyChange { Before = (ulong.TryParse(change8.OldValueString, out var result3) ? new ulong?(result3) : null), After = (ulong.TryParse(change8.NewValueString, out var result4) ? new ulong?(result4) : null) }; break; } case "type": { bool flag = long.TryParse(change8.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result); bool flag2 = long.TryParse(change8.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result2); discordAuditLogStickerEntry.TypeChange = new PropertyChange { Before = (flag ? new StickerType?((StickerType)result) : null), After = (flag2 ? new StickerType?((StickerType)result2) : null) }; break; } case "format_type": { bool flag = long.TryParse(change8.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result); bool flag2 = long.TryParse(change8.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result2); discordAuditLogStickerEntry.FormatChange = new PropertyChange { Before = (flag ? new StickerFormat?((StickerFormat)result) : null), After = (flag2 ? new StickerFormat?((StickerFormat)result2) : null) }; break; } default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in sticker update: {Key} - this should be reported to library developers", change8.Key); break; } } break; } case AuditLogActionType.MessageDelete: case AuditLogActionType.MessageBulkDelete: { entry = new DiscordAuditLogMessageEntry(); DiscordAuditLogMessageEntry entrymsg = entry as DiscordAuditLogMessageEntry; if (xac.Options != null) { entrymsg.Channel = GetChannel(xac.Options.ChannelId) ?? new DiscordChannel { Id = xac.Options.ChannelId, Discord = base.Discord, GuildId = base.Id }; entrymsg.MessageCount = xac.Options.Count; } if (entrymsg.Channel != null) { entrymsg.Target = ((base.Discord is DiscordClient discordClient2 && discordClient2.MessageCache != null && discordClient2.MessageCache.TryGet((DiscordMessage xm) => xm.Id == xac.TargetId.Value && xm.ChannelId == entrymsg.Channel.Id, out var item2)) ? item2 : new DiscordMessage { Discord = base.Discord, Id = xac.TargetId.Value }); } break; } case AuditLogActionType.MessagePin: case AuditLogActionType.MessageUnpin: { entry = new DiscordAuditLogMessagePinEntry(); DiscordAuditLogMessagePinEntry discordAuditLogMessagePinEntry = entry as DiscordAuditLogMessagePinEntry; if (!(base.Discord is DiscordClient discordClient)) { break; } if (xac.Options != null) { DiscordMessage item = null; discordClient.MessageCache?.TryGet((DiscordMessage x) => x.Id == xac.Options.MessageId && x.ChannelId == xac.Options.ChannelId, out item); discordAuditLogMessagePinEntry.Channel = GetChannel(xac.Options.ChannelId) ?? new DiscordChannel { Id = xac.Options.ChannelId, Discord = base.Discord, GuildId = base.Id }; discordAuditLogMessagePinEntry.Message = item ?? new DiscordMessage { Id = xac.Options.MessageId, Discord = base.Discord }; } if (xac.TargetId.HasValue) { discordClient.UserCache.TryGetValue(xac.TargetId.Value, out var value3); discordAuditLogMessagePinEntry.Target = value3 ?? new DiscordUser { Id = value3.Id, Discord = base.Discord }; } break; } case AuditLogActionType.BotAdd: entry = new DiscordAuditLogBotAddEntry(); if (base.Discord is DiscordClient discordClient3 && xac.TargetId.HasValue) { discordClient3.UserCache.TryGetValue(xac.TargetId.Value, out var value13); (entry as DiscordAuditLogBotAddEntry).TargetBot = value13 ?? new DiscordUser { Id = xac.TargetId.Value, Discord = base.Discord }; } break; case AuditLogActionType.MemberMove: entry = new DiscordAuditLogMemberMoveEntry(); if (xac.Options != null) { DiscordAuditLogMemberMoveEntry obj = entry as DiscordAuditLogMemberMoveEntry; obj.UserCount = xac.Options.Count; obj.Channel = GetChannel(xac.Options.ChannelId) ?? new DiscordChannel { Id = xac.Options.ChannelId, Discord = base.Discord, GuildId = base.Id }; } break; case AuditLogActionType.MemberDisconnect: entry = new DiscordAuditLogMemberDisconnectEntry { UserCount = (xac.Options?.Count ?? 0) }; break; case AuditLogActionType.IntegrationCreate: case AuditLogActionType.IntegrationUpdate: case AuditLogActionType.IntegrationDelete: { entry = new DiscordAuditLogIntegrationEntry(); DiscordAuditLogIntegrationEntry discordAuditLogIntegrationEntry = entry as DiscordAuditLogIntegrationEntry; foreach (AuditLogActionChange change9 in xac.Changes) { switch (change9.Key.ToLowerInvariant()) { case "enable_emoticons": discordAuditLogIntegrationEntry.EnableEmoticons = new PropertyChange { Before = (bool?)change9.OldValue, After = (bool?)change9.NewValue }; break; case "expire_behavior": discordAuditLogIntegrationEntry.ExpireBehavior = new PropertyChange { Before = (int?)change9.OldValue, After = (int?)change9.NewValue }; break; case "expire_grace_period": discordAuditLogIntegrationEntry.ExpireBehavior = new PropertyChange { Before = (int?)change9.OldValue, After = (int?)change9.NewValue }; break; default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in integration update: {Key} - this should be reported to library developers", change9.Key); break; } } break; } case AuditLogActionType.GuildScheduledEventCreate: case AuditLogActionType.GuildScheduledEventUpdate: case AuditLogActionType.GuildScheduledEventDelete: { entry = new DiscordAuditLogGuildScheduledEventEntry { Target = (events.TryGetValue(xac.TargetId.Value, out var value4) ? value4 : new DiscordScheduledGuildEvent { Id = xac.TargetId.Value, Discord = base.Discord }) }; DiscordAuditLogGuildScheduledEventEntry discordAuditLogGuildScheduledEventEntry = entry as DiscordAuditLogGuildScheduledEventEntry; foreach (AuditLogActionChange change10 in xac.Changes) { switch (change10.Key.ToLowerInvariant()) { case "name": discordAuditLogGuildScheduledEventEntry.Name = new PropertyChange { Before = ((change10.OldValue != null) ? change10.OldValueString : null), After = ((change10.NewValue != null) ? change10.NewValueString : null) }; break; case "channel_id": ulong.TryParse(change10.NewValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result7); ulong.TryParse(change10.OldValue as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out result8); discordAuditLogGuildScheduledEventEntry.Channel = new PropertyChange { Before = (GetChannel(result8) ?? new DiscordChannel { Id = result8, Discord = base.Discord, GuildId = base.Id }), After = (GetChannel(result7) ?? new DiscordChannel { Id = result7, Discord = base.Discord, GuildId = base.Id }) }; break; case "description": discordAuditLogGuildScheduledEventEntry.Description = new PropertyChange { Before = ((change10.OldValue != null) ? change10.OldValueString : null), After = ((change10.NewValue != null) ? change10.NewValueString : null) }; break; case "entity_type": discordAuditLogGuildScheduledEventEntry.Type = new PropertyChange { Before = ((change10.OldValue != null) ? new ScheduledGuildEventType?((ScheduledGuildEventType)(long)change10.OldValue) : null), After = ((change10.NewValue != null) ? new ScheduledGuildEventType?((ScheduledGuildEventType)(long)change10.NewValue) : null) }; break; case "image_hash": discordAuditLogGuildScheduledEventEntry.ImageHash = new PropertyChange { Before = (string)change10.OldValue, After = (string)change10.NewValue }; break; case "location": discordAuditLogGuildScheduledEventEntry.Location = new PropertyChange { Before = (string)change10.OldValue, After = (string)change10.NewValue }; break; case "privacy_level": discordAuditLogGuildScheduledEventEntry.PrivacyLevel = new PropertyChange { Before = ((change10.OldValue != null) ? new ScheduledGuildEventPrivacyLevel?((ScheduledGuildEventPrivacyLevel)(long)change10.OldValue) : null), After = ((change10.NewValue != null) ? new ScheduledGuildEventPrivacyLevel?((ScheduledGuildEventPrivacyLevel)(long)change10.NewValue) : null) }; break; case "status": discordAuditLogGuildScheduledEventEntry.Status = new PropertyChange { Before = ((change10.OldValue != null) ? new ScheduledGuildEventStatus?((ScheduledGuildEventStatus)(long)change10.OldValue) : null), After = ((change10.NewValue != null) ? new ScheduledGuildEventStatus?((ScheduledGuildEventStatus)(long)change10.NewValue) : null) }; break; default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in scheduled event update: {Key} - this should be reported to library developers", change10.Key); break; } } break; } case AuditLogActionType.ThreadCreate: case AuditLogActionType.ThreadUpdate: case AuditLogActionType.ThreadDelete: { entry = new DiscordAuditLogThreadEventEntry { Target = (Threads.TryGetValue(xac.TargetId.Value, out var value) ? value : new DiscordThreadChannel { Id = xac.TargetId.Value, Discord = base.Discord }) }; DiscordAuditLogThreadEventEntry discordAuditLogThreadEventEntry = entry as DiscordAuditLogThreadEventEntry; foreach (AuditLogActionChange change11 in xac.Changes) { switch (change11.Key.ToLowerInvariant()) { case "name": discordAuditLogThreadEventEntry.Name = new PropertyChange { Before = ((change11.OldValue != null) ? change11.OldValueString : null), After = ((change11.NewValue != null) ? change11.NewValueString : null) }; break; case "type": discordAuditLogThreadEventEntry.Type = new PropertyChange { Before = ((change11.OldValue != null) ? new ChannelType?((ChannelType)change11.OldValueLong) : null), After = ((change11.NewValue != null) ? new ChannelType?((ChannelType)change11.NewValueLong) : null) }; break; case "archived": discordAuditLogThreadEventEntry.Archived = new PropertyChange { Before = ((change11.OldValue != null) ? new bool?(change11.OldValueBool) : null), After = ((change11.NewValue != null) ? new bool?(change11.NewValueBool) : null) }; break; case "auto_archive_duration": discordAuditLogThreadEventEntry.AutoArchiveDuration = new PropertyChange { Before = ((change11.OldValue != null) ? new int?((int)change11.OldValueLong) : null), After = ((change11.NewValue != null) ? new int?((int)change11.NewValueLong) : null) }; break; case "invitable": discordAuditLogThreadEventEntry.Invitable = new PropertyChange { Before = ((change11.OldValue != null) ? new bool?(change11.OldValueBool) : null), After = ((change11.NewValue != null) ? new bool?(change11.NewValueBool) : null) }; break; case "locked": discordAuditLogThreadEventEntry.Locked = new PropertyChange { Before = ((change11.OldValue != null) ? new bool?(change11.OldValueBool) : null), After = ((change11.NewValue != null) ? new bool?(change11.NewValueBool) : null) }; break; case "rate_limit_per_user": discordAuditLogThreadEventEntry.PerUserRateLimit = new PropertyChange { Before = ((change11.OldValue != null) ? new int?((int)change11.OldValueLong) : null), After = ((change11.NewValue != null) ? new int?((int)change11.NewValueLong) : null) }; break; default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown key in thread update: {Key} - this should be reported to library developers", change11.Key); break; } } break; } default: base.Discord.Logger.LogWarning(LoggerEvents.AuditLog, "Unknown audit log action type: {0} - this should be reported to library developers", (int)xac.ActionType); break; } if (entry != null) { DiscordAuditLogEntry discordAuditLogEntry = entry; AuditLogActionCategory actionCategory; switch (xac.ActionType) { case AuditLogActionType.ChannelCreate: case AuditLogActionType.OverwriteCreate: case AuditLogActionType.RoleCreate: case AuditLogActionType.InviteCreate: case AuditLogActionType.WebhookCreate: case AuditLogActionType.EmojiCreate: case AuditLogActionType.IntegrationCreate: case AuditLogActionType.StickerCreate: actionCategory = AuditLogActionCategory.Create; break; case AuditLogActionType.ChannelDelete: case AuditLogActionType.OverwriteDelete: case AuditLogActionType.RoleDelete: case AuditLogActionType.InviteDelete: case AuditLogActionType.WebhookDelete: case AuditLogActionType.EmojiDelete: case AuditLogActionType.MessageDelete: case AuditLogActionType.MessageBulkDelete: case AuditLogActionType.IntegrationDelete: case AuditLogActionType.StickerDelete: actionCategory = AuditLogActionCategory.Delete; break; case AuditLogActionType.ChannelUpdate: case AuditLogActionType.OverwriteUpdate: case AuditLogActionType.MemberUpdate: case AuditLogActionType.MemberRoleUpdate: case AuditLogActionType.RoleUpdate: case AuditLogActionType.InviteUpdate: case AuditLogActionType.WebhookUpdate: case AuditLogActionType.EmojiUpdate: case AuditLogActionType.IntegrationUpdate: case AuditLogActionType.StickerUpdate: actionCategory = AuditLogActionCategory.Update; break; default: actionCategory = AuditLogActionCategory.Other; break; } discordAuditLogEntry.ActionCategory = actionCategory; entry.Discord = base.Discord; entry.ActionType = xac.ActionType; entry.Id = xac.Id; entry.Reason = xac.Reason; entry.UserResponsible = amd[xac.UserId]; entries.Add(entry); } } return new ReadOnlyCollection(entries); } public Task> GetEmojisAsync() { return base.Discord.ApiClient.GetGuildEmojisAsync(base.Id); } public Task GetEmojiAsync(ulong id) { return base.Discord.ApiClient.GetGuildEmojiAsync(base.Id, id); } public Task CreateEmojiAsync(string name, Stream image, IEnumerable roles = null, string reason = null) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException("name"); } name = name.Trim(); if (name.Length < 2 || name.Length > 50) { throw new ArgumentException("Emoji name needs to be between 2 and 50 characters long."); } if (image == null) { throw new ArgumentNullException("image"); } string imageb = null; using (ImageTool imageTool = new ImageTool(image)) { imageb = imageTool.GetBase64(); } return base.Discord.ApiClient.CreateGuildEmojiAsync(base.Id, name, imageb, roles?.Select((DiscordRole xr) => xr.Id), reason); } public Task ModifyEmojiAsync(DiscordGuildEmoji emoji, string name, IEnumerable roles = null, string reason = null) { if (emoji == null) { throw new ArgumentNullException("emoji"); } if (emoji.Guild.Id != base.Id) { throw new ArgumentException("This emoji does not belong to this guild."); } if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException("name"); } name = name.Trim(); if (name.Length >= 2 && name.Length <= 50) { return base.Discord.ApiClient.ModifyGuildEmojiAsync(base.Id, emoji.Id, name, roles?.Select((DiscordRole xr) => xr.Id), reason); } throw new ArgumentException("Emoji name needs to be between 2 and 50 characters long."); } public Task DeleteEmojiAsync(DiscordGuildEmoji emoji, string reason = null) { if (emoji == null) { throw new ArgumentNullException("emoji"); } if (emoji.Guild.Id == base.Id) { return base.Discord.ApiClient.DeleteGuildEmojiAsync(base.Id, emoji.Id, reason); } throw new ArgumentException("This emoji does not belong to this guild."); } public DiscordChannel GetDefaultChannel() { return (from xc in _channels?.Values where xc.Type == ChannelType.Text orderby xc.Position select xc).FirstOrDefault((DiscordChannel xc) => (xc.PermissionsFor(CurrentMember) & DSharpPlus.Permissions.AccessChannels) == DSharpPlus.Permissions.AccessChannels); } public Task GetWidgetAsync() { return base.Discord.ApiClient.GetGuildWidgetAsync(base.Id); } public Task GetWidgetSettingsAsync() { return base.Discord.ApiClient.GetGuildWidgetSettingsAsync(base.Id); } public Task ModifyWidgetSettingsAsync(bool? isEnabled = null, DiscordChannel channel = null, string reason = null) { return base.Discord.ApiClient.ModifyGuildWidgetSettingsAsync(base.Id, isEnabled, channel?.Id, reason); } public Task> GetTemplatesAsync() { return base.Discord.ApiClient.GetGuildTemplatesAsync(base.Id); } public Task CreateTemplateAsync(string name, string description = null) { return base.Discord.ApiClient.CreateGuildTemplateAsync(base.Id, name, description); } public Task SyncTemplateAsync(string code) { return base.Discord.ApiClient.SyncGuildTemplateAsync(base.Id, code); } public Task ModifyTemplateAsync(string code, string name = null, string description = null) { return base.Discord.ApiClient.ModifyGuildTemplateAsync(base.Id, code, name, description); } public Task DeleteTemplateAsync(string code) { return base.Discord.ApiClient.DeleteGuildTemplateAsync(base.Id, code); } public Task GetMembershipScreeningFormAsync() { return base.Discord.ApiClient.GetGuildMembershipScreeningFormAsync(base.Id); } public Task ModifyMembershipScreeningFormAsync(Action action) { MembershipScreeningEditModel membershipScreeningEditModel = new MembershipScreeningEditModel(); action(membershipScreeningEditModel); return base.Discord.ApiClient.ModifyGuildMembershipScreeningFormAsync(base.Id, membershipScreeningEditModel.Enabled, membershipScreeningEditModel.Fields, membershipScreeningEditModel.Description); } public Task> GetStickersAsync() { return base.Discord.ApiClient.GetGuildStickersAsync(base.Id); } public Task GetStickerAsync(ulong stickerId) { return base.Discord.ApiClient.GetGuildStickerAsync(base.Id, stickerId); } public Task CreateStickerAsync(string name, string description, string tags, Stream imageContents, StickerFormat format, string reason = null) { string text = null; string text2 = null; if (format == StickerFormat.PNG || format == StickerFormat.APNG) { text = "image/png"; text2 = "png"; } else { if (!Features.Contains("PARTNERED") && !Features.Contains("VERIFIED")) { throw new InvalidOperationException("Lottie stickers can only be created on partnered or verified guilds."); } text = "application/json"; text2 = "json"; } return base.Discord.ApiClient.CreateGuildStickerAsync(base.Id, name, description ?? string.Empty, tags, new DiscordMessageFile(null, imageContents, null, text2, text), reason); } public Task ModifyStickerAsync(ulong stickerId, Action action, string reason = null) { StickerEditModel stickerEditModel = new StickerEditModel(); action(stickerEditModel); return base.Discord.ApiClient.ModifyStickerAsync(base.Id, stickerId, stickerEditModel.Name, stickerEditModel.Description, stickerEditModel.Tags, reason ?? stickerEditModel.AuditLogReason); } public Task ModifyStickerAsync(DiscordMessageSticker sticker, Action action, string reason = null) { StickerEditModel stickerEditModel = new StickerEditModel(); action(stickerEditModel); return base.Discord.ApiClient.ModifyStickerAsync(base.Id, sticker.Id, stickerEditModel.Name, stickerEditModel.Description, stickerEditModel.Tags, reason ?? stickerEditModel.AuditLogReason); } public Task DeleteStickerAsync(ulong stickerId, string reason = null) { return base.Discord.ApiClient.DeleteStickerAsync(base.Id, stickerId, reason); } public Task DeleteStickerAsync(DiscordMessageSticker sticker, string reason = null) { return base.Discord.ApiClient.DeleteStickerAsync(base.Id, sticker.Id, reason); } public Task> GetApplicationCommandsAsync() { return base.Discord.ApiClient.GetGuildApplicationCommandsAsync(base.Discord.CurrentApplication.Id, base.Id); } public Task> BulkOverwriteApplicationCommandsAsync(IEnumerable commands) { return base.Discord.ApiClient.BulkOverwriteGuildApplicationCommandsAsync(base.Discord.CurrentApplication.Id, base.Id, commands); } public Task CreateApplicationCommandAsync(DiscordApplicationCommand command) { return base.Discord.ApiClient.CreateGuildApplicationCommandAsync(base.Discord.CurrentApplication.Id, base.Id, command); } public async Task EditApplicationCommandAsync(ulong commandId, Action action) { ApplicationCommandEditModel applicationCommandEditModel = new ApplicationCommandEditModel(); action(applicationCommandEditModel); return await base.Discord.ApiClient.EditGuildApplicationCommandAsync(base.Discord.CurrentApplication.Id, base.Id, commandId, applicationCommandEditModel.Name, applicationCommandEditModel.Description, applicationCommandEditModel.Options, applicationCommandEditModel.DefaultPermission, null, null, applicationCommandEditModel.AllowDMUsage, applicationCommandEditModel.DefaultMemberPermissions).ConfigureAwait(continueOnCapturedContext: false); } public Task GetApplicationCommandAsync(ulong commandId) { return base.Discord.ApiClient.GetGlobalApplicationCommandAsync(base.Discord.CurrentApplication.Id, commandId); } public async Task GetApplicationCommandAsync(string commandName) { foreach (DiscordApplicationCommand item in await base.Discord.ApiClient.GetGlobalApplicationCommandsAsync(base.Discord.CurrentApplication.Id)) { if (item.Name == commandName) { return item; } } return null; } public Task GetWelcomeScreenAsync() { return base.Discord.ApiClient.GetGuildWelcomeScreenAsync(base.Id); } public async Task ModifyWelcomeScreenAsync(Action action, string reason = null) { WelcomeScreenEditModel welcomeScreenEditModel = new WelcomeScreenEditModel(); action(welcomeScreenEditModel); return await base.Discord.ApiClient.ModifyGuildWelcomeScreenAsync(base.Id, welcomeScreenEditModel.Enabled, welcomeScreenEditModel.WelcomeChannels, welcomeScreenEditModel.Description, reason).ConfigureAwait(continueOnCapturedContext: false); } public Task> GetApplicationCommandsPermissionsAsync() { return base.Discord.ApiClient.GetGuildApplicationCommandPermissionsAsync(base.Discord.CurrentApplication.Id, base.Id); } public Task GetApplicationCommandPermissionsAsync(DiscordApplicationCommand command) { return base.Discord.ApiClient.GetApplicationCommandPermissionsAsync(base.Discord.CurrentApplication.Id, base.Id, command.Id); } public Task EditApplicationCommandPermissionsAsync(DiscordApplicationCommand command, IEnumerable permissions) { return base.Discord.ApiClient.EditApplicationCommandPermissionsAsync(base.Discord.CurrentApplication.Id, base.Id, command.Id, permissions); } public Task> BatchEditApplicationCommandPermissionsAsync(IEnumerable permissions) { return base.Discord.ApiClient.BatchEditApplicationCommandPermissionsAsync(base.Discord.CurrentApplication.Id, base.Id, permissions); } public override string ToString() { return $"Guild {base.Id}; {Name}"; } public override bool Equals(object obj) { return Equals(obj as DiscordGuild); } public bool Equals(DiscordGuild e) { if ((object)e == null) { return false; } if ((object)this != e) { return base.Id == e.Id; } return true; } public override int GetHashCode() { return base.Id.GetHashCode(); } public static bool operator ==(DiscordGuild e1, DiscordGuild e2) { if (((object)e1 == null && (object)e2 != null) || ((object)e1 != null && (object)e2 == null)) { return false; } if ((object)e1 != null || (object)e2 != null) { return e1.Id == e2.Id; } return true; } public static bool operator !=(DiscordGuild e1, DiscordGuild e2) { return !(e1 == e2); } } internal enum VerificationLevel { None, Low, Medium, High, Highest } internal enum DefaultMessageNotifications { AllMessages, MentionsOnly } internal enum MfaLevel { Disabled, Enabled } internal enum ExplicitContentFilter { Disabled, MembersWithoutRoles, AllMembers } internal enum WidgetType { Shield, Banner1, Banner2, Banner3, Banner4 } internal class DiscordGuildEmbed { [JsonProperty("enabled", NullValueHandling = NullValueHandling.Ignore)] public bool IsEnabled { get; set; } [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)] public ulong ChannelId { get; set; } } internal sealed class DiscordGuildEmoji : DiscordEmoji { [Newtonsoft.Json.JsonIgnore] public DiscordUser User { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild { get; internal set; } internal DiscordGuildEmoji() { } public Task ModifyAsync(string name, IEnumerable roles = null, string reason = null) { return Guild.ModifyEmojiAsync(this, name, roles, reason); } public Task DeleteAsync(string reason = null) { return Guild.DeleteEmojiAsync(this, reason); } } internal class DiscordGuildMembershipScreening { [JsonProperty("version")] public DateTimeOffset Version { get; internal set; } [JsonProperty("form_fields")] public IReadOnlyList Fields { get; internal set; } [JsonProperty("description")] public string Description { get; internal set; } } internal class DiscordGuildMembershipScreeningField { [JsonProperty("field_type", NullValueHandling = NullValueHandling.Ignore)] public MembershipScreeningFieldType Type { get; internal set; } [JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)] public string Label { get; internal set; } [JsonProperty("values", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Values { get; internal set; } [JsonProperty("required", NullValueHandling = NullValueHandling.Ignore)] public bool IsRequired { get; internal set; } public DiscordGuildMembershipScreeningField(MembershipScreeningFieldType type, string label, IEnumerable values, bool required = true) { Type = type; Label = label; Values = values.ToList(); IsRequired = required; } internal DiscordGuildMembershipScreeningField() { } } internal class DiscordGuildPreview : SnowflakeObject { [JsonProperty("emojis", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(SnowflakeArrayAsDictionaryJsonConverter))] internal ConcurrentDictionary _emojis; [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("icon", NullValueHandling = NullValueHandling.Ignore)] public string Icon { get; internal set; } [JsonProperty("splash", NullValueHandling = NullValueHandling.Ignore)] public string Splash { get; internal set; } [JsonProperty("discovery_splash", NullValueHandling = NullValueHandling.Ignore)] public string DiscoverySplash { get; internal set; } [Newtonsoft.Json.JsonIgnore] public IReadOnlyDictionary Emojis => new ReadOnlyConcurrentDictionary(_emojis); [JsonProperty("features", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Features { get; internal set; } [JsonProperty("approximate_member_count")] public int ApproximateMemberCount { get; internal set; } [JsonProperty("approximate_presence_count")] public int ApproximatePresenceCount { get; internal set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; internal set; } internal DiscordGuildPreview() { } } internal class DiscordGuildTemplate { [JsonProperty("code", NullValueHandling = NullValueHandling.Ignore)] public string Code { get; internal set; } [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; internal set; } [JsonProperty("usage_count", NullValueHandling = NullValueHandling.Ignore)] public int UsageCount { get; internal set; } [JsonProperty("creator_id", NullValueHandling = NullValueHandling.Ignore)] public ulong CreatorId { get; internal set; } [JsonProperty("creator", NullValueHandling = NullValueHandling.Ignore)] public DiscordUser Creator { get; internal set; } [JsonProperty("created_at", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset CreatedAt { get; internal set; } [JsonProperty("updated_at", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset UpdatedAt { get; internal set; } [JsonProperty("source_guild_id", NullValueHandling = NullValueHandling.Ignore)] public ulong SourceGuildId { get; internal set; } [JsonProperty("serialized_source_guild", NullValueHandling = NullValueHandling.Ignore)] public DiscordGuild SourceGuild { get; internal set; } [JsonProperty("is_dirty", NullValueHandling = NullValueHandling.Ignore)] public bool? IsDirty { get; internal set; } } internal class DiscordGuildWelcomeScreen { [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; internal set; } [JsonProperty("welcome_channels", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList WelcomeChannels { get; internal set; } } internal class DiscordGuildWelcomeScreenChannel { [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)] public ulong ChannelId { get; internal set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; internal set; } [JsonProperty("emoji_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? EmojiId { get; internal set; } [JsonProperty("emoji_name", NullValueHandling = NullValueHandling.Ignore)] public string EmojiName { get; internal set; } public DiscordGuildWelcomeScreenChannel(ulong channelId, string description, DiscordEmoji emoji = null) { ChannelId = channelId; Description = description; if (emoji != null) { if (emoji.Id == 0L) { EmojiName = emoji.Name; } else { EmojiId = emoji.Id; } } } } internal class DiscordMember : DiscordUser, IEquatable { [Newtonsoft.Json.JsonIgnore] internal string _avatarHash; [JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)] internal List _role_ids; [Newtonsoft.Json.JsonIgnore] private readonly Lazy> _role_ids_lazy; [Newtonsoft.Json.JsonIgnore] internal ulong _guild_id; [Newtonsoft.Json.JsonIgnore] public string GuildAvatarHash => _avatarHash; [Newtonsoft.Json.JsonIgnore] public string GuildAvatarUrl { get { if (!string.IsNullOrWhiteSpace(GuildAvatarHash)) { return string.Format("https://cdn.discordapp.com{0}/{1}{2}/{3}{4}/{5}.{6}?size=1024", "/guilds", _guild_id, "/users", base.Id, "/avatars", GuildAvatarHash, GuildAvatarHash.StartsWith("a_") ? "gif" : "png"); } return null; } } [JsonProperty("nick", NullValueHandling = NullValueHandling.Ignore)] public string Nickname { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string DisplayName => Nickname ?? Username; [JsonProperty("communication_disabled_until", NullValueHandling = NullValueHandling.Include)] public DateTimeOffset? CommunicationDisabledUntil { get; internal set; } [Newtonsoft.Json.JsonIgnore] internal IReadOnlyList RoleIds => _role_ids_lazy.Value; [Newtonsoft.Json.JsonIgnore] public IEnumerable Roles => from id in RoleIds select Guild.GetRole(id) into x where x != null select x; [Newtonsoft.Json.JsonIgnore] public DiscordColor Color { get { DiscordRole discordRole = Roles.OrderByDescending((DiscordRole xr) => xr.Position).FirstOrDefault((DiscordRole xr) => xr.Color.Value != 0); if (!(discordRole != null)) { return default(DiscordColor); } return discordRole.Color; } } [JsonProperty("joined_at", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset JoinedAt { get; internal set; } [JsonProperty("premium_since", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset? PremiumSince { get; internal set; } [JsonProperty("is_deafened", NullValueHandling = NullValueHandling.Ignore)] public bool IsDeafened { get; internal set; } [JsonProperty("is_muted", NullValueHandling = NullValueHandling.Ignore)] public bool IsMuted { get; internal set; } [JsonProperty("pending", NullValueHandling = NullValueHandling.Ignore)] public bool? IsPending { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DiscordVoiceState VoiceState { get { if (!base.Discord.Guilds[_guild_id].VoiceStates.TryGetValue(base.Id, out var value)) { return null; } return value; } } [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild => base.Discord.Guilds[_guild_id]; [Newtonsoft.Json.JsonIgnore] public bool IsOwner => base.Id == Guild.OwnerId; [Newtonsoft.Json.JsonIgnore] public int Hierarchy { get { if (!IsOwner) { if (RoleIds.Count != 0) { return Roles.Max((DiscordRole x) => x.Position); } return 0; } return int.MaxValue; } } [Newtonsoft.Json.JsonIgnore] public Permissions Permissions => GetPermissions(); [Newtonsoft.Json.JsonIgnore] internal DiscordUser User => base.Discord.UserCache[base.Id]; [Newtonsoft.Json.JsonIgnore] public override string Username { get { return User.Username; } internal set { User.Username = value; } } [Newtonsoft.Json.JsonIgnore] public override string Discriminator { get { return User.Discriminator; } internal set { User.Discriminator = value; } } [Newtonsoft.Json.JsonIgnore] public override string BannerHash { get { return User.BannerHash; } internal set { User.BannerHash = value; } } [Newtonsoft.Json.JsonIgnore] public override DiscordColor? BannerColor => User.BannerColor; [Newtonsoft.Json.JsonIgnore] public override string AvatarHash { get { return User.AvatarHash; } internal set { User.AvatarHash = value; } } [Newtonsoft.Json.JsonIgnore] public override bool IsBot { get { return User.IsBot; } internal set { User.IsBot = value; } } [Newtonsoft.Json.JsonIgnore] public override string Email { get { return User.Email; } internal set { User.Email = value; } } [Newtonsoft.Json.JsonIgnore] public override bool? MfaEnabled { get { return User.MfaEnabled; } internal set { User.MfaEnabled = value; } } [Newtonsoft.Json.JsonIgnore] public override bool? Verified { get { return User.Verified; } internal set { User.Verified = value; } } [Newtonsoft.Json.JsonIgnore] public override string Locale { get { return User.Locale; } internal set { User.Locale = value; } } [Newtonsoft.Json.JsonIgnore] public override UserFlags? OAuthFlags { get { return User.OAuthFlags; } internal set { User.OAuthFlags = value; } } [Newtonsoft.Json.JsonIgnore] public override UserFlags? Flags { get { return User.Flags; } internal set { User.Flags = value; } } internal DiscordMember() { _role_ids_lazy = new Lazy>(() => new ReadOnlyCollection(_role_ids)); } internal DiscordMember(DiscordUser user) { base.Discord = user.Discord; base.Id = user.Id; _role_ids = new List(); _role_ids_lazy = new Lazy>(() => new ReadOnlyCollection(_role_ids)); } internal DiscordMember(TransportMember member) { base.Id = member.User.Id; IsDeafened = member.IsDeafened; IsMuted = member.IsMuted; JoinedAt = member.JoinedAt; Nickname = member.Nickname; PremiumSince = member.PremiumSince; IsPending = member.IsPending; _avatarHash = member.AvatarHash; _role_ids = member.Roles ?? new List(); _role_ids_lazy = new Lazy>(() => new ReadOnlyCollection(_role_ids)); CommunicationDisabledUntil = member.CommunicationDisabledUntil; } public Task CreateDmChannelAsync() { DiscordDmChannel discordDmChannel = null; if (base.Discord is DiscordClient discordClient) { discordDmChannel = discordClient._privateChannels.Values.FirstOrDefault((DiscordDmChannel x) => x.Recipients.FirstOrDefault() == this); } if (!(discordDmChannel != null)) { return base.Discord.ApiClient.CreateDmAsync(base.Id); } return Task.FromResult(discordDmChannel); } public async Task SendMessageAsync(string content) { if (IsBot && base.Discord.CurrentUser.IsBot) { throw new ArgumentException("Bots cannot DM each other."); } return await (await CreateDmChannelAsync().ConfigureAwait(continueOnCapturedContext: false)).SendMessageAsync(content).ConfigureAwait(continueOnCapturedContext: false); } public async Task SendMessageAsync(DiscordEmbed embed) { if (IsBot && base.Discord.CurrentUser.IsBot) { throw new ArgumentException("Bots cannot DM each other."); } return await (await CreateDmChannelAsync().ConfigureAwait(continueOnCapturedContext: false)).SendMessageAsync(embed).ConfigureAwait(continueOnCapturedContext: false); } public async Task SendMessageAsync(string content, DiscordEmbed embed) { if (IsBot && base.Discord.CurrentUser.IsBot) { throw new ArgumentException("Bots cannot DM each other."); } return await (await CreateDmChannelAsync().ConfigureAwait(continueOnCapturedContext: false)).SendMessageAsync(content, embed).ConfigureAwait(continueOnCapturedContext: false); } public async Task SendMessageAsync(DiscordMessageBuilder message) { if (IsBot && base.Discord.CurrentUser.IsBot) { throw new ArgumentException("Bots cannot DM each other."); } return await (await CreateDmChannelAsync().ConfigureAwait(continueOnCapturedContext: false)).SendMessageAsync(message).ConfigureAwait(continueOnCapturedContext: false); } public Task TimeoutAsync(DateTimeOffset? until, string reason = null) { return base.Discord.ApiClient.ModifyGuildMemberAsync(_guild_id, base.Id, default(Optional), default(Optional>), default(Optional), default(Optional), default(Optional), until, reason); } public Task SetMuteAsync(bool mute, string reason = null) { return base.Discord.ApiClient.ModifyGuildMemberAsync(_guild_id, base.Id, default(Optional), default(Optional>), mute, default(Optional), default(Optional), default(Optional), reason); } public Task SetDeafAsync(bool deaf, string reason = null) { return base.Discord.ApiClient.ModifyGuildMemberAsync(_guild_id, base.Id, default(Optional), default(Optional>), default(Optional), deaf, default(Optional), default(Optional), reason); } public async Task ModifyAsync(Action action) { MemberEditModel mdl = new MemberEditModel(); action(mdl); if (mdl.VoiceChannel.HasValue && mdl.VoiceChannel.Value != null && mdl.VoiceChannel.Value.Type != ChannelType.Voice && mdl.VoiceChannel.Value.Type != ChannelType.Stage) { throw new ArgumentException("Given channel is not a voice or stage channel.", "VoiceChannel"); } if (!mdl.Nickname.HasValue || base.Discord.CurrentUser.Id != base.Id) { await base.Discord.ApiClient.ModifyGuildMemberAsync(Guild.Id, base.Id, mdl.Nickname, mdl.Roles.IfPresent((List e) => e.Select((DiscordRole xr) => xr.Id)), mdl.Muted, mdl.Deafened, mdl.VoiceChannel.IfPresent((DiscordChannel e) => e?.Id), mdl.CommunicationDisabledUntil, mdl.AuditLogReason).ConfigureAwait(continueOnCapturedContext: false); return; } await base.Discord.ApiClient.ModifyCurrentMemberAsync(Guild.Id, mdl.Nickname.Value, mdl.AuditLogReason).ConfigureAwait(continueOnCapturedContext: false); await base.Discord.ApiClient.ModifyGuildMemberAsync(Guild.Id, base.Id, Optional.FromNoValue(), mdl.Roles.IfPresent((List e) => e.Select((DiscordRole xr) => xr.Id)), mdl.Muted, mdl.Deafened, mdl.VoiceChannel.IfPresent((DiscordChannel e) => e?.Id), default(Optional), mdl.AuditLogReason).ConfigureAwait(continueOnCapturedContext: false); } public Task GrantRoleAsync(DiscordRole role, string reason = null) { return base.Discord.ApiClient.AddGuildMemberRoleAsync(Guild.Id, base.Id, role.Id, reason); } public Task RevokeRoleAsync(DiscordRole role, string reason = null) { return base.Discord.ApiClient.RemoveGuildMemberRoleAsync(Guild.Id, base.Id, role.Id, reason); } public Task ReplaceRolesAsync(IEnumerable roles, string reason = null) { return base.Discord.ApiClient.ModifyGuildMemberAsync(Guild.Id, base.Id, default(Optional), new Optional>(roles.Select((DiscordRole xr) => xr.Id)), default(Optional), default(Optional), default(Optional), default(Optional), reason); } public Task BanAsync(int delete_message_days = 0, string reason = null) { return Guild.BanMemberAsync(this, delete_message_days, reason); } public Task UnbanAsync(string reason = null) { return Guild.UnbanMemberAsync(this, reason); } public Task RemoveAsync(string reason = null) { return base.Discord.ApiClient.RemoveGuildMemberAsync(_guild_id, base.Id, reason); } public Task PlaceInAsync(DiscordChannel channel) { return channel.PlaceMemberAsync(this); } public async Task UpdateVoiceStateAsync(DiscordChannel channel, bool? suppress) { if (channel.Type != ChannelType.Stage) { throw new ArgumentException("Voice state can only be updated in a stage channel."); } await base.Discord.ApiClient.UpdateUserVoiceStateAsync(Guild.Id, base.Id, channel.Id, suppress).ConfigureAwait(continueOnCapturedContext: false); } public Permissions PermissionsIn(DiscordChannel channel) { return channel.PermissionsFor(this); } public string GetGuildAvatarUrl(ImageFormat imageFormat, ushort imageSize = 1024) { if (string.IsNullOrWhiteSpace(GuildAvatarHash)) { return GetAvatarUrl(imageFormat, imageSize); } if (imageFormat == ImageFormat.Unknown) { throw new ArgumentException("You must specify valid image format.", "imageFormat"); } if (imageSize < 16 || imageSize > 4096) { throw new ArgumentOutOfRangeException("Image Size is not in between 16 and 4096: imageSize"); } if (imageSize == 0 || (imageSize & (imageSize - 1)) != 0) { throw new ArgumentOutOfRangeException("Image size is not a power of two: imageSize"); } string text = imageFormat switch { ImageFormat.Gif => "gif", ImageFormat.Jpeg => "jpg", ImageFormat.Png => "png", ImageFormat.WebP => "webp", ImageFormat.Auto => string.IsNullOrWhiteSpace(GuildAvatarHash) ? "png" : (GuildAvatarHash.StartsWith("a_") ? "gif" : "png"), _ => throw new ArgumentOutOfRangeException("imageFormat"), }; string text2 = imageSize.ToString(CultureInfo.InvariantCulture); return string.Format("https://cdn.discordapp.com{0}/{1}{2}/{3}{4}/{5}.{6}?size={7}", "/guilds", _guild_id, "/users", base.Id, "/avatars", GuildAvatarHash, text, text2); } public override string ToString() { return $"Member {base.Id}; {Username}#{Discriminator} ({DisplayName})"; } public override bool Equals(object obj) { return Equals(obj as DiscordMember); } public bool Equals(DiscordMember e) { if ((object)e == null) { return false; } if ((object)this != e) { if (base.Id == e.Id) { return _guild_id == e._guild_id; } return false; } return true; } public override int GetHashCode() { return (13 * 7 + base.Id.GetHashCode()) * 7 + _guild_id.GetHashCode(); } public static bool operator ==(DiscordMember e1, DiscordMember e2) { if (((object)e1 == null && (object)e2 != null) || ((object)e1 != null && (object)e2 == null)) { return false; } if ((object)e1 != null || (object)e2 != null) { if (e1.Id == e2.Id) { return e1._guild_id == e2._guild_id; } return false; } return true; } public static bool operator !=(DiscordMember e1, DiscordMember e2) { return !(e1 == e2); } private Permissions GetPermissions() { if (Guild.OwnerId == base.Id) { return PermissionMethods.FULL_PERMS; } Permissions permissions = Guild.EveryoneRole.Permissions; permissions |= Roles.Aggregate(Permissions.None, (Permissions c, DiscordRole role) => c | role.Permissions); if ((permissions & Permissions.Administrator) == Permissions.Administrator) { return PermissionMethods.FULL_PERMS; } return permissions; } } internal class DiscordRole : SnowflakeObject, IEquatable { [JsonProperty("color", NullValueHandling = NullValueHandling.Ignore)] internal int _color; [JsonProperty("unicode_emoji")] internal string _emoji; [Newtonsoft.Json.JsonIgnore] internal ulong _guild_id; [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DiscordColor Color => new DiscordColor(_color); [JsonProperty("hoist", NullValueHandling = NullValueHandling.Ignore)] public bool IsHoisted { get; internal set; } public string IconUrl { get { if (IconHash == null) { return null; } return $"https://cdn.discordapp.com/role-icons/{base.Id}/{IconHash}.png"; } } [JsonProperty("icon")] public string IconHash { get; internal set; } public DiscordEmoji Emoji { get { if (_emoji == null) { return null; } return DiscordEmoji.FromUnicode(_emoji); } } [JsonProperty("position", NullValueHandling = NullValueHandling.Ignore)] public int Position { get; internal set; } [JsonProperty("permissions", NullValueHandling = NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions Permissions { get; internal set; } [JsonProperty("managed", NullValueHandling = NullValueHandling.Ignore)] public bool IsManaged { get; internal set; } [JsonProperty("mentionable", NullValueHandling = NullValueHandling.Ignore)] public bool IsMentionable { get; internal set; } [JsonProperty("tags", NullValueHandling = NullValueHandling.Ignore)] public DiscordRoleTags Tags { get; internal set; } public string Mention => Formatter.Mention(this); public Task ModifyPositionAsync(int position, string reason = null) { DiscordRole[] array = base.Discord.Guilds[_guild_id].Roles.Values.OrderByDescending((DiscordRole xr) => xr.Position).ToArray(); RestGuildRoleReorderPayload[] array2 = new RestGuildRoleReorderPayload[array.Length]; for (int i = 0; i < array.Length; i++) { array2[i] = new RestGuildRoleReorderPayload { RoleId = array[i].Id }; array2[i].Position = ((array[i].Id == base.Id) ? position : ((array[i].Position <= position) ? (array[i].Position - 1) : array[i].Position)); } return base.Discord.ApiClient.ModifyGuildRolePositionAsync(_guild_id, array2, reason); } public Task ModifyAsync(string name = null, Permissions? permissions = null, DiscordColor? color = null, bool? hoist = null, bool? mentionable = null, string reason = null, Stream icon = null, DiscordEmoji emoji = null) { return base.Discord.ApiClient.ModifyGuildRoleAsync(_guild_id, base.Id, name, permissions, color?.Value, hoist, mentionable, reason, icon, emoji?.ToString()); } public Task ModifyAsync(Action action) { RoleEditModel roleEditModel = new RoleEditModel(); action(roleEditModel); return ModifyAsync(roleEditModel.Name, roleEditModel.Permissions, roleEditModel.Color, roleEditModel.Hoist, roleEditModel.Mentionable, roleEditModel.AuditLogReason, roleEditModel.Icon, roleEditModel.Emoji); } public Task DeleteAsync(string reason = null) { return base.Discord.ApiClient.DeleteRoleAsync(_guild_id, base.Id, reason); } internal DiscordRole() { } public PermissionLevel CheckPermission(Permissions permission) { if ((Permissions & permission) == Permissions.None) { return PermissionLevel.Unset; } return PermissionLevel.Allowed; } public override string ToString() { return $"Role {base.Id}; {Name}"; } public override bool Equals(object obj) { return Equals(obj as DiscordRole); } public bool Equals(DiscordRole e) { if ((object)e == null) { return false; } return (object)this == e || base.Id == e.Id; } public override int GetHashCode() { return base.Id.GetHashCode(); } public static bool operator ==(DiscordRole e1, DiscordRole e2) { if ((object)e1 == null == ((object)e2 == null)) { if ((object)e1 != null || (object)e2 != null) { return e1.Id == e2.Id; } return true; } return false; } public static bool operator !=(DiscordRole e1, DiscordRole e2) { return !(e1 == e2); } } internal class DiscordRoleTags { [JsonProperty("premium_subscriber", NullValueHandling = NullValueHandling.Include)] internal Optional _premiumSubscriber = false; [JsonProperty("bot_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? BotId { get; internal set; } [JsonProperty("integration_id", NullValueHandling = NullValueHandling.Ignore)] public ulong? IntegrationId { get; internal set; } [Newtonsoft.Json.JsonIgnore] public bool IsPremiumSubscriber { get { if (_premiumSubscriber.HasValue) { return !_premiumSubscriber.Value.HasValue; } return false; } } } internal sealed class DiscordScheduledGuildEvent : SnowflakeObject { [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("description")] public string Description { get; internal set; } [JsonProperty("scheduled_start_time")] public DateTimeOffset StartTime { get; internal set; } [JsonProperty("scheduled_end_time")] public DateTimeOffset? EndTime { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild => (base.Discord as DiscordClient).InternalGetCachedGuild(GuildId); [Newtonsoft.Json.JsonIgnore] public DiscordChannel Channel { get { if (!ChannelId.HasValue) { return null; } return Guild.GetChannel(ChannelId.Value); } } [JsonProperty("channel_id")] public ulong? ChannelId { get; internal set; } [JsonProperty("guild_id")] public ulong GuildId { get; set; } [JsonProperty("creator")] public DiscordUser Creator { get; internal set; } [JsonProperty("privacy_level")] public ScheduledGuildEventPrivacyLevel PrivacyLevel { get; internal set; } [JsonProperty("status")] public ScheduledGuildEventStatus Status { get; internal set; } [JsonProperty("entity_metadata")] public DiscordScheduledGuildEventMetadata Metadata { get; internal set; } [JsonProperty("entity_type")] public ScheduledGuildEventType Type { get; internal set; } [JsonProperty("user_count")] public int? UserCount { get; internal set; } internal DiscordScheduledGuildEvent() { } } internal sealed class DiscordScheduledGuildEventMetadata { [JsonProperty("location")] public string Location { get; internal set; } internal DiscordScheduledGuildEventMetadata() { } public DiscordScheduledGuildEventMetadata(string location) { Location = location; } } internal enum ScheduledGuildEventPrivacyLevel { Public = 1, GuildOnly } internal enum ScheduledGuildEventStatus { Scheduled = 1, Active, Completed, Cancelled } internal enum ScheduledGuildEventType { StageInstance = 1, VoiceChannel, External } internal class DiscordWidget : SnowflakeObject { [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild { get; internal set; } [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("instant_invite", NullValueHandling = NullValueHandling.Ignore)] public string InstantInviteUrl { get; internal set; } [JsonProperty("presence_count", NullValueHandling = NullValueHandling.Ignore)] public int PresenceCount { get; internal set; } [JsonProperty("members", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Members { get; internal set; } [Newtonsoft.Json.JsonIgnore] public IReadOnlyList Channels { get; internal set; } } internal class DiscordWidgetMember { [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public ulong Id { get; internal set; } [JsonProperty("username", NullValueHandling = NullValueHandling.Ignore)] public string Username { get; internal set; } [JsonProperty("discriminator", NullValueHandling = NullValueHandling.Ignore)] public string Discriminator { get; internal set; } [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] public string Avatar { get; internal set; } [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] public string Status { get; internal set; } [JsonProperty("avatar_url", NullValueHandling = NullValueHandling.Ignore)] public string AvatarUrl { get; internal set; } } internal class DiscordWidgetSettings { internal DiscordGuild Guild { get; set; } [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)] public ulong ChannelId { get; internal set; } public DiscordChannel Channel => Guild?.GetChannel(ChannelId); [JsonProperty("enabled", NullValueHandling = NullValueHandling.Ignore)] public bool IsEnabled { get; internal set; } } internal class DiscordIntegration : SnowflakeObject { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public string Type { get; internal set; } [JsonProperty("enabled", NullValueHandling = NullValueHandling.Ignore)] public bool IsEnabled { get; internal set; } [JsonProperty("syncing", NullValueHandling = NullValueHandling.Ignore)] public bool IsSyncing { get; internal set; } [JsonProperty("role_id", NullValueHandling = NullValueHandling.Ignore)] public ulong RoleId { get; internal set; } [JsonProperty("expire_behavior", NullValueHandling = NullValueHandling.Ignore)] public int ExpireBehavior { get; internal set; } [JsonProperty("expire_grace_period", NullValueHandling = NullValueHandling.Ignore)] public int ExpireGracePeriod { get; internal set; } [JsonProperty("user", NullValueHandling = NullValueHandling.Ignore)] public DiscordUser User { get; internal set; } [JsonProperty("account", NullValueHandling = NullValueHandling.Ignore)] public DiscordIntegrationAccount Account { get; internal set; } [JsonProperty("synced_at", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset SyncedAt { get; internal set; } internal DiscordIntegration() { } } internal class DiscordIntegrationAccount { [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public string Id { get; internal set; } [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } internal DiscordIntegrationAccount() { } } internal sealed class DiscordApplicationCommand : SnowflakeObject, IEquatable { [JsonProperty("application_id")] public ulong ApplicationId { get; internal set; } [JsonProperty("type")] public ApplicationCommandType Type { get; internal set; } [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("description")] public string Description { get; internal set; } [JsonProperty("options", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyCollection Options { get; internal set; } [JsonProperty("default_permission")] public bool? DefaultPermission { get; internal set; } [JsonProperty("dm_permission")] public bool? AllowDMUsage { get; internal set; } [JsonProperty("default_member_permissions")] [Newtonsoft.Json.JsonConverter(typeof(DiscordPermissionsJsonConverter))] public Permissions? DefaultMemberPermissions { get; internal set; } [JsonProperty("version")] public ulong Version { get; internal set; } [JsonProperty("name_localizations")] public IReadOnlyDictionary NameLocalizations { get; internal set; } [JsonProperty("description_localizations")] public IReadOnlyDictionary DescriptionLocalizations { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string Mention => Formatter.Mention(this); public DiscordApplicationCommand(string name, string description, IEnumerable options = null, bool? defaultPermission = null, ApplicationCommandType type = ApplicationCommandType.SlashCommand, IReadOnlyDictionary name_localizations = null, IReadOnlyDictionary description_localizations = null, bool? allowDMUsage = null, Permissions? defaultMemberPermissions = null) { switch (type) { case ApplicationCommandType.SlashCommand: if (!Utilities.IsValidSlashCommandName(name)) { throw new ArgumentException("Invalid slash command name specified. It must be below 32 characters and not contain any whitespace.", "name"); } if (name.Any((char ch) => char.IsUpper(ch))) { throw new ArgumentException("Slash command name cannot have any upper case characters.", "name"); } if (description.Length > 100) { throw new ArgumentException("Slash command description cannot exceed 100 characters.", "description"); } break; case ApplicationCommandType.UserContextMenu: case ApplicationCommandType.MessageContextMenu: if (options != null && options.Any()) { throw new ArgumentException("Context menus do not support options."); } break; } ReadOnlyCollection options2 = ((options != null) ? new ReadOnlyCollection(options.ToList()) : null); Type = type; Name = name; Description = description; Options = options2; DefaultPermission = defaultPermission; NameLocalizations = name_localizations; DescriptionLocalizations = description_localizations; AllowDMUsage = allowDMUsage; DefaultMemberPermissions = defaultMemberPermissions; } public string GetSubcommandMention(params string[] name) { if (!Options.Any((DiscordApplicationCommandOption x) => x.Name == name[0])) { throw new ArgumentException("Specified subgroup/subcommand doesn't exist."); } return ""; } public bool Equals(DiscordApplicationCommand other) { return base.Id == other.Id; } public static bool operator ==(DiscordApplicationCommand e1, DiscordApplicationCommand e2) { return e1.Equals(e2); } public static bool operator !=(DiscordApplicationCommand e1, DiscordApplicationCommand e2) { return !(e1 == e2); } public override bool Equals(object other) { if (!(other is DiscordApplicationCommand other2)) { return false; } return Equals(other2); } public override int GetHashCode() { return base.Id.GetHashCode(); } } internal sealed class DiscordApplicationCommandOption { [JsonProperty("type")] public ApplicationCommandOptionType Type { get; internal set; } [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("description")] public string Description { get; internal set; } [JsonProperty("autocomplete")] public bool? AutoComplete { get; internal set; } [JsonProperty("required", NullValueHandling = NullValueHandling.Ignore)] public bool? Required { get; internal set; } [JsonProperty("choices", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyCollection Choices { get; internal set; } [JsonProperty("options", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyCollection Options { get; internal set; } [JsonProperty("channel_types", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyCollection ChannelTypes { get; internal set; } [JsonProperty("min_value", NullValueHandling = NullValueHandling.Ignore)] public object MinValue { get; internal set; } [JsonProperty("max_value", NullValueHandling = NullValueHandling.Ignore)] public object MaxValue { get; internal set; } [JsonProperty("min_length", NullValueHandling = NullValueHandling.Ignore)] public int? MinLength { get; internal set; } [JsonProperty("max_length", NullValueHandling = NullValueHandling.Ignore)] public int? MaxLength { get; internal set; } [JsonProperty("name_localizations", NullValueHandling = NullValueHandling.Include)] public IReadOnlyDictionary NameLocalizations { get; internal set; } [JsonProperty("description_localizations", NullValueHandling = NullValueHandling.Include)] public IReadOnlyDictionary DescriptionLocalizations { get; internal set; } public DiscordApplicationCommandOption(string name, string description, ApplicationCommandOptionType type, bool? required = null, IEnumerable choices = null, IEnumerable options = null, IEnumerable channelTypes = null, bool? autocomplete = null, object minValue = null, object maxValue = null, IReadOnlyDictionary name_localizations = null, IReadOnlyDictionary description_localizations = null, int? minLength = null, int? maxLength = null) { if (!Utilities.IsValidSlashCommandName(name)) { throw new ArgumentException("Invalid slash command option name specified. It must be below 32 characters and not contain any whitespace.", "name"); } if (name.Any((char ch) => char.IsUpper(ch))) { throw new ArgumentException("Slash command option name cannot have any upper case characters.", "name"); } if (description.Length > 100) { throw new ArgumentException("Slash command option description cannot exceed 100 characters.", "description"); } if (autocomplete.GetValueOrDefault() && choices != null && choices.Any()) { throw new InvalidOperationException("Auto-complete slash command options cannot provide choices."); } ReadOnlyCollection choices2 = ((choices != null) ? new ReadOnlyCollection(choices.ToList()) : null); ReadOnlyCollection options2 = ((options != null) ? new ReadOnlyCollection(options.ToList()) : null); ReadOnlyCollection channelTypes2 = ((channelTypes != null) ? new ReadOnlyCollection(channelTypes.ToList()) : null); Name = name; Description = description; Type = type; AutoComplete = autocomplete; Required = required; Choices = choices2; Options = options2; ChannelTypes = channelTypes2; MinValue = minValue; MaxValue = maxValue; MinLength = minLength; MaxLength = maxLength; NameLocalizations = name_localizations; DescriptionLocalizations = description_localizations; } } internal sealed class DiscordApplicationCommandOptionChoice { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("value")] public object Value { get; set; } public DiscordApplicationCommandOptionChoice(string name, object value) { if (!(value is string) && !(value is long) && !(value is int) && !(value is double)) { throw new InvalidOperationException($"Only {typeof(string)}, {typeof(long)}, {typeof(double)} or {typeof(int)} types may be passed to a command option choice."); } if (name.Length > 100) { throw new ArgumentException("Application command choice name cannot exceed 100 characters.", "name"); } if (value is string text && text.Length > 100) { throw new ArgumentException("Application command choice value cannot exceed 100 characters.", "value"); } Name = name; Value = value; } } internal sealed class DiscordAutoCompleteChoice { [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("value")] public object Value { get; internal set; } public DiscordAutoCompleteChoice(string name, object value) { if ((!(value is string) && !(value is int) && !(value is long)) || 1 == 0) { throw new ArgumentException($"Object type must be of {typeof(int)} or {typeof(string)} or {typeof(long)}", "value"); } if (name.Length > 100) { throw new ArgumentException("Application command choice name cannot exceed 100 characters.", "name"); } if (value is string text && text.Length > 100) { throw new ArgumentException("Application command choice value cannot exceed 100 characters.", "value"); } Name = name; Value = value; } } internal sealed class DiscordActionRowComponent : DiscordComponent { [JsonProperty("components", NullValueHandling = NullValueHandling.Ignore)] private List _components; public IReadOnlyCollection Components { get { return _components ?? new List(); } set { _components = new List(value); } } public DiscordActionRowComponent(IEnumerable components) : this() { Components = components.ToList().AsReadOnly(); } internal DiscordActionRowComponent() { base.Type = ComponentType.ActionRow; } } internal sealed class DiscordButtonComponent : DiscordComponent { [JsonProperty("style", NullValueHandling = NullValueHandling.Ignore)] public ButtonStyle Style { get; internal set; } [JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)] public string Label { get; internal set; } [JsonProperty("disabled", NullValueHandling = NullValueHandling.Ignore)] public bool Disabled { get; internal set; } [JsonProperty("emoji", NullValueHandling = NullValueHandling.Ignore)] public DiscordComponentEmoji Emoji { get; internal set; } public DiscordButtonComponent Enable() { Disabled = false; return this; } public DiscordButtonComponent Disable() { Disabled = true; return this; } internal DiscordButtonComponent() { base.Type = ComponentType.Button; } public DiscordButtonComponent(DiscordButtonComponent other) : this() { base.CustomId = other.CustomId; Style = other.Style; Label = other.Label; Disabled = other.Disabled; Emoji = other.Emoji; } public DiscordButtonComponent(ButtonStyle style, string customId, string label, bool disabled = false, DiscordComponentEmoji emoji = null) { Style = style; Label = label; base.CustomId = customId; Disabled = disabled; Emoji = emoji; base.Type = ComponentType.Button; } } [Newtonsoft.Json.JsonConverter(typeof(DiscordComponentJsonConverter))] internal class DiscordComponent { [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public ComponentType Type { get; internal set; } [JsonProperty("custom_id", NullValueHandling = NullValueHandling.Ignore)] public string CustomId { get; internal set; } internal DiscordComponent() { } } internal sealed class DiscordComponentEmoji { [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public ulong Id { get; set; } [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } public DiscordComponentEmoji() { } public DiscordComponentEmoji(ulong id) { Id = id; } public DiscordComponentEmoji(string name) { if (!DiscordEmoji.IsValidUnicode(name)) { throw new ArgumentException("Only unicode emojis can be passed."); } Name = name; } public DiscordComponentEmoji(DiscordEmoji emoji) { Id = emoji.Id; Name = emoji.Name; } } internal class DiscordLinkButtonComponent : DiscordComponent { [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)] public string Url { get; set; } [JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)] public string Label { get; set; } [JsonProperty("disabled", NullValueHandling = NullValueHandling.Ignore)] public bool Disabled { get; set; } [JsonProperty("emoji", NullValueHandling = NullValueHandling.Ignore)] public DiscordComponentEmoji Emoji { get; set; } [JsonProperty("style", NullValueHandling = NullValueHandling.Ignore)] internal int Style { get; } = 5; internal DiscordLinkButtonComponent() { base.Type = ComponentType.Button; } public DiscordLinkButtonComponent(string url, string label, bool disabled = false, DiscordComponentEmoji emoji = null) : this() { Url = url; Label = label; Disabled = disabled; Emoji = emoji; } } internal abstract class BaseDiscordSelectComponent : DiscordComponent { [JsonProperty("placeholder", NullValueHandling = NullValueHandling.Ignore)] public string Placeholder { get; internal set; } [JsonProperty("disabled", NullValueHandling = NullValueHandling.Ignore)] public bool Disabled { get; internal set; } [JsonProperty("min_values", NullValueHandling = NullValueHandling.Ignore)] public int? MinimumSelectedValues { get; internal set; } [JsonProperty("max_values", NullValueHandling = NullValueHandling.Ignore)] public int? MaximumSelectedValues { get; internal set; } } internal sealed class DiscordChannelSelectComponent : BaseDiscordSelectComponent { [JsonProperty("channel_types", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList ChannelTypes { get; internal set; } public DiscordChannelSelectComponent Enable() { base.Disabled = false; return this; } public DiscordChannelSelectComponent Disable() { base.Disabled = true; return this; } internal DiscordChannelSelectComponent() { base.Type = ComponentType.ChannelSelect; } public DiscordChannelSelectComponent(string customId, string placeholder, IEnumerable? channelTypes = null, bool disabled = false, int minOptions = 1, int maxOptions = 1) : this() { base.CustomId = customId; base.Placeholder = placeholder; ChannelTypes = channelTypes?.ToList(); base.Disabled = disabled; base.MinimumSelectedValues = minOptions; base.MaximumSelectedValues = maxOptions; } } internal sealed class DiscordMentionableSelectComponent : BaseDiscordSelectComponent { public DiscordMentionableSelectComponent Enable() { base.Disabled = false; return this; } public DiscordMentionableSelectComponent Disable() { base.Disabled = true; return this; } internal DiscordMentionableSelectComponent() { base.Type = ComponentType.MentionableSelect; } public DiscordMentionableSelectComponent(string customId, string placeholder, bool disabled = false, int minOptions = 1, int maxOptions = 1) : this() { base.CustomId = customId; base.Placeholder = placeholder; base.Disabled = disabled; base.MinimumSelectedValues = minOptions; base.MaximumSelectedValues = maxOptions; } } internal sealed class DiscordRoleSelectComponent : BaseDiscordSelectComponent { public DiscordRoleSelectComponent Enable() { base.Disabled = false; return this; } public DiscordRoleSelectComponent Disable() { base.Disabled = true; return this; } internal DiscordRoleSelectComponent() { base.Type = ComponentType.RoleSelect; } public DiscordRoleSelectComponent(string customId, string placeholder, bool disabled = false, int minOptions = 1, int maxOptions = 1) : this() { base.CustomId = customId; base.Placeholder = placeholder; base.Disabled = disabled; base.MinimumSelectedValues = minOptions; base.MaximumSelectedValues = maxOptions; } } internal sealed class DiscordSelectComponent : BaseDiscordSelectComponent { [JsonProperty("options", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Options { get; internal set; } = Array.Empty(); public DiscordSelectComponent Enable() { base.Disabled = false; return this; } public DiscordSelectComponent Disable() { base.Disabled = true; return this; } internal DiscordSelectComponent() { base.Type = ComponentType.StringSelect; } public DiscordSelectComponent(string customId, string placeholder, IEnumerable options, bool disabled = false, int minOptions = 1, int maxOptions = 1) : this() { base.CustomId = customId; Options = options.ToArray(); base.Placeholder = placeholder; base.Disabled = disabled; base.MinimumSelectedValues = minOptions; base.MaximumSelectedValues = maxOptions; } } internal sealed class DiscordSelectComponentOption { [JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)] public string Label { get; internal set; } [JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)] public string Value { get; internal set; } [JsonProperty("default", NullValueHandling = NullValueHandling.Ignore)] public bool Default { get; internal set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; internal set; } [JsonProperty("emoji", NullValueHandling = NullValueHandling.Ignore)] public DiscordComponentEmoji Emoji { get; internal set; } public DiscordSelectComponentOption(string label, string value, string description = null, bool isDefault = false, DiscordComponentEmoji emoji = null) { Label = label; Value = value; Description = description; Default = isDefault; Emoji = emoji; } } internal sealed class DiscordUserSelectComponent : BaseDiscordSelectComponent { public DiscordUserSelectComponent Enable() { base.Disabled = false; return this; } public DiscordUserSelectComponent Disable() { base.Disabled = true; return this; } internal DiscordUserSelectComponent() { base.Type = ComponentType.UserSelect; } public DiscordUserSelectComponent(string customId, string placeholder, bool disabled = false, int minOptions = 1, int maxOptions = 1) : this() { base.CustomId = customId; base.Placeholder = placeholder; base.Disabled = disabled; base.MinimumSelectedValues = minOptions; base.MaximumSelectedValues = maxOptions; } } internal sealed class TextInputComponent : DiscordComponent { [JsonProperty("placeholder", NullValueHandling = NullValueHandling.Ignore)] public string Placeholder { get; set; } [JsonProperty("label")] public string Label { get; set; } [JsonProperty("value")] public string Value { get; set; } [JsonProperty("min_length", NullValueHandling = NullValueHandling.Ignore)] public int MinimumLength { get; set; } [JsonProperty("max_length", NullValueHandling = NullValueHandling.Ignore)] public int? MaximumLength { get; set; } [JsonProperty("required")] public bool Required { get; set; } [JsonProperty("style")] public TextInputStyle Style { get; set; } public TextInputComponent() { base.Type = ComponentType.FormInput; } public TextInputComponent(string label, string customId, string placeholder = null, string value = null, bool required = true, TextInputStyle style = TextInputStyle.Short, int min_length = 0, int? max_length = null) { base.CustomId = customId; base.Type = ComponentType.FormInput; Label = label; Required = required; Placeholder = placeholder; MinimumLength = min_length; MaximumLength = max_length; Style = style; Value = value; } } internal sealed class DiscordFollowupMessageBuilder : BaseDiscordMessageBuilder { public bool IsEphemeral { get; set; } internal int? _flags { get { if (!IsEphemeral) { return null; } return (int)(base.Flags | MessageFlags.Ephemeral); } } public DiscordFollowupMessageBuilder() { } public DiscordFollowupMessageBuilder(DiscordFollowupMessageBuilder builder) : base((IDiscordMessageBuilder)builder) { IsEphemeral = builder.IsEphemeral; } public DiscordFollowupMessageBuilder(IDiscordMessageBuilder builder) : base(builder) { } public DiscordFollowupMessageBuilder AsEphemeral(bool ephemeral = true) { IsEphemeral = ephemeral; return this; } public override void Clear() { IsEphemeral = false; base.Clear(); } internal void Validate() { IReadOnlyList files = base.Files; if (files != null && files.Count == 0 && string.IsNullOrEmpty(base.Content) && !base.Embeds.Any()) { throw new ArgumentException("You must specify content, an embed, or at least one file."); } } } internal sealed class DiscordInteraction : SnowflakeObject { [JsonProperty("type")] public InteractionType Type { get; internal set; } [JsonProperty("data", NullValueHandling = NullValueHandling.Ignore)] public DiscordInteractionData Data { get; internal set; } [Newtonsoft.Json.JsonIgnore] public ulong? GuildId { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild => (base.Discord as DiscordClient).InternalGetCachedGuild(GuildId); [JsonProperty("channel_id")] public ulong ChannelId { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DiscordChannel Channel { get { object obj = (base.Discord as DiscordClient).InternalGetCachedChannel(ChannelId); if (obj == null) { obj = (base.Discord as DiscordClient).InternalGetCachedThread(ChannelId); if (obj == null) { if (!(Guild == null)) { return null; } DiscordDmChannel discordDmChannel = new DiscordDmChannel(); discordDmChannel.Id = ChannelId; discordDmChannel.Type = ChannelType.Private; discordDmChannel.Discord = base.Discord; discordDmChannel.Recipients = new DiscordUser[1] { User }; obj = discordDmChannel; } } return (DiscordChannel)obj; } } [Newtonsoft.Json.JsonIgnore] public DiscordUser User { get; internal set; } [JsonProperty("token")] public string Token { get; internal set; } [JsonProperty("version")] public int Version { get; internal set; } [JsonProperty("application_id")] public ulong ApplicationId { get; internal set; } [JsonProperty("message")] internal DiscordMessage Message { get; set; } [JsonProperty("locale")] public string? Locale { get; internal set; } [JsonProperty("guild_locale")] public string? GuildLocale { get; internal set; } public Task CreateResponseAsync(InteractionResponseType type, DiscordInteractionResponseBuilder builder = null) { return base.Discord.ApiClient.CreateInteractionResponseAsync(base.Id, Token, type, builder); } public Task DeferAsync(bool ephemeral = false) { return CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, new DiscordInteractionResponseBuilder().AsEphemeral(ephemeral)); } public Task GetOriginalResponseAsync() { return base.Discord.ApiClient.GetOriginalInteractionResponseAsync(base.Discord.CurrentApplication.Id, Token); } public async Task EditOriginalResponseAsync(DiscordWebhookBuilder builder, IEnumerable attachments = null) { builder.Validate(isModify: false, isFollowup: false, isInteractionResponse: true); return await base.Discord.ApiClient.EditOriginalInteractionResponseAsync(base.Discord.CurrentApplication.Id, Token, builder, attachments).ConfigureAwait(continueOnCapturedContext: false); } public Task DeleteOriginalResponseAsync() { return base.Discord.ApiClient.DeleteOriginalInteractionResponseAsync(base.Discord.CurrentApplication.Id, Token); } public async Task CreateFollowupMessageAsync(DiscordFollowupMessageBuilder builder) { builder.Validate(); return await base.Discord.ApiClient.CreateFollowupMessageAsync(base.Discord.CurrentApplication.Id, Token, builder).ConfigureAwait(continueOnCapturedContext: false); } public Task GetFollowupMessageAsync(ulong messageId) { return base.Discord.ApiClient.GetFollowupMessageAsync(base.Discord.CurrentApplication.Id, Token, messageId); } public async Task EditFollowupMessageAsync(ulong messageId, DiscordWebhookBuilder builder, IEnumerable attachments = null) { builder.Validate(isModify: false, isFollowup: true); return await base.Discord.ApiClient.EditFollowupMessageAsync(base.Discord.CurrentApplication.Id, Token, messageId, builder, attachments).ConfigureAwait(continueOnCapturedContext: false); } public Task DeleteFollowupMessageAsync(ulong messageId) { return base.Discord.ApiClient.DeleteFollowupMessageAsync(base.Discord.CurrentApplication.Id, Token, messageId); } } internal class DiscordInteractionApplicationCommandCallbackData { [JsonProperty("tts", NullValueHandling = NullValueHandling.Ignore)] public bool? IsTTS { get; internal set; } [JsonProperty("custom_id", NullValueHandling = NullValueHandling.Ignore)] public string CustomId { get; internal set; } [JsonProperty("title", NullValueHandling = NullValueHandling.Ignore)] public string Title { get; internal set; } [JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)] public string Content { get; internal set; } [JsonProperty("embeds", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Embeds { get; internal set; } [JsonProperty("allowed_mentions", NullValueHandling = NullValueHandling.Ignore)] public DiscordMentions Mentions { get; internal set; } [JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)] public MessageFlags? Flags { get; internal set; } [JsonProperty("components", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyCollection Components { get; internal set; } [JsonProperty("choices")] public IReadOnlyCollection Choices { get; internal set; } } internal sealed class DiscordInteractionData : SnowflakeObject { [JsonProperty("components", NullValueHandling = NullValueHandling.Ignore)] internal List _components; [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("options", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Options { get; internal set; } [JsonProperty("resolved", NullValueHandling = NullValueHandling.Ignore)] public DiscordInteractionResolvedCollection Resolved { get; internal set; } [JsonProperty("custom_id", NullValueHandling = NullValueHandling.Ignore)] public string CustomId { get; internal set; } [JsonProperty("title", NullValueHandling = NullValueHandling.Ignore)] public string Title { get; internal set; } public IReadOnlyList Components => _components; [JsonProperty("target_id", NullValueHandling = NullValueHandling.Ignore)] internal ulong? Target { get; set; } [JsonProperty("component_type", NullValueHandling = NullValueHandling.Ignore)] public ComponentType ComponentType { get; internal set; } [JsonProperty("values", NullValueHandling = NullValueHandling.Ignore)] public string[] Values { get; internal set; } = Array.Empty(); [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public ApplicationCommandType Type { get; internal set; } } internal sealed class DiscordInteractionDataOption { [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("type")] public ApplicationCommandOptionType Type { get; internal set; } [JsonProperty("focused")] public bool Focused { get; internal set; } [JsonProperty("value")] internal string InternalValue { get; set; } [Newtonsoft.Json.JsonIgnore] public object Value => Type switch { ApplicationCommandOptionType.Boolean => bool.Parse(InternalValue), ApplicationCommandOptionType.Integer => long.Parse(InternalValue), ApplicationCommandOptionType.String => InternalValue, ApplicationCommandOptionType.Channel => ulong.Parse(InternalValue), ApplicationCommandOptionType.User => ulong.Parse(InternalValue), ApplicationCommandOptionType.Role => ulong.Parse(InternalValue), ApplicationCommandOptionType.Mentionable => ulong.Parse(InternalValue), ApplicationCommandOptionType.Number => double.Parse(InternalValue, CultureInfo.InvariantCulture), ApplicationCommandOptionType.Attachment => ulong.Parse(InternalValue, CultureInfo.InvariantCulture), _ => InternalValue, }; [JsonProperty("options", NullValueHandling = NullValueHandling.Ignore)] public IEnumerable Options { get; internal set; } } internal sealed class DiscordInteractionResolvedCollection { [JsonProperty("users", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyDictionary Users { get; internal set; } [JsonProperty("members", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyDictionary Members { get; internal set; } [JsonProperty("channels", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyDictionary Channels { get; internal set; } [JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyDictionary Roles { get; internal set; } [JsonProperty("messages", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyDictionary Messages { get; internal set; } [JsonProperty("attachments")] public IReadOnlyDictionary Attachments { get; internal set; } } internal sealed class DiscordInteractionResponseBuilder : BaseDiscordMessageBuilder { private readonly List _choices = new List(); public bool IsEphemeral { get { return (base.Flags & MessageFlags.Ephemeral) == MessageFlags.Ephemeral; } set { if (!value) { base.Flags &= ~MessageFlags.Ephemeral; } else { base.Flags |= MessageFlags.Ephemeral; } } } public string CustomId { get; set; } public string Title { get; set; } public IReadOnlyList Choices => _choices; public DiscordInteractionResponseBuilder() { } public DiscordInteractionResponseBuilder(IDiscordMessageBuilder builder) : base(builder) { } public DiscordInteractionResponseBuilder(DiscordInteractionResponseBuilder builder) : base((IDiscordMessageBuilder)builder) { IsEphemeral = builder.IsEphemeral; _choices.AddRange(builder._choices); } public DiscordInteractionResponseBuilder WithTitle(string title) { if (string.IsNullOrEmpty(title) || title.Length > 256) { throw new ArgumentException("Title must be between 1 and 256 characters."); } Title = title; return this; } public DiscordInteractionResponseBuilder WithCustomId(string id) { if (string.IsNullOrEmpty(id) || id.Length > 100) { throw new ArgumentException("Custom ID must be between 1 and 100 characters."); } CustomId = id; return this; } public DiscordInteractionResponseBuilder AddAutoCompleteChoice(DiscordAutoCompleteChoice choice) { if (_choices.Count >= 25) { throw new ArgumentException("Maximum of 25 choices per response."); } _choices.Add(choice); return this; } public DiscordInteractionResponseBuilder AddAutoCompleteChoices(IEnumerable choices) { if (_choices.Count >= 25 || _choices.Count + choices.Count() > 25) { throw new ArgumentException("Maximum of 25 choices per response."); } _choices.AddRange(choices); return this; } public DiscordInteractionResponseBuilder AddAutoCompleteChoices(params DiscordAutoCompleteChoice[] choices) { return AddAutoCompleteChoices((IEnumerable)choices); } public DiscordInteractionResponseBuilder AsEphemeral(bool ephemeral = true) { IsEphemeral = ephemeral; return this; } public override void Clear() { IsEphemeral = false; _choices.Clear(); base.Clear(); } } internal class DiscordApplicationCommandPermission { [JsonProperty("id")] public ulong Id { get; internal set; } [JsonProperty("type")] public ApplicationCommandPermissionType Type { get; internal set; } [JsonProperty("permission")] public bool Permission { get; internal set; } public DiscordApplicationCommandPermission(DiscordRole role, bool permission) { Id = role.Id; Type = ApplicationCommandPermissionType.Role; Permission = permission; } public DiscordApplicationCommandPermission(DiscordMember member, bool permission) { Id = member.Id; Type = ApplicationCommandPermissionType.User; Permission = permission; } internal DiscordApplicationCommandPermission() { } } internal class DiscordGuildApplicationCommandPermissions : SnowflakeObject { [JsonProperty("application_id")] public ulong ApplicationId { get; internal set; } [JsonProperty("guild_id")] public ulong GuildId { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild => (base.Discord as DiscordClient).InternalGetCachedGuild(GuildId); [JsonProperty("permissions")] public IReadOnlyList Permissions { get; internal set; } internal DiscordGuildApplicationCommandPermissions() { } public DiscordGuildApplicationCommandPermissions(ulong commandId, IEnumerable permissions) { base.Id = commandId; Permissions = permissions.ToList(); } } internal class DiscordInvite { internal BaseDiscordClient Discord { get; set; } [JsonProperty("code", NullValueHandling = NullValueHandling.Ignore)] public string Code { get; internal set; } [JsonProperty("guild", NullValueHandling = NullValueHandling.Ignore)] public DiscordInviteGuild Guild { get; internal set; } [JsonProperty("channel", NullValueHandling = NullValueHandling.Ignore)] public DiscordInviteChannel Channel { get; internal set; } [JsonProperty("target_user", NullValueHandling = NullValueHandling.Ignore)] public DiscordUser TargetUser { get; internal set; } [JsonProperty("target_application", NullValueHandling = NullValueHandling.Ignore)] public DiscordApplication TargetApplication { get; internal set; } [Obsolete("This property is depreciated and will be removed in a future version. Please use TargetType instead.", false)] [JsonProperty("target_user_type", NullValueHandling = NullValueHandling.Ignore)] public TargetUserType? TargetUserType { get; internal set; } [JsonProperty("target_type", NullValueHandling = NullValueHandling.Ignore)] public InviteTargetType? TargetType { get; internal set; } [JsonProperty("approximate_presence_count", NullValueHandling = NullValueHandling.Ignore)] public int? ApproximatePresenceCount { get; internal set; } [JsonProperty("approximate_member_count")] public int? ApproximateMemberCount { get; internal set; } [JsonProperty("inviter", NullValueHandling = NullValueHandling.Ignore)] public DiscordUser Inviter { get; internal set; } [JsonProperty("uses", NullValueHandling = NullValueHandling.Ignore)] public int Uses { get; internal set; } [JsonProperty("max_uses", NullValueHandling = NullValueHandling.Ignore)] public int MaxUses { get; internal set; } [JsonProperty("max_age", NullValueHandling = NullValueHandling.Ignore)] public int MaxAge { get; internal set; } [JsonProperty("temporary", NullValueHandling = NullValueHandling.Ignore)] public bool IsTemporary { get; internal set; } [JsonProperty("created_at", NullValueHandling = NullValueHandling.Ignore)] public DateTimeOffset CreatedAt { get; internal set; } [JsonProperty("revoked", NullValueHandling = NullValueHandling.Ignore)] public bool IsRevoked { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DateTimeOffset? ExpiresAt { get { if (string.IsNullOrWhiteSpace(ExpiresAtRaw) || !DateTimeOffset.TryParse(ExpiresAtRaw, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result)) { return null; } return result; } } [JsonProperty("expires_at", NullValueHandling = NullValueHandling.Ignore)] internal string ExpiresAtRaw { get; set; } [JsonProperty("stage_instance")] public DiscordStageInvite StageInstance { get; internal set; } internal DiscordInvite() { } public Task DeleteAsync(string reason = null) { return Discord.ApiClient.DeleteInviteAsync(Code, reason); } public override string ToString() { return "https://discord.gg/" + Code; } } internal class DiscordInviteChannel : SnowflakeObject { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] public ChannelType Type { get; internal set; } internal DiscordInviteChannel() { } } internal class DiscordInviteGuild : SnowflakeObject { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("icon", NullValueHandling = NullValueHandling.Ignore)] public string IconHash { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string IconUrl { get { if (string.IsNullOrWhiteSpace(IconHash)) { return null; } return "https://cdn.discordapp.com/icons/" + base.Id.ToString(CultureInfo.InvariantCulture) + "/" + IconHash + ".jpg"; } } [JsonProperty("splash", NullValueHandling = NullValueHandling.Ignore)] internal string SplashHash { get; set; } [Newtonsoft.Json.JsonIgnore] public string SplashUrl { get { if (string.IsNullOrWhiteSpace(SplashHash)) { return null; } return "https://cdn.discordapp.com/splashes/" + base.Id.ToString(CultureInfo.InvariantCulture) + "/" + SplashHash + ".jpg"; } } [JsonProperty("banner", NullValueHandling = NullValueHandling.Ignore)] public string Banner { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string BannerUrl { get { if (string.IsNullOrWhiteSpace(Banner)) { return null; } return $"https://cdn.discordapp.com/banners/{base.Id}/{Banner}"; } } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; internal set; } [JsonProperty("features", NullValueHandling = NullValueHandling.Ignore)] public IReadOnlyList Features { get; internal set; } [JsonProperty("verification_level", NullValueHandling = NullValueHandling.Ignore)] public VerificationLevel VerificationLevel { get; internal set; } [JsonProperty("vanity_url_code")] public string VanityUrlCode { get; internal set; } [JsonProperty("welcome_screen", NullValueHandling = NullValueHandling.Ignore)] public DiscordGuildWelcomeScreen WelcomeScreen { get; internal set; } internal DiscordInviteGuild() { } } internal class DiscordStageInvite { [JsonProperty("members")] public IReadOnlyCollection Members { get; internal set; } [JsonProperty("participant_count")] public int ParticipantCount { get; internal set; } [JsonProperty("speaker_count")] public int SpeakerCount { get; internal set; } [JsonProperty("topic")] public string Topic { get; internal set; } } internal static class Optional { public static Optional FromValue(T value) { return new Optional(value); } public static Optional FromNoValue() { return default(Optional); } } internal interface IOptional { bool HasValue { get; } object RawValue { get; } } [Newtonsoft.Json.JsonConverter(typeof(OptionalJsonConverter))] internal readonly struct Optional : IEquatable>, IEquatable, IOptional { private readonly T _val; public bool HasValue { get; } public T Value { get { if (!HasValue) { throw new InvalidOperationException("Value is not set."); } return _val; } } object IOptional.RawValue => _val; public Optional(T value) { _val = value; HasValue = true; } public bool IsDefined(out T? value) { return (value = _val) != null; } public override string ToString() { return string.Format("Optional<{0}> ({1})", typeof(T), HasValue ? Value.ToString() : ""); } public override bool Equals(object obj) { if (!(obj is T e)) { if (obj is Optional e2) { return Equals(e2); } return false; } return Equals(e); } public bool Equals(Optional e) { if (HasValue || e.HasValue) { if (HasValue == e.HasValue) { return Value.Equals(e.Value); } return false; } return true; } public bool Equals(T e) { if (HasValue) { return (object)Value == (object)e; } return false; } public override int GetHashCode() { if (!HasValue) { return 0; } return Value.GetHashCode(); } public static implicit operator Optional(T val) { return new Optional(val); } public static explicit operator T(Optional opt) { return opt.Value; } public static bool operator ==(Optional opt1, Optional opt2) { return opt1.Equals(opt2); } public static bool operator !=(Optional opt1, Optional opt2) { return !opt1.Equals(opt2); } public static bool operator ==(Optional opt, T t) { return opt.Equals(t); } public static bool operator !=(Optional opt, T t) { return !opt.Equals(t); } public Optional IfPresent(Func mapper) { if (!HasValue) { return default(Optional); } return new Optional(mapper(Value)); } } internal sealed class OptionalJsonContractResolver : DefaultContractResolver { protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { Newtonsoft.Json.Serialization.JsonProperty property = base.CreateProperty(member, memberSerialization); if (!property.PropertyType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IOptional))) { return property; } MemberInfo memberInfo = property.DeclaringType.GetTypeInfo().DeclaredMembers.FirstOrDefault((MemberInfo e) => e.Name == property.UnderlyingName); PropertyInfo propertyInfo = memberInfo as PropertyInfo; if ((object)propertyInfo == null) { FieldInfo fieldInfo = memberInfo as FieldInfo; if ((object)fieldInfo != null) { property.ShouldSerialize = (object instance) => (fieldInfo.GetValue(instance) as IOptional).HasValue; return property; } throw new InvalidOperationException("Can only serialize Optional members that are fields or properties"); } property.ShouldSerialize = (object instance) => (propertyInfo.GetValue(instance) as IOptional).HasValue; return property; } } internal sealed class OptionalJsonConverter : Newtonsoft.Json.JsonConverter { public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { object rawValue = (value as IOptional).RawValue; if (rawValue == null) { writer.WriteToken(JsonToken.Null); } else { JToken.FromObject(rawValue).WriteTo(writer); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { Type genericType = objectType.GenericTypeArguments[0]; return objectType.GetTypeInfo().DeclaredConstructors.FirstOrDefault((ConstructorInfo e) => e.GetParameters()[0].ParameterType == genericType).Invoke(new object[1] { serializer.Deserialize(reader, genericType) }); } public override bool CanConvert(Type objectType) { return objectType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IOptional)); } } internal abstract class SnowflakeObject { [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public ulong Id { get; internal set; } [Newtonsoft.Json.JsonIgnore] public DateTimeOffset CreationTimestamp => Id.GetSnowflakeTime(); [Newtonsoft.Json.JsonIgnore] internal BaseDiscordClient Discord { get; set; } internal SnowflakeObject() { } } [Newtonsoft.Json.JsonConverter(typeof(UserStatusConverter))] internal enum UserStatus { Offline = 0, Online = 1, Idle = 2, DoNotDisturb = 4, Invisible = 5 } internal sealed class UserStatusConverter : Newtonsoft.Json.JsonConverter { public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { if (value is UserStatus) { switch ((UserStatus)value) { case UserStatus.Online: writer.WriteValue("online"); break; case UserStatus.Idle: writer.WriteValue("idle"); break; case UserStatus.DoNotDisturb: writer.WriteValue("dnd"); break; case UserStatus.Invisible: writer.WriteValue("invisible"); break; default: writer.WriteValue("offline"); break; } } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { return reader.Value?.ToString().ToLowerInvariant() switch { "online" => UserStatus.Online, "idle" => UserStatus.Idle, "dnd" => UserStatus.DoNotDisturb, "invisible" => UserStatus.Invisible, _ => UserStatus.Offline, }; } public override bool CanConvert(Type objectType) { return objectType == typeof(UserStatus); } } internal sealed class DiscordActivity { public string Name { get; set; } public string StreamUrl { get; set; } public ActivityType ActivityType { get; set; } public DiscordRichPresence RichPresence { get; internal set; } public DiscordCustomStatus CustomStatus { get; internal set; } public DiscordActivity() { ActivityType = ActivityType.Playing; } public DiscordActivity(string name) { Name = name; ActivityType = ActivityType.Playing; } public DiscordActivity(string name, ActivityType type) { if (type == ActivityType.Custom) { throw new InvalidOperationException("Bots cannot use a custom status."); } Name = name; ActivityType = type; } internal DiscordActivity(TransportActivity rawActivity) { UpdateWith(rawActivity); } internal DiscordActivity(DiscordActivity other) { Name = other.Name; ActivityType = other.ActivityType; StreamUrl = other.StreamUrl; if (other.RichPresence != null) { RichPresence = new DiscordRichPresence(other.RichPresence); } if (other.CustomStatus != null) { CustomStatus = new DiscordCustomStatus(other.CustomStatus); } } internal void UpdateWith(TransportActivity rawActivity) { Name = rawActivity?.Name; ActivityType = rawActivity?.ActivityType ?? ActivityType.Playing; StreamUrl = rawActivity?.StreamUrl; if (rawActivity != null && rawActivity.IsRichPresence() && RichPresence != null) { RichPresence.UpdateWith(rawActivity); } else { RichPresence = ((rawActivity != null && rawActivity.IsRichPresence()) ? new DiscordRichPresence(rawActivity) : null); } if (rawActivity != null && rawActivity.IsCustomStatus() && CustomStatus != null) { CustomStatus.UpdateWith(rawActivity.State, rawActivity.Emoji); return; } CustomStatus = ((rawActivity != null && rawActivity.IsCustomStatus()) ? new DiscordCustomStatus { Name = rawActivity.State, Emoji = rawActivity.Emoji } : null); } } internal sealed class DiscordCustomStatus { public string Name { get; internal set; } public DiscordEmoji Emoji { get; internal set; } internal DiscordCustomStatus() { } internal DiscordCustomStatus(DiscordCustomStatus other) { Name = other.Name; Emoji = other.Emoji; } internal void UpdateWith(string state, DiscordEmoji emoji) { Name = state; Emoji = emoji; } } internal sealed class DiscordRichPresence { public string Details { get; internal set; } public string State { get; internal set; } public DiscordApplication Application { get; internal set; } public bool? Instance { get; internal set; } public DiscordAsset LargeImage { get; internal set; } public string LargeImageText { get; internal set; } public DiscordAsset SmallImage { get; internal set; } public string SmallImageText { get; internal set; } public long? CurrentPartySize { get; internal set; } public long? MaximumPartySize { get; internal set; } public ulong? PartyId { get; internal set; } public DateTimeOffset? StartTimestamp { get; internal set; } public DateTimeOffset? EndTimestamp { get; internal set; } public string JoinSecret { get; internal set; } public string MatchSecret { get; internal set; } public string SpectateSecret { get; internal set; } public IReadOnlyList Buttons { get; internal set; } internal DiscordRichPresence() { } internal DiscordRichPresence(TransportActivity rawGame) { UpdateWith(rawGame); } internal DiscordRichPresence(DiscordRichPresence other) { Details = other.Details; State = other.State; Application = other.Application; Instance = other.Instance; LargeImageText = other.LargeImageText; SmallImageText = other.SmallImageText; LargeImage = other.LargeImage; SmallImage = other.SmallImage; CurrentPartySize = other.CurrentPartySize; MaximumPartySize = other.MaximumPartySize; PartyId = other.PartyId; StartTimestamp = other.StartTimestamp; EndTimestamp = other.EndTimestamp; JoinSecret = other.JoinSecret; MatchSecret = other.MatchSecret; SpectateSecret = other.SpectateSecret; Buttons = other.Buttons; } internal void UpdateWith(TransportActivity rawGame) { Details = rawGame?.Details; State = rawGame?.State; Application = ((rawGame != null && rawGame.ApplicationId.HasValue) ? new DiscordApplication { Id = rawGame.ApplicationId.Value } : null); Instance = rawGame?.Instance; LargeImageText = rawGame?.Assets?.LargeImageText; SmallImageText = rawGame?.Assets?.SmallImageText; CurrentPartySize = rawGame?.Party?.Size?.Current; MaximumPartySize = rawGame?.Party?.Size?.Maximum; if (rawGame?.Party != null && ulong.TryParse(rawGame.Party.Id, NumberStyles.Number, CultureInfo.InvariantCulture, out var result)) { PartyId = result; } StartTimestamp = rawGame?.Timestamps?.Start; EndTimestamp = rawGame?.Timestamps?.End; JoinSecret = rawGame?.Secrets?.Join; MatchSecret = rawGame?.Secrets?.Match; SpectateSecret = rawGame?.Secrets?.Spectate; Buttons = rawGame?.Buttons; string text = rawGame?.Assets?.LargeImage; if (text != null) { ulong result2; if (text.StartsWith("spotify:")) { LargeImage = new DiscordSpotifyAsset { Id = text }; } else if (ulong.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out result2)) { LargeImage = new DiscordApplicationAsset { Id = text, Application = Application, Type = ApplicationAssetType.LargeImage }; } } string text2 = rawGame?.Assets?.SmallImage; if (text2 != null) { ulong result3; if (text2.StartsWith("spotify:")) { SmallImage = new DiscordSpotifyAsset { Id = text2 }; } else if (ulong.TryParse(text2, NumberStyles.Number, CultureInfo.InvariantCulture, out result3)) { SmallImage = new DiscordApplicationAsset { Id = text2, Application = Application, Type = ApplicationAssetType.LargeImage }; } } } } internal enum ActivityType { Playing, Streaming, ListeningTo, Watching, Custom, Competing } internal sealed class DiscordPresence { [Newtonsoft.Json.JsonIgnore] internal DiscordActivity[] _internalActivities; [Newtonsoft.Json.JsonIgnore] internal DiscordClient Discord { get; set; } [JsonProperty("user", NullValueHandling = NullValueHandling.Ignore)] internal TransportUser InternalUser { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordUser User => Discord.GetCachedOrEmptyUserInternal(InternalUser.Id); [Newtonsoft.Json.JsonIgnore] public DiscordActivity Activity { get; internal set; } internal TransportActivity RawActivity { get; set; } [Newtonsoft.Json.JsonIgnore] public IReadOnlyList Activities => _internalActivities; [JsonProperty("activities", NullValueHandling = NullValueHandling.Ignore)] internal TransportActivity[] RawActivities { get; set; } [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] public UserStatus Status { get; internal set; } [JsonProperty("guild_id", NullValueHandling = NullValueHandling.Ignore)] internal ulong GuildId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild { get { if (GuildId == 0L) { return null; } return Discord._guilds[GuildId]; } } [JsonProperty("client_status", NullValueHandling = NullValueHandling.Ignore)] public DiscordClientStatus ClientStatus { get; internal set; } internal DiscordPresence() { } internal DiscordPresence(DiscordPresence other) { Discord = other.Discord; if (other.Activity != null) { Activity = new DiscordActivity(other.Activity); } if (other.Activity != null) { RawActivity = new TransportActivity(Activity); } _internalActivities = (DiscordActivity[])other._internalActivities?.Clone(); RawActivities = (TransportActivity[])other.RawActivities?.Clone(); Status = other.Status; InternalUser = new TransportUser(other.InternalUser); } } internal sealed class DiscordClientStatus { [JsonProperty("desktop", NullValueHandling = NullValueHandling.Ignore)] public Optional Desktop { get; internal set; } [JsonProperty("mobile", NullValueHandling = NullValueHandling.Ignore)] public Optional Mobile { get; internal set; } [JsonProperty("web", NullValueHandling = NullValueHandling.Ignore)] public Optional Web { get; internal set; } } internal class DiscordUser : SnowflakeObject, IEquatable { [JsonProperty("accent_color")] internal int? _bannerColor; [JsonProperty("username", NullValueHandling = NullValueHandling.Ignore)] public virtual string Username { get; internal set; } [JsonProperty("discriminator", NullValueHandling = NullValueHandling.Ignore)] public virtual string Discriminator { get; internal set; } [Newtonsoft.Json.JsonIgnore] internal int DiscriminatorInt => int.Parse(Discriminator, NumberStyles.Integer, CultureInfo.InvariantCulture); public virtual DiscordColor? BannerColor { get { if (_bannerColor.HasValue) { return new DiscordColor(_bannerColor.Value); } return null; } } [Newtonsoft.Json.JsonIgnore] public string BannerUrl { get { if (!string.IsNullOrEmpty(BannerHash)) { return string.Format("https://cdn.discordapp.com/banners/{0}/{1}.{2}?size=4096", base.Id, BannerHash, BannerHash.StartsWith("a") ? "gif" : "png"); } return null; } } [JsonProperty("banner", NullValueHandling = NullValueHandling.Ignore)] public virtual string BannerHash { get; internal set; } [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] public virtual string AvatarHash { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string AvatarUrl { get { if (string.IsNullOrWhiteSpace(AvatarHash)) { return DefaultAvatarUrl; } if (!AvatarHash.StartsWith("a_")) { return $"https://cdn.discordapp.com/avatars/{base.Id}/{AvatarHash}.png?size=1024"; } return "https://cdn.discordapp.com/avatars/" + base.Id.ToString(CultureInfo.InvariantCulture) + "/" + AvatarHash + ".gif?size=1024"; } } [Newtonsoft.Json.JsonIgnore] public string DefaultAvatarUrl => "https://cdn.discordapp.com/embed/avatars/" + (DiscriminatorInt % 5).ToString(CultureInfo.InvariantCulture) + ".png?size=1024"; [JsonProperty("bot", NullValueHandling = NullValueHandling.Ignore)] public virtual bool IsBot { get; internal set; } [JsonProperty("mfa_enabled", NullValueHandling = NullValueHandling.Ignore)] public virtual bool? MfaEnabled { get; internal set; } [JsonProperty("system", NullValueHandling = NullValueHandling.Ignore)] public bool? IsSystem { get; internal set; } [JsonProperty("verified", NullValueHandling = NullValueHandling.Ignore)] public virtual bool? Verified { get; internal set; } [JsonProperty("email", NullValueHandling = NullValueHandling.Ignore)] public virtual string Email { get; internal set; } [JsonProperty("premium_type", NullValueHandling = NullValueHandling.Ignore)] public virtual PremiumType? PremiumType { get; internal set; } [JsonProperty("locale", NullValueHandling = NullValueHandling.Ignore)] public virtual string Locale { get; internal set; } [JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)] public virtual UserFlags? OAuthFlags { get; internal set; } [JsonProperty("public_flags", NullValueHandling = NullValueHandling.Ignore)] public virtual UserFlags? Flags { get; internal set; } [Newtonsoft.Json.JsonIgnore] public string Mention => Formatter.Mention(this, this is DiscordMember); [Newtonsoft.Json.JsonIgnore] public bool IsCurrent => base.Id == base.Discord.CurrentUser.Id; [Newtonsoft.Json.JsonIgnore] public DiscordPresence Presence { get { if (!(base.Discord is DiscordClient discordClient)) { return null; } if (!discordClient.Presences.TryGetValue(base.Id, out var value)) { return null; } return value; } } internal DiscordUser() { } internal DiscordUser(TransportUser transport) { base.Id = transport.Id; Username = transport.Username; Discriminator = transport.Discriminator; AvatarHash = transport.AvatarHash; _bannerColor = transport.BannerColor; BannerHash = transport.BannerHash; IsBot = transport.IsBot; MfaEnabled = transport.MfaEnabled; Verified = transport.Verified; Email = transport.Email; PremiumType = transport.PremiumType; Locale = transport.Locale; Flags = transport.Flags; OAuthFlags = transport.OAuthFlags; } public Task UnbanAsync(DiscordGuild guild, string reason = null) { return guild.UnbanMemberAsync(this, reason); } public string GetAvatarUrl(ImageFormat imageFormat, ushort imageSize = 1024) { if (imageFormat == ImageFormat.Unknown) { throw new ArgumentException("You must specify valid image format.", "imageFormat"); } if (imageSize < 16 || imageSize > 4096) { throw new ArgumentOutOfRangeException("Image Size is not in between 16 and 4096: imageSize"); } if (imageSize == 0 || (imageSize & (imageSize - 1)) != 0) { throw new ArgumentOutOfRangeException("Image size is not a power of two: imageSize"); } string text = imageFormat switch { ImageFormat.Gif => "gif", ImageFormat.Jpeg => "jpg", ImageFormat.Png => "png", ImageFormat.WebP => "webp", ImageFormat.Auto => string.IsNullOrWhiteSpace(AvatarHash) ? "png" : (AvatarHash.StartsWith("a_") ? "gif" : "png"), _ => throw new ArgumentOutOfRangeException("imageFormat"), }; string text2 = imageSize.ToString(CultureInfo.InvariantCulture); if (!string.IsNullOrWhiteSpace(AvatarHash)) { string text3 = base.Id.ToString(CultureInfo.InvariantCulture); return "https://cdn.discordapp.com/avatars/" + text3 + "/" + AvatarHash + "." + text + "?size=" + text2; } string text4 = (DiscriminatorInt % 5).ToString(CultureInfo.InvariantCulture); return "https://cdn.discordapp.com/embed/avatars/" + text4 + "." + text + "?size=" + text2; } public override string ToString() { return $"User {base.Id}; {Username}#{Discriminator}"; } public override bool Equals(object obj) { return Equals(obj as DiscordUser); } public bool Equals(DiscordUser e) { if ((object)e == null) { return false; } if ((object)this != e) { return base.Id == e.Id; } return true; } public override int GetHashCode() { return base.Id.GetHashCode(); } public static bool operator ==(DiscordUser e1, DiscordUser e2) { if (((object)e1 == null && (object)e2 != null) || ((object)e1 != null && (object)e2 == null)) { return false; } if ((object)e1 != null || (object)e2 != null) { return e1.Id == e2.Id; } return true; } public static bool operator !=(DiscordUser e1, DiscordUser e2) { return !(e1 == e2); } } internal class DiscordUserComparer : IEqualityComparer { public bool Equals(DiscordUser x, DiscordUser y) { return x.Equals(y); } public int GetHashCode(DiscordUser obj) { return obj.Id.GetHashCode(); } } internal class DiscordVoiceRegion { [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public string Id { get; internal set; } [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("sample_hostname", NullValueHandling = NullValueHandling.Ignore)] public string SampleHostname { get; internal set; } [JsonProperty("sample_port", NullValueHandling = NullValueHandling.Ignore)] public int SamplePort { get; internal set; } [JsonProperty("vip", NullValueHandling = NullValueHandling.Ignore)] public bool IsVIP { get; internal set; } [JsonProperty("optimal", NullValueHandling = NullValueHandling.Ignore)] public bool IsOptimal { get; internal set; } [JsonProperty("deprecated", NullValueHandling = NullValueHandling.Ignore)] public bool IsDeprecated { get; internal set; } [JsonProperty("custom", NullValueHandling = NullValueHandling.Ignore)] public bool IsCustom { get; internal set; } public bool Equals(DiscordVoiceRegion region) { return this == region; } public override bool Equals(object obj) { return Equals(obj as DiscordVoiceRegion); } public override int GetHashCode() { return Id.GetHashCode(); } public static bool operator ==(DiscordVoiceRegion left, DiscordVoiceRegion right) { if (((object)left == null && (object)right != null) || ((object)left != null && (object)right == null)) { return false; } if ((object)left != null || (object)right != null) { return left.Id == right.Id; } return true; } public static bool operator !=(DiscordVoiceRegion left, DiscordVoiceRegion right) { return !(left == right); } internal DiscordVoiceRegion() { } } internal class DiscordVoiceState { internal DiscordClient Discord { get; set; } [JsonProperty("guild_id", NullValueHandling = NullValueHandling.Ignore)] internal ulong? GuildId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordGuild Guild { get { if (!GuildId.HasValue) { return Channel?.Guild; } return Discord.Guilds[GuildId.Value]; } } [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Include)] internal ulong? ChannelId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordChannel Channel { get { if (!ChannelId.HasValue || ChannelId.Value == 0L) { return null; } return Discord.InternalGetCachedChannel(ChannelId.Value); } } [JsonProperty("user_id", NullValueHandling = NullValueHandling.Ignore)] internal ulong UserId { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordUser User { get { DiscordUser discordUser = null; if (Guild != null) { discordUser = (Guild._members.TryGetValue(UserId, out var value) ? value : null); } if (discordUser == null) { discordUser = Discord.GetCachedOrEmptyUserInternal(UserId); } return discordUser; } } [JsonProperty("session_id", NullValueHandling = NullValueHandling.Ignore)] internal string SessionId { get; set; } [JsonProperty("deaf", NullValueHandling = NullValueHandling.Ignore)] public bool IsServerDeafened { get; internal set; } [JsonProperty("mute", NullValueHandling = NullValueHandling.Ignore)] public bool IsServerMuted { get; internal set; } [JsonProperty("self_deaf", NullValueHandling = NullValueHandling.Ignore)] public bool IsSelfDeafened { get; internal set; } [JsonProperty("self_mute", NullValueHandling = NullValueHandling.Ignore)] public bool IsSelfMuted { get; internal set; } [JsonProperty("self_video", NullValueHandling = NullValueHandling.Ignore)] public bool IsSelfVideo { get; internal set; } [JsonProperty("self_stream", NullValueHandling = NullValueHandling.Ignore)] public bool IsSelfStream { get; internal set; } [JsonProperty("suppress", NullValueHandling = NullValueHandling.Ignore)] public bool IsSuppressed { get; internal set; } [JsonProperty("request_to_speak_timestamp", NullValueHandling = NullValueHandling.Ignore)] internal DateTimeOffset? RequestToSpeakTimestamp { get; set; } [Newtonsoft.Json.JsonIgnore] public DiscordMember Member { get { if (!Guild.Members.TryGetValue(TransportMember.User.Id, out var value)) { return new DiscordMember(TransportMember) { Discord = Discord }; } return value; } } [JsonProperty("member", NullValueHandling = NullValueHandling.Ignore)] internal TransportMember TransportMember { get; set; } internal DiscordVoiceState() { } internal DiscordVoiceState(DiscordVoiceState other) { Discord = other.Discord; UserId = other.UserId; ChannelId = other.ChannelId; GuildId = other.GuildId; IsServerDeafened = other.IsServerDeafened; IsServerMuted = other.IsServerMuted; IsSuppressed = other.IsSuppressed; IsSelfDeafened = other.IsSelfDeafened; IsSelfMuted = other.IsSelfMuted; IsSelfStream = other.IsSelfStream; IsSelfVideo = other.IsSelfVideo; SessionId = other.SessionId; RequestToSpeakTimestamp = other.RequestToSpeakTimestamp; } internal DiscordVoiceState(DiscordMember m) { Discord = m.Discord as DiscordClient; UserId = m.Id; ChannelId = 0uL; GuildId = m._guild_id; IsServerDeafened = m.IsDeafened; IsServerMuted = m.IsMuted; } public override string ToString() { return UserId.ToString(CultureInfo.InvariantCulture) + " in " + (GuildId ?? Channel.GuildId.Value).ToString(CultureInfo.InvariantCulture); } } internal class DiscordWebhook : SnowflakeObject, IEquatable { internal DiscordApiClient ApiClient { get; set; } [JsonProperty("guild_id", NullValueHandling = NullValueHandling.Ignore)] public ulong GuildId { get; internal set; } [JsonProperty("channel_id", NullValueHandling = NullValueHandling.Ignore)] public ulong ChannelId { get; internal set; } [JsonProperty("user", NullValueHandling = NullValueHandling.Ignore)] public DiscordUser User { get; internal set; } [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; internal set; } [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] internal string AvatarHash { get; set; } public string AvatarUrl { get { if (string.IsNullOrWhiteSpace(AvatarHash)) { return null; } return $"https://cdn.discordapp.com/avatars/{base.Id}/{AvatarHash}.png?size=1024"; } } [JsonProperty("token", NullValueHandling = NullValueHandling.Ignore)] public string Token { get; internal set; } [JsonProperty("source_guild", NullValueHandling = NullValueHandling.Ignore)] public DiscordGuild SourceGuild { get; internal set; } [JsonProperty("source_channel", NullValueHandling = NullValueHandling.Ignore)] public DiscordChannel SourceChannel { get; internal set; } [JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)] public string Url { get; internal set; } internal DiscordWebhook() { } public Task ModifyAsync(string name = null, Optional avatar = default(Optional), ulong? channelId = null, string reason = null) { Optional base64_avatar = Optional.FromNoValue(); if (avatar.HasValue && avatar.Value != null) { using ImageTool imageTool = new ImageTool(avatar.Value); base64_avatar = imageTool.GetBase64(); } else if (avatar.HasValue) { base64_avatar = null; } ulong channelId2 = channelId ?? ChannelId; return base.Discord.ApiClient.ModifyWebhookAsync(base.Id, channelId2, name, base64_avatar, reason); } public Task DeleteAsync() { return base.Discord.ApiClient.DeleteWebhookAsync(base.Id, Token); } public Task ExecuteAsync(DiscordWebhookBuilder builder) { return (base.Discord?.ApiClient ?? ApiClient).ExecuteWebhookAsync(base.Id, Token, builder); } public Task ExecuteSlackAsync(string json) { return (base.Discord?.ApiClient ?? ApiClient).ExecuteWebhookSlackAsync(base.Id, Token, json); } public Task ExecuteGithubAsync(string json) { return (base.Discord?.ApiClient ?? ApiClient).ExecuteWebhookGithubAsync(base.Id, Token, json); } public async Task GetMessageAsync(ulong messageId) { return await (base.Discord?.ApiClient ?? ApiClient).GetWebhookMessageAsync(base.Id, Token, messageId).ConfigureAwait(continueOnCapturedContext: false); } public async Task EditMessageAsync(ulong messageId, DiscordWebhookBuilder builder, IEnumerable attachments = null) { builder.Validate(isModify: true); return await (base.Discord?.ApiClient ?? ApiClient).EditWebhookMessageAsync(base.Id, Token, messageId, builder, attachments).ConfigureAwait(continueOnCapturedContext: false); } public Task DeleteMessageAsync(ulong messageId) { return (base.Discord?.ApiClient ?? ApiClient).DeleteWebhookMessageAsync(base.Id, Token, messageId); } public override bool Equals(object obj) { return Equals(obj as DiscordWebhook); } public bool Equals(DiscordWebhook e) { if ((object)e == null) { return false; } if ((object)this != e) { return base.Id == e.Id; } return true; } public override int GetHashCode() { return base.Id.GetHashCode(); } public static bool operator ==(DiscordWebhook e1, DiscordWebhook e2) { if (((object)e1 == null && (object)e2 != null) || ((object)e1 != null && (object)e2 == null)) { return false; } if ((object)e1 != null || (object)e2 != null) { return e1.Id == e2.Id; } return true; } public static bool operator !=(DiscordWebhook e1, DiscordWebhook e2) { return !(e1 == e2); } } internal sealed class DiscordWebhookBuilder : BaseDiscordMessageBuilder { public Optional Username { get; set; } public Optional AvatarUrl { get; set; } public ulong? ThreadId { get; set; } public DiscordWebhookBuilder() { } public DiscordWebhookBuilder(DiscordWebhookBuilder builder) : base((IDiscordMessageBuilder)builder) { Username = builder.Username; AvatarUrl = builder.AvatarUrl; ThreadId = builder.ThreadId; } public DiscordWebhookBuilder(IDiscordMessageBuilder builder) : base(builder) { } public DiscordWebhookBuilder WithUsername(string username) { Username = username; return this; } public DiscordWebhookBuilder WithAvatarUrl(string avatarUrl) { AvatarUrl = avatarUrl; return this; } public DiscordWebhookBuilder WithThreadId(ulong? threadId) { ThreadId = threadId; return this; } public override void Clear() { Username = default(Optional); AvatarUrl = default(Optional); ThreadId = null; base.Clear(); } public async Task SendAsync(DiscordWebhook webhook) { return await webhook.ExecuteAsync(this).ConfigureAwait(continueOnCapturedContext: false); } public async Task ModifyAsync(DiscordWebhook webhook, DiscordMessage message) { return await ModifyAsync(webhook, message.Id).ConfigureAwait(continueOnCapturedContext: false); } public async Task ModifyAsync(DiscordWebhook webhook, ulong messageId) { return await webhook.EditMessageAsync(messageId, this).ConfigureAwait(continueOnCapturedContext: false); } internal void Validate(bool isModify = false, bool isFollowup = false, bool isInteractionResponse = false) { if (isModify) { if (Username.HasValue) { throw new ArgumentException("You cannot change the username of a message."); } if (AvatarUrl.HasValue) { throw new ArgumentException("You cannot change the avatar of a message."); } } else if (isFollowup) { if (Username.HasValue) { throw new ArgumentException("You cannot change the username of a follow up message."); } if (AvatarUrl.HasValue) { throw new ArgumentException("You cannot change the avatar of a follow up message."); } } else if (isInteractionResponse) { if (Username.HasValue) { throw new ArgumentException("You cannot change the username of an interaction response."); } if (AvatarUrl.HasValue) { throw new ArgumentException("You cannot change the avatar of an interaction response."); } } else { IReadOnlyList files = base.Files; if (files != null && files.Count == 0 && string.IsNullOrEmpty(base.Content) && !base.Embeds.Any()) { throw new ArgumentException("You must specify content, an embed, or at least one file."); } } } } } namespace DSharpPlus.AsyncEvents { internal abstract class AsyncEvent { public string Name { get; } protected internal AsyncEvent(string name) { Name = name; } } internal class AsyncEventArgs : System.EventArgs { [Obsolete("This is no longer utilized in DSharpPlus.", true)] public bool Handled { get; set; } } internal delegate Task AsyncEventHandler(TSender sender, TArgs args) where TArgs : AsyncEventArgs; internal delegate void AsyncEventExceptionHandler(AsyncEvent @event, Exception exception, AsyncEventHandler handler, TSender sender, TArgs args) where TArgs : AsyncEventArgs; internal sealed class AsyncEvent : AsyncEvent where TArgs : AsyncEventArgs { private readonly SemaphoreSlim _lock = new SemaphoreSlim(1); private readonly AsyncEventExceptionHandler _exceptionHandler; private List> _handlers; public AsyncEvent(string name, AsyncEventExceptionHandler exceptionHandler) : base(name) { _handlers = new List>(); _exceptionHandler = exceptionHandler; } public void Register(AsyncEventHandler handler) { if (handler == null) { throw new ArgumentNullException("handler"); } _lock.Wait(); try { _handlers.Add(handler); } finally { _lock.Release(); } } public void Unregister(AsyncEventHandler handler) { if (handler == null) { throw new ArgumentNullException("handler"); } _lock.Wait(); try { _handlers.Remove(handler); } finally { _lock.Release(); } } public void UnregisterAll() { _handlers = new List>(); } public async Task InvokeAsync(TSender sender, TArgs args) { if (_handlers.Count == 0) { return; } await _lock.WaitAsync(); List> source = new List>(_handlers); _lock.Release(); Task.WhenAll(((IEnumerable>)source).Select((Func, Task>)async delegate(AsyncEventHandler handler) { try { await handler(sender, args); } catch (Exception exception) { _exceptionHandler?.Invoke(this, exception, handler, sender, args); } })); } } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class NullablePublicOnlyAttribute : Attribute { public readonly bool IncludesInternals; public NullablePublicOnlyAttribute(bool P_0) { IncludesInternals = P_0; } } } namespace FxResources.Microsoft.Extensions.Logging.Abstractions { internal static class SR { } } namespace System { internal static class <0576b3bf-cbaa-4181-b422-b9b8c666ee18>SR { private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled) && isEnabled; private static ResourceManager s_resourceManager; internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(FxResources.Microsoft.Extensions.Logging.Abstractions.SR))); internal static string UnexpectedNumberOfNamedParameters => GetResourceString("UnexpectedNumberOfNamedParameters"); private static bool UsingResourceKeys() { return s_usingResourceKeys; } internal static string GetResourceString(string resourceKey) { if (UsingResourceKeys()) { return resourceKey; } string result = null; try { result = ResourceManager.GetString(resourceKey); } catch (MissingManifestResourceException) { } return result; } internal static string GetResourceString(string resourceKey, string defaultString) { string resourceString = GetResourceString(resourceKey); if (!(resourceKey == resourceString) && resourceString != null) { return resourceString; } return defaultString; } internal static string Format(string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(resourceFormat, p1); } internal static string Format(string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(resourceFormat, p1, p2); } internal static string Format(string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(resourceFormat, p1, p2, p3); } internal static string Format(string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(resourceFormat, args); } return resourceFormat; } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(provider, resourceFormat, p1); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(provider, resourceFormat, p1, p2); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(provider, resourceFormat, p1, p2, p3); } internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(provider, resourceFormat, args); } return resourceFormat; } } } namespace System.Text { internal ref struct ValueStringBuilder { private char[] _arrayToReturnToPool; private Span _chars; private int _pos; public int Length { get { return _pos; } set { _pos = value; } } public int Capacity => _chars.Length; public ref char this[int index] => ref _chars[index]; public Span RawChars => _chars; public ValueStringBuilder(Span initialBuffer) { _arrayToReturnToPool = null; _chars = initialBuffer; _pos = 0; } public ValueStringBuilder(int initialCapacity) { _arrayToReturnToPool = ArrayPool.Shared.Rent(initialCapacity); _chars = _arrayToReturnToPool; _pos = 0; } public void EnsureCapacity(int capacity) { if ((uint)capacity > (uint)_chars.Length) { Grow(capacity - _pos); } } public ref char GetPinnableReference() { return ref MemoryMarshal.GetReference(_chars); } public ref char GetPinnableReference(bool terminate) { if (terminate) { EnsureCapacity(Length + 1); _chars[Length] = '\0'; } return ref MemoryMarshal.GetReference(_chars); } public override string ToString() { string result = _chars.Slice(0, _pos).ToString(); Dispose(); return result; } public ReadOnlySpan AsSpan(bool terminate) { if (terminate) { EnsureCapacity(Length + 1); _chars[Length] = '\0'; } return _chars.Slice(0, _pos); } public ReadOnlySpan AsSpan() { return _chars.Slice(0, _pos); } public ReadOnlySpan AsSpan(int start) { return _chars.Slice(start, _pos - start); } public ReadOnlySpan AsSpan(int start, int length) { return _chars.Slice(start, length); } public bool TryCopyTo(Span destination, out int charsWritten) { if (_chars.Slice(0, _pos).TryCopyTo(destination)) { charsWritten = _pos; Dispose(); return true; } charsWritten = 0; Dispose(); return false; } public void Insert(int index, char value, int count) { if (_pos > _chars.Length - count) { Grow(count); } int length = _pos - index; _chars.Slice(index, length).CopyTo(_chars.Slice(index + count)); _chars.Slice(index, count).Fill(value); _pos += count; } public void Insert(int index, string? s) { if (s != null) { int length = s.Length; if (_pos > _chars.Length - length) { Grow(length); } int length2 = _pos - index; _chars.Slice(index, length2).CopyTo(_chars.Slice(index + length)); s.CopyTo(_chars.Slice(index)); _pos += length; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Append(char c) { int pos = _pos; if ((uint)pos < (uint)_chars.Length) { _chars[pos] = c; _pos = pos + 1; } else { GrowAndAppend(c); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Append(string? s) { if (s != null) { int pos = _pos; if (s.Length == 1 && (uint)pos < (uint)_chars.Length) { _chars[pos] = s[0]; _pos = pos + 1; } else { AppendSlow(s); } } } private void AppendSlow(string s) { int pos = _pos; if (pos > _chars.Length - s.Length) { Grow(s.Length); } s.CopyTo(_chars.Slice(pos)); _pos += s.Length; } public void Append(char c, int count) { if (_pos > _chars.Length - count) { Grow(count); } Span span = _chars.Slice(_pos, count); for (int i = 0; i < span.Length; i++) { span[i] = c; } _pos += count; } public unsafe void Append(char* value, int length) { int pos = _pos; if (pos > _chars.Length - length) { Grow(length); } Span span = _chars.Slice(_pos, length); for (int i = 0; i < span.Length; i++) { span[i] = *(value++); } _pos += length; } public void Append(ReadOnlySpan value) { int pos = _pos; if (pos > _chars.Length - value.Length) { Grow(value.Length); } value.CopyTo(_chars.Slice(_pos)); _pos += value.Length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span AppendSpan(int length) { int pos = _pos; if (pos > _chars.Length - length) { Grow(length); } _pos = pos + length; return _chars.Slice(pos, length); } [MethodImpl(MethodImplOptions.NoInlining)] private void GrowAndAppend(char c) { Grow(1); Append(c); } [MethodImpl(MethodImplOptions.NoInlining)] private void Grow(int additionalCapacityBeyondPos) { char[] array = ArrayPool.Shared.Rent((int)Math.Max((uint)(_pos + additionalCapacityBeyondPos), (uint)(_chars.Length * 2))); _chars.Slice(0, _pos).CopyTo(array); char[] arrayToReturnToPool = _arrayToReturnToPool; _chars = (_arrayToReturnToPool = array); if (arrayToReturnToPool != null) { ArrayPool.Shared.Return(arrayToReturnToPool); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { char[] arrayToReturnToPool = _arrayToReturnToPool; this = default(System.Text.ValueStringBuilder); if (arrayToReturnToPool != null) { ArrayPool.Shared.Return(arrayToReturnToPool); } } } } namespace Microsoft.Extensions.Internal { internal static class TypeNameHelper { private readonly struct DisplayNameOptions { public bool FullName { get; } public bool IncludeGenericParameters { get; } public bool IncludeGenericParameterNames { get; } public char NestedTypeDelimiter { get; } public DisplayNameOptions(bool fullName, bool includeGenericParameterNames, bool includeGenericParameters, char nestedTypeDelimiter) { FullName = fullName; IncludeGenericParameters = includeGenericParameters; IncludeGenericParameterNames = includeGenericParameterNames; NestedTypeDelimiter = nestedTypeDelimiter; } } private const char DefaultNestedTypeDelimiter = '+'; private static readonly Dictionary _builtInTypeNames = new Dictionary { { typeof(void), "void" }, { typeof(bool), "bool" }, { typeof(byte), "byte" }, { typeof(char), "char" }, { typeof(decimal), "decimal" }, { typeof(double), "double" }, { typeof(float), "float" }, { typeof(int), "int" }, { typeof(long), "long" }, { typeof(object), "object" }, { typeof(sbyte), "sbyte" }, { typeof(short), "short" }, { typeof(string), "string" }, { typeof(uint), "uint" }, { typeof(ulong), "ulong" }, { typeof(ushort), "ushort" } }; [return: NotNullIfNotNull("item")] public static string? GetTypeDisplayName(object? item, bool fullName = true) { if (item != null) { return GetTypeDisplayName(item.GetType(), fullName); } return null; } public static string GetTypeDisplayName(Type type, bool fullName = true, bool includeGenericParameterNames = false, bool includeGenericParameters = true, char nestedTypeDelimiter = '+') { StringBuilder stringBuilder = new StringBuilder(); DisplayNameOptions options = new DisplayNameOptions(fullName, includeGenericParameterNames, includeGenericParameters, nestedTypeDelimiter); ProcessType(stringBuilder, type, in options); return stringBuilder.ToString(); } private static void ProcessType(StringBuilder builder, Type type, in DisplayNameOptions options) { if (type.IsGenericType) { Type[] genericArguments = type.GetGenericArguments(); ProcessGenericType(builder, type, genericArguments, genericArguments.Length, in options); return; } if (type.IsArray) { ProcessArrayType(builder, type, in options); return; } if (_builtInTypeNames.TryGetValue(type, out var value)) { builder.Append(value); return; } if (type.IsGenericParameter) { if (options.IncludeGenericParameterNames) { builder.Append(type.Name); } return; } string text = (options.FullName ? type.FullName : type.Name); builder.Append(text); if (options.NestedTypeDelimiter != '+') { builder.Replace('+', options.NestedTypeDelimiter, builder.Length - text.Length, text.Length); } } private static void ProcessArrayType(StringBuilder builder, Type type, in DisplayNameOptions options) { Type type2 = type; while (type2.IsArray) { type2 = type2.GetElementType(); } ProcessType(builder, type2, in options); while (type.IsArray) { builder.Append('['); builder.Append(',', type.GetArrayRank() - 1); builder.Append(']'); type = type.GetElementType(); } } private static void ProcessGenericType(StringBuilder builder, Type type, Type[] genericArguments, int length, in DisplayNameOptions options) { int num = 0; if (type.IsNested) { num = type.DeclaringType.GetGenericArguments().Length; } if (options.FullName) { if (type.IsNested) { ProcessGenericType(builder, type.DeclaringType, genericArguments, num, in options); builder.Append(options.NestedTypeDelimiter); } else if (!string.IsNullOrEmpty(type.Namespace)) { builder.Append(type.Namespace); builder.Append('.'); } } int num2 = type.Name.IndexOf('`'); if (num2 <= 0) { builder.Append(type.Name); return; } builder.Append(type.Name, 0, num2); if (!options.IncludeGenericParameters) { return; } builder.Append('<'); for (int i = num; i < length; i++) { ProcessType(builder, genericArguments[i], in options); if (i + 1 != length) { builder.Append(','); if (options.IncludeGenericParameterNames || !genericArguments[i + 1].IsGenericParameter) { builder.Append(' '); } } } builder.Append('>'); } } } namespace Microsoft.Extensions.Logging { internal readonly struct EventId { public int Id { get; } public string? Name { get; } public static implicit operator EventId(int i) { return new EventId(i); } public static bool operator ==(EventId left, EventId right) { return left.Equals(right); } public static bool operator !=(EventId left, EventId right) { return !left.Equals(right); } public EventId(int id, string? name = null) { Id = id; Name = name; } public override string ToString() { return Name ?? Id.ToString(); } public bool Equals(EventId other) { return Id == other.Id; } public override bool Equals([NotNullWhen(true)] object? obj) { if (obj == null) { return false; } if (obj is EventId other) { return Equals(other); } return false; } public override int GetHashCode() { return Id; } } internal readonly struct FormattedLogValues : IReadOnlyList>, IEnumerable>, IEnumerable, IReadOnlyCollection> { internal const int MaxCachedFormatters = 1024; private const string? NullFormat = "[null]"; private static int _count; private static ConcurrentDictionary? _formatters = new ConcurrentDictionary(); private readonly LogValuesFormatter? _formatter; private readonly object?[]? _values; private readonly string? _originalMessage; internal LogValuesFormatter? Formatter => _formatter; public KeyValuePair this[int index] { get { if (index < 0 || index >= Count) { throw new IndexOutOfRangeException("index"); } if (index == Count - 1) { return new KeyValuePair("{OriginalFormat}", _originalMessage); } return _formatter.GetValue(_values, index); } } public int Count { get { if (_formatter == null) { return 1; } return _formatter.ValueNames.Count + 1; } } public FormattedLogValues(string? format, params object?[]? values) { if (values != null && values.Length != 0 && format != null) { if (_count >= 1024) { if (!_formatters.TryGetValue(format, out _formatter)) { _formatter = new LogValuesFormatter(format); } } else { _formatter = _formatters.GetOrAdd(format, delegate(string? f) { Interlocked.Increment(ref _count); return new LogValuesFormatter(f); }); } } else { _formatter = null; } _originalMessage = format ?? "[null]"; _values = values; } public IEnumerator> GetEnumerator() { int i = 0; while (i < Count) { yield return this[i]; int num = i + 1; i = num; } } public override string ToString() { if (_formatter == null) { return _originalMessage; } return _formatter.Format(_values); } IEnumerator? IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal interface IExternalScopeProvider { void ForEachScope(Action callback, TState state); IDisposable Push(object? state); } internal interface ILogger { void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter); bool IsEnabled(LogLevel logLevel); IDisposable BeginScope(TState state); } internal interface ILoggerFactory : IDisposable { ILogger CreateLogger(string categoryName); void AddProvider(ILoggerProvider provider); } internal interface ILoggerProvider : IDisposable { ILogger CreateLogger(string categoryName); } internal interface ILogger : ILogger { } internal interface ISupportExternalScope { void SetScopeProvider(IExternalScopeProvider scopeProvider); } internal class LogDefineOptions { public bool SkipEnabledCheck { get; set; } } internal static class LoggerExtensions { private static readonly Func _messageFormatter = MessageFormatter; public static void LogDebug(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Debug, eventId, exception, message, args); } public static void LogDebug(this ILogger logger, EventId eventId, string? message, params object?[] args) { logger.Log(LogLevel.Debug, eventId, message, args); } public static void LogDebug(this ILogger logger, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Debug, exception, message, args); } public static void LogDebug(this ILogger logger, string? message, params object?[] args) { logger.Log(LogLevel.Debug, message, args); } public static void LogTrace(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Trace, eventId, exception, message, args); } public static void LogTrace(this ILogger logger, EventId eventId, string? message, params object?[] args) { logger.Log(LogLevel.Trace, eventId, message, args); } public static void LogTrace(this ILogger logger, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Trace, exception, message, args); } public static void LogTrace(this ILogger logger, string? message, params object?[] args) { logger.Log(LogLevel.Trace, message, args); } public static void LogInformation(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Information, eventId, exception, message, args); } public static void LogInformation(this ILogger logger, EventId eventId, string? message, params object?[] args) { logger.Log(LogLevel.Information, eventId, message, args); } public static void LogInformation(this ILogger logger, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Information, exception, message, args); } public static void LogInformation(this ILogger logger, string? message, params object?[] args) { logger.Log(LogLevel.Information, message, args); } public static void LogWarning(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Warning, eventId, exception, message, args); } public static void LogWarning(this ILogger logger, EventId eventId, string? message, params object?[] args) { logger.Log(LogLevel.Warning, eventId, message, args); } public static void LogWarning(this ILogger logger, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Warning, exception, message, args); } public static void LogWarning(this ILogger logger, string? message, params object?[] args) { logger.Log(LogLevel.Warning, message, args); } public static void LogError(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Error, eventId, exception, message, args); } public static void LogError(this ILogger logger, EventId eventId, string? message, params object?[] args) { logger.Log(LogLevel.Error, eventId, message, args); } public static void LogError(this ILogger logger, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Error, exception, message, args); } public static void LogError(this ILogger logger, string? message, params object?[] args) { logger.Log(LogLevel.Error, message, args); } public static void LogCritical(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Critical, eventId, exception, message, args); } public static void LogCritical(this ILogger logger, EventId eventId, string? message, params object?[] args) { logger.Log(LogLevel.Critical, eventId, message, args); } public static void LogCritical(this ILogger logger, Exception? exception, string? message, params object?[] args) { logger.Log(LogLevel.Critical, exception, message, args); } public static void LogCritical(this ILogger logger, string? message, params object?[] args) { logger.Log(LogLevel.Critical, message, args); } public static void Log(this ILogger logger, LogLevel logLevel, string? message, params object?[] args) { logger.Log(logLevel, 0, null, message, args); } public static void Log(this ILogger logger, LogLevel logLevel, EventId eventId, string? message, params object?[] args) { logger.Log(logLevel, eventId, null, message, args); } public static void Log(this ILogger logger, LogLevel logLevel, Exception? exception, string? message, params object?[] args) { logger.Log(logLevel, 0, exception, message, args); } public static void Log(this ILogger logger, LogLevel logLevel, EventId eventId, Exception? exception, string? message, params object?[] args) { if (logger == null) { throw new ArgumentNullException("logger"); } logger.Log(logLevel, eventId, new FormattedLogValues(message, args), exception, _messageFormatter); } public static IDisposable BeginScope(this ILogger logger, string messageFormat, params object?[] args) { if (logger == null) { throw new ArgumentNullException("logger"); } return logger.BeginScope(new FormattedLogValues(messageFormat, args)); } private static string MessageFormatter(FormattedLogValues state, Exception error) { return state.ToString(); } } internal class LoggerExternalScopeProvider : IExternalScopeProvider { private sealed class Scope : IDisposable { private readonly LoggerExternalScopeProvider _provider; private bool _isDisposed; public Scope Parent { get; } public object State { get; } internal Scope(LoggerExternalScopeProvider provider, object state, Scope parent) { _provider = provider; State = state; Parent = parent; } public override string ToString() { return State?.ToString(); } public void Dispose() { if (!_isDisposed) { _provider._currentScope.Value = Parent; _isDisposed = true; } } } private readonly AsyncLocal _currentScope = new AsyncLocal(); public void ForEachScope(Action callback, TState state) { Action callback2 = callback; TState state2 = state; Report(_currentScope.Value); void Report(Scope? current) { if (current != null) { Report(current.Parent); callback2(current.State, state2); } } } public IDisposable Push(object? state) { Scope value = _currentScope.Value; Scope scope = new Scope(this, state, value); _currentScope.Value = scope; return scope; } } internal static class LoggerFactoryExtensions { public static ILogger CreateLogger(this ILoggerFactory factory) { if (factory == null) { throw new ArgumentNullException("factory"); } return new Logger(factory); } public static ILogger CreateLogger(this ILoggerFactory factory, Type type) { if (factory == null) { throw new ArgumentNullException("factory"); } if (type == null) { throw new ArgumentNullException("type"); } return factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(type, fullName: true, includeGenericParameterNames: false, includeGenericParameters: false, '.')); } } internal static class LoggerMessage { private readonly struct LogValues : IReadOnlyList>, IEnumerable>, IEnumerable, IReadOnlyCollection> { public static readonly Func? Callback = (LogValues state, Exception? exception) => state.ToString(); private readonly LogValuesFormatter? _formatter; public KeyValuePair this[int index] { get { if (index == 0) { return new KeyValuePair("{OriginalFormat}", _formatter.OriginalFormat); } throw new IndexOutOfRangeException("index"); } } public int Count => 1; public LogValues(LogValuesFormatter? formatter) { _formatter = formatter; } public IEnumerator>? GetEnumerator() { yield return this[0]; } public override string? ToString() { return _formatter.Format(); } IEnumerator? IEnumerable.GetEnumerator() { return GetEnumerator(); } } private readonly struct LogValues : IReadOnlyList>, IEnumerable>, IEnumerable, IReadOnlyCollection> { public static readonly Func, Exception?, string?>? Callback = (LogValues state, Exception? exception) => state.ToString(); private readonly LogValuesFormatter? _formatter; private readonly T0? _value0; public KeyValuePair this[int index] => index switch { 0 => new KeyValuePair(_formatter.ValueNames[0], _value0), 1 => new KeyValuePair("{OriginalFormat}", _formatter.OriginalFormat), _ => throw new IndexOutOfRangeException("index"), }; public int Count => 2; public LogValues(LogValuesFormatter? formatter, T0? value0) { _formatter = formatter; _value0 = value0; } public IEnumerator>? GetEnumerator() { int i = 0; while (i < Count) { yield return this[i]; int num = i + 1; i = num; } } public override string? ToString() { return _formatter.Format(_value0); } IEnumerator? IEnumerable.GetEnumerator() { return GetEnumerator(); } } private readonly struct LogValues : IReadOnlyList>, IEnumerable>, IEnumerable, IReadOnlyCollection> { public static readonly Func, Exception?, string?>? Callback = (LogValues state, Exception? exception) => state.ToString(); private readonly LogValuesFormatter? _formatter; private readonly T0? _value0; private readonly T1? _value1; public KeyValuePair this[int index] => index switch { 0 => new KeyValuePair(_formatter.ValueNames[0], _value0), 1 => new KeyValuePair(_formatter.ValueNames[1], _value1), 2 => new KeyValuePair("{OriginalFormat}", _formatter.OriginalFormat), _ => throw new IndexOutOfRangeException("index"), }; public int Count => 3; public LogValues(LogValuesFormatter? formatter, T0? value0, T1? value1) { _formatter = formatter; _value0 = value0; _value1 = value1; } public IEnumerator>? GetEnumerator() { int i = 0; while (i < Count) { yield return this[i]; int num = i + 1; i = num; } } public override string? ToString() { return _formatter.Format(_value0, _value1); } IEnumerator? IEnumerable.GetEnumerator() { return GetEnumerator(); } } private readonly struct LogValues : IReadOnlyList>, IEnumerable>, IEnumerable, IReadOnlyCollection> { public static readonly Func, Exception?, string?>? Callback = (LogValues state, Exception? exception) => state.ToString(); private readonly LogValuesFormatter? _formatter; private readonly T0? _value0; private readonly T1? _value1; private readonly T2? _value2; public int Count => 4; public KeyValuePair this[int index] => index switch { 0 => new KeyValuePair(_formatter.ValueNames[0], _value0), 1 => new KeyValuePair(_formatter.ValueNames[1], _value1), 2 => new KeyValuePair(_formatter.ValueNames[2], _value2), 3 => new KeyValuePair("{OriginalFormat}", _formatter.OriginalFormat), _ => throw new IndexOutOfRangeException("index"), }; public LogValues(LogValuesFormatter? formatter, T0? value0, T1? value1, T2? value2) { _formatter = formatter; _value0 = value0; _value1 = value1; _value2 = value2; } public override string? ToString() { return _formatter.Format(_value0, _value1, _value2); } public IEnumerator>? GetEnumerator() { int i = 0; while (i < Count) { yield return this[i]; int num = i + 1; i = num; } } IEnumerator? IEnumerable.GetEnumerator() { return GetEnumerator(); } } private readonly struct LogValues : IReadOnlyList>, IEnumerable>, IEnumerable, IReadOnlyCollection> { public static readonly Func, Exception?, string?>? Callback = (LogValues state, Exception? exception) => state.ToString(); private readonly LogValuesFormatter? _formatter; private readonly T0? _value0; private readonly T1? _value1; private readonly T2? _value2; private readonly T3? _value3; public int Count => 5; public KeyValuePair this[int index] => index switch { 0 => new KeyValuePair(_formatter.ValueNames[0], _value0), 1 => new KeyValuePair(_formatter.ValueNames[1], _value1), 2 => new KeyValuePair(_formatter.ValueNames[2], _value2), 3 => new KeyValuePair(_formatter.ValueNames[3], _value3), 4 => new KeyValuePair("{OriginalFormat}", _formatter.OriginalFormat), _ => throw new IndexOutOfRangeException("index"), }; public LogValues(LogValuesFormatter? formatter, T0? value0, T1? value1, T2? value2, T3? value3) { _formatter = formatter; _value0 = value0; _value1 = value1; _value2 = value2; _value3 = value3; } private object?[]? ToArray() { return new object[4] { _value0, _value1, _value2, _value3 }; } public override string? ToString() { return _formatter.FormatWithOverwrite(ToArray()); } public IEnumerator>? GetEnumerator() { int i = 0; while (i < Count) { yield return this[i]; int num = i + 1; i = num; } } IEnumerator? IEnumerable.GetEnumerator() { return GetEnumerator(); } } private readonly struct LogValues : IReadOnlyList>, IEnumerable>, IEnumerable, IReadOnlyCollection> { public static readonly Func, Exception?, string?>? Callback = (LogValues state, Exception? exception) => state.ToString(); private readonly LogValuesFormatter? _formatter; private readonly T0? _value0; private readonly T1? _value1; private readonly T2? _value2; private readonly T3? _value3; private readonly T4? _value4; public int Count => 6; public KeyValuePair this[int index] => index switch { 0 => new KeyValuePair(_formatter.ValueNames[0], _value0), 1 => new KeyValuePair(_formatter.ValueNames[1], _value1), 2 => new KeyValuePair(_formatter.ValueNames[2], _value2), 3 => new KeyValuePair(_formatter.ValueNames[3], _value3), 4 => new KeyValuePair(_formatter.ValueNames[4], _value4), 5 => new KeyValuePair("{OriginalFormat}", _formatter.OriginalFormat), _ => throw new IndexOutOfRangeException("index"), }; public LogValues(LogValuesFormatter? formatter, T0? value0, T1? value1, T2? value2, T3? value3, T4? value4) { _formatter = formatter; _value0 = value0; _value1 = value1; _value2 = value2; _value3 = value3; _value4 = value4; } private object?[]? ToArray() { return new object[5] { _value0, _value1, _value2, _value3, _value4 }; } public override string? ToString() { return _formatter.FormatWithOverwrite(ToArray()); } public IEnumerator>? GetEnumerator() { int i = 0; while (i < Count) { yield return this[i]; int num = i + 1; i = num; } } IEnumerator? IEnumerable.GetEnumerator() { return GetEnumerator(); } } private readonly struct LogValues : IReadOnlyList>, IEnumerable>, IEnumerable, IReadOnlyCollection> { public static readonly Func, Exception?, string?>? Callback = (LogValues state, Exception? exception) => state.ToString(); private readonly LogValuesFormatter? _formatter; private readonly T0? _value0; private readonly T1? _value1; private readonly T2? _value2; private readonly T3? _value3; private readonly T4? _value4; private readonly T5? _value5; public int Count => 7; public KeyValuePair this[int index] => index switch { 0 => new KeyValuePair(_formatter.ValueNames[0], _value0), 1 => new KeyValuePair(_formatter.ValueNames[1], _value1), 2 => new KeyValuePair(_formatter.ValueNames[2], _value2), 3 => new KeyValuePair(_formatter.ValueNames[3], _value3), 4 => new KeyValuePair(_formatter.ValueNames[4], _value4), 5 => new KeyValuePair(_formatter.ValueNames[5], _value5), 6 => new KeyValuePair("{OriginalFormat}", _formatter.OriginalFormat), _ => throw new IndexOutOfRangeException("index"), }; public LogValues(LogValuesFormatter? formatter, T0? value0, T1? value1, T2? value2, T3? value3, T4? value4, T5? value5) { _formatter = formatter; _value0 = value0; _value1 = value1; _value2 = value2; _value3 = value3; _value4 = value4; _value5 = value5; } private object?[]? ToArray() { return new object[6] { _value0, _value1, _value2, _value3, _value4, _value5 }; } public override string? ToString() { return _formatter.FormatWithOverwrite(ToArray()); } public IEnumerator>? GetEnumerator() { int i = 0; while (i < Count) { yield return this[i]; int num = i + 1; i = num; } } IEnumerator? IEnumerable.GetEnumerator() { return GetEnumerator(); } } public static Func DefineScope(string formatString) { LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 0); LogValues logValues = new LogValues(formatter); return (ILogger? logger) => logger.BeginScope(logValues); } public static Func DefineScope(string formatString) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 1); return (ILogger? logger, T1? arg1) => logger.BeginScope(new LogValues(formatter, arg1)); } public static Func DefineScope(string formatString) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 2); return (ILogger? logger, T1? arg1, T2? arg2) => logger.BeginScope(new LogValues(formatter, arg1, arg2)); } public static Func DefineScope(string formatString) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 3); return (ILogger? logger, T1? arg1, T2? arg2, T3? arg3) => logger.BeginScope(new LogValues(formatter, arg1, arg2, arg3)); } public static Func DefineScope(string formatString) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 4); return (ILogger? logger, T1? arg1, T2? arg2, T3? arg3, T4? arg4) => logger.BeginScope(new LogValues(formatter, arg1, arg2, arg3, arg4)); } public static Func DefineScope(string formatString) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 5); return (ILogger? logger, T1? arg1, T2? arg2, T3? arg3, T4? arg4, T5? arg5) => logger.BeginScope(new LogValues(formatter, arg1, arg2, arg3, arg4, arg5)); } public static Func DefineScope(string formatString) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 6); return (ILogger? logger, T1? arg1, T2? arg2, T3? arg3, T4? arg4, T5? arg5, T6? arg6) => logger.BeginScope(new LogValues(formatter, arg1, arg2, arg3, arg4, arg5, arg6)); } public static Action Define(LogLevel logLevel, EventId eventId, string formatString) { return Define(logLevel, eventId, formatString, null); } public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 0); if (options != null && options.SkipEnabledCheck) { return Log; } return delegate(ILogger? logger, Exception? exception) { if (logger.IsEnabled(logLevel)) { Log(logger, exception); } }; void Log(ILogger? logger, Exception? exception) { logger.Log(logLevel, eventId, new LogValues(formatter), exception, LogValues.Callback); } } public static Action Define(LogLevel logLevel, EventId eventId, string formatString) { return Define(logLevel, eventId, formatString, null); } public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 1); if (options != null && options.SkipEnabledCheck) { return Log; } return delegate(ILogger? logger, T1? arg1, Exception? exception) { if (logger.IsEnabled(logLevel)) { Log(logger, arg1, exception); } }; void Log(ILogger? logger, T1? arg1, Exception? exception) { logger.Log(logLevel, eventId, new LogValues(formatter, arg1), exception, LogValues.Callback); } } public static Action Define(LogLevel logLevel, EventId eventId, string formatString) { return Define(logLevel, eventId, formatString, null); } public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 2); if (options != null && options.SkipEnabledCheck) { return Log; } return delegate(ILogger? logger, T1? arg1, T2? arg2, Exception? exception) { if (logger.IsEnabled(logLevel)) { Log(logger, arg1, arg2, exception); } }; void Log(ILogger? logger, T1? arg1, T2? arg2, Exception? exception) { logger.Log(logLevel, eventId, new LogValues(formatter, arg1, arg2), exception, LogValues.Callback); } } public static Action Define(LogLevel logLevel, EventId eventId, string formatString) { return Define(logLevel, eventId, formatString, null); } public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 3); if (options != null && options.SkipEnabledCheck) { return Log; } return delegate(ILogger? logger, T1? arg1, T2? arg2, T3? arg3, Exception? exception) { if (logger.IsEnabled(logLevel)) { Log(logger, arg1, arg2, arg3, exception); } }; void Log(ILogger? logger, T1? arg1, T2? arg2, T3? arg3, Exception? exception) { logger.Log(logLevel, eventId, new LogValues(formatter, arg1, arg2, arg3), exception, LogValues.Callback); } } public static Action Define(LogLevel logLevel, EventId eventId, string formatString) { return Define(logLevel, eventId, formatString, null); } public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 4); if (options != null && options.SkipEnabledCheck) { return Log; } return delegate(ILogger? logger, T1? arg1, T2? arg2, T3? arg3, T4? arg4, Exception? exception) { if (logger.IsEnabled(logLevel)) { Log(logger, arg1, arg2, arg3, arg4, exception); } }; void Log(ILogger? logger, T1? arg1, T2? arg2, T3? arg3, T4? arg4, Exception? exception) { logger.Log(logLevel, eventId, new LogValues(formatter, arg1, arg2, arg3, arg4), exception, LogValues.Callback); } } public static Action Define(LogLevel logLevel, EventId eventId, string formatString) { return Define(logLevel, eventId, formatString, null); } public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 5); if (options != null && options.SkipEnabledCheck) { return Log; } return delegate(ILogger? logger, T1? arg1, T2? arg2, T3? arg3, T4? arg4, T5? arg5, Exception? exception) { if (logger.IsEnabled(logLevel)) { Log(logger, arg1, arg2, arg3, arg4, arg5, exception); } }; void Log(ILogger? logger, T1? arg1, T2? arg2, T3? arg3, T4? arg4, T5? arg5, Exception? exception) { logger.Log(logLevel, eventId, new LogValues(formatter, arg1, arg2, arg3, arg4, arg5), exception, LogValues.Callback); } } public static Action Define(LogLevel logLevel, EventId eventId, string formatString) { return Define(logLevel, eventId, formatString, null); } public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options) { LogValuesFormatter? formatter = CreateLogValuesFormatter(formatString, 6); if (options != null && options.SkipEnabledCheck) { return Log; } return delegate(ILogger? logger, T1? arg1, T2? arg2, T3? arg3, T4? arg4, T5? arg5, T6? arg6, Exception? exception) { if (logger.IsEnabled(logLevel)) { Log(logger, arg1, arg2, arg3, arg4, arg5, arg6, exception); } }; void Log(ILogger? logger, T1? arg1, T2? arg2, T3? arg3, T4? arg4, T5? arg5, T6? arg6, Exception? exception) { logger.Log(logLevel, eventId, new LogValues(formatter, arg1, arg2, arg3, arg4, arg5, arg6), exception, LogValues.Callback); } } private static LogValuesFormatter? CreateLogValuesFormatter(string? formatString, int expectedNamedParameterCount) { LogValuesFormatter logValuesFormatter = new LogValuesFormatter(formatString); int count = logValuesFormatter.ValueNames.Count; if (count != expectedNamedParameterCount) { throw new ArgumentException(<0576b3bf-cbaa-4181-b422-b9b8c666ee18>SR.Format(<0576b3bf-cbaa-4181-b422-b9b8c666ee18>SR.UnexpectedNumberOfNamedParameters, formatString, expectedNamedParameterCount, count)); } return logValuesFormatter; } } [AttributeUsage(AttributeTargets.Method)] internal sealed class LoggerMessageAttribute : Attribute { public int EventId { get; set; } = -1; public string? EventName { get; set; } public LogLevel Level { get; set; } = LogLevel.None; public string Message { get; set; } = ""; public bool SkipEnabledCheck { get; set; } public LoggerMessageAttribute() { } public LoggerMessageAttribute(int eventId, LogLevel level, string message) { EventId = eventId; Level = level; Message = message; } } internal class Logger : ILogger, ILogger { private readonly ILogger _logger; public Logger(ILoggerFactory factory) { if (factory == null) { throw new ArgumentNullException("factory"); } _logger = factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(typeof(T), fullName: true, includeGenericParameterNames: false, includeGenericParameters: false, '.')); } IDisposable ILogger.BeginScope(TState state) { return _logger.BeginScope(state); } bool ILogger.IsEnabled(LogLevel logLevel) { return _logger.IsEnabled(logLevel); } void ILogger.Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { _logger.Log(logLevel, eventId, state, exception, formatter); } } internal enum LogLevel { Trace, Debug, Information, Warning, Error, Critical, None } internal sealed class LogValuesFormatter { private const string NullValue = "(null)"; private static readonly char[] FormatDelimiters = new char[2] { ',', ':' }; private readonly string _format; private readonly List _valueNames = new List(); public string OriginalFormat { get; private set; } public List ValueNames => _valueNames; public LogValuesFormatter(string format) { if (format == null) { throw new ArgumentNullException("format"); } OriginalFormat = format; Span initialBuffer = stackalloc char[256]; System.Text.ValueStringBuilder valueStringBuilder = new System.Text.ValueStringBuilder(initialBuffer); int num = 0; int length = format.Length; while (num < length) { int num2 = FindBraceIndex(format, '{', num, length); if (num == 0 && num2 == length) { _format = format; return; } int num3 = FindBraceIndex(format, '}', num2, length); if (num3 == length) { valueStringBuilder.Append(format.AsSpan(num, length - num)); num = length; continue; } int num4 = FindIndexOfAny(format, FormatDelimiters, num2, num3); valueStringBuilder.Append(format.AsSpan(num, num2 - num + 1)); valueStringBuilder.Append(_valueNames.Count.ToString()); _valueNames.Add(format.Substring(num2 + 1, num4 - num2 - 1)); valueStringBuilder.Append(format.AsSpan(num4, num3 - num4 + 1)); num = num3 + 1; } _format = valueStringBuilder.ToString(); } private static int FindBraceIndex(string format, char brace, int startIndex, int endIndex) { int result = endIndex; int i = startIndex; int num = 0; for (; i < endIndex; i++) { if (num > 0 && format[i] != brace) { if (num % 2 != 0) { break; } num = 0; result = endIndex; } else { if (format[i] != brace) { continue; } if (brace == '}') { if (num == 0) { result = i; } } else { result = i; } num++; } } return result; } private static int FindIndexOfAny(string format, char[] chars, int startIndex, int endIndex) { int num = format.IndexOfAny(chars, startIndex, endIndex - startIndex); if (num != -1) { return num; } return endIndex; } public string Format(object?[]? values) { object[] array = values; if (values != null) { for (int i = 0; i < values.Length; i++) { object obj = FormatArgument(values[i]); if (obj != values[i]) { array = new object[values.Length]; Array.Copy(values, array, i); array[i++] = obj; for (; i < values.Length; i++) { array[i] = FormatArgument(values[i]); } break; } } } return string.Format(CultureInfo.InvariantCulture, _format, array ?? Array.Empty()); } internal string FormatWithOverwrite(object?[]? values) { if (values != null) { for (int i = 0; i < values.Length; i++) { values[i] = FormatArgument(values[i]); } } return string.Format(CultureInfo.InvariantCulture, _format, values ?? Array.Empty()); } internal string Format() { return _format; } internal string Format(object? arg0) { return string.Format(CultureInfo.InvariantCulture, _format, FormatArgument(arg0)); } internal string Format(object? arg0, object? arg1) { return string.Format(CultureInfo.InvariantCulture, _format, FormatArgument(arg0), FormatArgument(arg1)); } internal string Format(object? arg0, object? arg1, object? arg2) { return string.Format(CultureInfo.InvariantCulture, _format, FormatArgument(arg0), FormatArgument(arg1), FormatArgument(arg2)); } public KeyValuePair GetValue(object?[] values, int index) { if (index < 0 || index > _valueNames.Count) { throw new IndexOutOfRangeException("index"); } if (_valueNames.Count > index) { return new KeyValuePair(_valueNames[index], values[index]); } return new KeyValuePair("{OriginalFormat}", OriginalFormat); } public IEnumerable> GetValues(object[] values) { KeyValuePair[] array = new KeyValuePair[values.Length + 1]; for (int i = 0; i != _valueNames.Count; i++) { array[i] = new KeyValuePair(_valueNames[i], values[i]); } array[^1] = new KeyValuePair("{OriginalFormat}", OriginalFormat); return array; } private object FormatArgument(object value) { if (value == null) { return "(null)"; } if (value is string) { return value; } if (value is IEnumerable enumerable) { Span initialBuffer = stackalloc char[256]; System.Text.ValueStringBuilder valueStringBuilder = new System.Text.ValueStringBuilder(initialBuffer); bool flag = true; foreach (object item in enumerable) { if (!flag) { valueStringBuilder.Append(", "); } valueStringBuilder.Append((item != null) ? item.ToString() : "(null)"); flag = false; } return valueStringBuilder.ToString(); } return value; } } internal sealed class NullExternalScopeProvider : IExternalScopeProvider { public static IExternalScopeProvider Instance { get; } = new NullExternalScopeProvider(); private NullExternalScopeProvider() { } void IExternalScopeProvider.ForEachScope(Action callback, TState state) { } IDisposable IExternalScopeProvider.Push(object state) { return NullScope.Instance; } } internal sealed class NullScope : IDisposable { public static NullScope Instance { get; } = new NullScope(); private NullScope() { } public void Dispose() { } } } namespace Microsoft.Extensions.Logging.Abstractions { internal readonly struct LogEntry { public LogLevel LogLevel { get; } public string Category { get; } public EventId EventId { get; } public TState State { get; } public Exception? Exception { get; } public Func? Formatter { get; } public LogEntry(LogLevel logLevel, string category, EventId eventId, TState state, Exception? exception, Func formatter) { LogLevel = logLevel; Category = category; EventId = eventId; State = state; Exception = exception; Formatter = formatter; } } internal class NullLogger : ILogger { public static NullLogger Instance { get; } = new NullLogger(); private NullLogger() { } public IDisposable BeginScope(TState state) { return NullScope.Instance; } public bool IsEnabled(LogLevel logLevel) { return false; } public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { } } internal class NullLoggerFactory : ILoggerFactory, IDisposable { public static readonly NullLoggerFactory Instance = new NullLoggerFactory(); public ILogger CreateLogger(string name) { return NullLogger.Instance; } public void AddProvider(ILoggerProvider provider) { } public void Dispose() { } } internal class NullLoggerProvider : ILoggerProvider, IDisposable { public static NullLoggerProvider Instance { get; } = new NullLoggerProvider(); private NullLoggerProvider() { } public ILogger CreateLogger(string categoryName) { return NullLogger.Instance; } public void Dispose() { } } internal class NullLogger : ILogger, ILogger { public static readonly NullLogger Instance = new NullLogger(); public IDisposable BeginScope(TState state) { return NullScope.Instance; } public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { } public bool IsEnabled(LogLevel logLevel) { return false; } } } namespace FxResources.System.Collections.Immutable { internal static class SR { } } namespace System { internal static class SR { private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled) && isEnabled; private static ResourceManager s_resourceManager; internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(FxResources.System.Collections.Immutable.SR))); internal static string Arg_KeyNotFoundWithKey => GetResourceString("Arg_KeyNotFoundWithKey"); internal static string ArrayInitializedStateNotEqual => GetResourceString("ArrayInitializedStateNotEqual"); internal static string ArrayLengthsNotEqual => GetResourceString("ArrayLengthsNotEqual"); internal static string CannotFindOldValue => GetResourceString("CannotFindOldValue"); internal static string CapacityMustBeGreaterThanOrEqualToCount => GetResourceString("CapacityMustBeGreaterThanOrEqualToCount"); internal static string CapacityMustEqualCountOnMove => GetResourceString("CapacityMustEqualCountOnMove"); internal static string CollectionModifiedDuringEnumeration => GetResourceString("CollectionModifiedDuringEnumeration"); internal static string DuplicateKey => GetResourceString("DuplicateKey"); internal static string InvalidEmptyOperation => GetResourceString("InvalidEmptyOperation"); internal static string InvalidOperationOnDefaultArray => GetResourceString("InvalidOperationOnDefaultArray"); private static bool UsingResourceKeys() { return s_usingResourceKeys; } internal static string GetResourceString(string resourceKey) { if (UsingResourceKeys()) { return resourceKey; } string result = null; try { result = ResourceManager.GetString(resourceKey); } catch (MissingManifestResourceException) { } return result; } internal static string GetResourceString(string resourceKey, string defaultString) { string resourceString = GetResourceString(resourceKey); if (!(resourceKey == resourceString) && resourceString != null) { return resourceString; } return defaultString; } internal static string Format(string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(resourceFormat, p1); } internal static string Format(string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(resourceFormat, p1, p2); } internal static string Format(string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(resourceFormat, p1, p2, p3); } internal static string Format(string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(resourceFormat, args); } return resourceFormat; } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(provider, resourceFormat, p1); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(provider, resourceFormat, p1, p2); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(provider, resourceFormat, p1, p2, p3); } internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(provider, resourceFormat, args); } return resourceFormat; } } } namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] internal sealed class LibraryImportAttribute : Attribute { public string LibraryName { get; } public string? EntryPoint { get; set; } public StringMarshalling StringMarshalling { get; set; } public Type? StringMarshallingCustomType { get; set; } public bool SetLastError { get; set; } public LibraryImportAttribute(string libraryName) { LibraryName = libraryName; } } internal enum StringMarshalling { Custom, Utf8, Utf16 } } namespace System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = false)] internal sealed class NonVersionableAttribute : Attribute { } } namespace System.Linq { internal static class ImmutableArrayExtensions { public static IEnumerable Select(this ImmutableArray immutableArray, Func selector) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.Select(selector); } public static IEnumerable SelectMany(this ImmutableArray immutableArray, Func> collectionSelector, Func resultSelector) { immutableArray.ThrowNullRefIfNotInitialized(); if (collectionSelector == null || resultSelector == null) { return Enumerable.SelectMany(immutableArray, collectionSelector, resultSelector); } if (immutableArray.Length != 0) { return immutableArray.SelectManyIterator(collectionSelector, resultSelector); } return Enumerable.Empty(); } public static IEnumerable Where(this ImmutableArray immutableArray, Func predicate) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.Where(predicate); } public static bool Any(this ImmutableArray immutableArray) { return immutableArray.Length > 0; } public static bool Any(this ImmutableArray immutableArray, Func predicate) { immutableArray.ThrowNullRefIfNotInitialized(); Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T arg in array) { if (predicate(arg)) { return true; } } return false; } public static bool All(this ImmutableArray immutableArray, Func predicate) { immutableArray.ThrowNullRefIfNotInitialized(); Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T arg in array) { if (!predicate(arg)) { return false; } } return true; } public static bool SequenceEqual(this ImmutableArray immutableArray, ImmutableArray items, IEqualityComparer? comparer = null) where TDerived : TBase { immutableArray.ThrowNullRefIfNotInitialized(); items.ThrowNullRefIfNotInitialized(); if (immutableArray.array == items.array) { return true; } if (immutableArray.Length != items.Length) { return false; } if (comparer == null) { comparer = EqualityComparer.Default; } for (int i = 0; i < immutableArray.Length; i++) { if (!comparer.Equals(immutableArray.array[i], (TBase)(object)items.array[i])) { return false; } } return true; } public static bool SequenceEqual(this ImmutableArray immutableArray, IEnumerable items, IEqualityComparer? comparer = null) where TDerived : TBase { Requires.NotNull(items, "items"); if (comparer == null) { comparer = EqualityComparer.Default; } int num = 0; int length = immutableArray.Length; foreach (TDerived item in items) { if (num == length) { return false; } if (!comparer.Equals(immutableArray[num], (TBase)(object)item)) { return false; } num++; } return num == length; } public static bool SequenceEqual(this ImmutableArray immutableArray, ImmutableArray items, Func predicate) where TDerived : TBase { Requires.NotNull(predicate, "predicate"); immutableArray.ThrowNullRefIfNotInitialized(); items.ThrowNullRefIfNotInitialized(); if (immutableArray.array == items.array) { return true; } if (immutableArray.Length != items.Length) { return false; } int i = 0; for (int length = immutableArray.Length; i < length; i++) { if (!predicate(immutableArray[i], (TBase)(object)items[i])) { return false; } } return true; } public static T? Aggregate(this ImmutableArray immutableArray, Func func) { Requires.NotNull(func, "func"); if (immutableArray.Length == 0) { return default(T); } T val = immutableArray[0]; int i = 1; for (int length = immutableArray.Length; i < length; i++) { val = func(val, immutableArray[i]); } return val; } public static TAccumulate Aggregate(this ImmutableArray immutableArray, TAccumulate seed, Func func) { Requires.NotNull(func, "func"); TAccumulate val = seed; T[] array = immutableArray.array; foreach (T arg in array) { val = func(val, arg); } return val; } public static TResult Aggregate(this ImmutableArray immutableArray, TAccumulate seed, Func func, Func resultSelector) { Requires.NotNull(resultSelector, "resultSelector"); return resultSelector(immutableArray.Aggregate(seed, func)); } public static T ElementAt(this ImmutableArray immutableArray, int index) { return immutableArray[index]; } public static T? ElementAtOrDefault(this ImmutableArray immutableArray, int index) { if (index < 0 || index >= immutableArray.Length) { return default(T); } return immutableArray[index]; } public static T First(this ImmutableArray immutableArray, Func predicate) { Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { return val; } } return Enumerable.Empty().First(); } public static T First(this ImmutableArray immutableArray) { if (immutableArray.Length <= 0) { return immutableArray.array.First(); } return immutableArray[0]; } public static T? FirstOrDefault(this ImmutableArray immutableArray) { if (immutableArray.array.Length == 0) { return default(T); } return immutableArray.array[0]; } public static T? FirstOrDefault(this ImmutableArray immutableArray, Func predicate) { Requires.NotNull(predicate, "predicate"); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { return val; } } return default(T); } public static T Last(this ImmutableArray immutableArray) { if (immutableArray.Length <= 0) { return immutableArray.array.Last(); } return immutableArray[immutableArray.Length - 1]; } public static T Last(this ImmutableArray immutableArray, Func predicate) { Requires.NotNull(predicate, "predicate"); for (int num = immutableArray.Length - 1; num >= 0; num--) { if (predicate(immutableArray[num])) { return immutableArray[num]; } } return Enumerable.Empty().Last(); } public static T? LastOrDefault(this ImmutableArray immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.LastOrDefault(); } public static T? LastOrDefault(this ImmutableArray immutableArray, Func predicate) { Requires.NotNull(predicate, "predicate"); for (int num = immutableArray.Length - 1; num >= 0; num--) { if (predicate(immutableArray[num])) { return immutableArray[num]; } } return default(T); } public static T Single(this ImmutableArray immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.Single(); } public static T Single(this ImmutableArray immutableArray, Func predicate) { Requires.NotNull(predicate, "predicate"); bool flag = true; T result = default(T); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { if (!flag) { ImmutableArray.TwoElementArray.Single(); } flag = false; result = val; } } if (flag) { Enumerable.Empty().Single(); } return result; } public static T? SingleOrDefault(this ImmutableArray immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); return immutableArray.array.SingleOrDefault(); } public static T? SingleOrDefault(this ImmutableArray immutableArray, Func predicate) { Requires.NotNull(predicate, "predicate"); bool flag = true; T result = default(T); T[] array = immutableArray.array; foreach (T val in array) { if (predicate(val)) { if (!flag) { ImmutableArray.TwoElementArray.Single(); } flag = false; result = val; } } return result; } public static Dictionary ToDictionary(this ImmutableArray immutableArray, Func keySelector) where TKey : notnull { return immutableArray.ToDictionary(keySelector, EqualityComparer.Default); } public static Dictionary ToDictionary(this ImmutableArray immutableArray, Func keySelector, Func elementSelector) where TKey : notnull { return immutableArray.ToDictionary(keySelector, elementSelector, EqualityComparer.Default); } public static Dictionary ToDictionary(this ImmutableArray immutableArray, Func keySelector, IEqualityComparer? comparer) where TKey : notnull { Requires.NotNull(keySelector, "keySelector"); Dictionary dictionary = new Dictionary(immutableArray.Length, comparer); ImmutableArray.Enumerator enumerator = immutableArray.GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; dictionary.Add(keySelector(current), current); } return dictionary; } public static Dictionary ToDictionary(this ImmutableArray immutableArray, Func keySelector, Func elementSelector, IEqualityComparer? comparer) where TKey : notnull { Requires.NotNull(keySelector, "keySelector"); Requires.NotNull(elementSelector, "elementSelector"); Dictionary dictionary = new Dictionary(immutableArray.Length, comparer); T[] array = immutableArray.array; foreach (T arg in array) { dictionary.Add(keySelector(arg), elementSelector(arg)); } return dictionary; } public static T[] ToArray(this ImmutableArray immutableArray) { immutableArray.ThrowNullRefIfNotInitialized(); if (immutableArray.array.Length == 0) { return ImmutableArray.Empty.array; } return (T[])immutableArray.array.Clone(); } public static T First(this ImmutableArray.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { throw new InvalidOperationException(); } return builder[0]; } public static T? FirstOrDefault(this ImmutableArray.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { return default(T); } return builder[0]; } public static T Last(this ImmutableArray.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { throw new InvalidOperationException(); } return builder[builder.Count - 1]; } public static T? LastOrDefault(this ImmutableArray.Builder builder) { Requires.NotNull(builder, "builder"); if (!builder.Any()) { return default(T); } return builder[builder.Count - 1]; } public static bool Any(this ImmutableArray.Builder builder) { Requires.NotNull(builder, "builder"); return builder.Count > 0; } private static IEnumerable SelectManyIterator(this ImmutableArray immutableArray, Func> collectionSelector, Func resultSelector) where TSource : notnull where TCollection : notnull where TResult : notnull { TSource[] array = immutableArray.array; foreach (TSource item in array) { foreach (TCollection item2 in collectionSelector(item)) { yield return resultSelector(item, item2); } } } } } namespace System.Collections.Immutable { internal static class AllocFreeConcurrentStack { [ThreadStatic] private static Stack> t_stack; public static void TryAdd(T item) { Stack> stack = t_stack ?? (t_stack = new Stack>(35)); if (stack.Count < 35) { stack.Push(new RefAsValueType(item)); } } public static bool TryTake([MaybeNullWhen(false)] out T item) { Stack> stack = t_stack; if (stack != null && stack.Count > 0) { item = stack.Pop().Value; return true; } item = default(T); return false; } } internal sealed class DictionaryEnumerator : IDictionaryEnumerator, IEnumerator where TKey : notnull { private readonly IEnumerator> _inner; public DictionaryEntry Entry => new DictionaryEntry(_inner.Current.Key, _inner.Current.Value); public object Key => _inner.Current.Key; public object? Value => _inner.Current.Value; public object Current => Entry; internal DictionaryEnumerator(IEnumerator> inner) { Requires.NotNull(inner, "inner"); _inner = inner; } public bool MoveNext() { return _inner.MoveNext(); } public void Reset() { _inner.Reset(); } } internal struct DisposableEnumeratorAdapter : IDisposable where TEnumerator : struct, IEnumerator { private readonly IEnumerator _enumeratorObject; private TEnumerator _enumeratorStruct; public T Current { get { if (_enumeratorObject == null) { return _enumeratorStruct.Current; } return _enumeratorObject.Current; } } internal DisposableEnumeratorAdapter(TEnumerator enumerator) { _enumeratorStruct = enumerator; _enumeratorObject = null; } internal DisposableEnumeratorAdapter(IEnumerator enumerator) { _enumeratorStruct = default(TEnumerator); _enumeratorObject = enumerator; } public bool MoveNext() { if (_enumeratorObject == null) { return _enumeratorStruct.MoveNext(); } return _enumeratorObject.MoveNext(); } public void Dispose() { if (_enumeratorObject != null) { _enumeratorObject.Dispose(); } else { _enumeratorStruct.Dispose(); } } public DisposableEnumeratorAdapter GetEnumerator() { return this; } } internal interface IBinaryTree { int Height { get; } bool IsEmpty { get; } int Count { get; } IBinaryTree? Left { get; } IBinaryTree? Right { get; } } internal interface IBinaryTree : IBinaryTree { T Value { get; } new IBinaryTree? Left { get; } new IBinaryTree? Right { get; } } internal interface IImmutableArray { Array? Array { get; } } internal interface IImmutableDictionary : IReadOnlyDictionary, IEnumerable>, IEnumerable, IReadOnlyCollection> { IImmutableDictionary Clear(); IImmutableDictionary Add(TKey key, TValue value); IImmutableDictionary AddRange(IEnumerable> pairs); IImmutableDictionary SetItem(TKey key, TValue value); IImmutableDictionary SetItems(IEnumerable> items); IImmutableDictionary RemoveRange(IEnumerable keys); IImmutableDictionary Remove(TKey key); bool Contains(KeyValuePair pair); bool TryGetKey(TKey equalKey, out TKey actualKey); } internal interface IImmutableDictionaryInternal { bool ContainsValue(TValue value); } internal interface IImmutableList : IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { IImmutableList Clear(); int IndexOf(T item, int index, int count, IEqualityComparer? equalityComparer); int LastIndexOf(T item, int index, int count, IEqualityComparer? equalityComparer); IImmutableList Add(T value); IImmutableList AddRange(IEnumerable items); IImmutableList Insert(int index, T element); IImmutableList InsertRange(int index, IEnumerable items); IImmutableList Remove(T value, IEqualityComparer? equalityComparer); IImmutableList RemoveAll(Predicate match); IImmutableList RemoveRange(IEnumerable items, IEqualityComparer? equalityComparer); IImmutableList RemoveRange(int index, int count); IImmutableList RemoveAt(int index); IImmutableList SetItem(int index, T value); IImmutableList Replace(T oldValue, T newValue, IEqualityComparer? equalityComparer); } internal interface IImmutableListQueries : IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { ImmutableList ConvertAll(Func converter); void ForEach(Action action); ImmutableList GetRange(int index, int count); void CopyTo(T[] array); void CopyTo(T[] array, int arrayIndex); void CopyTo(int index, T[] array, int arrayIndex, int count); bool Exists(Predicate match); T? Find(Predicate match); ImmutableList FindAll(Predicate match); int FindIndex(Predicate match); int FindIndex(int startIndex, Predicate match); int FindIndex(int startIndex, int count, Predicate match); T? FindLast(Predicate match); int FindLastIndex(Predicate match); int FindLastIndex(int startIndex, Predicate match); int FindLastIndex(int startIndex, int count, Predicate match); bool TrueForAll(Predicate match); int BinarySearch(T item); int BinarySearch(T item, IComparer? comparer); int BinarySearch(int index, int count, T item, IComparer? comparer); } internal interface IImmutableQueue : IEnumerable, IEnumerable { bool IsEmpty { get; } IImmutableQueue Clear(); T Peek(); IImmutableQueue Enqueue(T value); IImmutableQueue Dequeue(); } internal interface IImmutableSet : IReadOnlyCollection, IEnumerable, IEnumerable { IImmutableSet Clear(); bool Contains(T value); IImmutableSet Add(T value); IImmutableSet Remove(T value); bool TryGetValue(T equalValue, out T actualValue); IImmutableSet Intersect(IEnumerable other); IImmutableSet Except(IEnumerable other); IImmutableSet SymmetricExcept(IEnumerable other); IImmutableSet Union(IEnumerable other); bool SetEquals(IEnumerable other); bool IsProperSubsetOf(IEnumerable other); bool IsProperSupersetOf(IEnumerable other); bool IsSubsetOf(IEnumerable other); bool IsSupersetOf(IEnumerable other); bool Overlaps(IEnumerable other); } internal interface IImmutableStack : IEnumerable, IEnumerable { bool IsEmpty { get; } IImmutableStack Clear(); IImmutableStack Push(T value); IImmutableStack Pop(); T Peek(); } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] internal sealed class ImmutableHashSet : IImmutableSet, IReadOnlyCollection, IEnumerable, IEnumerable, IHashKeyCollection, ICollection, ISet, ICollection, IStrongEnumerable.Enumerator>, IReadOnlySet { private sealed class HashBucketByValueEqualityComparer : IEqualityComparer { private static readonly IEqualityComparer.HashBucket> s_defaultInstance = new HashBucketByValueEqualityComparer(EqualityComparer.Default); private readonly IEqualityComparer _valueComparer; internal static IEqualityComparer.HashBucket> DefaultInstance => s_defaultInstance; internal HashBucketByValueEqualityComparer(IEqualityComparer valueComparer) { Requires.NotNull(valueComparer, "valueComparer"); _valueComparer = valueComparer; } public bool Equals(ImmutableHashSet.HashBucket x, ImmutableHashSet.HashBucket y) { return x.EqualsByValue(y, _valueComparer); } public int GetHashCode(ImmutableHashSet.HashBucket obj) { throw new NotSupportedException(); } } private sealed class HashBucketByRefEqualityComparer : IEqualityComparer { private static readonly IEqualityComparer.HashBucket> s_defaultInstance = new HashBucketByRefEqualityComparer(); internal static IEqualityComparer.HashBucket> DefaultInstance => s_defaultInstance; private HashBucketByRefEqualityComparer() { } public bool Equals(ImmutableHashSet.HashBucket x, ImmutableHashSet.HashBucket y) { return x.EqualsByRef(y); } public int GetHashCode(ImmutableHashSet.HashBucket obj) { throw new NotSupportedException(); } } [DebuggerDisplay("Count = {Count}")] public sealed class Builder : IReadOnlyCollection, IEnumerable, IEnumerable, ISet, ICollection { private SortedInt32KeyNode.HashBucket> _root = SortedInt32KeyNode.EmptyNode; private IEqualityComparer _equalityComparer; private readonly IEqualityComparer.HashBucket> _hashBucketEqualityComparer; private int _count; private ImmutableHashSet _immutable; private int _version; public int Count => _count; bool ICollection.IsReadOnly => false; public IEqualityComparer KeyComparer { get { return _equalityComparer; } set { Requires.NotNull(value, "value"); if (value != _equalityComparer) { MutationResult mutationResult = ImmutableHashSet.Union((IEnumerable)this, new MutationInput(SortedInt32KeyNode.EmptyNode, value, _hashBucketEqualityComparer, 0)); _immutable = null; _equalityComparer = value; Root = mutationResult.Root; _count = mutationResult.Count; } } } internal int Version => _version; private MutationInput Origin => new MutationInput(Root, _equalityComparer, _hashBucketEqualityComparer, _count); private SortedInt32KeyNode Root { get { return _root; } set { _version++; if (_root != value) { _root = value; _immutable = null; } } } internal Builder(ImmutableHashSet set) { Requires.NotNull(set, "set"); _root = set._root; _count = set._count; _equalityComparer = set._equalityComparer; _hashBucketEqualityComparer = set._hashBucketEqualityComparer; _immutable = set; } public Enumerator GetEnumerator() { return new Enumerator(_root, this); } public ImmutableHashSet ToImmutable() { return _immutable ?? (_immutable = ImmutableHashSet.Wrap(_root, _equalityComparer, _count)); } public bool TryGetValue(T equalValue, out T actualValue) { int key = ((equalValue != null) ? _equalityComparer.GetHashCode(equalValue) : 0); if (_root.TryGetValue(key, out var value)) { return value.TryExchange(equalValue, _equalityComparer, out actualValue); } actualValue = equalValue; return false; } public bool Add(T item) { MutationResult result = ImmutableHashSet.Add(item, Origin); Apply(result); return result.Count != 0; } public bool Remove(T item) { MutationResult result = ImmutableHashSet.Remove(item, Origin); Apply(result); return result.Count != 0; } public bool Contains(T item) { return ImmutableHashSet.Contains(item, Origin); } public void Clear() { _count = 0; Root = SortedInt32KeyNode.EmptyNode; } public void ExceptWith(IEnumerable other) { MutationResult result = ImmutableHashSet.Except(other, _equalityComparer, _hashBucketEqualityComparer, _root); Apply(result); } public void IntersectWith(IEnumerable other) { MutationResult result = ImmutableHashSet.Intersect(other, Origin); Apply(result); } public bool IsProperSubsetOf(IEnumerable other) { return ImmutableHashSet.IsProperSubsetOf(other, Origin); } public bool IsProperSupersetOf(IEnumerable other) { return ImmutableHashSet.IsProperSupersetOf(other, Origin); } public bool IsSubsetOf(IEnumerable other) { return ImmutableHashSet.IsSubsetOf(other, Origin); } public bool IsSupersetOf(IEnumerable other) { return ImmutableHashSet.IsSupersetOf(other, Origin); } public bool Overlaps(IEnumerable other) { return ImmutableHashSet.Overlaps(other, Origin); } public bool SetEquals(IEnumerable other) { if (this == other) { return true; } return ImmutableHashSet.SetEquals(other, Origin); } public void SymmetricExceptWith(IEnumerable other) { MutationResult result = ImmutableHashSet.SymmetricExcept(other, Origin); Apply(result); } public void UnionWith(IEnumerable other) { MutationResult result = ImmutableHashSet.Union(other, Origin); Apply(result); } void ICollection.Add(T item) { Add(item); } void ICollection.CopyTo(T[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array[arrayIndex++] = current; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private void Apply(ImmutableHashSet.MutationResult result) { Root = result.Root; if (result.CountType == ImmutableHashSet.CountType.Adjustment) { _count += result.Count; } else { _count = result.Count; } } } public struct Enumerator : IEnumerator, IEnumerator, IDisposable, IStrongEnumerator { private readonly Builder _builder; private SortedInt32KeyNode.Enumerator _mapEnumerator; private HashBucket.Enumerator _bucketEnumerator; private int _enumeratingBuilderVersion; public T Current { get { _mapEnumerator.ThrowIfDisposed(); return _bucketEnumerator.Current; } } object? IEnumerator.Current => Current; internal Enumerator(SortedInt32KeyNode root, Builder? builder = null) { _builder = builder; _mapEnumerator = new SortedInt32KeyNode.Enumerator(root); _bucketEnumerator = default(HashBucket.Enumerator); _enumeratingBuilderVersion = builder?.Version ?? (-1); } public bool MoveNext() { ThrowIfChanged(); if (_bucketEnumerator.MoveNext()) { return true; } if (_mapEnumerator.MoveNext()) { _bucketEnumerator = new HashBucket.Enumerator(_mapEnumerator.Current.Value); return _bucketEnumerator.MoveNext(); } return false; } public void Reset() { _enumeratingBuilderVersion = ((_builder != null) ? _builder.Version : (-1)); _mapEnumerator.Reset(); _bucketEnumerator.Dispose(); _bucketEnumerator = default(HashBucket.Enumerator); } public void Dispose() { _mapEnumerator.Dispose(); _bucketEnumerator.Dispose(); } private void ThrowIfChanged() { if (_builder != null && _builder.Version != _enumeratingBuilderVersion) { throw new InvalidOperationException(System.SR.CollectionModifiedDuringEnumeration); } } } internal enum OperationResult { SizeChanged, NoChangeRequired } internal readonly struct HashBucket { internal struct Enumerator : IEnumerator, IEnumerator, IDisposable { private enum Position { BeforeFirst, First, Additional, End } private readonly HashBucket _bucket; private bool _disposed; private Position _currentPosition; private ImmutableList.Enumerator _additionalEnumerator; object? IEnumerator.Current => Current; public T Current { get { ThrowIfDisposed(); return _currentPosition switch { Position.First => _bucket._firstValue, Position.Additional => _additionalEnumerator.Current, _ => throw new InvalidOperationException(), }; } } internal Enumerator(HashBucket bucket) { _disposed = false; _bucket = bucket; _currentPosition = Position.BeforeFirst; _additionalEnumerator = default(ImmutableList.Enumerator); } public bool MoveNext() { ThrowIfDisposed(); if (_bucket.IsEmpty) { _currentPosition = Position.End; return false; } switch (_currentPosition) { case Position.BeforeFirst: _currentPosition = Position.First; return true; case Position.First: if (_bucket._additionalElements.IsEmpty) { _currentPosition = Position.End; return false; } _currentPosition = Position.Additional; _additionalEnumerator = new ImmutableList.Enumerator(_bucket._additionalElements); return _additionalEnumerator.MoveNext(); case Position.Additional: return _additionalEnumerator.MoveNext(); case Position.End: return false; default: throw new InvalidOperationException(); } } public void Reset() { ThrowIfDisposed(); _additionalEnumerator.Dispose(); _currentPosition = Position.BeforeFirst; } public void Dispose() { _disposed = true; _additionalEnumerator.Dispose(); } private void ThrowIfDisposed() { if (_disposed) { Requires.FailObjectDisposed(this); } } } private readonly T _firstValue; private readonly ImmutableList.Node _additionalElements; internal bool IsEmpty => _additionalElements == null; private HashBucket(T firstElement, ImmutableList.Node additionalElements = null) { _firstValue = firstElement; _additionalElements = additionalElements ?? ImmutableList.Node.EmptyNode; } public Enumerator GetEnumerator() { return new Enumerator(this); } public override bool Equals(object? obj) { throw new NotSupportedException(); } public override int GetHashCode() { throw new NotSupportedException(); } internal bool EqualsByRef(HashBucket other) { if ((object)_firstValue == (object)other._firstValue) { return _additionalElements == other._additionalElements; } return false; } internal bool EqualsByValue(HashBucket other, IEqualityComparer valueComparer) { if (valueComparer.Equals(_firstValue, other._firstValue)) { return _additionalElements == other._additionalElements; } return false; } internal HashBucket Add(T value, IEqualityComparer valueComparer, out OperationResult result) { if (IsEmpty) { result = OperationResult.SizeChanged; return new HashBucket(value); } if (valueComparer.Equals(value, _firstValue) || _additionalElements.IndexOf(value, valueComparer) >= 0) { result = OperationResult.NoChangeRequired; return this; } result = OperationResult.SizeChanged; return new HashBucket(_firstValue, _additionalElements.Add(value)); } internal bool Contains(T value, IEqualityComparer valueComparer) { if (IsEmpty) { return false; } if (!valueComparer.Equals(value, _firstValue)) { return _additionalElements.IndexOf(value, valueComparer) >= 0; } return true; } internal bool TryExchange(T value, IEqualityComparer valueComparer, out T existingValue) { if (!IsEmpty) { if (valueComparer.Equals(value, _firstValue)) { existingValue = _firstValue; return true; } int num = _additionalElements.IndexOf(value, valueComparer); if (num >= 0) { existingValue = _additionalElements.ItemRef(num); return true; } } existingValue = value; return false; } internal HashBucket Remove(T value, IEqualityComparer equalityComparer, out OperationResult result) { if (IsEmpty) { result = OperationResult.NoChangeRequired; return this; } if (equalityComparer.Equals(_firstValue, value)) { if (_additionalElements.IsEmpty) { result = OperationResult.SizeChanged; return default(HashBucket); } int count = _additionalElements.Left.Count; result = OperationResult.SizeChanged; return new HashBucket(_additionalElements.Key, _additionalElements.RemoveAt(count)); } int num = _additionalElements.IndexOf(value, equalityComparer); if (num < 0) { result = OperationResult.NoChangeRequired; return this; } result = OperationResult.SizeChanged; return new HashBucket(_firstValue, _additionalElements.RemoveAt(num)); } internal void Freeze() { _additionalElements?.Freeze(); } } private readonly struct MutationInput { private readonly SortedInt32KeyNode.HashBucket> _root; private readonly IEqualityComparer _equalityComparer; private readonly int _count; private readonly IEqualityComparer.HashBucket> _hashBucketEqualityComparer; internal SortedInt32KeyNode.HashBucket> Root => _root; internal IEqualityComparer EqualityComparer => _equalityComparer; internal int Count => _count; internal IEqualityComparer.HashBucket> HashBucketEqualityComparer => _hashBucketEqualityComparer; internal MutationInput(ImmutableHashSet set) { Requires.NotNull(set, "set"); _root = set._root; _equalityComparer = set._equalityComparer; _count = set._count; _hashBucketEqualityComparer = set._hashBucketEqualityComparer; } internal MutationInput(SortedInt32KeyNode.HashBucket> root, IEqualityComparer equalityComparer, IEqualityComparer.HashBucket> hashBucketEqualityComparer, int count) { Requires.NotNull(root, "root"); Requires.NotNull(equalityComparer, "equalityComparer"); Requires.Range(count >= 0, "count"); Requires.NotNull(hashBucketEqualityComparer, "hashBucketEqualityComparer"); _root = root; _equalityComparer = equalityComparer; _count = count; _hashBucketEqualityComparer = hashBucketEqualityComparer; } } private enum CountType { Adjustment, FinalValue } private readonly struct MutationResult { private readonly SortedInt32KeyNode.HashBucket> _root; private readonly int _count; private readonly ImmutableHashSet.CountType _countType; internal SortedInt32KeyNode.HashBucket> Root => _root; internal int Count => _count; internal ImmutableHashSet.CountType CountType => _countType; internal MutationResult(SortedInt32KeyNode.HashBucket> root, int count, ImmutableHashSet.CountType countType = ImmutableHashSet.CountType.Adjustment) { Requires.NotNull(root, "root"); _root = root; _count = count; _countType = countType; } internal ImmutableHashSet Finalize(ImmutableHashSet priorSet) { Requires.NotNull(priorSet, "priorSet"); int num = Count; if (CountType == CountType.Adjustment) { num += priorSet._count; } return priorSet.Wrap(Root, num); } } private readonly struct NodeEnumerable : IEnumerable, IEnumerable { private readonly SortedInt32KeyNode.HashBucket> _root; internal NodeEnumerable(SortedInt32KeyNode.HashBucket> root) { Requires.NotNull(root, "root"); _root = root; } public ImmutableHashSet.Enumerator GetEnumerator() { return new Enumerator(_root); } [ExcludeFromCodeCoverage] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } [ExcludeFromCodeCoverage] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public static readonly ImmutableHashSet Empty = new ImmutableHashSet(SortedInt32KeyNode.EmptyNode, EqualityComparer.Default, 0); private static readonly Action.HashBucket>> s_FreezeBucketAction = delegate(KeyValuePair kv) { kv.Value.Freeze(); }; private readonly IEqualityComparer _equalityComparer; private readonly int _count; private readonly SortedInt32KeyNode.HashBucket> _root; private readonly IEqualityComparer.HashBucket> _hashBucketEqualityComparer; public int Count => _count; public bool IsEmpty => Count == 0; public IEqualityComparer KeyComparer => _equalityComparer; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot => this; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; internal IBinaryTree Root => _root; private MutationInput Origin => new MutationInput(this); bool ICollection.IsReadOnly => true; internal ImmutableHashSet(IEqualityComparer equalityComparer) : this(SortedInt32KeyNode.EmptyNode, equalityComparer, 0) { } private ImmutableHashSet(SortedInt32KeyNode.HashBucket> root, IEqualityComparer equalityComparer, int count) { Requires.NotNull(root, "root"); Requires.NotNull(equalityComparer, "equalityComparer"); root.Freeze(s_FreezeBucketAction); _root = root; _count = count; _equalityComparer = equalityComparer; _hashBucketEqualityComparer = GetHashBucketEqualityComparer(equalityComparer); } public ImmutableHashSet Clear() { if (!IsEmpty) { return Empty.WithComparer(_equalityComparer); } return this; } IImmutableSet IImmutableSet.Clear() { return Clear(); } public Builder ToBuilder() { return new Builder(this); } public ImmutableHashSet Add(T item) { return Add(item, Origin).Finalize(this); } public ImmutableHashSet Remove(T item) { return Remove(item, Origin).Finalize(this); } public bool TryGetValue(T equalValue, out T actualValue) { int key = ((equalValue != null) ? _equalityComparer.GetHashCode(equalValue) : 0); if (_root.TryGetValue(key, out var value)) { return value.TryExchange(equalValue, _equalityComparer, out actualValue); } actualValue = equalValue; return false; } public ImmutableHashSet Union(IEnumerable other) { Requires.NotNull(other, "other"); return Union(other, avoidWithComparer: false); } public ImmutableHashSet Intersect(IEnumerable other) { Requires.NotNull(other, "other"); return Intersect(other, Origin).Finalize(this); } public ImmutableHashSet Except(IEnumerable other) { Requires.NotNull(other, "other"); return Except(other, _equalityComparer, _hashBucketEqualityComparer, _root).Finalize(this); } public ImmutableHashSet SymmetricExcept(IEnumerable other) { Requires.NotNull(other, "other"); return SymmetricExcept(other, Origin).Finalize(this); } public bool SetEquals(IEnumerable other) { Requires.NotNull(other, "other"); if (this == other) { return true; } return SetEquals(other, Origin); } public bool IsProperSubsetOf(IEnumerable other) { Requires.NotNull(other, "other"); return IsProperSubsetOf(other, Origin); } public bool IsProperSupersetOf(IEnumerable other) { Requires.NotNull(other, "other"); return IsProperSupersetOf(other, Origin); } public bool IsSubsetOf(IEnumerable other) { Requires.NotNull(other, "other"); return IsSubsetOf(other, Origin); } public bool IsSupersetOf(IEnumerable other) { Requires.NotNull(other, "other"); return IsSupersetOf(other, Origin); } public bool Overlaps(IEnumerable other) { Requires.NotNull(other, "other"); return Overlaps(other, Origin); } IImmutableSet IImmutableSet.Add(T item) { return Add(item); } IImmutableSet IImmutableSet.Remove(T item) { return Remove(item); } IImmutableSet IImmutableSet.Union(IEnumerable other) { return Union(other); } IImmutableSet IImmutableSet.Intersect(IEnumerable other) { return Intersect(other); } IImmutableSet IImmutableSet.Except(IEnumerable other) { return Except(other); } IImmutableSet IImmutableSet.SymmetricExcept(IEnumerable other) { return SymmetricExcept(other); } public bool Contains(T item) { return Contains(item, Origin); } public ImmutableHashSet WithComparer(IEqualityComparer? equalityComparer) { if (equalityComparer == null) { equalityComparer = EqualityComparer.Default; } if (equalityComparer == _equalityComparer) { return this; } ImmutableHashSet immutableHashSet = new ImmutableHashSet(equalityComparer); return immutableHashSet.Union(this, avoidWithComparer: true); } bool ISet.Add(T item) { throw new NotSupportedException(); } void ISet.ExceptWith(IEnumerable other) { throw new NotSupportedException(); } void ISet.IntersectWith(IEnumerable other) { throw new NotSupportedException(); } void ISet.SymmetricExceptWith(IEnumerable other) { throw new NotSupportedException(); } void ISet.UnionWith(IEnumerable other) { throw new NotSupportedException(); } void ICollection.CopyTo(T[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array[arrayIndex++] = current; } } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } void ICollection.CopyTo(Array array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array.SetValue(current, arrayIndex++); } } public Enumerator GetEnumerator() { return new Enumerator(_root); } IEnumerator IEnumerable.GetEnumerator() { if (!IsEmpty) { return GetEnumerator(); } return Enumerable.Empty().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private static bool IsSupersetOf(IEnumerable other, ImmutableHashSet.MutationInput origin) { Requires.NotNull(other, "other"); foreach (T item in other.GetEnumerableDisposable()) { if (!Contains(item, origin)) { return false; } } return true; } private static ImmutableHashSet.MutationResult Add(T item, ImmutableHashSet.MutationInput origin) { int num = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); OperationResult result; HashBucket newBucket = origin.Root.GetValueOrDefault(num).Add(item, origin.EqualityComparer, out result); if (result == OperationResult.NoChangeRequired) { return new MutationResult(origin.Root, 0); } SortedInt32KeyNode root = UpdateRoot(origin.Root, num, origin.HashBucketEqualityComparer, newBucket); return new MutationResult(root, 1); } private static ImmutableHashSet.MutationResult Remove(T item, ImmutableHashSet.MutationInput origin) { OperationResult result = OperationResult.NoChangeRequired; int num = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); SortedInt32KeyNode root = origin.Root; if (origin.Root.TryGetValue(num, out HashBucket value)) { HashBucket newBucket = value.Remove(item, origin.EqualityComparer, out result); if (result == OperationResult.NoChangeRequired) { return new MutationResult(origin.Root, 0); } root = UpdateRoot(origin.Root, num, origin.HashBucketEqualityComparer, newBucket); } return new MutationResult(root, (result == OperationResult.SizeChanged) ? (-1) : 0); } private static bool Contains(T item, ImmutableHashSet.MutationInput origin) { int key = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); if (origin.Root.TryGetValue(key, out HashBucket value)) { return value.Contains(item, origin.EqualityComparer); } return false; } private static ImmutableHashSet.MutationResult Union(IEnumerable other, ImmutableHashSet.MutationInput origin) { Requires.NotNull(other, "other"); int num = 0; SortedInt32KeyNode sortedInt32KeyNode = origin.Root; foreach (T item in other.GetEnumerableDisposable()) { int num2 = ((item != null) ? origin.EqualityComparer.GetHashCode(item) : 0); OperationResult result; HashBucket newBucket = sortedInt32KeyNode.GetValueOrDefault(num2).Add(item, origin.EqualityComparer, out result); if (result == OperationResult.SizeChanged) { sortedInt32KeyNode = UpdateRoot(sortedInt32KeyNode, num2, origin.HashBucketEqualityComparer, newBucket); num++; } } return new MutationResult(sortedInt32KeyNode, num); } private static bool Overlaps(IEnumerable other, ImmutableHashSet.MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return false; } foreach (T item in other.GetEnumerableDisposable()) { if (Contains(item, origin)) { return true; } } return false; } private static bool SetEquals(IEnumerable other, ImmutableHashSet.MutationInput origin) { Requires.NotNull(other, "other"); HashSet hashSet = new HashSet(other, origin.EqualityComparer); if (origin.Count != hashSet.Count) { return false; } foreach (T item in hashSet) { if (!Contains(item, origin)) { return false; } } return true; } private static SortedInt32KeyNode.HashBucket> UpdateRoot(SortedInt32KeyNode.HashBucket> root, int hashCode, IEqualityComparer.HashBucket> hashBucketEqualityComparer, ImmutableHashSet.HashBucket newBucket) { bool mutated; if (newBucket.IsEmpty) { return root.Remove(hashCode, out mutated); } bool mutated2; return root.SetItem(hashCode, newBucket, hashBucketEqualityComparer, out mutated, out mutated2); } private static ImmutableHashSet.MutationResult Intersect(IEnumerable other, ImmutableHashSet.MutationInput origin) { Requires.NotNull(other, "other"); SortedInt32KeyNode root = SortedInt32KeyNode.EmptyNode; int num = 0; foreach (T item in other.GetEnumerableDisposable()) { if (Contains(item, origin)) { MutationResult mutationResult = Add(item, new MutationInput(root, origin.EqualityComparer, origin.HashBucketEqualityComparer, num)); root = mutationResult.Root; num += mutationResult.Count; } } return new MutationResult(root, num, CountType.FinalValue); } private static ImmutableHashSet.MutationResult Except(IEnumerable other, IEqualityComparer equalityComparer, IEqualityComparer.HashBucket> hashBucketEqualityComparer, SortedInt32KeyNode.HashBucket> root) { Requires.NotNull(other, "other"); Requires.NotNull(equalityComparer, "equalityComparer"); Requires.NotNull(root, "root"); int num = 0; SortedInt32KeyNode sortedInt32KeyNode = root; foreach (T item in other.GetEnumerableDisposable()) { int num2 = ((item != null) ? equalityComparer.GetHashCode(item) : 0); if (sortedInt32KeyNode.TryGetValue(num2, out var value)) { OperationResult result; HashBucket newBucket = value.Remove(item, equalityComparer, out result); if (result == OperationResult.SizeChanged) { num--; sortedInt32KeyNode = UpdateRoot(sortedInt32KeyNode, num2, hashBucketEqualityComparer, newBucket); } } } return new MutationResult(sortedInt32KeyNode, num); } private static ImmutableHashSet.MutationResult SymmetricExcept(IEnumerable other, ImmutableHashSet.MutationInput origin) { Requires.NotNull(other, "other"); ImmutableHashSet immutableHashSet = ImmutableHashSet.CreateRange(origin.EqualityComparer, other); int num = 0; SortedInt32KeyNode root = SortedInt32KeyNode.EmptyNode; foreach (T item in new NodeEnumerable(origin.Root)) { if (!immutableHashSet.Contains(item)) { MutationResult mutationResult = Add(item, new MutationInput(root, origin.EqualityComparer, origin.HashBucketEqualityComparer, num)); root = mutationResult.Root; num += mutationResult.Count; } } foreach (T item2 in immutableHashSet) { if (!Contains(item2, origin)) { MutationResult mutationResult2 = Add(item2, new MutationInput(root, origin.EqualityComparer, origin.HashBucketEqualityComparer, num)); root = mutationResult2.Root; num += mutationResult2.Count; } } return new MutationResult(root, num, CountType.FinalValue); } private static bool IsProperSubsetOf(IEnumerable other, ImmutableHashSet.MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return other.Any(); } HashSet hashSet = new HashSet(other, origin.EqualityComparer); if (origin.Count >= hashSet.Count) { return false; } int num = 0; bool flag = false; foreach (T item in hashSet) { if (Contains(item, origin)) { num++; } else { flag = true; } if (num == origin.Count && flag) { return true; } } return false; } private static bool IsProperSupersetOf(IEnumerable other, ImmutableHashSet.MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return false; } int num = 0; foreach (T item in other.GetEnumerableDisposable()) { num++; if (!Contains(item, origin)) { return false; } } return origin.Count > num; } private static bool IsSubsetOf(IEnumerable other, ImmutableHashSet.MutationInput origin) { Requires.NotNull(other, "other"); if (origin.Root.IsEmpty) { return true; } HashSet hashSet = new HashSet(other, origin.EqualityComparer); int num = 0; foreach (T item in hashSet) { if (Contains(item, origin)) { num++; } } return num == origin.Count; } private static ImmutableHashSet Wrap(SortedInt32KeyNode.HashBucket> root, IEqualityComparer equalityComparer, int count) { Requires.NotNull(root, "root"); Requires.NotNull(equalityComparer, "equalityComparer"); Requires.Range(count >= 0, "count"); return new ImmutableHashSet(root, equalityComparer, count); } private static IEqualityComparer.HashBucket> GetHashBucketEqualityComparer(IEqualityComparer valueComparer) { if (!ImmutableExtensions.IsValueType()) { return HashBucketByRefEqualityComparer.DefaultInstance; } if (valueComparer == EqualityComparer.Default) { return HashBucketByValueEqualityComparer.DefaultInstance; } return new HashBucketByValueEqualityComparer(valueComparer); } private ImmutableHashSet Wrap(SortedInt32KeyNode.HashBucket> root, int adjustedCountIfDifferentRoot) { if (root == _root) { return this; } return new ImmutableHashSet(root, _equalityComparer, adjustedCountIfDifferentRoot); } private ImmutableHashSet Union(IEnumerable items, bool avoidWithComparer) { Requires.NotNull(items, "items"); if (IsEmpty && !avoidWithComparer && items is ImmutableHashSet immutableHashSet) { return immutableHashSet.WithComparer(KeyComparer); } return Union(items, Origin).Finalize(this); } } internal interface IStrongEnumerable where TEnumerator : struct, IStrongEnumerator { TEnumerator GetEnumerator(); } internal interface IStrongEnumerator { T Current { get; } bool MoveNext(); } internal interface IOrderedCollection : IEnumerable, IEnumerable { int Count { get; } T this[int index] { get; } } internal static class ImmutableArray { internal static readonly byte[] TwoElementArray = new byte[2]; public static ImmutableArray Create() { return ImmutableArray.Empty; } public static ImmutableArray Create(T item) { T[] items = new T[1] { item }; return new ImmutableArray(items); } public static ImmutableArray Create(T item1, T item2) { T[] items = new T[2] { item1, item2 }; return new ImmutableArray(items); } public static ImmutableArray Create(T item1, T item2, T item3) { T[] items = new T[3] { item1, item2, item3 }; return new ImmutableArray(items); } public static ImmutableArray Create(T item1, T item2, T item3, T item4) { T[] items = new T[4] { item1, item2, item3, item4 }; return new ImmutableArray(items); } public static ImmutableArray Create(ReadOnlySpan items) { if (items.IsEmpty) { return ImmutableArray.Empty; } T[] items2 = items.ToArray(); return new ImmutableArray(items2); } public static ImmutableArray Create(Span items) { return Create((ReadOnlySpan)items); } public static ImmutableArray ToImmutableArray(this ReadOnlySpan items) { return Create(items); } public static ImmutableArray ToImmutableArray(this Span items) { return Create((ReadOnlySpan)items); } public static ImmutableArray CreateRange(IEnumerable items) { Requires.NotNull(items, "items"); if (items is IImmutableArray immutableArray) { Array array = immutableArray.Array; if (array == null) { throw new InvalidOperationException(System.SR.InvalidOperationOnDefaultArray); } return new ImmutableArray((T[])array); } if (items.TryGetCount(out var count)) { return new ImmutableArray(items.ToArray(count)); } return new ImmutableArray(items.ToArray()); } public static ImmutableArray Create(params T[]? items) { if (items == null || items.Length == 0) { return ImmutableArray.Empty; } T[] array = new T[items.Length]; Array.Copy(items, array, items.Length); return new ImmutableArray(array); } public static ImmutableArray Create(T[] items, int start, int length) { Requires.NotNull(items, "items"); Requires.Range(start >= 0 && start <= items.Length, "start"); Requires.Range(length >= 0 && start + length <= items.Length, "length"); if (length == 0) { return Create(); } T[] array = new T[length]; for (int i = 0; i < array.Length; i++) { array[i] = items[start + i]; } return new ImmutableArray(array); } public static ImmutableArray Create(ImmutableArray items, int start, int length) { Requires.Range(start >= 0 && start <= items.Length, "start"); Requires.Range(length >= 0 && start + length <= items.Length, "length"); if (length == 0) { return Create(); } if (start == 0 && length == items.Length) { return items; } T[] array = new T[length]; Array.Copy(items.array, start, array, 0, length); return new ImmutableArray(array); } public static ImmutableArray CreateRange(ImmutableArray items, Func selector) { Requires.NotNull(selector, "selector"); int length = items.Length; if (length == 0) { return Create(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i]); } return new ImmutableArray(array); } public static ImmutableArray CreateRange(ImmutableArray items, int start, int length, Func selector) { int length2 = items.Length; Requires.Range(start >= 0 && start <= length2, "start"); Requires.Range(length >= 0 && start + length <= length2, "length"); Requires.NotNull(selector, "selector"); if (length == 0) { return Create(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i + start]); } return new ImmutableArray(array); } public static ImmutableArray CreateRange(ImmutableArray items, Func selector, TArg arg) { Requires.NotNull(selector, "selector"); int length = items.Length; if (length == 0) { return Create(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i], arg); } return new ImmutableArray(array); } public static ImmutableArray CreateRange(ImmutableArray items, int start, int length, Func selector, TArg arg) { int length2 = items.Length; Requires.Range(start >= 0 && start <= length2, "start"); Requires.Range(length >= 0 && start + length <= length2, "length"); Requires.NotNull(selector, "selector"); if (length == 0) { return Create(); } TResult[] array = new TResult[length]; for (int i = 0; i < array.Length; i++) { array[i] = selector(items[i + start], arg); } return new ImmutableArray(array); } public static ImmutableArray.Builder CreateBuilder() { return Create().ToBuilder(); } public static ImmutableArray.Builder CreateBuilder(int initialCapacity) { return new ImmutableArray.Builder(initialCapacity); } public static ImmutableArray ToImmutableArray(this IEnumerable items) { if (items is ImmutableArray) { return (ImmutableArray)(object)items; } return CreateRange(items); } public static ImmutableArray ToImmutableArray(this ImmutableArray.Builder builder) { Requires.NotNull(builder, "builder"); return builder.ToImmutable(); } public static int BinarySearch(this ImmutableArray array, T value) { return Array.BinarySearch(array.array, value); } public static int BinarySearch(this ImmutableArray array, T value, IComparer? comparer) { return Array.BinarySearch(array.array, value, comparer); } public static int BinarySearch(this ImmutableArray array, int index, int length, T value) { return Array.BinarySearch(array.array, index, length, value); } public static int BinarySearch(this ImmutableArray array, int index, int length, T value, IComparer? comparer) { return Array.BinarySearch(array.array, index, length, value, comparer); } } [DebuggerDisplay("{DebuggerDisplay,nq}")] [System.Runtime.Versioning.NonVersionable] internal readonly struct ImmutableArray : IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection, IList, ICollection, IEquatable>, IList, ICollection, IImmutableArray, IStructuralComparable, IStructuralEquatable, IImmutableList { [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableArrayBuilderDebuggerProxy<>))] public sealed class Builder : IList, ICollection, IEnumerable, IEnumerable, IReadOnlyList, IReadOnlyCollection { private T[] _elements; private int _count; public int Capacity { get { return _elements.Length; } set { if (value < _count) { throw new ArgumentException(System.SR.CapacityMustBeGreaterThanOrEqualToCount, "value"); } if (value == _elements.Length) { return; } if (value > 0) { T[] array = new T[value]; if (_count > 0) { Array.Copy(_elements, array, _count); } _elements = array; } else { _elements = ImmutableArray.Empty.array; } } } public int Count { get { return _count; } set { Requires.Range(value >= 0, "value"); if (value < _count) { if (_count - value > 64) { Array.Clear(_elements, value, _count - value); } else { for (int i = value; i < Count; i++) { _elements[i] = default(T); } } } else if (value > _count) { EnsureCapacity(value); } _count = value; } } public T this[int index] { get { if (index >= Count) { ThrowIndexOutOfRangeException(); } return _elements[index]; } set { if (index >= Count) { ThrowIndexOutOfRangeException(); } _elements[index] = value; } } bool ICollection.IsReadOnly => false; internal Builder(int capacity) { Requires.Range(capacity >= 0, "capacity"); _elements = new T[capacity]; _count = 0; } internal Builder() : this(8) { } private static void ThrowIndexOutOfRangeException() { throw new IndexOutOfRangeException(); } public ref readonly T ItemRef(int index) { if (index >= Count) { ThrowIndexOutOfRangeException(); } return ref _elements[index]; } public ImmutableArray ToImmutable() { return new ImmutableArray(ToArray()); } public ImmutableArray MoveToImmutable() { if (Capacity != Count) { throw new InvalidOperationException(System.SR.CapacityMustEqualCountOnMove); } T[] elements = _elements; _elements = ImmutableArray.Empty.array; _count = 0; return new ImmutableArray(elements); } public void Clear() { Count = 0; } public void Insert(int index, T item) { Requires.Range(index >= 0 && index <= Count, "index"); EnsureCapacity(Count + 1); if (index < Count) { Array.Copy(_elements, index, _elements, index + 1, Count - index); } _count++; _elements[index] = item; } public void InsertRange(int index, IEnumerable items) { Requires.Range(index >= 0 && index <= Count, "index"); Requires.NotNull(items, "items"); int count = ImmutableExtensions.GetCount(ref items); EnsureCapacity(Count + count); if (index != Count) { Array.Copy(_elements, index, _elements, index + count, _count - index); } if (!items.TryCopyTo(_elements, index)) { foreach (T item in items) { _elements[index++] = item; } } _count += count; } public void InsertRange(int index, ImmutableArray items) { Requires.Range(index >= 0 && index <= Count, "index"); if (!items.IsEmpty) { EnsureCapacity(Count + items.Length); if (index != Count) { Array.Copy(_elements, index, _elements, index + items.Length, _count - index); } Array.Copy(items.array, 0, _elements, index, items.Length); _count += items.Length; } } public void Add(T item) { int num = _count + 1; EnsureCapacity(num); _elements[_count] = item; _count = num; } public void AddRange(IEnumerable items) { Requires.NotNull(items, "items"); if (items.TryGetCount(out var count)) { EnsureCapacity(Count + count); if (items.TryCopyTo(_elements, _count)) { _count += count; return; } } foreach (T item in items) { Add(item); } } public void AddRange(params T[] items) { Requires.NotNull(items, "items"); int count = Count; Count += items.Length; Array.Copy(items, 0, _elements, count, items.Length); } public void AddRange(TDerived[] items) where TDerived : T { Requires.NotNull(items, "items"); int count = Count; Count += items.Length; Array.Copy(items, 0, _elements, count, items.Length); } public void AddRange(T[] items, int length) { Requires.NotNull(items, "items"); Requires.Range(length >= 0 && length <= items.Length, "length"); int count = Count; Count += length; Array.Copy(items, 0, _elements, count, length); } public void AddRange(ImmutableArray items) { AddRange(items, items.Length); } public void AddRange(ImmutableArray items, int length) { Requires.Range(length >= 0, "length"); if (items.array != null) { AddRange(items.array, length); } } public void AddRange(ReadOnlySpan items) { int count = Count; Count += items.Length; items.CopyTo(new Span(_elements, count, items.Length)); } public void AddRange(ReadOnlySpan items) where TDerived : T { int count = Count; Count += items.Length; Span span = new Span(_elements, count, items.Length); for (int i = 0; i < items.Length; i++) { span[i] = (T)(object)items[i]; } } public void AddRange(ImmutableArray items) where TDerived : T { if (items.array != null) { this.AddRange(items.array); } } public void AddRange(Builder items) { Requires.NotNull(items, "items"); AddRange(items._elements, items.Count); } public void AddRange(ImmutableArray.Builder items) where TDerived : T { Requires.NotNull(items, "items"); AddRange(items._elements, items.Count); } public bool Remove(T element) { int num = IndexOf(element); if (num >= 0) { RemoveAt(num); return true; } return false; } public bool Remove(T element, IEqualityComparer? equalityComparer) { int num = IndexOf(element, 0, _count, equalityComparer); if (num >= 0) { RemoveAt(num); return true; } return false; } public void RemoveAll(Predicate match) { List list = null; for (int i = 0; i < _count; i++) { if (match(_elements[i])) { if (list == null) { list = new List(); } list.Add(i); } } if (list != null) { RemoveAtRange(list); } } public void RemoveAt(int index) { Requires.Range(index >= 0 && index < Count, "index"); if (index < Count - 1) { Array.Copy(_elements, index + 1, _elements, index, Count - index - 1); } Count--; } public void RemoveRange(int index, int length) { Requires.Range(index >= 0 && index + length <= _count, "index"); if (length == 0) { return; } if (index + length < _count) { if (RuntimeHelpers.IsReferenceOrContainsReferences()) { Array.Clear(_elements, index, length); } Array.Copy(_elements, index + length, _elements, index, Count - index - length); } _count -= length; } public void RemoveRange(IEnumerable items) { RemoveRange(items, EqualityComparer.Default); } public void RemoveRange(IEnumerable items, IEqualityComparer? equalityComparer) { Requires.NotNull(items, "items"); SortedSet sortedSet = new SortedSet(); foreach (T item in items) { int num = IndexOf(item, 0, _count, equalityComparer); while (num >= 0 && !sortedSet.Add(num) && num + 1 < _count) { num = IndexOf(item, num + 1, equalityComparer); } } RemoveAtRange(sortedSet); } public void Replace(T oldValue, T newValue) { Replace(oldValue, newValue, EqualityComparer.Default); } public void Replace(T oldValue, T newValue, IEqualityComparer? equalityComparer) { int num = IndexOf(oldValue, 0, _count, equalityComparer); if (num >= 0) { _elements[num] = newValue; } } public bool Contains(T item) { return IndexOf(item) >= 0; } public T[] ToArray() { if (Count == 0) { return ImmutableArray.Empty.array; } T[] array = new T[Count]; Array.Copy(_elements, array, Count); return array; } public void CopyTo(T[] array, int index) { Requires.NotNull(array, "array"); Requires.Range(index >= 0 && index + Count <= array.Length, "index"); Array.Copy(_elements, 0, array, index, Count); } public void CopyTo(T[] destination) { Requires.NotNull(destination, "destination"); Array.Copy(_elements, 0, destination, 0, Count); } public void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) { Requires.NotNull(destination, "destination"); Requires.Range(length >= 0, "length"); Requires.Range(sourceIndex >= 0 && sourceIndex + length <= Count, "sourceIndex"); Requires.Range(destinationIndex >= 0 && destinationIndex + length <= destination.Length, "destinationIndex"); Array.Copy(_elements, sourceIndex, destination, destinationIndex, length); } private void EnsureCapacity(int capacity) { if (_elements.Length < capacity) { int newSize = Math.Max(_elements.Length * 2, capacity); Array.Resize(ref _elements, newSize); } } public int IndexOf(T item) { return IndexOf(item, 0, _count, EqualityComparer.Default); } public int IndexOf(T item, int startIndex) { return IndexOf(item, startIndex, Count - startIndex, EqualityComparer.Default); } public int IndexOf(T item, int startIndex, int count) { return IndexOf(item, startIndex, count, EqualityComparer.Default); } public int IndexOf(T item, int startIndex, int count, IEqualityComparer? equalityComparer) { if (count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < Count, "startIndex"); Requires.Range(count >= 0 && startIndex + count <= Count, "count"); if (equalityComparer == null) { equalityComparer = EqualityComparer.Default; } if (equalityComparer == EqualityComparer.Default) { return Array.IndexOf(_elements, item, startIndex, count); } for (int i = startIndex; i < startIndex + count; i++) { if (equalityComparer.Equals(_elements[i], item)) { return i; } } return -1; } public int IndexOf(T item, int startIndex, IEqualityComparer? equalityComparer) { return IndexOf(item, startIndex, Count - startIndex, equalityComparer); } public int LastIndexOf(T item) { if (Count == 0) { return -1; } return LastIndexOf(item, Count - 1, Count, EqualityComparer.Default); } public int LastIndexOf(T item, int startIndex) { if (Count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < Count, "startIndex"); return LastIndexOf(item, startIndex, startIndex + 1, EqualityComparer.Default); } public int LastIndexOf(T item, int startIndex, int count) { return LastIndexOf(item, startIndex, count, EqualityComparer.Default); } public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer? equalityComparer) { if (count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < Count, "startIndex"); Requires.Range(count >= 0 && startIndex - count + 1 >= 0, "count"); if (equalityComparer == null) { equalityComparer = EqualityComparer.Default; } if (equalityComparer == EqualityComparer.Default) { return Array.LastIndexOf(_elements, item, startIndex, count); } for (int num = startIndex; num >= startIndex - count + 1; num--) { if (equalityComparer.Equals(item, _elements[num])) { return num; } } return -1; } public void Reverse() { int num = 0; int num2 = _count - 1; T[] elements = _elements; while (num < num2) { T val = elements[num]; elements[num] = elements[num2]; elements[num2] = val; num++; num2--; } } public void Sort() { if (Count > 1) { Array.Sort(_elements, 0, Count, Comparer.Default); } } public void Sort(Comparison comparison) { Requires.NotNull(comparison, "comparison"); if (Count > 1) { _elements.AsSpan(0, _count).Sort(comparison); } } public void Sort(IComparer? comparer) { if (Count > 1) { Array.Sort(_elements, 0, _count, comparer); } } public void Sort(int index, int count, IComparer? comparer) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0 && index + count <= Count, "count"); if (count > 1) { Array.Sort(_elements, index, count, comparer); } } public void CopyTo(Span destination) { Requires.Range(Count <= destination.Length, "destination"); new ReadOnlySpan(_elements, 0, Count).CopyTo(destination); } public IEnumerator GetEnumerator() { for (int i = 0; i < Count; i++) { yield return this[i]; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private void AddRange(TDerived[] items, int length) where TDerived : notnull, T { EnsureCapacity(Count + length); int count = Count; Count += length; T[] elements = _elements; for (int i = 0; i < length; i++) { elements[count + i] = (T)(object)items[i]; } } private void RemoveAtRange(ICollection indicesToRemove) { Requires.NotNull(indicesToRemove, "indicesToRemove"); if (indicesToRemove.Count == 0) { return; } int num = 0; int num2 = 0; int num3 = -1; foreach (int item in indicesToRemove) { int num4 = ((num3 == -1) ? item : (item - num3 - 1)); Array.Copy(_elements, num + num2, _elements, num, num4); num2++; num += num4; num3 = item; } Array.Copy(_elements, num + num2, _elements, num, _elements.Length - (num + num2)); _count -= indicesToRemove.Count; } } public struct Enumerator { private readonly T[] _array; private int _index; public T Current => _array[_index]; internal Enumerator(T[] array) { _array = array; _index = -1; } public bool MoveNext() { return ++_index < _array.Length; } } private sealed class EnumeratorObject : IEnumerator, IEnumerator, IDisposable { private static readonly IEnumerator s_EmptyEnumerator = new EnumeratorObject(ImmutableArray.Empty.array); private readonly T[] _array; private int _index; public T Current { get { if ((uint)_index < (uint)_array.Length) { return _array[_index]; } throw new InvalidOperationException(); } } object IEnumerator.Current => Current; private EnumeratorObject(T[] array) { _index = -1; _array = array; } public bool MoveNext() { int num = _index + 1; int num2 = _array.Length; if ((uint)num <= (uint)num2) { _index = num; return (uint)num < (uint)num2; } return false; } void IEnumerator.Reset() { _index = -1; } public void Dispose() { } internal static IEnumerator Create(T[] array) { if (array.Length != 0) { return new EnumeratorObject(array); } return s_EmptyEnumerator; } } public static readonly ImmutableArray Empty = new ImmutableArray(new T[0]); [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] internal readonly T[]? array; T IList.this[int index] { get { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray[index]; } set { throw new NotSupportedException(); } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsReadOnly => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] int ICollection.Count { get { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Length; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] int IReadOnlyCollection.Count { get { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Length; } } T IReadOnlyList.this[int index] { get { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray[index]; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool IList.IsFixedSize => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool IList.IsReadOnly => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] int ICollection.Count { get { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Length; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot { get { throw new NotSupportedException(); } } object? IList.this[int index] { get { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray[index]; } set { throw new NotSupportedException(); } } public T this[int index] { [System.Runtime.Versioning.NonVersionable] get { return array[index]; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsEmpty { [System.Runtime.Versioning.NonVersionable] get { return array.Length == 0; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public int Length { [System.Runtime.Versioning.NonVersionable] get { return array.Length; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsDefault => array == null; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsDefaultOrEmpty { get { ImmutableArray immutableArray = this; if (immutableArray.array != null) { return immutableArray.array.Length == 0; } return true; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] Array? IImmutableArray.Array => array; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay { get { ImmutableArray immutableArray = this; if (!immutableArray.IsDefault) { return $"Length = {immutableArray.Length}"; } return "Uninitialized"; } } public ReadOnlySpan AsSpan() { return new ReadOnlySpan(array); } public ReadOnlyMemory AsMemory() { return new ReadOnlyMemory(array); } public int IndexOf(T item) { ImmutableArray immutableArray = this; return immutableArray.IndexOf(item, 0, immutableArray.Length, EqualityComparer.Default); } public int IndexOf(T item, int startIndex, IEqualityComparer? equalityComparer) { ImmutableArray immutableArray = this; return immutableArray.IndexOf(item, startIndex, immutableArray.Length - startIndex, equalityComparer); } public int IndexOf(T item, int startIndex) { ImmutableArray immutableArray = this; return immutableArray.IndexOf(item, startIndex, immutableArray.Length - startIndex, EqualityComparer.Default); } public int IndexOf(T item, int startIndex, int count) { return IndexOf(item, startIndex, count, EqualityComparer.Default); } public int IndexOf(T item, int startIndex, int count, IEqualityComparer? equalityComparer) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); if (count == 0 && startIndex == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < immutableArray.Length, "startIndex"); Requires.Range(count >= 0 && startIndex + count <= immutableArray.Length, "count"); if (equalityComparer == null) { equalityComparer = EqualityComparer.Default; } if (equalityComparer == EqualityComparer.Default) { return Array.IndexOf(immutableArray.array, item, startIndex, count); } for (int i = startIndex; i < startIndex + count; i++) { if (equalityComparer.Equals(immutableArray.array[i], item)) { return i; } } return -1; } public int LastIndexOf(T item) { ImmutableArray immutableArray = this; if (immutableArray.IsEmpty) { return -1; } return immutableArray.LastIndexOf(item, immutableArray.Length - 1, immutableArray.Length, EqualityComparer.Default); } public int LastIndexOf(T item, int startIndex) { ImmutableArray immutableArray = this; if (immutableArray.IsEmpty && startIndex == 0) { return -1; } return immutableArray.LastIndexOf(item, startIndex, startIndex + 1, EqualityComparer.Default); } public int LastIndexOf(T item, int startIndex, int count) { return LastIndexOf(item, startIndex, count, EqualityComparer.Default); } public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer? equalityComparer) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); if (startIndex == 0 && count == 0) { return -1; } Requires.Range(startIndex >= 0 && startIndex < immutableArray.Length, "startIndex"); Requires.Range(count >= 0 && startIndex - count + 1 >= 0, "count"); if (equalityComparer == null) { equalityComparer = EqualityComparer.Default; } if (equalityComparer == EqualityComparer.Default) { return Array.LastIndexOf(immutableArray.array, item, startIndex, count); } for (int num = startIndex; num >= startIndex - count + 1; num--) { if (equalityComparer.Equals(item, immutableArray.array[num])) { return num; } } return -1; } public bool Contains(T item) { return IndexOf(item) >= 0; } public ImmutableArray Insert(int index, T item) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index <= immutableArray.Length, "index"); if (immutableArray.IsEmpty) { return ImmutableArray.Create(item); } T[] array = new T[immutableArray.Length + 1]; array[index] = item; if (index != 0) { Array.Copy(immutableArray.array, array, index); } if (index != immutableArray.Length) { Array.Copy(immutableArray.array, index, array, index + 1, immutableArray.Length - index); } return new ImmutableArray(array); } public ImmutableArray InsertRange(int index, IEnumerable items) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index <= result.Length, "index"); Requires.NotNull(items, "items"); if (result.IsEmpty) { return ImmutableArray.CreateRange(items); } int count = ImmutableExtensions.GetCount(ref items); if (count == 0) { return result; } T[] array = new T[result.Length + count]; if (index != 0) { Array.Copy(result.array, array, index); } if (index != result.Length) { Array.Copy(result.array, index, array, index + count, result.Length - index); } if (!items.TryCopyTo(array, index)) { int num = index; foreach (T item in items) { array[num++] = item; } } return new ImmutableArray(array); } public ImmutableArray InsertRange(int index, ImmutableArray items) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); items.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index <= result.Length, "index"); if (result.IsEmpty) { return items; } if (items.IsEmpty) { return result; } return result.InsertSpanRangeInternal(index, items.AsSpan()); } public ImmutableArray Add(T item) { ImmutableArray immutableArray = this; if (immutableArray.IsEmpty) { return ImmutableArray.Create(item); } return immutableArray.Insert(immutableArray.Length, item); } public ImmutableArray AddRange(IEnumerable items) { ImmutableArray immutableArray = this; return immutableArray.InsertRange(immutableArray.Length, items); } public ImmutableArray AddRange(T[] items, int length) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); Requires.NotNull(items, "items"); Requires.Range(length >= 0 && length <= items.Length, "length"); if (items.Length == 0 || length == 0) { return result; } if (result.IsEmpty) { return ImmutableArray.Create(items, 0, length); } T[] array = new T[result.Length + length]; Array.Copy(result.array, array, result.Length); Array.Copy(items, 0, array, result.Length, length); return new ImmutableArray(array); } public ImmutableArray AddRange(TDerived[] items) where TDerived : T { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); Requires.NotNull(items, "items"); if (items.Length == 0) { return result; } T[] array = new T[result.Length + items.Length]; Array.Copy(result.array, array, result.Length); Array.Copy(items, 0, array, result.Length, items.Length); return new ImmutableArray(array); } public ImmutableArray AddRange(ImmutableArray items, int length) { ImmutableArray result = this; Requires.Range(length >= 0, "length"); if (items.array != null) { return result.AddRange(items.array, length); } return result; } public ImmutableArray AddRange(ImmutableArray items) where TDerived : T { ImmutableArray result = this; if (items.array != null) { return result.AddRange(items.array); } return result; } public ImmutableArray AddRange(ImmutableArray items) { ImmutableArray immutableArray = this; return immutableArray.InsertRange(immutableArray.Length, items); } public ImmutableArray SetItem(int index, T item) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index < immutableArray.Length, "index"); T[] array = new T[immutableArray.Length]; Array.Copy(immutableArray.array, array, immutableArray.Length); array[index] = item; return new ImmutableArray(array); } public ImmutableArray Replace(T oldValue, T newValue) { return Replace(oldValue, newValue, EqualityComparer.Default); } public ImmutableArray Replace(T oldValue, T newValue, IEqualityComparer? equalityComparer) { ImmutableArray immutableArray = this; int num = immutableArray.IndexOf(oldValue, 0, immutableArray.Length, equalityComparer); if (num < 0) { throw new ArgumentException(System.SR.CannotFindOldValue, "oldValue"); } return immutableArray.SetItem(num, newValue); } public ImmutableArray Remove(T item) { return Remove(item, EqualityComparer.Default); } public ImmutableArray Remove(T item, IEqualityComparer? equalityComparer) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); int num = result.IndexOf(item, 0, result.Length, equalityComparer); if (num >= 0) { return result.RemoveAt(num); } return result; } public ImmutableArray RemoveAt(int index) { return RemoveRange(index, 1); } public ImmutableArray RemoveRange(int index, int length) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index <= result.Length, "index"); Requires.Range(length >= 0 && index + length <= result.Length, "length"); if (length == 0) { return result; } T[] array = new T[result.Length - length]; Array.Copy(result.array, array, index); Array.Copy(result.array, index + length, array, index, result.Length - index - length); return new ImmutableArray(array); } public ImmutableArray RemoveRange(IEnumerable items) { return RemoveRange(items, EqualityComparer.Default); } public ImmutableArray RemoveRange(IEnumerable items, IEqualityComparer? equalityComparer) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Requires.NotNull(items, "items"); SortedSet sortedSet = new SortedSet(); foreach (T item in items) { int num = -1; do { num = immutableArray.IndexOf(item, num + 1, equalityComparer); } while (num >= 0 && !sortedSet.Add(num) && num < immutableArray.Length - 1); } return immutableArray.RemoveAtRange(sortedSet); } public ImmutableArray RemoveRange(ImmutableArray items) { return RemoveRange(items, EqualityComparer.Default); } public ImmutableArray RemoveRange(ImmutableArray items, IEqualityComparer? equalityComparer) { Requires.NotNull(items.array, "items"); return RemoveRange(items.AsSpan(), equalityComparer); } public ImmutableArray RemoveAll(Predicate match) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); Requires.NotNull(match, "match"); if (result.IsEmpty) { return result; } List list = null; for (int i = 0; i < result.array.Length; i++) { if (match(result.array[i])) { if (list == null) { list = new List(); } list.Add(i); } } if (list == null) { return result; } return result.RemoveAtRange(list); } public ImmutableArray Clear() { return Empty; } public ImmutableArray Sort() { ImmutableArray immutableArray = this; return immutableArray.Sort(0, immutableArray.Length, Comparer.Default); } public ImmutableArray Sort(Comparison comparison) { Requires.NotNull(comparison, "comparison"); ImmutableArray immutableArray = this; return immutableArray.Sort(Comparer.Create(comparison)); } public ImmutableArray Sort(IComparer? comparer) { ImmutableArray immutableArray = this; return immutableArray.Sort(0, immutableArray.Length, comparer); } public ImmutableArray Sort(int index, int count, IComparer? comparer) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0, "index"); Requires.Range(count >= 0 && index + count <= result.Length, "count"); if (count > 1) { if (comparer == null) { comparer = Comparer.Default; } bool flag = false; for (int i = index + 1; i < index + count; i++) { if (comparer.Compare(result.array[i - 1], result.array[i]) > 0) { flag = true; break; } } if (flag) { T[] array = new T[result.Length]; Array.Copy(result.array, array, result.Length); Array.Sort(array, index, count, comparer); return new ImmutableArray(array); } } return result; } public IEnumerable OfType() { ImmutableArray immutableArray = this; if (immutableArray.array == null || immutableArray.array.Length == 0) { return Enumerable.Empty(); } return immutableArray.array.OfType(); } public ImmutableArray AddRange(ReadOnlySpan items) { ImmutableArray immutableArray = this; return immutableArray.InsertRange(immutableArray.Length, items); } public ImmutableArray AddRange(params T[] items) { ImmutableArray immutableArray = this; return immutableArray.InsertRange(immutableArray.Length, items); } public ReadOnlySpan AsSpan(int start, int length) { return new ReadOnlySpan(array, start, length); } public void CopyTo(Span destination) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Requires.Range(immutableArray.Length <= destination.Length, "destination"); immutableArray.AsSpan().CopyTo(destination); } public ImmutableArray InsertRange(int index, T[] items) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index <= result.Length, "index"); Requires.NotNull(items, "items"); if (items.Length == 0) { return result; } if (result.IsEmpty) { return new ImmutableArray(items); } return result.InsertSpanRangeInternal(index, items); } public ImmutableArray InsertRange(int index, ReadOnlySpan items) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); Requires.Range(index >= 0 && index <= result.Length, "index"); if (items.IsEmpty) { return result; } if (result.IsEmpty) { return items.ToImmutableArray(); } return result.InsertSpanRangeInternal(index, items); } public ImmutableArray RemoveRange(ReadOnlySpan items, IEqualityComparer? equalityComparer = null) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); if (items.IsEmpty || result.IsEmpty) { return result; } if (items.Length == 1) { return result.Remove(items[0], equalityComparer); } SortedSet sortedSet = new SortedSet(); ReadOnlySpan readOnlySpan = items; for (int i = 0; i < readOnlySpan.Length; i++) { T item = readOnlySpan[i]; int num = -1; do { num = result.IndexOf(item, num + 1, equalityComparer); } while (num >= 0 && !sortedSet.Add(num) && num < result.Length - 1); } return result.RemoveAtRange(sortedSet); } public ImmutableArray RemoveRange(T[] items, IEqualityComparer? equalityComparer = null) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Requires.NotNull(items, "items"); return immutableArray.RemoveRange(new ReadOnlySpan(items), equalityComparer); } public ImmutableArray Slice(int start, int length) { ImmutableArray items = this; items.ThrowNullRefIfNotInitialized(); return ImmutableArray.Create(items, start, length); } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } IImmutableList IImmutableList.Clear() { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Clear(); } IImmutableList IImmutableList.Add(T value) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Add(value); } IImmutableList IImmutableList.AddRange(IEnumerable items) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.AddRange(items); } IImmutableList IImmutableList.Insert(int index, T element) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Insert(index, element); } IImmutableList IImmutableList.InsertRange(int index, IEnumerable items) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.InsertRange(index, items); } IImmutableList IImmutableList.Remove(T value, IEqualityComparer equalityComparer) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Remove(value, equalityComparer); } IImmutableList IImmutableList.RemoveAll(Predicate match) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.RemoveAll(match); } IImmutableList IImmutableList.RemoveRange(IEnumerable items, IEqualityComparer equalityComparer) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.RemoveRange(items, equalityComparer); } IImmutableList IImmutableList.RemoveRange(int index, int count) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.RemoveRange(index, count); } IImmutableList IImmutableList.RemoveAt(int index) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.RemoveAt(index); } IImmutableList IImmutableList.SetItem(int index, T value) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.SetItem(index, value); } IImmutableList IImmutableList.Replace(T oldValue, T newValue, IEqualityComparer equalityComparer) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Replace(oldValue, newValue, equalityComparer); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.Contains((T)value); } int IList.IndexOf(object value) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return immutableArray.IndexOf((T)value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } void ICollection.CopyTo(Array array, int index) { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); Array.Copy(immutableArray.array, 0, array, index, immutableArray.Length); } bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) { ImmutableArray immutableArray = this; Array array = other as Array; if (array == null && other is IImmutableArray immutableArray2) { array = immutableArray2.Array; if (immutableArray.array == null && array == null) { return true; } if (immutableArray.array == null) { return false; } } IStructuralEquatable structuralEquatable = immutableArray.array; return structuralEquatable.Equals(array, comparer); } int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { ImmutableArray immutableArray = this; return ((IStructuralEquatable)immutableArray.array)?.GetHashCode(comparer) ?? immutableArray.GetHashCode(); } int IStructuralComparable.CompareTo(object other, IComparer comparer) { ImmutableArray immutableArray = this; Array array = other as Array; if (array == null && other is IImmutableArray immutableArray2) { array = immutableArray2.Array; if (immutableArray.array == null && array == null) { return 0; } if ((immutableArray.array == null) ^ (array == null)) { throw new ArgumentException(System.SR.ArrayInitializedStateNotEqual, "other"); } } if (array != null) { IStructuralComparable structuralComparable = immutableArray.array; if (structuralComparable == null) { throw new ArgumentException(System.SR.ArrayInitializedStateNotEqual, "other"); } return structuralComparable.CompareTo(array, comparer); } throw new ArgumentException(System.SR.ArrayLengthsNotEqual, "other"); } private ImmutableArray RemoveAtRange(ICollection indicesToRemove) { ImmutableArray result = this; result.ThrowNullRefIfNotInitialized(); Requires.NotNull(indicesToRemove, "indicesToRemove"); if (indicesToRemove.Count == 0) { return result; } T[] array = new T[result.Length - indicesToRemove.Count]; int num = 0; int num2 = 0; int num3 = -1; foreach (int item in indicesToRemove) { int num4 = ((num3 == -1) ? item : (item - num3 - 1)); Array.Copy(result.array, num + num2, array, num, num4); num2++; num += num4; num3 = item; } Array.Copy(result.array, num + num2, array, num, result.Length - (num + num2)); return new ImmutableArray(array); } private ImmutableArray InsertSpanRangeInternal(int index, ReadOnlySpan items) { T[] array = new T[Length + items.Length]; if (index != 0) { Array.Copy(this.array, array, index); } items.CopyTo(new Span(array, index, items.Length)); if (index != Length) { Array.Copy(this.array, index, array, index + items.Length, Length - index); } return new ImmutableArray(array); } public ReadOnlySpan AsSpan(Range range) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); var (start, length) = range.GetOffsetAndLength(immutableArray.Length); return new ReadOnlySpan(immutableArray.array, start, length); } internal ImmutableArray(T[]? items) { array = items; } [System.Runtime.Versioning.NonVersionable] public static bool operator ==(ImmutableArray left, ImmutableArray right) { return left.Equals(right); } [System.Runtime.Versioning.NonVersionable] public static bool operator !=(ImmutableArray left, ImmutableArray right) { return !left.Equals(right); } public static bool operator ==(ImmutableArray? left, ImmutableArray? right) { return left.GetValueOrDefault().Equals(right.GetValueOrDefault()); } public static bool operator !=(ImmutableArray? left, ImmutableArray? right) { return !left.GetValueOrDefault().Equals(right.GetValueOrDefault()); } public ref readonly T ItemRef(int index) { return ref array[index]; } public void CopyTo(T[] destination) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Array.Copy(immutableArray.array, destination, immutableArray.Length); } public void CopyTo(T[] destination, int destinationIndex) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Array.Copy(immutableArray.array, 0, destination, destinationIndex, immutableArray.Length); } public void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); Array.Copy(immutableArray.array, sourceIndex, destination, destinationIndex, length); } public ImmutableArray.Builder ToBuilder() { ImmutableArray items = this; if (items.Length == 0) { return new Builder(); } Builder builder = new Builder(items.Length); builder.AddRange(items); return builder; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() { ImmutableArray immutableArray = this; immutableArray.ThrowNullRefIfNotInitialized(); return new Enumerator(immutableArray.array); } public override int GetHashCode() { ImmutableArray immutableArray = this; if (immutableArray.array != null) { return immutableArray.array.GetHashCode(); } return 0; } public override bool Equals([NotNullWhen(true)] object? obj) { if (obj is IImmutableArray immutableArray) { return array == immutableArray.Array; } return false; } [System.Runtime.Versioning.NonVersionable] public bool Equals(ImmutableArray other) { return array == other.array; } public static ImmutableArray CastUp(ImmutableArray items) where TDerived : class?, T { T[] items2 = (T[])(object)items.array; return new ImmutableArray(items2); } public ImmutableArray CastArray() where TOther : class? { return new ImmutableArray((TOther[])(object)array); } public ImmutableArray As() where TOther : class? { return new ImmutableArray(array as TOther[]); } IEnumerator IEnumerable.GetEnumerator() { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return EnumeratorObject.Create(immutableArray.array); } IEnumerator IEnumerable.GetEnumerator() { ImmutableArray immutableArray = this; immutableArray.ThrowInvalidOperationIfNotInitialized(); return EnumeratorObject.Create(immutableArray.array); } internal void ThrowNullRefIfNotInitialized() { _ = array.Length; } private void ThrowInvalidOperationIfNotInitialized() { if (IsDefault) { throw new InvalidOperationException(System.SR.InvalidOperationOnDefaultArray); } } } internal sealed class ImmutableArrayBuilderDebuggerProxy { private readonly ImmutableArray.Builder _builder; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public T[] A => _builder.ToArray(); public ImmutableArrayBuilderDebuggerProxy(ImmutableArray.Builder builder) { Requires.NotNull(builder, "builder"); _builder = builder; } } internal static class ImmutableDictionary { public static ImmutableDictionary Create() where TKey : notnull { return ImmutableDictionary.Empty; } public static ImmutableDictionary Create(IEqualityComparer? keyComparer) where TKey : notnull { return ImmutableDictionary.Empty.WithComparers(keyComparer); } public static ImmutableDictionary Create(IEqualityComparer? keyComparer, IEqualityComparer? valueComparer) where TKey : notnull { return ImmutableDictionary.Empty.WithComparers(keyComparer, valueComparer); } public static ImmutableDictionary CreateRange(IEnumerable> items) where TKey : notnull { return ImmutableDictionary.Empty.AddRange(items); } public static ImmutableDictionary CreateRange(IEqualityComparer? keyComparer, IEnumerable> items) where TKey : notnull { return ImmutableDictionary.Empty.WithComparers(keyComparer).AddRange(items); } public static ImmutableDictionary CreateRange(IEqualityComparer? keyComparer, IEqualityComparer? valueComparer, IEnumerable> items) where TKey : notnull { return ImmutableDictionary.Empty.WithComparers(keyComparer, valueComparer).AddRange(items); } public static ImmutableDictionary.Builder CreateBuilder() where TKey : notnull { return Create().ToBuilder(); } public static ImmutableDictionary.Builder CreateBuilder(IEqualityComparer? keyComparer) where TKey : notnull { return Create(keyComparer).ToBuilder(); } public static ImmutableDictionary.Builder CreateBuilder(IEqualityComparer? keyComparer, IEqualityComparer? valueComparer) where TKey : notnull { return Create(keyComparer, valueComparer).ToBuilder(); } public static ImmutableDictionary ToImmutableDictionary(this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer? keyComparer, IEqualityComparer? valueComparer) where TKey : notnull { Func keySelector2 = keySelector; Func elementSelector2 = elementSelector; Requires.NotNull(source, "source"); Requires.NotNull(keySelector2, "keySelector"); Requires.NotNull(elementSelector2, "elementSelector"); return ImmutableDictionary.Empty.WithComparers(keyComparer, valueComparer).AddRange(source.Select((TSource element) => new KeyValuePair(keySelector2(element), elementSelector2(element)))); } public static ImmutableDictionary ToImmutableDictionary(this ImmutableDictionary.Builder builder) where TKey : notnull { Requires.NotNull(builder, "builder"); return builder.ToImmutable(); } public static ImmutableDictionary ToImmutableDictionary(this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer? keyComparer) where TKey : notnull { return source.ToImmutableDictionary(keySelector, elementSelector, keyComparer, null); } public static ImmutableDictionary ToImmutableDictionary(this IEnumerable source, Func keySelector) where TKey : notnull { return source.ToImmutableDictionary(keySelector, (TSource v) => v, null, null); } public static ImmutableDictionary ToImmutableDictionary(this IEnumerable source, Func keySelector, IEqualityComparer? keyComparer) where TKey : notnull { return source.ToImmutableDictionary(keySelector, (TSource v) => v, keyComparer, null); } public static ImmutableDictionary ToImmutableDictionary(this IEnumerable source, Func keySelector, Func elementSelector) where TKey : notnull { return source.ToImmutableDictionary(keySelector, elementSelector, null, null); } public static ImmutableDictionary ToImmutableDictionary(this IEnumerable> source, IEqualityComparer? keyComparer, IEqualityComparer? valueComparer) where TKey : notnull { Requires.NotNull(source, "source"); if (source is ImmutableDictionary immutableDictionary) { return immutableDictionary.WithComparers(keyComparer, valueComparer); } return ImmutableDictionary.Empty.WithComparers(keyComparer, valueComparer).AddRange(source); } public static ImmutableDictionary ToImmutableDictionary(this IEnumerable> source, IEqualityComparer? keyComparer) where TKey : notnull { return source.ToImmutableDictionary(keyComparer, null); } public static ImmutableDictionary ToImmutableDictionary(this IEnumerable> source) where TKey : notnull { return source.ToImmutableDictionary(null, null); } public static bool Contains(this IImmutableDictionary map, TKey key, TValue value) where TKey : notnull { Requires.NotNull(map, "map"); Requires.NotNullAllowStructs(key, "key"); return map.Contains(new KeyValuePair(key, value)); } public static TValue? GetValueOrDefault(this IImmutableDictionary dictionary, TKey key) where TKey : notnull { return dictionary.GetValueOrDefault(key, default(TValue)); } public static TValue GetValueOrDefault(this IImmutableDictionary dictionary, TKey key, TValue defaultValue) where TKey : notnull { Requires.NotNull(dictionary, "dictionary"); Requires.NotNullAllowStructs(key, "key"); if (dictionary.TryGetValue(key, out TValue value)) { return value; } return defaultValue; } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableDictionaryDebuggerProxy<, >))] internal sealed class ImmutableDictionary : IImmutableDictionary, IReadOnlyDictionary, IEnumerable>, IEnumerable, IReadOnlyCollection>, IImmutableDictionaryInternal, IHashKeyCollection, IDictionary, ICollection>, IDictionary, ICollection where TKey : notnull { [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableDictionaryBuilderDebuggerProxy<, >))] public sealed class Builder : IDictionary, ICollection>, IEnumerable>, IEnumerable, IReadOnlyDictionary, IReadOnlyCollection>, IDictionary, ICollection { private SortedInt32KeyNode.HashBucket> _root = SortedInt32KeyNode.EmptyNode; private ImmutableDictionary.Comparers _comparers; private int _count; private ImmutableDictionary _immutable; private int _version; private object _syncRoot; public IEqualityComparer KeyComparer { get { return _comparers.KeyComparer; } set { Requires.NotNull(value, "value"); if (value != KeyComparer) { Comparers comparers = Comparers.Get(value, ValueComparer); MutationInput origin = new MutationInput(SortedInt32KeyNode.EmptyNode, comparers); MutationResult mutationResult = ImmutableDictionary.AddRange((IEnumerable>)this, origin, KeyCollisionBehavior.ThrowIfValueDifferent); _immutable = null; _comparers = comparers; _count = mutationResult.CountAdjustment; Root = mutationResult.Root; } } } public IEqualityComparer ValueComparer { get { return _comparers.ValueComparer; } set { Requires.NotNull(value, "value"); if (value != ValueComparer) { _comparers = _comparers.WithValueComparer(value); _immutable = null; } } } public int Count => _count; bool ICollection>.IsReadOnly => false; public IEnumerable Keys { get { using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { yield return enumerator.Current.Key; } } } ICollection IDictionary.Keys => Keys.ToArray(Count); public IEnumerable Values { get { using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { yield return enumerator.Current.Value; } } } ICollection IDictionary.Values => Values.ToArray(Count); bool IDictionary.IsFixedSize => false; bool IDictionary.IsReadOnly => false; ICollection IDictionary.Keys => Keys.ToArray(Count); ICollection IDictionary.Values => Values.ToArray(Count); [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), (object)null); } return _syncRoot; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => false; object? IDictionary.this[object key] { get { return this[(TKey)key]; } set { this[(TKey)key] = (TValue)value; } } internal int Version => _version; private MutationInput Origin => new MutationInput(Root, _comparers); private SortedInt32KeyNode Root { get { return _root; } set { _version++; if (_root != value) { _root = value; _immutable = null; } } } public TValue this[TKey key] { get { if (TryGetValue(key, out var value)) { return value; } throw new KeyNotFoundException(System.SR.Format(System.SR.Arg_KeyNotFoundWithKey, key.ToString())); } set { MutationResult result = ImmutableDictionary.Add(key, value, KeyCollisionBehavior.SetValue, Origin); Apply(result); } } internal Builder(ImmutableDictionary map) { Requires.NotNull(map, "map"); _root = map._root; _count = map._count; _comparers = map._comparers; _immutable = map; } void IDictionary.Add(object key, object value) { Add((TKey)key, (TValue)value); } bool IDictionary.Contains(object key) { return ContainsKey((TKey)key); } IDictionaryEnumerator IDictionary.GetEnumerator() { return new DictionaryEnumerator(GetEnumerator()); } void IDictionary.Remove(object key) { Remove((TKey)key); } void ICollection.CopyTo(Array array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; array.SetValue(new DictionaryEntry(current.Key, current.Value), arrayIndex++); } } public void AddRange(IEnumerable> items) { MutationResult result = ImmutableDictionary.AddRange(items, Origin, KeyCollisionBehavior.ThrowIfValueDifferent); Apply(result); } public void RemoveRange(IEnumerable keys) { Requires.NotNull(keys, "keys"); foreach (TKey key in keys) { Remove(key); } } public Enumerator GetEnumerator() { return new Enumerator(_root, this); } public TValue? GetValueOrDefault(TKey key) { return GetValueOrDefault(key, default(TValue)); } public TValue GetValueOrDefault(TKey key, TValue defaultValue) { Requires.NotNullAllowStructs(key, "key"); if (TryGetValue(key, out var value)) { return value; } return defaultValue; } public ImmutableDictionary ToImmutable() { return _immutable ?? (_immutable = ImmutableDictionary.Wrap(_root, _comparers, _count)); } public void Add(TKey key, TValue value) { MutationResult result = ImmutableDictionary.Add(key, value, KeyCollisionBehavior.ThrowIfValueDifferent, Origin); Apply(result); } public bool ContainsKey(TKey key) { return ImmutableDictionary.ContainsKey(key, Origin); } public bool ContainsValue(TValue value) { using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; if (ValueComparer.Equals(value, current.Value)) { return true; } } } return false; } public bool Remove(TKey key) { MutationResult result = ImmutableDictionary.Remove(key, Origin); return Apply(result); } public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) { return ImmutableDictionary.TryGetValue(key, Origin, out value); } public bool TryGetKey(TKey equalKey, out TKey actualKey) { return ImmutableDictionary.TryGetKey(equalKey, Origin, out actualKey); } public void Add(KeyValuePair item) { Add(item.Key, item.Value); } public void Clear() { Root = SortedInt32KeyNode.EmptyNode; _count = 0; } public bool Contains(KeyValuePair item) { return ImmutableDictionary.Contains(item, Origin); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { Requires.NotNull(array, "array"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; array[arrayIndex++] = current; } } public bool Remove(KeyValuePair item) { if (Contains(item)) { return Remove(item.Key); } return false; } IEnumerator> IEnumerable>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private bool Apply(ImmutableDictionary.MutationResult result) { Root = result.Root; _count += result.CountAdjustment; return result.CountAdjustment != 0; } } internal sealed class Comparers : IEqualityComparer, IEqualityComparer> { internal static readonly Comparers Default = new Comparers(EqualityComparer.Default, EqualityComparer.Default); private readonly IEqualityComparer _keyComparer; private readonly IEqualityComparer _valueComparer; internal IEqualityComparer KeyComparer => _keyComparer; internal IEqualityComparer> KeyOnlyComparer => this; internal IEqualityComparer ValueComparer => _valueComparer; internal IEqualityComparer HashBucketEqualityComparer => this; internal Comparers(IEqualityComparer keyComparer, IEqualityComparer valueComparer) { Requires.NotNull(keyComparer, "keyComparer"); Requires.NotNull(valueComparer, "valueComparer"); _keyComparer = keyComparer; _valueComparer = valueComparer; } public bool Equals(HashBucket x, HashBucket y) { if (x.AdditionalElements == y.AdditionalElements && KeyComparer.Equals(x.FirstValue.Key, y.FirstValue.Key)) { return ValueComparer.Equals(x.FirstValue.Value, y.FirstValue.Value); } return false; } public int GetHashCode(HashBucket obj) { return KeyComparer.GetHashCode(obj.FirstValue.Key); } bool IEqualityComparer>.Equals(KeyValuePair x, KeyValuePair y) { return _keyComparer.Equals(x.Key, y.Key); } int IEqualityComparer>.GetHashCode(KeyValuePair obj) { return _keyComparer.GetHashCode(obj.Key); } internal static Comparers Get(IEqualityComparer keyComparer, IEqualityComparer valueComparer) { Requires.NotNull(keyComparer, "keyComparer"); Requires.NotNull(valueComparer, "valueComparer"); if (keyComparer != Default.KeyComparer || valueComparer != Default.ValueComparer) { return new Comparers(keyComparer, valueComparer); } return Default; } internal Comparers WithValueComparer(IEqualityComparer valueComparer) { Requires.NotNull(valueComparer, "valueComparer"); if (_valueComparer != valueComparer) { return Get(KeyComparer, valueComparer); } return this; } } public struct Enumerator : IEnumerator>, IEnumerator, IDisposable { private readonly Builder _builder; private SortedInt32KeyNode.Enumerator _mapEnumerator; private HashBucket.Enumerator _bucketEnumerator; private int _enumeratingBuilderVersion; public KeyValuePair Current { get { _mapEnumerator.ThrowIfDisposed(); return _bucketEnumerator.Current; } } object IEnumerator.Current => Current; internal Enumerator(SortedInt32KeyNode root, Builder? builder = null) { _builder = builder; _mapEnumerator = new SortedInt32KeyNode.Enumerator(root); _bucketEnumerator = default(HashBucket.Enumerator); _enumeratingBuilderVersion = builder?.Version ?? (-1); } public bool MoveNext() { ThrowIfChanged(); if (_bucketEnumerator.MoveNext()) { return true; } if (_mapEnumerator.MoveNext()) { _bucketEnumerator = new HashBucket.Enumerator(_mapEnumerator.Current.Value); return _bucketEnumerator.MoveNext(); } return false; } public void Reset() { _enumeratingBuilderVersion = ((_builder != null) ? _builder.Version : (-1)); _mapEnumerator.Reset(); _bucketEnumerator.Dispose(); _bucketEnumerator = default(HashBucket.Enumerator); } public void Dispose() { _mapEnumerator.Dispose(); _bucketEnumerator.Dispose(); } private void ThrowIfChanged() { if (_builder != null && _builder.Version != _enumeratingBuilderVersion) { throw new InvalidOperationException(System.SR.CollectionModifiedDuringEnumeration); } } } internal readonly struct HashBucket : IEnumerable>, IEnumerable { internal struct Enumerator : IEnumerator>, IEnumerator, IDisposable { private enum Position { BeforeFirst, First, Additional, End } private readonly HashBucket _bucket; private Position _currentPosition; private ImmutableList>.Enumerator _additionalEnumerator; object IEnumerator.Current => Current; public KeyValuePair Current => _currentPosition switch { Position.First => _bucket._firstValue, Position.Additional => _additionalEnumerator.Current, _ => throw new InvalidOperationException(), }; internal Enumerator(HashBucket bucket) { _bucket = bucket; _currentPosition = Position.BeforeFirst; _additionalEnumerator = default(ImmutableList>.Enumerator); } public bool MoveNext() { if (_bucket.IsEmpty) { _currentPosition = Position.End; return false; } switch (_currentPosition) { case Position.BeforeFirst: _currentPosition = Position.First; return true; case Position.First: if (_bucket._additionalElements.IsEmpty) { _currentPosition = Position.End; return false; } _currentPosition = Position.Additional; _additionalEnumerator = new ImmutableList>.Enumerator(_bucket._additionalElements); return _additionalEnumerator.MoveNext(); case Position.Additional: return _additionalEnumerator.MoveNext(); case Position.End: return false; default: throw new InvalidOperationException(); } } public void Reset() { _additionalEnumerator.Dispose(); _currentPosition = Position.BeforeFirst; } public void Dispose() { _additionalEnumerator.Dispose(); } } private readonly KeyValuePair _firstValue; private readonly ImmutableList>.Node _additionalElements; internal bool IsEmpty => _additionalElements == null; internal KeyValuePair FirstValue { get { if (IsEmpty) { throw new InvalidOperationException(); } return _firstValue; } } internal ImmutableList>.Node AdditionalElements => _additionalElements; private HashBucket(KeyValuePair firstElement, ImmutableList>.Node additionalElements = null) { _firstValue = firstElement; _additionalElements = additionalElements ?? ImmutableList>.Node.EmptyNode; } public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator> IEnumerable>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public override bool Equals(object? obj) { throw new NotSupportedException(); } public override int GetHashCode() { throw new NotSupportedException(); } internal HashBucket Add(TKey key, TValue value, IEqualityComparer> keyOnlyComparer, IEqualityComparer valueComparer, KeyCollisionBehavior behavior, out OperationResult result) { KeyValuePair keyValuePair = new KeyValuePair(key, value); if (IsEmpty) { result = OperationResult.SizeChanged; return new HashBucket(keyValuePair); } if (keyOnlyComparer.Equals(keyValuePair, _firstValue)) { switch (behavior) { case KeyCollisionBehavior.SetValue: result = OperationResult.AppliedWithoutSizeChange; return new HashBucket(keyValuePair, _additionalElements); case KeyCollisionBehavior.Skip: result = OperationResult.NoChangeRequired; return this; case KeyCollisionBehavior.ThrowIfValueDifferent: if (!valueComparer.Equals(_firstValue.Value, value)) { throw new ArgumentException(System.SR.Format(System.SR.DuplicateKey, key)); } result = OperationResult.NoChangeRequired; return this; case KeyCollisionBehavior.ThrowAlways: throw new ArgumentException(System.SR.Format(System.SR.DuplicateKey, key)); default: throw new InvalidOperationException(); } } int num = _additionalElements.IndexOf(keyValuePair, keyOnlyComparer); if (num < 0) { result = OperationResult.SizeChanged; return new HashBucket(_firstValue, _additionalElements.Add(keyValuePair)); } switch (behavior) { case KeyCollisionBehavior.SetValue: result = OperationResult.AppliedWithoutSizeChange; return new HashBucket(_firstValue, _additionalElements.ReplaceAt(num, keyValuePair)); case KeyCollisionBehavior.Skip: result = OperationResult.NoChangeRequired; return this; case KeyCollisionBehavior.ThrowIfValueDifferent: if (!valueComparer.Equals(_additionalElements.ItemRef(num).Value, value)) { throw new ArgumentException(System.SR.Format(System.SR.DuplicateKey, key)); } result = OperationResult.NoChangeRequired; return this; case KeyCollisionBehavior.ThrowAlways: throw new ArgumentException(System.SR.Format(System.SR.DuplicateKey, key)); default: throw new InvalidOperationException(); } } internal HashBucket Remove(TKey key, IEqualityComparer> keyOnlyComparer, out OperationResult result) { if (IsEmpty) { result = OperationResult.NoChangeRequired; return this; } KeyValuePair keyValuePair = new KeyValuePair(key, default(TValue)); if (keyOnlyComparer.Equals(_firstValue, keyValuePair)) { if (_additionalElements.IsEmpty) { result = OperationResult.SizeChanged; return default(HashBucket); } int count = _additionalElements.Left.Count; result = OperationResult.SizeChanged; return new HashBucket(_additionalElements.Key, _additionalElements.RemoveAt(count)); } int num = _additionalElements.IndexOf(keyValuePair, keyOnlyComparer); if (num < 0) { result = OperationResult.NoChangeRequired; return this; } result = OperationResult.SizeChanged; return new HashBucket(_firstValue, _additionalElements.RemoveAt(num)); } internal bool TryGetValue(TKey key, Comparers comparers, [MaybeNullWhen(false)] out TValue value) { if (IsEmpty) { value = default(TValue); return false; } if (comparers.KeyComparer.Equals(_firstValue.Key, key)) { value = _firstValue.Value; return true; } KeyValuePair item = new KeyValuePair(key, default(TValue)); int num = _additionalElements.IndexOf(item, comparers.KeyOnlyComparer); if (num < 0) { value = default(TValue); return false; } value = _additionalElements.ItemRef(num).Value; return true; } internal bool TryGetKey(TKey equalKey, Comparers comparers, out TKey actualKey) { if (IsEmpty) { actualKey = equalKey; return false; } if (comparers.KeyComparer.Equals(_firstValue.Key, equalKey)) { actualKey = _firstValue.Key; return true; } KeyValuePair item = new KeyValuePair(equalKey, default(TValue)); int num = _additionalElements.IndexOf(item, comparers.KeyOnlyComparer); if (num < 0) { actualKey = equalKey; return false; } actualKey = _additionalElements.ItemRef(num).Key; return true; } internal void Freeze() { _additionalElements?.Freeze(); } } private readonly struct MutationInput { private readonly SortedInt32KeyNode.HashBucket> _root; private readonly ImmutableDictionary.Comparers _comparers; internal SortedInt32KeyNode.HashBucket> Root => _root; internal ImmutableDictionary.Comparers Comparers => _comparers; internal IEqualityComparer KeyComparer => _comparers.KeyComparer; internal IEqualityComparer> KeyOnlyComparer => _comparers.KeyOnlyComparer; internal IEqualityComparer ValueComparer => _comparers.ValueComparer; internal IEqualityComparer.HashBucket> HashBucketComparer => _comparers.HashBucketEqualityComparer; internal MutationInput(SortedInt32KeyNode.HashBucket> root, ImmutableDictionary.Comparers comparers) { _root = root; _comparers = comparers; } internal MutationInput(ImmutableDictionary map) { _root = map._root; _comparers = map._comparers; } } private readonly struct MutationResult { private readonly SortedInt32KeyNode.HashBucket> _root; private readonly int _countAdjustment; internal SortedInt32KeyNode.HashBucket> Root => _root; internal int CountAdjustment => _countAdjustment; internal MutationResult(ImmutableDictionary.MutationInput unchangedInput) { _root = unchangedInput.Root; _countAdjustment = 0; } internal MutationResult(SortedInt32KeyNode.HashBucket> root, int countAdjustment) { Requires.NotNull(root, "root"); _root = root; _countAdjustment = countAdjustment; } internal ImmutableDictionary Finalize(ImmutableDictionary priorMap) { Requires.NotNull(priorMap, "priorMap"); return priorMap.Wrap(Root, priorMap._count + CountAdjustment); } } internal enum KeyCollisionBehavior { SetValue, Skip, ThrowIfValueDifferent, ThrowAlways } internal enum OperationResult { AppliedWithoutSizeChange, SizeChanged, NoChangeRequired } public static readonly ImmutableDictionary Empty = new ImmutableDictionary(); private static readonly Action.HashBucket>> s_FreezeBucketAction = delegate(KeyValuePair kv) { kv.Value.Freeze(); }; private readonly int _count; private readonly SortedInt32KeyNode.HashBucket> _root; private readonly ImmutableDictionary.Comparers _comparers; public int Count => _count; public bool IsEmpty => Count == 0; public IEqualityComparer KeyComparer => _comparers.KeyComparer; public IEqualityComparer ValueComparer => _comparers.ValueComparer; public IEnumerable Keys { get { foreach (KeyValuePair item in _root) { foreach (KeyValuePair item2 in item.Value) { yield return item2.Key; } } } } public IEnumerable Values { get { foreach (KeyValuePair item in _root) { foreach (KeyValuePair item2 in item.Value) { yield return item2.Value; } } } } ICollection IDictionary.Keys => new KeysCollectionAccessor(this); ICollection IDictionary.Values => new ValuesCollectionAccessor(this); private MutationInput Origin => new MutationInput(this); public TValue this[TKey key] { get { Requires.NotNullAllowStructs(key, "key"); if (TryGetValue(key, out var value)) { return value; } throw new KeyNotFoundException(System.SR.Format(System.SR.Arg_KeyNotFoundWithKey, key.ToString())); } } TValue IDictionary.this[TKey key] { get { return this[key]; } set { throw new NotSupportedException(); } } bool ICollection>.IsReadOnly => true; bool IDictionary.IsFixedSize => true; bool IDictionary.IsReadOnly => true; ICollection IDictionary.Keys => new KeysCollectionAccessor(this); ICollection IDictionary.Values => new ValuesCollectionAccessor(this); internal SortedInt32KeyNode Root => _root; object? IDictionary.this[object key] { get { return this[(TKey)key]; } set { throw new NotSupportedException(); } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot => this; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; private ImmutableDictionary(SortedInt32KeyNode.HashBucket> root, ImmutableDictionary.Comparers comparers, int count) : this(Requires.NotNullPassthrough(comparers, "comparers")) { Requires.NotNull(root, "root"); root.Freeze(s_FreezeBucketAction); _root = root; _count = count; } private ImmutableDictionary(ImmutableDictionary.Comparers comparers = null) { _comparers = comparers ?? Comparers.Get(EqualityComparer.Default, EqualityComparer.Default); _root = SortedInt32KeyNode.EmptyNode; } public ImmutableDictionary Clear() { if (!IsEmpty) { return EmptyWithComparers(_comparers); } return this; } IImmutableDictionary IImmutableDictionary.Clear() { return Clear(); } public Builder ToBuilder() { return new Builder(this); } public ImmutableDictionary Add(TKey key, TValue value) { Requires.NotNullAllowStructs(key, "key"); return Add(key, value, KeyCollisionBehavior.ThrowIfValueDifferent, Origin).Finalize(this); } public ImmutableDictionary AddRange(IEnumerable> pairs) { Requires.NotNull(pairs, "pairs"); return AddRange(pairs, avoidToHashMap: false); } public ImmutableDictionary SetItem(TKey key, TValue value) { Requires.NotNullAllowStructs(key, "key"); return Add(key, value, KeyCollisionBehavior.SetValue, Origin).Finalize(this); } public ImmutableDictionary SetItems(IEnumerable> items) { Requires.NotNull(items, "items"); return AddRange(items, Origin, KeyCollisionBehavior.SetValue).Finalize(this); } public ImmutableDictionary Remove(TKey key) { Requires.NotNullAllowStructs(key, "key"); return Remove(key, Origin).Finalize(this); } public ImmutableDictionary RemoveRange(IEnumerable keys) { Requires.NotNull(keys, "keys"); int num = _count; SortedInt32KeyNode sortedInt32KeyNode = _root; foreach (TKey key in keys) { int hashCode = KeyComparer.GetHashCode(key); if (sortedInt32KeyNode.TryGetValue(hashCode, out var value)) { OperationResult result; HashBucket newBucket = value.Remove(key, _comparers.KeyOnlyComparer, out result); sortedInt32KeyNode = UpdateRoot(sortedInt32KeyNode, hashCode, newBucket, _comparers.HashBucketEqualityComparer); if (result == OperationResult.SizeChanged) { num--; } } } return Wrap(sortedInt32KeyNode, num); } public bool ContainsKey(TKey key) { Requires.NotNullAllowStructs(key, "key"); return ContainsKey(key, Origin); } public bool Contains(KeyValuePair pair) { return Contains(pair, Origin); } public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) { Requires.NotNullAllowStructs(key, "key"); return TryGetValue(key, Origin, out value); } public bool TryGetKey(TKey equalKey, out TKey actualKey) { Requires.NotNullAllowStructs(equalKey, "equalKey"); return TryGetKey(equalKey, Origin, out actualKey); } public ImmutableDictionary WithComparers(IEqualityComparer? keyComparer, IEqualityComparer? valueComparer) { if (keyComparer == null) { keyComparer = EqualityComparer.Default; } if (valueComparer == null) { valueComparer = EqualityComparer.Default; } if (KeyComparer == keyComparer) { if (ValueComparer == valueComparer) { return this; } Comparers comparers = _comparers.WithValueComparer(valueComparer); return new ImmutableDictionary(_root, comparers, _count); } Comparers comparers2 = Comparers.Get(keyComparer, valueComparer); ImmutableDictionary immutableDictionary = new ImmutableDictionary(comparers2); return immutableDictionary.AddRange(this, avoidToHashMap: true); } public ImmutableDictionary WithComparers(IEqualityComparer? keyComparer) { return WithComparers(keyComparer, _comparers.ValueComparer); } public bool ContainsValue(TValue value) { using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; if (ValueComparer.Equals(value, current.Value)) { return true; } } } return false; } public Enumerator GetEnumerator() { return new Enumerator(_root); } IImmutableDictionary IImmutableDictionary.Add(TKey key, TValue value) { return Add(key, value); } IImmutableDictionary IImmutableDictionary.SetItem(TKey key, TValue value) { return SetItem(key, value); } IImmutableDictionary IImmutableDictionary.SetItems(IEnumerable> items) { return SetItems(items); } IImmutableDictionary IImmutableDictionary.AddRange(IEnumerable> pairs) { return AddRange(pairs); } IImmutableDictionary IImmutableDictionary.RemoveRange(IEnumerable keys) { return RemoveRange(keys); } IImmutableDictionary IImmutableDictionary.Remove(TKey key) { return Remove(key); } void IDictionary.Add(TKey key, TValue value) { throw new NotSupportedException(); } bool IDictionary.Remove(TKey key) { throw new NotSupportedException(); } void ICollection>.Add(KeyValuePair item) { throw new NotSupportedException(); } void ICollection>.Clear() { throw new NotSupportedException(); } bool ICollection>.Remove(KeyValuePair item) { throw new NotSupportedException(); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; array[arrayIndex++] = current; } } void IDictionary.Add(object key, object value) { throw new NotSupportedException(); } bool IDictionary.Contains(object key) { return ContainsKey((TKey)key); } IDictionaryEnumerator IDictionary.GetEnumerator() { return new DictionaryEnumerator(GetEnumerator()); } void IDictionary.Remove(object key) { throw new NotSupportedException(); } void IDictionary.Clear() { throw new NotSupportedException(); } void ICollection.CopyTo(Array array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; array.SetValue(new DictionaryEntry(current.Key, current.Value), arrayIndex++); } } IEnumerator> IEnumerable>.GetEnumerator() { if (!IsEmpty) { return GetEnumerator(); } return Enumerable.Empty>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private static ImmutableDictionary EmptyWithComparers(ImmutableDictionary.Comparers comparers) { Requires.NotNull(comparers, "comparers"); if (Empty._comparers != comparers) { return new ImmutableDictionary(comparers); } return Empty; } private static bool TryCastToImmutableMap(IEnumerable> sequence, [NotNullWhen(true)] out ImmutableDictionary other) { other = sequence as ImmutableDictionary; if (other != null) { return true; } if (sequence is Builder builder) { other = builder.ToImmutable(); return true; } return false; } private static bool ContainsKey(TKey key, ImmutableDictionary.MutationInput origin) { int hashCode = origin.KeyComparer.GetHashCode(key); TValue value2; if (origin.Root.TryGetValue(hashCode, out HashBucket value)) { return value.TryGetValue(key, origin.Comparers, out value2); } return false; } private static bool Contains(KeyValuePair keyValuePair, ImmutableDictionary.MutationInput origin) { int hashCode = origin.KeyComparer.GetHashCode(keyValuePair.Key); if (origin.Root.TryGetValue(hashCode, out HashBucket value)) { if (value.TryGetValue(keyValuePair.Key, origin.Comparers, out var value2)) { return origin.ValueComparer.Equals(value2, keyValuePair.Value); } return false; } return false; } private static bool TryGetValue(TKey key, ImmutableDictionary.MutationInput origin, [MaybeNullWhen(false)] out TValue value) { int hashCode = origin.KeyComparer.GetHashCode(key); if (origin.Root.TryGetValue(hashCode, out HashBucket value2)) { return value2.TryGetValue(key, origin.Comparers, out value); } value = default(TValue); return false; } private static bool TryGetKey(TKey equalKey, ImmutableDictionary.MutationInput origin, out TKey actualKey) { int hashCode = origin.KeyComparer.GetHashCode(equalKey); if (origin.Root.TryGetValue(hashCode, out HashBucket value)) { return value.TryGetKey(equalKey, origin.Comparers, out actualKey); } actualKey = equalKey; return false; } private static ImmutableDictionary.MutationResult Add(TKey key, TValue value, ImmutableDictionary.KeyCollisionBehavior behavior, ImmutableDictionary.MutationInput origin) { Requires.NotNullAllowStructs(key, "key"); int hashCode = origin.KeyComparer.GetHashCode(key); OperationResult result; HashBucket newBucket = origin.Root.GetValueOrDefault(hashCode).Add(key, value, origin.KeyOnlyComparer, origin.ValueComparer, behavior, out result); if (result == OperationResult.NoChangeRequired) { return new MutationResult(origin); } SortedInt32KeyNode root = UpdateRoot(origin.Root, hashCode, newBucket, origin.HashBucketComparer); return new MutationResult(root, (result == OperationResult.SizeChanged) ? 1 : 0); } private static ImmutableDictionary.MutationResult AddRange(IEnumerable> items, ImmutableDictionary.MutationInput origin, ImmutableDictionary.KeyCollisionBehavior collisionBehavior = ImmutableDictionary.KeyCollisionBehavior.ThrowIfValueDifferent) { Requires.NotNull(items, "items"); int num = 0; SortedInt32KeyNode sortedInt32KeyNode = origin.Root; foreach (KeyValuePair item in items) { Requires.NotNullAllowStructs(item.Key, "Key"); int hashCode = origin.KeyComparer.GetHashCode(item.Key); OperationResult result; HashBucket newBucket = sortedInt32KeyNode.GetValueOrDefault(hashCode).Add(item.Key, item.Value, origin.KeyOnlyComparer, origin.ValueComparer, collisionBehavior, out result); sortedInt32KeyNode = UpdateRoot(sortedInt32KeyNode, hashCode, newBucket, origin.HashBucketComparer); if (result == OperationResult.SizeChanged) { num++; } } return new MutationResult(sortedInt32KeyNode, num); } private static ImmutableDictionary.MutationResult Remove(TKey key, ImmutableDictionary.MutationInput origin) { int hashCode = origin.KeyComparer.GetHashCode(key); if (origin.Root.TryGetValue(hashCode, out HashBucket value)) { OperationResult result; SortedInt32KeyNode root = UpdateRoot(origin.Root, hashCode, value.Remove(key, origin.KeyOnlyComparer, out result), origin.HashBucketComparer); return new MutationResult(root, (result == OperationResult.SizeChanged) ? (-1) : 0); } return new MutationResult(origin); } private static SortedInt32KeyNode.HashBucket> UpdateRoot(SortedInt32KeyNode.HashBucket> root, int hashCode, ImmutableDictionary.HashBucket newBucket, IEqualityComparer.HashBucket> hashBucketComparer) { bool mutated; if (newBucket.IsEmpty) { return root.Remove(hashCode, out mutated); } bool mutated2; return root.SetItem(hashCode, newBucket, hashBucketComparer, out mutated, out mutated2); } private static ImmutableDictionary Wrap(SortedInt32KeyNode.HashBucket> root, ImmutableDictionary.Comparers comparers, int count) { Requires.NotNull(root, "root"); Requires.NotNull(comparers, "comparers"); Requires.Range(count >= 0, "count"); return new ImmutableDictionary(root, comparers, count); } private ImmutableDictionary Wrap(SortedInt32KeyNode.HashBucket> root, int adjustedCountIfDifferentRoot) { if (root == null) { return Clear(); } if (_root != root) { if (!root.IsEmpty) { return new ImmutableDictionary(root, _comparers, adjustedCountIfDifferentRoot); } return Clear(); } return this; } private ImmutableDictionary AddRange(IEnumerable> pairs, bool avoidToHashMap) { Requires.NotNull(pairs, "pairs"); if (IsEmpty && !avoidToHashMap && TryCastToImmutableMap(pairs, out ImmutableDictionary other)) { return other.WithComparers(KeyComparer, ValueComparer); } return AddRange(pairs, Origin).Finalize(this); } } internal sealed class ImmutableDictionaryBuilderDebuggerProxy where TKey : notnull { private readonly ImmutableDictionary.Builder _map; private KeyValuePair[] _contents; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public KeyValuePair[] Contents => _contents ?? (_contents = _map.ToArray(_map.Count)); public ImmutableDictionaryBuilderDebuggerProxy(ImmutableDictionary.Builder map) { Requires.NotNull(map, "map"); _map = map; } } internal sealed class ImmutableDictionaryDebuggerProxy : ImmutableEnumerableDebuggerProxy> where TKey : notnull { public ImmutableDictionaryDebuggerProxy(IImmutableDictionary dictionary) : base((IEnumerable>)dictionary) { } } internal class ImmutableEnumerableDebuggerProxy { private readonly IEnumerable _enumerable; private T[] _cachedContents; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public T[] Contents => _cachedContents ?? (_cachedContents = _enumerable.ToArray()); public ImmutableEnumerableDebuggerProxy(IEnumerable enumerable) { Requires.NotNull(enumerable, "enumerable"); _enumerable = enumerable; } } internal static class ImmutableExtensions { private sealed class ListOfTWrapper : IOrderedCollection, IEnumerable, IEnumerable where T : notnull { private readonly IList _collection; public int Count => _collection.Count; public T this[int index] => _collection[index]; internal ListOfTWrapper(IList collection) { Requires.NotNull(collection, "collection"); _collection = collection; } public IEnumerator GetEnumerator() { return _collection.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private sealed class FallbackWrapper : IOrderedCollection, IEnumerable, IEnumerable where T : notnull { private readonly IEnumerable _sequence; private IList _collection; public int Count { get { if (_collection == null) { if (_sequence.TryGetCount(out var count)) { return count; } _collection = _sequence.ToArray(); } return _collection.Count; } } public T this[int index] { get { if (_collection == null) { _collection = _sequence.ToArray(); } return _collection[index]; } } internal FallbackWrapper(IEnumerable sequence) { Requires.NotNull(sequence, "sequence"); _sequence = sequence; } public IEnumerator GetEnumerator() { return _sequence.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal static bool IsValueType() { return typeof(T).IsValueType; } internal static IOrderedCollection AsOrderedCollection(this IEnumerable sequence) { Requires.NotNull(sequence, "sequence"); if (sequence is IOrderedCollection result) { return result; } if (sequence is IList collection) { return new ListOfTWrapper(collection); } return new FallbackWrapper(sequence); } internal static void ClearFastWhenEmpty(this Stack stack) { if (stack.Count > 0) { stack.Clear(); } } internal static DisposableEnumeratorAdapter GetEnumerableDisposable(this IEnumerable enumerable) where TEnumerator : struct, IStrongEnumerator, IEnumerator { Requires.NotNull(enumerable, "enumerable"); if (enumerable is IStrongEnumerable strongEnumerable) { return new DisposableEnumeratorAdapter(strongEnumerable.GetEnumerator()); } return new DisposableEnumeratorAdapter(enumerable.GetEnumerator()); } internal static bool TryGetCount(this IEnumerable sequence, out int count) { return ((IEnumerable)sequence).TryGetCount(out count); } internal static bool TryGetCount(this IEnumerable sequence, out int count) { if (sequence is ICollection collection) { count = collection.Count; return true; } if (sequence is ICollection collection2) { count = collection2.Count; return true; } if (sequence is IReadOnlyCollection readOnlyCollection) { count = readOnlyCollection.Count; return true; } count = 0; return false; } internal static int GetCount(ref IEnumerable sequence) { if (!sequence.TryGetCount(out var count)) { List list = sequence.ToList(); count = list.Count; sequence = list; } return count; } internal static bool TryCopyTo(this IEnumerable sequence, T[] array, int arrayIndex) { if (sequence is IList) { if (sequence is List list) { list.CopyTo(array, arrayIndex); return true; } if (sequence.GetType() == typeof(T[])) { T[] array2 = (T[])sequence; Array.Copy(array2, 0, array, arrayIndex, array2.Length); return true; } if (sequence is ImmutableArray immutableArray) { Array.Copy(immutableArray.array, 0, array, arrayIndex, immutableArray.Length); return true; } } return false; } internal static T[] ToArray(this IEnumerable sequence, int count) { Requires.NotNull(sequence, "sequence"); Requires.Range(count >= 0, "count"); if (count == 0) { return ImmutableArray.Empty.array; } T[] array = new T[count]; if (!sequence.TryCopyTo(array, 0)) { int num = 0; foreach (T item in sequence) { Requires.Argument(num < count); array[num++] = item; } Requires.Argument(num == count); } return array; } } internal static class ImmutableHashSet { public static ImmutableHashSet Create() { return ImmutableHashSet.Empty; } public static ImmutableHashSet Create(IEqualityComparer? equalityComparer) { return ImmutableHashSet.Empty.WithComparer(equalityComparer); } public static ImmutableHashSet Create(T item) { return ImmutableHashSet.Empty.Add(item); } public static ImmutableHashSet Create(IEqualityComparer? equalityComparer, T item) { return ImmutableHashSet.Empty.WithComparer(equalityComparer).Add(item); } public static ImmutableHashSet CreateRange(IEnumerable items) { return ImmutableHashSet.Empty.Union(items); } public static ImmutableHashSet CreateRange(IEqualityComparer? equalityComparer, IEnumerable items) { return ImmutableHashSet.Empty.WithComparer(equalityComparer).Union(items); } public static ImmutableHashSet Create(params T[] items) { return ImmutableHashSet.Empty.Union(items); } public static ImmutableHashSet Create(IEqualityComparer? equalityComparer, params T[] items) { return ImmutableHashSet.Empty.WithComparer(equalityComparer).Union(items); } public static ImmutableHashSet.Builder CreateBuilder() { return Create().ToBuilder(); } public static ImmutableHashSet.Builder CreateBuilder(IEqualityComparer? equalityComparer) { return Create(equalityComparer).ToBuilder(); } public static ImmutableHashSet ToImmutableHashSet(this IEnumerable source, IEqualityComparer? equalityComparer) { if (source is ImmutableHashSet immutableHashSet) { return immutableHashSet.WithComparer(equalityComparer); } return ImmutableHashSet.Empty.WithComparer(equalityComparer).Union(source); } public static ImmutableHashSet ToImmutableHashSet(this ImmutableHashSet.Builder builder) { Requires.NotNull(builder, "builder"); return builder.ToImmutable(); } public static ImmutableHashSet ToImmutableHashSet(this IEnumerable source) { return source.ToImmutableHashSet(null); } } internal static class ImmutableInterlocked { public static bool Update(ref T location, Func transformer) where T : class? { Requires.NotNull(transformer, "transformer"); T val = Volatile.Read(ref location); bool flag; do { T val2 = transformer(val); if (val == val2) { return false; } T val3 = Interlocked.CompareExchange(ref location, val2, val); flag = val == val3; val = val3; } while (!flag); return true; } public static bool Update(ref T location, Func transformer, TArg transformerArgument) where T : class? { Requires.NotNull(transformer, "transformer"); T val = Volatile.Read(ref location); bool flag; do { T val2 = transformer(val, transformerArgument); if (val == val2) { return false; } T val3 = Interlocked.CompareExchange(ref location, val2, val); flag = val == val3; val = val3; } while (!flag); return true; } public static bool Update(ref ImmutableArray location, Func, ImmutableArray> transformer) { Requires.NotNull(transformer, "transformer"); T[] array = Volatile.Read(ref Unsafe.AsRef(in location.array)); bool flag; do { ImmutableArray immutableArray = transformer(new ImmutableArray(array)); if (array == immutableArray.array) { return false; } T[] array2 = Interlocked.CompareExchange(ref Unsafe.AsRef(in location.array), immutableArray.array, array); flag = array == array2; array = array2; } while (!flag); return true; } public static bool Update(ref ImmutableArray location, Func, TArg, ImmutableArray> transformer, TArg transformerArgument) { Requires.NotNull(transformer, "transformer"); T[] array = Volatile.Read(ref Unsafe.AsRef(in location.array)); bool flag; do { ImmutableArray immutableArray = transformer(new ImmutableArray(array), transformerArgument); if (array == immutableArray.array) { return false; } T[] array2 = Interlocked.CompareExchange(ref Unsafe.AsRef(in location.array), immutableArray.array, array); flag = array == array2; array = array2; } while (!flag); return true; } public static ImmutableArray InterlockedExchange(ref ImmutableArray location, ImmutableArray value) { return new ImmutableArray(Interlocked.Exchange(ref Unsafe.AsRef(in location.array), value.array)); } public static ImmutableArray InterlockedCompareExchange(ref ImmutableArray location, ImmutableArray value, ImmutableArray comparand) { return new ImmutableArray(Interlocked.CompareExchange(ref Unsafe.AsRef(in location.array), value.array, comparand.array)); } public static bool InterlockedInitialize(ref ImmutableArray location, ImmutableArray value) { return InterlockedCompareExchange(ref location, value, default(ImmutableArray)).IsDefault; } public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, Func valueFactory, TArg factoryArgument) where TKey : notnull { Requires.NotNull(valueFactory, "valueFactory"); ImmutableDictionary immutableDictionary = Volatile.Read(ref location); Requires.NotNull(immutableDictionary, "location"); if (immutableDictionary.TryGetValue(key, out var value)) { return value; } value = valueFactory(key, factoryArgument); return GetOrAdd(ref location, key, value); } public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, Func valueFactory) where TKey : notnull { Requires.NotNull(valueFactory, "valueFactory"); ImmutableDictionary immutableDictionary = Volatile.Read(ref location); Requires.NotNull(immutableDictionary, "location"); if (immutableDictionary.TryGetValue(key, out var value)) { return value; } value = valueFactory(key); return GetOrAdd(ref location, key, value); } public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, TValue value) where TKey : notnull { ImmutableDictionary immutableDictionary = Volatile.Read(ref location); bool flag; do { Requires.NotNull(immutableDictionary, "location"); if (immutableDictionary.TryGetValue(key, out var value2)) { return value2; } ImmutableDictionary value3 = immutableDictionary.Add(key, value); ImmutableDictionary immutableDictionary2 = Interlocked.CompareExchange(ref location, value3, immutableDictionary); flag = immutableDictionary == immutableDictionary2; immutableDictionary = immutableDictionary2; } while (!flag); return value; } public static TValue AddOrUpdate(ref ImmutableDictionary location, TKey key, Func addValueFactory, Func updateValueFactory) where TKey : notnull { Requires.NotNull(addValueFactory, "addValueFactory"); Requires.NotNull(updateValueFactory, "updateValueFactory"); ImmutableDictionary immutableDictionary = Volatile.Read(ref location); TValue val; bool flag; do { Requires.NotNull(immutableDictionary, "location"); val = ((!immutableDictionary.TryGetValue(key, out var value)) ? addValueFactory(key) : updateValueFactory(key, value)); ImmutableDictionary immutableDictionary2 = immutableDictionary.SetItem(key, val); if (immutableDictionary == immutableDictionary2) { return value; } ImmutableDictionary immutableDictionary3 = Interlocked.CompareExchange(ref location, immutableDictionary2, immutableDictionary); flag = immutableDictionary == immutableDictionary3; immutableDictionary = immutableDictionary3; } while (!flag); return val; } public static TValue AddOrUpdate(ref ImmutableDictionary location, TKey key, TValue addValue, Func updateValueFactory) where TKey : notnull { Requires.NotNull(updateValueFactory, "updateValueFactory"); ImmutableDictionary immutableDictionary = Volatile.Read(ref location); TValue val; bool flag; do { Requires.NotNull(immutableDictionary, "location"); val = (TValue)((!immutableDictionary.TryGetValue(key, out var value)) ? ((object)addValue) : ((object)updateValueFactory(key, value))); ImmutableDictionary immutableDictionary2 = immutableDictionary.SetItem(key, val); if (immutableDictionary == immutableDictionary2) { return value; } ImmutableDictionary immutableDictionary3 = Interlocked.CompareExchange(ref location, immutableDictionary2, immutableDictionary); flag = immutableDictionary == immutableDictionary3; immutableDictionary = immutableDictionary3; } while (!flag); return val; } public static bool TryAdd(ref ImmutableDictionary location, TKey key, TValue value) where TKey : notnull { ImmutableDictionary immutableDictionary = Volatile.Read(ref location); bool flag; do { Requires.NotNull(immutableDictionary, "location"); if (immutableDictionary.ContainsKey(key)) { return false; } ImmutableDictionary value2 = immutableDictionary.Add(key, value); ImmutableDictionary immutableDictionary2 = Interlocked.CompareExchange(ref location, value2, immutableDictionary); flag = immutableDictionary == immutableDictionary2; immutableDictionary = immutableDictionary2; } while (!flag); return true; } public static bool TryUpdate(ref ImmutableDictionary location, TKey key, TValue newValue, TValue comparisonValue) where TKey : notnull { EqualityComparer @default = EqualityComparer.Default; ImmutableDictionary immutableDictionary = Volatile.Read(ref location); bool flag; do { Requires.NotNull(immutableDictionary, "location"); if (!immutableDictionary.TryGetValue(key, out var value) || !@default.Equals(value, comparisonValue)) { return false; } ImmutableDictionary value2 = immutableDictionary.SetItem(key, newValue); ImmutableDictionary immutableDictionary2 = Interlocked.CompareExchange(ref location, value2, immutableDictionary); flag = immutableDictionary == immutableDictionary2; immutableDictionary = immutableDictionary2; } while (!flag); return true; } public static bool TryRemove(ref ImmutableDictionary location, TKey key, [MaybeNullWhen(false)] out TValue value) where TKey : notnull { ImmutableDictionary immutableDictionary = Volatile.Read(ref location); bool flag; do { Requires.NotNull(immutableDictionary, "location"); if (!immutableDictionary.TryGetValue(key, out value)) { return false; } ImmutableDictionary value2 = immutableDictionary.Remove(key); ImmutableDictionary immutableDictionary2 = Interlocked.CompareExchange(ref location, value2, immutableDictionary); flag = immutableDictionary == immutableDictionary2; immutableDictionary = immutableDictionary2; } while (!flag); return true; } public static bool TryPop(ref ImmutableStack location, [MaybeNullWhen(false)] out T value) { ImmutableStack immutableStack = Volatile.Read(ref location); bool flag; do { Requires.NotNull(immutableStack, "location"); if (immutableStack.IsEmpty) { value = default(T); return false; } ImmutableStack value2 = immutableStack.Pop(out value); ImmutableStack immutableStack2 = Interlocked.CompareExchange(ref location, value2, immutableStack); flag = immutableStack == immutableStack2; immutableStack = immutableStack2; } while (!flag); return true; } public static void Push(ref ImmutableStack location, T value) { ImmutableStack immutableStack = Volatile.Read(ref location); bool flag; do { Requires.NotNull(immutableStack, "location"); ImmutableStack value2 = immutableStack.Push(value); ImmutableStack immutableStack2 = Interlocked.CompareExchange(ref location, value2, immutableStack); flag = immutableStack == immutableStack2; immutableStack = immutableStack2; } while (!flag); } public static bool TryDequeue(ref ImmutableQueue location, [MaybeNullWhen(false)] out T value) { ImmutableQueue immutableQueue = Volatile.Read(ref location); bool flag; do { Requires.NotNull(immutableQueue, "location"); if (immutableQueue.IsEmpty) { value = default(T); return false; } ImmutableQueue value2 = immutableQueue.Dequeue(out value); ImmutableQueue immutableQueue2 = Interlocked.CompareExchange(ref location, value2, immutableQueue); flag = immutableQueue == immutableQueue2; immutableQueue = immutableQueue2; } while (!flag); return true; } public static void Enqueue(ref ImmutableQueue location, T value) { ImmutableQueue immutableQueue = Volatile.Read(ref location); bool flag; do { Requires.NotNull(immutableQueue, "location"); ImmutableQueue value2 = immutableQueue.Enqueue(value); ImmutableQueue immutableQueue2 = Interlocked.CompareExchange(ref location, value2, immutableQueue); flag = immutableQueue == immutableQueue2; immutableQueue = immutableQueue2; } while (!flag); } } internal static class ImmutableList { public static ImmutableList Create() { return ImmutableList.Empty; } public static ImmutableList Create(T item) { return ImmutableList.Empty.Add(item); } public static ImmutableList CreateRange(IEnumerable items) { return ImmutableList.Empty.AddRange(items); } public static ImmutableList Create(params T[] items) { return ImmutableList.Empty.AddRange(items); } public static ImmutableList.Builder CreateBuilder() { return Create().ToBuilder(); } public static ImmutableList ToImmutableList(this IEnumerable source) { if (source is ImmutableList result) { return result; } return ImmutableList.Empty.AddRange(source); } public static ImmutableList ToImmutableList(this ImmutableList.Builder builder) { Requires.NotNull(builder, "builder"); return builder.ToImmutable(); } public static IImmutableList Replace(this IImmutableList list, T oldValue, T newValue) { Requires.NotNull(list, "list"); return list.Replace(oldValue, newValue, EqualityComparer.Default); } public static IImmutableList Remove(this IImmutableList list, T value) { Requires.NotNull(list, "list"); return list.Remove(value, EqualityComparer.Default); } public static IImmutableList RemoveRange(this IImmutableList list, IEnumerable items) { Requires.NotNull(list, "list"); return list.RemoveRange(items, EqualityComparer.Default); } public static int IndexOf(this IImmutableList list, T item) { Requires.NotNull(list, "list"); return list.IndexOf(item, 0, list.Count, EqualityComparer.Default); } public static int IndexOf(this IImmutableList list, T item, IEqualityComparer? equalityComparer) { Requires.NotNull(list, "list"); return list.IndexOf(item, 0, list.Count, equalityComparer); } public static int IndexOf(this IImmutableList list, T item, int startIndex) { Requires.NotNull(list, "list"); return list.IndexOf(item, startIndex, list.Count - startIndex, EqualityComparer.Default); } public static int IndexOf(this IImmutableList list, T item, int startIndex, int count) { Requires.NotNull(list, "list"); return list.IndexOf(item, startIndex, count, EqualityComparer.Default); } public static int LastIndexOf(this IImmutableList list, T item) { Requires.NotNull(list, "list"); if (list.Count == 0) { return -1; } return list.LastIndexOf(item, list.Count - 1, list.Count, EqualityComparer.Default); } public static int LastIndexOf(this IImmutableList list, T item, IEqualityComparer? equalityComparer) { Requires.NotNull(list, "list"); if (list.Count == 0) { return -1; } return list.LastIndexOf(item, list.Count - 1, list.Count, equalityComparer); } public static int LastIndexOf(this IImmutableList list, T item, int startIndex) { Requires.NotNull(list, "list"); if (list.Count == 0 && startIndex == 0) { return -1; } return list.LastIndexOf(item, startIndex, startIndex + 1, EqualityComparer.Default); } public static int LastIndexOf(this IImmutableList list, T item, int startIndex, int count) { Requires.NotNull(list, "list"); return list.LastIndexOf(item, startIndex, count, EqualityComparer.Default); } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] internal sealed class ImmutableList : IImmutableList, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection, IList, ICollection, IList, ICollection, IOrderedCollection, IImmutableListQueries, IStrongEnumerable.Enumerator> { [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableListBuilderDebuggerProxy<>))] public sealed class Builder : IList, ICollection, IEnumerable, IEnumerable, IList, ICollection, IOrderedCollection, IImmutableListQueries, IReadOnlyList, IReadOnlyCollection { private ImmutableList.Node _root = Node.EmptyNode; private ImmutableList _immutable; private int _version; private object _syncRoot; public int Count => Root.Count; bool ICollection.IsReadOnly => false; internal int Version => _version; internal Node Root { get { return _root; } private set { _version++; if (_root != value) { _root = value; _immutable = null; } } } public T this[int index] { get { return Root.ItemRef(index); } set { Root = Root.ReplaceAt(index, value); } } T IOrderedCollection.this[int index] => this[index]; bool IList.IsFixedSize => false; bool IList.IsReadOnly => false; object? IList.this[int index] { get { return this[index]; } set { this[index] = (T)value; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => false; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), (object)null); } return _syncRoot; } } internal Builder(ImmutableList list) { Requires.NotNull(list, "list"); _root = list._root; _immutable = list; } public ref readonly T ItemRef(int index) { return ref Root.ItemRef(index); } public int IndexOf(T item) { return Root.IndexOf(item, EqualityComparer.Default); } public void Insert(int index, T item) { Root = Root.Insert(index, item); } public void RemoveAt(int index) { Root = Root.RemoveAt(index); } public void Add(T item) { Root = Root.Add(item); } public void Clear() { Root = Node.EmptyNode; } public bool Contains(T item) { return IndexOf(item) >= 0; } public bool Remove(T item) { int num = IndexOf(item); if (num < 0) { return false; } Root = Root.RemoveAt(num); return true; } public ImmutableList.Enumerator GetEnumerator() { return Root.GetEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public void ForEach(Action action) { Requires.NotNull(action, "action"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; action(current); } } public void CopyTo(T[] array) { _root.CopyTo(array); } public void CopyTo(T[] array, int arrayIndex) { _root.CopyTo(array, arrayIndex); } public void CopyTo(int index, T[] array, int arrayIndex, int count) { _root.CopyTo(index, array, arrayIndex, count); } public ImmutableList GetRange(int index, int count) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0, "count"); Requires.Range(index + count <= Count, "count"); return ImmutableList.WrapNode(Node.NodeTreeFromList(this, index, count)); } public ImmutableList ConvertAll(Func converter) { Requires.NotNull(converter, "converter"); return ImmutableList.WrapNode(_root.ConvertAll(converter)); } public bool Exists(Predicate match) { return _root.Exists(match); } public T? Find(Predicate match) { return _root.Find(match); } public ImmutableList FindAll(Predicate match) { return _root.FindAll(match); } public int FindIndex(Predicate match) { return _root.FindIndex(match); } public int FindIndex(int startIndex, Predicate match) { return _root.FindIndex(startIndex, match); } public int FindIndex(int startIndex, int count, Predicate match) { return _root.FindIndex(startIndex, count, match); } public T? FindLast(Predicate match) { return _root.FindLast(match); } public int FindLastIndex(Predicate match) { return _root.FindLastIndex(match); } public int FindLastIndex(int startIndex, Predicate match) { return _root.FindLastIndex(startIndex, match); } public int FindLastIndex(int startIndex, int count, Predicate match) { return _root.FindLastIndex(startIndex, count, match); } public int IndexOf(T item, int index) { return _root.IndexOf(item, index, Count - index, EqualityComparer.Default); } public int IndexOf(T item, int index, int count) { return _root.IndexOf(item, index, count, EqualityComparer.Default); } public int IndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) { return _root.IndexOf(item, index, count, equalityComparer); } public int LastIndexOf(T item) { if (Count == 0) { return -1; } return _root.LastIndexOf(item, Count - 1, Count, EqualityComparer.Default); } public int LastIndexOf(T item, int startIndex) { if (Count == 0 && startIndex == 0) { return -1; } return _root.LastIndexOf(item, startIndex, startIndex + 1, EqualityComparer.Default); } public int LastIndexOf(T item, int startIndex, int count) { return _root.LastIndexOf(item, startIndex, count, EqualityComparer.Default); } public int LastIndexOf(T item, int startIndex, int count, IEqualityComparer? equalityComparer) { return _root.LastIndexOf(item, startIndex, count, equalityComparer); } public bool TrueForAll(Predicate match) { return _root.TrueForAll(match); } public void AddRange(IEnumerable items) { Requires.NotNull(items, "items"); Root = Root.AddRange(items); } public void InsertRange(int index, IEnumerable items) { Requires.Range(index >= 0 && index <= Count, "index"); Requires.NotNull(items, "items"); Root = Root.InsertRange(index, items); } public int RemoveAll(Predicate match) { Requires.NotNull(match, "match"); int count = Count; Root = Root.RemoveAll(match); return count - Count; } public bool Remove(T item, IEqualityComparer? equalityComparer) { int num = IndexOf(item, 0, Count, equalityComparer); if (num >= 0) { RemoveAt(num); return true; } return false; } public void RemoveRange(int index, int count) { Requires.Range(index >= 0 && index <= Count, "index"); Requires.Range(count >= 0 && index + count <= Count, "count"); int num = count; while (num-- > 0) { RemoveAt(index); } } public void RemoveRange(IEnumerable items, IEqualityComparer? equalityComparer) { Requires.NotNull(items, "items"); foreach (T item in items.GetEnumerableDisposable()) { int num = Root.IndexOf(item, equalityComparer); if (num >= 0) { RemoveAt(num); } } } public void RemoveRange(IEnumerable items) { RemoveRange(items, EqualityComparer.Default); } public void Replace(T oldValue, T newValue) { Replace(oldValue, newValue, EqualityComparer.Default); } public void Replace(T oldValue, T newValue, IEqualityComparer? equalityComparer) { int num = IndexOf(oldValue, 0, Count, equalityComparer); if (num < 0) { throw new ArgumentException(System.SR.CannotFindOldValue, "oldValue"); } Root = Root.ReplaceAt(num, newValue); } public void Reverse() { Reverse(0, Count); } public void Reverse(int index, int count) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0, "count"); Requires.Range(index + count <= Count, "count"); Root = Root.Reverse(index, count); } public void Sort() { Root = Root.Sort(); } public void Sort(Comparison comparison) { Requires.NotNull(comparison, "comparison"); Root = Root.Sort(comparison); } public void Sort(IComparer? comparer) { Root = Root.Sort(comparer); } public void Sort(int index, int count, IComparer? comparer) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0, "count"); Requires.Range(index + count <= Count, "count"); Root = Root.Sort(index, count, comparer); } public int BinarySearch(T item) { return BinarySearch(item, null); } public int BinarySearch(T item, IComparer? comparer) { return BinarySearch(0, Count, item, comparer); } public int BinarySearch(int index, int count, T item, IComparer? comparer) { return Root.BinarySearch(index, count, item, comparer); } public ImmutableList ToImmutable() { return _immutable ?? (_immutable = ImmutableList.WrapNode(Root)); } int IList.Add(object value) { Add((T)value); return Count - 1; } void IList.Clear() { Clear(); } bool IList.Contains(object value) { if (ImmutableList.IsCompatibleObject(value)) { return Contains((T)value); } return false; } int IList.IndexOf(object value) { if (ImmutableList.IsCompatibleObject(value)) { return IndexOf((T)value); } return -1; } void IList.Insert(int index, object value) { Insert(index, (T)value); } void IList.Remove(object value) { if (ImmutableList.IsCompatibleObject(value)) { Remove((T)value); } } void ICollection.CopyTo(Array array, int arrayIndex) { Root.CopyTo(array, arrayIndex); } } [EditorBrowsable(EditorBrowsableState.Advanced)] public struct Enumerator : IEnumerator, IEnumerator, IDisposable, ISecurePooledObjectUser, IStrongEnumerator { private readonly Builder _builder; private readonly int _poolUserId; private readonly int _startIndex; private readonly int _count; private int _remainingCount; private readonly bool _reversed; private Node _root; private SecurePooledObject>> _stack; private Node _current; private int _enumeratingBuilderVersion; int ISecurePooledObjectUser.PoolUserId => _poolUserId; public T Current { get { ThrowIfDisposed(); if (_current != null) { return _current.Value; } throw new InvalidOperationException(); } } object? IEnumerator.Current => Current; internal Enumerator(Node root, Builder? builder = null, int startIndex = -1, int count = -1, bool reversed = false) { Requires.NotNull(root, "root"); Requires.Range(startIndex >= -1, "startIndex"); Requires.Range(count >= -1, "count"); Requires.Argument(reversed || count == -1 || ((startIndex != -1) ? startIndex : 0) + count <= root.Count); Requires.Argument(!reversed || count == -1 || ((startIndex == -1) ? (root.Count - 1) : startIndex) - count + 1 >= 0); _root = root; _builder = builder; _current = null; _startIndex = ((startIndex >= 0) ? startIndex : (reversed ? (root.Count - 1) : 0)); _count = ((count == -1) ? root.Count : count); _remainingCount = _count; _reversed = reversed; _enumeratingBuilderVersion = builder?.Version ?? (-1); _poolUserId = SecureObjectPool.NewId(); _stack = null; if (_count > 0) { if (!SecureObjectPool>, Enumerator>.TryTake(this, out _stack)) { _stack = SecureObjectPool>, Enumerator>.PrepNew(this, new Stack>(root.Height)); } ResetStack(); } } public void Dispose() { _root = null; _current = null; if (_stack != null && _stack.TryUse(ref this, out var value)) { value.ClearFastWhenEmpty(); SecureObjectPool>, Enumerator>.TryAdd(this, _stack); } _stack = null; } public bool MoveNext() { ThrowIfDisposed(); ThrowIfChanged(); if (_stack != null) { Stack> stack = _stack.Use(ref this); if (_remainingCount > 0 && stack.Count > 0) { PushNext(NextBranch(_current = stack.Pop().Value)); _remainingCount--; return true; } } _current = null; return false; } public void Reset() { ThrowIfDisposed(); _enumeratingBuilderVersion = ((_builder != null) ? _builder.Version : (-1)); _remainingCount = _count; if (_stack != null) { ResetStack(); } } private void ResetStack() { Stack> stack = _stack.Use(ref this); stack.ClearFastWhenEmpty(); Node node = _root; int num = (_reversed ? (_root.Count - _startIndex - 1) : _startIndex); while (!node.IsEmpty && num != PreviousBranch(node).Count) { if (num < PreviousBranch(node).Count) { stack.Push(new RefAsValueType(node)); node = PreviousBranch(node); } else { num -= PreviousBranch(node).Count + 1; node = NextBranch(node); } } if (!node.IsEmpty) { stack.Push(new RefAsValueType(node)); } } private Node NextBranch(Node node) { if (!_reversed) { return node.Right; } return node.Left; } private Node PreviousBranch(Node node) { if (!_reversed) { return node.Left; } return node.Right; } private void ThrowIfDisposed() { if (_root == null || (_stack != null && !_stack.IsOwned(ref this))) { Requires.FailObjectDisposed(this); } } private void ThrowIfChanged() { if (_builder != null && _builder.Version != _enumeratingBuilderVersion) { throw new InvalidOperationException(System.SR.CollectionModifiedDuringEnumeration); } } private void PushNext(Node node) { Requires.NotNull(node, "node"); if (!node.IsEmpty) { Stack> stack = _stack.Use(ref this); while (!node.IsEmpty) { stack.Push(new RefAsValueType(node)); node = PreviousBranch(node); } } } } [DebuggerDisplay("{_key}")] internal sealed class Node : IBinaryTree, IBinaryTree, IEnumerable, IEnumerable { internal static readonly Node EmptyNode = new Node(); private T _key; private bool _frozen; private byte _height; private int _count; private ImmutableList.Node _left; private ImmutableList.Node _right; public bool IsEmpty => _left == null; public int Height => _height; public Node? Left => _left; IBinaryTree? IBinaryTree.Left => _left; public Node? Right => _right; IBinaryTree? IBinaryTree.Right => _right; IBinaryTree? IBinaryTree.Left => _left; IBinaryTree? IBinaryTree.Right => _right; public T Value => _key; public int Count => _count; internal T Key => _key; internal T this[int index] { get { Requires.Range(index >= 0 && index < Count, "index"); if (index < _left._count) { return _left[index]; } if (index > _left._count) { return _right[index - _left._count - 1]; } return _key; } } private int BalanceFactor => _right._height - _left._height; private bool IsRightHeavy => BalanceFactor >= 2; private bool IsLeftHeavy => BalanceFactor <= -2; private bool IsBalanced => (uint)(BalanceFactor + 1) <= 2u; private Node() { _frozen = true; } private Node(T key, ImmutableList.Node left, ImmutableList.Node right, bool frozen = false) { Requires.NotNull(left, "left"); Requires.NotNull(right, "right"); _key = key; _left = left; _right = right; _height = ParentHeight(left, right); _count = ParentCount(left, right); _frozen = frozen; } internal ref readonly T ItemRef(int index) { Requires.Range(index >= 0 && index < Count, "index"); return ref ItemRefUnchecked(index); } private ref readonly T ItemRefUnchecked(int index) { if (index < _left._count) { return ref _left.ItemRefUnchecked(index); } if (index > _left._count) { return ref _right.ItemRefUnchecked(index - _left._count - 1); } return ref _key; } public Enumerator GetEnumerator() { return new Enumerator(this); } [ExcludeFromCodeCoverage] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } [ExcludeFromCodeCoverage] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } internal Enumerator GetEnumerator(Builder builder) { return new Enumerator(this, builder); } internal static Node NodeTreeFromList(IOrderedCollection items, int start, int length) { Requires.NotNull(items, "items"); Requires.Range(start >= 0, "start"); Requires.Range(length >= 0, "length"); if (length == 0) { return EmptyNode; } int num = (length - 1) / 2; int num2 = length - 1 - num; Node left = NodeTreeFromList(items, start, num2); Node right = NodeTreeFromList(items, start + num2 + 1, num); return new Node(items[start + num2], left, right, frozen: true); } internal Node Add(T key) { if (IsEmpty) { return CreateLeaf(key); } Node right = _right.Add(key); Node node = MutateRight(right); if (!node.IsBalanced) { return node.BalanceRight(); } return node; } internal Node Insert(int index, T key) { Requires.Range(index >= 0 && index <= Count, "index"); if (IsEmpty) { return CreateLeaf(key); } if (index <= _left._count) { Node left = _left.Insert(index, key); Node node = MutateLeft(left); if (!node.IsBalanced) { return node.BalanceLeft(); } return node; } Node right = _right.Insert(index - _left._count - 1, key); Node node2 = MutateRight(right); if (!node2.IsBalanced) { return node2.BalanceRight(); } return node2; } internal Node AddRange(IEnumerable keys) { Requires.NotNull(keys, "keys"); if (IsEmpty) { return CreateRange(keys); } Node right = _right.AddRange(keys); Node node = MutateRight(right); return node.BalanceMany(); } internal Node InsertRange(int index, IEnumerable keys) { Requires.Range(index >= 0 && index <= Count, "index"); Requires.NotNull(keys, "keys"); if (IsEmpty) { return CreateRange(keys); } Node node; if (index <= _left._count) { Node left = _left.InsertRange(index, keys); node = MutateLeft(left); } else { Node right = _right.InsertRange(index - _left._count - 1, keys); node = MutateRight(right); } return node.BalanceMany(); } internal Node RemoveAt(int index) { Requires.Range(index >= 0 && index < Count, "index"); Node node; if (index == _left._count) { if (_right.IsEmpty && _left.IsEmpty) { node = EmptyNode; } else if (_right.IsEmpty && !_left.IsEmpty) { node = _left; } else if (!_right.IsEmpty && _left.IsEmpty) { node = _right; } else { Node node2 = _right; while (!node2._left.IsEmpty) { node2 = node2._left; } Node right = _right.RemoveAt(0); node = node2.MutateBoth(_left, right); } } else if (index < _left._count) { Node left = _left.RemoveAt(index); node = MutateLeft(left); } else { Node right2 = _right.RemoveAt(index - _left._count - 1); node = MutateRight(right2); } if (!node.IsEmpty && !node.IsBalanced) { return node.Balance(); } return node; } internal Node RemoveAll(Predicate match) { Requires.NotNull(match, "match"); Node node = this; Enumerator enumerator = new Enumerator(node); try { int num = 0; while (enumerator.MoveNext()) { if (match(enumerator.Current)) { node = node.RemoveAt(num); enumerator.Dispose(); enumerator = new Enumerator(node, null, num); } else { num++; } } return node; } finally { enumerator.Dispose(); } } internal Node ReplaceAt(int index, T value) { Requires.Range(index >= 0 && index < Count, "index"); if (index == _left._count) { return MutateKey(value); } if (index < _left._count) { Node left = _left.ReplaceAt(index, value); return MutateLeft(left); } Node right = _right.ReplaceAt(index - _left._count - 1, value); return MutateRight(right); } internal Node Reverse() { return Reverse(0, Count); } internal Node Reverse(int index, int count) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0, "count"); Requires.Range(index + count <= Count, "index"); Node node = this; int num = index; int num2 = index + count - 1; while (num < num2) { T value = node.ItemRef(num); T value2 = node.ItemRef(num2); node = node.ReplaceAt(num2, value).ReplaceAt(num, value2); num++; num2--; } return node; } internal Node Sort() { return Sort(Comparer.Default); } internal Node Sort(Comparison comparison) { Requires.NotNull(comparison, "comparison"); T[] array = new T[Count]; CopyTo(array); Array.Sort(array, comparison); return NodeTreeFromList(array.AsOrderedCollection(), 0, Count); } internal Node Sort(IComparer? comparer) { return Sort(0, Count, comparer); } internal Node Sort(int index, int count, IComparer? comparer) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0, "count"); Requires.Argument(index + count <= Count); T[] array = new T[Count]; CopyTo(array); Array.Sort(array, index, count, comparer); return NodeTreeFromList(array.AsOrderedCollection(), 0, Count); } internal int BinarySearch(int index, int count, T item, IComparer? comparer) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0, "count"); if (comparer == null) { comparer = Comparer.Default; } if (IsEmpty || count <= 0) { return ~index; } int count2 = _left.Count; if (index + count <= count2) { return _left.BinarySearch(index, count, item, comparer); } if (index > count2) { int num = _right.BinarySearch(index - count2 - 1, count, item, comparer); int num2 = count2 + 1; if (num >= 0) { return num + num2; } return num - num2; } int num3 = comparer.Compare(item, _key); if (num3 == 0) { return count2; } if (num3 > 0) { int num4 = count - (count2 - index) - 1; int num5 = ((num4 < 0) ? (-1) : _right.BinarySearch(0, num4, item, comparer)); int num6 = count2 + 1; if (num5 >= 0) { return num5 + num6; } return num5 - num6; } if (index == count2) { return ~index; } return _left.BinarySearch(index, count, item, comparer); } internal int IndexOf(T item, IEqualityComparer? equalityComparer) { return IndexOf(item, 0, Count, equalityComparer); } internal bool Contains(T item, IEqualityComparer equalityComparer) { return Contains(this, item, equalityComparer); } internal int IndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0, "count"); Requires.Range(count <= Count, "count"); Requires.Range(index + count <= Count, "count"); if (equalityComparer == null) { equalityComparer = EqualityComparer.Default; } using (Enumerator enumerator = new Enumerator(this, null, index, count)) { while (enumerator.MoveNext()) { if (equalityComparer.Equals(item, enumerator.Current)) { return index; } index++; } } return -1; } internal int LastIndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0 && count <= Count, "count"); Requires.Argument(index - count + 1 >= 0); if (equalityComparer == null) { equalityComparer = EqualityComparer.Default; } using (Enumerator enumerator = new Enumerator(this, null, index, count, reversed: true)) { while (enumerator.MoveNext()) { if (equalityComparer.Equals(item, enumerator.Current)) { return index; } index--; } } return -1; } internal void CopyTo(T[] array) { Requires.NotNull(array, "array"); Requires.Range(array.Length >= Count, "array"); int num = 0; using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array[num++] = current; } } internal void CopyTo(T[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array[arrayIndex++] = current; } } internal void CopyTo(int index, T[] array, int arrayIndex, int count) { Requires.NotNull(array, "array"); Requires.Range(index >= 0, "index"); Requires.Range(count >= 0, "count"); Requires.Range(index + count <= Count, "count"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(arrayIndex + count <= array.Length, "arrayIndex"); using Enumerator enumerator = new Enumerator(this, null, index, count); while (enumerator.MoveNext()) { array[arrayIndex++] = enumerator.Current; } } internal void CopyTo(Array array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array.SetValue(current, arrayIndex++); } } internal ImmutableList.Node ConvertAll(Func converter) { ImmutableList.Node emptyNode = ImmutableList.Node.EmptyNode; if (IsEmpty) { return emptyNode; } return emptyNode.AddRange(this.Select(converter)); } internal bool TrueForAll(Predicate match) { Requires.NotNull(match, "match"); using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { T current = enumerator.Current; if (!match(current)) { return false; } } } return true; } internal bool Exists(Predicate match) { Requires.NotNull(match, "match"); using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { T current = enumerator.Current; if (match(current)) { return true; } } } return false; } internal T? Find(Predicate match) { Requires.NotNull(match, "match"); using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { T current = enumerator.Current; if (match(current)) { return current; } } } return default(T); } internal ImmutableList FindAll(Predicate match) { Requires.NotNull(match, "match"); if (IsEmpty) { return ImmutableList.Empty; } List list = null; using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { T current = enumerator.Current; if (match(current)) { if (list == null) { list = new List(); } list.Add(current); } } } if (list == null) { return ImmutableList.Empty; } return ImmutableList.CreateRange(list); } internal int FindIndex(Predicate match) { Requires.NotNull(match, "match"); return FindIndex(0, _count, match); } internal int FindIndex(int startIndex, Predicate match) { Requires.NotNull(match, "match"); Requires.Range(startIndex >= 0 && startIndex <= Count, "startIndex"); return FindIndex(startIndex, Count - startIndex, match); } internal int FindIndex(int startIndex, int count, Predicate match) { Requires.NotNull(match, "match"); Requires.Range(startIndex >= 0, "startIndex"); Requires.Range(count >= 0, "count"); Requires.Range(startIndex + count <= Count, "count"); using (Enumerator enumerator = new Enumerator(this, null, startIndex, count)) { int num = startIndex; while (enumerator.MoveNext()) { if (match(enumerator.Current)) { return num; } num++; } } return -1; } internal T? FindLast(Predicate match) { Requires.NotNull(match, "match"); using (Enumerator enumerator = new Enumerator(this, null, -1, -1, reversed: true)) { while (enumerator.MoveNext()) { if (match(enumerator.Current)) { return enumerator.Current; } } } return default(T); } internal int FindLastIndex(Predicate match) { Requires.NotNull(match, "match"); if (!IsEmpty) { return FindLastIndex(Count - 1, Count, match); } return -1; } internal int FindLastIndex(int startIndex, Predicate match) { Requires.NotNull(match, "match"); Requires.Range(startIndex >= 0, "startIndex"); Requires.Range(startIndex == 0 || startIndex < Count, "startIndex"); if (!IsEmpty) { return FindLastIndex(startIndex, startIndex + 1, match); } return -1; } internal int FindLastIndex(int startIndex, int count, Predicate match) { Requires.NotNull(match, "match"); Requires.Range(startIndex >= 0, "startIndex"); Requires.Range(count <= Count, "count"); Requires.Range(startIndex - count + 1 >= 0, "startIndex"); using (Enumerator enumerator = new Enumerator(this, null, startIndex, count, reversed: true)) { int num = startIndex; while (enumerator.MoveNext()) { if (match(enumerator.Current)) { return num; } num--; } } return -1; } internal void Freeze() { if (!_frozen) { _left.Freeze(); _right.Freeze(); _frozen = true; } } private ImmutableList.Node RotateLeft() { return _right.MutateLeft(MutateRight(_right._left)); } private ImmutableList.Node RotateRight() { return _left.MutateRight(MutateLeft(_left._right)); } private ImmutableList.Node DoubleLeft() { Node right = _right; Node left = right._left; return left.MutateBoth(MutateRight(left._left), right.MutateLeft(left._right)); } private ImmutableList.Node DoubleRight() { Node left = _left; Node right = left._right; return right.MutateBoth(left.MutateRight(right._left), MutateLeft(right._right)); } private ImmutableList.Node Balance() { if (!IsLeftHeavy) { return BalanceRight(); } return BalanceLeft(); } private ImmutableList.Node BalanceLeft() { if (_left.BalanceFactor <= 0) { return RotateRight(); } return DoubleRight(); } private ImmutableList.Node BalanceRight() { if (_right.BalanceFactor >= 0) { return RotateLeft(); } return DoubleLeft(); } private ImmutableList.Node BalanceMany() { Node node = this; while (!node.IsBalanced) { if (node.IsRightHeavy) { node = node.BalanceRight(); node.MutateLeft(node._left.BalanceMany()); } else { node = node.BalanceLeft(); node.MutateRight(node._right.BalanceMany()); } } return node; } private ImmutableList.Node MutateBoth(ImmutableList.Node left, ImmutableList.Node right) { Requires.NotNull(left, "left"); Requires.NotNull(right, "right"); if (_frozen) { return new Node(_key, left, right); } _left = left; _right = right; _height = ParentHeight(left, right); _count = ParentCount(left, right); return this; } private ImmutableList.Node MutateLeft(ImmutableList.Node left) { Requires.NotNull(left, "left"); if (_frozen) { return new Node(_key, left, _right); } _left = left; _height = ParentHeight(left, _right); _count = ParentCount(left, _right); return this; } private ImmutableList.Node MutateRight(ImmutableList.Node right) { Requires.NotNull(right, "right"); if (_frozen) { return new Node(_key, _left, right); } _right = right; _height = ParentHeight(_left, right); _count = ParentCount(_left, right); return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static byte ParentHeight(ImmutableList.Node left, ImmutableList.Node right) { return checked((byte)(1 + Math.Max(left._height, right._height))); } private static int ParentCount(ImmutableList.Node left, ImmutableList.Node right) { return 1 + left._count + right._count; } private ImmutableList.Node MutateKey(T key) { if (_frozen) { return new Node(key, _left, _right); } _key = key; return this; } private static ImmutableList.Node CreateRange(IEnumerable keys) { if (ImmutableList.TryCastToImmutableList(keys, out ImmutableList other)) { return other._root; } IOrderedCollection orderedCollection = keys.AsOrderedCollection(); return NodeTreeFromList(orderedCollection, 0, orderedCollection.Count); } private static ImmutableList.Node CreateLeaf(T key) { return new Node(key, EmptyNode, EmptyNode); } private static bool Contains(ImmutableList.Node node, T value, IEqualityComparer equalityComparer) { if (!node.IsEmpty) { if (!equalityComparer.Equals(value, node._key) && !Contains(node._left, value, equalityComparer)) { return Contains(node._right, value, equalityComparer); } return true; } return false; } } public static readonly ImmutableList Empty = new ImmutableList(); private readonly ImmutableList.Node _root; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsEmpty => _root.IsEmpty; public int Count => _root.Count; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot => this; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; public T this[int index] => _root.ItemRef(index); T IOrderedCollection.this[int index] => this[index]; T IList.this[int index] { get { return this[index]; } set { throw new NotSupportedException(); } } bool ICollection.IsReadOnly => true; bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; object? IList.this[int index] { get { return this[index]; } set { throw new NotSupportedException(); } } internal Node Root => _root; internal ImmutableList() { _root = Node.EmptyNode; } private ImmutableList(ImmutableList.Node root) { Requires.NotNull(root, "root"); root.Freeze(); _root = root; } public ImmutableList Clear() { return Empty; } public int BinarySearch(T item) { return BinarySearch(item, null); } public int BinarySearch(T item, IComparer? comparer) { return BinarySearch(0, Count, item, comparer); } public int BinarySearch(int index, int count, T item, IComparer? comparer) { return _root.BinarySearch(index, count, item, comparer); } IImmutableList IImmutableList.Clear() { return Clear(); } public ref readonly T ItemRef(int index) { return ref _root.ItemRef(index); } public Builder ToBuilder() { return new Builder(this); } public ImmutableList Add(T value) { Node root = _root.Add(value); return Wrap(root); } public ImmutableList AddRange(IEnumerable items) { Requires.NotNull(items, "items"); if (IsEmpty) { return CreateRange(items); } Node root = _root.AddRange(items); return Wrap(root); } public ImmutableList Insert(int index, T item) { Requires.Range(index >= 0 && index <= Count, "index"); return Wrap(_root.Insert(index, item)); } public ImmutableList InsertRange(int index, IEnumerable items) { Requires.Range(index >= 0 && index <= Count, "index"); Requires.NotNull(items, "items"); Node root = _root.InsertRange(index, items); return Wrap(root); } public ImmutableList Remove(T value) { return Remove(value, EqualityComparer.Default); } public ImmutableList Remove(T value, IEqualityComparer? equalityComparer) { int num = this.IndexOf(value, equalityComparer); if (num >= 0) { return RemoveAt(num); } return this; } public ImmutableList RemoveRange(int index, int count) { Requires.Range(index >= 0 && index <= Count, "index"); Requires.Range(count >= 0 && index + count <= Count, "count"); Node node = _root; int num = count; while (num-- > 0) { node = node.RemoveAt(index); } return Wrap(node); } public ImmutableList RemoveRange(IEnumerable items) { return RemoveRange(items, EqualityComparer.Default); } public ImmutableList RemoveRange(IEnumerable items, IEqualityComparer? equalityComparer) { Requires.NotNull(items, "items"); if (IsEmpty) { return this; } Node node = _root; foreach (T item in items.GetEnumerableDisposable()) { int num = node.IndexOf(item, equalityComparer); if (num >= 0) { node = node.RemoveAt(num); } } return Wrap(node); } public ImmutableList RemoveAt(int index) { Requires.Range(index >= 0 && index < Count, "index"); Node root = _root.RemoveAt(index); return Wrap(root); } public ImmutableList RemoveAll(Predicate match) { Requires.NotNull(match, "match"); return Wrap(_root.RemoveAll(match)); } public ImmutableList SetItem(int index, T value) { return Wrap(_root.ReplaceAt(index, value)); } public ImmutableList Replace(T oldValue, T newValue) { return Replace(oldValue, newValue, EqualityComparer.Default); } public ImmutableList Replace(T oldValue, T newValue, IEqualityComparer? equalityComparer) { int num = this.IndexOf(oldValue, equalityComparer); if (num < 0) { throw new ArgumentException(System.SR.CannotFindOldValue, "oldValue"); } return SetItem(num, newValue); } public ImmutableList Reverse() { return Wrap(_root.Reverse()); } public ImmutableList Reverse(int index, int count) { return Wrap(_root.Reverse(index, count)); } public ImmutableList Sort() { return Wrap(_root.Sort()); } public ImmutableList Sort(Comparison comparison) { Requires.NotNull(comparison, "comparison"); return Wrap(_root.Sort(comparison)); } public ImmutableList Sort(IComparer? comparer) { return Wrap(_root.Sort(comparer)); } public ImmutableList Sort(int index, int count, IComparer? comparer) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0, "count"); Requires.Range(index + count <= Count, "count"); return Wrap(_root.Sort(index, count, comparer)); } public void ForEach(Action action) { Requires.NotNull(action, "action"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; action(current); } } public void CopyTo(T[] array) { _root.CopyTo(array); } public void CopyTo(T[] array, int arrayIndex) { _root.CopyTo(array, arrayIndex); } public void CopyTo(int index, T[] array, int arrayIndex, int count) { _root.CopyTo(index, array, arrayIndex, count); } public ImmutableList GetRange(int index, int count) { Requires.Range(index >= 0, "index"); Requires.Range(count >= 0, "count"); Requires.Range(index + count <= Count, "count"); return Wrap(Node.NodeTreeFromList(this, index, count)); } public ImmutableList ConvertAll(Func converter) { Requires.NotNull(converter, "converter"); return ImmutableList.WrapNode(_root.ConvertAll(converter)); } public bool Exists(Predicate match) { return _root.Exists(match); } public T? Find(Predicate match) { return _root.Find(match); } public ImmutableList FindAll(Predicate match) { return _root.FindAll(match); } public int FindIndex(Predicate match) { return _root.FindIndex(match); } public int FindIndex(int startIndex, Predicate match) { return _root.FindIndex(startIndex, match); } public int FindIndex(int startIndex, int count, Predicate match) { return _root.FindIndex(startIndex, count, match); } public T? FindLast(Predicate match) { return _root.FindLast(match); } public int FindLastIndex(Predicate match) { return _root.FindLastIndex(match); } public int FindLastIndex(int startIndex, Predicate match) { return _root.FindLastIndex(startIndex, match); } public int FindLastIndex(int startIndex, int count, Predicate match) { return _root.FindLastIndex(startIndex, count, match); } public int IndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) { return _root.IndexOf(item, index, count, equalityComparer); } public int LastIndexOf(T item, int index, int count, IEqualityComparer? equalityComparer) { return _root.LastIndexOf(item, index, count, equalityComparer); } public bool TrueForAll(Predicate match) { return _root.TrueForAll(match); } public bool Contains(T value) { return _root.Contains(value, EqualityComparer.Default); } public int IndexOf(T value) { return this.IndexOf(value, EqualityComparer.Default); } IImmutableList IImmutableList.Add(T value) { return Add(value); } IImmutableList IImmutableList.AddRange(IEnumerable items) { return AddRange(items); } IImmutableList IImmutableList.Insert(int index, T item) { return Insert(index, item); } IImmutableList IImmutableList.InsertRange(int index, IEnumerable items) { return InsertRange(index, items); } IImmutableList IImmutableList.Remove(T value, IEqualityComparer equalityComparer) { return Remove(value, equalityComparer); } IImmutableList IImmutableList.RemoveAll(Predicate match) { return RemoveAll(match); } IImmutableList IImmutableList.RemoveRange(IEnumerable items, IEqualityComparer equalityComparer) { return RemoveRange(items, equalityComparer); } IImmutableList IImmutableList.RemoveRange(int index, int count) { return RemoveRange(index, count); } IImmutableList IImmutableList.RemoveAt(int index) { return RemoveAt(index); } IImmutableList IImmutableList.SetItem(int index, T value) { return SetItem(index, value); } IImmutableList IImmutableList.Replace(T oldValue, T newValue, IEqualityComparer equalityComparer) { return Replace(oldValue, newValue, equalityComparer); } IEnumerator IEnumerable.GetEnumerator() { if (!IsEmpty) { return GetEnumerator(); } return Enumerable.Empty().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } void ICollection.CopyTo(Array array, int arrayIndex) { _root.CopyTo(array, arrayIndex); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { if (IsCompatibleObject(value)) { return Contains((T)value); } return false; } int IList.IndexOf(object value) { if (!IsCompatibleObject(value)) { return -1; } return IndexOf((T)value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } public Enumerator GetEnumerator() { return new Enumerator(_root); } private static ImmutableList WrapNode(ImmutableList.Node root) { if (!root.IsEmpty) { return new ImmutableList(root); } return Empty; } private static bool TryCastToImmutableList(IEnumerable sequence, [NotNullWhen(true)] out ImmutableList other) { other = sequence as ImmutableList; if (other != null) { return true; } if (sequence is Builder builder) { other = builder.ToImmutable(); return true; } return false; } private static bool IsCompatibleObject(object value) { if (!(value is T)) { if (value == null) { return default(T) == null; } return false; } return true; } private ImmutableList Wrap(ImmutableList.Node root) { if (root != _root) { if (!root.IsEmpty) { return new ImmutableList(root); } return Clear(); } return this; } private static ImmutableList CreateRange(IEnumerable items) { if (TryCastToImmutableList(items, out ImmutableList other)) { return other; } IOrderedCollection orderedCollection = items.AsOrderedCollection(); if (orderedCollection.Count == 0) { return Empty; } Node root = Node.NodeTreeFromList(orderedCollection, 0, orderedCollection.Count); return new ImmutableList(root); } } internal sealed class ImmutableListBuilderDebuggerProxy { private readonly ImmutableList.Builder _list; private T[] _cachedContents; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public T[] Contents => _cachedContents ?? (_cachedContents = _list.ToArray(_list.Count)); public ImmutableListBuilderDebuggerProxy(ImmutableList.Builder builder) { Requires.NotNull(builder, "builder"); _list = builder; } } internal static class ImmutableQueue { public static ImmutableQueue Create() { return ImmutableQueue.Empty; } public static ImmutableQueue Create(T item) { return ImmutableQueue.Empty.Enqueue(item); } public static ImmutableQueue CreateRange(IEnumerable items) { Requires.NotNull(items, "items"); if (items is T[] items2) { return Create(items2); } using IEnumerator enumerator = items.GetEnumerator(); if (!enumerator.MoveNext()) { return ImmutableQueue.Empty; } ImmutableStack forwards = ImmutableStack.Create(enumerator.Current); ImmutableStack immutableStack = ImmutableStack.Empty; while (enumerator.MoveNext()) { immutableStack = immutableStack.Push(enumerator.Current); } return new ImmutableQueue(forwards, immutableStack); } public static ImmutableQueue Create(params T[] items) { Requires.NotNull(items, "items"); if (items.Length == 0) { return ImmutableQueue.Empty; } ImmutableStack immutableStack = ImmutableStack.Empty; for (int num = items.Length - 1; num >= 0; num--) { immutableStack = immutableStack.Push(items[num]); } return new ImmutableQueue(immutableStack, ImmutableStack.Empty); } public static IImmutableQueue Dequeue(this IImmutableQueue queue, out T value) { Requires.NotNull(queue, "queue"); value = queue.Peek(); return queue.Dequeue(); } } [DebuggerDisplay("IsEmpty = {IsEmpty}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] internal sealed class ImmutableQueue : IImmutableQueue, IEnumerable, IEnumerable { [EditorBrowsable(EditorBrowsableState.Advanced)] public struct Enumerator { private readonly ImmutableQueue _originalQueue; private ImmutableStack _remainingForwardsStack; private ImmutableStack _remainingBackwardsStack; public T Current { get { if (_remainingForwardsStack == null) { throw new InvalidOperationException(); } if (!_remainingForwardsStack.IsEmpty) { return _remainingForwardsStack.Peek(); } if (!_remainingBackwardsStack.IsEmpty) { return _remainingBackwardsStack.Peek(); } throw new InvalidOperationException(); } } internal Enumerator(ImmutableQueue queue) { _originalQueue = queue; _remainingForwardsStack = null; _remainingBackwardsStack = null; } public bool MoveNext() { if (_remainingForwardsStack == null) { _remainingForwardsStack = _originalQueue._forwards; _remainingBackwardsStack = _originalQueue.BackwardsReversed; } else if (!_remainingForwardsStack.IsEmpty) { _remainingForwardsStack = _remainingForwardsStack.Pop(); } else if (!_remainingBackwardsStack.IsEmpty) { _remainingBackwardsStack = _remainingBackwardsStack.Pop(); } if (_remainingForwardsStack.IsEmpty) { return !_remainingBackwardsStack.IsEmpty; } return true; } } private sealed class EnumeratorObject : IEnumerator, IEnumerator, IDisposable { private readonly ImmutableQueue _originalQueue; private ImmutableStack _remainingForwardsStack; private ImmutableStack _remainingBackwardsStack; private bool _disposed; public T Current { get { ThrowIfDisposed(); if (_remainingForwardsStack == null) { throw new InvalidOperationException(); } if (!_remainingForwardsStack.IsEmpty) { return _remainingForwardsStack.Peek(); } if (!_remainingBackwardsStack.IsEmpty) { return _remainingBackwardsStack.Peek(); } throw new InvalidOperationException(); } } object IEnumerator.Current => Current; internal EnumeratorObject(ImmutableQueue queue) { _originalQueue = queue; } public bool MoveNext() { ThrowIfDisposed(); if (_remainingForwardsStack == null) { _remainingForwardsStack = _originalQueue._forwards; _remainingBackwardsStack = _originalQueue.BackwardsReversed; } else if (!_remainingForwardsStack.IsEmpty) { _remainingForwardsStack = _remainingForwardsStack.Pop(); } else if (!_remainingBackwardsStack.IsEmpty) { _remainingBackwardsStack = _remainingBackwardsStack.Pop(); } if (_remainingForwardsStack.IsEmpty) { return !_remainingBackwardsStack.IsEmpty; } return true; } public void Reset() { ThrowIfDisposed(); _remainingBackwardsStack = null; _remainingForwardsStack = null; } public void Dispose() { _disposed = true; } private void ThrowIfDisposed() { if (_disposed) { Requires.FailObjectDisposed(this); } } } private static readonly ImmutableQueue s_EmptyField = new ImmutableQueue(ImmutableStack.Empty, ImmutableStack.Empty); private readonly ImmutableStack _backwards; private readonly ImmutableStack _forwards; private ImmutableStack _backwardsReversed; public bool IsEmpty => _forwards.IsEmpty; public static ImmutableQueue Empty => s_EmptyField; private ImmutableStack BackwardsReversed { get { if (_backwardsReversed == null) { _backwardsReversed = _backwards.Reverse(); } return _backwardsReversed; } } internal ImmutableQueue(ImmutableStack forwards, ImmutableStack backwards) { _forwards = forwards; _backwards = backwards; } public ImmutableQueue Clear() { return Empty; } IImmutableQueue IImmutableQueue.Clear() { return Clear(); } public T Peek() { if (IsEmpty) { throw new InvalidOperationException(System.SR.InvalidEmptyOperation); } return _forwards.Peek(); } public ref readonly T PeekRef() { if (IsEmpty) { throw new InvalidOperationException(System.SR.InvalidEmptyOperation); } return ref _forwards.PeekRef(); } public ImmutableQueue Enqueue(T value) { if (IsEmpty) { return new ImmutableQueue(ImmutableStack.Create(value), ImmutableStack.Empty); } return new ImmutableQueue(_forwards, _backwards.Push(value)); } IImmutableQueue IImmutableQueue.Enqueue(T value) { return Enqueue(value); } public ImmutableQueue Dequeue() { if (IsEmpty) { throw new InvalidOperationException(System.SR.InvalidEmptyOperation); } ImmutableStack immutableStack = _forwards.Pop(); if (!immutableStack.IsEmpty) { return new ImmutableQueue(immutableStack, _backwards); } if (_backwards.IsEmpty) { return Empty; } return new ImmutableQueue(BackwardsReversed, ImmutableStack.Empty); } public ImmutableQueue Dequeue(out T value) { value = Peek(); return Dequeue(); } IImmutableQueue IImmutableQueue.Dequeue() { return Dequeue(); } public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { if (!IsEmpty) { return new EnumeratorObject(this); } return Enumerable.Empty().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return new EnumeratorObject(this); } } internal static class ImmutableSortedDictionary { public static ImmutableSortedDictionary Create() where TKey : notnull { return ImmutableSortedDictionary.Empty; } public static ImmutableSortedDictionary Create(IComparer? keyComparer) where TKey : notnull { return ImmutableSortedDictionary.Empty.WithComparers(keyComparer); } public static ImmutableSortedDictionary Create(IComparer? keyComparer, IEqualityComparer? valueComparer) where TKey : notnull { return ImmutableSortedDictionary.Empty.WithComparers(keyComparer, valueComparer); } public static ImmutableSortedDictionary CreateRange(IEnumerable> items) where TKey : notnull { return ImmutableSortedDictionary.Empty.AddRange(items); } public static ImmutableSortedDictionary CreateRange(IComparer? keyComparer, IEnumerable> items) where TKey : notnull { return ImmutableSortedDictionary.Empty.WithComparers(keyComparer).AddRange(items); } public static ImmutableSortedDictionary CreateRange(IComparer? keyComparer, IEqualityComparer? valueComparer, IEnumerable> items) where TKey : notnull { return ImmutableSortedDictionary.Empty.WithComparers(keyComparer, valueComparer).AddRange(items); } public static ImmutableSortedDictionary.Builder CreateBuilder() where TKey : notnull { return Create().ToBuilder(); } public static ImmutableSortedDictionary.Builder CreateBuilder(IComparer? keyComparer) where TKey : notnull { return Create(keyComparer).ToBuilder(); } public static ImmutableSortedDictionary.Builder CreateBuilder(IComparer? keyComparer, IEqualityComparer? valueComparer) where TKey : notnull { return Create(keyComparer, valueComparer).ToBuilder(); } public static ImmutableSortedDictionary ToImmutableSortedDictionary(this IEnumerable source, Func keySelector, Func elementSelector, IComparer? keyComparer, IEqualityComparer? valueComparer) where TKey : notnull { Func keySelector2 = keySelector; Func elementSelector2 = elementSelector; Requires.NotNull(source, "source"); Requires.NotNull(keySelector2, "keySelector"); Requires.NotNull(elementSelector2, "elementSelector"); return ImmutableSortedDictionary.Empty.WithComparers(keyComparer, valueComparer).AddRange(source.Select((TSource element) => new KeyValuePair(keySelector2(element), elementSelector2(element)))); } public static ImmutableSortedDictionary ToImmutableSortedDictionary(this ImmutableSortedDictionary.Builder builder) where TKey : notnull { Requires.NotNull(builder, "builder"); return builder.ToImmutable(); } public static ImmutableSortedDictionary ToImmutableSortedDictionary(this IEnumerable source, Func keySelector, Func elementSelector, IComparer? keyComparer) where TKey : notnull { return source.ToImmutableSortedDictionary(keySelector, elementSelector, keyComparer, null); } public static ImmutableSortedDictionary ToImmutableSortedDictionary(this IEnumerable source, Func keySelector, Func elementSelector) where TKey : notnull { return source.ToImmutableSortedDictionary(keySelector, elementSelector, null, null); } public static ImmutableSortedDictionary ToImmutableSortedDictionary(this IEnumerable> source, IComparer? keyComparer, IEqualityComparer? valueComparer) where TKey : notnull { Requires.NotNull(source, "source"); if (source is ImmutableSortedDictionary immutableSortedDictionary) { return immutableSortedDictionary.WithComparers(keyComparer, valueComparer); } return ImmutableSortedDictionary.Empty.WithComparers(keyComparer, valueComparer).AddRange(source); } public static ImmutableSortedDictionary ToImmutableSortedDictionary(this IEnumerable> source, IComparer? keyComparer) where TKey : notnull { return source.ToImmutableSortedDictionary(keyComparer, null); } public static ImmutableSortedDictionary ToImmutableSortedDictionary(this IEnumerable> source) where TKey : notnull { return source.ToImmutableSortedDictionary(null, null); } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableDictionaryDebuggerProxy<, >))] internal sealed class ImmutableSortedDictionary : IImmutableDictionary, IReadOnlyDictionary, IEnumerable>, IEnumerable, IReadOnlyCollection>, ISortKeyCollection, IDictionary, ICollection>, IDictionary, ICollection where TKey : notnull { [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableSortedDictionaryBuilderDebuggerProxy<, >))] public sealed class Builder : IDictionary, ICollection>, IEnumerable>, IEnumerable, IReadOnlyDictionary, IReadOnlyCollection>, IDictionary, ICollection { private ImmutableSortedDictionary.Node _root = Node.EmptyNode; private IComparer _keyComparer = Comparer.Default; private IEqualityComparer _valueComparer = EqualityComparer.Default; private int _count; private ImmutableSortedDictionary _immutable; private int _version; private object _syncRoot; ICollection IDictionary.Keys => Root.Keys.ToArray(Count); public IEnumerable Keys => Root.Keys; ICollection IDictionary.Values => Root.Values.ToArray(Count); public IEnumerable Values => Root.Values; public int Count => _count; bool ICollection>.IsReadOnly => false; internal int Version => _version; private Node Root { get { return _root; } set { _version++; if (_root != value) { _root = value; _immutable = null; } } } public TValue this[TKey key] { get { if (TryGetValue(key, out var value)) { return value; } throw new KeyNotFoundException(System.SR.Format(System.SR.Arg_KeyNotFoundWithKey, key.ToString())); } set { Root = _root.SetItem(key, value, _keyComparer, _valueComparer, out var replacedExistingValue, out var mutated); if (mutated && !replacedExistingValue) { _count++; } } } bool IDictionary.IsFixedSize => false; bool IDictionary.IsReadOnly => false; ICollection IDictionary.Keys => Keys.ToArray(Count); ICollection IDictionary.Values => Values.ToArray(Count); [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), (object)null); } return _syncRoot; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => false; public IComparer KeyComparer { get { return _keyComparer; } set { Requires.NotNull(value, "value"); if (value == _keyComparer) { return; } Node node = Node.EmptyNode; int num = 0; using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; node = node.Add(current.Key, current.Value, value, _valueComparer, out var mutated); if (mutated) { num++; } } } _keyComparer = value; Root = node; _count = num; } } public IEqualityComparer ValueComparer { get { return _valueComparer; } set { Requires.NotNull(value, "value"); if (value != _valueComparer) { _valueComparer = value; _immutable = null; } } } object? IDictionary.this[object key] { get { return this[(TKey)key]; } set { this[(TKey)key] = (TValue)value; } } internal Builder(ImmutableSortedDictionary map) { Requires.NotNull(map, "map"); _root = map._root; _keyComparer = map.KeyComparer; _valueComparer = map.ValueComparer; _count = map.Count; _immutable = map; } public ref readonly TValue ValueRef(TKey key) { Requires.NotNullAllowStructs(key, "key"); return ref _root.ValueRef(key, _keyComparer); } void IDictionary.Add(object key, object value) { Add((TKey)key, (TValue)value); } bool IDictionary.Contains(object key) { return ContainsKey((TKey)key); } IDictionaryEnumerator IDictionary.GetEnumerator() { return new DictionaryEnumerator(GetEnumerator()); } void IDictionary.Remove(object key) { Remove((TKey)key); } void ICollection.CopyTo(Array array, int index) { Root.CopyTo(array, index, Count); } public void Add(TKey key, TValue value) { Root = Root.Add(key, value, _keyComparer, _valueComparer, out var mutated); if (mutated) { _count++; } } public bool ContainsKey(TKey key) { return Root.ContainsKey(key, _keyComparer); } public bool Remove(TKey key) { Root = Root.Remove(key, _keyComparer, out var mutated); if (mutated) { _count--; } return mutated; } public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) { return Root.TryGetValue(key, _keyComparer, out value); } public bool TryGetKey(TKey equalKey, out TKey actualKey) { Requires.NotNullAllowStructs(equalKey, "equalKey"); return Root.TryGetKey(equalKey, _keyComparer, out actualKey); } public void Add(KeyValuePair item) { Add(item.Key, item.Value); } public void Clear() { Root = Node.EmptyNode; _count = 0; } public bool Contains(KeyValuePair item) { return Root.Contains(item, _keyComparer, _valueComparer); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { Root.CopyTo(array, arrayIndex, Count); } public bool Remove(KeyValuePair item) { if (Contains(item)) { return Remove(item.Key); } return false; } public ImmutableSortedDictionary.Enumerator GetEnumerator() { return Root.GetEnumerator(this); } IEnumerator> IEnumerable>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public bool ContainsValue(TValue value) { return _root.ContainsValue(value, _valueComparer); } public void AddRange(IEnumerable> items) { Requires.NotNull(items, "items"); foreach (KeyValuePair item in items) { Add(item); } } public void RemoveRange(IEnumerable keys) { Requires.NotNull(keys, "keys"); foreach (TKey key in keys) { Remove(key); } } public TValue? GetValueOrDefault(TKey key) { return GetValueOrDefault(key, default(TValue)); } public TValue GetValueOrDefault(TKey key, TValue defaultValue) { Requires.NotNullAllowStructs(key, "key"); if (TryGetValue(key, out var value)) { return value; } return defaultValue; } public ImmutableSortedDictionary ToImmutable() { return _immutable ?? (_immutable = ImmutableSortedDictionary.Wrap(Root, _count, _keyComparer, _valueComparer)); } } [EditorBrowsable(EditorBrowsableState.Advanced)] public struct Enumerator : IEnumerator>, IEnumerator, IDisposable, ISecurePooledObjectUser { private readonly Builder _builder; private readonly int _poolUserId; private Node _root; private SecurePooledObject>> _stack; private Node _current; private int _enumeratingBuilderVersion; public KeyValuePair Current { get { ThrowIfDisposed(); if (_current != null) { return _current.Value; } throw new InvalidOperationException(); } } int ISecurePooledObjectUser.PoolUserId => _poolUserId; object IEnumerator.Current => Current; internal Enumerator(Node root, Builder? builder = null) { Requires.NotNull(root, "root"); _root = root; _builder = builder; _current = null; _enumeratingBuilderVersion = builder?.Version ?? (-1); _poolUserId = SecureObjectPool.NewId(); _stack = null; if (!_root.IsEmpty) { if (!SecureObjectPool>, Enumerator>.TryTake(this, out _stack)) { _stack = SecureObjectPool>, Enumerator>.PrepNew(this, new Stack>(root.Height)); } PushLeft(_root); } } public void Dispose() { _root = null; _current = null; if (_stack != null && _stack.TryUse(ref this, out var value)) { value.ClearFastWhenEmpty(); SecureObjectPool>, Enumerator>.TryAdd(this, _stack); } _stack = null; } public bool MoveNext() { ThrowIfDisposed(); ThrowIfChanged(); if (_stack != null) { Stack> stack = _stack.Use(ref this); if (stack.Count > 0) { PushLeft((_current = stack.Pop().Value).Right); return true; } } _current = null; return false; } public void Reset() { ThrowIfDisposed(); _enumeratingBuilderVersion = ((_builder != null) ? _builder.Version : (-1)); _current = null; if (_stack != null) { Stack> stack = _stack.Use(ref this); stack.ClearFastWhenEmpty(); PushLeft(_root); } } internal void ThrowIfDisposed() { if (_root == null || (_stack != null && !_stack.IsOwned(ref this))) { Requires.FailObjectDisposed(this); } } private void ThrowIfChanged() { if (_builder != null && _builder.Version != _enumeratingBuilderVersion) { throw new InvalidOperationException(System.SR.CollectionModifiedDuringEnumeration); } } private void PushLeft(Node node) { Requires.NotNull(node, "node"); Stack> stack = _stack.Use(ref this); while (!node.IsEmpty) { stack.Push(new RefAsValueType(node)); node = node.Left; } } } [DebuggerDisplay("{_key} = {_value}")] internal sealed class Node : IBinaryTree>, IBinaryTree, IEnumerable>, IEnumerable { internal static readonly Node EmptyNode = new Node(); private readonly TKey _key; private readonly TValue _value; private bool _frozen; private byte _height; private ImmutableSortedDictionary.Node _left; private ImmutableSortedDictionary.Node _right; public bool IsEmpty => _left == null; IBinaryTree>? IBinaryTree>.Left => _left; IBinaryTree>? IBinaryTree>.Right => _right; public int Height => _height; public Node? Left => _left; IBinaryTree? IBinaryTree.Left => _left; public Node? Right => _right; IBinaryTree? IBinaryTree.Right => _right; public KeyValuePair Value => new KeyValuePair(_key, _value); int IBinaryTree.Count { get { throw new NotSupportedException(); } } internal IEnumerable Keys => this.Select((KeyValuePair p) => p.Key); internal IEnumerable Values => this.Select((KeyValuePair p) => p.Value); private Node() { _frozen = true; } private Node(TKey key, TValue value, ImmutableSortedDictionary.Node left, ImmutableSortedDictionary.Node right, bool frozen = false) { Requires.NotNullAllowStructs(key, "key"); Requires.NotNull(left, "left"); Requires.NotNull(right, "right"); _key = key; _value = value; _left = left; _right = right; _height = checked((byte)(1 + Math.Max(left._height, right._height))); _frozen = frozen; } public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator> IEnumerable>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } internal Enumerator GetEnumerator(Builder builder) { return new Enumerator(this, builder); } internal void CopyTo(KeyValuePair[] array, int arrayIndex, int dictionarySize) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + dictionarySize, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; array[arrayIndex++] = current; } } internal void CopyTo(Array array, int arrayIndex, int dictionarySize) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + dictionarySize, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; array.SetValue(new DictionaryEntry(current.Key, current.Value), arrayIndex++); } } internal static Node NodeTreeFromSortedDictionary(SortedDictionary dictionary) { Requires.NotNull(dictionary, "dictionary"); IOrderedCollection> orderedCollection = dictionary.AsOrderedCollection(); return NodeTreeFromList(orderedCollection, 0, orderedCollection.Count); } internal Node Add(TKey key, TValue value, IComparer keyComparer, IEqualityComparer valueComparer, out bool mutated) { Requires.NotNullAllowStructs(key, "key"); Requires.NotNull(keyComparer, "keyComparer"); Requires.NotNull(valueComparer, "valueComparer"); bool replacedExistingValue; return SetOrAdd(key, value, keyComparer, valueComparer, overwriteExistingValue: false, out replacedExistingValue, out mutated); } internal Node SetItem(TKey key, TValue value, IComparer keyComparer, IEqualityComparer valueComparer, out bool replacedExistingValue, out bool mutated) { Requires.NotNullAllowStructs(key, "key"); Requires.NotNull(keyComparer, "keyComparer"); Requires.NotNull(valueComparer, "valueComparer"); return SetOrAdd(key, value, keyComparer, valueComparer, overwriteExistingValue: true, out replacedExistingValue, out mutated); } internal Node Remove(TKey key, IComparer keyComparer, out bool mutated) { Requires.NotNullAllowStructs(key, "key"); Requires.NotNull(keyComparer, "keyComparer"); return RemoveRecursive(key, keyComparer, out mutated); } internal ref readonly TValue ValueRef(TKey key, IComparer keyComparer) { Requires.NotNullAllowStructs(key, "key"); Requires.NotNull(keyComparer, "keyComparer"); Node node = Search(key, keyComparer); if (node.IsEmpty) { throw new KeyNotFoundException(System.SR.Format(System.SR.Arg_KeyNotFoundWithKey, key.ToString())); } return ref node._value; } internal bool TryGetValue(TKey key, IComparer keyComparer, [MaybeNullWhen(false)] out TValue value) { Requires.NotNullAllowStructs(key, "key"); Requires.NotNull(keyComparer, "keyComparer"); Node node = Search(key, keyComparer); if (node.IsEmpty) { value = default(TValue); return false; } value = node._value; return true; } internal bool TryGetKey(TKey equalKey, IComparer keyComparer, out TKey actualKey) { Requires.NotNullAllowStructs(equalKey, "equalKey"); Requires.NotNull(keyComparer, "keyComparer"); Node node = Search(equalKey, keyComparer); if (node.IsEmpty) { actualKey = equalKey; return false; } actualKey = node._key; return true; } internal bool ContainsKey(TKey key, IComparer keyComparer) { Requires.NotNullAllowStructs(key, "key"); Requires.NotNull(keyComparer, "keyComparer"); return !Search(key, keyComparer).IsEmpty; } internal bool ContainsValue(TValue value, IEqualityComparer valueComparer) { Requires.NotNull(valueComparer, "valueComparer"); using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { if (valueComparer.Equals(value, enumerator.Current.Value)) { return true; } } } return false; } internal bool Contains(KeyValuePair pair, IComparer keyComparer, IEqualityComparer valueComparer) { Requires.NotNullAllowStructs(pair.Key, "Key"); Requires.NotNull(keyComparer, "keyComparer"); Requires.NotNull(valueComparer, "valueComparer"); Node node = Search(pair.Key, keyComparer); if (node.IsEmpty) { return false; } return valueComparer.Equals(node._value, pair.Value); } internal void Freeze() { if (!_frozen) { _left.Freeze(); _right.Freeze(); _frozen = true; } } private static ImmutableSortedDictionary.Node RotateLeft(ImmutableSortedDictionary.Node tree) { Requires.NotNull(tree, "tree"); if (tree._right.IsEmpty) { return tree; } Node right = tree._right; return right.Mutate(tree.Mutate(null, right._left)); } private static ImmutableSortedDictionary.Node RotateRight(ImmutableSortedDictionary.Node tree) { Requires.NotNull(tree, "tree"); if (tree._left.IsEmpty) { return tree; } Node left = tree._left; return left.Mutate(null, tree.Mutate(left._right)); } private static ImmutableSortedDictionary.Node DoubleLeft(ImmutableSortedDictionary.Node tree) { Requires.NotNull(tree, "tree"); if (tree._right.IsEmpty) { return tree; } Node tree2 = tree.Mutate(null, RotateRight(tree._right)); return RotateLeft(tree2); } private static ImmutableSortedDictionary.Node DoubleRight(ImmutableSortedDictionary.Node tree) { Requires.NotNull(tree, "tree"); if (tree._left.IsEmpty) { return tree; } Node tree2 = tree.Mutate(RotateLeft(tree._left)); return RotateRight(tree2); } private static int Balance(ImmutableSortedDictionary.Node tree) { Requires.NotNull(tree, "tree"); return tree._right._height - tree._left._height; } private static bool IsRightHeavy(ImmutableSortedDictionary.Node tree) { Requires.NotNull(tree, "tree"); return Balance(tree) >= 2; } private static bool IsLeftHeavy(ImmutableSortedDictionary.Node tree) { Requires.NotNull(tree, "tree"); return Balance(tree) <= -2; } private static ImmutableSortedDictionary.Node MakeBalanced(ImmutableSortedDictionary.Node tree) { Requires.NotNull(tree, "tree"); if (IsRightHeavy(tree)) { if (Balance(tree._right) >= 0) { return RotateLeft(tree); } return DoubleLeft(tree); } if (IsLeftHeavy(tree)) { if (Balance(tree._left) <= 0) { return RotateRight(tree); } return DoubleRight(tree); } return tree; } private static ImmutableSortedDictionary.Node NodeTreeFromList(IOrderedCollection> items, int start, int length) { Requires.NotNull(items, "items"); Requires.Range(start >= 0, "start"); Requires.Range(length >= 0, "length"); if (length == 0) { return EmptyNode; } int num = (length - 1) / 2; int num2 = length - 1 - num; Node left = NodeTreeFromList(items, start, num2); Node right = NodeTreeFromList(items, start + num2 + 1, num); KeyValuePair keyValuePair = items[start + num2]; return new Node(keyValuePair.Key, keyValuePair.Value, left, right, frozen: true); } private ImmutableSortedDictionary.Node SetOrAdd(TKey key, TValue value, IComparer keyComparer, IEqualityComparer valueComparer, bool overwriteExistingValue, out bool replacedExistingValue, out bool mutated) { replacedExistingValue = false; if (IsEmpty) { mutated = true; return new Node(key, value, this, this); } Node node = this; int num = keyComparer.Compare(key, _key); if (num > 0) { Node right = _right.SetOrAdd(key, value, keyComparer, valueComparer, overwriteExistingValue, out replacedExistingValue, out mutated); if (mutated) { node = Mutate(null, right); } } else if (num < 0) { Node left = _left.SetOrAdd(key, value, keyComparer, valueComparer, overwriteExistingValue, out replacedExistingValue, out mutated); if (mutated) { node = Mutate(left); } } else { if (valueComparer.Equals(_value, value)) { mutated = false; return this; } if (!overwriteExistingValue) { throw new ArgumentException(System.SR.Format(System.SR.DuplicateKey, key)); } mutated = true; replacedExistingValue = true; node = new Node(key, value, _left, _right); } if (!mutated) { return node; } return MakeBalanced(node); } private ImmutableSortedDictionary.Node RemoveRecursive(TKey key, IComparer keyComparer, out bool mutated) { if (IsEmpty) { mutated = false; return this; } Node node = this; int num = keyComparer.Compare(key, _key); if (num == 0) { mutated = true; if (_right.IsEmpty && _left.IsEmpty) { node = EmptyNode; } else if (_right.IsEmpty && !_left.IsEmpty) { node = _left; } else if (!_right.IsEmpty && _left.IsEmpty) { node = _right; } else { Node node2 = _right; while (!node2._left.IsEmpty) { node2 = node2._left; } bool mutated2; Node right = _right.Remove(node2._key, keyComparer, out mutated2); node = node2.Mutate(_left, right); } } else if (num < 0) { Node left = _left.Remove(key, keyComparer, out mutated); if (mutated) { node = Mutate(left); } } else { Node right2 = _right.Remove(key, keyComparer, out mutated); if (mutated) { node = Mutate(null, right2); } } if (!node.IsEmpty) { return MakeBalanced(node); } return node; } private ImmutableSortedDictionary.Node Mutate(ImmutableSortedDictionary.Node left = null, ImmutableSortedDictionary.Node right = null) { if (_frozen) { return new Node(_key, _value, left ?? _left, right ?? _right); } if (left != null) { _left = left; } if (right != null) { _right = right; } _height = checked((byte)(1 + Math.Max(_left._height, _right._height))); return this; } private ImmutableSortedDictionary.Node Search(TKey key, IComparer keyComparer) { if (IsEmpty) { return this; } int num = keyComparer.Compare(key, _key); if (num == 0) { return this; } if (num > 0) { return _right.Search(key, keyComparer); } return _left.Search(key, keyComparer); } } public static readonly ImmutableSortedDictionary Empty = new ImmutableSortedDictionary(); private readonly ImmutableSortedDictionary.Node _root; private readonly int _count; private readonly IComparer _keyComparer; private readonly IEqualityComparer _valueComparer; public IEqualityComparer ValueComparer => _valueComparer; public bool IsEmpty => _root.IsEmpty; public int Count => _count; public IEnumerable Keys => _root.Keys; public IEnumerable Values => _root.Values; ICollection IDictionary.Keys => new KeysCollectionAccessor(this); ICollection IDictionary.Values => new ValuesCollectionAccessor(this); bool ICollection>.IsReadOnly => true; public IComparer KeyComparer => _keyComparer; internal Node Root => _root; public TValue this[TKey key] { get { Requires.NotNullAllowStructs(key, "key"); if (TryGetValue(key, out var value)) { return value; } throw new KeyNotFoundException(System.SR.Format(System.SR.Arg_KeyNotFoundWithKey, key.ToString())); } } TValue IDictionary.this[TKey key] { get { return this[key]; } set { throw new NotSupportedException(); } } bool IDictionary.IsFixedSize => true; bool IDictionary.IsReadOnly => true; ICollection IDictionary.Keys => new KeysCollectionAccessor(this); ICollection IDictionary.Values => new ValuesCollectionAccessor(this); object? IDictionary.this[object key] { get { return this[(TKey)key]; } set { throw new NotSupportedException(); } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot => this; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; internal ImmutableSortedDictionary(IComparer? keyComparer = null, IEqualityComparer? valueComparer = null) { _keyComparer = keyComparer ?? Comparer.Default; _valueComparer = valueComparer ?? EqualityComparer.Default; _root = Node.EmptyNode; } private ImmutableSortedDictionary(ImmutableSortedDictionary.Node root, int count, IComparer keyComparer, IEqualityComparer valueComparer) { Requires.NotNull(root, "root"); Requires.Range(count >= 0, "count"); Requires.NotNull(keyComparer, "keyComparer"); Requires.NotNull(valueComparer, "valueComparer"); root.Freeze(); _root = root; _count = count; _keyComparer = keyComparer; _valueComparer = valueComparer; } public ImmutableSortedDictionary Clear() { if (!_root.IsEmpty) { return Empty.WithComparers(_keyComparer, _valueComparer); } return this; } IImmutableDictionary IImmutableDictionary.Clear() { return Clear(); } public ref readonly TValue ValueRef(TKey key) { Requires.NotNullAllowStructs(key, "key"); return ref _root.ValueRef(key, _keyComparer); } public Builder ToBuilder() { return new Builder(this); } public ImmutableSortedDictionary Add(TKey key, TValue value) { Requires.NotNullAllowStructs(key, "key"); bool mutated; Node root = _root.Add(key, value, _keyComparer, _valueComparer, out mutated); return Wrap(root, _count + 1); } public ImmutableSortedDictionary SetItem(TKey key, TValue value) { Requires.NotNullAllowStructs(key, "key"); bool replacedExistingValue; bool mutated; Node root = _root.SetItem(key, value, _keyComparer, _valueComparer, out replacedExistingValue, out mutated); return Wrap(root, replacedExistingValue ? _count : (_count + 1)); } public ImmutableSortedDictionary SetItems(IEnumerable> items) { Requires.NotNull(items, "items"); return AddRange(items, overwriteOnCollision: true, avoidToSortedMap: false); } public ImmutableSortedDictionary AddRange(IEnumerable> items) { Requires.NotNull(items, "items"); return AddRange(items, overwriteOnCollision: false, avoidToSortedMap: false); } public ImmutableSortedDictionary Remove(TKey value) { Requires.NotNullAllowStructs(value, "value"); bool mutated; Node root = _root.Remove(value, _keyComparer, out mutated); return Wrap(root, _count - 1); } public ImmutableSortedDictionary RemoveRange(IEnumerable keys) { Requires.NotNull(keys, "keys"); Node node = _root; int num = _count; foreach (TKey key in keys) { bool mutated; Node node2 = node.Remove(key, _keyComparer, out mutated); if (mutated) { node = node2; num--; } } return Wrap(node, num); } public ImmutableSortedDictionary WithComparers(IComparer? keyComparer, IEqualityComparer? valueComparer) { if (keyComparer == null) { keyComparer = Comparer.Default; } if (valueComparer == null) { valueComparer = EqualityComparer.Default; } if (keyComparer == _keyComparer) { if (valueComparer == _valueComparer) { return this; } return new ImmutableSortedDictionary(_root, _count, _keyComparer, valueComparer); } ImmutableSortedDictionary immutableSortedDictionary = new ImmutableSortedDictionary(Node.EmptyNode, 0, keyComparer, valueComparer); return immutableSortedDictionary.AddRange(this, overwriteOnCollision: false, avoidToSortedMap: true); } public ImmutableSortedDictionary WithComparers(IComparer? keyComparer) { return WithComparers(keyComparer, _valueComparer); } public bool ContainsValue(TValue value) { return _root.ContainsValue(value, _valueComparer); } IImmutableDictionary IImmutableDictionary.Add(TKey key, TValue value) { return Add(key, value); } IImmutableDictionary IImmutableDictionary.SetItem(TKey key, TValue value) { return SetItem(key, value); } IImmutableDictionary IImmutableDictionary.SetItems(IEnumerable> items) { return SetItems(items); } IImmutableDictionary IImmutableDictionary.AddRange(IEnumerable> pairs) { return AddRange(pairs); } IImmutableDictionary IImmutableDictionary.RemoveRange(IEnumerable keys) { return RemoveRange(keys); } IImmutableDictionary IImmutableDictionary.Remove(TKey key) { return Remove(key); } public bool ContainsKey(TKey key) { Requires.NotNullAllowStructs(key, "key"); return _root.ContainsKey(key, _keyComparer); } public bool Contains(KeyValuePair pair) { return _root.Contains(pair, _keyComparer, _valueComparer); } public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) { Requires.NotNullAllowStructs(key, "key"); return _root.TryGetValue(key, _keyComparer, out value); } public bool TryGetKey(TKey equalKey, out TKey actualKey) { Requires.NotNullAllowStructs(equalKey, "equalKey"); return _root.TryGetKey(equalKey, _keyComparer, out actualKey); } void IDictionary.Add(TKey key, TValue value) { throw new NotSupportedException(); } bool IDictionary.Remove(TKey key) { throw new NotSupportedException(); } void ICollection>.Add(KeyValuePair item) { throw new NotSupportedException(); } void ICollection>.Clear() { throw new NotSupportedException(); } bool ICollection>.Remove(KeyValuePair item) { throw new NotSupportedException(); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; array[arrayIndex++] = current; } } void IDictionary.Add(object key, object value) { throw new NotSupportedException(); } bool IDictionary.Contains(object key) { return ContainsKey((TKey)key); } IDictionaryEnumerator IDictionary.GetEnumerator() { return new DictionaryEnumerator(GetEnumerator()); } void IDictionary.Remove(object key) { throw new NotSupportedException(); } void IDictionary.Clear() { throw new NotSupportedException(); } void ICollection.CopyTo(Array array, int index) { _root.CopyTo(array, index, Count); } IEnumerator> IEnumerable>.GetEnumerator() { if (!IsEmpty) { return GetEnumerator(); } return Enumerable.Empty>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public Enumerator GetEnumerator() { return _root.GetEnumerator(); } private static ImmutableSortedDictionary Wrap(ImmutableSortedDictionary.Node root, int count, IComparer keyComparer, IEqualityComparer valueComparer) { if (!root.IsEmpty) { return new ImmutableSortedDictionary(root, count, keyComparer, valueComparer); } return Empty.WithComparers(keyComparer, valueComparer); } private static bool TryCastToImmutableMap(IEnumerable> sequence, [NotNullWhen(true)] out ImmutableSortedDictionary other) { other = sequence as ImmutableSortedDictionary; if (other != null) { return true; } if (sequence is Builder builder) { other = builder.ToImmutable(); return true; } return false; } private ImmutableSortedDictionary AddRange(IEnumerable> items, bool overwriteOnCollision, bool avoidToSortedMap) { Requires.NotNull(items, "items"); if (IsEmpty && !avoidToSortedMap) { return FillFromEmpty(items, overwriteOnCollision); } Node node = _root; int num = _count; foreach (KeyValuePair item in items) { bool replacedExistingValue = false; bool mutated; Node node2 = (overwriteOnCollision ? node.SetItem(item.Key, item.Value, _keyComparer, _valueComparer, out replacedExistingValue, out mutated) : node.Add(item.Key, item.Value, _keyComparer, _valueComparer, out mutated)); if (mutated) { node = node2; if (!replacedExistingValue) { num++; } } } return Wrap(node, num); } private ImmutableSortedDictionary Wrap(ImmutableSortedDictionary.Node root, int adjustedCountIfDifferentRoot) { if (_root != root) { if (!root.IsEmpty) { return new ImmutableSortedDictionary(root, adjustedCountIfDifferentRoot, _keyComparer, _valueComparer); } return Clear(); } return this; } private ImmutableSortedDictionary FillFromEmpty(IEnumerable> items, bool overwriteOnCollision) { Requires.NotNull(items, "items"); if (TryCastToImmutableMap(items, out ImmutableSortedDictionary other)) { return other.WithComparers(KeyComparer, ValueComparer); } SortedDictionary sortedDictionary; if (items is IDictionary dictionary) { sortedDictionary = new SortedDictionary(dictionary, KeyComparer); } else { sortedDictionary = new SortedDictionary(KeyComparer); foreach (KeyValuePair item in items) { TValue value; if (overwriteOnCollision) { sortedDictionary[item.Key] = item.Value; } else if (sortedDictionary.TryGetValue(item.Key, out value)) { if (!_valueComparer.Equals(value, item.Value)) { throw new ArgumentException(System.SR.Format(System.SR.DuplicateKey, item.Key)); } } else { sortedDictionary.Add(item.Key, item.Value); } } } if (sortedDictionary.Count == 0) { return this; } Node root = Node.NodeTreeFromSortedDictionary(sortedDictionary); return new ImmutableSortedDictionary(root, sortedDictionary.Count, KeyComparer, ValueComparer); } } internal sealed class ImmutableSortedDictionaryBuilderDebuggerProxy where TKey : notnull { private readonly ImmutableSortedDictionary.Builder _map; private KeyValuePair[] _contents; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public KeyValuePair[] Contents => _contents ?? (_contents = _map.ToArray(_map.Count)); public ImmutableSortedDictionaryBuilderDebuggerProxy(ImmutableSortedDictionary.Builder map) { Requires.NotNull(map, "map"); _map = map; } } internal static class ImmutableSortedSet { public static ImmutableSortedSet Create() { return ImmutableSortedSet.Empty; } public static ImmutableSortedSet Create(IComparer? comparer) { return ImmutableSortedSet.Empty.WithComparer(comparer); } public static ImmutableSortedSet Create(T item) { return ImmutableSortedSet.Empty.Add(item); } public static ImmutableSortedSet Create(IComparer? comparer, T item) { return ImmutableSortedSet.Empty.WithComparer(comparer).Add(item); } public static ImmutableSortedSet CreateRange(IEnumerable items) { return ImmutableSortedSet.Empty.Union(items); } public static ImmutableSortedSet CreateRange(IComparer? comparer, IEnumerable items) { return ImmutableSortedSet.Empty.WithComparer(comparer).Union(items); } public static ImmutableSortedSet Create(params T[] items) { return ImmutableSortedSet.Empty.Union(items); } public static ImmutableSortedSet Create(IComparer? comparer, params T[] items) { return ImmutableSortedSet.Empty.WithComparer(comparer).Union(items); } public static ImmutableSortedSet.Builder CreateBuilder() { return Create().ToBuilder(); } public static ImmutableSortedSet.Builder CreateBuilder(IComparer? comparer) { return Create(comparer).ToBuilder(); } public static ImmutableSortedSet ToImmutableSortedSet(this IEnumerable source, IComparer? comparer) { if (source is ImmutableSortedSet immutableSortedSet) { return immutableSortedSet.WithComparer(comparer); } return ImmutableSortedSet.Empty.WithComparer(comparer).Union(source); } public static ImmutableSortedSet ToImmutableSortedSet(this IEnumerable source) { return source.ToImmutableSortedSet(null); } public static ImmutableSortedSet ToImmutableSortedSet(this ImmutableSortedSet.Builder builder) { Requires.NotNull(builder, "builder"); return builder.ToImmutable(); } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] internal sealed class ImmutableSortedSet : IImmutableSet, IReadOnlyCollection, IEnumerable, IEnumerable, ISortKeyCollection, IReadOnlySet, IReadOnlyList, IList, ICollection, ISet, IList, ICollection, IStrongEnumerable.Enumerator> { [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableSortedSetBuilderDebuggerProxy<>))] public sealed class Builder : ISortKeyCollection, IReadOnlyCollection, IEnumerable, IEnumerable, ISet, ICollection, ICollection { private ImmutableSortedSet.Node _root = Node.EmptyNode; private IComparer _comparer = Comparer.Default; private ImmutableSortedSet _immutable; private int _version; private object _syncRoot; public int Count => Root.Count; bool ICollection.IsReadOnly => false; public T this[int index] => _root.ItemRef(index); public T? Max => _root.Max; public T? Min => _root.Min; public IComparer KeyComparer { get { return _comparer; } set { Requires.NotNull(value, "value"); if (value == _comparer) { return; } Node node = Node.EmptyNode; using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { T current = enumerator.Current; node = node.Add(current, value, out var _); } } _immutable = null; _comparer = value; Root = node; } } internal int Version => _version; private Node Root { get { return _root; } set { _version++; if (_root != value) { _root = value; _immutable = null; } } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => false; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), (object)null); } return _syncRoot; } } internal Builder(ImmutableSortedSet set) { Requires.NotNull(set, "set"); _root = set._root; _comparer = set.KeyComparer; _immutable = set; } public ref readonly T ItemRef(int index) { return ref _root.ItemRef(index); } public bool Add(T item) { Root = Root.Add(item, _comparer, out var mutated); return mutated; } public void ExceptWith(IEnumerable other) { Requires.NotNull(other, "other"); foreach (T item in other) { Root = Root.Remove(item, _comparer, out var _); } } public void IntersectWith(IEnumerable other) { Requires.NotNull(other, "other"); Node node = Node.EmptyNode; foreach (T item in other) { if (Contains(item)) { node = node.Add(item, _comparer, out var _); } } Root = node; } public bool IsProperSubsetOf(IEnumerable other) { return ToImmutable().IsProperSubsetOf(other); } public bool IsProperSupersetOf(IEnumerable other) { return ToImmutable().IsProperSupersetOf(other); } public bool IsSubsetOf(IEnumerable other) { return ToImmutable().IsSubsetOf(other); } public bool IsSupersetOf(IEnumerable other) { return ToImmutable().IsSupersetOf(other); } public bool Overlaps(IEnumerable other) { return ToImmutable().Overlaps(other); } public bool SetEquals(IEnumerable other) { return ToImmutable().SetEquals(other); } public void SymmetricExceptWith(IEnumerable other) { Root = ToImmutable().SymmetricExcept(other)._root; } public void UnionWith(IEnumerable other) { Requires.NotNull(other, "other"); foreach (T item in other) { Root = Root.Add(item, _comparer, out var _); } } void ICollection.Add(T item) { Add(item); } public void Clear() { Root = Node.EmptyNode; } public bool Contains(T item) { return Root.Contains(item, _comparer); } void ICollection.CopyTo(T[] array, int arrayIndex) { _root.CopyTo(array, arrayIndex); } public bool Remove(T item) { Root = Root.Remove(item, _comparer, out var mutated); return mutated; } public ImmutableSortedSet.Enumerator GetEnumerator() { return Root.GetEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return Root.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public int IndexOf(T item) { return Root.IndexOf(item, _comparer); } public IEnumerable Reverse() { return new ReverseEnumerable(_root); } public ImmutableSortedSet ToImmutable() { return _immutable ?? (_immutable = ImmutableSortedSet.Wrap(Root, _comparer)); } public bool TryGetValue(T equalValue, out T actualValue) { Node node = _root.Search(equalValue, _comparer); if (!node.IsEmpty) { actualValue = node.Key; return true; } actualValue = equalValue; return false; } void ICollection.CopyTo(Array array, int arrayIndex) { Root.CopyTo(array, arrayIndex); } } private sealed class ReverseEnumerable : IEnumerable, IEnumerable { private readonly ImmutableSortedSet.Node _root; internal ReverseEnumerable(ImmutableSortedSet.Node root) { Requires.NotNull(root, "root"); _root = root; } public IEnumerator GetEnumerator() { return _root.Reverse(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [EditorBrowsable(EditorBrowsableState.Advanced)] public struct Enumerator : IEnumerator, IEnumerator, IDisposable, ISecurePooledObjectUser, IStrongEnumerator { private readonly Builder _builder; private readonly int _poolUserId; private readonly bool _reverse; private Node _root; private SecurePooledObject>> _stack; private Node _current; private int _enumeratingBuilderVersion; int ISecurePooledObjectUser.PoolUserId => _poolUserId; public T Current { get { ThrowIfDisposed(); if (_current != null) { return _current.Value; } throw new InvalidOperationException(); } } object? IEnumerator.Current => Current; internal Enumerator(Node root, Builder? builder = null, bool reverse = false) { Requires.NotNull(root, "root"); _root = root; _builder = builder; _current = null; _reverse = reverse; _enumeratingBuilderVersion = builder?.Version ?? (-1); _poolUserId = SecureObjectPool.NewId(); _stack = null; if (!SecureObjectPool>, Enumerator>.TryTake(this, out _stack)) { _stack = SecureObjectPool>, Enumerator>.PrepNew(this, new Stack>(root.Height)); } PushNext(_root); } public void Dispose() { _root = null; _current = null; if (_stack != null && _stack.TryUse(ref this, out var value)) { value.ClearFastWhenEmpty(); SecureObjectPool>, Enumerator>.TryAdd(this, _stack); _stack = null; } } public bool MoveNext() { ThrowIfDisposed(); ThrowIfChanged(); Stack> stack = _stack.Use(ref this); if (stack.Count > 0) { Node node = (_current = stack.Pop().Value); PushNext(_reverse ? node.Left : node.Right); return true; } _current = null; return false; } public void Reset() { ThrowIfDisposed(); _enumeratingBuilderVersion = ((_builder != null) ? _builder.Version : (-1)); _current = null; Stack> stack = _stack.Use(ref this); stack.ClearFastWhenEmpty(); PushNext(_root); } private void ThrowIfDisposed() { if (_root == null || (_stack != null && !_stack.IsOwned(ref this))) { Requires.FailObjectDisposed(this); } } private void ThrowIfChanged() { if (_builder != null && _builder.Version != _enumeratingBuilderVersion) { throw new InvalidOperationException(System.SR.CollectionModifiedDuringEnumeration); } } private void PushNext(Node node) { Requires.NotNull(node, "node"); Stack> stack = _stack.Use(ref this); while (!node.IsEmpty) { stack.Push(new RefAsValueType(node)); node = (_reverse ? node.Right : node.Left); } } } [DebuggerDisplay("{_key}")] internal sealed class Node : IBinaryTree, IBinaryTree, IEnumerable, IEnumerable { internal static readonly Node EmptyNode = new Node(); private readonly T _key; private bool _frozen; private byte _height; private int _count; private ImmutableSortedSet.Node _left; private ImmutableSortedSet.Node _right; public bool IsEmpty => _left == null; public int Height => _height; public Node? Left => _left; IBinaryTree? IBinaryTree.Left => _left; public Node? Right => _right; IBinaryTree? IBinaryTree.Right => _right; IBinaryTree? IBinaryTree.Left => _left; IBinaryTree? IBinaryTree.Right => _right; public T Value => _key; public int Count => _count; internal T Key => _key; internal T? Max { get { if (IsEmpty) { return default(T); } Node node = this; while (!node._right.IsEmpty) { node = node._right; } return node._key; } } internal T? Min { get { if (IsEmpty) { return default(T); } Node node = this; while (!node._left.IsEmpty) { node = node._left; } return node._key; } } internal T this[int index] { get { Requires.Range(index >= 0 && index < Count, "index"); if (index < _left._count) { return _left[index]; } if (index > _left._count) { return _right[index - _left._count - 1]; } return _key; } } private Node() { _frozen = true; } private Node(T key, ImmutableSortedSet.Node left, ImmutableSortedSet.Node right, bool frozen = false) { Requires.NotNull(left, "left"); Requires.NotNull(right, "right"); _key = key; _left = left; _right = right; _height = checked((byte)(1 + Math.Max(left._height, right._height))); _count = 1 + left._count + right._count; _frozen = frozen; } internal ref readonly T ItemRef(int index) { Requires.Range(index >= 0 && index < Count, "index"); return ref ItemRefUnchecked(index); } private ref readonly T ItemRefUnchecked(int index) { if (index < _left._count) { return ref _left.ItemRefUnchecked(index); } if (index > _left._count) { return ref _right.ItemRefUnchecked(index - _left._count - 1); } return ref _key; } public Enumerator GetEnumerator() { return new Enumerator(this); } [ExcludeFromCodeCoverage] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } [ExcludeFromCodeCoverage] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } internal Enumerator GetEnumerator(Builder builder) { return new Enumerator(this, builder); } internal void CopyTo(T[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array[arrayIndex++] = current; } } internal void CopyTo(Array array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array.SetValue(current, arrayIndex++); } } internal Node Add(T key, IComparer comparer, out bool mutated) { Requires.NotNull(comparer, "comparer"); if (IsEmpty) { mutated = true; return new Node(key, this, this); } Node node = this; int num = comparer.Compare(key, _key); if (num > 0) { Node right = _right.Add(key, comparer, out mutated); if (mutated) { node = Mutate(null, right); } } else { if (num >= 0) { mutated = false; return this; } Node left = _left.Add(key, comparer, out mutated); if (mutated) { node = Mutate(left); } } if (!mutated) { return node; } return MakeBalanced(node); } internal Node Remove(T key, IComparer comparer, out bool mutated) { Requires.NotNull(comparer, "comparer"); if (IsEmpty) { mutated = false; return this; } Node node = this; int num = comparer.Compare(key, _key); if (num == 0) { mutated = true; if (_right.IsEmpty && _left.IsEmpty) { node = EmptyNode; } else if (_right.IsEmpty && !_left.IsEmpty) { node = _left; } else if (!_right.IsEmpty && _left.IsEmpty) { node = _right; } else { Node node2 = _right; while (!node2._left.IsEmpty) { node2 = node2._left; } bool mutated2; Node right = _right.Remove(node2._key, comparer, out mutated2); node = node2.Mutate(_left, right); } } else if (num < 0) { Node left = _left.Remove(key, comparer, out mutated); if (mutated) { node = Mutate(left); } } else { Node right2 = _right.Remove(key, comparer, out mutated); if (mutated) { node = Mutate(null, right2); } } if (!node.IsEmpty) { return MakeBalanced(node); } return node; } internal bool Contains(T key, IComparer comparer) { Requires.NotNull(comparer, "comparer"); return !Search(key, comparer).IsEmpty; } internal void Freeze() { if (!_frozen) { _left.Freeze(); _right.Freeze(); _frozen = true; } } internal Node Search(T key, IComparer comparer) { Requires.NotNull(comparer, "comparer"); if (IsEmpty) { return this; } int num = comparer.Compare(key, _key); if (num == 0) { return this; } if (num > 0) { return _right.Search(key, comparer); } return _left.Search(key, comparer); } internal int IndexOf(T key, IComparer comparer) { Requires.NotNull(comparer, "comparer"); if (IsEmpty) { return -1; } int num = comparer.Compare(key, _key); if (num == 0) { return _left.Count; } if (num > 0) { int num2 = _right.IndexOf(key, comparer); bool flag = num2 < 0; if (flag) { num2 = ~num2; } num2 = _left.Count + 1 + num2; if (flag) { num2 = ~num2; } return num2; } return _left.IndexOf(key, comparer); } internal IEnumerator Reverse() { return new Enumerator(this, null, reverse: true); } private static ImmutableSortedSet.Node RotateLeft(ImmutableSortedSet.Node tree) { Requires.NotNull(tree, "tree"); if (tree._right.IsEmpty) { return tree; } Node right = tree._right; return right.Mutate(tree.Mutate(null, right._left)); } private static ImmutableSortedSet.Node RotateRight(ImmutableSortedSet.Node tree) { Requires.NotNull(tree, "tree"); if (tree._left.IsEmpty) { return tree; } Node left = tree._left; return left.Mutate(null, tree.Mutate(left._right)); } private static ImmutableSortedSet.Node DoubleLeft(ImmutableSortedSet.Node tree) { Requires.NotNull(tree, "tree"); if (tree._right.IsEmpty) { return tree; } Node tree2 = tree.Mutate(null, RotateRight(tree._right)); return RotateLeft(tree2); } private static ImmutableSortedSet.Node DoubleRight(ImmutableSortedSet.Node tree) { Requires.NotNull(tree, "tree"); if (tree._left.IsEmpty) { return tree; } Node tree2 = tree.Mutate(RotateLeft(tree._left)); return RotateRight(tree2); } private static int Balance(ImmutableSortedSet.Node tree) { Requires.NotNull(tree, "tree"); return tree._right._height - tree._left._height; } private static bool IsRightHeavy(ImmutableSortedSet.Node tree) { Requires.NotNull(tree, "tree"); return Balance(tree) >= 2; } private static bool IsLeftHeavy(ImmutableSortedSet.Node tree) { Requires.NotNull(tree, "tree"); return Balance(tree) <= -2; } private static ImmutableSortedSet.Node MakeBalanced(ImmutableSortedSet.Node tree) { Requires.NotNull(tree, "tree"); if (IsRightHeavy(tree)) { if (Balance(tree._right) >= 0) { return RotateLeft(tree); } return DoubleLeft(tree); } if (IsLeftHeavy(tree)) { if (Balance(tree._left) <= 0) { return RotateRight(tree); } return DoubleRight(tree); } return tree; } internal static Node NodeTreeFromList(IOrderedCollection items, int start, int length) { Requires.NotNull(items, "items"); if (length == 0) { return EmptyNode; } int num = (length - 1) / 2; int num2 = length - 1 - num; Node left = NodeTreeFromList(items, start, num2); Node right = NodeTreeFromList(items, start + num2 + 1, num); return new Node(items[start + num2], left, right, frozen: true); } private ImmutableSortedSet.Node Mutate(ImmutableSortedSet.Node left = null, ImmutableSortedSet.Node right = null) { if (_frozen) { return new Node(_key, left ?? _left, right ?? _right); } if (left != null) { _left = left; } if (right != null) { _right = right; } _height = checked((byte)(1 + Math.Max(_left._height, _right._height))); _count = 1 + _left._count + _right._count; return this; } } public static readonly ImmutableSortedSet Empty = new ImmutableSortedSet(); private readonly ImmutableSortedSet.Node _root; private readonly IComparer _comparer; public T? Max => _root.Max; public T? Min => _root.Min; public bool IsEmpty => _root.IsEmpty; public int Count => _root.Count; public IComparer KeyComparer => _comparer; internal IBinaryTree Root => _root; public T this[int index] => _root.ItemRef(index); bool ICollection.IsReadOnly => true; T IList.this[int index] { get { return this[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot => this; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; object? IList.this[int index] { get { return this[index]; } set { throw new NotSupportedException(); } } internal ImmutableSortedSet(IComparer? comparer = null) { _root = Node.EmptyNode; _comparer = comparer ?? Comparer.Default; } private ImmutableSortedSet(ImmutableSortedSet.Node root, IComparer comparer) { Requires.NotNull(root, "root"); Requires.NotNull(comparer, "comparer"); root.Freeze(); _root = root; _comparer = comparer; } public ImmutableSortedSet Clear() { if (!_root.IsEmpty) { return Empty.WithComparer(_comparer); } return this; } public ref readonly T ItemRef(int index) { return ref _root.ItemRef(index); } public Builder ToBuilder() { return new Builder(this); } public ImmutableSortedSet Add(T value) { bool mutated; return Wrap(_root.Add(value, _comparer, out mutated)); } public ImmutableSortedSet Remove(T value) { bool mutated; return Wrap(_root.Remove(value, _comparer, out mutated)); } public bool TryGetValue(T equalValue, out T actualValue) { Node node = _root.Search(equalValue, _comparer); if (node.IsEmpty) { actualValue = equalValue; return false; } actualValue = node.Key; return true; } public ImmutableSortedSet Intersect(IEnumerable other) { Requires.NotNull(other, "other"); ImmutableSortedSet immutableSortedSet = Clear(); foreach (T item in other.GetEnumerableDisposable()) { if (Contains(item)) { immutableSortedSet = immutableSortedSet.Add(item); } } return immutableSortedSet; } public ImmutableSortedSet Except(IEnumerable other) { Requires.NotNull(other, "other"); Node node = _root; foreach (T item in other.GetEnumerableDisposable()) { node = node.Remove(item, _comparer, out var _); } return Wrap(node); } public ImmutableSortedSet SymmetricExcept(IEnumerable other) { Requires.NotNull(other, "other"); ImmutableSortedSet immutableSortedSet = ImmutableSortedSet.CreateRange(_comparer, other); ImmutableSortedSet immutableSortedSet2 = Clear(); using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { T current = enumerator.Current; if (!immutableSortedSet.Contains(current)) { immutableSortedSet2 = immutableSortedSet2.Add(current); } } } foreach (T item in immutableSortedSet) { if (!Contains(item)) { immutableSortedSet2 = immutableSortedSet2.Add(item); } } return immutableSortedSet2; } public ImmutableSortedSet Union(IEnumerable other) { Requires.NotNull(other, "other"); if (TryCastToImmutableSortedSet(other, out ImmutableSortedSet other2) && other2.KeyComparer == KeyComparer) { if (other2.IsEmpty) { return this; } if (IsEmpty) { return other2; } if (other2.Count > Count) { return other2.Union(this); } } if (IsEmpty || (other.TryGetCount(out var count) && (float)(Count + count) * 0.15f > (float)Count)) { return LeafToRootRefill(other); } return UnionIncremental(other); } public ImmutableSortedSet WithComparer(IComparer? comparer) { if (comparer == null) { comparer = Comparer.Default; } if (comparer == _comparer) { return this; } ImmutableSortedSet immutableSortedSet = new ImmutableSortedSet(Node.EmptyNode, comparer); return immutableSortedSet.Union(this); } public bool SetEquals(IEnumerable other) { Requires.NotNull(other, "other"); if (this == other) { return true; } SortedSet sortedSet = new SortedSet(other, KeyComparer); if (Count != sortedSet.Count) { return false; } int num = 0; foreach (T item in sortedSet) { if (!Contains(item)) { return false; } num++; } return num == Count; } public bool IsProperSubsetOf(IEnumerable other) { Requires.NotNull(other, "other"); if (IsEmpty) { return other.Any(); } SortedSet sortedSet = new SortedSet(other, KeyComparer); if (Count >= sortedSet.Count) { return false; } int num = 0; bool flag = false; foreach (T item in sortedSet) { if (Contains(item)) { num++; } else { flag = true; } if (num == Count && flag) { return true; } } return false; } public bool IsProperSupersetOf(IEnumerable other) { Requires.NotNull(other, "other"); if (IsEmpty) { return false; } int num = 0; foreach (T item in other.GetEnumerableDisposable()) { num++; if (!Contains(item)) { return false; } } return Count > num; } public bool IsSubsetOf(IEnumerable other) { Requires.NotNull(other, "other"); if (IsEmpty) { return true; } SortedSet sortedSet = new SortedSet(other, KeyComparer); int num = 0; foreach (T item in sortedSet) { if (Contains(item)) { num++; } } return num == Count; } public bool IsSupersetOf(IEnumerable other) { Requires.NotNull(other, "other"); foreach (T item in other.GetEnumerableDisposable()) { if (!Contains(item)) { return false; } } return true; } public bool Overlaps(IEnumerable other) { Requires.NotNull(other, "other"); if (IsEmpty) { return false; } foreach (T item in other.GetEnumerableDisposable()) { if (Contains(item)) { return true; } } return false; } public IEnumerable Reverse() { return new ReverseEnumerable(_root); } public int IndexOf(T item) { return _root.IndexOf(item, _comparer); } public bool Contains(T value) { return _root.Contains(value, _comparer); } IImmutableSet IImmutableSet.Clear() { return Clear(); } IImmutableSet IImmutableSet.Add(T value) { return Add(value); } IImmutableSet IImmutableSet.Remove(T value) { return Remove(value); } IImmutableSet IImmutableSet.Intersect(IEnumerable other) { return Intersect(other); } IImmutableSet IImmutableSet.Except(IEnumerable other) { return Except(other); } IImmutableSet IImmutableSet.SymmetricExcept(IEnumerable other) { return SymmetricExcept(other); } IImmutableSet IImmutableSet.Union(IEnumerable other) { return Union(other); } bool ISet.Add(T item) { throw new NotSupportedException(); } void ISet.ExceptWith(IEnumerable other) { throw new NotSupportedException(); } void ISet.IntersectWith(IEnumerable other) { throw new NotSupportedException(); } void ISet.SymmetricExceptWith(IEnumerable other) { throw new NotSupportedException(); } void ISet.UnionWith(IEnumerable other) { throw new NotSupportedException(); } void ICollection.CopyTo(T[] array, int arrayIndex) { _root.CopyTo(array, arrayIndex); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return Contains((T)value); } int IList.IndexOf(object value) { return IndexOf((T)value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } void ICollection.CopyTo(Array array, int index) { _root.CopyTo(array, index); } IEnumerator IEnumerable.GetEnumerator() { if (!IsEmpty) { return GetEnumerator(); } return Enumerable.Empty().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public Enumerator GetEnumerator() { return _root.GetEnumerator(); } private static bool TryCastToImmutableSortedSet(IEnumerable sequence, [NotNullWhen(true)] out ImmutableSortedSet other) { other = sequence as ImmutableSortedSet; if (other != null) { return true; } if (sequence is Builder builder) { other = builder.ToImmutable(); return true; } return false; } private static ImmutableSortedSet Wrap(ImmutableSortedSet.Node root, IComparer comparer) { if (!root.IsEmpty) { return new ImmutableSortedSet(root, comparer); } return Empty.WithComparer(comparer); } private ImmutableSortedSet UnionIncremental(IEnumerable items) { Requires.NotNull(items, "items"); Node node = _root; foreach (T item in items.GetEnumerableDisposable()) { node = node.Add(item, _comparer, out var _); } return Wrap(node); } private ImmutableSortedSet Wrap(ImmutableSortedSet.Node root) { if (root != _root) { if (!root.IsEmpty) { return new ImmutableSortedSet(root, _comparer); } return Clear(); } return this; } private ImmutableSortedSet LeafToRootRefill(IEnumerable addedItems) { Requires.NotNull(addedItems, "addedItems"); List list; if (IsEmpty) { if (addedItems.TryGetCount(out var count) && count == 0) { return this; } list = new List(addedItems); if (list.Count == 0) { return this; } } else { list = new List(this); list.AddRange(addedItems); } IComparer keyComparer = KeyComparer; list.Sort(keyComparer); int num = 1; for (int i = 1; i < list.Count; i++) { if (keyComparer.Compare(list[i], list[i - 1]) != 0) { list[num++] = list[i]; } } list.RemoveRange(num, list.Count - num); Node root = Node.NodeTreeFromList(list.AsOrderedCollection(), 0, list.Count); return Wrap(root); } } internal sealed class ImmutableSortedSetBuilderDebuggerProxy { private readonly ImmutableSortedSet.Builder _set; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public T[] Contents => _set.ToArray(_set.Count); public ImmutableSortedSetBuilderDebuggerProxy(ImmutableSortedSet.Builder builder) { Requires.NotNull(builder, "builder"); _set = builder; } } internal static class ImmutableStack { public static ImmutableStack Create() { return ImmutableStack.Empty; } public static ImmutableStack Create(T item) { return ImmutableStack.Empty.Push(item); } public static ImmutableStack CreateRange(IEnumerable items) { Requires.NotNull(items, "items"); ImmutableStack immutableStack = ImmutableStack.Empty; foreach (T item in items) { immutableStack = immutableStack.Push(item); } return immutableStack; } public static ImmutableStack Create(params T[] items) { Requires.NotNull(items, "items"); ImmutableStack immutableStack = ImmutableStack.Empty; foreach (T value in items) { immutableStack = immutableStack.Push(value); } return immutableStack; } public static IImmutableStack Pop(this IImmutableStack stack, out T value) { Requires.NotNull(stack, "stack"); value = stack.Peek(); return stack.Pop(); } } [DebuggerDisplay("IsEmpty = {IsEmpty}; Top = {_head}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] internal sealed class ImmutableStack : IImmutableStack, IEnumerable, IEnumerable { [EditorBrowsable(EditorBrowsableState.Advanced)] public struct Enumerator { private readonly ImmutableStack _originalStack; private ImmutableStack _remainingStack; public T Current { get { if (_remainingStack == null || _remainingStack.IsEmpty) { throw new InvalidOperationException(); } return _remainingStack.Peek(); } } internal Enumerator(ImmutableStack stack) { Requires.NotNull(stack, "stack"); _originalStack = stack; _remainingStack = null; } public bool MoveNext() { if (_remainingStack == null) { _remainingStack = _originalStack; } else if (!_remainingStack.IsEmpty) { _remainingStack = _remainingStack.Pop(); } return !_remainingStack.IsEmpty; } } private sealed class EnumeratorObject : IEnumerator, IEnumerator, IDisposable { private readonly ImmutableStack _originalStack; private ImmutableStack _remainingStack; private bool _disposed; public T Current { get { ThrowIfDisposed(); if (_remainingStack == null || _remainingStack.IsEmpty) { throw new InvalidOperationException(); } return _remainingStack.Peek(); } } object IEnumerator.Current => Current; internal EnumeratorObject(ImmutableStack stack) { Requires.NotNull(stack, "stack"); _originalStack = stack; } public bool MoveNext() { ThrowIfDisposed(); if (_remainingStack == null) { _remainingStack = _originalStack; } else if (!_remainingStack.IsEmpty) { _remainingStack = _remainingStack.Pop(); } return !_remainingStack.IsEmpty; } public void Reset() { ThrowIfDisposed(); _remainingStack = null; } public void Dispose() { _disposed = true; } private void ThrowIfDisposed() { if (_disposed) { Requires.FailObjectDisposed(this); } } } private static readonly ImmutableStack s_EmptyField = new ImmutableStack(); private readonly T _head; private readonly ImmutableStack _tail; public static ImmutableStack Empty => s_EmptyField; public bool IsEmpty => _tail == null; private ImmutableStack() { } private ImmutableStack(T head, ImmutableStack tail) { _head = head; _tail = tail; } public ImmutableStack Clear() { return Empty; } IImmutableStack IImmutableStack.Clear() { return Clear(); } public T Peek() { if (IsEmpty) { throw new InvalidOperationException(System.SR.InvalidEmptyOperation); } return _head; } public ref readonly T PeekRef() { if (IsEmpty) { throw new InvalidOperationException(System.SR.InvalidEmptyOperation); } return ref _head; } public ImmutableStack Push(T value) { return new ImmutableStack(value, this); } IImmutableStack IImmutableStack.Push(T value) { return Push(value); } public ImmutableStack Pop() { if (IsEmpty) { throw new InvalidOperationException(System.SR.InvalidEmptyOperation); } return _tail; } public ImmutableStack Pop(out T value) { value = Peek(); return Pop(); } IImmutableStack IImmutableStack.Pop() { return Pop(); } public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { if (!IsEmpty) { return new EnumeratorObject(this); } return Enumerable.Empty().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return new EnumeratorObject(this); } internal ImmutableStack Reverse() { ImmutableStack immutableStack = Clear(); ImmutableStack immutableStack2 = this; while (!immutableStack2.IsEmpty) { immutableStack = immutableStack.Push(immutableStack2.Peek()); immutableStack2 = immutableStack2.Pop(); } return immutableStack; } } internal abstract class KeysOrValuesCollectionAccessor : ICollection, IEnumerable, IEnumerable, ICollection where TKey : notnull { private readonly IImmutableDictionary _dictionary; private readonly IEnumerable _keysOrValues; public bool IsReadOnly => true; public int Count => _dictionary.Count; protected IImmutableDictionary Dictionary => _dictionary; [DebuggerBrowsable(DebuggerBrowsableState.Never)] bool ICollection.IsSynchronized => true; [DebuggerBrowsable(DebuggerBrowsableState.Never)] object ICollection.SyncRoot => this; protected KeysOrValuesCollectionAccessor(IImmutableDictionary dictionary, IEnumerable keysOrValues) { Requires.NotNull(dictionary, "dictionary"); Requires.NotNull(keysOrValues, "keysOrValues"); _dictionary = dictionary; _keysOrValues = keysOrValues; } public void Add(T item) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public abstract bool Contains(T item); public void CopyTo(T[] array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using IEnumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array[arrayIndex++] = current; } } public bool Remove(T item) { throw new NotSupportedException(); } public IEnumerator GetEnumerator() { return _keysOrValues.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void ICollection.CopyTo(Array array, int arrayIndex) { Requires.NotNull(array, "array"); Requires.Range(arrayIndex >= 0, "arrayIndex"); Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex"); using IEnumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { T current = enumerator.Current; array.SetValue(current, arrayIndex++); } } } internal sealed class KeysCollectionAccessor : KeysOrValuesCollectionAccessor where TKey : notnull { internal KeysCollectionAccessor(IImmutableDictionary dictionary) : base(dictionary, dictionary.Keys) { } public override bool Contains(TKey item) { return base.Dictionary.ContainsKey(item); } } internal sealed class ValuesCollectionAccessor : KeysOrValuesCollectionAccessor where TKey : notnull { internal ValuesCollectionAccessor(IImmutableDictionary dictionary) : base(dictionary, dictionary.Values) { } public override bool Contains(TValue item) { if (base.Dictionary is ImmutableSortedDictionary immutableSortedDictionary) { return immutableSortedDictionary.ContainsValue(item); } if (base.Dictionary is IImmutableDictionaryInternal immutableDictionaryInternal) { return immutableDictionaryInternal.ContainsValue(item); } throw new NotSupportedException(); } } [DebuggerDisplay("{Value,nq}")] internal struct RefAsValueType { internal T Value; internal RefAsValueType(T value) { Value = value; } } internal static class SecureObjectPool { private static int s_poolUserIdCounter; internal const int UnassignedId = -1; internal static int NewId() { int num; do { num = Interlocked.Increment(ref s_poolUserIdCounter); } while (num == -1); return num; } } internal static class SecureObjectPool where TCaller : ISecurePooledObjectUser { public static void TryAdd(TCaller caller, SecurePooledObject item) { if (caller.PoolUserId == item.Owner) { item.Owner = -1; AllocFreeConcurrentStack>.TryAdd(item); } } public static bool TryTake(TCaller caller, out SecurePooledObject? item) { if (caller.PoolUserId != -1 && AllocFreeConcurrentStack>.TryTake(out item)) { item.Owner = caller.PoolUserId; return true; } item = null; return false; } public static SecurePooledObject PrepNew(TCaller caller, T newValue) { Requires.NotNullAllowStructs(newValue, "newValue"); SecurePooledObject securePooledObject = new SecurePooledObject(newValue); securePooledObject.Owner = caller.PoolUserId; return securePooledObject; } } internal interface ISecurePooledObjectUser { int PoolUserId { get; } } internal sealed class SecurePooledObject { private readonly T _value; private int _owner; internal int Owner { get { return _owner; } set { _owner = value; } } internal SecurePooledObject(T newValue) { Requires.NotNullAllowStructs(newValue, "newValue"); _value = newValue; } internal T Use(ref TCaller caller) where TCaller : struct, ISecurePooledObjectUser { if (!IsOwned(ref caller)) { Requires.FailObjectDisposed(caller); } return _value; } internal bool TryUse(ref TCaller caller, [MaybeNullWhen(false)] out T value) where TCaller : struct, ISecurePooledObjectUser { if (IsOwned(ref caller)) { value = _value; return true; } value = default(T); return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal bool IsOwned(ref TCaller caller) where TCaller : struct, ISecurePooledObjectUser { return caller.PoolUserId == _owner; } } [DebuggerDisplay("{_key} = {_value}")] internal sealed class SortedInt32KeyNode : IBinaryTree { [EditorBrowsable(EditorBrowsableState.Advanced)] public struct Enumerator : IEnumerator>, IEnumerator, IDisposable, ISecurePooledObjectUser { private readonly int _poolUserId; private SortedInt32KeyNode _root; private SecurePooledObject>>> _stack; private SortedInt32KeyNode _current; public KeyValuePair Current { get { ThrowIfDisposed(); if (_current != null) { return _current.Value; } throw new InvalidOperationException(); } } int ISecurePooledObjectUser.PoolUserId => _poolUserId; object IEnumerator.Current => Current; internal Enumerator(SortedInt32KeyNode root) { Requires.NotNull(root, "root"); _root = root; _current = null; _poolUserId = SecureObjectPool.NewId(); _stack = null; if (!_root.IsEmpty) { if (!SecureObjectPool>>, Enumerator>.TryTake(this, out _stack)) { _stack = SecureObjectPool>>, Enumerator>.PrepNew(this, new Stack>>(root.Height)); } PushLeft(_root); } } public void Dispose() { _root = null; _current = null; if (_stack != null && _stack.TryUse(ref this, out var value)) { value.ClearFastWhenEmpty(); SecureObjectPool>>, Enumerator>.TryAdd(this, _stack); } _stack = null; } public bool MoveNext() { ThrowIfDisposed(); if (_stack != null) { Stack>> stack = _stack.Use(ref this); if (stack.Count > 0) { PushLeft((_current = stack.Pop().Value).Right); return true; } } _current = null; return false; } public void Reset() { ThrowIfDisposed(); _current = null; if (_stack != null) { Stack>> stack = _stack.Use(ref this); stack.ClearFastWhenEmpty(); PushLeft(_root); } } internal void ThrowIfDisposed() { if (_root == null || (_stack != null && !_stack.IsOwned(ref this))) { Requires.FailObjectDisposed(this); } } private void PushLeft(SortedInt32KeyNode node) { Requires.NotNull(node, "node"); Stack>> stack = _stack.Use(ref this); while (!node.IsEmpty) { stack.Push(new RefAsValueType>(node)); node = node.Left; } } } internal static readonly SortedInt32KeyNode EmptyNode = new SortedInt32KeyNode(); private readonly int _key; private readonly TValue _value; private bool _frozen; private byte _height; private SortedInt32KeyNode _left; private SortedInt32KeyNode _right; public bool IsEmpty => _left == null; public int Height => _height; public SortedInt32KeyNode? Left => _left; public SortedInt32KeyNode? Right => _right; IBinaryTree? IBinaryTree.Left => _left; IBinaryTree? IBinaryTree.Right => _right; int IBinaryTree.Count { get { throw new NotSupportedException(); } } public KeyValuePair Value => new KeyValuePair(_key, _value); internal IEnumerable Values { get { using Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { yield return enumerator.Current.Value; } } } private SortedInt32KeyNode() { _frozen = true; } private SortedInt32KeyNode(int key, TValue value, SortedInt32KeyNode left, SortedInt32KeyNode right, bool frozen = false) { Requires.NotNull(left, "left"); Requires.NotNull(right, "right"); _key = key; _value = value; _left = left; _right = right; _frozen = frozen; _height = checked((byte)(1 + Math.Max(left._height, right._height))); } public Enumerator GetEnumerator() { return new Enumerator(this); } internal SortedInt32KeyNode SetItem(int key, TValue value, IEqualityComparer valueComparer, out bool replacedExistingValue, out bool mutated) { Requires.NotNull(valueComparer, "valueComparer"); return SetOrAdd(key, value, valueComparer, overwriteExistingValue: true, out replacedExistingValue, out mutated); } internal SortedInt32KeyNode Remove(int key, out bool mutated) { return RemoveRecursive(key, out mutated); } internal TValue? GetValueOrDefault(int key) { SortedInt32KeyNode sortedInt32KeyNode = this; while (true) { if (sortedInt32KeyNode.IsEmpty) { return default(TValue); } if (key == sortedInt32KeyNode._key) { break; } sortedInt32KeyNode = ((key <= sortedInt32KeyNode._key) ? sortedInt32KeyNode._left : sortedInt32KeyNode._right); } return sortedInt32KeyNode._value; } internal bool TryGetValue(int key, [MaybeNullWhen(false)] out TValue value) { SortedInt32KeyNode sortedInt32KeyNode = this; while (true) { if (sortedInt32KeyNode.IsEmpty) { value = default(TValue); return false; } if (key == sortedInt32KeyNode._key) { break; } sortedInt32KeyNode = ((key <= sortedInt32KeyNode._key) ? sortedInt32KeyNode._left : sortedInt32KeyNode._right); } value = sortedInt32KeyNode._value; return true; } internal void Freeze(Action>? freezeAction = null) { if (!_frozen) { freezeAction?.Invoke(new KeyValuePair(_key, _value)); _left.Freeze(freezeAction); _right.Freeze(freezeAction); _frozen = true; } } private static SortedInt32KeyNode RotateLeft(SortedInt32KeyNode tree) { Requires.NotNull(tree, "tree"); if (tree._right.IsEmpty) { return tree; } SortedInt32KeyNode right = tree._right; return right.Mutate(tree.Mutate(null, right._left)); } private static SortedInt32KeyNode RotateRight(SortedInt32KeyNode tree) { Requires.NotNull(tree, "tree"); if (tree._left.IsEmpty) { return tree; } SortedInt32KeyNode left = tree._left; return left.Mutate(null, tree.Mutate(left._right)); } private static SortedInt32KeyNode DoubleLeft(SortedInt32KeyNode tree) { Requires.NotNull(tree, "tree"); if (tree._right.IsEmpty) { return tree; } SortedInt32KeyNode tree2 = tree.Mutate(null, RotateRight(tree._right)); return RotateLeft(tree2); } private static SortedInt32KeyNode DoubleRight(SortedInt32KeyNode tree) { Requires.NotNull(tree, "tree"); if (tree._left.IsEmpty) { return tree; } SortedInt32KeyNode tree2 = tree.Mutate(RotateLeft(tree._left)); return RotateRight(tree2); } private static int Balance(SortedInt32KeyNode tree) { Requires.NotNull(tree, "tree"); return tree._right._height - tree._left._height; } private static bool IsRightHeavy(SortedInt32KeyNode tree) { Requires.NotNull(tree, "tree"); return Balance(tree) >= 2; } private static bool IsLeftHeavy(SortedInt32KeyNode tree) { Requires.NotNull(tree, "tree"); return Balance(tree) <= -2; } private static SortedInt32KeyNode MakeBalanced(SortedInt32KeyNode tree) { Requires.NotNull(tree, "tree"); if (IsRightHeavy(tree)) { if (Balance(tree._right) >= 0) { return RotateLeft(tree); } return DoubleLeft(tree); } if (IsLeftHeavy(tree)) { if (Balance(tree._left) <= 0) { return RotateRight(tree); } return DoubleRight(tree); } return tree; } private SortedInt32KeyNode SetOrAdd(int key, TValue value, IEqualityComparer valueComparer, bool overwriteExistingValue, out bool replacedExistingValue, out bool mutated) { replacedExistingValue = false; if (IsEmpty) { mutated = true; return new SortedInt32KeyNode(key, value, this, this); } SortedInt32KeyNode sortedInt32KeyNode = this; if (key > _key) { SortedInt32KeyNode right = _right.SetOrAdd(key, value, valueComparer, overwriteExistingValue, out replacedExistingValue, out mutated); if (mutated) { sortedInt32KeyNode = Mutate(null, right); } } else if (key < _key) { SortedInt32KeyNode left = _left.SetOrAdd(key, value, valueComparer, overwriteExistingValue, out replacedExistingValue, out mutated); if (mutated) { sortedInt32KeyNode = Mutate(left); } } else { if (valueComparer.Equals(_value, value)) { mutated = false; return this; } if (!overwriteExistingValue) { throw new ArgumentException(System.SR.Format(System.SR.DuplicateKey, key)); } mutated = true; replacedExistingValue = true; sortedInt32KeyNode = new SortedInt32KeyNode(key, value, _left, _right); } if (!mutated) { return sortedInt32KeyNode; } return MakeBalanced(sortedInt32KeyNode); } private SortedInt32KeyNode RemoveRecursive(int key, out bool mutated) { if (IsEmpty) { mutated = false; return this; } SortedInt32KeyNode sortedInt32KeyNode = this; if (key == _key) { mutated = true; if (_right.IsEmpty && _left.IsEmpty) { sortedInt32KeyNode = EmptyNode; } else if (_right.IsEmpty && !_left.IsEmpty) { sortedInt32KeyNode = _left; } else if (!_right.IsEmpty && _left.IsEmpty) { sortedInt32KeyNode = _right; } else { SortedInt32KeyNode sortedInt32KeyNode2 = _right; while (!sortedInt32KeyNode2._left.IsEmpty) { sortedInt32KeyNode2 = sortedInt32KeyNode2._left; } bool mutated2; SortedInt32KeyNode right = _right.Remove(sortedInt32KeyNode2._key, out mutated2); sortedInt32KeyNode = sortedInt32KeyNode2.Mutate(_left, right); } } else if (key < _key) { SortedInt32KeyNode left = _left.Remove(key, out mutated); if (mutated) { sortedInt32KeyNode = Mutate(left); } } else { SortedInt32KeyNode right2 = _right.Remove(key, out mutated); if (mutated) { sortedInt32KeyNode = Mutate(null, right2); } } if (!sortedInt32KeyNode.IsEmpty) { return MakeBalanced(sortedInt32KeyNode); } return sortedInt32KeyNode; } private SortedInt32KeyNode Mutate(SortedInt32KeyNode left = null, SortedInt32KeyNode right = null) { if (_frozen) { return new SortedInt32KeyNode(_key, _value, left ?? _left, right ?? _right); } if (left != null) { _left = left; } if (right != null) { _right = right; } _height = checked((byte)(1 + Math.Max(_left._height, _right._height))); return this; } } internal static class Requires { [DebuggerStepThrough] public static void NotNull([ValidatedNotNull] T value, string? parameterName) where T : class { if (value == null) { FailArgumentNullException(parameterName); } } [DebuggerStepThrough] public static T NotNullPassthrough([ValidatedNotNull] T value, string? parameterName) where T : class { NotNull(value, parameterName); return value; } [DebuggerStepThrough] public static void NotNullAllowStructs([ValidatedNotNull] T value, string? parameterName) { if (value == null) { FailArgumentNullException(parameterName); } } [DebuggerStepThrough] private static void FailArgumentNullException(string? parameterName) { throw new ArgumentNullException(parameterName); } [DebuggerStepThrough] public static void Range(bool condition, string? parameterName, string? message = null) { if (!condition) { FailRange(parameterName, message); } } [DebuggerStepThrough] public static void FailRange(string? parameterName, string? message = null) { if (string.IsNullOrEmpty(message)) { throw new ArgumentOutOfRangeException(parameterName); } throw new ArgumentOutOfRangeException(parameterName, message); } [DebuggerStepThrough] public static void Argument(bool condition, string? parameterName, string? message) { if (!condition) { throw new ArgumentException(message, parameterName); } } [DebuggerStepThrough] public static void Argument(bool condition) { if (!condition) { throw new ArgumentException(); } } [MethodImpl(MethodImplOptions.NoInlining)] [DebuggerStepThrough] public static void FailObjectDisposed(TDisposed disposed) { throw new ObjectDisposedException(disposed.GetType().FullName); } } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] internal sealed class ValidatedNotNullAttribute : Attribute { } } namespace System.Collections.Generic { internal interface IHashKeyCollection { IEqualityComparer KeyComparer { get; } } internal interface ISortKeyCollection { IComparer KeyComparer { get; } } }