// 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.OFFlowWildcards;
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 OFFlowWildcardsSerializerVer11 {

    public final static int IN_PORT_VAL = 0x1;
    public final static int DL_VLAN_VAL = 0x2;
    public final static int DL_TYPE_VAL = 0x8;
    public final static int NW_PROTO_VAL = 0x20;
    public final static int TP_SRC_VAL = 0x40;
    public final static int TP_DST_VAL = 0x80;
    public final static int DL_VLAN_PCP_VAL = 0x4;
    public final static int NW_TOS_VAL = 0x10;
    public final static int ALL_VAL = 0x3ff;
    public final static int MPLS_LABEL_VAL = 0x100;
    public final static int MPLS_TC_VAL = 0x200;

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

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

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


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

        if((val & IN_PORT_VAL) != 0)
            set.add(OFFlowWildcards.IN_PORT);
        if((val & DL_VLAN_VAL) != 0)
            set.add(OFFlowWildcards.DL_VLAN);
        if((val & DL_TYPE_VAL) != 0)
            set.add(OFFlowWildcards.DL_TYPE);
        if((val & NW_PROTO_VAL) != 0)
            set.add(OFFlowWildcards.NW_PROTO);
        if((val & TP_SRC_VAL) != 0)
            set.add(OFFlowWildcards.TP_SRC);
        if((val & TP_DST_VAL) != 0)
            set.add(OFFlowWildcards.TP_DST);
        if((val & DL_VLAN_PCP_VAL) != 0)
            set.add(OFFlowWildcards.DL_VLAN_PCP);
        if((val & NW_TOS_VAL) != 0)
            set.add(OFFlowWildcards.NW_TOS);
        if((val & ALL_VAL) != 0)
            set.add(OFFlowWildcards.ALL);
        if((val & MPLS_LABEL_VAL) != 0)
            set.add(OFFlowWildcards.MPLS_LABEL);
        if((val & MPLS_TC_VAL) != 0)
            set.add(OFFlowWildcards.MPLS_TC);
        return Collections.unmodifiableSet(set);
    }

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

        for(OFFlowWildcards e: set) {
            switch(e) {
                case IN_PORT:
                    wireValue |= IN_PORT_VAL;
                    break;
                case DL_VLAN:
                    wireValue |= DL_VLAN_VAL;
                    break;
                case DL_TYPE:
                    wireValue |= DL_TYPE_VAL;
                    break;
                case NW_PROTO:
                    wireValue |= NW_PROTO_VAL;
                    break;
                case TP_SRC:
                    wireValue |= TP_SRC_VAL;
                    break;
                case TP_DST:
                    wireValue |= TP_DST_VAL;
                    break;
                case DL_VLAN_PCP:
                    wireValue |= DL_VLAN_PCP_VAL;
                    break;
                case NW_TOS:
                    wireValue |= NW_TOS_VAL;
                    break;
                case ALL:
                    wireValue |= ALL_VAL;
                    break;
                case MPLS_LABEL:
                    wireValue |= MPLS_LABEL_VAL;
                    break;
                case MPLS_TC:
                    wireValue |= MPLS_TC_VAL;
                    break;
                default:
                    throw new IllegalArgumentException("Illegal enum value for type OFFlowWildcards in version 1.1: " + e);
            }
        }
        return wireValue;
    }

}
