57 lines
1.5 KiB
Python
57 lines
1.5 KiB
Python
import enum
|
|
from destruct import Struct
|
|
|
|
|
|
def pad_to(v, n):
|
|
return (n - (v % n)) % n
|
|
|
|
def align_to(v, n):
|
|
return v + pad_to(v, n)
|
|
|
|
|
|
class IndexEntryFlag(enum.IntFlag):
|
|
HasSubNode = 1
|
|
Last = 2
|
|
|
|
class IndexEntry(Struct, generics=['G']):
|
|
file_reference = UInt(64)
|
|
length = UInt(16)
|
|
data_length = UInt(16)
|
|
flags = Enum(IndexEntryFlag, UInt(8))
|
|
_pad13 = Pad(3)
|
|
data = Switch(options={
|
|
True: Capped(G, exact=True),
|
|
False: Nothing
|
|
})
|
|
_dalign = Data()
|
|
sub_node_vcn = Switch(options={
|
|
True: UInt(64),
|
|
False: Nothing
|
|
})
|
|
|
|
def on_flags(self, spec, context):
|
|
spec.data.selector = not bool(self.flags & IndexEntryFlag.Last)
|
|
spec.sub_node_vcn.selector = bool(self.flags & IndexEntryFlag.HasSubNode)
|
|
|
|
spec._dalign.length = self.length - 16
|
|
if spec.data.selector:
|
|
spec.data.current.limit = self.data_length
|
|
spec._dalign.length -= align_to(self.data_length, 8)
|
|
if spec.sub_node_vcn.selector:
|
|
spec._dalign.length -= 8
|
|
|
|
class IndexNode(Struct, generics=['G']):
|
|
entry_offset = UInt(32)
|
|
entry_size = UInt(32)
|
|
node_size = UInt(32)
|
|
has_children = Bool()
|
|
_pad13 = Pad(3)
|
|
entries = Capped(Arr(IndexEntry[G]))
|
|
|
|
def on_entry_size(self, spec, context):
|
|
spec.entries.limit = self.entry_size - 40 # 16
|
|
|
|
def parse(self, input, context):
|
|
value = super().parse(input, context)
|
|
return value.entries
|