Exemple #1
0
def substitute_len_field(cls, descriptor, container_name, container_tp):
    index, field = ifilter(lambda x: x[1][0] is container_tp._BOUND,
                           enumerate(descriptor)).next()
    name, tp = field
    bound_shift = container_tp._BOUND_SHIFT

    if tp._OPTIONAL:
        raise ProphyError("array must not be bound to optional field")
    if not issubclass(tp, (int, long)):
        raise ProphyError("array must be bound to an unsigned integer")

    class container_len(tp):
        _BOUND = container_name

        @staticmethod
        def _encode(value, endianness):
            return tp._encode(value + bound_shift, endianness)

        @staticmethod
        def _decode(data, pos, endianness):
            value, size = tp._decode(data, pos, endianness)
            array_guard = 65536
            if value > array_guard:
                raise ProphyError("decoded array length over %s" % array_guard)
            value -= bound_shift
            if value < 0:
                raise ProphyError("decoded array length smaller than shift")
            return value, size

    descriptor[index] = (name, container_len)
    delattr(cls, name)
Exemple #2
0
 def _check(value):
     if not isinstance(value, str):
         raise ProphyError("not a str")
     if size and len(value) > size:
         raise ProphyError("too long")
     if size and not bound:
         return value.ljust(size, '\x00')
     return value
Exemple #3
0
 def _decode(data, pos, endianness):
     value, size = tp._decode(data, pos, endianness)
     array_guard = 65536
     if value > array_guard:
         raise ProphyError("decoded array length over %s" % array_guard)
     value -= bound_shift
     if value < 0:
         raise ProphyError("decoded array length smaller than shift")
     return value, size
Exemple #4
0
def validate_union(descriptor):
    if any(type._DYNAMIC for _, type, _ in descriptor):
        raise ProphyError("dynamic types not allowed in union")
    if any(type._BOUND for _, type, _ in descriptor):
        raise ProphyError("bound array/bytes not allowed in union")
    if any(
            issubclass(type, container.base_array)
            for _, type, _ in descriptor):
        raise ProphyError("static array not implemented in union")
    if any(type._OPTIONAL for _, type, _ in descriptor):
        raise ProphyError("union with optional field disallowed")
Exemple #5
0
 def check(value):
     if isinstance(value, str):
         value = name_to_int.get(value)
         if value is None:
             raise ProphyError("unknown enumerator name")
         return cls(value)
     elif isinstance(value, (int, long)):
         if not value in int_to_name:
             raise ProphyError("unknown enumerator value")
         return cls(value)
     else:
         raise ProphyError("neither string nor int")
Exemple #6
0
 def _decode(data, pos, len_hint):
     if (len(data) - pos) < size:
         raise ProphyError("too few bytes to decode string")
     if size and not bound:
         return data[pos:pos + size], size
     elif size and bound:
         return data[pos:pos + len_hint], size
     elif bound:
         if (len(data) - pos) < len_hint:
             raise ProphyError("too few bytes to decode string")
         return data[pos:pos + len_hint], len_hint
     else:  # greedy
         return data[pos:], (len(data) - pos)
Exemple #7
0
def bytes(**kwargs):
    size = kwargs.pop("size", 0)
    bound = kwargs.pop("bound", None)
    shift = kwargs.pop("shift", 0)
    if shift and (not bound or size):
        raise ProphyError("only shifting bound bytes implemented")
    if kwargs:
        raise ProphyError("unknown arguments to bytes field")

    class _bytes(str):
        _SIZE = size
        _DYNAMIC = not size
        _UNLIMITED = not size and not bound
        _DEFAULT = "\x00" * size if size and not bound else ""
        _OPTIONAL = False
        _ALIGNMENT = 1
        _BOUND = bound
        _BOUND_SHIFT = shift
        _PARTIAL_ALIGNMENT = None

        @staticmethod
        def _check(value):
            if not isinstance(value, str):
                raise ProphyError("not a str")
            if size and len(value) > size:
                raise ProphyError("too long")
            if size and not bound:
                return value.ljust(size, '\x00')
            return value

        @staticmethod
        def _encode(value):
            return value.ljust(size, '\x00')

        @staticmethod
        def _decode(data, pos, len_hint):
            if (len(data) - pos) < size:
                raise ProphyError("too few bytes to decode string")
            if size and not bound:
                return data[pos:pos + size], size
            elif size and bound:
                return data[pos:pos + len_hint], size
            elif bound:
                if (len(data) - pos) < len_hint:
                    raise ProphyError("too few bytes to decode string")
                return data[pos:pos + len_hint], len_hint
            else:  # greedy
                return data[pos:], (len(data) - pos)

    return _bytes
