diff --git a/bmemcached/protocol.py b/bmemcached/protocol.py index 1d3c45c..9a3b266 100644 --- a/bmemcached/protocol.py +++ b/bmemcached/protocol.py @@ -15,6 +15,11 @@ logger = logging.getLogger(__name__) +# The value body of a get response starts with a 4 byte flags field. A Struct +# for '!L%ds' would be specific to one value length, so it is not reusable. +# Read the fixed part with this, then slice the rest. A slice compiles nothing. +FLAGS_UNPACKER = struct.Struct("!L") + class Protocol(threading.local): """ @@ -475,7 +480,8 @@ def get(self, key): raise MemcachedException(f"Code: {status:d} Message: {extra_content}", status) - flags, value = struct.unpack(f"!L{bodylen - 4}s", extra_content) + (flags,) = FLAGS_UNPACKER.unpack_from(extra_content) + value = extra_content[4:] return self.deserialize(value, flags), cas @@ -549,7 +555,9 @@ def get_multi(self, keys): ) if status == SUCCESS: - flags, key, value = struct.unpack(f"!L{keylen}s{bodylen - keylen - 4}s", extra_content) + (flags,) = FLAGS_UNPACKER.unpack_from(extra_content) + key = extra_content[4 : 4 + keylen] + value = extra_content[4 + keylen :] d[key] = self.deserialize(value, flags), cas elif status == DISCONNECTED: