public static void encodePayload(Packet[] packets, EncodeCallback<byte[]> callback) {
        if (packets.length == 0) {
            callback.call(new byte[0]);
            return;
        }

        final ArrayList<byte[]> results = new ArrayList<byte[]>(packets.length);

        for (Packet packet : packets) {
            encodePacket(packet, new EncodeCallback() {
                @Override
                public void call(Object packet) {
                    if (packet instanceof String) {
                        String encodingLength = String.valueOf(((String) packet).length());
                        byte[] sizeBuffer = new byte[encodingLength.length() + 2];

                        sizeBuffer[0] = (byte)0; // is a string
                        for (int i = 0; i < encodingLength.length(); i ++) {
                            sizeBuffer[i + 1] = (byte)Character.getNumericValue(encodingLength.charAt(i));
                        }
                        sizeBuffer[sizeBuffer.length - 1] = (byte)255;
                        results.add(Buffer.concat(new byte[][] {sizeBuffer, stringToByteArray((String)packet)}));
                        return;
                    }

                    String encodingLength = String.valueOf(((byte[])packet).length);
                    byte[] sizeBuffer = new byte[encodingLength.length() + 2];
                    sizeBuffer[0] = (byte)1; // is binary
                    for (int i = 0; i < encodingLength.length(); i ++) {
                        sizeBuffer[i + 1] = (byte)Character.getNumericValue(encodingLength.charAt(i));
                    }
                    sizeBuffer[sizeBuffer.length - 1] = (byte)255;
                    results.add(Buffer.concat(new byte[][] {sizeBuffer, (byte[])packet}));
                }
            });
        }

        callback.call(Buffer.concat(results.toArray(new byte[results.size()][])));
    }