Decompiled source of REPLUG v1.2.0

core/Buttplug.dll

Decompiled 2 months ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Buttplug.Core;
using Buttplug.Core.Messages;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Buttplug.Test")]
[assembly: InternalsVisibleTo("Buttplug.Client.Test")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Nonpolynomial Labs, LLC")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright Nonpolynomial Labs, LLC")]
[assembly: AssemblyDescription("Buttplug Sex Toy Control Library. Contains Core (messages, errors, etc), Client, and Websocket Connector components")]
[assembly: AssemblyFileVersion("4.0.0.0")]
[assembly: AssemblyInformationalVersion("4.0.0+41a6e2363781583c9c9f475b1544b7ebee02bd52")]
[assembly: AssemblyProduct("Buttplug")]
[assembly: AssemblyTitle("Buttplug")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/buttplugio/buttplug-csharp")]
[assembly: AssemblyVersion("4.0.0.0")]
namespace Buttplug.Core
{
	public static class ButtplugConsts
	{
		public const uint SystemMsgId = 0u;

		public const uint DefaultMsgId = 1u;

		public const uint CurrentSpecVersion = 3u;
	}
	public class ButtplugDeviceException : ButtplugException
	{
		public ButtplugDeviceException(string message, uint id = 0u, Exception inner = null)
			: base(message, Error.ErrorClass.ERROR_DEVICE, id, inner)
		{
		}
	}
	public class ButtplugException : Exception
	{
		public Error ButtplugErrorMessage { get; }

		public static ButtplugException FromError(Error msg)
		{
			return msg.ErrorCode switch
			{
				Error.ErrorClass.ERROR_DEVICE => new ButtplugDeviceException(msg.ErrorMessage, msg.Id), 
				Error.ErrorClass.ERROR_INIT => new ButtplugHandshakeException(msg.ErrorMessage, msg.Id), 
				Error.ErrorClass.ERROR_MSG => new ButtplugMessageException(msg.ErrorMessage, msg.Id), 
				Error.ErrorClass.ERROR_PING => new ButtplugPingException(msg.ErrorMessage, msg.Id), 
				Error.ErrorClass.ERROR_UNKNOWN => new ButtplugException(msg.ErrorMessage, msg.Id), 
				_ => new ButtplugException(msg.ErrorMessage, msg.Id), 
			};
		}

		public ButtplugException(string message, uint id = 0u, Exception inner = null)
			: this(message, Error.ErrorClass.ERROR_UNKNOWN, id, inner)
		{
		}

		public ButtplugException(string message, Error.ErrorClass err = Error.ErrorClass.ERROR_UNKNOWN, uint id = 0u, Exception inner = null)
			: base(message, inner)
		{
			ButtplugErrorMessage = new Error(message, err, id);
		}
	}
	public class ButtplugExceptionEventArgs : EventArgs
	{
		public ButtplugException Exception { get; }

		public ButtplugExceptionEventArgs(ButtplugException ex)
		{
			Exception = ex;
		}
	}
	public class ButtplugHandshakeException : ButtplugException
	{
		public ButtplugHandshakeException(string message, uint id = 0u, Exception inner = null)
			: base(message, Error.ErrorClass.ERROR_INIT, id, inner)
		{
		}
	}
	public class ButtplugJsonMessageParser
	{
		private readonly Dictionary<string, Type> _messageTypes;

		private readonly JsonSerializer _serializer;

		public ButtplugJsonMessageParser()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			_serializer = new JsonSerializer
			{
				MissingMemberHandling = (MissingMemberHandling)1
			};
			_messageTypes = new Dictionary<string, Type>();
			foreach (Type allMessageType in ButtplugUtils.GetAllMessageTypes())
			{
				_messageTypes.Add(allMessageType.Name, allMessageType);
			}
			if (!_messageTypes.Any())
			{
				throw new ButtplugMessageException("No message types available.");
			}
		}

		public IEnumerable<ButtplugMessage> Deserialize(string jsonMsg)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0031: Expected O, but got Unknown
			//IL_005b: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			JsonTextReader val = new JsonTextReader((TextReader)new StringReader(jsonMsg))
			{
				CloseInput = false,
				SupportMultipleContent = true
			};
			List<ButtplugMessage> list = new List<ButtplugMessage>();
			while (true)
			{
				try
				{
					if (!((JsonReader)val).Read())
					{
						return list;
					}
				}
				catch (JsonReaderException val2)
				{
					JsonReaderException val3 = val2;
					throw new ButtplugMessageException("Not valid JSON: " + jsonMsg + " - " + ((Exception)(object)val3).Message);
				}
				JArray val4;
				try
				{
					val4 = JArray.Load((JsonReader)(object)val);
				}
				catch (JsonReaderException val5)
				{
					JsonReaderException val6 = val5;
					throw new ButtplugMessageException("Not valid JSON: " + jsonMsg + " - " + ((Exception)(object)val6).Message);
				}
				foreach (JObject item in ((JToken)val4).Children<JObject>())
				{
					string name = item.Properties().First().Name;
					if (!_messageTypes.ContainsKey(name))
					{
						throw new ButtplugMessageException(name + " is not a valid message class");
					}
					list.Add(DeserializeAs(item, _messageTypes[name]));
				}
			}
		}

		private ButtplugMessage DeserializeAs(JObject obj, Type msgType)
		{
			//IL_00c0: Expected O, but got Unknown
			if (!msgType.IsSubclassOf(typeof(ButtplugMessage)))
			{
				throw new ButtplugMessageException("Type " + msgType.Name + " is not a subclass of ButtplugMessage");
			}
			if (msgType.Namespace != "Buttplug.Core.Messages")
			{
				throw new ButtplugMessageException("Type " + msgType.Name + " (" + msgType.Namespace + ") is not in the namespace of Buttplug.Core.Messages");
			}
			string name = ButtplugMessage.GetName(msgType);
			try
			{
				return (ButtplugMessage)((JToken)Extensions.Value<JObject>((IEnumerable<JToken>)obj[name])).ToObject(msgType, _serializer);
			}
			catch (InvalidCastException ex)
			{
				throw new ButtplugMessageException($"Could not create message for JSON {obj}: {ex.Message}");
			}
			catch (JsonSerializationException val)
			{
				JsonSerializationException val2 = val;
				throw new ButtplugMessageException($"Could not create message for JSON {obj}: {((Exception)(object)val2).Message}");
			}
		}

		public string Serialize(ButtplugMessage msg)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (msg.GetType().Namespace != "Buttplug.Core.Messages")
			{
				throw new ButtplugMessageException("Type " + msg.GetType().Name + " (" + msg.GetType().Namespace + ") is not in the namespace of Buttplug.Core.Messages");
			}
			JObject val = ButtplugMessageToJObject(msg);
			if (val == null)
			{
				throw new ButtplugMessageException("Message cannot be converted to JSON.", msg.Id);
			}
			JArray val2 = new JArray();
			val2.Add((JToken)(object)val);
			return ((JToken)val2).ToString((Formatting)0, Array.Empty<JsonConverter>());
		}

		public string Serialize(IEnumerable<ButtplugMessage> msgs)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			JArray val = new JArray();
			foreach (ButtplugMessage msg in msgs)
			{
				JObject val2 = ButtplugMessageToJObject(msg);
				if (val2 != null)
				{
					val.Add((JToken)(object)val2);
				}
			}
			if (!((IEnumerable<JToken>)val).Any())
			{
				throw new ButtplugMessageException("No messages serialized.");
			}
			return ((JToken)val).ToString((Formatting)0, Array.Empty<JsonConverter>());
		}

		private JObject ButtplugMessageToJObject(ButtplugMessage msg)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			return new JObject((object)new JProperty(msg.Name, (object)JObject.FromObject((object)msg)));
		}
	}
	public class ButtplugMessageException : ButtplugException
	{
		public ButtplugMessageException(string message, uint id = 0u, Exception inner = null)
			: base(message, Error.ErrorClass.ERROR_MSG, id, inner)
		{
		}
	}
	public class ButtplugPingException : ButtplugException
	{
		public ButtplugPingException(string message, uint id = 0u, Exception inner = null)
			: base(message, Error.ErrorClass.ERROR_PING, id, inner)
		{
		}
	}
	public static class ButtplugUtils
	{
		public static IEnumerable<Type> GetAllMessageTypes()
		{
			IEnumerable<Type> enumerable;
			try
			{
				enumerable = Assembly.GetAssembly(typeof(ButtplugMessage))?.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				enumerable = ex.Types;
			}
			return (enumerable ?? throw new InvalidOperationException()).Where((Type type) => type != null && type.IsClass && type.IsSubclassOf(typeof(ButtplugMessage)) && type != typeof(ButtplugDeviceMessage));
		}

		[DebuggerStepThrough]
		public static void ArgumentNotNull(object argument, string argumentName)
		{
			if (argument == null)
			{
				throw new ArgumentNullException(argumentName);
			}
		}

		public static Type GetMessageType(string messageName)
		{
			return Type.GetType("Buttplug.Core.Messages." + messageName);
		}
	}
}
namespace Buttplug.Core.Messages
{
	public class ButtplugDeviceMessage : ButtplugMessage
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public uint DeviceIndex { get; set; }

		public ButtplugDeviceMessage(uint id = 1u, uint deviceIndex = uint.MaxValue)
			: base(id)
		{
			DeviceIndex = deviceIndex;
		}
	}
	public abstract class ButtplugMessage
	{
		private static readonly Dictionary<Type, ButtplugMessageMetadata> _metadataCache = new Dictionary<Type, ButtplugMessageMetadata>();

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public uint Id { get; set; }

		[JsonIgnore]
		public string Name => GetName(GetType());

		protected ButtplugMessage(uint id)
		{
			Id = id;
		}

		private static T GetMessageAttribute<T>(Type msgType, Func<ButtplugMessageMetadata, T> func)
		{
			ButtplugUtils.ArgumentNotNull(msgType, "msgType");
			ButtplugUtils.ArgumentNotNull(func, "func");
			if (!msgType.IsSubclassOf(typeof(ButtplugMessage)))
			{
				throw new ArgumentException("Argument " + msgType.Name + " must be a subclass of ButtplugMessage");
			}
			if (_metadataCache.ContainsKey(msgType))
			{
				return func(_metadataCache[msgType]);
			}
			Attribute[] customAttributes = Attribute.GetCustomAttributes(msgType);
			for (int i = 0; i < customAttributes.Length; i++)
			{
				if (customAttributes[i] is ButtplugMessageMetadata buttplugMessageMetadata)
				{
					_metadataCache[msgType] = buttplugMessageMetadata;
					return func(buttplugMessageMetadata);
				}
			}
			throw new ArgumentException($"Type {msgType} does not have ButtplugMessageMetadata Attributes");
		}

		public static string GetName(Type msgType)
		{
			return GetMessageAttribute(msgType, (ButtplugMessageMetadata md) => md.Name);
		}
	}
	public interface IButtplugMessageOutgoingOnly
	{
	}
	public interface IButtplugDeviceInfoMessage
	{
		string DeviceName { get; }

		uint DeviceIndex { get; }

		DeviceMessageAttributes DeviceMessages { get; }

		string DeviceDisplayName { get; }

		uint DeviceMessageTimingGap { get; }
	}
	[AttributeUsage(AttributeTargets.Class)]
	public class ButtplugMessageMetadata : Attribute
	{
		public string Name { get; }

		public ButtplugMessageMetadata(string name)
		{
			Name = name;
		}
	}
	[JsonConverter(typeof(StringEnumConverter))]
	public enum ActuatorType
	{
		[EnumMember(Value = "Unknown")]
		Unknown,
		[EnumMember(Value = "Vibrate")]
		Vibrate,
		[EnumMember(Value = "Rotate")]
		Rotate,
		[EnumMember(Value = "Oscillate")]
		Oscillate,
		[EnumMember(Value = "Constrict")]
		Constrict,
		[EnumMember(Value = "Inflate")]
		Inflate,
		[EnumMember(Value = "Position")]
		Position
	}
	[JsonConverter(typeof(StringEnumConverter))]
	public enum SensorType
	{
		[EnumMember(Value = "Unknown")]
		Unknown,
		[EnumMember(Value = "Battery")]
		Battery,
		[EnumMember(Value = "RSSI")]
		RSSI,
		[EnumMember(Value = "Button")]
		Button,
		[EnumMember(Value = "Pressure")]
		Pressure
	}
	public class GenericDeviceMessageAttributes
	{
		[JsonIgnore]
		internal uint _index;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly string FeatureDescriptor;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		[JsonConverter(typeof(StringEnumConverter))]
		public readonly ActuatorType ActuatorType;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly uint StepCount;

		[JsonIgnore]
		public uint Index => _index;
	}
	public class SensorDeviceMessageAttributes
	{
		[JsonIgnore]
		internal uint _index;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly string FeatureDescriptor;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		[JsonConverter(typeof(StringEnumConverter))]
		public readonly SensorType SensorType;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly uint[][] SensorRange;

		[JsonIgnore]
		public uint Index => _index;
	}
	public class RawDeviceMessageAttributes
	{
		public readonly string[] Endpoints;
	}
	public class NullDeviceMessageAttributes
	{
	}
	public class DeviceMessageAttributes
	{
		internal class EnumeratePair<T>
		{
			public readonly int index;

			public readonly T attr;

			public EnumeratePair(T attr, int index)
			{
				this.index = index;
				this.attr = attr;
			}
		}

		public GenericDeviceMessageAttributes[] ScalarCmd;

		public GenericDeviceMessageAttributes[] RotateCmd;

		public GenericDeviceMessageAttributes[] LinearCmd;

		public SensorDeviceMessageAttributes[] SensorReadCmd;

		public SensorDeviceMessageAttributes[] SensorSubscribeCmd;

		public readonly RawDeviceMessageAttributes[] RawReadCmd;

		public readonly RawDeviceMessageAttributes[] RawWriteCmd;

		public readonly RawDeviceMessageAttributes[] RawSubscribeCmd;

		public readonly NullDeviceMessageAttributes StopDeviceCmd;

		[OnDeserialized]
		internal void OnDeserializedMethod(StreamingContext context)
		{
			ScalarCmd?.Select((GenericDeviceMessageAttributes x, int i) => new EnumeratePair<GenericDeviceMessageAttributes>(x, i)).ToList().ForEach(delegate(EnumeratePair<GenericDeviceMessageAttributes> x)
			{
				x.attr._index = (uint)x.index;
			});
			RotateCmd?.Select((GenericDeviceMessageAttributes x, int i) => new EnumeratePair<GenericDeviceMessageAttributes>(x, i)).ToList().ForEach(delegate(EnumeratePair<GenericDeviceMessageAttributes> x)
			{
				x.attr._index = (uint)x.index;
			});
			LinearCmd?.Select((GenericDeviceMessageAttributes x, int i) => new EnumeratePair<GenericDeviceMessageAttributes>(x, i)).ToList().ForEach(delegate(EnumeratePair<GenericDeviceMessageAttributes> x)
			{
				x.attr._index = (uint)x.index;
			});
			SensorReadCmd?.Select((SensorDeviceMessageAttributes x, int i) => new EnumeratePair<SensorDeviceMessageAttributes>(x, i)).ToList().ForEach(delegate(EnumeratePair<SensorDeviceMessageAttributes> x)
			{
				x.attr._index = (uint)x.index;
			});
			SensorSubscribeCmd?.Select((SensorDeviceMessageAttributes x, int i) => new EnumeratePair<SensorDeviceMessageAttributes>(x, i)).ToList().ForEach(delegate(EnumeratePair<SensorDeviceMessageAttributes> x)
			{
				x.attr._index = (uint)x.index;
			});
		}
	}
	public class MessageReceivedEventArgs : EventArgs
	{
		public ButtplugMessage Message { get; }

		public MessageReceivedEventArgs(ButtplugMessage message)
		{
			Message = message;
		}
	}
	[ButtplugMessageMetadata("Ok")]
	public class Ok : ButtplugMessage, IButtplugMessageOutgoingOnly
	{
		public Ok(uint id)
			: base(id)
		{
		}
	}
	[ButtplugMessageMetadata("Test")]
	public class Test : ButtplugMessage
	{
		private string _testStringImpl;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string TestString
		{
			get
			{
				return _testStringImpl;
			}
			set
			{
				if (value == "Error")
				{
					throw new ArgumentException("Got an Error Message");
				}
				_testStringImpl = value;
			}
		}

		public Test(string str, uint id = 1u)
			: base(id)
		{
			TestString = str;
		}
	}
	[ButtplugMessageMetadata("Error")]
	public class Error : ButtplugMessage, IButtplugMessageOutgoingOnly
	{
		public enum ErrorClass
		{
			ERROR_UNKNOWN,
			ERROR_INIT,
			ERROR_PING,
			ERROR_MSG,
			ERROR_DEVICE
		}

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public ErrorClass ErrorCode;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string ErrorMessage;

		public Error(string errorMessage, ErrorClass errorCode, uint id)
			: base(id)
		{
			ErrorMessage = errorMessage;
			ErrorCode = errorCode;
		}
	}
	public class MessageAttributes : IEquatable<MessageAttributes>
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public uint? FeatureCount;

		public MessageAttributes()
		{
		}

		public MessageAttributes(uint featureCount)
		{
			FeatureCount = featureCount;
		}

		public bool Equals(MessageAttributes attrs)
		{
			return FeatureCount == attrs.FeatureCount;
		}
	}
	public class DeviceMessageInfo : IButtplugDeviceInfoMessage
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly string DeviceName;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly uint DeviceIndex;

		public readonly string DeviceDisplayName;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly uint DeviceMessageTimingGap;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly DeviceMessageAttributes DeviceMessages;

		string IButtplugDeviceInfoMessage.DeviceName => DeviceName;

		uint IButtplugDeviceInfoMessage.DeviceIndex => DeviceIndex;

		DeviceMessageAttributes IButtplugDeviceInfoMessage.DeviceMessages => DeviceMessages;

		string IButtplugDeviceInfoMessage.DeviceDisplayName => DeviceDisplayName;

		uint IButtplugDeviceInfoMessage.DeviceMessageTimingGap => DeviceMessageTimingGap;

		public DeviceMessageInfo(uint index, string name, DeviceMessageAttributes messages)
		{
			DeviceName = name;
			DeviceIndex = index;
			DeviceMessages = messages;
		}
	}
	[ButtplugMessageMetadata("DeviceList")]
	public class DeviceList : ButtplugMessage, IButtplugMessageOutgoingOnly
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly DeviceMessageInfo[] Devices = new DeviceMessageInfo[0];

		public DeviceList(DeviceMessageInfo[] deviceList, uint id)
			: base(id)
		{
			Devices = deviceList;
		}

		internal DeviceList()
			: base(0u)
		{
		}
	}
	[ButtplugMessageMetadata("DeviceAdded")]
	public class DeviceAdded : ButtplugDeviceMessage, IButtplugMessageOutgoingOnly, IButtplugDeviceInfoMessage
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string DeviceName;

		public readonly string DeviceDisplayName;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly uint DeviceMessageTimingGap;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly DeviceMessageAttributes DeviceMessages;

		string IButtplugDeviceInfoMessage.DeviceName => DeviceName;

		uint IButtplugDeviceInfoMessage.DeviceIndex => base.DeviceIndex;

		DeviceMessageAttributes IButtplugDeviceInfoMessage.DeviceMessages => DeviceMessages;

		string IButtplugDeviceInfoMessage.DeviceDisplayName => DeviceDisplayName;

		uint IButtplugDeviceInfoMessage.DeviceMessageTimingGap => DeviceMessageTimingGap;

		public DeviceAdded(uint index, string name, DeviceMessageAttributes messages)
			: base(0u, index)
		{
			DeviceName = name;
			DeviceMessages = messages;
		}

		internal DeviceAdded()
			: base(0u)
		{
		}
	}
	[ButtplugMessageMetadata("DeviceRemoved")]
	public class DeviceRemoved : ButtplugMessage, IButtplugMessageOutgoingOnly
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly uint DeviceIndex;

		public DeviceRemoved(uint index)
			: base(0u)
		{
			DeviceIndex = index;
		}
	}
	[ButtplugMessageMetadata("RequestDeviceList")]
	public class RequestDeviceList : ButtplugMessage
	{
		public RequestDeviceList(uint id = 1u)
			: base(id)
		{
		}
	}
	[ButtplugMessageMetadata("StartScanning")]
	public class StartScanning : ButtplugMessage
	{
		public StartScanning(uint id = 1u)
			: base(id)
		{
		}
	}
	[ButtplugMessageMetadata("StopScanning")]
	public class StopScanning : ButtplugMessage
	{
		public StopScanning(uint id = 1u)
			: base(id)
		{
		}
	}
	[ButtplugMessageMetadata("ScanningFinished")]
	public class ScanningFinished : ButtplugMessage, IButtplugMessageOutgoingOnly
	{
		public ScanningFinished()
			: base(0u)
		{
		}
	}
	[ButtplugMessageMetadata("RequestServerInfo")]
	public class RequestServerInfo : ButtplugMessage
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string ClientName;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public uint MessageVersion;

		public RequestServerInfo(string clientName, uint id = 1u, uint schemversion = 3u)
			: base(id)
		{
			ClientName = clientName;
			MessageVersion = schemversion;
		}
	}
	[ButtplugMessageMetadata("ServerInfo")]
	public class ServerInfo : ButtplugMessage, IButtplugMessageOutgoingOnly
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public uint MessageVersion;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public uint MaxPingTime;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string ServerName;

		public ServerInfo(string serverName, uint messageVersion, uint maxPingTime, uint id = 1u)
			: base(id)
		{
			ServerName = serverName;
			MessageVersion = messageVersion;
			MaxPingTime = maxPingTime;
		}
	}
	[ButtplugMessageMetadata("Ping")]
	public class Ping : ButtplugMessage
	{
		public Ping(uint id = 1u)
			: base(id)
		{
		}
	}
	public class GenericMessageSubcommand
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public uint Index;

		protected GenericMessageSubcommand(uint index)
		{
			Index = index;
		}
	}
	[ButtplugMessageMetadata("ScalarCmd")]
	public class ScalarCmd : ButtplugDeviceMessage
	{
		public class ScalarCommand
		{
			public readonly uint index;

			public readonly double scalar;

			public ScalarCommand(uint index, double scalar)
			{
				this.index = index;
				this.scalar = scalar;
			}
		}

		public class ScalarSubcommand : GenericMessageSubcommand
		{
			private double _scalarImpl;

			public readonly ActuatorType ActuatorType;

			[JsonProperty(/*Could not decode attribute arguments.*/)]
			public double Scalar
			{
				get
				{
					return _scalarImpl;
				}
				set
				{
					if (value < 0.0)
					{
						throw new ArgumentException("ScalarCmd value cannot be less than 0!");
					}
					if (value > 1.0)
					{
						throw new ArgumentException("ScalarCmd value cannot be greater than 1!");
					}
					_scalarImpl = value;
				}
			}

			public ScalarSubcommand(uint index, double scalar, ActuatorType actuatorType)
				: base(index)
			{
				Scalar = scalar;
				ActuatorType = actuatorType;
			}
		}

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public List<ScalarSubcommand> Scalars;

		[JsonConstructor]
		public ScalarCmd(uint deviceIndex, List<ScalarSubcommand> scalars, uint id = 1u)
			: base(id, deviceIndex)
		{
			Scalars = scalars;
		}

		public ScalarCmd(List<ScalarSubcommand> scalars)
			: this(uint.MaxValue, scalars)
		{
		}
	}
	[ButtplugMessageMetadata("RotateCmd")]
	public class RotateCmd : ButtplugDeviceMessage
	{
		public class RotateCommand
		{
			public readonly double speed;

			public readonly bool clockwise;

			public RotateCommand(double speed, bool clockwise)
			{
				this.speed = speed;
				this.clockwise = clockwise;
			}
		}

		public class RotateSubcommand : GenericMessageSubcommand
		{
			private double _speedImpl;

			[JsonProperty(/*Could not decode attribute arguments.*/)]
			public bool Clockwise;

			[JsonProperty(/*Could not decode attribute arguments.*/)]
			public double Speed
			{
				get
				{
					return _speedImpl;
				}
				set
				{
					if (value < 0.0)
					{
						throw new ArgumentException("RotateCmd Speed cannot be less than 0!");
					}
					if (value > 1.0)
					{
						throw new ArgumentException("RotateCmd Speed cannot be greater than 1!");
					}
					_speedImpl = value;
				}
			}

			public RotateSubcommand(uint index, double speed, bool clockwise)
				: base(index)
			{
				Speed = speed;
				Clockwise = clockwise;
			}
		}

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public List<RotateSubcommand> Rotations;

		public static RotateCmd Create(double speed, bool clockwise, uint cmdCount)
		{
			return Create(uint.MaxValue, 1u, Enumerable.Repeat(new RotateCommand(speed, clockwise), (int)cmdCount));
		}

		public static RotateCmd Create(IEnumerable<RotateCommand> cmds)
		{
			return Create(uint.MaxValue, 1u, cmds);
		}

		public static RotateCmd Create(uint deviceIndex, uint msgId, double speed, bool clockwise, uint cmdCount)
		{
			return Create(deviceIndex, msgId, Enumerable.Repeat(new RotateCommand(speed, clockwise), (int)cmdCount));
		}

		public static RotateCmd Create(uint deviceIndex, uint msgId, IEnumerable<RotateCommand> cmds)
		{
			List<RotateSubcommand> list = new List<RotateSubcommand>(cmds.Count());
			uint num = 0u;
			foreach (RotateCommand cmd in cmds)
			{
				list.Add(new RotateSubcommand(num, cmd.speed, cmd.clockwise));
				num++;
			}
			return new RotateCmd(deviceIndex, list, msgId);
		}

		[JsonConstructor]
		public RotateCmd(uint deviceIndex, List<RotateSubcommand> rotations, uint id = 1u)
			: base(id, deviceIndex)
		{
			Rotations = rotations;
		}

		public RotateCmd(List<RotateSubcommand> rotations)
			: this(uint.MaxValue, rotations)
		{
		}
	}
	[ButtplugMessageMetadata("LinearCmd")]
	public class LinearCmd : ButtplugDeviceMessage
	{
		public class VectorCommand
		{
			public readonly double position;

			public readonly uint duration;

			public VectorCommand(double position, uint duration)
			{
				this.position = position;
				this.duration = duration;
			}
		}

		public class VectorSubcommand : GenericMessageSubcommand
		{
			private double _positionImpl;

			[JsonProperty(/*Could not decode attribute arguments.*/)]
			public uint Duration;

			[JsonProperty(/*Could not decode attribute arguments.*/)]
			public double Position
			{
				get
				{
					return _positionImpl;
				}
				set
				{
					if (value < 0.0)
					{
						throw new ArgumentException("LinearCmd Speed cannot be less than 0!");
					}
					if (value > 1.0)
					{
						throw new ArgumentException("LinearCmd Speed cannot be greater than 1!");
					}
					_positionImpl = value;
				}
			}

			public VectorSubcommand(uint index, uint duration, double position)
				: base(index)
			{
				Duration = duration;
				Position = position;
			}
		}

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public List<VectorSubcommand> Vectors;

		public static LinearCmd Create(uint duration, double position, uint cmdCount)
		{
			return Create(uint.MaxValue, 1u, Enumerable.Repeat(new VectorCommand(position, duration), (int)cmdCount));
		}

		public static LinearCmd Create(uint deviceIndex, uint msgId, uint duration, double position, uint cmdCount)
		{
			return Create(deviceIndex, msgId, Enumerable.Repeat(new VectorCommand(position, duration), (int)cmdCount));
		}

		public static LinearCmd Create(IEnumerable<VectorCommand> cmds)
		{
			return Create(uint.MaxValue, 1u, cmds);
		}

		public static LinearCmd Create(uint deviceIndex, uint msgId, IEnumerable<VectorCommand> cmds)
		{
			List<VectorSubcommand> list = new List<VectorSubcommand>(cmds.Count());
			uint num = 0u;
			foreach (VectorCommand cmd in cmds)
			{
				list.Add(new VectorSubcommand(num, cmd.duration, cmd.position));
				num++;
			}
			return new LinearCmd(deviceIndex, list, msgId);
		}

		[JsonConstructor]
		public LinearCmd(uint deviceIndex, List<VectorSubcommand> vectors, uint id = 1u)
			: base(id, deviceIndex)
		{
			Vectors = vectors;
		}

		public LinearCmd(List<VectorSubcommand> vectors)
			: this(uint.MaxValue, vectors)
		{
		}
	}
	[ButtplugMessageMetadata("StopDeviceCmd")]
	public class StopDeviceCmd : ButtplugDeviceMessage
	{
		public StopDeviceCmd(uint deviceIndex = uint.MaxValue, uint id = 1u)
			: base(id, deviceIndex)
		{
		}
	}
	[ButtplugMessageMetadata("StopAllDevices")]
	public class StopAllDevices : ButtplugMessage
	{
		public StopAllDevices(uint id = 1u)
			: base(id)
		{
		}
	}
	[ButtplugMessageMetadata("SensorReadCmd")]
	public class SensorReadCmd : ButtplugDeviceMessage
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public uint SensorIndex;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public SensorType SensorType;

		[JsonConstructor]
		public SensorReadCmd(uint deviceIndex, uint sensorIndex, SensorType sensorType, uint id = 1u)
			: base(id, deviceIndex)
		{
			SensorIndex = sensorIndex;
			SensorType = sensorType;
		}

		public SensorReadCmd(uint sensorIndex, SensorType sensorType)
			: this(uint.MaxValue, sensorIndex, sensorType)
		{
		}
	}
	[ButtplugMessageMetadata("SensorReading")]
	public class SensorReading : ButtplugDeviceMessage
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly uint SensorIndex;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly SensorType SensorType;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public readonly List<int> data;
	}
}
namespace Buttplug.Client
{
	public class ButtplugClient : IDisposable, IAsyncDisposable
	{
		protected Timer _pingTimer;

