Ejemplo n.º 1
0
 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
Ejemplo n.º 2
0
    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))
Ejemplo n.º 3
0
 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]
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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)