-
Notifications
You must be signed in to change notification settings - Fork 4
/
FixedIO.py
53 lines (41 loc) · 1.88 KB
/
FixedIO.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from flipjump.interpretter.io_devices.IODevice import IODevice
from flipjump.utils.exceptions import IOReadOnEOF, IncompleteOutput
class FixedIO(IODevice):
"""
read from fixed input, don't output (with get_output functionality)
"""
def __init__(self, _input: bytes):
self.remaining_input = _input
self._output = b''
self.current_input_byte = 0
self.bits_to_read_in_input_byte = 0
self.current_output_byte = 0
self.bits_to_write_in_output_byte = 0
def read_bit(self) -> bool:
if 0 == self.bits_to_read_in_input_byte:
if not self.remaining_input:
raise IOReadOnEOF("Read an empty input on fixed IO (EOF)")
self.current_input_byte = self.remaining_input[0]
self.remaining_input = self.remaining_input[1:]
self.bits_to_read_in_input_byte = 8
bit = (self.current_input_byte & 1) == 1
self.current_input_byte >>= 1
self.bits_to_read_in_input_byte -= 1
return bit
def write_bit(self, bit: bool) -> None:
self.current_output_byte |= bit << self.bits_to_write_in_output_byte
self.bits_to_write_in_output_byte += 1
if 8 == self.bits_to_write_in_output_byte:
self._output += self.current_output_byte.to_bytes(1, 'little')
self.current_output_byte = 0
self.bits_to_write_in_output_byte = 0
def get_output(self, *, allow_incomplete_output: bool = False) -> bytes:
"""
@raise IncompleteOutput when the number of outputted bits can't be divided by 8
@return: full output until now
"""
if not allow_incomplete_output and 0 != self.bits_to_write_in_output_byte:
raise IncompleteOutput(
"tries to get output when an unaligned number of bits was outputted " "(doesn't divide 8)"
)
return self._output