All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.digitalpetri.enip.cip.epath.LogicalSegment Maven / Gradle / Ivy

package com.digitalpetri.enip.cip.epath;

import com.digitalpetri.enip.cip.structs.ElectronicKey;
import io.netty.buffer.ByteBuf;

public abstract class LogicalSegment extends EPathSegment {

    public static final int SEGMENT_TYPE = 0x01;

    private final T value;
    private final LogicalType type;
    private final LogicalFormat format;

    protected LogicalSegment(T value, LogicalType type, LogicalFormat format) {
        this.value = value;
        this.type = type;
        this.format = format;
    }

    public T getValue() {
        return value;
    }

    public LogicalType getType() {
        return type;
    }

    public LogicalFormat getFormat() {
        return format;
    }

    protected abstract ByteBuf encodeValue(ByteBuf buffer);

    protected static LogicalFormat smallestFormat(int value) {
        if ((value & 0xFF) == value) {
            return LogicalFormat.Bits_8;
        } else if ((value & 0xFFFF) == value) {
            return LogicalFormat.Bits_16;
        } else {
            return LogicalFormat.Bits_32;
        }
    }

    public static ByteBuf encode(LogicalSegment segment, boolean padded, ByteBuf buffer) {
        int segmentByte = 0;

        segmentByte |= (SEGMENT_TYPE << 5);
        segmentByte |= (segment.getType().getType() << 2);
        segmentByte |= segment.getFormat().getType();

        buffer.writeByte(segmentByte);

        if (padded && (segment.getFormat() == LogicalFormat.Bits_16 || segment.getFormat() == LogicalFormat.Bits_32)) {
            buffer.writeByte(0x00);
        }

        segment.encodeValue(buffer);

        return buffer;
    }

    private static ByteBuf encodeIntValue(LogicalFormat format, int value, ByteBuf buffer) {
        switch (format) {
            case Bits_8:
                return buffer.writeByte(value);
            case Bits_16:
                return buffer.writeShort(value);
            case Bits_32:
                return buffer.writeInt(value);
            case Reserved:
            default:
                throw new IllegalStateException("Reserved segment type not supported");
        }
    }

    private static ByteBuf encodeKeyValue(LogicalFormat format, ElectronicKey value, ByteBuf buffer) {
        return ElectronicKey.encode(value, buffer);
    }

    public static final class ClassId extends LogicalSegment {

        public ClassId(Integer value) {
            this(value, smallestFormat(value));
        }

        public ClassId(int value, LogicalFormat format) {
            super(value, LogicalType.ClassId, format);
        }

        @Override
        protected ByteBuf encodeValue(ByteBuf buffer) {
            return encodeIntValue(getFormat(), getValue(), buffer);
        }

    }

    public static final class InstanceId extends LogicalSegment {

        public InstanceId(int value) {
            this(value, smallestFormat(value));
        }

        public InstanceId(int value, LogicalFormat format) {
            super(value, LogicalType.InstanceId, format);
        }

        @Override
        protected ByteBuf encodeValue(ByteBuf buffer) {
            return encodeIntValue(getFormat(), getValue(), buffer);
        }

    }

    public static final class MemberId extends LogicalSegment {

        public MemberId(Integer value) {
            this(value, smallestFormat(value));
        }

        public MemberId(Integer value, LogicalFormat format) {
            super(value, LogicalType.MemberId, format);
        }

        @Override
        protected ByteBuf encodeValue(ByteBuf buffer) {
            return encodeIntValue(getFormat(), getValue(), buffer);
        }

    }

    public static final class ConnectionPoint extends LogicalSegment {

        public ConnectionPoint(Integer value) {
            this(value, smallestFormat(value));
        }

        public ConnectionPoint(Integer value, LogicalFormat format) {
            super(value, LogicalType.ConnectionPoint, format);
        }

        @Override
        protected ByteBuf encodeValue(ByteBuf buffer) {
            return encodeIntValue(getFormat(), getValue(), buffer);
        }

    }

    public static final class AttributeId extends LogicalSegment {

        public AttributeId(Integer value) {
            super(value, LogicalType.AttributeId, smallestFormat(value));
        }

        public AttributeId(Integer value, LogicalFormat format) {
            super(value, LogicalType.AttributeId, format);
        }

        @Override
        protected ByteBuf encodeValue(ByteBuf buffer) {
            return encodeIntValue(getFormat(), getValue(), buffer);
        }

    }

    public static final class ServiceId extends LogicalSegment {

        public ServiceId(Integer value, LogicalFormat format) {
            super(value, LogicalType.ServiceId, format);
        }

        @Override
        protected ByteBuf encodeValue(ByteBuf buffer) {
            return encodeIntValue(getFormat(), getValue(), buffer);
        }

    }

    public static final class KeySegment extends LogicalSegment {

        public KeySegment(ElectronicKey value, LogicalFormat format) {
            super(value, LogicalType.Special, format);
        }

        @Override
        protected ByteBuf encodeValue(ByteBuf buffer) {
            return encodeKeyValue(getFormat(), getValue(), buffer);
        }

    }

    public static enum LogicalType {

        ClassId(0x0),
        InstanceId(0x1),
        MemberId(0x2),
        ConnectionPoint(0x3),
        AttributeId(0x4),
        Special(0x5),
        ServiceId(0x6),
        Reserved(0x7);

        private final int type;

        LogicalType(int type) {
            this.type = type;
        }

        public int getType() {
            return type;
        }

    }

    public static enum LogicalFormat {

        Bits_8(0x0),
        Bits_16(0x1),
        Bits_32(0x2),
        Reserved(0x3);

        private final int type;

        LogicalFormat(int type) {
            this.type = type;
        }

        public int getType() {
            return type;
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy