# Path: pif_ir/bir/objects/metadata_instance.py
# class MetadataInstance(object):
#     required_attributes = ['values', 'visibility']
# 
#     def __init__(self, name, metadata_attrs, bir_structs, buf=None, 
#                  bit_offset=0):
#         check_attributes(name, metadata_attrs, 
#                          MetadataInstance.required_attributes)
# 
#         logging.debug("Adding metadata {0}".format(name))
#         self.name = name
#         self.values = OrderedDict()
#         # FIXME: used for syntactic checking
#         self.visibility = metadata_attrs['visibility']
# 
#         struct_name = metadata_attrs['values']
#         for f_name, f_size in bir_structs[struct_name].fields.items():
#             self.values[f_name] = ValueInstance(f_name, f_size)
# 
#         if buf:
#             self.extract(buf, bit_offset)
# 
#     def __len__(self):
#         return sum([len(fld) for fld in self.values.values()])
# 
#     def __int__(self):
#         value = 0;
#         for fld in self.values.values():
#             value = (value << len(fld)) + int(fld)
#         return value
# 
#     def to_dict(self):
#         return dict([(v.name,int(v)) for v in self.values.values()])
# 
#     def extract(self, buf, bit_offset=0):
#         fld_offset = 0;
#         for fld in self.values.values():
#             fld.extract(buf, bit_offset + fld_offset);
#             fld_offset += len(fld)
# 
#     def serialize(self):
#         byte_list = bytearray(len(self)/8)
#         bit_offset = 0;
#         for fld in self.values.values():
#             fld.update(byte_list, bit_offset)
#             bit_offset += len(fld)
#         return byte_list
# 
#     def get_value(self, value_name):
#         if value_name not in  self.values:
#             return 0
#         return self.values[value_name].value
# 
#     def set_value(self, value_name, value):
#         fld = self.values.get(value_name, None)
#         if fld:
#             fld.value = value
# 
#     def reset_values(self, new_val=0):
#         for fld in self.values.values():
#             fld.value = new_val
# 
# Path: pif_ir/bir/utils/common.py
# def int_to_bytearray(bit_offset, value, bit_width):
#     BYTE_MASK = [0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff]
#     RBYTE_MASK = [0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff]
#     ret_vals = []
#     ret_mask = []
# 
#     # pad the value so it's byte aligned
#     padding = (8 - ((bit_offset + bit_width) % 8)) % 8
#     value <<= padding
# 
#     remain = bit_width + padding
#     while remain > 0:
#         if remain == bit_width + padding:
#             ret_vals.append(value & 0xFF)
#             ret_mask.append(BYTE_MASK[padding])
#         else:
#             ret_vals.append(value & 0xFF)
#             ret_mask.append(0x00)
#         value >>= 8
#         remain -= 8
# 
#     ret_vals[-1] &= BYTE_MASK[8-bit_offset]
#     ret_mask[-1] |= RBYTE_MASK[bit_offset]
#     return ret_vals[::-1], ret_mask[::-1]
# 
# def bytearray_to_int(buf, bit_width, bit_offset=0):
#     BYTE_MASK = [0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff]
#     base = bit_offset / 8
#     last = (bit_offset + bit_width + 7) / 8
# 
#     offset = bit_offset % 8
#     if last - base == 1:
#         shift = 8 - (offset + bit_width)
#         return (buf[base] >> shift) & BYTE_MASK[bit_width]
# 
#     value = 0
#     remain = bit_width
#     for byte in buf[base:last]:
#         if remain == bit_width: # first byte
#             take = 8 - offset
#             value = byte & BYTE_MASK[take]
#         else:
#             take = min(8, remain)
#             value = (value << take) + (byte >> (8 - take))
#         remain -= take
#     return value


import logging
from pif_ir.bir.objects.metadata_instance import MetadataInstance
from pif_ir.bir.utils.common import int_to_bytearray, bytearray_to_int
from pif_ir.bir.utils.exceptions import *


class PacketInstance(object):
    id_next = 0

    def __init__(self, packet_data, metadata_attrs, bir_structs):
        """
        @brief PacketInstance constructor
        @param packet_data The original packet data as a byte array
        @param metadata_dict The metadata values associated with the packet
        @param bir_structs The structs used for metadata fields
        """
        self.packet_data = packet_data
        self.idx = PacketInstance.id_next
        PacketInstance.id_next += 1

        self.metadata = {}
        for name, md in metadata_attrs.items():

