Esempio n. 1
0
    def normalise_filled(self, meta, val):
        """
        Convert to and from a string into an integer
        """
        if self.unpacking:
            if type(val) is str:
                if not regexes["version_number"].match(val):
                    raise BadSpecValue(r"Expected string to match \d+.\d+",
                                       got=val,
                                       meta=meta)
                return val

            val = sb.integer_spec().normalise(meta, val)
            major = val >> 0x10
            minor = val & 0xFFFF
            return f"{major}.{minor}"
        else:
            if type(val) is int:
                return val

            val = sb.string_spec().normalise(meta, val)
            m = regexes["version_number"].match(val)
            if not m:
                raise BadSpecValue(
                    r"Expected version string to match (\d+.\d+)",
                    wanted=val,
                    meta=meta)

            groups = m.groupdict()
            major = int(groups["major"])
            minor = int(groups["minor"])
            return (major << 0x10) + minor
Esempio n. 2
0
    def pack(self, meta, val):
        if type(val) not in (bytes, bitarray):
            try:
                if type(val) is not list:
                    raise BadSpecValue("Not a list")

                items = sb.listof(sb.dictionary_spec()).normalise(meta, val)
            except BadSpecValue as error:
                raise BadSpecValue(
                    "Sorry, many fields only supports a list of dictionary of values",
                    error=error)
            else:
                res = []
                for i, v in enumerate(items):
                    nxt = self.kls(**v)
                    spec = self.bytes_spec_for(nxt)
                    if hasattr(self.kls.Meta, "cache"):
                        items = tuple(sorted(nxt.items()))
                        if items not in self.kls.Meta.cache:
                            self.kls.Meta.cache[items] = nxt.pack()
                        packd = self.kls.Meta.cache[items]
                    else:
                        packd = nxt.pack()
                    res.append(spec.normalise(meta.indexed_at(i), packd))
                val = functools.reduce(operator.add, res)

        # The spec is likely a T.Bytes and will ensure we have enough bytes length in the result
        return self.spec.normalise(meta, val)
Esempio n. 3
0
    def normalise(self, meta, val):
        if self.unpacking:
            if type(val) in (bitarray, bytes):
                return self.kls.create(self.spec.normalise(meta, val))
            elif isinstance(val, self.kls):
                return val
            elif isinstance(val, dict):
                return self.kls.create(val)
            elif val is sb.NotSpecified:
                return self.kls.create()
            else:
                raise BadSpecValue("Expected to unpack bytes",
                                   found=val,
                                   transforming_into=self.kls)
        else:
            if type(val) not in (bytes, bitarray):
                try:
                    fields = sb.dictionary_spec().normalise(meta, val)
                except BadSpecValue as error:
                    raise BadSpecValue(
                        "Sorry, dynamic fields only supports a dictionary of values",
                        error=error)
                else:
                    val = self.kls.create(fields).pack()

            # The spec is likely a T.Bytes and will ensure we have enough bytes length in the result
            return self.spec.normalise(meta, val)
Esempio n. 4
0
    def normalise_filled(self, meta, val):
        if type(val) is bool:
            raise BadSpecValue(
                "Converting a boolean into a float makes no sense",
                got=val,
                meta=meta)

        try:
            return float(val)
        except (TypeError, ValueError) as error:
            raise BadSpecValue("Failed to convert value into a float",
                               got=val,
                               error=error,
                               meta=meta)
Esempio n. 5
0
    def unpack(self, meta, val):
        if type(val) in (bitarray, bytes):
            res = []
            bts = self.spec.normalise(meta, val)

            i = -1
            while True:
                i += 1
                nxt = self.kls.unpack(bts)
                res.append(nxt)

                size = len(
                    self.bytes_spec_for(nxt).normalise(meta.indexed_at(i),
                                                       bts))
                bts = bts[size:]
                if not bts:
                    break

            return res
        elif isinstance(val, list):
            return val
        else:
            raise BadSpecValue("Expected to unpack bytes",
                               found=val,
                               transforming_into_list_of=self.kls)
Esempio n. 6
0
    def pack(self, meta, val):
        if val is sb.NotSpecified:
            val = []

        if not isinstance(val, list):
            raise BadSpecValue("Expected a list", meta=meta, got=type(val))

        number = self.number
        if len(val) > number:
            raise BadSpecValue("Expected correct number of items",
                               meta=meta,
                               got=len(val),
                               want=number)

        kls = self.kls
        if kls and not isinstance(kls, type):
            kls = kls(self.pkt)

        res = []
        i = -1
        for item in val:
            i += 1
            if kls:
                item = self.val_to_kls(kls, meta.indexed_at(i), item)
                if hasattr(kls.Meta, "cache"):
                    items = tuple(sorted(item.items()))
                    if items not in kls.Meta.cache:
                        kls.Meta.cache[items] = item.pack()
                    item = kls.Meta.cache[items]
                else:
                    item = item.pack()
            res.append(self.spec.normalise(meta.indexed_at(i), item))

        while len(res) < number:
            i += 1
            res.append(self.spec.normalise(meta.indexed_at(i),
                                           sb.NotSpecified))

        return res
Esempio n. 7
0
    def normalise_filled(self, meta, val):
        """
        Booleans are returned as is.

        Integers are returned as True or False depending on whether they are 0 or 1

        Otherwise an error is raised
        """
        if type(val) is bool:
            return val
        if val in (0, 1):
            return bool(val)
        raise BadSpecValue("Could not convert value into a boolean",
                           val=val,
                           meta=meta)
Esempio n. 8
0
    def normalise_filled(self, meta, val):
        """
        Booleans are returned as integer 0 or 1.

        Integers are returned as is if they are 0 or 1

        Otherwise an error is raised
        """
        if type(val) is bool:
            return int(val)
        if val in (0, 1):
            return val
        raise BadSpecValue("BoolInts must be True, False, 0 or 1",
                           got=val,
                           meta=meta)
Esempio n. 9
0
    def unpack(self, meta, val):
        kls = self.kls
        if kls and not isinstance(kls, type):
            kls = kls(self.pkt)

        if val is sb.NotSpecified:
            val = []

        if val is sb.NotSpecified or type(val) in (bytes, bitarray):
            return self.unpack_bytes(meta, val, kls, self.number)
        elif isinstance(val, MultipleWrapper):
            return val.clone(kls, self.number, meta, self.val_to_kls)
        elif isinstance(val, list):
            return self.unpack_list(meta, val, kls, self.number)
        else:
            raise BadSpecValue("Expected to unpack bytes or list",
                               found=type(val))
Esempio n. 10
0
    def unpack_list(self, meta, val, kls, number):
        if len(val) > number:
            raise BadSpecValue("Expected correct number of items",
                               meta=meta,
                               got=len(val),
                               want=number)

        kls = self.kls
        if kls and not isinstance(kls, type):
            kls = kls(self.pkt)

        res = []
        i = -1
        for v in val:
            i += 1
            res.append(self.val_to_kls(kls, meta.indexed_at(i), v))

        while len(res) < number:
            i += 1
            res.append(
                self.val_to_kls(kls, meta.indexed_at(i), sb.NotSpecified))

        return MultipleWrapper(res, kls, number, meta, self.val_to_kls)
Esempio n. 11
0
    def normalise_filled(self, meta, val):
        """
        If we're unpacking, then:

        * If a string, return as is
        * If bytes, find the null byte and cut off there

        If we're packing, then just use ``bytes_spec``
        """
        if self.unpacking:
            if type(val) is str:
                return val

            if type(val) is bitarray:
                val = val.tobytes()

            if b"\x00" in val:
                val = val[:val.find(b"\x00")]

            try:
                return val.decode()
            except UnicodeDecodeError as error:
                log.warning(
                    __import__("photons_app").helpers.
                    lc("Can't turn bytes into string, so just returning bytes",
                       error=error))
                return val
            except Exception as error:
                raise BadSpecValue(
                    "String before the null byte could not be decoded",
                    val=val,
                    erorr=error)
        else:
            if type(val) is str:
                val = val.encode()
            return bytes_spec(self.pkt, self.size_bits).normalise(meta, val)
Esempio n. 12
0
 def normalise_empty(self, meta):
     raise BadSpecValue("Must specify boolean values", meta=meta)