Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of REPLUG v1.2.0
core/Buttplug.dll
Decompiled a year 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 a year 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 a year 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); } } }