		internal ButtplugClientMessageHandler _handler;

		private readonly ConcurrentDictionary<uint, ButtplugClientDevice> _devices = new ConcurrentDictionary<uint, ButtplugClientDevice>();

		private IButtplugClientConnector _connector;

		public string Name { get; }

		public ButtplugClientDevice[] Devices => _devices.Values.ToArray();

		public bool Connected => _connector?.Connected ?? false;

		public event EventHandler<DeviceAddedEventArgs> DeviceAdded;

		public event EventHandler<DeviceRemovedEventArgs> DeviceRemoved;

		public event EventHandler<ButtplugExceptionEventArgs> ErrorReceived;

		public event EventHandler ScanningFinished;

		public event EventHandler PingTimeout;

		public event EventHandler ServerDisconnect;

		public ButtplugClient(string clientName)
		{
			Name = clientName;
		}

		public async Task ConnectAsync(IButtplugClientConnector connector, CancellationToken token = default(CancellationToken))
		{
			if (Connected)
			{
				throw new ButtplugHandshakeException("Client already connected to a server.");
			}
			ButtplugUtils.ArgumentNotNull(connector, "connector");
			_connector = connector;
			_connector.Disconnected += delegate(object obj, EventArgs eventArgs)
			{
				this.ServerDisconnect?.Invoke(obj, eventArgs);
			};
			_connector.InvalidMessageReceived += ConnectorErrorHandler;
			_connector.MessageReceived += MessageReceivedHandler;
			_devices.Clear();
			_handler = new ButtplugClientMessageHandler(connector);
			await _connector.ConnectAsync(token).ConfigureAwait(continueOnCapturedContext: false);
			ButtplugMessage res = await _handler.SendMessageAsync(new RequestServerInfo(Name), token).ConfigureAwait(continueOnCapturedContext: false);
			if (!(res is ServerInfo si))
			{
				if (res is Error e)
				{
					await DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false);
					throw ButtplugException.FromError(e);
				}
				await DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false);
				throw new ButtplugHandshakeException("Unrecognized message " + res.Name + " during handshake", res.Id);
			}
			if (si.MaxPingTime != 0)
			{
				_pingTimer?.Dispose();
				_pingTimer = new Timer(OnPingTimer, null, 0, Convert.ToInt32(Math.Round((double)si.MaxPingTime / 2.0, 0)));
			}
			if (si.MessageVersion < 3)
			{
				await DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false);
				throw new ButtplugHandshakeException($"Buttplug Server's schema version ({si.MessageVersion}) is less than the client's ({3u}). A newer server is required.", res.Id);
			}
			ButtplugMessage resp = await _handler.SendMessageAsync(new RequestDeviceList()).ConfigureAwait(continueOnCapturedContext: false);
			if (resp is DeviceList deviceList)
			{
				DeviceMessageInfo[] devices = deviceList.Devices;
				foreach (DeviceMessageInfo deviceMessageInfo in devices)
				{
					if (!_devices.ContainsKey(deviceMessageInfo.DeviceIndex))
					{
						ButtplugClientDevice buttplugClientDevice = new ButtplugClientDevice(_handler, deviceMessageInfo);
						_devices[deviceMessageInfo.DeviceIndex] = buttplugClientDevice;
						this.DeviceAdded?.Invoke(this, new DeviceAddedEventArgs(buttplugClientDevice));
					}
				}
				return;
			}
			await DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false);
			if (resp is Error msg)
			{
				throw ButtplugException.FromError(msg);
			}
			throw new ButtplugHandshakeException("Received unknown response to DeviceList handshake query");
		}

		public async Task DisconnectAsync()
		{
			if (Connected)
			{
				_connector.MessageReceived -= MessageReceivedHandler;
				await _connector.DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false);
				this.ServerDisconnect?.Invoke(this, EventArgs.Empty);
			}
		}

		public async Task StartScanningAsync(CancellationToken token = default(CancellationToken))
		{
			await _handler.SendMessageExpectOk(new StartScanning(), token).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task StopScanningAsync(CancellationToken token = default(CancellationToken))
		{
			await _handler.SendMessageExpectOk(new StopScanning(), token).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task StopAllDevicesAsync(CancellationToken token = default(CancellationToken))
		{
			await _handler.SendMessageExpectOk(new StopAllDevices(), token).ConfigureAwait(continueOnCapturedContext: false);
		}

		private void ConnectorErrorHandler(object sender, ButtplugExceptionEventArgs exception)
		{
			this.ErrorReceived?.Invoke(this, exception);
		}

		private async void MessageReceivedHandler(object sender, MessageReceivedEventArgs args)
		{
			ButtplugMessage message = args.Message;
			if (!(message is DeviceAdded deviceAdded))
			{
				ButtplugClientDevice value;
				if (!(message is DeviceRemoved deviceRemoved))
				{
					if (!(message is ScanningFinished))
					{
						if (message is Error error)
						{
							this.ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(ButtplugException.FromError(error)));
							if (error.ErrorCode == Error.ErrorClass.ERROR_PING)
							{
								this.PingTimeout?.Invoke(this, EventArgs.Empty);
								await DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false);
							}
						}
						else
						{
							this.ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(new ButtplugMessageException($"Got unhandled message: {message}", message.Id)));
						}
					}
					else
					{
						this.ScanningFinished?.Invoke(this, EventArgs.Empty);
					}
				}
				else if (!_devices.ContainsKey(deviceRemoved.DeviceIndex))
				{
					this.ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(new ButtplugDeviceException("Got device removed message for unknown device.", message.Id)));
				}
				else if (_devices.TryRemove(deviceRemoved.DeviceIndex, out value))
				{
					this.DeviceRemoved?.Invoke(this, new DeviceRemovedEventArgs(value));
				}
			}
			else
			{
				ButtplugClientDevice dev = new ButtplugClientDevice(_handler, deviceAdded);
				_devices.AddOrUpdate(deviceAdded.DeviceIndex, dev, (uint u, ButtplugClientDevice device) => dev);
				this.DeviceAdded?.Invoke(this, new DeviceAddedEventArgs(dev));
			}
		}

		private async void OnPingTimer(object state)
		{
			try
			{
				await _handler.SendMessageExpectOk(new Ping()).ConfigureAwait(continueOnCapturedContext: false);
			}
			catch (Exception inner)
			{
				this.ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(new ButtplugPingException("Exception thrown during ping update", 0u, inner)));
				await DisconnectAsync().ConfigureAwait(continueOnCapturedContext: false);
			}
		}

		protected virtual void Dispose(bool disposing)
		{
			DisconnectAsync().GetAwaiter().GetResult();
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		protected virtual async ValueTask DisposeAsync(bool disposing)
		{
			await DisconnectAsync();
		}

		public async ValueTask DisposeAsync()
		{
			await DisposeAsync(disposing: true);
			GC.SuppressFinalize(this);
		}
	}
	public class ButtplugClientConnectorException : ButtplugException
	{
		public ButtplugClientConnectorException(string message, Exception inner = null)
			: base(message, Error.ErrorClass.ERROR_UNKNOWN, 0u, inner)
		{
		}
	}
	public class ButtplugClientDevice
	{
		private readonly ButtplugClientMessageHandler _handler;

		public uint Index { get; }

		public string Name { get; }

		public string DisplayName { get; }

		public uint MessageTimingGap { get; }

		public DeviceMessageAttributes MessageAttributes { get; }

		public List<GenericDeviceMessageAttributes> VibrateAttributes => GenericAcutatorAttributes(ActuatorType.Vibrate);

		public List<GenericDeviceMessageAttributes> OscillateAttributes => GenericAcutatorAttributes(ActuatorType.Oscillate);

		public List<GenericDeviceMessageAttributes> RotateAttributes
		{
			get
			{
				if (MessageAttributes.RotateCmd != null)
				{
					return MessageAttributes.RotateCmd.ToList();
				}
				return Enumerable.Empty<GenericDeviceMessageAttributes>().ToList();
			}
		}

		public List<GenericDeviceMessageAttributes> LinearAttributes
		{
			get
			{
				if (MessageAttributes.LinearCmd != null)
				{
					return MessageAttributes.LinearCmd.ToList();
				}
				return Enumerable.Empty<GenericDeviceMessageAttributes>().ToList();
			}
		}

		public bool HasBattery => SensorReadAttributes(SensorType.Battery).Any();

		internal ButtplugClientDevice(ButtplugClientMessageHandler handler, IButtplugDeviceInfoMessage devInfo)
			: this(handler, devInfo.DeviceIndex, devInfo.DeviceName, devInfo.DeviceMessages, devInfo.DeviceDisplayName, devInfo.DeviceMessageTimingGap)
		{
			ButtplugUtils.ArgumentNotNull(devInfo, "devInfo");
		}

		internal ButtplugClientDevice(ButtplugClientMessageHandler handler, uint index, string name, DeviceMessageAttributes messages, string displayName, uint messageTimingGap)
		{
			ButtplugUtils.ArgumentNotNull(handler, "handler");
			_handler = handler;
			Index = index;
			Name = name;
			MessageAttributes = messages;
			DisplayName = displayName;
			MessageTimingGap = messageTimingGap;
		}

		public List<GenericDeviceMessageAttributes> GenericAcutatorAttributes(ActuatorType actuator)
		{
			if (MessageAttributes.ScalarCmd != null)
			{
				return MessageAttributes.ScalarCmd.Where((GenericDeviceMessageAttributes x) => x.ActuatorType == actuator).ToList();
			}
			return Enumerable.Empty<GenericDeviceMessageAttributes>().ToList();
		}

		public async Task ScalarAsync(ScalarCmd.ScalarSubcommand command)
		{
			List<ScalarCmd.ScalarSubcommand> scalars = new List<ScalarCmd.ScalarSubcommand>();
			GenericAcutatorAttributes(command.ActuatorType).ForEach(delegate(GenericDeviceMessageAttributes x)
			{
				scalars.Add(new ScalarCmd.ScalarSubcommand(x.Index, command.Scalar, command.ActuatorType));
			});
			if (!scalars.Any())
			{
				throw new ButtplugDeviceException("Scalar command for device " + Name + " did not generate any commands. Are you sure the device supports the ActuatorType sent?");
			}
			await _handler.SendMessageExpectOk(new ScalarCmd(Index, scalars)).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task ScalarAsync(List<ScalarCmd.ScalarSubcommand> command)
		{
			if (!command.Any())
			{
				throw new ArgumentException("Command List for ScalarAsync must have at least 1 command.");
			}
			await _handler.SendMessageExpectOk(new ScalarCmd(Index, command)).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task VibrateAsync(double speed)
		{
			await ScalarAsync(new ScalarCmd.ScalarSubcommand(uint.MaxValue, speed, ActuatorType.Vibrate));
		}

		public async Task VibrateAsync(IEnumerable<double> cmds)
		{
			List<GenericDeviceMessageAttributes> vibrateAttributes = VibrateAttributes;
			if (cmds.Count() > vibrateAttributes.Count())
			{
				throw new ButtplugDeviceException($"Device {Name} only has {vibrateAttributes.Count()} vibrators, but {cmds.Count()} commands given.");
			}
			await ScalarAsync(vibrateAttributes.Select((GenericDeviceMessageAttributes x, int i) => new ScalarCmd.ScalarSubcommand(x.Index, cmds.ElementAt(i), ActuatorType.Vibrate)).ToList()).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task VibrateAsync(IEnumerable<ScalarCmd.ScalarCommand> cmds)
		{
			await ScalarAsync(cmds.Select((ScalarCmd.ScalarCommand x) => new ScalarCmd.ScalarSubcommand(x.index, x.scalar, ActuatorType.Vibrate)).ToList()).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task OscillateAsync(double speed)
		{
			await ScalarAsync(new ScalarCmd.ScalarSubcommand(uint.MaxValue, speed, ActuatorType.Oscillate));
		}

		public async Task OscillateAsync(IEnumerable<double> cmds)
		{
			List<GenericDeviceMessageAttributes> oscillateAttributes = OscillateAttributes;
			if (cmds.Count() > oscillateAttributes.Count())
			{
				throw new ButtplugDeviceException($"Device {Name} only has {oscillateAttributes.Count()} vibrators, but {cmds.Count()} commands given.");
			}
			await ScalarAsync(oscillateAttributes.Select((GenericDeviceMessageAttributes x, int i) => new ScalarCmd.ScalarSubcommand(x.Index, cmds.ElementAt(i), ActuatorType.Oscillate)).ToList()).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task OscillateAsync(IEnumerable<ScalarCmd.ScalarCommand> cmds)
		{
			await ScalarAsync(cmds.Select((ScalarCmd.ScalarCommand x) => new ScalarCmd.ScalarSubcommand(x.index, x.scalar, ActuatorType.Oscillate)).ToList()).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task RotateAsync(double speed, bool clockwise)
		{
			if (!RotateAttributes.Any())
			{
				throw new ButtplugDeviceException("Device " + Name + " does not support rotation");
			}
			RotateCmd rotateCmd = RotateCmd.Create(speed, clockwise, (uint)RotateAttributes.Count);
			rotateCmd.DeviceIndex = Index;
			await _handler.SendMessageExpectOk(rotateCmd).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task RotateAsync(IEnumerable<RotateCmd.RotateCommand> cmds)
		{
			if (!RotateAttributes.Any())
			{
				throw new ButtplugDeviceException("Device " + Name + " does not support rotation");
			}
			RotateCmd rotateCmd = RotateCmd.Create(cmds);
			rotateCmd.DeviceIndex = Index;
			await _handler.SendMessageExpectOk(rotateCmd).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task LinearAsync(uint duration, double position)
		{
			if (!LinearAttributes.Any())
			{
				throw new ButtplugDeviceException("Device " + Name + " does not support linear position");
			}
			LinearCmd linearCmd = LinearCmd.Create(duration, position, (uint)LinearAttributes.Count);
			linearCmd.DeviceIndex = Index;
			await _handler.SendMessageExpectOk(linearCmd).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task LinearAsync(IEnumerable<LinearCmd.VectorCommand> cmds)
		{
			if (!LinearAttributes.Any())
			{
				throw new ButtplugDeviceException("Device " + Name + " does not support linear position");
			}
			LinearCmd linearCmd = LinearCmd.Create(cmds);
			linearCmd.DeviceIndex = Index;
			await _handler.SendMessageExpectOk(linearCmd).ConfigureAwait(continueOnCapturedContext: false);
		}

		public List<SensorDeviceMessageAttributes> SensorReadAttributes(SensorType sensor)
		{
			if (MessageAttributes.SensorReadCmd != null)
			{
				return MessageAttributes.SensorReadCmd.Where((SensorDeviceMessageAttributes x) => x.SensorType == sensor).ToList();
			}
			return Enumerable.Empty<SensorDeviceMessageAttributes>().ToList();
		}

		public async Task<double> BatteryAsync()
		{
			if (!HasBattery)
			{
				throw new ButtplugDeviceException("Device " + Name + " does not have battery capabilities.");
			}
			ButtplugMessage buttplugMessage = await _handler.SendMessageAsync(new SensorReadCmd(Index, SensorReadAttributes(SensorType.Battery).ElementAt(0).Index, SensorType.Battery)).ConfigureAwait(continueOnCapturedContext: false);
			if (!(buttplugMessage is SensorReading sensorReading))
			{
				if (buttplugMessage is Error msg)
				{
					throw ButtplugException.FromError(msg);
				}
				throw new ButtplugMessageException("Message type " + buttplugMessage.Name + " not handled by BatteryAsync", buttplugMessage.Id);
			}
			return (double)sensorReading.data[0] / 100.0;
		}

		public async Task Stop()
		{
			await _handler.SendMessageExpectOk(new StopDeviceCmd(Index)).ConfigureAwait(continueOnCapturedContext: false);
		}
	}
	internal class ButtplugClientMessageHandler
	{
		private IButtplugClientConnector _connector;

		internal ButtplugClientMessageHandler(IButtplugClientConnector connector)
		{
			_connector = connector;
		}

		public async Task<ButtplugMessage> SendMessageAsync(ButtplugMessage msg, CancellationToken token = default(CancellationToken))
		{
			if (!_connector.Connected)
			{
				throw new ButtplugClientConnectorException("Client not connected.");
			}
			return await _connector.SendAsync(msg, token).ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task SendMessageExpectOk(ButtplugMessage msg, CancellationToken token = default(CancellationToken))
		{
			ButtplugMessage buttplugMessage = await SendMessageAsync(msg, token).ConfigureAwait(continueOnCapturedContext: false);
			if (!(buttplugMessage is Ok))
			{
				if (buttplugMessage is Error msg2)
				{
					throw ButtplugException.FromError(msg2);
				}
				throw new ButtplugMessageException("Message type " + msg.Name + " not handled by SendMessageExpectOk", msg.Id);
			}
		}
	}
	public class ButtplugConnectorJSONParser
	{
		private readonly ButtplugJsonMessageParser _parser = new ButtplugJsonMessageParser();

		public string Serialize(ButtplugMessage msg)
		{
			return _parser.Serialize(msg);
		}

		public string Serialize(ButtplugMessage[] msgs)
		{
			return _parser.Serialize(msgs);
		}

		public IEnumerable<ButtplugMessage> Deserialize(string msg)
		{
			return _parser.Deserialize(msg);
		}
	}
	public class ButtplugConnectorMessageSorter : IDisposable
	{
		private int _counter;

		private readonly ConcurrentDictionary<uint, TaskCompletionSource<ButtplugMessage>> _waitingMsgs = new ConcurrentDictionary<uint, TaskCompletionSource<ButtplugMessage>>();

		public uint NextMsgId => Convert.ToUInt32(Interlocked.Increment(ref _counter));

		public Task<ButtplugMessage> PrepareMessage(ButtplugMessage msg)
		{
			msg.Id = NextMsgId;
			TaskCompletionSource<ButtplugMessage> taskCompletionSource = new TaskCompletionSource<ButtplugMessage>();
			_waitingMsgs.TryAdd(msg.Id, taskCompletionSource);
			return taskCompletionSource.Task;
		}

		public void CheckMessage(ButtplugMessage msg)
		{
			if (msg.Id == 0)
			{
				throw new ButtplugMessageException("Cannot sort message with System ID", msg.Id);
			}
			if (!_waitingMsgs.TryRemove(msg.Id, out var value))
			{
				throw new ButtplugMessageException("Message with non-matching ID received.", msg.Id);
			}
			if (msg is Error msg2)
			{
				value.SetException(ButtplugException.FromError(msg2));
			}
			else
			{
				value.SetResult(msg);
			}
		}

		protected virtual void Dispose(bool disposing)
		{
			foreach (TaskCompletionSource<ButtplugMessage> value in _waitingMsgs.Values)
			{
				value.TrySetException(new Exception("Sorter has been destroyed with live tasks still in queue."));
			}
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}
	}
	public class ReturnMessage
	{
		public readonly string Message;

		public readonly Task<ButtplugMessage> Promise;

		public ReturnMessage(string message, Task<ButtplugMessage> promise)
		{
			Message = message;
			Promise = promise;
		}
	}
	public class ButtplugRemoteJSONConnector : IDisposable
	{
		private readonly ButtplugConnectorJSONParser _jsonSerializer = new ButtplugConnectorJSONParser();

		private readonly ButtplugConnectorMessageSorter _msgSorter = new ButtplugConnectorMessageSorter();

		public event EventHandler<MessageReceivedEventArgs> MessageReceived;

		public event EventHandler<ButtplugExceptionEventArgs> InvalidMessageReceived;

		public ReturnMessage PrepareMessage(ButtplugMessage msg)
		{
			Task<ButtplugMessage> promise = _msgSorter.PrepareMessage(msg);
			return new ReturnMessage(_jsonSerializer.Serialize(msg), promise);
		}

		protected void ReceiveMessages(string jSONMsg)
		{
			IEnumerable<ButtplugMessage> enumerable;
			try
			{
				enumerable = _jsonSerializer.Deserialize(jSONMsg);
			}
			catch (ButtplugMessageException ex)
			{
				this.InvalidMessageReceived?.Invoke(this, new ButtplugExceptionEventArgs(ex));
				return;
			}
			foreach (ButtplugMessage item in enumerable)
			{
				if (item.Id == 0)
				{
					this.MessageReceived?.Invoke(this, new MessageReceivedEventArgs(item));
					continue;
				}
				try
				{
					_msgSorter.CheckMessage(item);
				}
				catch (ButtplugMessageException ex2)
				{
					this.InvalidMessageReceived?.Invoke(this, new ButtplugExceptionEventArgs(ex2));
				}
			}
		}

		protected virtual void Dispose(bool disposing)
		{
			_msgSorter.Dispose();
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}
	}
	public class ButtplugWebsocketConnector : ButtplugRemoteJSONConnector, IButtplugClientConnector
	{
		private ClientWebSocket _wsClient;

		private readonly SynchronizationContext _owningDispatcher = SynchronizationContext.Current ?? new SynchronizationContext();

		private readonly Uri _uri;

		private Task _readTask;

		public bool Connected
		{
			get
			{
				ClientWebSocket wsClient = _wsClient;
				if (wsClient == null)
				{
					return false;
				}
				return wsClient.State == WebSocketState.Open;
			}
		}

		public event EventHandler Disconnected;

		public ButtplugWebsocketConnector(Uri uri)
		{
			_uri = uri;
		}

		public async Task ConnectAsync(CancellationToken token = default(CancellationToken))
		{
			if (_wsClient != null)
			{
				throw new ButtplugHandshakeException("Websocket connector is already connected.");
			}
			try
			{
				_wsClient = new ClientWebSocket();
				await _wsClient.ConnectAsync(_uri, token).ConfigureAwait(continueOnCapturedContext: false);
			}
			catch (Exception inner)
			{
				throw new ButtplugClientConnectorException("Websocket Connection Exception! See Inner Exception", inner);
			}
			_readTask = Task.Run(async delegate
			{
				await RunClientLoop(token).ConfigureAwait(continueOnCapturedContext: false);
			}, token);
		}

		public async Task DisconnectAsync(CancellationToken token = default(CancellationToken))
		{
			if (_wsClient != null && (_wsClient.State == WebSocketState.Connecting || _wsClient.State == WebSocketState.Open))
			{
				await _wsClient.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false);
			}
			_wsClient?.Dispose();
			_wsClient = null;
			await _readTask.ConfigureAwait(continueOnCapturedContext: false);
		}

		public async Task<ButtplugMessage> SendAsync(ButtplugMessage msg, CancellationToken cancellationToken)
		{
			if (_wsClient == null)
			{
				throw new ButtplugException("Cannot send messages while disconnected", Error.ErrorClass.ERROR_MSG);
			}
			ReturnMessage returnMsg = PrepareMessage(msg);
			await _wsClient.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(returnMsg.Message)), WebSocketMessageType.Text, endOfMessage: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
			return await returnMsg.Promise.ConfigureAwait(continueOnCapturedContext: false);
		}

		private async Task RunClientLoop(CancellationToken token)
		{
			try
			{
				new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false);
				byte[] buff = new byte[2048];
				while (Connected && !token.IsCancellationRequested)
				{
					WebSocketReceiveResult webSocketReceiveResult = await _wsClient.ReceiveAsync(new ArraySegment<byte>(buff), token).ConfigureAwait(continueOnCapturedContext: false);
					if (webSocketReceiveResult.MessageType == WebSocketMessageType.Text)
					{
						string @string = Encoding.Default.GetString(buff, 0, webSocketReceiveResult.Count);
						ReceiveMessages(@string);
					}
				}
			}
			catch (Exception)
			{
			}
			finally
			{
				if (_wsClient != null)
				{
					_wsClient.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", token).Dispose();
					_wsClient = null;
				}
				_owningDispatcher.Send(delegate
				{
					Dispose();
				}, null);
				_owningDispatcher.Send(delegate
				{
					this.Disconnected?.Invoke(this, EventArgs.Empty);
				}, null);
			}
		}
	}
	public class DeviceAddedEventArgs
	{
		public readonly ButtplugClientDevice Device;

		public DeviceAddedEventArgs(ButtplugClientDevice device)
		{
			Device = device;
		}
	}
	public class DeviceRemovedEventArgs
	{
		public readonly ButtplugClientDevice Device;

		public DeviceRemovedEventArgs(ButtplugClientDevice device)
		{
			Device = device;
		}
	}
	public interface IButtplugClientConnector
	{
		bool Connected { get; }

		event EventHandler<MessageReceivedEventArgs> MessageReceived;

		event EventHandler<ButtplugExceptionEventArgs> InvalidMessageReceived;

		event EventHandler Disconnected;

		Task ConnectAsync(CancellationToken token = default(CancellationToken));

		Task DisconnectAsync(CancellationToken token = default(CancellationToken));

		Task<ButtplugMessage> SendAsync(ButtplugMessage msg, CancellationToken token = default(CancellationToken));
	}
}

core/Microsoft.CSharp.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics.Hashing;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;
using System.Text;
using System.Threading;
using FxResources.Microsoft.CSharp;
using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Semantics;
using Microsoft.CSharp.RuntimeBinder.Syntax;
using Microsoft.CodeAnalysis;

[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyDefaultAlias("Microsoft.CSharp")]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyDescription("Microsoft.CSharp")]
[assembly: AssemblyFileVersion("4.700.19.56404")]
[assembly: AssemblyInformationalVersion("3.1.0+0f7f38c4fd323b26da10cce95f857f77f0f09b48")]
[assembly: AssemblyProduct("Microsoft® .NET Core")]
[assembly: AssemblyTitle("Microsoft.CSharp")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: CLSCompliant(true)]
[assembly: AssemblyVersion("4.0.5.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[Microsoft.CodeAnalysis.Embedded]
	[CompilerGenerated]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
}
namespace FxResources.Microsoft.CSharp
{
	internal static class SR
	{
	}
}
namespace System
{
	internal static class SR
	{
		private static ResourceManager s_resourceManager;

		internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR)));

		internal static string InternalCompilerError => GetResourceString("InternalCompilerError");

		internal static string BindPropertyFailedMethodGroup => GetResourceString("BindPropertyFailedMethodGroup");

		internal static string BindPropertyFailedEvent => GetResourceString("BindPropertyFailedEvent");

		internal static string BindInvokeFailedNonDelegate => GetResourceString("BindInvokeFailedNonDelegate");

		internal static string NullReferenceOnMemberException => GetResourceString("NullReferenceOnMemberException");

		internal static string BindCallToConditionalMethod => GetResourceString("BindCallToConditionalMethod");

		internal static string BindToVoidMethodButExpectResult => GetResourceString("BindToVoidMethodButExpectResult");

		internal static string EmptyDynamicView => GetResourceString("EmptyDynamicView");

		internal static string GetValueonWriteOnlyProperty => GetResourceString("GetValueonWriteOnlyProperty");

		internal static string BadBinaryOps => GetResourceString("BadBinaryOps");

		internal static string BadIndexLHS => GetResourceString("BadIndexLHS");

		internal static string BadIndexCount => GetResourceString("BadIndexCount");

		internal static string BadUnaryOp => GetResourceString("BadUnaryOp");

		internal static string NoImplicitConv => GetResourceString("NoImplicitConv");

		internal static string NoExplicitConv => GetResourceString("NoExplicitConv");

		internal static string ConstOutOfRange => GetResourceString("ConstOutOfRange");

		internal static string AmbigBinaryOps => GetResourceString("AmbigBinaryOps");

		internal static string AmbigUnaryOp => GetResourceString("AmbigUnaryOp");

		internal static string ValueCantBeNull => GetResourceString("ValueCantBeNull");

		internal static string NoSuchMember => GetResourceString("NoSuchMember");

		internal static string ObjectRequired => GetResourceString("ObjectRequired");

		internal static string AmbigCall => GetResourceString("AmbigCall");

		internal static string BadAccess => GetResourceString("BadAccess");

		internal static string AssgLvalueExpected => GetResourceString("AssgLvalueExpected");

		internal static string NoConstructors => GetResourceString("NoConstructors");

		internal static string PropertyLacksGet => GetResourceString("PropertyLacksGet");

		internal static string ObjectProhibited => GetResourceString("ObjectProhibited");

		internal static string AssgReadonly => GetResourceString("AssgReadonly");

		internal static string AssgReadonlyStatic => GetResourceString("AssgReadonlyStatic");

		internal static string AssgReadonlyProp => GetResourceString("AssgReadonlyProp");

		internal static string UnsafeNeeded => GetResourceString("UnsafeNeeded");

		internal static string BadBoolOp => GetResourceString("BadBoolOp");

		internal static string MustHaveOpTF => GetResourceString("MustHaveOpTF");

		internal static string ConstOutOfRangeChecked => GetResourceString("ConstOutOfRangeChecked");

		internal static string AmbigMember => GetResourceString("AmbigMember");

		internal static string NoImplicitConvCast => GetResourceString("NoImplicitConvCast");

		internal static string InaccessibleGetter => GetResourceString("InaccessibleGetter");

		internal static string InaccessibleSetter => GetResourceString("InaccessibleSetter");

		internal static string BadArity => GetResourceString("BadArity");

		internal static string TypeArgsNotAllowed => GetResourceString("TypeArgsNotAllowed");

		internal static string HasNoTypeVars => GetResourceString("HasNoTypeVars");

		internal static string NewConstraintNotSatisfied => GetResourceString("NewConstraintNotSatisfied");

		internal static string GenericConstraintNotSatisfiedRefType => GetResourceString("GenericConstraintNotSatisfiedRefType");

		internal static string GenericConstraintNotSatisfiedNullableEnum => GetResourceString("GenericConstraintNotSatisfiedNullableEnum");

		internal static string GenericConstraintNotSatisfiedNullableInterface => GetResourceString("GenericConstraintNotSatisfiedNullableInterface");

		internal static string GenericConstraintNotSatisfiedValType => GetResourceString("GenericConstraintNotSatisfiedValType");

		internal static string CantInferMethTypeArgs => GetResourceString("CantInferMethTypeArgs");

		internal static string RefConstraintNotSatisfied => GetResourceString("RefConstraintNotSatisfied");

		internal static string ValConstraintNotSatisfied => GetResourceString("ValConstraintNotSatisfied");

		internal static string AmbigUDConv => GetResourceString("AmbigUDConv");

		internal static string BindToBogus => GetResourceString("BindToBogus");

		internal static string CantCallSpecialMethod => GetResourceString("CantCallSpecialMethod");

		internal static string ConvertToStaticClass => GetResourceString("ConvertToStaticClass");

		internal static string IncrementLvalueExpected => GetResourceString("IncrementLvalueExpected");

		internal static string BadArgCount => GetResourceString("BadArgCount");

		internal static string BadArgTypes => GetResourceString("BadArgTypes");

		internal static string BadProtectedAccess => GetResourceString("BadProtectedAccess");

		internal static string BindToBogusProp2 => GetResourceString("BindToBogusProp2");

		internal static string BindToBogusProp1 => GetResourceString("BindToBogusProp1");

		internal static string BadDelArgCount => GetResourceString("BadDelArgCount");

		internal static string BadDelArgTypes => GetResourceString("BadDelArgTypes");

		internal static string BadCtorArgCount => GetResourceString("BadCtorArgCount");

		internal static string NonInvocableMemberCalled => GetResourceString("NonInvocableMemberCalled");

		internal static string BadNamedArgument => GetResourceString("BadNamedArgument");

		internal static string BadNamedArgumentForDelegateInvoke => GetResourceString("BadNamedArgumentForDelegateInvoke");

		internal static string DuplicateNamedArgument => GetResourceString("DuplicateNamedArgument");

		internal static string NamedArgumentUsedInPositional => GetResourceString("NamedArgumentUsedInPositional");

		internal static string TypeArgumentRequiredForStaticCall => GetResourceString("TypeArgumentRequiredForStaticCall");

		internal static string DynamicArgumentNeedsValue => GetResourceString("DynamicArgumentNeedsValue");

		internal static string BadNonTrailingNamedArgument => GetResourceString("BadNonTrailingNamedArgument");

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool UsingResourceKeys()
		{
			return false;
		}

		internal static string GetResourceString(string resourceKey, string defaultString = null)
		{
			if (UsingResourceKeys())
			{
				return defaultString ?? resourceKey;
			}
			string text = null;
			try
			{
				text = ResourceManager.GetString(resourceKey);
			}
			catch (MissingManifestResourceException)
			{
			}
			if (defaultString != null && resourceKey.Equals(text))
			{
				return defaultString;
			}
			return text;
		}

		internal static string Format(string resourceFormat, object p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(resourceFormat, p1);
		}
	}
}
namespace System.Numerics.Hashing
{
	internal static class HashHelpers
	{
		public static readonly int RandomSeed = new Random().Next(int.MinValue, int.MaxValue);

		public static int Combine(int h1, int h2)
		{
			uint num = (uint)(h1 << 5) | ((uint)h1 >> 27);
			return ((int)num + h1) ^ h2;
		}
	}
}
namespace Microsoft.CSharp.RuntimeBinder
{
	internal readonly struct ArgumentObject
	{
		internal readonly object Value;

		internal readonly CSharpArgumentInfo Info;

		internal readonly Type Type;

		public ArgumentObject(object value, CSharpArgumentInfo info, Type type)
		{
			Value = value;
			Info = info;
			Type = type;
		}
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	public static class Binder
	{
		public static CallSiteBinder BinaryOperation(CSharpBinderFlags flags, ExpressionType operation, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
		{
			bool isChecked = (flags & CSharpBinderFlags.CheckedContext) != 0;
			bool flag = (flags & CSharpBinderFlags.BinaryOperationLogical) != 0;
			CSharpBinaryOperationFlags cSharpBinaryOperationFlags = CSharpBinaryOperationFlags.None;
			if (flag)
			{
				cSharpBinaryOperationFlags |= CSharpBinaryOperationFlags.LogicalOperation;
			}
			return new CSharpBinaryOperationBinder(operation, isChecked, cSharpBinaryOperationFlags, context, argumentInfo).TryGetExisting();
		}

		public static CallSiteBinder Convert(CSharpBinderFlags flags, Type type, Type context)
		{
			CSharpConversionKind conversionKind = (((flags & CSharpBinderFlags.ConvertExplicit) != 0) ? CSharpConversionKind.ExplicitConversion : (((flags & CSharpBinderFlags.ConvertArrayIndex) != 0) ? CSharpConversionKind.ArrayCreationConversion : CSharpConversionKind.ImplicitConversion));
			bool isChecked = (flags & CSharpBinderFlags.CheckedContext) != 0;
			return new CSharpConvertBinder(type, conversionKind, isChecked, context).TryGetExisting();
		}

		public static CallSiteBinder GetIndex(CSharpBinderFlags flags, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
		{
			return new CSharpGetIndexBinder(context, argumentInfo).TryGetExisting();
		}

		public static CallSiteBinder GetMember(CSharpBinderFlags flags, string name, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
		{
			bool resultIndexed = (flags & CSharpBinderFlags.ResultIndexed) != 0;
			return new CSharpGetMemberBinder(name, resultIndexed, context, argumentInfo).TryGetExisting();
		}

		public static CallSiteBinder Invoke(CSharpBinderFlags flags, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
		{
			bool flag = (flags & CSharpBinderFlags.ResultDiscarded) != 0;
			CSharpCallFlags cSharpCallFlags = CSharpCallFlags.None;
			if (flag)
			{
				cSharpCallFlags |= CSharpCallFlags.ResultDiscarded;
			}
			return new CSharpInvokeBinder(cSharpCallFlags, context, argumentInfo).TryGetExisting();
		}

		public static CallSiteBinder InvokeMember(CSharpBinderFlags flags, string name, IEnumerable<Type> typeArguments, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
		{
			bool flag = (flags & CSharpBinderFlags.InvokeSimpleName) != 0;
			bool flag2 = (flags & CSharpBinderFlags.InvokeSpecialName) != 0;
			bool flag3 = (flags & CSharpBinderFlags.ResultDiscarded) != 0;
			CSharpCallFlags cSharpCallFlags = CSharpCallFlags.None;
			if (flag)
			{
				cSharpCallFlags |= CSharpCallFlags.SimpleNameCall;
			}
			if (flag2)
			{
				cSharpCallFlags |= CSharpCallFlags.EventHookup;
			}
			if (flag3)
			{
				cSharpCallFlags |= CSharpCallFlags.ResultDiscarded;
			}
			return new CSharpInvokeMemberBinder(cSharpCallFlags, name, context, typeArguments, argumentInfo).TryGetExisting();
		}

		public static CallSiteBinder InvokeConstructor(CSharpBinderFlags flags, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
		{
			return new CSharpInvokeConstructorBinder(CSharpCallFlags.None, context, argumentInfo).TryGetExisting();
		}

		public static CallSiteBinder IsEvent(CSharpBinderFlags flags, string name, Type context)
		{
			return new CSharpIsEventBinder(name, context).TryGetExisting();
		}

		public static CallSiteBinder SetIndex(CSharpBinderFlags flags, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
		{
			bool isCompoundAssignment = (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0;
			bool isChecked = (flags & CSharpBinderFlags.CheckedContext) != 0;
			return new CSharpSetIndexBinder(isCompoundAssignment, isChecked, context, argumentInfo).TryGetExisting();
		}

		public static CallSiteBinder SetMember(CSharpBinderFlags flags, string name, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
		{
			bool isCompoundAssignment = (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0;
			bool isChecked = (flags & CSharpBinderFlags.CheckedContext) != 0;
			return new CSharpSetMemberBinder(name, isCompoundAssignment, isChecked, context, argumentInfo).TryGetExisting();
		}

		public static CallSiteBinder UnaryOperation(CSharpBinderFlags flags, ExpressionType operation, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
		{
			bool isChecked = (flags & CSharpBinderFlags.CheckedContext) != 0;
			return new CSharpUnaryOperationBinder(operation, isChecked, context, argumentInfo).TryGetExisting();
		}
	}
	internal static class BinderEquivalence
	{
		internal class BinderEqualityComparer : IEqualityComparer<ICSharpBinder>
		{
			public bool Equals(ICSharpBinder x, ICSharpBinder y)
			{
				return x.IsEquivalentTo(y);
			}

			public int GetHashCode(ICSharpBinder obj)
			{
				return obj.GetGetBinderEquivalenceHash();
			}
		}

		private static int cachedBinderCount;

		private static readonly ConcurrentDictionary<ICSharpBinder, ICSharpBinder> binderEquivalenceCache = new ConcurrentDictionary<ICSharpBinder, ICSharpBinder>(2, 32, new BinderEqualityComparer());

		internal static T TryGetExisting<T>(this T binder) where T : ICSharpBinder
		{
			ICSharpBinder orAdd = binderEquivalenceCache.GetOrAdd(binder, binder);
			if (orAdd == (object)binder)
			{
				int num = Interlocked.Increment(ref cachedBinderCount);
				if ((uint)num > 4096u)
				{
					binderEquivalenceCache.Clear();
					cachedBinderCount = 0;
				}
			}
			return (T)orAdd;
		}
	}
	internal static class BinderHelper
	{
		private static MethodInfo s_DoubleIsNaN;

		private static MethodInfo s_SingleIsNaN;

		internal static DynamicMetaObject Bind(ICSharpBinder action, RuntimeBinder binder, DynamicMetaObject[] args, IEnumerable<CSharpArgumentInfo> arginfos, DynamicMetaObject onBindingError)
		{
			Expression[] array = new Expression[args.Length];
			BindingRestrictions bindingRestrictions = BindingRestrictions.Empty;
			ICSharpInvokeOrInvokeMemberBinder callPayload = action as ICSharpInvokeOrInvokeMemberBinder;
			ParameterExpression parameterExpression = null;
			IEnumerator<CSharpArgumentInfo> enumerator = (arginfos ?? Array.Empty<CSharpArgumentInfo>()).GetEnumerator();
			for (int i = 0; i < args.Length; i++)
			{
				DynamicMetaObject dynamicMetaObject = args[i];
				CSharpArgumentInfo cSharpArgumentInfo = (enumerator.MoveNext() ? enumerator.Current : null);
				if (i == 0 && IsIncrementOrDecrementActionOnLocal(action))
				{
					object value = dynamicMetaObject.Value;
					parameterExpression = (ParameterExpression)(array[0] = Expression.Variable((value != null) ? value.GetType() : typeof(object), "t0"));
				}
				else
				{
					array[i] = dynamicMetaObject.Expression;
				}
				BindingRestrictions restrictions = DeduceArgumentRestriction(i, callPayload, dynamicMetaObject, cSharpArgumentInfo);
				bindingRestrictions = bindingRestrictions.Merge(restrictions);
				if (cSharpArgumentInfo != null && cSharpArgumentInfo.LiteralConstant)
				{
					if (dynamicMetaObject.Value is double && double.IsNaN((double)dynamicMetaObject.Value))
					{
						MethodInfo method = s_DoubleIsNaN ?? (s_DoubleIsNaN = typeof(double).GetMethod("IsNaN"));
						Expression expression = Expression.Call(null, method, dynamicMetaObject.Expression);
						bindingRestrictions = bindingRestrictions.Merge(BindingRestrictions.GetExpressionRestriction(expression));
					}
					else if (dynamicMetaObject.Value is float && float.IsNaN((float)dynamicMetaObject.Value))
					{
						MethodInfo method2 = s_SingleIsNaN ?? (s_SingleIsNaN = typeof(float).GetMethod("IsNaN"));
						Expression expression2 = Expression.Call(null, method2, dynamicMetaObject.Expression);
						bindingRestrictions = bindingRestrictions.Merge(BindingRestrictions.GetExpressionRestriction(expression2));
					}
					else
					{
						Expression expression3 = Expression.Equal(dynamicMetaObject.Expression, Expression.Constant(dynamicMetaObject.Value, dynamicMetaObject.Expression.Type));
						restrictions = BindingRestrictions.GetExpressionRestriction(expression3);
						bindingRestrictions = bindingRestrictions.Merge(restrictions);
					}
				}
			}
			try
			{
				Expression expression4 = binder.Bind(action, array, args, out var deferredBinding);
				if (deferredBinding != null)
				{
					expression4 = ConvertResult(deferredBinding.Expression, action);
					bindingRestrictions = deferredBinding.Restrictions.Merge(bindingRestrictions);
					return new DynamicMetaObject(expression4, bindingRestrictions);
				}
				if (parameterExpression != null)
				{
					DynamicMetaObject dynamicMetaObject2 = args[0];
					expression4 = Expression.Block(new ParameterExpression[1] { parameterExpression }, Expression.Assign(parameterExpression, Expression.Convert(dynamicMetaObject2.Expression, dynamicMetaObject2.Value.GetType())), expression4, Expression.Assign(dynamicMetaObject2.Expression, Expression.Convert(parameterExpression, dynamicMetaObject2.Expression.Type)));
				}
				expression4 = ConvertResult(expression4, action);
				return new DynamicMetaObject(expression4, bindingRestrictions);
			}
			catch (RuntimeBinderException ex)
			{
				if (onBindingError != null)
				{
					return onBindingError;
				}
				return new DynamicMetaObject(Expression.Throw(Expression.New(typeof(RuntimeBinderException).GetConstructor(new Type[1] { typeof(string) }), Expression.Constant(ex.Message)), GetTypeForErrorMetaObject(action, args)), bindingRestrictions);
			}
		}

		public static void ValidateBindArgument(DynamicMetaObject argument, string paramName)
		{
			if (argument == null)
			{
				throw Error.ArgumentNull(paramName);
			}
			if (!argument.HasValue)
			{
				throw Error.DynamicArgumentNeedsValue(paramName);
			}
		}

		public static void ValidateBindArgument(DynamicMetaObject[] arguments, string paramName)
		{
			if (arguments != null)
			{
				for (int i = 0; i != arguments.Length; i++)
				{
					ValidateBindArgument(arguments[i], $"{paramName}[{i}]");
				}
			}
		}

		private static bool IsTypeOfStaticCall(int parameterIndex, ICSharpInvokeOrInvokeMemberBinder callPayload)
		{
			if (parameterIndex == 0 && callPayload != null)
			{
				return callPayload.StaticCall;
			}
			return false;
		}

		private static bool IsComObject(object obj)
		{
			if (obj != null)
			{
				return Marshal.IsComObject(obj);
			}
			return false;
		}

		private static bool IsTransparentProxy(object obj)
		{
			return false;
		}

		private static bool IsDynamicallyTypedRuntimeProxy(DynamicMetaObject argument, CSharpArgumentInfo info)
		{
			return info != null && !info.UseCompileTimeType && (IsComObject(argument.Value) || IsTransparentProxy(argument.Value));
		}

		private static BindingRestrictions DeduceArgumentRestriction(int parameterIndex, ICSharpInvokeOrInvokeMemberBinder callPayload, DynamicMetaObject argument, CSharpArgumentInfo info)
		{
			if (argument.Value != null && !IsTypeOfStaticCall(parameterIndex, callPayload) && !IsDynamicallyTypedRuntimeProxy(argument, info))
			{
				return BindingRestrictions.GetTypeRestriction(argument.Expression, argument.RuntimeType);
			}
			return BindingRestrictions.GetInstanceRestriction(argument.Expression, argument.Value);
		}

		private static Expression ConvertResult(Expression binding, ICSharpBinder action)
		{
			if (action is CSharpInvokeConstructorBinder)
			{
				return binding;
			}
			if (binding.Type == typeof(void))
			{
				if (action is ICSharpInvokeOrInvokeMemberBinder iCSharpInvokeOrInvokeMemberBinder && iCSharpInvokeOrInvokeMemberBinder.ResultDiscarded)
				{
					return Expression.Block(binding, Expression.Default(action.ReturnType));
				}
				throw Error.BindToVoidMethodButExpectResult();
			}
			if (binding.Type.IsValueType && !action.ReturnType.IsValueType)
			{
				return Expression.Convert(binding, action.ReturnType);
			}
			return binding;
		}

		private static Type GetTypeForErrorMetaObject(ICSharpBinder action, DynamicMetaObject[] args)
		{
			if (action is CSharpInvokeConstructorBinder)
			{
				return args[0].Value as Type;
			}
			return action.ReturnType;
		}

		private static bool IsIncrementOrDecrementActionOnLocal(ICSharpBinder action)
		{
			if (action is CSharpUnaryOperationBinder cSharpUnaryOperationBinder)
			{
				if (cSharpUnaryOperationBinder.Operation != ExpressionType.Increment)
				{
					return cSharpUnaryOperationBinder.Operation == ExpressionType.Decrement;
				}
				return true;
			}
			return false;
		}

		internal static T[] Cons<T>(T sourceHead, T[] sourceTail)
		{
			if (sourceTail == null || sourceTail.Length != 0)
			{
				T[] array = new T[sourceTail.Length + 1];
				array[0] = sourceHead;
				sourceTail.CopyTo(array, 1);
				return array;
			}
			return new T[1] { sourceHead };
		}

		internal static T[] Cons<T>(T sourceHead, T[] sourceMiddle, T sourceLast)
		{
			if (sourceMiddle == null || sourceMiddle.Length != 0)
			{
				T[] array = new T[sourceMiddle.Length + 2];
				array[0] = sourceHead;
				array[^1] = sourceLast;
				sourceMiddle.CopyTo(array, 1);
				return array;
			}
			return new T[2] { sourceHead, sourceLast };
		}

		internal static T[] ToArray<T>(IEnumerable<T> source)
		{
			if (source != null)
			{
				return source.ToArray();
			}
			return Array.Empty<T>();
		}

		internal static CallInfo CreateCallInfo(ref IEnumerable<CSharpArgumentInfo> argInfos, int discard)
		{
			int num = 0;
			List<string> list = new List<string>();
			CSharpArgumentInfo[] array = (CSharpArgumentInfo[])(argInfos = ToArray(argInfos));
			foreach (CSharpArgumentInfo cSharpArgumentInfo in array)
			{
				if (cSharpArgumentInfo.NamedArgument)
				{
					list.Add(cSharpArgumentInfo.Name);
				}
				num++;
			}
			return new CallInfo(num - discard, list);
		}

		internal static string GetCLROperatorName(this ExpressionType p)
		{
			return p switch
			{
				ExpressionType.Add => "op_Addition", 
				ExpressionType.Subtract => "op_Subtraction", 
				ExpressionType.Multiply => "op_Multiply", 
				ExpressionType.Divide => "op_Division", 
				ExpressionType.Modulo => "op_Modulus", 
				ExpressionType.LeftShift => "op_LeftShift", 
				ExpressionType.RightShift => "op_RightShift", 
				ExpressionType.LessThan => "op_LessThan", 
				ExpressionType.GreaterThan => "op_GreaterThan", 
				ExpressionType.LessThanOrEqual => "op_LessThanOrEqual", 
				ExpressionType.GreaterThanOrEqual => "op_GreaterThanOrEqual", 
				ExpressionType.Equal => "op_Equality", 
				ExpressionType.NotEqual => "op_Inequality", 
				ExpressionType.And => "op_BitwiseAnd", 
				ExpressionType.ExclusiveOr => "op_ExclusiveOr", 
				ExpressionType.Or => "op_BitwiseOr", 
				ExpressionType.AddAssign => "op_Addition", 
				ExpressionType.SubtractAssign => "op_Subtraction", 
				ExpressionType.MultiplyAssign => "op_Multiply", 
				ExpressionType.DivideAssign => "op_Division", 
				ExpressionType.ModuloAssign => "op_Modulus", 
				ExpressionType.AndAssign => "op_BitwiseAnd", 
				ExpressionType.ExclusiveOrAssign => "op_ExclusiveOr", 
				ExpressionType.OrAssign => "op_BitwiseOr", 
				ExpressionType.LeftShiftAssign => "op_LeftShift", 
				ExpressionType.RightShiftAssign => "op_RightShift", 
				ExpressionType.Negate => "op_UnaryNegation", 
				ExpressionType.UnaryPlus => "op_UnaryPlus", 
				ExpressionType.Not => "op_LogicalNot", 
				ExpressionType.OnesComplement => "op_OnesComplement", 
				ExpressionType.IsTrue => "op_True", 
				ExpressionType.IsFalse => "op_False", 
				ExpressionType.Increment => "op_Increment", 
				ExpressionType.Decrement => "op_Decrement", 
				_ => null, 
			};
		}

		internal static int AddArgHashes(int hash, Type[] typeArguments, CSharpArgumentInfo[] argInfos)
		{
			foreach (Type type in typeArguments)
			{
				hash = HashHelpers.Combine(hash, type.GetHashCode());
			}
			return AddArgHashes(hash, argInfos);
		}

		internal static int AddArgHashes(int hash, CSharpArgumentInfo[] argInfos)
		{
			foreach (CSharpArgumentInfo cSharpArgumentInfo in argInfos)
			{
				hash = HashHelpers.Combine(hash, (int)cSharpArgumentInfo.Flags);
				string name = cSharpArgumentInfo.Name;
				if (!string.IsNullOrEmpty(name))
				{
					hash = HashHelpers.Combine(hash, name.GetHashCode());
				}
			}
			return hash;
		}

		internal static bool CompareArgInfos(Type[] typeArgs, Type[] otherTypeArgs, CSharpArgumentInfo[] argInfos, CSharpArgumentInfo[] otherArgInfos)
		{
			for (int i = 0; i < typeArgs.Length; i++)
			{
				if (typeArgs[i] != otherTypeArgs[i])
				{
					return false;
				}
			}
			return CompareArgInfos(argInfos, otherArgInfos);
		}

		internal static bool CompareArgInfos(CSharpArgumentInfo[] argInfos, CSharpArgumentInfo[] otherArgInfos)
		{
			for (int i = 0; i < argInfos.Length; i++)
			{
				CSharpArgumentInfo cSharpArgumentInfo = argInfos[i];
				CSharpArgumentInfo cSharpArgumentInfo2 = otherArgInfos[i];
				if (cSharpArgumentInfo.Flags != cSharpArgumentInfo2.Flags || cSharpArgumentInfo.Name != cSharpArgumentInfo2.Name)
				{
					return false;
				}
			}
			return true;
		}
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	public sealed class CSharpArgumentInfo
	{
		internal static readonly CSharpArgumentInfo None = new CSharpArgumentInfo(CSharpArgumentInfoFlags.None, null);

		internal CSharpArgumentInfoFlags Flags { get; }

		internal string Name { get; }

		internal bool UseCompileTimeType => (Flags & CSharpArgumentInfoFlags.UseCompileTimeType) != 0;

		internal bool LiteralConstant => (Flags & CSharpArgumentInfoFlags.Constant) != 0;

		internal bool NamedArgument => (Flags & CSharpArgumentInfoFlags.NamedArgument) != 0;

		internal bool IsByRefOrOut => (Flags & (CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.IsOut)) != 0;

		internal bool IsOut => (Flags & CSharpArgumentInfoFlags.IsOut) != 0;

		internal bool IsStaticType => (Flags & CSharpArgumentInfoFlags.IsStaticType) != 0;

		private CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name)
		{
			Flags = flags;
			Name = name;
		}

		public static CSharpArgumentInfo Create(CSharpArgumentInfoFlags flags, string name)
		{
			return new CSharpArgumentInfo(flags, name);
		}
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[Flags]
	public enum CSharpArgumentInfoFlags
	{
		None = 0,
		UseCompileTimeType = 1,
		Constant = 2,
		NamedArgument = 4,
		IsRef = 8,
		IsOut = 0x10,
		IsStaticType = 0x20
	}
	internal sealed class CSharpBinaryOperationBinder : BinaryOperationBinder, ICSharpBinder
	{
		private readonly CSharpBinaryOperationFlags _binopFlags;

		private readonly CSharpArgumentInfo[] _argumentInfo;

		private readonly RuntimeBinder _binder;

		private readonly Type _callingContext;

		[ExcludeFromCodeCoverage]
		public string Name => null;

		public BindingFlag BindingFlags => (BindingFlag)0;

		public bool IsBinderThatCanHaveRefReceiver => false;

		internal bool IsLogicalOperation => (_binopFlags & CSharpBinaryOperationFlags.LogicalOperation) != 0;

		private bool IsChecked => _binder.IsChecked;

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			return runtimeBinder.BindBinaryOperation(this, arguments, locals);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
			string cLROperatorName = base.Operation.GetCLROperatorName();
			SymbolTable.PopulateSymbolTableWithName(cLROperatorName, null, arguments[0].Type);
			SymbolTable.PopulateSymbolTableWithName(cLROperatorName, null, arguments[1].Type);
		}

		CSharpArgumentInfo ICSharpBinder.GetArgumentInfo(int index)
		{
			return _argumentInfo[index];
		}

		public CSharpBinaryOperationBinder(ExpressionType operation, bool isChecked, CSharpBinaryOperationFlags binaryOperationFlags, Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
			: base(operation)
		{
			_binopFlags = binaryOperationFlags;
			_callingContext = callingContext;
			_argumentInfo = BinderHelper.ToArray(argumentInfo);
			_binder = new RuntimeBinder(callingContext, isChecked);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int h = _callingContext?.GetHashCode() ?? 0;
			h = HashHelpers.Combine(h, (int)_binopFlags);
			if (IsChecked)
			{
				h = HashHelpers.Combine(h, 1);
			}
			h = HashHelpers.Combine(h, (int)base.Operation);
			return BinderHelper.AddArgHashes(h, _argumentInfo);
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpBinaryOperationBinder cSharpBinaryOperationBinder))
			{
				return false;
			}
			if (_binopFlags != cSharpBinaryOperationBinder._binopFlags || base.Operation != cSharpBinaryOperationBinder.Operation || IsChecked != cSharpBinaryOperationBinder.IsChecked || _callingContext != cSharpBinaryOperationBinder._callingContext)
			{
				return false;
			}
			return BinderHelper.CompareArgInfos(_argumentInfo, cSharpBinaryOperationBinder._argumentInfo);
		}

		public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			BinderHelper.ValidateBindArgument(arg, "arg");
			return BinderHelper.Bind(this, _binder, new DynamicMetaObject[2] { target, arg }, _argumentInfo, errorSuggestion);
		}
	}
	[Flags]
	internal enum CSharpBinaryOperationFlags
	{
		None = 0,
		MemberAccess = 1,
		LogicalOperation = 2
	}
	[Flags]
	[EditorBrowsable(EditorBrowsableState.Never)]
	public enum CSharpBinderFlags
	{
		None = 0,
		CheckedContext = 1,
		InvokeSimpleName = 2,
		InvokeSpecialName = 4,
		BinaryOperationLogical = 8,
		ConvertExplicit = 0x10,
		ConvertArrayIndex = 0x20,
		ResultIndexed = 0x40,
		ValueFromCompoundAssignment = 0x80,
		ResultDiscarded = 0x100
	}
	[Flags]
	internal enum CSharpCallFlags
	{
		None = 0,
		SimpleNameCall = 1,
		EventHookup = 2,
		ResultDiscarded = 4
	}
	internal enum CSharpConversionKind
	{
		ImplicitConversion,
		ExplicitConversion,
		ArrayCreationConversion
	}
	internal sealed class CSharpConvertBinder : ConvertBinder, ICSharpBinder
	{
		private readonly RuntimeBinder _binder;

		private readonly Type _callingContext;

		[ExcludeFromCodeCoverage]
		public string Name => null;

		public BindingFlag BindingFlags => (BindingFlag)0;

		public bool IsBinderThatCanHaveRefReceiver => false;

		private CSharpConversionKind ConversionKind { get; }

		private bool IsChecked => _binder.IsChecked;

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			if (!base.Explicit)
			{
				return runtimeBinder.BindImplicitConversion(arguments, base.Type, locals, ConversionKind == CSharpConversionKind.ArrayCreationConversion);
			}
			return runtimeBinder.BindExplicitConversion(arguments, base.Type, locals);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
		}

		CSharpArgumentInfo ICSharpBinder.GetArgumentInfo(int index)
		{
			return CSharpArgumentInfo.None;
		}

		public CSharpConvertBinder(Type type, CSharpConversionKind conversionKind, bool isChecked, Type callingContext)
			: base(type, conversionKind == CSharpConversionKind.ExplicitConversion)
		{
			ConversionKind = conversionKind;
			_callingContext = callingContext;
			_binder = new RuntimeBinder(callingContext, isChecked);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int h = _callingContext?.GetHashCode() ?? 0;
			h = HashHelpers.Combine(h, (int)ConversionKind);
			if (IsChecked)
			{
				h = HashHelpers.Combine(h, 1);
			}
			return HashHelpers.Combine(h, base.Type.GetHashCode());
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpConvertBinder cSharpConvertBinder))
			{
				return false;
			}
			if (ConversionKind != cSharpConvertBinder.ConversionKind || IsChecked != cSharpConvertBinder.IsChecked || _callingContext != cSharpConvertBinder._callingContext || base.Type != cSharpConvertBinder.Type)
			{
				return false;
			}
			return true;
		}

		public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			return BinderHelper.Bind(this, _binder, new DynamicMetaObject[1] { target }, null, errorSuggestion);
		}
	}
	internal sealed class CSharpGetIndexBinder : GetIndexBinder, ICSharpBinder
	{
		private readonly CSharpArgumentInfo[] _argumentInfo;

		private readonly RuntimeBinder _binder;

		private readonly Type _callingContext;

		public string Name => "$Item$";

		public BindingFlag BindingFlags => BindingFlag.BIND_RVALUEREQUIRED;

		public bool IsBinderThatCanHaveRefReceiver => true;

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			Expr optionalIndexerArguments = runtimeBinder.CreateArgumentListEXPR(arguments, locals, 1, arguments.Length);
			return runtimeBinder.BindProperty(this, arguments[0], locals[0], optionalIndexerArguments);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
			SymbolTable.PopulateSymbolTableWithName("$Item$", null, arguments[0].Type);
		}

		CSharpArgumentInfo ICSharpBinder.GetArgumentInfo(int index)
		{
			return _argumentInfo[index];
		}

		public CSharpGetIndexBinder(Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
			: base(BinderHelper.CreateCallInfo(ref argumentInfo, 1))
		{
			_argumentInfo = argumentInfo as CSharpArgumentInfo[];
			_callingContext = callingContext;
			_binder = new RuntimeBinder(callingContext);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int hash = _callingContext?.GetHashCode() ?? 0;
			return BinderHelper.AddArgHashes(hash, _argumentInfo);
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpGetIndexBinder cSharpGetIndexBinder))
			{
				return false;
			}
			if (_callingContext != cSharpGetIndexBinder._callingContext || _argumentInfo.Length != cSharpGetIndexBinder._argumentInfo.Length)
			{
				return false;
			}
			return BinderHelper.CompareArgInfos(_argumentInfo, cSharpGetIndexBinder._argumentInfo);
		}

		public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			BinderHelper.ValidateBindArgument(indexes, "indexes");
			return BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, indexes), _argumentInfo, errorSuggestion);
		}
	}
	internal sealed class CSharpGetMemberBinder : GetMemberBinder, IInvokeOnGetBinder, ICSharpBinder
	{
		private readonly CSharpArgumentInfo[] _argumentInfo;

		private readonly RuntimeBinder _binder;

		private readonly Type _callingContext;

		public BindingFlag BindingFlags => BindingFlag.BIND_RVALUEREQUIRED;

		public bool IsBinderThatCanHaveRefReceiver => false;

		bool IInvokeOnGetBinder.InvokeOnGet => !ResultIndexed;

		private bool ResultIndexed { get; }

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			return runtimeBinder.BindProperty(this, arguments[0], locals[0], null);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
			SymbolTable.PopulateSymbolTableWithName(base.Name, null, arguments[0].Type);
		}

		CSharpArgumentInfo ICSharpBinder.GetArgumentInfo(int index)
		{
			return _argumentInfo[index];
		}

		public CSharpGetMemberBinder(string name, bool resultIndexed, Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
			: base(name, ignoreCase: false)
		{
			ResultIndexed = resultIndexed;
			_argumentInfo = BinderHelper.ToArray(argumentInfo);
			_callingContext = callingContext;
			_binder = new RuntimeBinder(callingContext);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int h = _callingContext?.GetHashCode() ?? 0;
			if (ResultIndexed)
			{
				h = HashHelpers.Combine(h, 1);
			}
			h = HashHelpers.Combine(h, base.Name.GetHashCode());
			return BinderHelper.AddArgHashes(h, _argumentInfo);
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpGetMemberBinder cSharpGetMemberBinder))
			{
				return false;
			}
			if (base.Name != cSharpGetMemberBinder.Name || ResultIndexed != cSharpGetMemberBinder.ResultIndexed || _callingContext != cSharpGetMemberBinder._callingContext || _argumentInfo.Length != cSharpGetMemberBinder._argumentInfo.Length)
			{
				return false;
			}
			return BinderHelper.CompareArgInfos(_argumentInfo, cSharpGetMemberBinder._argumentInfo);
		}

		public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			return BinderHelper.Bind(this, _binder, new DynamicMetaObject[1] { target }, _argumentInfo, errorSuggestion);
		}

		[SpecialName]
		string ICSharpBinder.get_Name()
		{
			return base.Name;
		}
	}
	internal sealed class CSharpInvokeBinder : InvokeBinder, ICSharpInvokeOrInvokeMemberBinder, ICSharpBinder
	{
		private readonly CSharpCallFlags _flags;

		private readonly CSharpArgumentInfo[] _argumentInfo;

		private readonly RuntimeBinder _binder;

		private readonly Type _callingContext;

		public BindingFlag BindingFlags => (BindingFlag)0;

		public bool IsBinderThatCanHaveRefReceiver => true;

		bool ICSharpInvokeOrInvokeMemberBinder.StaticCall
		{
			get
			{
				if (_argumentInfo[0] != null)
				{
					return _argumentInfo[0].IsStaticType;
				}
				return false;
			}
		}

		string ICSharpBinder.Name => "Invoke";

		Type[] ICSharpInvokeOrInvokeMemberBinder.TypeArguments => Array.Empty<Type>();

		CSharpCallFlags ICSharpInvokeOrInvokeMemberBinder.Flags => _flags;

		bool ICSharpInvokeOrInvokeMemberBinder.ResultDiscarded => (_flags & CSharpCallFlags.ResultDiscarded) != 0;

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			return runtimeBinder.DispatchPayload(this, arguments, locals);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
			RuntimeBinder.PopulateSymbolTableWithPayloadInformation(this, callingType, arguments);
		}

		CSharpArgumentInfo ICSharpBinder.GetArgumentInfo(int index)
		{
			return _argumentInfo[index];
		}

		public CSharpInvokeBinder(CSharpCallFlags flags, Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
			: base(BinderHelper.CreateCallInfo(ref argumentInfo, 1))
		{
			_flags = flags;
			_callingContext = callingContext;
			_argumentInfo = argumentInfo as CSharpArgumentInfo[];
			_binder = new RuntimeBinder(callingContext);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int h = _callingContext?.GetHashCode() ?? 0;
			h = HashHelpers.Combine(h, (int)_flags);
			return BinderHelper.AddArgHashes(h, _argumentInfo);
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpInvokeBinder cSharpInvokeBinder))
			{
				return false;
			}
			if (_flags != cSharpInvokeBinder._flags || _callingContext != cSharpInvokeBinder._callingContext || _argumentInfo.Length != cSharpInvokeBinder._argumentInfo.Length)
			{
				return false;
			}
			return BinderHelper.CompareArgInfos(_argumentInfo, cSharpInvokeBinder._argumentInfo);
		}

		public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			BinderHelper.ValidateBindArgument(args, "args");
			return BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, args), _argumentInfo, errorSuggestion);
		}
	}
	internal sealed class CSharpInvokeConstructorBinder : DynamicMetaObjectBinder, ICSharpInvokeOrInvokeMemberBinder, ICSharpBinder
	{
		private readonly CSharpArgumentInfo[] _argumentInfo;

		private readonly RuntimeBinder _binder;

		private readonly Type _callingContext;

		public BindingFlag BindingFlags => (BindingFlag)0;

		public bool IsBinderThatCanHaveRefReceiver => true;

		public CSharpCallFlags Flags { get; }

		public bool StaticCall => true;

		public Type[] TypeArguments => Array.Empty<Type>();

		public string Name => ".ctor";

		bool ICSharpInvokeOrInvokeMemberBinder.ResultDiscarded => false;

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			return runtimeBinder.DispatchPayload(this, arguments, locals);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
			RuntimeBinder.PopulateSymbolTableWithPayloadInformation(this, callingType, arguments);
		}

		CSharpArgumentInfo ICSharpBinder.GetArgumentInfo(int index)
		{
			return _argumentInfo[index];
		}

		public CSharpInvokeConstructorBinder(CSharpCallFlags flags, Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
		{
			Flags = flags;
			_callingContext = callingContext;
			_argumentInfo = BinderHelper.ToArray(argumentInfo);
			_binder = new RuntimeBinder(callingContext);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int h = _callingContext?.GetHashCode() ?? 0;
			h = HashHelpers.Combine(h, (int)Flags);
			h = HashHelpers.Combine(h, Name.GetHashCode());
			return BinderHelper.AddArgHashes(h, TypeArguments, _argumentInfo);
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpInvokeConstructorBinder cSharpInvokeConstructorBinder))
			{
				return false;
			}
			if (Flags != cSharpInvokeConstructorBinder.Flags || _callingContext != cSharpInvokeConstructorBinder._callingContext || Name != cSharpInvokeConstructorBinder.Name || TypeArguments.Length != cSharpInvokeConstructorBinder.TypeArguments.Length || _argumentInfo.Length != cSharpInvokeConstructorBinder._argumentInfo.Length)
			{
				return false;
			}
			return BinderHelper.CompareArgInfos(TypeArguments, cSharpInvokeConstructorBinder.TypeArguments, _argumentInfo, cSharpInvokeConstructorBinder._argumentInfo);
		}

		public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			BinderHelper.ValidateBindArgument(args, "args");
			return BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, args), _argumentInfo, null);
		}
	}
	internal sealed class CSharpInvokeMemberBinder : InvokeMemberBinder, ICSharpInvokeOrInvokeMemberBinder, ICSharpBinder
	{
		private readonly CSharpArgumentInfo[] _argumentInfo;

		private readonly RuntimeBinder _binder;

		public BindingFlag BindingFlags => (BindingFlag)0;

		public bool IsBinderThatCanHaveRefReceiver => true;

		bool ICSharpInvokeOrInvokeMemberBinder.StaticCall => _argumentInfo[0]?.IsStaticType ?? false;

		public CSharpCallFlags Flags { get; }

		public Type CallingContext { get; }

		public Type[] TypeArguments { get; }

		bool ICSharpInvokeOrInvokeMemberBinder.ResultDiscarded => (Flags & CSharpCallFlags.ResultDiscarded) != 0;

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			return runtimeBinder.DispatchPayload(this, arguments, locals);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
			RuntimeBinder.PopulateSymbolTableWithPayloadInformation(this, callingType, arguments);
		}

		public CSharpArgumentInfo GetArgumentInfo(int index)
		{
			return _argumentInfo[index];
		}

		public CSharpArgumentInfo[] ArgumentInfoArray()
		{
			CSharpArgumentInfo[] array = new CSharpArgumentInfo[_argumentInfo.Length];
			_argumentInfo.CopyTo(array, 0);
			return array;
		}

		public CSharpInvokeMemberBinder(CSharpCallFlags flags, string name, Type callingContext, IEnumerable<Type> typeArguments, IEnumerable<CSharpArgumentInfo> argumentInfo)
			: base(name, ignoreCase: false, BinderHelper.CreateCallInfo(ref argumentInfo, 1))
		{
			Flags = flags;
			CallingContext = callingContext;
			TypeArguments = BinderHelper.ToArray(typeArguments);
			_argumentInfo = BinderHelper.ToArray(argumentInfo);
			_binder = new RuntimeBinder(callingContext);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int h = CallingContext?.GetHashCode() ?? 0;
			h = HashHelpers.Combine(h, (int)Flags);
			h = HashHelpers.Combine(h, base.Name.GetHashCode());
			return BinderHelper.AddArgHashes(h, TypeArguments, _argumentInfo);
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpInvokeMemberBinder cSharpInvokeMemberBinder))
			{
				return false;
			}
			if (Flags != cSharpInvokeMemberBinder.Flags || CallingContext != cSharpInvokeMemberBinder.CallingContext || base.Name != cSharpInvokeMemberBinder.Name || TypeArguments.Length != cSharpInvokeMemberBinder.TypeArguments.Length || _argumentInfo.Length != cSharpInvokeMemberBinder._argumentInfo.Length)
			{
				return false;
			}
			return BinderHelper.CompareArgInfos(TypeArguments, cSharpInvokeMemberBinder.TypeArguments, _argumentInfo, cSharpInvokeMemberBinder._argumentInfo);
		}

		public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			BinderHelper.ValidateBindArgument(args, "args");
			return BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, args), _argumentInfo, errorSuggestion);
		}

		public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
		{
			CSharpInvokeBinder cSharpInvokeBinder = new CSharpInvokeBinder(Flags, CallingContext, _argumentInfo).TryGetExisting();
			return cSharpInvokeBinder.Defer(target, args);
		}

		[SpecialName]
		string ICSharpBinder.get_Name()
		{
			return base.Name;
		}
	}
	internal sealed class CSharpIsEventBinder : DynamicMetaObjectBinder, ICSharpBinder
	{
		private readonly RuntimeBinder _binder;

		private readonly Type _callingContext;

		public BindingFlag BindingFlags => (BindingFlag)0;

		public bool IsBinderThatCanHaveRefReceiver => false;

		public string Name { get; }

		public override Type ReturnType => typeof(bool);

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			return runtimeBinder.BindIsEvent(this, arguments, locals);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
			SymbolTable.PopulateSymbolTableWithName(Name, null, arguments[0].Info.IsStaticType ? (arguments[0].Value as Type) : arguments[0].Type);
		}

		CSharpArgumentInfo ICSharpBinder.GetArgumentInfo(int index)
		{
			return CSharpArgumentInfo.None;
		}

		public CSharpIsEventBinder(string name, Type callingContext)
		{
			Name = name;
			_callingContext = callingContext;
			_binder = new RuntimeBinder(callingContext);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int h = _callingContext?.GetHashCode() ?? 0;
			return HashHelpers.Combine(h, Name.GetHashCode());
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpIsEventBinder cSharpIsEventBinder))
			{
				return false;
			}
			if (_callingContext != cSharpIsEventBinder._callingContext || Name != cSharpIsEventBinder.Name)
			{
				return false;
			}
			return true;
		}

		public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			return BinderHelper.Bind(this, _binder, new DynamicMetaObject[1] { target }, null, null);
		}
	}
	internal sealed class CSharpSetIndexBinder : SetIndexBinder, ICSharpBinder
	{
		private readonly CSharpArgumentInfo[] _argumentInfo;

		private readonly RuntimeBinder _binder;

		private readonly Type _callingContext;

		public string Name => "$Item$";

		public BindingFlag BindingFlags => (BindingFlag)0;

		public bool IsBinderThatCanHaveRefReceiver => true;

		internal bool IsCompoundAssignment { get; }

		private bool IsChecked => _binder.IsChecked;

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			return runtimeBinder.BindAssignment(this, arguments, locals);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
			SymbolTable.PopulateSymbolTableWithName("$Item$", null, arguments[0].Type);
		}

		CSharpArgumentInfo ICSharpBinder.GetArgumentInfo(int index)
		{
			return _argumentInfo[index];
		}

		public CSharpSetIndexBinder(bool isCompoundAssignment, bool isChecked, Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
			: base(BinderHelper.CreateCallInfo(ref argumentInfo, 2))
		{
			IsCompoundAssignment = isCompoundAssignment;
			_argumentInfo = argumentInfo as CSharpArgumentInfo[];
			_callingContext = callingContext;
			_binder = new RuntimeBinder(callingContext, isChecked);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int num = _callingContext?.GetHashCode() ?? 0;
			if (IsChecked)
			{
				num = HashHelpers.Combine(num, 1);
			}
			if (IsCompoundAssignment)
			{
				num = HashHelpers.Combine(num, 1);
			}
			return BinderHelper.AddArgHashes(num, _argumentInfo);
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpSetIndexBinder cSharpSetIndexBinder))
			{
				return false;
			}
			if (_callingContext != cSharpSetIndexBinder._callingContext || IsChecked != cSharpSetIndexBinder.IsChecked || IsCompoundAssignment != cSharpSetIndexBinder.IsCompoundAssignment || _argumentInfo.Length != cSharpSetIndexBinder._argumentInfo.Length)
			{
				return false;
			}
			return BinderHelper.CompareArgInfos(_argumentInfo, cSharpSetIndexBinder._argumentInfo);
		}

		public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			BinderHelper.ValidateBindArgument(indexes, "indexes");
			BinderHelper.ValidateBindArgument(value, "value");
			return BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, indexes, value), _argumentInfo, errorSuggestion);
		}
	}
	internal sealed class CSharpSetMemberBinder : SetMemberBinder, ICSharpBinder
	{
		private readonly CSharpArgumentInfo[] _argumentInfo;

		private readonly RuntimeBinder _binder;

		private readonly Type _callingContext;

		public BindingFlag BindingFlags => (BindingFlag)0;

		public bool IsBinderThatCanHaveRefReceiver => false;

		internal bool IsCompoundAssignment { get; }

		private bool IsChecked => _binder.IsChecked;

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			return runtimeBinder.BindAssignment(this, arguments, locals);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
			SymbolTable.PopulateSymbolTableWithName(base.Name, null, arguments[0].Type);
		}

		CSharpArgumentInfo ICSharpBinder.GetArgumentInfo(int index)
		{
			return _argumentInfo[index];
		}

		public CSharpSetMemberBinder(string name, bool isCompoundAssignment, bool isChecked, Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
			: base(name, ignoreCase: false)
		{
			IsCompoundAssignment = isCompoundAssignment;
			_argumentInfo = BinderHelper.ToArray(argumentInfo);
			_callingContext = callingContext;
			_binder = new RuntimeBinder(callingContext, isChecked);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int h = _callingContext?.GetHashCode() ?? 0;
			if (IsChecked)
			{
				h = HashHelpers.Combine(h, 1);
			}
			if (IsCompoundAssignment)
			{
				h = HashHelpers.Combine(h, 1);
			}
			h = HashHelpers.Combine(h, base.Name.GetHashCode());
			return BinderHelper.AddArgHashes(h, _argumentInfo);
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpSetMemberBinder cSharpSetMemberBinder))
			{
				return false;
			}
			if (base.Name != cSharpSetMemberBinder.Name || _callingContext != cSharpSetMemberBinder._callingContext || IsChecked != cSharpSetMemberBinder.IsChecked || IsCompoundAssignment != cSharpSetMemberBinder.IsCompoundAssignment || _argumentInfo.Length != cSharpSetMemberBinder._argumentInfo.Length)
			{
				return false;
			}
			return BinderHelper.CompareArgInfos(_argumentInfo, cSharpSetMemberBinder._argumentInfo);
		}

		public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			BinderHelper.ValidateBindArgument(value, "value");
			return BinderHelper.Bind(this, _binder, new DynamicMetaObject[2] { target, value }, _argumentInfo, errorSuggestion);
		}

		[SpecialName]
		string ICSharpBinder.get_Name()
		{
			return base.Name;
		}
	}
	internal sealed class CSharpUnaryOperationBinder : UnaryOperationBinder, ICSharpBinder
	{
		private readonly CSharpArgumentInfo[] _argumentInfo;

		private readonly RuntimeBinder _binder;

		private readonly Type _callingContext;

		[ExcludeFromCodeCoverage]
		public string Name => null;

		public BindingFlag BindingFlags => (BindingFlag)0;

		public bool IsBinderThatCanHaveRefReceiver => false;

		private bool IsChecked => _binder.IsChecked;

		public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			return runtimeBinder.BindUnaryOperation(this, arguments, locals);
		}

		public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
		{
			SymbolTable.PopulateSymbolTableWithName(base.Operation.GetCLROperatorName(), null, arguments[0].Type);
		}

		CSharpArgumentInfo ICSharpBinder.GetArgumentInfo(int index)
		{
			return _argumentInfo[index];
		}

		public CSharpUnaryOperationBinder(ExpressionType operation, bool isChecked, Type callingContext, IEnumerable<CSharpArgumentInfo> argumentInfo)
			: base(operation)
		{
			_argumentInfo = BinderHelper.ToArray(argumentInfo);
			_callingContext = callingContext;
			_binder = new RuntimeBinder(callingContext, isChecked);
		}

		public int GetGetBinderEquivalenceHash()
		{
			int h = _callingContext?.GetHashCode() ?? 0;
			h = HashHelpers.Combine(h, (int)base.Operation);
			if (IsChecked)
			{
				h = HashHelpers.Combine(h, 1);
			}
			return BinderHelper.AddArgHashes(h, _argumentInfo);
		}

		public bool IsEquivalentTo(ICSharpBinder other)
		{
			if (!(other is CSharpUnaryOperationBinder cSharpUnaryOperationBinder))
			{
				return false;
			}
			if (base.Operation != cSharpUnaryOperationBinder.Operation || IsChecked != cSharpUnaryOperationBinder.IsChecked || _callingContext != cSharpUnaryOperationBinder._callingContext)
			{
				return false;
			}
			return BinderHelper.CompareArgInfos(_argumentInfo, cSharpUnaryOperationBinder._argumentInfo);
		}

		public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
		{
			BinderHelper.ValidateBindArgument(target, "target");
			return BinderHelper.Bind(this, _binder, new DynamicMetaObject[1] { target }, _argumentInfo, errorSuggestion);
		}
	}
	[Serializable]
	[EditorBrowsable(EditorBrowsableState.Never)]
	internal sealed class DynamicBindingFailedException : Exception
	{
		public DynamicBindingFailedException()
		{
		}

		private DynamicBindingFailedException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}
	}
	internal sealed class GetMemberValueBinder : GetMemberBinder
	{
		public GetMemberValueBinder(string name, bool ignoreCase)
			: base(name, ignoreCase)
		{
		}

		public override DynamicMetaObject FallbackGetMember(DynamicMetaObject self, DynamicMetaObject onBindingError)
		{
			if (onBindingError == null)
			{
				List<DynamicMetaObject> contributingObjects = new List<DynamicMetaObject> { self };
				return new DynamicMetaObject(Expression.Throw(Expression.Constant(new DynamicBindingFailedException(), typeof(Exception)), typeof(object)), BindingRestrictions.Combine(contributingObjects));
			}
			return onBindingError;
		}
	}
	internal sealed class DynamicMetaObjectProviderDebugView
	{
		[DebuggerDisplay("{value}", Name = "{name, nq}", Type = "{type, nq}")]
		internal class DynamicProperty
		{
			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			private readonly string name;

			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			private readonly object value;

			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			private readonly string type;

			public DynamicProperty(string name, object value)
			{
				this.name = name;
				this.value = value;
				type = ((value == null) ? "<null>" : value.GetType().ToString());
			}
		}

		[Serializable]
		internal class DynamicDebugViewEmptyException : Exception
		{
			public string Empty => System.SR.EmptyDynamicView;

			public DynamicDebugViewEmptyException()
			{
			}

			protected DynamicDebugViewEmptyException(SerializationInfo info, StreamingContext context)
				: base(info, context)
			{
			}
		}

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private IList<KeyValuePair<string, object>> results;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private object obj;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private static readonly ParameterExpression parameter = Expression.Parameter(typeof(object), "debug");

		[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
		internal DynamicProperty[] Items
		{
			get
			{
				if (results == null || results.Count == 0)
				{
					results = QueryDynamicObject(obj);
					if (results == null || results.Count == 0)
					{
						throw new DynamicDebugViewEmptyException();
					}
				}
				DynamicProperty[] array = new DynamicProperty[results.Count];
				for (int i = 0; i < results.Count; i++)
				{
					array[i] = new DynamicProperty(results[i].Key, results[i].Value);
				}
				return array;
			}
		}

		public DynamicMetaObjectProviderDebugView(object arg)
		{
			obj = arg;
		}

		public static object TryEvalBinaryOperators<T1, T2>(T1 arg1, T2 arg2, CSharpArgumentInfoFlags arg1Flags, CSharpArgumentInfoFlags arg2Flags, ExpressionType opKind, Type accessibilityContext)
		{
			CSharpArgumentInfo cSharpArgumentInfo = CSharpArgumentInfo.Create(arg1Flags, null);
			CSharpArgumentInfo cSharpArgumentInfo2 = CSharpArgumentInfo.Create(arg2Flags, null);
			CSharpBinaryOperationBinder binder = new CSharpBinaryOperationBinder(opKind, isChecked: false, CSharpBinaryOperationFlags.None, accessibilityContext, new CSharpArgumentInfo[2] { cSharpArgumentInfo, cSharpArgumentInfo2 });
			CallSite<Func<CallSite, T1, T2, object>> callSite = CallSite<Func<CallSite, T1, T2, object>>.Create(binder);
			return callSite.Target(callSite, arg1, arg2);
		}

		public static object TryEvalUnaryOperators<T>(T obj, ExpressionType oper, Type accessibilityContext)
		{
			if (oper == ExpressionType.IsTrue || oper == ExpressionType.IsFalse)
			{
				CallSite<Func<CallSite, T, bool>> callSite = CallSite<Func<CallSite, T, bool>>.Create(new CSharpUnaryOperationBinder(oper, isChecked: false, accessibilityContext, new CSharpArgumentInfo[1] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
				return callSite.Target(callSite, obj);
			}
			CallSite<Func<CallSite, T, object>> callSite2 = CallSite<Func<CallSite, T, object>>.Create(new CSharpUnaryOperationBinder(oper, isChecked: false, accessibilityContext, new CSharpArgumentInfo[1] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
			return callSite2.Target(callSite2, obj);
		}

		public static K TryEvalCast<T, K>(T obj, Type type, CSharpBinderFlags kind, Type accessibilityContext)
		{
			CallSite<Func<CallSite, T, K>> callSite = CallSite<Func<CallSite, T, K>>.Create(Binder.Convert(kind, type, accessibilityContext));
			return callSite.Target(callSite, obj);
		}

		private static void CreateDelegateSignatureAndArgumentInfos(object[] args, Type[] argTypes, CSharpArgumentInfoFlags[] argFlags, out Type[] delegateSignatureTypes, out CSharpArgumentInfo[] argInfos)
		{
			int num = args.Length;
			delegateSignatureTypes = new Type[num + 2];
			delegateSignatureTypes[0] = typeof(CallSite);
			argInfos = new CSharpArgumentInfo[num];
			for (int i = 0; i < num; i++)
			{
				if (argTypes[i] != null)
				{
					delegateSignatureTypes[i + 1] = argTypes[i];
				}
				else if (args[i] != null)
				{
					delegateSignatureTypes[i + 1] = args[i].GetType();
				}
				else
				{
					delegateSignatureTypes[i + 1] = typeof(object);
				}
				argInfos[i] = CSharpArgumentInfo.Create(argFlags[i], null);
			}
			delegateSignatureTypes[num + 1] = typeof(object);
		}

		private static object CreateDelegateAndInvoke(Type[] delegateSignatureTypes, CallSiteBinder binder, object[] args)
		{
			Type delegateType = Expression.GetDelegateType(delegateSignatureTypes);
			CallSite callSite = CallSite.Create(delegateType, binder);
			Delegate @delegate = (Delegate)callSite.GetType().GetField("Target").GetValue(callSite);
			object[] array = new object[args.Length + 1];
			array[0] = callSite;
			args.CopyTo(array, 1);
			return @delegate.DynamicInvoke(array);
		}

		public static object TryEvalMethodVarArgs(object[] methodArgs, Type[] argTypes, CSharpArgumentInfoFlags[] argFlags, string methodName, Type accessibilityContext, Type[] typeArguments)
		{
			Type[] delegateSignatureTypes = null;
			CSharpArgumentInfo[] argInfos = null;
			CreateDelegateSignatureAndArgumentInfos(methodArgs, argTypes, argFlags, out delegateSignatureTypes, out argInfos);
			return CreateDelegateAndInvoke(binder: (!string.IsNullOrEmpty(methodName)) ? ((CallSiteBinder)new CSharpInvokeMemberBinder(CSharpCallFlags.ResultDiscarded, methodName, accessibilityContext, typeArguments, argInfos)) : ((CallSiteBinder)new CSharpInvokeBinder(CSharpCallFlags.ResultDiscarded, accessibilityContext, argInfos)), delegateSignatureTypes: delegateSignatureTypes, args: methodArgs);
		}

		public static object TryGetMemberValue<T>(T obj, string propName, Type accessibilityContext, bool isResultIndexed)
		{
			CSharpGetMemberBinder binder = new CSharpGetMemberBinder(propName, isResultIndexed, accessibilityContext, new CSharpArgumentInfo[1] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
			CallSite<Func<CallSite, T, object>> callSite = CallSite<Func<CallSite, T, object>>.Create(binder);
			return callSite.Target(callSite, obj);
		}

		public static object TryGetMemberValueVarArgs(object[] propArgs, Type[] argTypes, CSharpArgumentInfoFlags[] argFlags, Type accessibilityContext)
		{
			Type[] delegateSignatureTypes = null;
			CSharpArgumentInfo[] argInfos = null;
			CreateDelegateSignatureAndArgumentInfos(propArgs, argTypes, argFlags, out delegateSignatureTypes, out argInfos);
			CallSiteBinder binder = new CSharpGetIndexBinder(accessibilityContext, argInfos);
			return CreateDelegateAndInvoke(delegateSignatureTypes, binder, propArgs);
		}

		public static object TrySetMemberValue<TObject, TValue>(TObject obj, string propName, TValue value, CSharpArgumentInfoFlags valueFlags, Type accessibilityContext)
		{
			CSharpArgumentInfo cSharpArgumentInfo = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
			CSharpArgumentInfo cSharpArgumentInfo2 = CSharpArgumentInfo.Create(valueFlags, null);
			CSharpSetMemberBinder binder = new CSharpSetMemberBinder(propName, isCompoundAssignment: false, isChecked: false, accessibilityContext, new CSharpArgumentInfo[2] { cSharpArgumentInfo, cSharpArgumentInfo2 });
			CallSite<Func<CallSite, TObject, TValue, object>> callSite = CallSite<Func<CallSite, TObject, TValue, object>>.Create(binder);
			return callSite.Target(callSite, obj, value);
		}

		public static object TrySetMemberValueVarArgs(object[] propArgs, Type[] argTypes, CSharpArgumentInfoFlags[] argFlags, Type accessibilityContext)
		{
			Type[] delegateSignatureTypes = null;
			CSharpArgumentInfo[] argInfos = null;
			CreateDelegateSignatureAndArgumentInfos(propArgs, argTypes, argFlags, out delegateSignatureTypes, out argInfos);
			CallSiteBinder binder = new CSharpSetIndexBinder(isCompoundAssignment: false, isChecked: false, accessibilityContext, argInfos);
			return CreateDelegateAndInvoke(delegateSignatureTypes, binder, propArgs);
		}

		internal static object TryGetMemberValue(object obj, string name, bool ignoreException)
		{
			bool ignoreCase = false;
			object obj2 = null;
			CallSite<Func<CallSite, object, object>> callSite = CallSite<Func<CallSite, object, object>>.Create(new GetMemberValueBinder(name, ignoreCase));
			try
			{
				return callSite.Target(callSite, obj);
			}
			catch (DynamicBindingFailedException ex)
			{
				if (ignoreException)
				{
					return null;
				}
				throw ex;
			}
			catch (MissingMemberException ex2)
			{
				if (ignoreException)
				{
					return System.SR.GetValueonWriteOnlyProperty;
				}
				throw ex2;
			}
		}

		private static IList<KeyValuePair<string, object>> QueryDynamicObject(object obj)
		{
			if (obj is IDynamicMetaObjectProvider dynamicMetaObjectProvider)
			{
				DynamicMetaObject metaObject = dynamicMetaObjectProvider.GetMetaObject(parameter);
				List<string> list = new List<string>(metaObject.GetDynamicMemberNames());
				list.Sort();
				if (list != null)
				{
					List<KeyValuePair<string, object>> list2 = new List<KeyValuePair<string, object>>();
					{
						foreach (string item in list)
						{
							object value;
							if ((value = TryGetMemberValue(obj, item, ignoreException: true)) != null)
							{
								list2.Add(new KeyValuePair<string, object>(item, value));
							}
						}
						return list2;
					}
				}
			}
			return new KeyValuePair<string, object>[0];
		}
	}
	internal static class Error
	{
		internal static Exception InternalCompilerError()
		{
			return new RuntimeBinderInternalCompilerException(System.SR.InternalCompilerError);
		}

		internal static Exception BindPropertyFailedMethodGroup(object p0)
		{
			return new RuntimeBinderException(System.SR.Format(System.SR.BindPropertyFailedMethodGroup, p0));
		}

		internal static Exception BindPropertyFailedEvent(object p0)
		{
			return new RuntimeBinderException(System.SR.Format(System.SR.BindPropertyFailedEvent, p0));
		}

		internal static Exception BindInvokeFailedNonDelegate()
		{
			return new RuntimeBinderException(System.SR.BindInvokeFailedNonDelegate);
		}

		internal static Exception BindStaticRequiresType(string paramName)
		{
			return new ArgumentException(System.SR.TypeArgumentRequiredForStaticCall, paramName);
		}

		internal static Exception NullReferenceOnMemberException()
		{
			return new RuntimeBinderException(System.SR.NullReferenceOnMemberException);
		}

		internal static Exception BindCallToConditionalMethod(object p0)
		{
			return new RuntimeBinderException(System.SR.Format(System.SR.BindCallToConditionalMethod, p0));
		}

		internal static Exception BindToVoidMethodButExpectResult()
		{
			return new RuntimeBinderException(System.SR.BindToVoidMethodButExpectResult);
		}

		internal static Exception ArgumentNull(string paramName)
		{
			return new ArgumentNullException(paramName);
		}

		internal static Exception DynamicArgumentNeedsValue(string paramName)
		{
			return new ArgumentException(System.SR.DynamicArgumentNeedsValue, paramName);
		}
	}
	internal sealed class ExpressionTreeCallRewriter : ExprVisitorBase
	{
		private sealed class ExpressionExpr : Expr
		{
			public readonly Expression Expression;

			public ExpressionExpr(Expression e)
				: base(ExpressionKind.NoOp)
			{
				Expression = e;
			}
		}

		private readonly Dictionary<ExprCall, Expression> _DictionaryOfParameters;

		private readonly Expression[] _ListOfParameters;

		private int _currentParameterIndex;

		private ExpressionTreeCallRewriter(Expression[] listOfParameters)
		{
			_DictionaryOfParameters = new Dictionary<ExprCall, Expression>();
			_ListOfParameters = listOfParameters;
		}

		public static Expression Rewrite(ExprBinOp binOp, Expression[] listOfParameters)
		{
			ExpressionTreeCallRewriter expressionTreeCallRewriter = new ExpressionTreeCallRewriter(listOfParameters);
			expressionTreeCallRewriter.Visit(binOp.OptionalLeftChild);
			ExprCall pExpr = (ExprCall)binOp.OptionalRightChild;
			ExpressionExpr expressionExpr = expressionTreeCallRewriter.Visit(pExpr) as ExpressionExpr;
			return expressionExpr.Expression;
		}

		protected override Expr VisitSAVE(ExprBinOp pExpr)
		{
			ExprCall key = (ExprCall)pExpr.OptionalLeftChild;
			Expression value = _ListOfParameters[_currentParameterIndex++];
			_DictionaryOfParameters.Add(key, value);
			return null;
		}

		protected override Expr VisitCALL(ExprCall pExpr)
		{
			if (pExpr.PredefinedMethod == PREDEFMETH.PM_COUNT)
			{
				return pExpr;
			}
			Expression e;
			switch (pExpr.PredefinedMethod)
			{
			case PREDEFMETH.PM_EXPRESSION_LAMBDA:
				return GenerateLambda(pExpr);
			case PREDEFMETH.PM_EXPRESSION_CALL:
				e = GenerateCall(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX:
			case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2:
				e = GenerateArrayIndex(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_CONVERT:
			case PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED:
			case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED:
				e = GenerateConvert(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_PROPERTY:
				e = GenerateProperty(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_FIELD:
				e = GenerateField(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_INVOKE:
				e = GenerateInvoke(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_NEW:
				e = GenerateNew(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_ADD:
			case PREDEFMETH.PM_EXPRESSION_ADDCHECKED:
			case PREDEFMETH.PM_EXPRESSION_AND:
			case PREDEFMETH.PM_EXPRESSION_ANDALSO:
			case PREDEFMETH.PM_EXPRESSION_DIVIDE:
			case PREDEFMETH.PM_EXPRESSION_EQUAL:
			case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR:
			case PREDEFMETH.PM_EXPRESSION_GREATERTHAN:
			case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL:
			case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT:
			case PREDEFMETH.PM_EXPRESSION_LESSTHAN:
			case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL:
			case PREDEFMETH.PM_EXPRESSION_MODULO:
			case PREDEFMETH.PM_EXPRESSION_MULTIPLY:
			case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED:
			case PREDEFMETH.PM_EXPRESSION_NOTEQUAL:
			case PREDEFMETH.PM_EXPRESSION_OR:
			case PREDEFMETH.PM_EXPRESSION_ORELSE:
			case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT:
			case PREDEFMETH.PM_EXPRESSION_SUBTRACT:
			case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED:
				e = GenerateBinaryOperator(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED:
				e = GenerateUserDefinedBinaryOperator(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_NEGATE:
			case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED:
			case PREDEFMETH.PM_EXPRESSION_NOT:
				e = GenerateUnaryOperator(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED:
				e = GenerateUserDefinedUnaryOperator(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE:
				e = GenerateConstantType(pExpr);
				break;
			case PREDEFMETH.PM_EXPRESSION_ASSIGN:
				e = GenerateAssignment(pExpr);
				break;
			default:
				throw Error.InternalCompilerError();
			}
			return new ExpressionExpr(e);
		}

		protected override Expr VisitWRAP(ExprWrap pExpr)
		{
			return new ExpressionExpr(GetExpression(pExpr));
		}

		private Expr GenerateLambda(ExprCall pExpr)
		{
			return Visit(((ExprList)pExpr.OptionalArguments).OptionalElement);
		}

		private Expression GenerateCall(ExprCall pExpr)
		{
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			ExprMethodInfo exprMethodInfo;
			ExprArrayInit arrinit;
			if (exprList.OptionalNextListNode is ExprList exprList2)
			{
				exprMethodInfo = (ExprMethodInfo)exprList2.OptionalElement;
				arrinit = (ExprArrayInit)exprList2.OptionalNextListNode;
			}
			else
			{
				exprMethodInfo = (ExprMethodInfo)exprList.OptionalNextListNode;
				arrinit = null;
			}
			Expression instance = null;
			MethodInfo methodInfo = exprMethodInfo.MethodInfo;
			Expression[] argumentsFromArrayInit = GetArgumentsFromArrayInit(arrinit);
			if (methodInfo == null)
			{
				throw Error.InternalCompilerError();
			}
			if (!methodInfo.IsStatic)
			{
				instance = GetExpression(((ExprList)pExpr.OptionalArguments).OptionalElement);
			}
			return Expression.Call(instance, methodInfo, argumentsFromArrayInit);
		}

		private Expression GenerateArrayIndex(ExprCall pExpr)
		{
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			Expression expression = GetExpression(exprList.OptionalElement);
			Expression[] indexes = ((pExpr.PredefinedMethod != PREDEFMETH.PM_EXPRESSION_ARRAYINDEX) ? GetArgumentsFromArrayInit((ExprArrayInit)exprList.OptionalNextListNode) : new Expression[1] { GetExpression(exprList.OptionalNextListNode) });
			return Expression.ArrayAccess(expression, indexes);
		}

		private Expression GenerateConvert(ExprCall pExpr)
		{
			PREDEFMETH predefinedMethod = pExpr.PredefinedMethod;
			Expression expression;
			Type associatedSystemType;
			if (predefinedMethod == PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED || predefinedMethod == PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED)
			{
				ExprList exprList = (ExprList)pExpr.OptionalArguments;
				ExprList exprList2 = (ExprList)exprList.OptionalNextListNode;
				expression = GetExpression(exprList.OptionalElement);
				associatedSystemType = ((ExprTypeOf)exprList2.OptionalElement).SourceType.AssociatedSystemType;
				if (expression.Type.MakeByRefType() == associatedSystemType)
				{
					return expression;
				}
				MethodInfo methodInfo = ((ExprMethodInfo)exprList2.OptionalNextListNode).MethodInfo;
				if (predefinedMethod == PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED)
				{
					return Expression.Convert(expression, associatedSystemType, methodInfo);
				}
				return Expression.ConvertChecked(expression, associatedSystemType, methodInfo);
			}
			ExprList exprList3 = (ExprList)pExpr.OptionalArguments;
			expression = GetExpression(exprList3.OptionalElement);
			associatedSystemType = ((ExprTypeOf)exprList3.OptionalNextListNode).SourceType.AssociatedSystemType;
			if (expression.Type.MakeByRefType() == associatedSystemType)
			{
				return expression;
			}
			if ((pExpr.Flags & EXPRFLAG.EXF_USERCALLABLE) != 0)
			{
				return Expression.Unbox(expression, associatedSystemType);
			}
			if (predefinedMethod == PREDEFMETH.PM_EXPRESSION_CONVERT)
			{
				return Expression.Convert(expression, associatedSystemType);
			}
			return Expression.ConvertChecked(expression, associatedSystemType);
		}

		private Expression GenerateProperty(ExprCall pExpr)
		{
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			Expr optionalElement = exprList.OptionalElement;
			Expr optionalNextListNode = exprList.OptionalNextListNode;
			ExprPropertyInfo exprPropertyInfo;
			ExprArrayInit exprArrayInit;
			if (optionalNextListNode is ExprList exprList2)
			{
				exprPropertyInfo = exprList2.OptionalElement as ExprPropertyInfo;
				exprArrayInit = exprList2.OptionalNextListNode as ExprArrayInit;
			}
			else
			{
				exprPropertyInfo = optionalNextListNode as ExprPropertyInfo;
				exprArrayInit = null;
			}
			PropertyInfo propertyInfo = exprPropertyInfo.PropertyInfo;
			if (propertyInfo == null)
			{
				throw Error.InternalCompilerError();
			}
			if (exprArrayInit == null)
			{
				return Expression.Property(GetExpression(optionalElement), propertyInfo);
			}
			return Expression.Property(GetExpression(optionalElement), propertyInfo, GetArgumentsFromArrayInit(exprArrayInit));
		}

		private Expression GenerateField(ExprCall pExpr)
		{
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			ExprFieldInfo exprFieldInfo = (ExprFieldInfo)exprList.OptionalNextListNode;
			Type type = exprFieldInfo.FieldType.AssociatedSystemType;
			FieldInfo fieldInfo = exprFieldInfo.Field.AssociatedFieldInfo;
			if (!type.IsGenericType && !type.IsNested)
			{
				type = fieldInfo.DeclaringType;
			}
			if (type.IsGenericType)
			{
				fieldInfo = type.GetField(fieldInfo.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			}
			return Expression.Field(GetExpression(exprList.OptionalElement), fieldInfo);
		}

		private Expression GenerateInvoke(ExprCall pExpr)
		{
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			return Expression.Invoke(GetExpression(exprList.OptionalElement), GetArgumentsFromArrayInit(exprList.OptionalNextListNode as ExprArrayInit));
		}

		private Expression GenerateNew(ExprCall pExpr)
		{
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			ConstructorInfo constructorInfo = ((ExprMethodInfo)exprList.OptionalElement).ConstructorInfo;
			Expression[] argumentsFromArrayInit = GetArgumentsFromArrayInit(exprList.OptionalNextListNode as ExprArrayInit);
			return Expression.New(constructorInfo, argumentsFromArrayInit);
		}

		private static Expression GenerateConstantType(ExprCall pExpr)
		{
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			return Expression.Constant(exprList.OptionalElement.Object, ((ExprTypeOf)exprList.OptionalNextListNode).SourceType.AssociatedSystemType);
		}

		private Expression GenerateAssignment(ExprCall pExpr)
		{
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			return Expression.Assign(GetExpression(exprList.OptionalElement), GetExpression(exprList.OptionalNextListNode));
		}

		private Expression GenerateBinaryOperator(ExprCall pExpr)
		{
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			Expression expression = GetExpression(exprList.OptionalElement);
			Expression expression2 = GetExpression(exprList.OptionalNextListNode);
			return pExpr.PredefinedMethod switch
			{
				PREDEFMETH.PM_EXPRESSION_ADD => Expression.Add(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_AND => Expression.And(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_DIVIDE => Expression.Divide(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_EQUAL => Expression.Equal(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR => Expression.ExclusiveOr(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_GREATERTHAN => Expression.GreaterThan(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL => Expression.GreaterThanOrEqual(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_LEFTSHIFT => Expression.LeftShift(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_LESSTHAN => Expression.LessThan(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL => Expression.LessThanOrEqual(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_MODULO => Expression.Modulo(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_MULTIPLY => Expression.Multiply(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_NOTEQUAL => Expression.NotEqual(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_OR => Expression.Or(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT => Expression.RightShift(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_SUBTRACT => Expression.Subtract(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_ORELSE => Expression.OrElse(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_ANDALSO => Expression.AndAlso(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_ADDCHECKED => Expression.AddChecked(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED => Expression.MultiplyChecked(expression, expression2), 
				PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED => Expression.SubtractChecked(expression, expression2), 
				_ => throw Error.InternalCompilerError(), 
			};
		}

		private Expression GenerateUserDefinedBinaryOperator(ExprCall pExpr)
		{
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			Expression expression = GetExpression(exprList.OptionalElement);
			Expression expression2 = GetExpression(((ExprList)exprList.OptionalNextListNode).OptionalElement);
			exprList = (ExprList)exprList.OptionalNextListNode;
			bool liftToNull = false;
			MethodInfo methodInfo;
			if (exprList.OptionalNextListNode is ExprList exprList2)
			{
				ExprConstant exprConstant = (ExprConstant)exprList2.OptionalElement;
				liftToNull = exprConstant.Val.Int32Val == 1;
				methodInfo = ((ExprMethodInfo)exprList2.OptionalNextListNode).MethodInfo;
			}
			else
			{
				methodInfo = ((ExprMethodInfo)exprList.OptionalNextListNode).MethodInfo;
			}
			return pExpr.PredefinedMethod switch
			{
				PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED => Expression.Add(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED => Expression.And(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED => Expression.Divide(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED => Expression.Equal(expression, expression2, liftToNull, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED => Expression.ExclusiveOr(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED => Expression.GreaterThan(expression, expression2, liftToNull, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED => Expression.GreaterThanOrEqual(expression, expression2, liftToNull, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED => Expression.LeftShift(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED => Expression.LessThan(expression, expression2, liftToNull, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED => Expression.LessThanOrEqual(expression, expression2, liftToNull, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED => Expression.Modulo(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED => Expression.Multiply(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED => Expression.NotEqual(expression, expression2, liftToNull, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED => Expression.Or(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED => Expression.RightShift(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED => Expression.Subtract(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED => Expression.OrElse(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED => Expression.AndAlso(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED => Expression.AddChecked(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED => Expression.MultiplyChecked(expression, expression2, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED => Expression.SubtractChecked(expression, expression2, methodInfo), 
				_ => throw Error.InternalCompilerError(), 
			};
		}

		private Expression GenerateUnaryOperator(ExprCall pExpr)
		{
			PREDEFMETH predefinedMethod = pExpr.PredefinedMethod;
			Expression expression = GetExpression(pExpr.OptionalArguments);
			return predefinedMethod switch
			{
				PREDEFMETH.PM_EXPRESSION_NOT => Expression.Not(expression), 
				PREDEFMETH.PM_EXPRESSION_NEGATE => Expression.Negate(expression), 
				PREDEFMETH.PM_EXPRESSION_NEGATECHECKED => Expression.NegateChecked(expression), 
				_ => throw Error.InternalCompilerError(), 
			};
		}

		private Expression GenerateUserDefinedUnaryOperator(ExprCall pExpr)
		{
			PREDEFMETH predefinedMethod = pExpr.PredefinedMethod;
			ExprList exprList = (ExprList)pExpr.OptionalArguments;
			Expression expression = GetExpression(exprList.OptionalElement);
			MethodInfo methodInfo = ((ExprMethodInfo)exprList.OptionalNextListNode).MethodInfo;
			return predefinedMethod switch
			{
				PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED => Expression.Not(expression, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED => Expression.Negate(expression, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED => Expression.UnaryPlus(expression, methodInfo), 
				PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED => Expression.NegateChecked(expression, methodInfo), 
				_ => throw Error.InternalCompilerError(), 
			};
		}

		private Expression GetExpression(Expr pExpr)
		{
			if (pExpr is ExprWrap exprWrap)
			{
				return _DictionaryOfParameters[(ExprCall)exprWrap.OptionalExpression];
			}
			if (pExpr is ExprConstant)
			{
				return null;
			}
			ExprCall exprCall = (ExprCall)pExpr;
			switch (exprCall.PredefinedMethod)
			{
			case PREDEFMETH.PM_EXPRESSION_CALL:
				return GenerateCall(exprCall);
			case PREDEFMETH.PM_EXPRESSION_CONVERT:
			case PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED:
			case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED:
				return GenerateConvert(exprCall);
			case PREDEFMETH.PM_EXPRESSION_NEWARRAYINIT:
			{
				ExprList exprList = (ExprList)exprCall.OptionalArguments;
				return Expression.NewArrayInit(((ExprTypeOf)exprList.OptionalElement).SourceType.AssociatedSystemType, GetArgumentsFromArrayInit((ExprArrayInit)exprList.OptionalNextListNode));
			}
			case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX:
			case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2:
				return GenerateArrayIndex(exprCall);
			case PREDEFMETH.PM_EXPRESSION_NEW:
				return GenerateNew(exprCall);
			case PREDEFMETH.PM_EXPRESSION_PROPERTY:
				return GenerateProperty(exprCall);
			case PREDEFMETH.PM_EXPRESSION_FIELD:
				return GenerateField(exprCall);
			case PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE:
				return GenerateConstantType(exprCall);
			case PREDEFMETH.PM_EXPRESSION_ASSIGN:
				return GenerateAssignment(exprCall);
			case PREDEFMETH.PM_EXPRESSION_ADD:
			case PREDEFMETH.PM_EXPRESSION_ADDCHECKED:
			case PREDEFMETH.PM_EXPRESSION_AND:
			case PREDEFMETH.PM_EXPRESSION_ANDALSO:
			case PREDEFMETH.PM_EXPRESSION_DIVIDE:
			case PREDEFMETH.PM_EXPRESSION_EQUAL:
			case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR:
			case PREDEFMETH.PM_EXPRESSION_GREATERTHAN:
			case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL:
			case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT:
			case PREDEFMETH.PM_EXPRESSION_LESSTHAN:
			case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL:
			case PREDEFMETH.PM_EXPRESSION_MODULO:
			case PREDEFMETH.PM_EXPRESSION_MULTIPLY:
			case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED:
			case PREDEFMETH.PM_EXPRESSION_NOTEQUAL:
			case PREDEFMETH.PM_EXPRESSION_OR:
			case PREDEFMETH.PM_EXPRESSION_ORELSE:
			case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT:
			case PREDEFMETH.PM_EXPRESSION_SUBTRACT:
			case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED:
				return GenerateBinaryOperator(exprCall);
			case PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED:
				return GenerateUserDefinedBinaryOperator(exprCall);
			case PREDEFMETH.PM_EXPRESSION_NEGATE:
			case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED:
			case PREDEFMETH.PM_EXPRESSION_NOT:
				return GenerateUnaryOperator(exprCall);
			case PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED:
			case PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED:
				return GenerateUserDefinedUnaryOperator(exprCall);
			default:
				throw Error.InternalCompilerError();
			}
		}

		private Expression[] GetArgumentsFromArrayInit(ExprArrayInit arrinit)
		{
			List<Expression> list = new List<Expression>();
			if (arrinit != null)
			{
				Expr expr = arrinit.OptionalArguments;
				while (expr != null)
				{
					Expr pExpr;
					if (expr is ExprList exprList)
					{
						pExpr = exprList.OptionalElement;
						expr = exprList.OptionalNextListNode;
					}
					else
					{
						pExpr = expr;
						expr = null;
					}
					list.Add(GetExpression(pExpr));
				}
			}
			return list.ToArray();
		}
	}
	internal interface ICSharpBinder
	{
		bool IsBinderThatCanHaveRefReceiver { get; }

		BindingFlag BindingFlags { get; }

		string Name { get; }

		Type ReturnType { get; }

		CSharpArgumentInfo GetArgumentInfo(int index);

		void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments);

		Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals);

		int GetGetBinderEquivalenceHash();

		bool IsEquivalentTo(ICSharpBinder other);
	}
	internal interface ICSharpInvokeOrInvokeMemberBinder : ICSharpBinder
	{
		bool StaticCall { get; }

		bool ResultDiscarded { get; }

		CSharpCallFlags Flags { get; }

		Type[] TypeArguments { get; }
	}
	internal readonly struct RuntimeBinder
	{
		private static readonly object s_bindLock = new object();

		private readonly ExpressionBinder _binder;

		internal bool IsChecked => _binder.Context.Checked;

		public RuntimeBinder(Type contextType, bool isChecked = false)
		{
			AggregateSymbol context;
			if (contextType != null)
			{
				lock (s_bindLock)
				{
					context = ((AggregateType)SymbolTable.GetCTypeFromType(contextType)).OwningAggregate;
				}
			}
			else
			{
				context = null;
			}
			_binder = new ExpressionBinder(new BindingContext(context, isChecked));
		}

		public Expression Bind(ICSharpBinder payload, Expression[] parameters, DynamicMetaObject[] args, out DynamicMetaObject deferredBinding)
		{
			lock (s_bindLock)
			{
				return BindCore(payload, parameters, args, out deferredBinding);
			}
		}

		private Expression BindCore(ICSharpBinder payload, Expression[] parameters, DynamicMetaObject[] args, out DynamicMetaObject deferredBinding)
		{
			ArgumentObject[] array = CreateArgumentArray(payload, parameters, args);
			payload.PopulateSymbolTableWithName(array[0].Type, array);
			AddConversionsForArguments(array);
			Scope pScope = SymFactory.CreateScope();
			LocalVariableSymbol[] locals = PopulateLocalScope(payload, pScope, array, parameters);
			if (DeferBinding(payload, array, args, locals, out deferredBinding))
			{
				return null;
			}
			Expr pResult = payload.DispatchPayload(this, array, locals);
			return CreateExpressionTreeFromResult(parameters, pScope, pResult);
		}

		private bool DeferBinding(ICSharpBinder payload, ArgumentObject[] arguments, DynamicMetaObject[] args, LocalVariableSymbol[] locals, out DynamicMetaObject deferredBinding)
		{
			if (payload is CSharpInvokeMemberBinder cSharpInvokeMemberBinder)
			{
				Type[] typeArguments = cSharpInvokeMemberBinder.TypeArguments;
				int arity = ((typeArguments != null) ? typeArguments.Length : 0);
				MemberLookup mem = new MemberLookup();
				Expr callingObject = CreateCallingObjectForCall(cSharpInvokeMemberBinder, arguments, locals);
				SymWithType symWithType = SymbolTable.LookupMember(cSharpInvokeMemberBinder.Name, callingObject, _binder.Context.ContextForMemberLookup, arity, mem, (cSharpInvokeMemberBinder.Flags & CSharpCallFlags.EventHookup) != 0, requireInvocable: true);
				if (symWithType != null && symWithType.Sym.getKind() != SYMKIND.SK_MethodSymbol)
				{
					CSharpGetMemberBinder cSharpGetMemberBinder = new CSharpGetMemberBinder(cSharpInvokeMemberBinder.Name, resultIndexed: false, cSharpInvokeMemberBinder.CallingContext, new CSharpArgumentInfo[1] { cSharpInvokeMemberBinder.GetArgumentInfo(0) }).TryGetExisting();
					CSharpArgumentInfo[] array = cSharpInvokeMemberBinder.ArgumentInfoArray();
					array[0] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
					CSharpInvokeBinder cSharpInvokeBinder = new CSharpInvokeBinder(cSharpInvokeMemberBinder.Flags, cSharpInvokeMemberBinder.CallingContext, array).TryGetExisting();
					DynamicMetaObject[] array2 = new DynamicMetaObject[args.Length - 1];
					Array.Copy(args, 1, array2, 0, args.Length - 1);
					deferredBinding = cSharpInvokeBinder.Defer(cSharpGetMemberBinder.Defer(args[0]), array2);
					return true;
				}
			}
			deferredBinding = null;
			return false;
		}

		private static Expression CreateExpressionTreeFromResult(Expression[] parameters, Scope pScope, Expr pResult)
		{
			ExprBoundLambda expr = GenerateBoundLambda(pScope, pResult);
			ExprBinOp binOp = ExpressionTreeRewriter.Rewrite(expr);
			return ExpressionTreeCallRewriter.Rewrite(binOp, parameters);
		}

		private Type GetArgumentType(ICSharpBinder p, CSharpArgumentInfo argInfo, Expression param, DynamicMetaObject arg, int index)
		{
			Type type = (argInfo.UseCompileTimeType ? param.Type : arg.LimitType);
			if (argInfo.IsByRefOrOut)
			{
				if (index != 0 || !p.IsBinderThatCanHaveRefReceiver)
				{
					type = type.MakeByRefType();
				}
			}
			else if (!argInfo.UseCompileTimeType)
			{
				CType cTypeFromType = SymbolTable.GetCTypeFromType(type);
				CType bestAccessibleType = TypeManager.GetBestAccessibleType(_binder.Context.ContextForMemberLookup, cTypeFromType);
				type = bestAccessibleType.AssociatedSystemType;
			}
			return type;
		}

		private ArgumentObject[] CreateArgumentArray(ICSharpBinder payload, Expression[] parameters, DynamicMetaObject[] args)
		{
			ArgumentObject[] array = new ArgumentObject[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				CSharpArgumentInfo argumentInfo = payload.GetArgumentInfo(i);
				array[i] = new ArgumentObject(args[i].Value, argumentInfo, GetArgumentType(payload, argumentInfo, parameters[i], args[i], i));
			}
			return array;
		}

		internal static void PopulateSymbolTableWithPayloadInformation(ICSharpInvokeOrInvokeMemberBinder callOrInvoke, Type callingType, ArgumentObject[] arguments)
		{
			Type type;
			if (callOrInvoke.StaticCall)
			{
				type = arguments[0].Value as Type;
				if (type == null)
				{
					throw Error.BindStaticRequiresType(arguments[0].Info.Name);
				}
			}
			else
			{
				type = callingType;
			}
			SymbolTable.PopulateSymbolTableWithName(callOrInvoke.Name, callOrInvoke.TypeArguments, type);
			if (callOrInvoke.Name.StartsWith("set_", StringComparison.Ordinal) || callOrInvoke.Name.StartsWith("get_", StringComparison.Ordinal))
			{
				SymbolTable.PopulateSymbolTableWithName(callOrInvoke.Name.Substring(4), callOrInvoke.TypeArguments, type);
			}
		}

		private static void AddConversionsForArguments(ArgumentObject[] arguments)
		{
			for (int i = 0; i < arguments.Length; i++)
			{
				ArgumentObject argumentObject = arguments[i];
				SymbolTable.AddConversionsForType(argumentObject.Type);
			}
		}

		internal ExprWithArgs DispatchPayload(ICSharpInvokeOrInvokeMemberBinder payload, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
		{
			return BindCall(payload, CreateCallingObjectForCall(payload, arguments, locals), arguments, locals);
		}

		private static LocalVariableSymbol[] PopulateLocalScope(ICSharpBinder payload, Scope pScope, ArgumentObject[] arguments, Expression[] parameterExpressions)
		{
			LocalVariableSymbol[] array = new LocalVariableSymbol[parameterExpressions.Length];
			for (int i = 0; i < parameterExpressions.Length; i++)
			{
				Expression expression = parameterExpressions[i];
				CType cType = SymbolTable.GetCTypeFromType(expression.Type);
				if ((i != 0 || !payload.IsBinderThatCanHaveRefReceiver) && expression is ParameterExpression parameterExpression && parameterExpression.IsByRef)
				{
					CSharpArgumentInfo info = arguments[i].Info;
					if (info.IsByRefOrOut)
					{
						cType = TypeManager.GetParameterModifier(cType, info.IsOut);
					}
				}
				LocalVariableSymbol localVariableSymbol = SymFactory.CreateLocalVar(NameManager.Add("p" + i), pScope, cType);
				array[i] = localVariableSymbol;
			}
			return array;
		}

		private static ExprBoundLambda GenerateBoundLambda(Scope pScope, Expr call)
		{
			AggregateType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_FUNC);
			return ExprFactory.CreateAnonymousMethod(predefindType, pScope, call);
		}

		private Expr CreateLocal(Type type, bool isOut, LocalVariableSymbol local)
		{
			CType dest = ((!isOut) ? SymbolTable.GetCTypeFromType(type) : TypeManager.GetParameterModifier(SymbolTable.GetCTypeFromType(type.GetElementType()), isOut: true));
			ExprLocal expr = ExprFactory.CreateLocal(local);
			Expr expr2 = _binder.tryConvert(expr, dest) ?? _binder.mustCast(expr, dest);
			expr2.Flags |= EXPRFLAG.EXF_LVALUE;
			return expr2;
		}

		internal Expr CreateArgumentListEXPR(ArgumentObject[] arguments, LocalVariableSymbol[] locals, int startIndex, int endIndex)
		{
			Expr first = null;
			Expr last = null;
			if (arguments != null)
			{
				for (int i = startIndex; i < endIndex; i++)
				{
					ArgumentObject argument = arguments[i];
					Expr expr = CreateArgumentEXPR(argument, locals[i]);
					if (first == null)
					{
						first = expr;
						last = first;
					}
					else
					{
						ExprFactory.AppendItemToList(expr, ref first, ref last);
					}
				}
			}
			return first;
		}

		private Expr CreateArgumentEXPR(ArgumentObject argument, LocalVariableSymbol local)
		{
			Expr expr = (argument.Info.LiteralConstant ? ((argument.Value != null) ? ExprFactory.CreateConstant(SymbolTable.GetCTypeFromType(argument.Type), ConstVal.Get(argument.Value)) : ((!argument.Info.UseCompileTimeType) ? ExprFactory.CreateNull() : ExprFactory.CreateConstant(SymbolTable.GetCTypeFromType(argument.Type), default(ConstVal)))) : ((argument.Info.UseCompileTimeType || argument.Value != null) ? CreateLocal(argument.Type, argument.Info.IsOut, local) : ExprFactory.CreateNull()));
			if (argument.Info.NamedArgument)
			{
				expr = ExprFactory.CreateNamedArgumentSpecification(NameManager.Add(argument.Info.Name), expr);
			}
			if (!argument.Info.UseCompileTimeType && argument.Value != null)
			{
				expr.RuntimeObject = argument.Value;

plugins/Replug.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Buttplug.Client;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Replug.Patches;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Zelfmonco")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("Replug")]
[assembly: AssemblyTitle("Replug")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.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 Replug
{
	public class DeviceManager
	{
		public bool isVibing = false;

		public List<ButtplugClientDevice> ConnectedDevices { get; set; }

		public ButtplugClient ButtplugClient { get; set; }

		public DeviceManager(string clientName)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			ConnectedDevices = new List<ButtplugClientDevice>();
			ButtplugClient = new ButtplugClient(clientName);
			ButtplugClient.DeviceAdded += HandleDeviceAdded;
			ButtplugClient.DeviceRemoved += HandleDeviceRemoved;
		}

		public bool Connected()
		{
			return ButtplugClient.Connected;
		}

		public async void Connect()
		{
			try
			{
				await ButtplugClient.ConnectAsync((IButtplugClientConnector)new ButtplugWebsocketConnector(new Uri(Config.ServerUri.Value)), default(CancellationToken));
				if (Connected())
				{
					await ButtplugClient.StartScanningAsync(default(CancellationToken));
				}
			}
			catch (ButtplugClientConnectorException val)
			{
				ButtplugClientConnectorException val2 = val;
				ButtplugClientConnectorException ex = val2;
				ReplugMod.Logger.LogError((object)ex);
			}
		}

		private void HandleDeviceAdded(object sender, DeviceAddedEventArgs args)
		{
			if (IsVibratable(args.Device))
			{
				ReplugMod.Logger.LogInfo((object)(args.Device.Name + " connected to " + ButtplugClient.Name));
				ConnectedDevices.Add(args.Device);
			}
		}

		private void HandleDeviceRemoved(object sender, DeviceRemovedEventArgs args)
		{
			if (IsVibratable(args.Device))
			{
				ReplugMod.Logger.LogInfo((object)(args.Device.Name + " disconnected from " + ButtplugClient.Name));
				ConnectedDevices.Remove(args.Device);
			}
		}

		public void VibrateAllWithDuration(double intensity, float time)
		{
			ConnectedDevices.ForEach(Repeat);
			async void Repeat(ButtplugClientDevice device)
			{
				await device.VibrateAsync((double)Mathf.Clamp((float)intensity, 0f, 1f));
				isVibing = true;
				await Task.Delay((int)(time * 1000f));
				await device.VibrateAsync(0.0);
				isVibing = false;
			}
		}

		public void VibrateAllDevices(double intensity)
		{
			ConnectedDevices.ForEach(Repeat);
			async void Repeat(ButtplugClientDevice device)
			{
				await device.VibrateAsync((double)Mathf.Clamp((float)intensity, 0f, 1f));
			}
		}

		private bool IsVibratable(ButtplugClientDevice device)
		{
			return device.VibrateAttributes.Count > 0;
		}

		public void StopAllDevices()
		{
			ConnectedDevices.ForEach(async delegate(ButtplugClientDevice device)
			{
				await device.Stop();
			});
		}
	}
	internal class Config
	{
		private static ConfigFile ConfigFile { get; set; }

		internal static ConfigEntry<string> ServerUri { get; set; }

		internal static ConfigEntry<int> HurtIntensity { get; set; }

		internal static ConfigEntry<bool> HurtToggle { get; set; }

		internal static ConfigEntry<int> HealIntensity { get; set; }

		internal static ConfigEntry<bool> HealToggle { get; set; }

		internal static ConfigEntry<int> GunIntensity { get; set; }

		internal static ConfigEntry<bool> GunToggle { get; set; }

		internal static ConfigEntry<int> CrouchStandIntensity { get; set; }

		internal static ConfigEntry<bool> CrouchStandToggle { get; set; }

		internal static ConfigEntry<int> CameraShakeIntensity { get; set; }

		internal static ConfigEntry<bool> CameraShakeToggle { get; set; }

		internal static ConfigEntry<int> ButtonHoverIntensity { get; set; }

		internal static ConfigEntry<bool> ButtonHoverToggle { get; set; }

		internal static ConfigEntry<int> ButtonSelectIntensity { get; set; }

		internal static ConfigEntry<bool> ButtonSelectToggle { get; set; }

		internal static ConfigEntry<int> DiscoverValuableIntensity { get; set; }

		internal static ConfigEntry<bool> DiscoverValuableToggle { get; set; }

		internal static ConfigEntry<bool> DiscoverValuableScalesWithValue { get; set; }

		internal static ConfigEntry<int> DiscoverValuableMinValue { get; set; }

		internal static ConfigEntry<int> DiscoverValuableMaxValue { get; set; }

		internal static ConfigEntry<int> DiscoverValuableMinIntensity { get; set; }

		internal static ConfigEntry<int> DiscoverValuableMaxIntensity { get; set; }

		static Config()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Expected O, but got Unknown
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Expected O, but got Unknown
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Expected O, but got Unknown
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Expected O, but got Unknown
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Expected O, but got Unknown
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Expected O, but got Unknown
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Expected O, but got Unknown
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Expected O, but got Unknown
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Expected O, but got Unknown
			ConfigFile = new ConfigFile(Paths.ConfigPath + "\\Replug.cfg", true);
			ServerUri = ConfigFile.Bind<string>("Connection", "Server URI", "ws://127.0.0.1:12345", "URI for Intiface server");
			HurtIntensity = ConfigFile.Bind<int>("Buttplug", "Hurt Intensity", 20, new ConfigDescription("Hurt intensity setting", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			HurtToggle = ConfigFile.Bind<bool>("Toggles", "Hurt vibrate toggle", true, "Hurt vibration toggle");
			HealIntensity = ConfigFile.Bind<int>("Buttplug", "Heal Intensity", 8, new ConfigDescription("Heal intensity setting", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			HealToggle = ConfigFile.Bind<bool>("Toggles", "Heal vibrate toggle", true, "Hurt vibration toggle");
			GunIntensity = ConfigFile.Bind<int>("Buttplug", "Gun Intensity", 12, new ConfigDescription("Gun item intensity setting", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			GunToggle = ConfigFile.Bind<bool>("Toggles", "Gun vibrate toggle", false, "Hurt vibration toggle");
			CameraShakeIntensity = ConfigFile.Bind<int>("Buttplug", "Camera Shake Intensity", 10, new ConfigDescription("Camera shake intensity setting", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			CameraShakeToggle = ConfigFile.Bind<bool>("Toggles", "Camera shake vibrate toggle", true, "Camera vibrate toggle");
			CrouchStandIntensity = ConfigFile.Bind<int>("Buttplug", "Crouch Stand Intensity", 1, new ConfigDescription("Button hover intensity setting", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			CrouchStandToggle = ConfigFile.Bind<bool>("Toggles", "Crouch stand vibration toggle", true, (ConfigDescription)null);
			ButtonHoverIntensity = ConfigFile.Bind<int>("Buttplug", "Hover Button Intensity", 1, new ConfigDescription("Button hover intensity setting", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			ButtonHoverToggle = ConfigFile.Bind<bool>("Toggles", "Hover button vibration toggle", true, (ConfigDescription)null);
			ButtonSelectIntensity = ConfigFile.Bind<int>("Buttplug", "Select button intensity", 1, new ConfigDescription("Button select intensity setting", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			ButtonSelectToggle = ConfigFile.Bind<bool>("Toggles", "Select button vibration toggle", true, (ConfigDescription)null);
			DiscoverValuableIntensity = ConfigFile.Bind<int>("Buttplug", "Discover valuable intensity", 2, new ConfigDescription("Discover valuable intensity setting", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			DiscoverValuableToggle = ConfigFile.Bind<bool>("Toggles", "Discover valuable toggle", true, (ConfigDescription)null);
			DiscoverValuableScalesWithValue = ConfigFile.Bind<bool>("Toggles", "Discover valuable scales toggle", true, new ConfigDescription("Discover valuable scales intensity by value setting", (AcceptableValueBase)null, Array.Empty<object>()));
			DiscoverValuableMinValue = ConfigFile.Bind<int>("Buttplug", "Discover valuable min", 1000, new ConfigDescription("Minimum item value that triggers vibration scaling", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50000), Array.Empty<object>()));
			DiscoverValuableMaxValue = ConfigFile.Bind<int>("Buttplug", "Discover valuable max", 30000, new ConfigDescription("Maximum item value used to scale vibration intensity", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50000), Array.Empty<object>()));
			DiscoverValuableMinIntensity = ConfigFile.Bind<int>("Buttplug", "Discover intensity min", 2, new ConfigDescription("Vibration intensity at the minimum item value", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			DiscoverValuableMaxIntensity = ConfigFile.Bind<int>("Buttplug", "Discover intensity max", 18, new ConfigDescription("Vibration intensity at the maximum item value", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
		}
	}
	[BepInPlugin("Zelfmonco.Replug", "Replug", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ReplugMod : BaseUnityPlugin
	{
		internal static ReplugMod Instance { get; private set; }

		public static ManualLogSource Logger => Instance._logger;

		public ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		internal static DeviceManager DeviceManager { get; private set; }

		private void Awake()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			DeviceManager = new DeviceManager("R.E.P.L.U.G");
			DeviceManager.Connect();
			Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
			val.PatchAll(typeof(PlayerPatch));
			val.PatchAll(typeof(ItemPatch));
			val.PatchAll(typeof(MenuPatch));
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		private void Update()
		{
			if (Input.GetKey((KeyCode)306) && Input.GetKey((KeyCode)308) && Input.GetKeyDown((KeyCode)99))
			{
				DeviceManager.Connect();
				Debug.Log((object)"retrying connection");
			}
		}
	}
}
namespace Replug.Patches
{
	internal class ItemPatch
	{
		[HarmonyPatch(typeof(ItemGun), "ShootBullet")]
		[HarmonyPostfix]
		private static void GunVibration(CameraShake __instance)
		{
			if (Config.GunToggle.Value)
			{
				ReplugMod.DeviceManager.VibrateAllWithDuration((float)Config.GunIntensity.Value / 20f, 0.25f);
			}
		}
	}
	internal class MenuPatch
	{
		[HarmonyPatch(typeof(MenuButton), "OnHoverStart")]
		[HarmonyPostfix]
		private static void HoverVibrate(MenuButton __instance)
		{
			if (Config.ButtonHoverToggle.Value)
			{
				ReplugMod.DeviceManager.VibrateAllWithDuration((float)Config.ButtonHoverIntensity.Value / 20f, 0.1f);
			}
		}

		[HarmonyPatch(typeof(MenuButton), "OnSelectEnd")]
		[HarmonyPostfix]
		private static void SelectVibrate(MenuButton __instance)
		{
			if (Config.ButtonSelectToggle.Value)
			{
				ReplugMod.DeviceManager.VibrateAllWithDuration((float)Config.ButtonSelectIntensity.Value / 20f, 0.1f);
			}
		}
	}
	internal class PlayerPatch
	{
		private static bool canVibeShake;

		[HarmonyPatch(typeof(PlayerHealth), "Hurt")]
		[HarmonyPostfix]
		private static void VibrateOnHurt(PlayerHealth __instance)
		{
			if ((!(__instance.invincibleTimer > 0f) || __instance.photonView.IsMine) && Config.HurtToggle.Value)
			{
				ReplugMod.DeviceManager.VibrateAllWithDuration((float)Config.HurtIntensity.Value / 20f, 1f);
			}
		}

		[HarmonyPatch(typeof(PlayerHealth), "Heal")]
		[HarmonyPostfix]
		private static void VibrateOnHeal(PlayerHealth __instance)
		{
			if ((!(__instance.invincibleTimer > 0f) || __instance.photonView.IsMine) && Config.HealToggle.Value)
			{
				ReplugMod.DeviceManager.VibrateAllWithDuration((float)Config.HealIntensity.Value, 0.5f);
			}
		}

		[HarmonyPatch(typeof(CameraShake), "Update")]
		[HarmonyPostfix]
		private static void VibrateCameraShake(CameraShake __instance)
		{
			if (__instance.Strength > 4f && Config.CameraShakeToggle.Value)
			{
				canVibeShake = true;
			}
			else if (__instance.Strength < 1f && canVibeShake && Config.CameraShakeToggle.Value)
			{
				canVibeShake = false;
				ReplugMod.DeviceManager.StopAllDevices();
			}
			if (canVibeShake && !ReplugMod.DeviceManager.isVibing)
			{
				ReplugMod.DeviceManager.VibrateAllDevices(__instance.Strength * (float)Config.CameraShakeIntensity.Value / 600f);
			}
		}

		[HarmonyPatch(typeof(PlayerAvatar), "StandToCrouch")]
		[HarmonyPostfix]
		private static void VibrateOnCrouch(PlayerAvatar __instance)
		{
			if (Config.CrouchStandToggle.Value)
			{
				ReplugMod.DeviceManager.VibrateAllWithDuration((float)Config.CrouchStandIntensity.Value / 20f, 0.25f);
			}
		}

		[HarmonyPatch(typeof(PlayerAvatar), "CrouchToStand")]
		[HarmonyPostfix]
		private static void VibrateOnStand(PlayerAvatar __instance)
		{
			if (Config.CrouchStandToggle.Value)
			{
				ReplugMod.DeviceManager.VibrateAllWithDuration((float)Config.CrouchStandIntensity.Value / 20f, 0.25f);
			}
		}

		[HarmonyPatch(typeof(ValuableDiscover), "New")]
		[HarmonyPostfix]
		private static void VibrateOnDiscoverValuable(ValuableDiscover __instance, PhysGrabObject _target)
		{
			if (!Config.DiscoverValuableToggle.Value)
			{
				return;
			}
			float num6;
			if (Config.DiscoverValuableScalesWithValue.Value)
			{
				if (!Object.op_Implicit((Object)(object)_target))
				{
					return;
				}
				ValuableObject component = ((Component)((Component)_target).transform).GetComponent<ValuableObject>();
				if (!Object.op_Implicit((Object)(object)component) || !component.discovered)
				{
					return;
				}
				float dollarValueCurrent = component.dollarValueCurrent;
				float num = Config.DiscoverValuableMinValue.Value;
				float num2 = Config.DiscoverValuableMaxValue.Value;
				float num3 = Config.DiscoverValuableMinIntensity.Value;
				float num4 = Config.DiscoverValuableMaxIntensity.Value;
				float num5 = Mathf.Clamp01((dollarValueCurrent - num) / (num2 - num));
				num6 = Mathf.Lerp(num3, num4, num5);
			}
			else
			{
				num6 = Config.DiscoverValuableIntensity.Value;
			}
			ReplugMod.DeviceManager.VibrateAllWithDuration(num6 / 20f, 0.25f);
		}
	}
}