// 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 const_set_serializer.java
// Do not modify

package org.projectfloodlight.openflow.protocol.ver11;

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.projectfloodlight.openflow.protocol.OFBsnVportL2GreFlags;
import java.util.Set;
import org.jboss.netty.buffer.ChannelBuffer;
import com.google.common.hash.PrimitiveSink;
import java.util.EnumSet;
import java.util.Collections;


public class OFBsnVportL2GreFlagsSerializerVer11 {

    public final static int BSN_VPORT_L2GRE_LOCAL_MAC_IS_VALID_VAL = 0x1;
    public final static int BSN_VPORT_L2GRE_DSCP_ASSIGN_VAL = 0x2;
    public final static int BSN_VPORT_L2GRE_DSCP_COPY_VAL = 0x4;
    public final static int BSN_VPORT_L2GRE_LOOPBACK_IS_VALID_VAL = 0x8;
    public final static int BSN_VPORT_L2GRE_RATE_LIMIT_IS_VALID_VAL = 0x10;

    public static Set<OFBsnVportL2GreFlags> readFrom(ChannelBuffer bb) throws OFParseError {
        try {
            return ofWireValue(bb.readInt());
        } catch (IllegalArgumentException e) {
            throw new OFParseError(e);
        }
    }

    public static void writeTo(ChannelBuffer bb, Set<OFBsnVportL2GreFlags> set) {
        bb.writeInt(toWireValue(set));
    }

    public static void putTo(Set<OFBsnVportL2GreFlags> set, PrimitiveSink sink) {
        sink.putInt(toWireValue(set));
    }


    public static Set<OFBsnVportL2GreFlags> ofWireValue(int val) {
        EnumSet<OFBsnVportL2GreFlags> set = EnumSet.noneOf(OFBsnVportL2GreFlags.class);

        if((val & BSN_VPORT_L2GRE_LOCAL_MAC_IS_VALID_VAL) != 0)
            set.add(OFBsnVportL2GreFlags.BSN_VPORT_L2GRE_LOCAL_MAC_IS_VALID);
        if((val & BSN_VPORT_L2GRE_DSCP_ASSIGN_VAL) != 0)
            set.add(OFBsnVportL2GreFlags.BSN_VPORT_L2GRE_DSCP_ASSIGN);
        if((val & BSN_VPORT_L2GRE_DSCP_COPY_VAL) != 0)
            set.add(OFBsnVportL2GreFlags.BSN_VPORT_L2GRE_DSCP_COPY);
        if((val & BSN_VPORT_L2GRE_LOOPBACK_IS_VALID_VAL) != 0)
            set.add(OFBsnVportL2GreFlags.BSN_VPORT_L2GRE_LOOPBACK_IS_VALID);
        if((val & BSN_VPORT_L2GRE_RATE_LIMIT_IS_VALID_VAL) != 0)
            set.add(OFBsnVportL2GreFlags.BSN_VPORT_L2GRE_RATE_LIMIT_IS_VALID);
        return Collections.unmodifiableSet(set);
    }

    public static int toWireValue(Set<OFBsnVportL2GreFlags> set) {
        int wireValue = 0;

        for(OFBsnVportL2GreFlags e: set) {
            switch(e) {
                case BSN_VPORT_L2GRE_LOCAL_MAC_IS_VALID:
                    wireValue |= BSN_VPORT_L2GRE_LOCAL_MAC_IS_VALID_VAL;
                    break;
                case BSN_VPORT_L2GRE_DSCP_ASSIGN:
                    wireValue |= BSN_VPORT_L2GRE_DSCP_ASSIGN_VAL;
                    break;
                case BSN_VPORT_L2GRE_DSCP_COPY:
                    wireValue |= BSN_VPORT_L2GRE_DSCP_COPY_VAL;
                    break;
                case BSN_VPORT_L2GRE_LOOPBACK_IS_VALID:
                    wireValue |= BSN_VPORT_L2GRE_LOOPBACK_IS_VALID_VAL;
                    break;
                case BSN_VPORT_L2GRE_RATE_LIMIT_IS_VALID:
                    wireValue |= BSN_VPORT_L2GRE_RATE_LIMIT_IS_VALID_VAL;
                    break;
                default:
                    throw new IllegalArgumentException("Illegal enum value for type OFBsnVportL2GreFlags in version 1.1: " + e);
            }
        }
        return wireValue;
    }

}
