import time


class Reader(object):

    wait = 0.2
    timeout = 2.0
    bufsize = 4096

    def __init__(self, fd, data_type=None, eof=False):
        self.fd = fd
        self.data_type = data_type if (data_type is not None) else lambda x: x
        self.eof = eof
        self.total = 0

    def __iter__(self):
        return self

    def next(self):
        block = bytearray()
        if self.eof:
            data = self.fd.read(self.bufsize)
            if data:
                self.total += len(data)
                block.extend(data)
                return block
            else:
                raise StopIteration()

        finish_time = time.time() + self.timeout
        while time.time() <= finish_time:
            left = self.bufsize - len(block)
            data = self.fd.read(left)
            if data:
                self.total += len(data)
                block.extend(data)

            if len(block) == self.bufsize:
                return self.data_type(block)

            time.sleep(self.wait)

        raise IOError('timeout')

    __next__ = next
