def write_regexp(self, obj): flags = 0 if obj.flags & re.IGNORECASE: flags += 1 if obj.flags & re.MULTILINE: flags += 4 self.fd.write(TYPE_IVAR) self.fd.write(TYPE_REGEXP) pattern = obj.pattern.encode("utf-8") self.write_long(len(pattern)) self.fd.write(pattern) write_ubyte(self.fd, flags) self.write_long(1) self.write(Symbol("E")) self.write(False)
def write_long(self, obj): if obj == 0: self.fd.write(b"\0") elif 0 < obj < 123: write_sbyte(self.fd, obj + 5) elif -124 < obj < 0: write_sbyte(self.fd, obj - 5) else: size = int(math.ceil(obj.bit_length() / 8.0)) if size > 5: raise ValueError("%d too long for serialization" % obj) original_obj = obj factor = 256**size if obj < 0 and obj == -factor: size -= 1 obj += factor / 256 elif obj < 0: obj += factor sign = int(math.copysign(size, original_obj)) write_sbyte(self.fd, sign) for i in range(size): write_ubyte(self.fd, obj % 256) obj //= 256
def write_long(self, obj): if obj == 0: self.fd.write(b"\0") elif 0 < obj < 123: write_sbyte(self.fd, obj + 5) elif -124 < obj < 0: write_sbyte(self.fd, obj - 5) else: size = int(math.ceil(obj.bit_length() / 8.0)) if size > 5: raise ValueError("%d too long for serialization" % obj) original_obj = obj factor = 256 ** size if obj < 0 and obj == -factor: size -= 1 obj += factor / 256 elif obj < 0: obj += factor sign = int(math.copysign(size, original_obj)) write_sbyte(self.fd, sign) for i in range(size): write_ubyte(self.fd, obj % 256) obj //= 256
def write(self, obj): if obj is None: self.fd.write(TYPE_NIL) elif obj is False: self.fd.write(TYPE_FALSE) elif obj is True: self.fd.write(TYPE_TRUE) elif isinstance(obj, int) or isinstance(obj, integer_types[-1]): if obj.bit_length() <= 5 * 8: self.fd.write(TYPE_FIXNUM) # noinspection PyTypeChecker self.write_long(obj) else: self.fd.write(TYPE_BIGNUM) if obj < 0: self.fd.write(b"-") else: self.fd.write(b"+") obj = abs(obj) size = int(math.ceil(obj.bit_length() / 16.0)) self.write_long(size) for i in range(size): self.write_short(obj % 65536) obj //= 65536 elif isinstance(obj, Symbol): if obj.name in self.symbols: self.fd.write(TYPE_SYMLINK) self.write_long(self.symbols[obj.name]) else: self.fd.write(TYPE_SYMBOL) symbol_index = len(self.symbols) self.symbols[obj.name] = symbol_index encoded = obj.name.encode("utf-8") self.write_long(len(encoded)) self.fd.write(encoded) elif isinstance(obj, list): if self.must_write(obj): self.fd.write(TYPE_ARRAY) self.write_long(len(obj)) for x in obj: self.write(x) elif isinstance(obj, dict): if self.must_write(obj): self.fd.write(TYPE_HASH) self.write_long(len(obj)) for key, value in obj.items(): self.write(key) self.write(value) elif isinstance(obj, binary_type): self.fd.write(TYPE_IVAR) self.fd.write(TYPE_STRING) self.write_long(len(obj)) self.fd.write(obj) self.write_long(1) self.write(Symbol("E")) self.write(False) elif isinstance(obj, text_type): obj = obj.encode("utf-8") self.fd.write(TYPE_IVAR) self.fd.write(TYPE_STRING) self.write_long(len(obj)) self.fd.write(obj) self.write_long(1) self.write(Symbol("E")) self.write(True) elif isinstance(obj, float): obj = "%.20g" % obj if simple_float_re.match(obj): while obj.endswith("0"): obj = obj[:-1] obj = obj.encode("utf-8") self.fd.write(TYPE_FLOAT) self.write_long(len(obj)) self.fd.write(obj) elif isinstance(obj, re_class): flags = 0 if obj.flags & re.IGNORECASE: flags += 1 if obj.flags & re.DOTALL: flags += 4 self.fd.write(TYPE_IVAR) self.fd.write(TYPE_REGEXP) pattern = obj.pattern.encode("utf-8") self.write_long(len(pattern)) self.fd.write(pattern) write_ubyte(self.fd, flags) self.write_long(1) self.write(Symbol("E")) self.write(False) elif isinstance(obj, UsrMarshal): if self.must_write(obj): self.fd.write(TYPE_USRMARSHAL) self.write(Symbol(obj.cls)) self.write(obj.values) else: raise ValueError(obj)