# Path: pif_ir/bir/objects/value_instance.py
# class ValueInstance(object):
#     def __init__(self, name, bit_width, value=0):
#         if bit_width <= 0:
#             raise BIRFieldWidthError(name, bit_width)
#         logging.debug("Adding value {0}".format(name))
#         self.name = name
#         self.bit_width = bit_width  
#         self.value = value 
# 
#     def __len__(self):
#         return self.bit_width
# 
#     def __int__(self):
#         return self.value
# 
#     def extract(self, buf, bit_offset=0):
#         self.value = bytearray_to_int(buf, self.bit_width, bit_offset)
#         return self.value
# 
#     def update(self, buf, bit_offset=0):
#         byte_offset = bit_offset / 8 
#         offset = bit_offset % 8
# 
#         vals, masks = int_to_bytearray(offset, self.value, self.bit_width)
#         for idx, (val, mask) in enumerate(zip(vals,masks)):
#             buf[byte_offset + idx] &= mask
#             buf[byte_offset + idx] += val
# 
# Path: pif_ir/bir/utils/validate.py
# def check_attributes(obj_name, attributes, required_attributes):
#     for attr in required_attributes:
#         if attr not in attributes:
#             raise BIRYamlAttrError(attr, obj_name)


import logging
from collections import OrderedDict
from pif_ir.bir.objects.value_instance import ValueInstance
from pif_ir.bir.utils.validate import check_attributes


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)

# Path: pif_ir/bir/objects/value_instance.py
# class ValueInstance(object):
#     def __init__(self, name, bit_width, value=0):
#         if bit_width <= 0:
#             raise BIRFieldWidthError(name, bit_width)
#         logging.debug("Adding value {0}".format(name))
#         self.name = name
#         self.bit_width = bit_width  
#         self.value = value 
# 
#     def __len__(self):
#         return self.bit_width
# 
#     def __int__(self):
#         return self.value
# 
#     def extract(self, buf, bit_offset=0):
#         self.value = bytearray_to_int(buf, self.bit_width, bit_offset)
#         return self.value
# 
#     def update(self, buf, bit_offset=0):
#         byte_offset = bit_offset / 8 
#         offset = bit_offset % 8
# 
#         vals, masks = int_to_bytearray(offset, self.value, self.bit_width)
#         for idx, (val, mask) in enumerate(zip(vals,masks)):
#             buf[byte_offset + idx] &= mask
#             buf[byte_offset + idx] += val
# 
# Path: pif_ir/bir/utils/validate.py
# def check_attributes(obj_name, attributes, required_attributes):
#     for attr in required_attributes:
#         if attr not in attributes:
#             raise BIRYamlAttrError(attr, obj_name)


# Path: pif_ir/bir/objects/metadata_instance.py
import logging
from collections import OrderedDict
from pif_ir.bir.objects.value_instance import ValueInstance
from pif_ir.bir.utils.validate import check_attributes



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