docs: def read(self, size=None):
          """
          read([size]) -> read at most size bytes, returned as a string.
  
          If the size argument is negative or None, read until EOF is reached.
          Return an empty string at EOF.
          """
          if size is None or size < 0:
              return "".join(list(self))
          else:
              data_chunks = []
              data_readed = 0
              try:
                  while data_readed < size:
                      chunk = self.next_chunk()
                      data_chunks.append(chunk)
                      data_readed += len(chunk)
              except StopIteration:
                  pass
  
              if data_readed > size:
                  last_chunk = data_chunks.pop()
                  extra_length = data_readed - size
                  last_chunk, extra_data = last_chunk[:-extra_length], last_chunk[-extra_length:]
                  self.unshift(extra_data)
                  data_chunks.append(last_chunk)
              return "".join(data_chunks)