Esempio n. 1
0
 def _validate(self):
     if self._decoder is None:
         from bdec.decode import Decoder
         self._decoder = Decoder(self)
Esempio n. 2
0
class Entry(object):
    """An entry is an item in a protocol that can be decoded.

    This class designed to be derived by other classes (not instantiated 
    directly).
    """

    def __init__(self, name, length, children, constraints=[]):
        """Construct an Entry instance.

        children -- A list of Entry or Child instances.
        length -- Optionally specify the size in bits of the entry. Must be an
            instance of bdec.expression.Expression or an integer.
        constraints -- A list of constraints for the value of this entry.
        """
        if length is not None:
            if isinstance(length, int):
                length = Constant(length)
            assert isinstance(length, Expression)
        self.name = name
        self.length = length
        self._children = ()
        self.children = children
        self._decoder = None
        self._encoder = None

        self.constraints = list(constraints)
        for constraint in self.constraints:
            assert getattr(constraint, 'check') is not None

    def _get_children(self):
        return self._children
    def _set_children(self, children):
        from bdec.spec.references import ReferencedEntry
        items = []
        for child in children:
            if isinstance(child, Child):
                items.append(child)
            else:
                items.append(Child(child.name, child))
            if isinstance(items[-1].entry, ReferencedEntry):
                items[-1].entry.add_parent(items[-1])
        self._children = list(items)
    children = property(_get_children, _set_children)

    def _validate(self):
        if self._decoder is None:
            from bdec.decode import Decoder
            self._decoder = Decoder(self)

    def decode(self, data, context={}, name=None):
        """ Shortcut to bdec.decode.Decoder(self) """
        self._validate()
        return self._decoder.decode(data, context, name)

    def encode(self, query, value):
        if self._encoder is None:
            from bdec.encode import create_encoder
            self._encoder = create_encoder(self)
        value = self._encoder.get_value(query, value, 0, self.name, {})
        return self._encoder.encode(query, value, 0, {}, self.name)

    def is_hidden(self):
        """Is this a 'hidden' entry."""
        return is_hidden(self.name)

    def __str__(self):
        return "%s '%s'" % (self.__class__.__name__.lower(), self.name)

    def __repr__(self):
        return "%s '%s'" % (self.__class__, self.name)

    def _range(self, ignore_entries):
        """
        Can be implemented by derived classes to detect ranges.
        """
        return bdec.entry.Range()

    def range(self, ignore_entries=set()):
        """Return a Range instance indicating the length of this entry.

        ignore_entries -- If self is in ignore_entries, a default Range 
           instance will be returned. 'self' and all child entries will
           be added to ignore_entries.
        """
        if self in ignore_entries:
            # If an entry is recursive, we cannot predict how long it will be.
            return Range()

        result = None
        if self.length is not None:
            try:
                min = max = self.length.evaluate({})
                result = bdec.entry.Range(min, max)
            except UndecodedReferenceError:
                pass
        if result is None:
            ignore_entries.add(self)
            result = self._range(ignore_entries)
            ignore_entries.remove(self)
        return result