private static EventFilter CreateFilter(EventKind internalEventKind, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, RequestId requestId, SuspendPolicy suspendPolicy, ImmutableList<EventRequestModifier> modifiers, EventRequestModifier modifier)
            {
                switch (modifier.Kind)
                {
                case ModifierKind.Count:
                    return new CountEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, modifier.Count);

                case ModifierKind.ThreadFilter:
                    return new ThreadEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, modifier.Thread);

                case ModifierKind.ClassTypeFilter:
                    throw new NotImplementedException();

                case ModifierKind.ClassMatchFilter:
                    throw new NotImplementedException();

                case ModifierKind.ClassExcludeFilter:
                    throw new NotImplementedException();

                case ModifierKind.LocationFilter:
                    return new LocationEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, modifier.Location);

                case ModifierKind.ExceptionFilter:
                    return new ExceptionEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, modifier.ExceptionOrNull, modifier.Caught, modifier.Uncaught);

                case ModifierKind.FieldFilter:
                    throw new NotImplementedException();

                case ModifierKind.Step:
                    return new StepEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, modifier.Thread, environment, nativeEnvironment, modifier.StepSize, modifier.StepDepth);

                case ModifierKind.InstanceFilter:
                    throw new NotImplementedException();

                case ModifierKind.SourceNameMatchFilter:
                    throw new NotImplementedException();

                case ModifierKind.Conditional:
                    throw new NotImplementedException();

                case ModifierKind.Invalid:
                default:
                    throw new ArgumentException();
                }
            }
        public Error SetEvent(out RequestId requestId, EventKind eventKind, SuspendPolicy suspendPolicy, EventRequestModifier[] modifiers)
        {
            if (eventKind == EventKind.SingleStep && modifiers.Length == 1 && modifiers[0].Thread == default(ThreadId))
            {
                ThreadId[] threads;
                Error threadsErrorCode = GetAllThreads(out threads);
                if (threadsErrorCode != Error.None)
                {
                    requestId = default(RequestId);
                    return threadsErrorCode;
                }

                requestId = default(RequestId);

                threadsErrorCode = Suspend();
                if (threadsErrorCode != Error.None)
                    return threadsErrorCode;

                List<RequestId> requests = new List<RequestId>();
                foreach (var thread in threads)
                {
                    EventRequestModifier modifier = modifiers[0];
                    modifier.Thread = thread;
                    threadsErrorCode = SetEvent(out requestId, eventKind, suspendPolicy, new[] { modifier });
                    if (threadsErrorCode != Error.None)
                        return threadsErrorCode;

                    requests.Add(requestId);
                }

                _linkedRequests[requestId] = requests;
                foreach (var request in requests)
                    _requestRemap[request] = requestId;

                threadsErrorCode = Resume();
                if (threadsErrorCode != Error.None)
                    return threadsErrorCode;

                return Error.None;
            }

            byte[] packet = new byte[HeaderSize + 6];
            packet[HeaderSize] = (byte)eventKind;
            packet[HeaderSize + 1] = (byte)suspendPolicy;
            WriteInt32(packet, HeaderSize + 2, modifiers.Length);

            List<byte> packetData = new List<byte>(packet);
            foreach (EventRequestModifier modifier in modifiers)
            {
                packetData.Add((byte)modifier.Kind);

                switch (modifier.Kind)
                {
                case ModifierKind.Count:
                    {
                        byte[] additionalData = new byte[sizeof(int)];
                        WriteInt32(additionalData, 0, modifier.Count);
                        packetData.AddRange(additionalData);
                    }
                    continue;

                case ModifierKind.Conditional:
                    {
                        byte[] additionalData = new byte[sizeof(int)];
                        WriteInt32(additionalData, 0, modifier.ExpressionId);
                        packetData.AddRange(additionalData);
                    }
                    continue;

                case ModifierKind.ThreadFilter:
                    {
                        byte[] additionalData = new byte[ThreadIdSize];
                        WriteObjectId(additionalData, 0, modifier.Thread);
                        packetData.AddRange(additionalData);
                    }
                    continue;

                case ModifierKind.ClassTypeFilter:
                    {
                        byte[] additionalData = new byte[ReferenceTypeIdSize];
                        WriteReferenceTypeId(additionalData, 0, modifier.Class);
                        packetData.AddRange(additionalData);
                    }
                    continue;

                case ModifierKind.ClassMatchFilter:
                case ModifierKind.ClassExcludeFilter:
                    {
                        byte[] stringData = Encoding.UTF8.GetBytes(modifier.ClassPattern);
                        byte[] sizeData = new byte[sizeof(int)];
                        WriteInt32(sizeData, 0, stringData.Length);
                        packetData.AddRange(sizeData);
                        packetData.AddRange(stringData);
                    }
                    continue;

                case ModifierKind.LocationFilter:
                    {
                        byte[] additionalData = new byte[LocationSize];
                        WriteLocation(additionalData, 0, modifier.Location);
                        packetData.AddRange(additionalData);
                    }
                    continue;

                case ModifierKind.ExceptionFilter:
                    {
                        byte[] additionalData = new byte[_referenceTypeIdSize.Value + 2];
                        WriteReferenceTypeId(additionalData, 0, modifier.ExceptionOrNull);
                        additionalData[_referenceTypeIdSize.Value] = (byte)(modifier.Caught ? 1 : 0);
                        additionalData[_referenceTypeIdSize.Value + 1] = (byte)(modifier.Uncaught ? 1 : 0);
                        packetData.AddRange(additionalData);
                    }
                    continue;

                case ModifierKind.FieldFilter:
                    {
                        byte[] additionalData = new byte[ReferenceTypeIdSize + FieldIdSize];
                        WriteReferenceTypeId(additionalData, 0, modifier.Class);
                        WriteFieldId(additionalData, ReferenceTypeIdSize, modifier.Field);
                        packetData.AddRange(additionalData);
                    }
                    continue;

                case ModifierKind.Step:
                    {
                        if (modifier.StepSize == StepSize.Statement)
                            throw new NotSupportedException();

                        byte[] additionalData = new byte[ThreadIdSize + (2 * sizeof(int))];
                        WriteObjectId(additionalData, 0, modifier.Thread);
                        WriteInt32(additionalData, ThreadIdSize, (int)modifier.StepSize);
                        WriteInt32(additionalData, ThreadIdSize + sizeof(int), (int)modifier.StepDepth);
                        packetData.AddRange(additionalData);
                    }
                    continue;

                case ModifierKind.InstanceFilter:
                    {
                        byte[] additionalData = new byte[ObjectIdSize];
                        WriteObjectId(additionalData, 0, modifier.Instance);
                        packetData.AddRange(additionalData);
                    }
                    continue;

                case ModifierKind.SourceNameMatchFilter:
                    {
                        byte[] stringData = Encoding.UTF8.GetBytes(modifier.SourceNamePattern);
                        byte[] sizeData = new byte[sizeof(int)];
                        WriteInt32(sizeData, 0, stringData.Length);
                        packetData.AddRange(sizeData);
                        packetData.AddRange(stringData);
                    }
                    continue;

                case ModifierKind.Invalid:
                default:
                    throw new InvalidOperationException();
                }
            }

            packet = packetData.ToArray();
            int id = GetMessageId();
            SerializeHeader(packet, id, EventRequestCommand.Set);

            byte[] response = SendPacket(id, packet);
            Error errorCode = ReadErrorCode(response);
            if (errorCode != Error.None)
            {
                requestId = default(RequestId);
                return errorCode;
            }

            int offset = HeaderSize;
            requestId = new RequestId(ReadInt32(response, ref offset));
            return Error.None;
        }
        public Error SetEvent(EventKind eventKind, SuspendPolicy suspendPolicy, EventRequestModifier[] modifiers, out RequestId requestId)
        {
            requestId = default(RequestId);

            JniEnvironment nativeEnvironment;
            JvmtiEnvironment environment;
            jvmtiError error = GetEnvironment(out environment, out nativeEnvironment);
            if (error != jvmtiError.None)
                return GetStandardError(error);

            return _eventProcessor.SetEvent(environment, nativeEnvironment, eventKind, suspendPolicy, new ImmutableList<EventRequestModifier>(modifiers), false, out requestId);
        }