# Path: pif_ir/bir/objects/metadata_instance.py
# class MetadataInstance(object):
#     required_attributes = ['values', 'visibility']
# 
#     def __init__(self, name, metadata_attrs, bir_structs, buf=None, 
#                  bit_offset=0):
#         check_attributes(name, metadata_attrs, 
#                          MetadataInstance.required_attributes)
# 
#         logging.debug("Adding metadata {0}".format(name))
#         self.name = name
#         self.values = OrderedDict()
#         # FIXME: used for syntactic checking
#         self.visibility = metadata_attrs['visibility']
# 
#         struct_name = metadata_attrs['values']
#         for f_name, f_size in bir_structs[struct_name].fields.items():
#             self.values[f_name] = ValueInstance(f_name, f_size)
# 
#         if buf:
#             self.extract(buf, bit_offset)
# 
#     def __len__(self):
#         return sum([len(fld) for fld in self.values.values()])
# 
#     def __int__(self):
#         value = 0;
#         for fld in self.values.values():
#             value = (value << len(fld)) + int(fld)
#         return value
# 
#     def to_dict(self):
#         return dict([(v.name,int(v)) for v in self.values.values()])
# 
#     def extract(self, buf, bit_offset=0):
#         fld_offset = 0;
#         for fld in self.values.values():
#             fld.extract(buf, bit_offset + fld_offset);
#             fld_offset += len(fld)
# 
#     def serialize(self):
#         byte_list = bytearray(len(self)/8)
#         bit_offset = 0;
#         for fld in self.values.values():
#             fld.update(byte_list, bit_offset)
#             bit_offset += len(fld)
#         return byte_list
# 
#     def get_value(self, value_name):
#         if value_name not in  self.values:
#             return 0
#         return self.values[value_name].value
# 
#     def set_value(self, value_name, value):
#         fld = self.values.get(value_name, None)
#         if fld:
#             fld.value = value
# 
#     def reset_values(self, new_val=0):
#         for fld in self.values.values():
#             fld.value = new_val
# 
# Path: pif_ir/bir/utils/common.py
# def int_to_bytearray(bit_offset, value, bit_width):
#     BYTE_MASK = [0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff]
#     RBYTE_MASK = [0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff]
#     ret_vals = []
#     ret_mask = []
# 
#     # pad the value so it's byte aligned
#     padding = (8 - ((bit_offset + bit_width) % 8)) % 8
#     value <<= padding
# 
#     remain = bit_width + padding
#     while remain > 0:
#         if remain == bit_width + padding:
#             ret_vals.append(value & 0xFF)
#             ret_mask.append(BYTE_MASK[padding])
#         else:
#             ret_vals.append(value & 0xFF)
#             ret_mask.append(0x00)
#         value >>= 8
#         remain -= 8
# 
#     ret_vals[-1] &= BYTE_MASK[8-bit_offset]
#     ret_mask[-1] |= RBYTE_MASK[bit_offset]
#     return ret_vals[::-1], ret_mask[::-1]
# 
# def bytearray_to_int(buf, bit_width, bit_offset=0):
#     BYTE_MASK = [0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff]
#     base = bit_offset / 8
#     last = (bit_offset + bit_width + 7) / 8
# 
#     offset = bit_offset % 8
#     if last - base == 1:
#         shift = 8 - (offset + bit_width)
#         return (buf[base] >> shift) & BYTE_MASK[bit_width]
# 
#     value = 0
#     remain = bit_width
#     for byte in buf[base:last]:
#         if remain == bit_width: # first byte
#             take = 8 - offset
#             value = byte & BYTE_MASK[take]
#         else:
#             take = min(8, remain)
#             value = (value << take) + (byte >> (8 - take))
#         remain -= take
#     return value


# Path: pif_ir/bir/objects/packet_instance.py
import logging
from pif_ir.bir.objects.metadata_instance import MetadataInstance
from pif_ir.bir.utils.common import int_to_bytearray, bytearray_to_int
from pif_ir.bir.utils.exceptions import *



class PacketInstance(object):
    id_next = 0

    def __init__(self, packet_data, metadata_attrs, bir_structs):
        """
        @brief PacketInstance constructor
        @param packet_data The original packet data as a byte array
        @param metadata_dict The metadata values associated with the packet
        @param bir_structs The structs used for metadata fields
        """
        self.packet_data = packet_data
        self.idx = PacketInstance.id_next
        PacketInstance.id_next += 1

        self.metadata = {}
        for name, md in metadata_attrs.items():

            self.metadata[name] = MetadataInstance(name, md, bir_structs)