Exemple #8
0
def optional(cls):
    if issubclass(cls, str):
        raise ProphyError("optional bytes not implemented")
    if issubclass(cls, container.base_array):
        raise ProphyError("optional array not implemented")
    if cls._DYNAMIC:
        raise ProphyError("optional dynamic fields not implemented")

    class _optional(cls):
        pass

    _optional._OPTIONAL = True
    _optional._optional_type = scalar.u32
    return _optional
Exemple #9
0
 def _decode_impl(self, data, pos, endianness, terminal):
     disc, bytes_read = self._discriminator_type._decode(
         data, pos, endianness)
     field = get_discriminated_field(self, disc)
     if not field:
         raise ProphyError("unknown discriminator")
     name, type, _, _, decode_ = field
     self._discriminated = field
     bytes_read += decode_(self, name, type, data, pos + bytes_read,
                           endianness, {})
     if (len(data) - pos) < self._SIZE:
         raise ProphyError("not enough bytes")
     if terminal and (len(data) - pos) > self._SIZE:
         raise ProphyError("not all bytes read")
     return self._SIZE
Exemple #10
0
 def setter(self, new_value):
     if new_value is True:
         self._fields[name] = tp()
     elif new_value is None:
         self._fields.pop(name, None)
     else:
         raise ProphyError("assignment to composite field not allowed")
Exemple #11
0
def composite_array_eq(self, other):
    if self is other:
        return True
    if not isinstance(other, self.__class__):
        raise ProphyError('Can only compare repeated composite fields against '
                          'other repeated composite fields.')
    return self._values == other._values
Exemple #12
0
    def add(self):
        if self._max_len and len(self) == self._max_len:
            raise ProphyError("exceeded array limit")

        new_element = self._TYPE()
        self._values.append(new_element)
        return new_element
Exemple #13
0
 def getter(self):
     if self._discriminated is not field:
         raise ProphyError("currently field %s is discriminated" %
                           self._discriminated[2])
     value = self._fields.get(name)
     if value is None:
         value = type()
         value = self._fields.setdefault(name, value)
     return value
Exemple #14
0
    def extend(self, elem_seq):
        if self._max_len and len(self) + len(elem_seq) > self._max_len:
            raise ProphyError("exceeded array limit")

        composite_cls = self._TYPE
        for message in elem_seq:
            new_element = composite_cls()
            new_element.copy_from(message)
            self._values.append(new_element)
Exemple #15
0
 def setter(self, new_value):
     field = next(
         ifilter(lambda x: new_value in (x[0], x[2]), self._descriptor),
         None)
     if field:
         if field != self._discriminated:
             self._discriminated = field
             self._fields = {}
     else:
         raise ProphyError("unknown discriminator")
Exemple #16
0
 def _decode_impl(self, data, pos, endianness, len_hint):
     if self._SIZE > (len(data) - pos):
         raise ProphyError("too few bytes to decode array")
     del self[:]
     cursor = 0
     if not self._SIZE and not self._BOUND:
         while (pos + cursor) < len(data):
             cursor += self.add()._decode_impl(data, pos + cursor, endianness, terminal = False)
     else:
         for _ in xrange(len_hint):
             cursor += self.add()._decode_impl(data, pos + cursor, endianness, terminal = False)
     return max(cursor, self._SIZE)
Exemple #17
0
    def _decode_impl(self, data, pos, endianness, terminal):
        len_hints = {}
        start_pos = pos

        for name, tp, _, decode_ in self._descriptor:
            pos += self._get_padding_size(pos, tp._ALIGNMENT)
            pos += decode_(self, name, tp, data, pos, endianness, len_hints)
            if tp._PARTIAL_ALIGNMENT:
                pos += self._get_padding_size(pos, tp._PARTIAL_ALIGNMENT)

        if not (self._descriptor and terminal
                and issubclass(tp, (container.base_array, str))):
            pos += self._get_padding_size(pos, self._ALIGNMENT)

        if terminal and pos < len(data):
            raise ProphyError("not all bytes read")

        return pos - start_pos
