// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
// Copyright (c) 2011, 2012 Open Networking Foundation
// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
// This library was generated by the LoxiGen Compiler.
// See the file LICENSE.txt which should have been included in the source distribution

// Automatically generated by LOXI from template of_virtual_class.java
// Do not modify

package org.projectfloodlight.openflow.protocol.ver13;

import org.projectfloodlight.openflow.protocol.*;
import org.projectfloodlight.openflow.protocol.action.*;
import org.projectfloodlight.openflow.protocol.actionid.*;
import org.projectfloodlight.openflow.protocol.bsntlv.*;
import org.projectfloodlight.openflow.protocol.errormsg.*;
import org.projectfloodlight.openflow.protocol.meterband.*;
import org.projectfloodlight.openflow.protocol.instruction.*;
import org.projectfloodlight.openflow.protocol.instructionid.*;
import org.projectfloodlight.openflow.protocol.match.*;
import org.projectfloodlight.openflow.protocol.oxm.*;
import org.projectfloodlight.openflow.protocol.queueprop.*;
import org.projectfloodlight.openflow.types.*;
import org.projectfloodlight.openflow.util.*;
import org.projectfloodlight.openflow.exceptions.*;
import org.jboss.netty.buffer.ChannelBuffer;

abstract class OFInstructionBsnVer13 {
    // version: 1.3
    final static byte WIRE_VERSION = 4;
    final static int MINIMUM_LENGTH = 16;


    public final static OFInstructionBsnVer13.Reader READER = new Reader();

    static class Reader implements OFMessageReader<OFInstructionBsn> {
        @Override
        public OFInstructionBsn readFrom(ChannelBuffer bb) throws OFParseError {
            if(bb.readableBytes() < MINIMUM_LENGTH)
                return null;
            int start = bb.readerIndex();
            // fixed value property type == 65535
            short type = bb.readShort();
            if(type != (short) 0xffff)
                throw new OFParseError("Wrong type: Expected=OFInstructionType.EXPERIMENTER(65535), got="+type);
            int length = U16.f(bb.readShort());
            if(length < MINIMUM_LENGTH)
                throw new OFParseError("Wrong length: Expected to be >= " + MINIMUM_LENGTH + ", was: " + length);
            // fixed value property experimenter == 0x5c16c7L
            int experimenter = bb.readInt();
            if(experimenter != 0x5c16c7)
                throw new OFParseError("Wrong experimenter: Expected=0x5c16c7L(0x5c16c7L), got="+experimenter);
            int subtype = bb.readInt();
            bb.readerIndex(start);
            switch(subtype) {
               case 0x1:
                   // discriminator value 0x1L=0x1L for class OFInstructionBsnArpOffloadVer13
                   return OFInstructionBsnArpOffloadVer13.READER.readFrom(bb);
               case 0x5:
                   // discriminator value 0x5L=0x5L for class OFInstructionBsnDenyVer13
                   return OFInstructionBsnDenyVer13.READER.readFrom(bb);
               case 0x2:
                   // discriminator value 0x2L=0x2L for class OFInstructionBsnDhcpOffloadVer13
                   return OFInstructionBsnDhcpOffloadVer13.READER.readFrom(bb);
               case 0x3:
                   // discriminator value 0x3L=0x3L for class OFInstructionBsnDisableSplitHorizonCheckVer13
                   return OFInstructionBsnDisableSplitHorizonCheckVer13.READER.readFrom(bb);
               case 0x0:
                   // discriminator value 0x0L=0x0L for class OFInstructionBsnDisableSrcMacCheckVer13
                   return OFInstructionBsnDisableSrcMacCheckVer13.READER.readFrom(bb);
               case 0x9:
                   // discriminator value 0x9L=0x9L for class OFInstructionBsnDisableVlanCountersVer13
                   return OFInstructionBsnDisableVlanCountersVer13.READER.readFrom(bb);
               case 0x6:
                   // discriminator value 0x6L=0x6L for class OFInstructionBsnPacketOfDeathVer13
                   return OFInstructionBsnPacketOfDeathVer13.READER.readFrom(bb);
               case 0x4:
                   // discriminator value 0x4L=0x4L for class OFInstructionBsnPermitVer13
                   return OFInstructionBsnPermitVer13.READER.readFrom(bb);
               case 0x7:
                   // discriminator value 0x7L=0x7L for class OFInstructionBsnPrioritizePdusVer13
                   return OFInstructionBsnPrioritizePdusVer13.READER.readFrom(bb);
               case 0x8:
                   // discriminator value 0x8L=0x8L for class OFInstructionBsnRequireVlanXlateVer13
                   return OFInstructionBsnRequireVlanXlateVer13.READER.readFrom(bb);
               default:
                   throw new OFParseError("Unknown value for discriminator subtype of class OFInstructionBsnVer13: " + subtype);
            }
        }
    }
}
