@Override
    public Object decode(Channel channel, InputStream input) throws IOException {
        if (log.isDebugEnabled()) {
            Thread thread = Thread.currentThread();
            log.debug("Decoding in thread -- [" + thread.getName() + "#" + thread.getId() + "]");
        }

        int contentLength = input.available();
        setAttribute(Constants.CONTENT_LENGTH_KEY, contentLength);

        // switch TCCL
        if (invocation != null && invocation.getServiceModel() != null) {
            Thread.currentThread()
                    .setContextClassLoader(invocation.getServiceModel().getClassLoader());
        }
        ObjectInput in = CodecSupport.getSerialization(serializationType).deserialize(channel.getUrl(), input);

        byte flag = in.readByte();
        switch (flag) {
            case DubboCodec.RESPONSE_NULL_VALUE:
                break;
            case DubboCodec.RESPONSE_VALUE:
                handleValue(in);
                break;
            case DubboCodec.RESPONSE_WITH_EXCEPTION:
                handleException(in);
                break;
            case DubboCodec.RESPONSE_NULL_VALUE_WITH_ATTACHMENTS:
                handleAttachment(in);
                break;
            case DubboCodec.RESPONSE_VALUE_WITH_ATTACHMENTS:
                handleValue(in);
                handleAttachment(in);
                break;
            case DubboCodec.RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS:
                handleException(in);
                handleAttachment(in);
                break;
            default:
                throw new IOException("Unknown result flag, expect '0' '1' '2' '3' '4' '5', but received: " + flag);
        }
        if (in instanceof Cleanable) {
            ((Cleanable) in).cleanup();
        }
        return this;
    }
@Test
    void test() throws Exception {
        // Mock a rpcInvocation, this rpcInvocation is usually generated by the client request, and stored in
        // Request#data
        Byte proto = CodecSupport.getIDByName(DefaultSerializationSelector.getDefaultRemotingSerialization());
        URL url = new ServiceConfigURL("dubbo", "127.0.0.1", 9103, DemoService.class.getName(), VERSION_KEY, "1.0.0");
        ServiceDescriptor serviceDescriptor = repository.registerService(DemoService.class);
        ProviderModel providerModel =
                new ProviderModel(url.getServiceKey(), new DemoServiceImpl(), serviceDescriptor, null, null);
        RpcInvocation rpcInvocation = new RpcInvocation(
                providerModel, "echo", DemoService.class.getName(), "", new Class<?>[] {String.class}, new String[] {
                    "yug"
                });
        rpcInvocation.put(SERIALIZATION_ID_KEY, proto);

        // Mock a response result returned from the server and write to the buffer
        Channel channel = new MockChannel();
        Response response = new Response(1);
        Result result = new AppResponse();
        result.setValue("yug");
        response.setResult(result);
        ChannelBuffer buffer = writeBuffer(url, response, proto, false);

        // The client reads and decode the buffer
        InputStream is = new ChannelBufferInputStream(buffer, buffer.readableBytes());
        DecodeableRpcResult decodeableRpcResult = new DecodeableRpcResult(channel, response, is, rpcInvocation, proto);
        decodeableRpcResult.decode();

        // Verify RESPONSE_VALUE_WITH_ATTACHMENTS
        // Verify that the decodeableRpcResult decoded by the client is consistent with the response returned by the
        // server
        Assertions.assertEquals(decodeableRpcResult.getValue(), result.getValue());
        Assertions.assertTrue(
                CollectionUtils.mapEquals(decodeableRpcResult.getObjectAttachments(), result.getObjectAttachments()));

        // Verify RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS
        Response exResponse = new Response(2);
        Result exResult = new AppResponse();
        exResult.setException(new RpcException(BIZ_EXCEPTION));
        exResponse.setResult(exResult);
        buffer = writeBuffer(url, exResponse, proto, true);
        is = new ChannelBufferInputStream(buffer, buffer.readableBytes());
        decodeableRpcResult = new DecodeableRpcResult(channel, response, is, rpcInvocation, proto);
        decodeableRpcResult.decode();
        Assertions.assertEquals(
                ((RpcException) decodeableRpcResult.getException()).getCode(),
                ((RpcException) exResult.getException()).getCode());
        Assertions.assertTrue(
                CollectionUtils.mapEquals(decodeableRpcResult.getObjectAttachments(), exResult.getObjectAttachments()));
    }