import enum from destruct import Struct from .util import MultiEnum from .common import CLIToken, CLITableType class CILFormat(enum.Enum): Tiny = 2 Extended = 3 class CILFlags(enum.Flag): MoreSections = 0x8 InitLocals = 0x10 class CILAttributes(MultiEnum): format = (CILFormat, 0b0011) flags = (CILFlags, 0x0FF0 | 0b1100) header_size = (int, 0xF000, 12) class CILTinyHeader(Struct, nocopy=True): attribs = Static(CILAttributes(CILFormat.Tiny.value)) stack_size = Static(0) code_size = Process(UInt(8), lambda v: v >> 2) vars = Static(None) code = Data() def on_attribs(self, spec, context): self.attribs.header_size = 1 def on_code_size(self, spec, context): spec.code.length = self.code_size class CILExtendedHeader(Struct, nocopy=True): attribs = Enum(CILAttributes, UInt(16)) stack_size = UInt(16) code_size = UInt(32) vars = CLIToken _pad = Data() code = Data() def on_attribs(self, spec, context): self.attribs.header_size *= 4 spec._pad.length = self.attribs.header_size - 12 def on_code_size(self, spec, context): spec.code.length = self.code_size def determine_header(b): format = CILFormat(b[0] & 0b11) if format == CILFormat.Tiny: return CILTinyHeader else: return CILExtendedHeader