Decompiled source of REPLUG v1.2.0
core/Buttplug.dll
Decompiled 2 months agousing 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
The result has been truncated due to the large size, download it to view full contents!
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 agousing 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); } } }