Deserialize entity key from a bytestring. This function can only be used with entity_key_serialization_version > 2. Args: entity_key_serialization_version: version of the entity key serialization serialized_entity_key: serialized entity key bytes Returns: EntityKeyProto
(
serialized_entity_key: bytes, entity_key_serialization_version=3
)
| 191 | |
| 192 | |
| 193 | def deserialize_entity_key( |
| 194 | serialized_entity_key: bytes, entity_key_serialization_version=3 |
| 195 | ) -> EntityKeyProto: |
| 196 | """ |
| 197 | Deserialize entity key from a bytestring. This function can only be used with entity_key_serialization_version > 2. |
| 198 | Args: |
| 199 | entity_key_serialization_version: version of the entity key serialization |
| 200 | serialized_entity_key: serialized entity key bytes |
| 201 | |
| 202 | Returns: EntityKeyProto |
| 203 | |
| 204 | """ |
| 205 | if entity_key_serialization_version < 3: |
| 206 | # Not raising the error, keeping it in warning state for reserialization purpose |
| 207 | # We should remove this after few releases |
| 208 | warnings.warn( |
| 209 | "Deserialization of entity key with version < 3 is removed. Please use version 3 by setting entity_key_serialization_version=3." |
| 210 | "To reserializa your online store featrues refer - https://github.com/feast-dev/feast/blob/master/docs/how-to-guides/entity-reserialization-of-from-v2-to-v3.md" |
| 211 | ) |
| 212 | # Optimized deserialization using memoryview for zero-copy slicing |
| 213 | buffer = memoryview(serialized_entity_key) |
| 214 | pos = 0 |
| 215 | keys = [] |
| 216 | values = [] |
| 217 | |
| 218 | # Read number of keys |
| 219 | if len(buffer) < pos + 4: |
| 220 | raise ValueError( |
| 221 | "Invalid serialized entity key: insufficient data for key count" |
| 222 | ) |
| 223 | num_keys = struct.unpack("<I", buffer[pos : pos + 4])[0] |
| 224 | pos += 4 |
| 225 | |
| 226 | # Process all keys uniformly |
| 227 | for _ in range(num_keys): |
| 228 | if len(buffer) < pos + 8: # Need at least 8 bytes for type + length |
| 229 | raise ValueError( |
| 230 | "Invalid serialized entity key: insufficient data for key metadata" |
| 231 | ) |
| 232 | |
| 233 | key_type, key_length = struct.unpack("<2I", buffer[pos : pos + 8]) |
| 234 | pos += 8 |
| 235 | |
| 236 | if key_type == ValueType.STRING: |
| 237 | if len(buffer) < pos + key_length: |
| 238 | raise ValueError( |
| 239 | "Invalid serialized entity key: insufficient data for key" |
| 240 | ) |
| 241 | key = struct.unpack(f"<{key_length}s", buffer[pos : pos + key_length])[0] |
| 242 | keys.append(key.decode("utf-8").rstrip("\x00")) |
| 243 | pos += key_length |
| 244 | else: |
| 245 | raise ValueError(f"Unsupported key type: {key_type}") |
| 246 | |
| 247 | # Process values with bounds checking |
| 248 | while pos < len(buffer): |
| 249 | if len(buffer) < pos + 8: # Need at least 8 bytes for type + length |
| 250 | raise ValueError( |