// Path: modbus-core/src/main/java/com/digitalpetri/modbus/ModbusPdu.java
// public interface ModbusPdu {
// 
//     FunctionCode getFunctionCode();
// 
// }
// 
// Path: modbus-core/src/main/java/com/digitalpetri/modbus/UnsupportedPdu.java
// public class UnsupportedPdu implements ModbusPdu {
// 
//     private final FunctionCode functionCode;
// 
//     public UnsupportedPdu(FunctionCode functionCode) {
//         this.functionCode = functionCode;
//     }
// 
//     @Override
//     public FunctionCode getFunctionCode() {
//         return functionCode;
//     }
// 
// }


import java.util.List;
import com.digitalpetri.modbus.ModbusPdu;
import com.digitalpetri.modbus.UnsupportedPdu;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
        int headerStartIndex = buffer.writerIndex();
        buffer.writeZero(MbapHeader.LENGTH);

        int pduStartIndex = buffer.writerIndex();
        encoder.encode(payload.getModbusPdu(), buffer);
        int pduLength = buffer.writerIndex() - pduStartIndex;

        MbapHeader header = new MbapHeader(
            payload.getTransactionId(),
            pduLength + 1,
            payload.getUnitId()
        );

        int currentWriterIndex = buffer.writerIndex();
        buffer.writerIndex(headerStartIndex);
        MbapHeader.encode(header, buffer);
        buffer.writerIndex(currentWriterIndex);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
        int startIndex = buffer.readerIndex();

        while (buffer.readableBytes() >= HeaderLength &&
            buffer.readableBytes() >= getLength(buffer, startIndex) + HeaderSize) {

            try {
                MbapHeader mbapHeader = MbapHeader.decode(buffer);
                ModbusPdu modbusPdu = decoder.decode(buffer);

// Path: modbus-core/src/main/java/com/digitalpetri/modbus/ModbusPdu.java
// public interface ModbusPdu {
// 
//     FunctionCode getFunctionCode();
// 
// }
// 
// Path: modbus-core/src/main/java/com/digitalpetri/modbus/UnsupportedPdu.java
// public class UnsupportedPdu implements ModbusPdu {
// 
//     private final FunctionCode functionCode;
// 
//     public UnsupportedPdu(FunctionCode functionCode) {
//         this.functionCode = functionCode;
//     }
// 
//     @Override
//     public FunctionCode getFunctionCode() {
//         return functionCode;
//     }
// 
// }


// Path: modbus-codec/src/main/java/com/digitalpetri/modbus/codec/ModbusTcpCodec.java
import java.util.List;
import com.digitalpetri.modbus.ModbusPdu;
import com.digitalpetri.modbus.UnsupportedPdu;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

        int headerStartIndex = buffer.writerIndex();
        buffer.writeZero(MbapHeader.LENGTH);

        int pduStartIndex = buffer.writerIndex();
        encoder.encode(payload.getModbusPdu(), buffer);
        int pduLength = buffer.writerIndex() - pduStartIndex;

        MbapHeader header = new MbapHeader(
            payload.getTransactionId(),
            pduLength + 1,
            payload.getUnitId()
        );

        int currentWriterIndex = buffer.writerIndex();
        buffer.writerIndex(headerStartIndex);
        MbapHeader.encode(header, buffer);
        buffer.writerIndex(currentWriterIndex);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
        int startIndex = buffer.readerIndex();

        while (buffer.readableBytes() >= HeaderLength &&
            buffer.readableBytes() >= getLength(buffer, startIndex) + HeaderSize) {

            try {
                MbapHeader mbapHeader = MbapHeader.decode(buffer);
                ModbusPdu modbusPdu = decoder.decode(buffer);

                if (modbusPdu instanceof UnsupportedPdu) {