feat(iphone): python topology codec

This commit is contained in:
clement
2026-06-30 21:58:42 +02:00
parent 67f347e705
commit fbc8b55044
2 changed files with 71 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
"""AVLiveWire topology payload codec.
Mirror of the Swift `TopologyPayload` (shared/AVLiveWire). Layout
(big-endian): u16 jointCount; per joint [u8 nameLen + utf8 name];
then per joint i16 parent (-1 = root).
"""
from __future__ import annotations
import struct
def encode_topology(names: list[str], parents: list[int]) -> bytes:
out = bytearray()
out += struct.pack(">H", len(names))
for nm in names:
b = nm.encode("utf-8")[:255]
out.append(len(b))
out += b
for p in parents:
out += struct.pack(">h", p)
return bytes(out)
def decode_topology(payload: bytes):
"""Return (joint_names, parents) or None if malformed."""
if len(payload) < 2:
return None
n = struct.unpack(">H", payload[:2])[0]
o = 2
names: list[str] = []
for _ in range(n):
if o >= len(payload):
return None
ln = payload[o]
o += 1
if o + ln > len(payload):
return None
names.append(payload[o:o + ln].decode("utf-8", "replace"))
o += ln
if o + n * 2 > len(payload):
return None
parents = list(struct.unpack(">" + "h" * n, payload[o:o + n * 2]))
return names, parents
@@ -0,0 +1,28 @@
"""AVLiveWire topology payload round-trip (mirror of Swift TopologyPayload)."""
from data_only_viz.arkit_topology import decode_topology, encode_topology
def test_round_trip():
names = ["root_joint", "hips_joint", "left_arm_joint"]
parents = [-1, 0, 1]
payload = encode_topology(names, parents)
out = decode_topology(payload)
assert out is not None
got_names, got_parents = out
assert got_names == names
assert got_parents == parents
def test_empty():
payload = encode_topology([], [])
out = decode_topology(payload)
assert out == ([], [])
def test_rejects_truncated():
# Claims 3 joints, provides no body.
assert decode_topology(b"\x00\x03") is None
def test_rejects_too_short():
assert decode_topology(b"\x00") is None