+class JsonDecoder(object):
+
+ def __init__(self):
+ self.buf = u""
+ self.raw_decode = json.JSONDecoder().raw_decode
+
+ def decode(self, data):
+ chunks = []
+ buf = self.buf + data
+ while True:
+ try:
+ buf = buf.lstrip()
+ res, ptr = self.raw_decode(buf)
+ buf = buf[ptr:]
+ chunks.append(res)
+ except ValueError:
+ break
+ self.buf = buf
+ return chunks
+
+
+class Timer(object):
+
+ def __init__(self, timeout):
+ # If timeout is None, we never expire.
+ self.timeout = timeout
+ self.reset()
+
+ def reset(self):
+ self.time = time.time()
+
+ def expired(self):
+ """
+ If expired, reset the timer and return True.
+ """
+ if self.timeout is None:
+ return False
+ elif time.time() - self.time > self.timeout:
+ self.reset()
+ return True
+ return False
+
+
+class SockReader(object):
+ def __init__(self, sock, sock_timeout):
+ self.sock = sock
+ self.sock_timeout = sock_timeout
+
+ def read(self):
+ try:
+ ready_to_read = select.select([self.sock], [], [], self.sock_timeout)[0]
+ if ready_to_read:
+ return self.sock.read()
+ except SSLError as e:
+ # Code 2 is error from a non-blocking read of an empty buffer.
+ if e.errno != 2:
+ raise
+ return bytearray()