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
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)
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)
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)
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)
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
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)
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)
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))
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)
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)
def normalise_empty(self, meta): raise BadSpecValue("Must specify boolean values", meta=meta)