preserves/implementations/python/preserves/iolist.py

73 lines
1.6 KiB
Python

# An iolist is one of
# - None
# - a list of iolists
# - a CountedIOList
# - a bytes
# - a number i, 0 <= i < 256
class CountedIOList:
def __init__(self, i):
self.value = i
self.length = len(i)
def counted(i):
if isinstance(i, CountedIOList): return i
return CountedIOList(i)
def withbyte(i, b):
if i is None:
return b
elif isinstance(i, list):
i.append(b)
return i
else:
return [i, b]
_len = len
def join(*iolists):
if _len(iolists) == 0:
return None
if _len(iolists) == 1:
return iolists[0]
return list(iolists)
def len(i):
if i is None:
return 0
if isinstance(i, int):
return 1
if isinstance(i, _bytes):
return _len(i)
if isinstance(i, list):
acc = 0
for j in i:
acc = acc + len(j)
return acc
if isinstance(i, CountedIOList):
return i.length
raise ValueError('invalid iolist: ' + repr(i) + ' ' + repr(type(i)))
_bytes = bytes
def bytes(i):
buffer = bytearray(len(i))
def fill(i, offset):
while isinstance(i, CountedIOList):
i = i.value
if i is None:
return offset
if isinstance(i, int):
buffer[offset] = i
return offset + 1
if isinstance(i, _bytes):
buffer[offset:offset+_len(i)] = i
return offset + _len(i)
if isinstance(i, list):
for j in i:
offset = fill(j, offset)
return offset
raise ValueError('invalid iolist')
fill(i, 0)
return _bytes(buffer)