blob: 143db4a95e38e1bde2d3cd7e35d33f216e04f6c4 [file] [log] [blame]
################################################################################
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
################################################################################
import struct
class InputStream(object):
"""
A pure Python implementation of InputStream.
"""
def __init__(self, data):
self.data = data
self.pos = 0
def read(self, size):
self.pos += size
return self.data[self.pos - size: self.pos]
def read_byte(self):
self.pos += 1
return self.data[self.pos - 1]
def read_int8(self):
return struct.unpack('b', self.read(1))[0]
def read_int16(self):
return struct.unpack('>h', self.read(2))[0]
def read_int32(self):
return struct.unpack('>i', self.read(4))[0]
def read_int64(self):
return struct.unpack('>q', self.read(8))[0]
def read_float(self):
return struct.unpack('>f', self.read(4))[0]
def read_double(self):
return struct.unpack('>d', self.read(8))[0]
def read_bytes(self):
size = self.read_int32()
return self.read(size)
def read_var_int64(self):
shift = 0
result = 0
while True:
byte = self.read_byte()
if byte < 0:
raise RuntimeError('VarLong not terminated.')
bits = byte & 0x7F
if shift >= 64 or (shift >= 63 and bits > 1):
raise RuntimeError('VarLong too long.')
result |= bits << shift
shift += 7
if not byte & 0x80:
break
if result >= 1 << 63:
result -= 1 << 64
return result
def size(self):
return len(self.data) - self.pos
class OutputStream(object):
"""
A pure Python implementation of OutputStream.
"""
def __init__(self):
self.data = []
self.byte_count = 0
def write(self, b: bytes):
self.data.append(b)
self.byte_count += len(b)
def write_byte(self, v):
self.data.append(chr(v).encode('latin-1'))
self.byte_count += 1
def write_int8(self, v: int):
self.write(struct.pack('b', v))
def write_int16(self, v: int):
self.write(struct.pack('>h', v))
def write_int32(self, v: int):
self.write(struct.pack('>i', v))
def write_int64(self, v: int):
self.write(struct.pack('>q', v))
def write_float(self, v: float):
self.write(struct.pack('>f', v))
def write_double(self, v: float):
self.write(struct.pack('>d', v))
def write_bytes(self, v: bytes, size: int):
self.write_int32(size)
self.write(v[:size])
def write_var_int64(self, v: int):
if v < 0:
v += 1 << 64
if v <= 0:
raise ValueError('Value too large (negative).')
while True:
bits = v & 0x7F
v >>= 7
if v:
bits |= 0x80
self.data.append(chr(bits).encode('latin-1'))
self.byte_count += 1
if not v:
break
def get(self) -> bytes:
return b''.join(self.data)
def size(self) -> int:
return self.byte_count
def clear(self):
self.data.clear()
self.byte_count = 0