github.com/apache/beam/sdks/v2@v2.48.2/python/apache_beam/coders/slow_stream.py (about) 1 # 2 # Licensed to the Apache Software Foundation (ASF) under one or more 3 # contributor license agreements. See the NOTICE file distributed with 4 # this work for additional information regarding copyright ownership. 5 # The ASF licenses this file to You under the Apache License, Version 2.0 6 # (the "License"); you may not use this file except in compliance with 7 # the License. You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 # 17 18 """A pure Python implementation of stream.pyx. 19 20 For internal use only; no backwards-compatibility guarantees. 21 """ 22 # pytype: skip-file 23 24 import struct 25 from typing import List 26 27 28 class OutputStream(object): 29 """For internal use only; no backwards-compatibility guarantees. 30 31 A pure Python implementation of stream.OutputStream.""" 32 def __init__(self): 33 self.data = [] # type: List[bytes] 34 self.byte_count = 0 35 36 def write(self, b, nested=False): 37 # type: (bytes, bool) -> None 38 assert isinstance(b, bytes) 39 if nested: 40 self.write_var_int64(len(b)) 41 self.data.append(b) 42 self.byte_count += len(b) 43 44 def write_byte(self, val): 45 self.data.append(chr(val).encode('latin-1')) 46 self.byte_count += 1 47 48 def write_var_int64(self, v): 49 # type: (int) -> None 50 if v < 0: 51 v += 1 << 64 52 if v <= 0: 53 raise ValueError('Value too large (negative).') 54 while True: 55 bits = v & 0x7F 56 v >>= 7 57 if v: 58 bits |= 0x80 59 self.write_byte(bits) 60 if not v: 61 break 62 63 def write_bigendian_int64(self, v): 64 self.write(struct.pack('>q', v)) 65 66 def write_bigendian_uint64(self, v): 67 self.write(struct.pack('>Q', v)) 68 69 def write_bigendian_int32(self, v): 70 self.write(struct.pack('>i', v)) 71 72 def write_bigendian_int16(self, v): 73 self.write(struct.pack('>h', v)) 74 75 def write_bigendian_double(self, v): 76 self.write(struct.pack('>d', v)) 77 78 def write_bigendian_float(self, v): 79 self.write(struct.pack('>f', v)) 80 81 def get(self): 82 # type: () -> bytes 83 return b''.join(self.data) 84 85 def size(self): 86 # type: () -> int 87 return self.byte_count 88 89 def _clear(self): 90 # type: () -> None 91 self.data = [] 92 self.byte_count = 0 93 94 95 class ByteCountingOutputStream(OutputStream): 96 """For internal use only; no backwards-compatibility guarantees. 97 98 A pure Python implementation of stream.ByteCountingOutputStream.""" 99 def __init__(self): 100 # Note that we don't actually use any of the data initialized by our super. 101 super().__init__() 102 self.count = 0 103 104 def write(self, byte_array, nested=False): 105 # type: (bytes, bool) -> None 106 blen = len(byte_array) 107 if nested: 108 self.write_var_int64(blen) 109 self.count += blen 110 111 def write_byte(self, _): 112 self.count += 1 113 114 def get_count(self): 115 return self.count 116 117 def get(self): 118 raise NotImplementedError 119 120 def __str__(self): 121 return '<%s %s>' % (self.__class__.__name__, self.count) 122 123 124 class InputStream(object): 125 """For internal use only; no backwards-compatibility guarantees. 126 127 A pure Python implementation of stream.InputStream.""" 128 def __init__(self, data): 129 # type: (bytes) -> None 130 self.data = data 131 self.pos = 0 132 133 def size(self): 134 return len(self.data) - self.pos 135 136 def read(self, size): 137 # type: (int) -> bytes 138 self.pos += size 139 return self.data[self.pos - size:self.pos] 140 141 def read_all(self, nested): 142 # type: (bool) -> bytes 143 return self.read(self.read_var_int64() if nested else self.size()) 144 145 def read_byte(self): 146 # type: () -> int 147 self.pos += 1 148 return self.data[self.pos - 1] 149 150 def read_var_int64(self): 151 shift = 0 152 result = 0 153 while True: 154 byte = self.read_byte() 155 if byte < 0: 156 raise RuntimeError('VarLong not terminated.') 157 158 bits = byte & 0x7F 159 if shift >= 64 or (shift >= 63 and bits > 1): 160 raise RuntimeError('VarLong too long.') 161 result |= bits << shift 162 shift += 7 163 if not byte & 0x80: 164 break 165 if result >= 1 << 63: 166 result -= 1 << 64 167 return result 168 169 def read_bigendian_int64(self): 170 return struct.unpack('>q', self.read(8))[0] 171 172 def read_bigendian_uint64(self): 173 return struct.unpack('>Q', self.read(8))[0] 174 175 def read_bigendian_int32(self): 176 return struct.unpack('>i', self.read(4))[0] 177 178 def read_bigendian_int16(self): 179 return struct.unpack('>h', self.read(2))[0] 180 181 def read_bigendian_double(self): 182 return struct.unpack('>d', self.read(8))[0] 183 184 def read_bigendian_float(self): 185 return struct.unpack('>f', self.read(4))[0] 186 187 188 def get_varint_size(v): 189 """For internal use only; no backwards-compatibility guarantees. 190 191 Returns the size of the given integer value when encode as a VarInt.""" 192 if v < 0: 193 v += 1 << 64 194 if v <= 0: 195 raise ValueError('Value too large (negative).') 196 varint_size = 0 197 while True: 198 varint_size += 1 199 v >>= 7 200 if not v: 201 break 202 return varint_size