# AGPLv3 or later import json import zlib def encode(data, send_raw=False): # This will encode data for sending. # Data should be a writable into JSON. if not send_raw: J = json.dumps(data).encode("utf-8") else: J = data.encode("utf-8") C = zlib.compress(J) zed = len(C) raw = len(J) # Sometime compressed is larger than raw. # We will add a byte saying 69 if it comressed # and a byte saying 0 if it not sexy like this. if not send_raw and zed < raw: return chr(69).encode("utf-8") + C else: return chr(0).encode("utf-8") + J def decode(data): # This will decode the data try: code = data[0] data = data[1:] except: code = 0 # 69 means the data is sexy # see encode() for more info if code == 69: data = zlib.decompress(data).decode() else: data = data.decode() # It should be Json but it could be something else try: return json.loads(data) except: return data cache = {} cache2 = {} def diff(d1, d2, CHANGED=True): # Function that checkes for differences # between two dictionaries ans = {} # Comparing dictionaries for i in d1: if d1[i] != d2.get(i) and i in d2: if not type(d2.get(i)) == dict: ans[i] = d2[i] else: try: ans[i] = diff(d1[i], d2[i], CHANGED=False) except: ans[i] = d2[i] # Adding in new stuff for i in d2: if i not in d1: ans[i] = d2[i] # Telling it to remove old stuff remove = [] for i in d1: if i not in d2: remove.append(i) if remove: ans["DELETED"] = remove if ans and CHANGED: ans["CHANGED"] = True return ans def combine(d1,d2): # Function that combines 2 dictionaries # based on the diff version. # Changed parts for i in d1: if d1[i] != d2.get(i) and i in d2: if not type(d2.get(i)) == dict: d1[i] = d2[i] else: try: combine(d1[i], d2[i]) except: d1[i] = d2[i] # Add new stuff for i in d2: if i in ("DELETED", "CHANGED"): continue if i not in d1: d1[i] = d2[i] # Deleting stuff if "DELETED" in d2: for i in d2["DELETED"]: try: del d1[i] except: pass def encodeObj(data, ID, cache=cache): # encodes Object, stripping it from all data # that is unecessary if ID not in cache: cache[ID] = data return encode(data) else: D = diff(cache[ID], data) cache[ID] = data return encode(D) def decodeObj(data, ID, cache=cache): data = decode(data) if ID not in cache: # TODO: implement the check to see # if the data is actually CHANGED # or not. And send back the request for the # full thing if it is only the part. cache[ID] = data return data else: combine(cache[ID], data) return cache[ID]