def UNORM(ld: LogicalData) -> int: """ Representation code 16, Unsigned 2-byte integer. [RP66V1 Appendix B Section B.16] """ ret = ld.read() ret <<= 8 ret |= ld.read() return ret
def __init__(self, ld: LogicalData, template: Template): component_descriptor = ComponentDescriptor(ld.read()) if not component_descriptor.is_object: raise ExceptionEFLRObject( f'Component Descriptor does not represent a object but a {component_descriptor.type}.' ) self.name: RepCode.ObjectName = RepCode.OBNAME(ld) self.attrs: typing.List[typing.Union[AttributeBase, None]] = [] self.attr_label_map: typing.Dict[bytes, int] = {} index: int = 0 while True: component_descriptor = ComponentDescriptor(ld.read()) if not component_descriptor.is_attribute_group: raise ExceptionEFLRObject( f'Component Descriptor does not represent a attribute but a {component_descriptor.type}.' ) if template[index].component_descriptor.is_invariant_attribute: self.attrs.append(template[index]) elif template[index].component_descriptor.is_absent_attribute: self.attrs.append(None) else: # TODO: Check the attribute label is the same as the template. Reference [RP66V1 Section 4.5] self.attrs.append( Attribute(component_descriptor, ld, template[index])) if ld.remain == 0 or ComponentDescriptor(ld.peek()).is_object: break # next_component_descriptor = ComponentDescriptor(ld.peek()) # if next_component_descriptor.is_object: # break index += 1 while len(self.attrs) < len(template): self.attrs.append(template[len(self.attrs)]) if len(template) != len(self.attrs): raise ExceptionEFLRObject( f'Template specifies {len(template)} attributes but Logical Data has {len(self.attrs)}' ) # Now populate self.attr_label_map for a, attr in enumerate(self.attrs): if attr is None: label = template.attrs[a].label else: label = attr.label # TODO: Assert that the attribute label is the same as the template. Reference [RP66V1 Section 4.5] if label in self.attr_label_map: raise ExceptionEFLRObjectDuplicateLabel( f'Duplicate Attribute label {label}') self.attr_label_map[label] = a
def SSHORT(ld: LogicalData) -> int: """ SSHORT Representation code 12, Signed 1-byte integer. [RP66V1 Appendix B Section B.12] """ r = ld.read() if r > 127: r -= 256 return r
def __init__(self, ld: LogicalData): ld_index = ld.index component_descriptor = ComponentDescriptor(ld.read()) if not component_descriptor.is_set_group: raise ExceptionEFLRSet(f'Component Descriptor does not represent a set but a {component_descriptor.type}.') self.type: bytes = RepCode.IDENT(ld) self.name: bytes = ComponentDescriptor.CHARACTERISTICS_AND_COMPONENT_FORMAT_SET_MAP['N'].global_default if component_descriptor.has_set_N: self.name = RepCode.IDENT(ld) self.logical_data_consumed = ld.index - ld_index
def __init__(self, ld: LogicalData): # TODO: Check ranges self.year: int = USHORT(ld) + 1900 v: int = ld.read() self.tz: int = (v >> 4) & 0xf self.month: int = v & 0xf self.day: int = USHORT(ld) self.hour: int = USHORT(ld) self.minute: int = USHORT(ld) self.second: int = USHORT(ld) self.millisecond: int = UNORM(ld)
def UVARI(ld: LogicalData) -> int: """ Representation code 18, Variable-length unsigned integer. [RP66V1 Appendix B Section B.18] """ value: int = ld.read() if value & 0xc0 == 0x80: # Two bytes value &= 0x7f value <<= 8 value |= ld.read() # TODO: Raise if < 2**7 elif value & 0xc0 == 0xc0: # Four bytes value &= 0x3f value <<= 8 value |= ld.read() value <<= 8 value |= ld.read() value <<= 8 value |= ld.read() # TODO: Raise if < 2**14 return value
def read(self, ld: LogicalData): """Populate the template with the Logical Data.""" while True: component_descriptor = ComponentDescriptor(ld.read()) if not component_descriptor.is_attribute_group: raise ExceptionEFLRTemplate( f'Component Descriptor does not represent a attribute but a {component_descriptor.type}.' ) template_attribute = TemplateAttribute(component_descriptor, ld) if template_attribute.label in self.attr_label_map: raise ExceptionEFLRTemplateDuplicateLabel(f'Duplicate template label {template_attribute.label}') self.attr_label_map[template_attribute.label] = len(self.attrs) self.attrs.append(template_attribute) if ld.remain == 0: # This is kind of unusual, it is an EFLR with a template but no objects. break next_component_descriptor = ComponentDescriptor(ld.peek()) if next_component_descriptor.is_object: break
def USHORT(ld: LogicalData) -> int: """ USHORT Representation code 15, Unsigned 1-byte integer. [RP66V1 Appendix B Section B.15] """ return ld.read()
def _pascal_string(ld: LogicalData) -> bytes: """Reads a Pascal like string from the LogicalData.""" siz: int = ld.read() return ld.chunk(siz)