From 950adb3dff1361a783ca600142e51a93587d637f Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 16 Feb 2015 09:15:11 +0100 Subject: [PATCH] =?UTF-8?q?use=20ByteBuf=20directly=20=E2=80=94=20avoid=20?= =?UTF-8?q?intermediate=20StringBuilder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can create efficient OutputStreamWriter backed by ByteBuf, but it will be implemented later --- .../jetbrains/io/jsonRpc/JsonRpcServer.java | 143 +++++++++++++----- .../src/io/netty/buffer/ByteBufUtilEx.java | 68 +++++++++ .../src/org/jetbrains/io/JsonUtil.java | 38 +++++ .../src/org/jetbrains/io/NettyUtil.java | 4 +- .../debugger/StandaloneVmHelper.java | 3 +- .../src/org/jetbrains/rpc/MessageWriter.java | 8 +- .../protocol-reader-runtime.iml | 1 + .../jetbrains/jsonProtocol/OutMessage.java | 43 +++--- .../org/jetbrains/jsonProtocol/Request.java | 3 +- .../jetbrains/jsonProtocol/StringWriter.java | 84 ---------- 10 files changed, 244 insertions(+), 151 deletions(-) create mode 100644 platform/platform-impl/src/io/netty/buffer/ByteBufUtilEx.java delete mode 100644 platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/StringWriter.java diff --git a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.java b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.java index 9f215e05e9b0..6b984b2013f2 100644 --- a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.java +++ b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.java @@ -1,7 +1,6 @@ package org.jetbrains.io.jsonRpc; import com.google.gson.*; -import com.google.gson.internal.Streams; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; @@ -9,6 +8,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.ArrayUtil; import com.intellij.util.ArrayUtilRt; import com.intellij.util.Consumer; @@ -17,10 +17,7 @@ import com.intellij.util.text.CharSequenceBackedByArray; import gnu.trove.THashMap; import gnu.trove.TIntArrayList; import gnu.trove.TIntProcedure; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.ByteBufUtil; -import io.netty.util.CharsetUtil; +import io.netty.buffer.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.concurrency.AsyncPromise; @@ -29,9 +26,10 @@ import org.jetbrains.io.JsonReaderEx; import org.jetbrains.io.JsonUtil; import java.io.IOException; +import java.io.OutputStreamWriter; import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.nio.CharBuffer; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -171,12 +169,12 @@ public class JsonRpcServer implements MessageServer { } } - public void sendResponse(int messageId, @NotNull Client client, @Nullable CharSequence rawMessage) { + public void sendResponse(int messageId, @NotNull Client client, @Nullable ByteBuf rawMessage) { client.send(encodeMessage(client.getByteBufAllocator(), messageId, null, null, rawMessage, ArrayUtil.EMPTY_OBJECT_ARRAY)); } public void sendErrorResponse(int messageId, @NotNull Client client, @Nullable CharSequence rawMessage) { - client.send(encodeMessage(client.getByteBufAllocator(), messageId, "e", null, rawMessage, ArrayUtil.EMPTY_OBJECT_ARRAY)); + client.send(encodeMessage(client.getByteBufAllocator(), messageId, "e", null, null, new Object[]{rawMessage})); } @SuppressWarnings("unused") @@ -194,7 +192,7 @@ public class JsonRpcServer implements MessageServer { clientManager.send(messageId, encodeMessage(ByteBufAllocator.DEFAULT, messageId, domain, command, null, params), results); } - public boolean sendWithRawPart(@NotNull Client client, @NotNull String domain, @NotNull String command, @Nullable CharSequence rawMessage, Object... params) { + public boolean sendWithRawPart(@NotNull Client client, @NotNull String domain, @NotNull String command, @Nullable ByteBuf rawMessage, Object... params) { client.send(encodeMessage(client.getByteBufAllocator(), -1, domain, command, rawMessage, params)); return true; } @@ -217,58 +215,100 @@ public class JsonRpcServer implements MessageServer { int messageId, @Nullable String domain, @Nullable String command, - @Nullable CharSequence rawData, + @Nullable ByteBuf rawData, @Nullable Object[] params) { - StringBuilder sb = new StringBuilder(); + ByteBuf buffer = byteBufAllocator.ioBuffer(); + boolean success = false; try { - doEncodeMessage(sb, messageId, domain, command, params == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : params, rawData); + Object[] notNullParams = params == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : params; + buffer = doEncodeMessage(byteBufAllocator, buffer, messageId, domain, command, notNullParams, rawData); if (LOG.isDebugEnabled()) { - LOG.debug("OUT " + sb.toString()); + LOG.debug("OUT " + domain + '.' + command + (notNullParams.length == 0 ? "" : " " + Arrays.toString(params)) + (rawData == null ? "" : " " + rawData.toString(CharsetToolkit.UTF8_CHARSET))); } - return ByteBufUtil.encodeString(byteBufAllocator, CharBuffer.wrap(sb), CharsetUtil.UTF_8); + success = true; + return buffer; } catch (IOException e) { throw new RuntimeException(e); } + finally { + if (!success) { + buffer.release(); + } + } } - private void doEncodeMessage(@NotNull StringBuilder sb, int id, @Nullable String domain, @Nullable String command, @NotNull Object[] params, @Nullable CharSequence rawData) throws IOException { - sb.append('['); + @NotNull + private ByteBuf doEncodeMessage(@NotNull ByteBufAllocator byteBufAllocator, + @NotNull ByteBuf buffer, + int id, + @Nullable String domain, + @Nullable String command, + @NotNull Object[] params, + @Nullable ByteBuf rawData) throws IOException { + buffer.writeByte('['); + ByteBuf effectiveBuffer = buffer; boolean hasPrev = false; + StringBuilder sb = null; if (id != -1) { - sb.append(id); + sb = new StringBuilder(); + ByteBufUtil.writeAscii(buffer, sb.append(id)); + sb.setLength(0); hasPrev = true; } if (domain != null) { if (hasPrev) { - sb.append(','); + buffer.writeByte(','); } - sb.append('"').append(domain).append("\",\""); - + buffer.writeByte('"'); + ByteBufUtil.writeAscii(buffer, domain); + buffer.writeByte('"').writeByte(',').writeByte('"'); if (command == null) { if (rawData != null) { - sb.append(rawData); + effectiveBuffer = byteBufAllocator.compositeBuffer().addComponent(buffer).addComponent(rawData); + buffer = byteBufAllocator.ioBuffer(); } - sb.append('"'); - return; + buffer.writeByte('"'); + return addBuffer(effectiveBuffer, buffer); } else { - sb.append(command).append('"'); + ByteBufUtil.writeAscii(buffer, command); + buffer.writeByte('"'); } } - encodeParameters(sb, params, rawData); - sb.append(']'); + encodeParameters(buffer, params, rawData, sb); + if (rawData != null) { + if (params.length > 0) { + buffer.writeByte(','); + } + effectiveBuffer = byteBufAllocator.compositeBuffer().addComponent(buffer).addComponent(rawData); + buffer = byteBufAllocator.ioBuffer(); + } + buffer.writeByte(']'); + + buffer.writeByte(']'); + return addBuffer(effectiveBuffer, buffer); } - private void encodeParameters(@NotNull StringBuilder sb, @NotNull Object[] params, @Nullable CharSequence rawData) throws IOException { + @NotNull + // addComponent always add sliced component, so, we must add last buffer only after all writes + private static ByteBuf addBuffer(@NotNull ByteBuf buffer, @NotNull ByteBuf lastComponent) { + if (buffer != lastComponent) { + ((CompositeByteBuf)buffer).addComponent(lastComponent); + buffer.writerIndex(buffer.capacity()); + } + return buffer; + } + + private void encodeParameters(@NotNull ByteBuf buffer, @NotNull Object[] params, @Nullable ByteBuf rawData, @Nullable StringBuilder sb) throws IOException { JsonWriter writer = null; - sb.append(',').append('['); + buffer.writeByte(',').writeByte('['); boolean hasPrev = false; for (Object param : params) { if (hasPrev) { - sb.append(','); + buffer.writeByte(','); } else { hasPrev = true; @@ -276,34 +316,53 @@ public class JsonRpcServer implements MessageServer { // gson - SOE if param has type class com.intellij.openapi.editor.impl.DocumentImpl$MyCharArray, so, use hack if (param instanceof CharSequence) { - JsonUtil.escape(((CharSequence)param), sb); + JsonUtil.escape(((CharSequence)param), buffer); } else if (param == null) { - sb.append("null"); + ByteBufUtil.writeAscii(buffer, "null"); } - else if (param instanceof Number || param instanceof Boolean) { - sb.append(param.toString()); + else if (param instanceof Boolean) { + ByteBufUtil.writeAscii(buffer, param.toString()); + } + else if (param instanceof Number) { + if (sb == null) { + sb = new StringBuilder(); + } + if (param instanceof Integer) { + sb.append(((Integer)param).intValue()); + } + else if (param instanceof Long) { + sb.append(((Long)param).longValue()); + } + else if (param instanceof Float) { + sb.append(((Float)param).floatValue()); + } + else if (param instanceof Double) { + sb.append(((Double)param).doubleValue()); + } + else { + sb.append(param.toString()); + } + ByteBufUtil.writeAscii(buffer, sb); + sb.setLength(0); } else if (param instanceof Consumer) { + if (sb == null) { + sb = new StringBuilder(); + } //noinspection unchecked ((Consumer)param).consume(sb); + ByteBufUtil.writeUtf8(buffer, sb); + sb.setLength(0); } else { if (writer == null) { - writer = new JsonWriter(Streams.writerForAppendable(sb)); + writer = new JsonWriter(new OutputStreamWriter(new ByteBufOutputStream(buffer))); } //noinspection unchecked ((TypeAdapter)gson.getAdapter(param.getClass())).write(writer, param); } } - - if (rawData != null) { - if (hasPrev) { - sb.append(','); - } - sb.append(rawData); - } - sb.append(']'); } private static class IntArrayListTypeAdapter extends TypeAdapter { diff --git a/platform/platform-impl/src/io/netty/buffer/ByteBufUtilEx.java b/platform/platform-impl/src/io/netty/buffer/ByteBufUtilEx.java new file mode 100644 index 000000000000..e959d0903fb0 --- /dev/null +++ b/platform/platform-impl/src/io/netty/buffer/ByteBufUtilEx.java @@ -0,0 +1,68 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.netty.buffer; + +import io.netty.util.CharsetUtil; + +public class ByteBufUtilEx { + // todo pull request + public static int writeUtf8(ByteBuf buf, CharSequence seq, int start, int end) { + if (buf == null) { + throw new NullPointerException("buf"); + } + if (seq == null) { + throw new NullPointerException("seq"); + } + // UTF-8 uses max. 3 bytes per char, so calculate the worst case. + final int len = end - start; + final int maxSize = len * 3; + buf.ensureWritable(maxSize); + if (buf instanceof AbstractByteBuf) { + // Fast-Path + AbstractByteBuf buffer = (AbstractByteBuf)buf; + int oldWriterIndex = buffer.writerIndex; + int writerIndex = oldWriterIndex; + + // We can use the _set methods as these not need to do any index checks and reference checks. + // This is possible as we called ensureWritable(...) before. + for (int i = start; i < end; i++) { + char c = seq.charAt(i); + if (c < 0x80) { + buffer._setByte(writerIndex++, (byte)c); + } + else if (c < 0x800) { + buffer._setByte(writerIndex++, (byte)(0xc0 | (c >> 6))); + buffer._setByte(writerIndex++, (byte)(0x80 | (c & 0x3f))); + } + else { + buffer._setByte(writerIndex++, (byte)(0xe0 | (c >> 12))); + buffer._setByte(writerIndex++, (byte)(0x80 | ((c >> 6) & 0x3f))); + buffer._setByte(writerIndex++, (byte)(0x80 | (c & 0x3f))); + } + } + // update the writerIndex without any extra checks for performance reasons + buffer.writerIndex = writerIndex; + return writerIndex - oldWriterIndex; + } + else { + // Maybe we could also check if we can unwrap() to access the wrapped buffer which + // may be an AbstractByteBuf. But this may be overkill so let us keep it simple for now. + byte[] bytes = seq.toString().getBytes(CharsetUtil.UTF_8); + buf.writeBytes(bytes); + return bytes.length; + } + } +} diff --git a/platform/platform-impl/src/org/jetbrains/io/JsonUtil.java b/platform/platform-impl/src/org/jetbrains/io/JsonUtil.java index d9a1514c137d..e1a0737bc0c9 100644 --- a/platform/platform-impl/src/org/jetbrains/io/JsonUtil.java +++ b/platform/platform-impl/src/org/jetbrains/io/JsonUtil.java @@ -3,6 +3,9 @@ package org.jetbrains.io; import com.intellij.util.ArrayUtil; import com.intellij.util.SmartList; import gnu.trove.THashMap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.ByteBufUtilEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -62,6 +65,41 @@ public class JsonUtil { sb.append('"'); } + public static void escape(@NotNull CharSequence value, @NotNull ByteBuf buffer) { + int length = value.length(); + buffer.ensureWritable(length * 2); + buffer.writeByte('"'); + int last = 0; + for (int i = 0; i < length; i++) { + char c = value.charAt(i); + String replacement; + if (c < 128) { + replacement = REPLACEMENT_CHARS[c]; + if (replacement == null) { + continue; + } + } + else if (c == '\u2028') { + replacement = "\\u2028"; + } + else if (c == '\u2029') { + replacement = "\\u2029"; + } + else { + continue; + } + if (last < i) { + ByteBufUtilEx.writeUtf8(buffer, value, last, i); + } + ByteBufUtil.writeAscii(buffer, replacement); + last = i + 1; + } + if (last < length) { + ByteBufUtilEx.writeUtf8(buffer, value, last, length); + } + buffer.writeByte('"'); + } + @NotNull public static List nextList(@NotNull JsonReaderEx reader) { reader.beginArray(); diff --git a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java index 99a8f6896f17..c38e372b9c07 100644 --- a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java +++ b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java @@ -29,6 +29,8 @@ import io.netty.channel.socket.oio.OioSocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; +import io.netty.handler.codec.http.cors.CorsConfig; +import io.netty.handler.codec.http.cors.CorsHandler; import io.netty.handler.stream.ChunkedWriteHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -217,6 +219,6 @@ public final class NettyUtil { if (pipeline.get(ChunkedWriteHandler.class) == null) { pipeline.addLast("chunkedWriteHandler", new ChunkedWriteHandler()); } - //pipeline.addLast("corsHandler", new CorsHandler(CorsConfig.withAnyOrigin().allowCredentials().allowNullOrigin().allowedRequestMethods().build())); + pipeline.addLast("corsHandler", new CorsHandler(CorsConfig.withAnyOrigin().allowCredentials().allowNullOrigin().allowedRequestMethods().build())); } } \ No newline at end of file diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/StandaloneVmHelper.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/StandaloneVmHelper.java index 82cd52640f67..232a47c4cb7b 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/StandaloneVmHelper.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/StandaloneVmHelper.java @@ -1,6 +1,7 @@ package org.jetbrains.debugger; import com.intellij.util.Consumer; +import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; @@ -23,7 +24,7 @@ public class StandaloneVmHelper extends MessageWriter implements Vm.AttachStateM } @Override - public boolean write(@NotNull CharSequence content) { + public boolean write(@NotNull ByteBuf content) { return write(((Object)content)); } diff --git a/platform/script-debugger/backend/src/org/jetbrains/rpc/MessageWriter.java b/platform/script-debugger/backend/src/org/jetbrains/rpc/MessageWriter.java index 17a850eb24d9..07dbee19f922 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/rpc/MessageWriter.java +++ b/platform/script-debugger/backend/src/org/jetbrains/rpc/MessageWriter.java @@ -1,6 +1,8 @@ package org.jetbrains.rpc; +import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.BooleanFunction; +import io.netty.buffer.ByteBuf; import org.jetbrains.annotations.NotNull; import org.jetbrains.jsonProtocol.Request; @@ -9,9 +11,9 @@ import static org.jetbrains.rpc.CommandProcessor.LOG; public abstract class MessageWriter implements BooleanFunction { @Override public boolean fun(@NotNull Request message) { - CharSequence content = message.toJson(); + ByteBuf content = message.getBuffer(); if (isDebugLoggingEnabled()) { - LOG.debug("OUT: " + content.toString()); + LOG.debug("OUT: " + content.toString(CharsetToolkit.UTF8_CHARSET)); } return write(content); } @@ -20,5 +22,5 @@ public abstract class MessageWriter implements BooleanFunction { return LOG.isDebugEnabled(); } - protected abstract boolean write(@NotNull CharSequence content); + protected abstract boolean write(@NotNull ByteBuf content); } \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/protocol-reader-runtime.iml b/platform/script-debugger/protocol/protocol-reader-runtime/protocol-reader-runtime.iml index 464a4cc3ab67..9e00b8655e5e 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/protocol-reader-runtime.iml +++ b/platform/script-debugger/protocol/protocol-reader-runtime/protocol-reader-runtime.iml @@ -10,5 +10,6 @@ + \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.java index a9e600e6225b..585a9f8fe424 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.java @@ -1,22 +1,28 @@ package org.jetbrains.jsonProtocol; import com.google.gson.stream.JsonWriter; +import com.intellij.openapi.vfs.CharsetToolkit; import gnu.trove.TIntArrayList; import gnu.trove.TIntHashSet; import gnu.trove.TIntProcedure; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.ByteBufUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.io.JsonUtil; import java.io.IOException; +import java.io.OutputStreamWriter; import java.util.Collection; import java.util.List; import java.util.Map; public abstract class OutMessage { - @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") - private final StringWriter stringWriter = new StringWriter(); - public final JsonWriter writer = new JsonWriter(stringWriter); + // todo don't want to risk - are we really can release it properly? heap buffer for now + private final ByteBuf buffer = ByteBufAllocator.DEFAULT.heapBuffer(); + public final JsonWriter writer = new JsonWriter(new OutputStreamWriter(new ByteBufOutputStream(buffer))); private boolean finalized; @@ -177,13 +183,12 @@ public abstract class OutMessage { boolean isNotFirst = false; for (OutMessage item : value) { if (isNotFirst) { - stringWriter.append(',').append(' '); + buffer.writeByte(',').writeByte(' '); } else { isNotFirst = true; } - StringBuilder buffer = item.stringWriter.getBuffer(); if (!item.finalized) { item.finalized = true; try { @@ -191,7 +196,7 @@ public abstract class OutMessage { } catch (IllegalStateException e) { if ("Nesting problem.".equals(e.getMessage())) { - throw new RuntimeException(item.stringWriter.getBuffer() + "\nparent:\n" + stringWriter.getBuffer(), e); + throw new RuntimeException(item.buffer.toString(CharsetToolkit.UTF8_CHARSET) + "\nparent:\n" + buffer.toString(CharsetToolkit.UTF8_CHARSET), e); } else { throw e; @@ -199,7 +204,7 @@ public abstract class OutMessage { } } - stringWriter.append(buffer); + buffer.writeBytes(item.buffer); } writer.endArray(); } @@ -218,26 +223,26 @@ public abstract class OutMessage { } } - public static void prepareWriteRaw(OutMessage message, String name) throws IOException { + public static void prepareWriteRaw(@NotNull OutMessage message, @NotNull String name) throws IOException { message.writer.name(name).nullValue(); - StringBuilder myBuffer = message.stringWriter.getBuffer(); - myBuffer.delete(myBuffer.length() - "null".length(), myBuffer.length()); + message.writer.flush(); + ByteBuf itemBuffer = message.buffer; + itemBuffer.writerIndex(itemBuffer.writerIndex() - "null".length()); } - public static void doWriteRaw(OutMessage message, String rawValue) { - message.stringWriter.append(rawValue); + public static void doWriteRaw(@NotNull OutMessage message, @NotNull String rawValue) { + ByteBufUtil.writeUtf8(message.buffer, rawValue); } - protected final void writeMessage(String name, OutMessage value) { + protected final void writeMessage(@NotNull String name, @NotNull OutMessage value) { try { beginArguments(); prepareWriteRaw(this, name); - StringBuilder buffer = value.stringWriter.getBuffer(); if (!value.finalized) { value.close(); } - stringWriter.append(buffer); + buffer.writeBytes(value.buffer); } catch (IOException e) { throw new RuntimeException(e); @@ -287,11 +292,11 @@ public abstract class OutMessage { } } - protected final void writeString(String name, CharSequence value) { + protected final void writeString(@NotNull String name, CharSequence value) { if (value != null) { try { prepareWriteRaw(this, name); - JsonUtil.escape(value, stringWriter.getBuffer()); + JsonUtil.escape(value, buffer); } catch (IOException e) { throw new RuntimeException(e); @@ -311,7 +316,7 @@ public abstract class OutMessage { @NotNull @SuppressWarnings("UnusedDeclaration") - public final CharSequence toJson() { - return stringWriter.getBuffer(); + public final ByteBuf getBuffer() { + return buffer; } } \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/Request.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/Request.java index cc98b67ccd4e..6876a9c24d4f 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/Request.java +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/Request.java @@ -1,10 +1,11 @@ package org.jetbrains.jsonProtocol; +import io.netty.buffer.ByteBuf; import org.jetbrains.annotations.NotNull; public interface Request { @NotNull - CharSequence toJson(); + ByteBuf getBuffer(); String getMethodName(); diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/StringWriter.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/StringWriter.java deleted file mode 100644 index 774f5ff68f1b..000000000000 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/StringWriter.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.jetbrains.jsonProtocol; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.io.Writer; - -public class StringWriter extends Writer { - private final StringBuilder builder; - - public StringWriter() { - builder = new StringBuilder(); - lock = builder; - } - - public StringWriter(int initialSize) { - if (initialSize < 0) { - throw new IllegalArgumentException("Negative buffer size"); - } - - builder = new StringBuilder(initialSize); - lock = builder; - } - - @Override - public void write(int c) { - builder.append((char)c); - } - - @Override - public void write(@NotNull char[] chars, int off, int len) { - builder.append(chars, off, len); - } - - @Override - public void write(@NotNull String string) { - builder.append(string); - } - - @Override - public void write(@NotNull String str, int off, int length) { - builder.append(str, off, off + length); - } - - @NotNull - @Override - public StringWriter append(CharSequence charSequence) { - builder.append(charSequence); - return this; - } - - @NotNull - @Override - public StringWriter append(CharSequence charSequence, int start, int end) { - builder.append(charSequence, start, end); - return this; - } - - @NotNull - @Override - public StringWriter append(char c) { - write(c); - return this; - } - - public String toString() { - return builder.toString(); - } - - public StringBuilder getBuffer() { - return builder; - } - - /** - * Flush the stream. - */ - @Override - public void flush() { - } - - @Override - public void close() throws IOException { - } -} \ No newline at end of file