skppy.parser.tlv

Core TLV primitives for SketchUp model.dat binary encoding.

Record wire format (model.dat geometry section):

tag : u16 little-endian (2 bytes) length : u32 little-endian (4 bytes) payload: <length> bytes

class skppy.parser.tlv.TlvTag[source]

Bases: IntEnum

All known TLV tag values for SketchUp model.dat binary format.

This enum contains every tag recognized by the skppy parser, covering root-level blocks (0x01F4-0x0214), entity records (0x05DC-0x7D64), and all sub-tags for materials, layers, cameras, styles, etc.

Tags are grouped by functional area with comments indicating the hex range and purpose. The numeric values match the on-disk TLV tag integers used in SketchUp’s model.dat binary stream.

See the SketchUp C API headers for the canonical tag definitions.

__new__(value)
skppy.parser.tlv.find_all_children(data: bytes, target_tag: int) list[bytes][source]

Return all child payloads whose tag matches target_tag.

Parameters:
  • data (bytes) – Raw TLV payload to search.

  • target_tag (int) – Tag value to match.

Returns:

All matching child payloads (may be empty).

Return type:

list of bytes

skppy.parser.tlv.find_child(data: bytes, target_tag: int) bytes | None[source]

Return the first child payload whose tag matches target_tag, or None.

Parameters:
  • data (bytes) – Parent TLV payload containing child records.

  • target_tag (int) – Tag value to locate.

Returns:

Matching child payload, or None when absent.

Return type:

bytes or None

skppy.parser.tlv.find_model_root(data: bytes) int[source]

Return the byte offset of the 0x01F4 root TLV record in model.dat.

In practice the root record starts at offset 0 and spans the entire model.dat payload. This function verifies that assumption and falls back to a short scan if the file starts differently.

Parameters:

data (bytes) – Raw model.dat byte stream.

Returns:

Offset of the MODEL_ROOT record.

Return type:

int

Raises:

ValueError – If no plausible model root can be found.

skppy.parser.tlv.format_guid(raw_bytes: bytes) str[source]

Convert raw 16-byte GUID to standard UUID string format.

SketchUp uses the standard Windows GUID format. The first 8 bytes (data1, data2, data3) are stored in little-endian byte order on disk and must be byte-swapped for display. The last 8 bytes (data4) are stored as-is.

This matches the standard GUID layout and the Windows ToString format.

Returns a UUID string in the standard 8-4-4-4-12 format (e.g., “550e8400-eb93-47d3-a957-1309ee55672b”).

Parameters:

raw_bytes (bytes) – Exactly 16 bytes representing a GUID.

Returns:

UUID string in standard format.

Return type:

str

skppy.parser.tlv.index_children(data: bytes) dict[int, bytes][source]

Index the first child payload for every tag in one pass.

This is equivalent to calling find_child() for several distinct tags, but avoids repeatedly scanning large entity records. Duplicate tags intentionally retain the first payload to preserve find_child semantics.

Parameters:

data (bytes) – Parent TLV payload containing child records.

Returns:

Mapping of integer tag values to their first payload.

Return type:

dict

skppy.parser.tlv.iter_record_prefix(data: bytes) Iterator[Tuple[int, bytes]][source]

Yield the complete TLV prefix before malformed trailing data.

This recovery-oriented iterator is intentionally separate from iter_records(). It is suitable for diagnostics and mutation analysis, never for constructing a model that will be returned as successfully parsed.

skppy.parser.tlv.iter_records(data: bytes) Iterator[Tuple[int, bytes]][source]

Yield (tag, payload) pairs for every TLV record in data.

Raises when a record header or payload is truncated. Structural parsers use this strict iterator so corrupt nested containers cannot masquerade as valid records with missing optional fields.

Parameters:

data (bytes) – Byte buffer containing zero or more TLV records.

Returns:

(tag, payload) pairs.

Return type:

iterator of tuple

skppy.parser.tlv.read_bool(payload: bytes) bool[source]

Decode a single-byte boolean value.

Parameters:

payload (bytes) – Raw bytes; the first byte is interpreted as a boolean.

Returns:

True if the first byte is non-zero, False for an empty payload or a zero byte.

Return type:

bool

