class GridDelimitedParser implements GridNioParser {
    /** Buffer metadata key. */
    private static final int BUF_META_KEY = GridNioSessionMetaKey.nextUniqueKey();

    /** Delimiter. */
    private final byte[] delim;

    /** Direct buffer. */
    private final boolean directBuf;

    /**
     * @param delim Delimiter.
     * @param directBuf Direct buffer.
     */
    public GridDelimitedParser(byte[] delim, boolean directBuf) {
        this.delim = delim;
        this.directBuf = directBuf;
    }

    /** {@inheritDoc} */
    @Override public byte[] decode(GridNioSession ses, ByteBuffer buf) throws IOException, IgniteCheckedException {<FILL_FUNCTION_BODY>}

    /** {@inheritDoc} */
    @Override public ByteBuffer encode(GridNioSession ses, Object msg) throws IOException, IgniteCheckedException {
        byte[] msg0 = (byte[])msg;

        int cap = msg0.length + delim.length;
        ByteBuffer res = directBuf ? ByteBuffer.allocateDirect(cap) : ByteBuffer.allocate(cap);

        res.put(msg0);
        res.put(delim);

        res.flip();

        return res;
    }

    /** {@inheritDoc} */
    @Override public String toString() {
        return this.getClass().getSimpleName();
    }
}

        GridNioDelimitedBuffer nioBuf = ses.meta(BUF_META_KEY);

        // Decode for a given session is called per one thread, so there should not be any concurrency issues.
        // However, we make some additional checks.
        if (nioBuf == null) {
            nioBuf = new GridNioDelimitedBuffer(delim);

            GridNioDelimitedBuffer old = ses.addMeta(BUF_META_KEY, nioBuf);

            assert old == null;
        }

        return nioBuf.read(buf);
    
<no_super_class>