def parse(cls, typedesc: bytes) -> TypeDesc: buf = io.BytesIO(typedesc) wrapped = binwrapper.BinWrapper(buf) codecs_list = [] while buf.tell() < len(typedesc): desc = cls._parse(wrapped, codecs_list) if desc is not None: codecs_list.append(desc) return desc
def dump(self, outfn: os.PathLike) -> None: with open(outfn, 'wb+') as outf: buf = binwrapper.BinWrapper(outf) buf.write_bytes(consts.HEADER_TITLE) buf.write_ui64(consts.DUMP_FORMAT_VER) self.conn._dump(on_header=functools.partial( self._header_callback, buf), on_data=functools.partial(self._block_callback, buf))
def parse(cls, typedesc: bytes, protocol_version: tuple) -> TypeDesc: buf = io.BytesIO(typedesc) wrapped = binwrapper.BinWrapper(buf) codecs_list = [] while buf.tell() < len(typedesc): desc = cls._parse(wrapped, codecs_list, protocol_version) if desc is not None: codecs_list.append(desc) if not codecs_list: raise errors.InternalServerError('could not parse type descriptor') return codecs_list[-1]
def dump(self) -> bytes: iobuf = io.BytesIO() buf = binwrapper.BinWrapper(iobuf) fields = type(self)._fields for fieldname, field in fields.items(): if fieldname in {'mtype', 'message_length'}: continue val = getattr(self, fieldname) field.dump(val, buf) dumped = iobuf.getvalue() return (fields['mtype'].default.to_bytes(1, 'big') + (len(dumped) + 4).to_bytes(4, 'big') + dumped)
def _parse( self, f: io.FileIO, ) -> Tuple[bytes, Iterator[bytes]]: def block_reader(buf: binwrapper.BinWrapper) -> Iterable[bytes]: while True: try: block_type = buf.read_bytes(1) except BufferError: # No more data blocks to read return if block_type != b'D': raise RuntimeError('cannot read the data block') block_hash = buf.read_bytes(20) block_bytes = buf.read_len32_prefixed_bytes() if hashlib.sha1(block_bytes).digest() != block_hash: raise RuntimeError( 'dump integrity is compromised: data block ' 'does not match the checksum') yield block_bytes buf = binwrapper.BinWrapper(f) header = buf.read_bytes(consts.HEADER_TITLE_LEN) if header != consts.HEADER_TITLE: raise RuntimeError('not an EdgeDB dump') dump_ver = buf.read_ui64() if dump_ver > consts.MAX_SUPPORTED_DUMP_VER: raise RuntimeError(f'dump version {dump_ver} is not supported') block_type = buf.read_bytes(1) if block_type != b'H': raise RuntimeError('cannot find the header block') header_hash = buf.read_bytes(20) header_bytes = buf.read_len32_prefixed_bytes() if hashlib.sha1(header_bytes).digest() != header_hash: raise RuntimeError( 'dump integrity is compromised: header data does not match ' 'the checksum') return header_bytes, block_reader(buf)
def parse(cls, mtype: int, data: bytes) -> ServerMessage: iobuf = io.BytesIO(data) buffer = binwrapper.BinWrapper(iobuf) kwargs: typing.Dict[str, any] = {} msg_types = cls.index.get(mtype) if not msg_types: raise ValueError(f"unspecced message type {chr(mtype)!r}") if len(msg_types) > 1: raise ValueError(f"multiple specs for message type {chr(mtype)!r}") msg_type = msg_types[0] for fieldname, field in msg_type._fields.items(): if fieldname in {'mtype', 'message_length'}: continue kwargs[fieldname] = field.parse(buffer) if len(iobuf.read(1)): raise ValueError( f'buffer is not empty after parsing {chr(mtype)!r} message') return msg_type(**kwargs)