skppy.parser.tlv.read_compact_int(payload: bytes) int[source]

Decode a variable-length little-endian unsigned integer (1-4 bytes).

SketchUp’s compact-int encoding uses 1 to 4 bytes depending on the magnitude of the value. Any payload length up to 4 bytes is accepted.

Parameters:

payload (bytes) – Raw bytes containing the encoded integer (little-endian).

Returns:

The decoded non-negative integer. Returns 0 for an empty payload.

Return type:

int

skppy.parser.tlv.read_entity_id(entity_base_payload: bytes) int[source]

Extract the entity ID from an entity-base (0x07D0) payload.

Navigates the TLV hierarchy ENTITY_BASE -> ID_WRAPPER -> ID_VALUE and returns the decoded compact integer.

Parameters:

entity_base_payload (bytes) – Raw payload of the ENTITY_BASE (0x07D0) TLV record.

Returns:

The entity ID, or 0 if the ID cannot be found.

Return type:

int

skppy.parser.tlv.read_f64_le(payload: bytes) float[source]

Decode a little-endian 64-bit IEEE 754 double.

Parameters:

payload (bytes) – Raw bytes (must contain at least 8 bytes).

Returns:

The decoded floating-point value.

Return type:

float

skppy.parser.tlv.read_guid(payload: bytes) bytes[source]

Return first 16 bytes as a raw GUID blob.

The raw bytes can be converted to a UUID string using format_guid().

Parameters:

payload (bytes) – Raw GUID payload.

Returns:

Up to the first 16 bytes from payload.

Return type:

bytes

skppy.parser.tlv.read_id_from_wrapper(wrapper_payload: bytes) int[source]

Extract the ID from a bare id-wrapper (0x05DC) payload.

This is a simplified path used when the ID wrapper is the direct parent (not nested inside an ENTITY_BASE).

Parameters:

wrapper_payload (bytes) – Raw payload of the ID_WRAPPER (0x05DC) TLV record.

Returns:

The decoded ID, or 0 if not found.

Return type:

int

skppy.parser.tlv.read_record(data: bytes, offset: int) Tuple[int, bytes, int][source]

Read one TLV record at offset.

Parameters:
  • data (bytes) – Byte buffer containing TLV records.

  • offset (int) – Offset of the record header.

Returns:

(tag, payload, next_offset).

Return type:

tuple

Raises:

ValueError – If the header or payload is truncated.

skppy.parser.tlv.read_transform13(payload: bytes) list[float][source]

Decode a SketchUp transformation (13 x little-endian f64).

The 13-value layout matches the documented SUTransformation storage: 12 rotation/scale matrix values (row-major 3x4) followed by a perspective component.

Parameters:

payload (bytes) – Raw bytes (must contain at least 104 bytes).

Returns:

13 transformation values in SUTransformation order.

Return type:

list of float

skppy.parser.tlv.read_u32_le(payload: bytes) int[source]

Decode a little-endian 32-bit unsigned integer.

Accepts payloads shorter than 4 bytes (zero-extended).

Parameters:

payload (bytes) – Raw bytes containing the encoded integer (little-endian).

Returns:

The decoded unsigned 32-bit integer.

Return type:

int

skppy.parser.tlv.read_utf8(payload: bytes) str[source]

Decode a UTF-8 string payload.

Malformed byte sequences are replaced with the Unicode replacement character (U+FFFD) rather than raising.

Parameters:

payload (bytes) – Raw UTF-8 encoded bytes.

Returns:

The decoded string.

Return type:

str

skppy.parser.tlv.read_vec3(payload: bytes) Tuple[float, float, float][source]

Decode a 3-D vector (3 x little-endian f64).

Parameters:

payload (bytes) – Raw bytes (must contain at least 24 bytes).

Returns:

(x, y, z) components.

Return type:

tuple of float

skppy.parser.tlv.read_vec4(payload: bytes) Tuple[float, float, float, float][source]

Decode a 4-component vector (4 x little-endian f64).

Used for plane equations (a, b, c, d) where ax + by + cz + d = 0.

Parameters:

payload (bytes) – Raw bytes (must contain at least 32 bytes).

Returns:

(a, b, c, d) components.

Return type:

tuple of float