Every field in a Crate file has a name (a token)
and a value, and the value is described by a 64-bit value representation: a type code,
flags, and either the value itself or where to find it. This page follows the OpenUSD
Core Specification and OpenUSD’s crateFile.cpp,
crateDataTypes.h and crateValueInliners.h.
Value representation
| Bits | Name | Meaning |
|---|---|---|
| 63 | array | the value is an array |
| 62 | inlined | the value is in the payload itself |
| 61 | compressed | the array is compressed |
| 60 | array edit | the value is an array edit (version 0.14.0) |
| 56–59 | unused | |
| 48–55 | type | the type code, from the table below |
| 0–47 | payload | an inlined value in its low 32 bits, or the offset of the value from the start of the file |
An inlined value cannot be an array or compressed. An array whose payload is 0 is empty. The same value used in many places is written once and shared.
Type codes
“Array” marks the types that may also be arrays.
| Code | Type | Array | Code | Type | Array |
|---|---|---|---|---|---|
| 1 | bool | yes | 31 | dictionary | |
| 2 | uchar | yes | 32 | token list op | |
| 3 | int | yes | 33 | string list op | |
| 4 | uint | yes | 34 | path list op | |
| 5 | int64 | yes | 35 | reference list op | |
| 6 | uint64 | yes | 36 | int list op | |
| 7 | half | yes | 37 | int64 list op | |
| 8 | float | yes | 38 | uint list op | |
| 9 | double | yes | 39 | uint64 list op | |
| 10 | string | yes | 40 | path vector | |
| 11 | token | yes | 41 | token vector | |
| 12 | asset path | yes | 42 | specifier | |
| 13 | matrix2d | yes | 43 | permission | |
| 14 | matrix3d | yes | 44 | variability | |
| 15 | matrix4d | yes | 45 | variant selection map | |
| 16 | quatd | yes | 46 | time samples | |
| 17 | quatf | yes | 47 | payload | |
| 18 | quath | yes | 48 | double vector | |
| 19 | double2 | yes | 49 | layer offset vector | |
| 20 | float2 | yes | 50 | string vector | |
| 21 | half2 | yes | 51 | value block (None) | |
| 22 | int2 | yes | 52 | value: a typed value inside a dictionary | |
| 23 | double3 | yes | 53 | unregistered value | |
| 24 | float3 | yes | 54 | unregistered value list op | |
| 25 | half3 | yes | 55 | payload list op | |
| 26 | int3 | yes | 56 | time code | yes |
| 27 | double4 | yes | 57 | path expression | yes |
| 28 | float4 | yes | 58 | relocates | |
| 29 | half4 | yes | 59 | spline | |
| 30 | int4 | yes | 60 | animation block (OpenUSD, newer than the specification) |
Code 0 is invalid. Role types such as point3f or color3f
are stored as their plain type (float3); the role is a separate field.
Inlined values
| Type | Payload |
|---|---|
| bool, uchar, int, uint, half, float, specifier, permission, variability | always inlined: the value’s bytes in the low 32 bits |
| string | always inlined: an index into the STRINGS section |
| token, asset path | always inlined: a token index |
| int64, uint64 | inlined when the value fits in 32 bits |
| double | inlined as a float when the float is exactly equal |
| vectors (2, 3, 4 components) | inlined when every component is a whole number from −128 to 127: one signed byte per component |
| matrices | inlined when every off-diagonal entry is 0 and every diagonal entry is a whole number from −128 to 127: the diagonal, one signed byte each |
| dictionary | inlined when empty, as 0 |
Specifier values are 0 def, 1 over, 2
class; permission 0 public, 1 private; variability 0 varying,
1 uniform (an old value 2 is read as uniform).
Arrays
An array’s payload is the offset of its data, which starts on an 8-byte boundary: the element count (u64 from version 0.7.0, u32 before), then the elements. Files before 0.5.0 have a u32 rank, always 1, in front of the count.
Arrays of 16 or more elements may be compressed, and the compressed bit is then set. After the count:
| Element type | From | Compressed form |
|---|---|---|
| int, uint, int64, uint64 | 0.5.0 | the compressed integer form: u64 compressed size, LZ4 block |
| half, float, double | 0.6.0 | one code byte: i when every value is a whole number that fits in int32, then those integers compressed as above; t for a lookup table, then a u32 table size, the distinct values in the array’s element type, and the compressed u32 index of each element into the table |
A writer uses a table only when it has at most a quarter as many entries as the array, and at most 1,024.
Structured values
| Type | Stored as |
|---|---|
| vector types (path, token, double, string, layer offset vectors) | u64 count, then the items: indices for paths, tokens and strings |
| list ops | one header byte, then each list it says is present, as a vector |
| dictionary | u64 entry count, then per entry the key as a string index and the value as an i64 forward offset followed by the value’s own representation |
| time samples | a value representation of the times (a double vector), a u64 count, then one value representation per sample |
| variant selection map | a map of variant set names to selected variants, as strings |
The list op header bits:
| Bit | Meaning |
|---|---|
| 0x01 | explicit: the list replaces weaker ones |
| 0x02 | has explicit items |
| 0x04 | has added items (legacy) |
| 0x08 | has deleted items |
| 0x10 | has ordered items (legacy) |
| 0x20 | has prepended items |
| 0x40 | has appended items |
The present lists follow in this order: explicit, added, prepended, appended, deleted, ordered.