Exemple #18
0
def array(type, **kwargs):
    size = kwargs.pop("size", 0)
    bound = kwargs.pop("bound", None)
    shift = kwargs.pop("shift", 0)
    if kwargs:
        raise ProphyError("unknown arguments to array field")

    if issubclass(type, base_array):
        raise ProphyError("array of arrays not allowed")
    if issubclass(type, str):
        raise ProphyError("array of strings not allowed")
    if size and type._DYNAMIC:
        raise ProphyError("static/limited array of dynamic type not allowed")
    if shift and (not bound or size):
        raise ProphyError("only shifting bound array implemented")
    if type._UNLIMITED:
        raise ProphyError("array with unlimited field disallowed")
    if type._OPTIONAL:
        raise ProphyError("array of optional type not allowed")

    is_static = size and not bound
    is_composite = issubclass(type, (composite.struct, composite.union))

    if is_composite:
        base = fixed_composite_array if is_static else bound_composite_array
    else:
        base = fixed_scalar_array if is_static else bound_scalar_array

    class _array(base):
        __slots__ = []
        _max_len = size
        _TYPE = type
        _SIZE = size * type._SIZE
        _DYNAMIC = not size
        _UNLIMITED = not size and not bound
        _OPTIONAL = False
        _ALIGNMENT = type._ALIGNMENT
        _BOUND = bound
        _BOUND_SHIFT = shift
        _PARTIAL_ALIGNMENT = None

    return _array
Exemple #19
0
def add_enum_attributes(cls, enumerators):
    @staticmethod
    def check(value):
        if isinstance(value, str):
            value = name_to_int.get(value)
            if value is None:
                raise ProphyError("unknown enumerator name")
            return cls(value)
        elif isinstance(value, (int, long)):
            if not value in int_to_name:
                raise ProphyError("unknown enumerator value")
            return cls(value)
        else:
            raise ProphyError("neither string nor int")

    name_to_int = {name: value for name, value in enumerators}
    int_to_name = {value: name for name, value in enumerators}
    if len(name_to_int) < len(enumerators):
        raise ProphyError("names overlap")
    map(cls._check, (value for _, value in enumerators))
    cls._DEFAULT = cls(enumerators[0][1])
    cls._name_to_int = name_to_int
    cls._int_to_name = int_to_name
    cls._check = check
Exemple #20
0
 def check(value):
     if not isinstance(value, (float, int, long)):
         raise ProphyError("not a float")
     return value
Exemple #21
0
 def check(value):
     if not isinstance(value, (int, long)):
         raise ProphyError("not an int")
     if not min <= value <= max:
         raise ProphyError("out of bounds")
     return value
Exemple #22
0
def validate(descriptor):
    if any(type._UNLIMITED for _, type in descriptor[:-1]):
        raise ProphyError("unlimited field is not the last one")
Exemple #23
0
 def setter(self, new_value):
     raise ProphyError("assignment to array field not allowed")
Exemple #24
0
 def decode(data, pos, endianness):
     if (len(data) - pos) < size:
         raise ProphyError("too few bytes to decode integer")
     value, = struct.unpack(endianness + id, data[pos:pos + size])
     return value, size
Exemple #25
0
 def insert(self, idx, value):
     value = self._TYPE._check(value)
     if self._max_len and len(self) == self._max_len:
         raise ProphyError("exceeded array limit")
     self._values.insert(idx, value)
Exemple #26
0
 def append(self, value):
     value = self._TYPE._check(value)
     if self._max_len and len(self) == self._max_len:
         raise ProphyError("exceeded array limit")
     self._values.append(value)
Exemple #27
0
 def __setslice__(self, start, stop, values):
     if len(self._values[start:stop]) != len(values):
         raise ProphyError("setting slice with different length collection")
     self._values[start:stop] = map(self._TYPE._check, values)
Exemple #28
0
 def extend(self, values):
     if not values:
         return
     if self._max_len and len(self) + len(values) > self._max_len:
         raise ProphyError("exceeded array limit")
     self._values.extend(map(self._TYPE._check, values))
Exemple #29
0
 def __setslice__(self, start, stop, values):
     if self._max_len and len(self) + len(values) - len(self._values[start:stop]) > self._max_len:
         raise ProphyError("exceeded array limit")
     self._values[start:stop] = map(self._TYPE._check, values)
Exemple #30
0
 def _decode_impl(self, data, pos, endianness, len_hint):
     if self._SIZE > (len(data) - pos):
         raise ProphyError("too few bytes to decode array")
     self[:], size = decode_scalar_array(self._TYPE, data, pos, endianness, len_hint)
     return max(size, self._SIZE)