diff --git a/doc/python-generated-code-guide.rst b/doc/python-generated-code-guide.rst index 39a40e9c..98553f2d 100644 --- a/doc/python-generated-code-guide.rst +++ b/doc/python-generated-code-guide.rst @@ -144,3 +144,24 @@ generated during serialization. | c: TestStruct if c_c = 1, | c: Optional[TestStruct] = field(kw_only=True, | | | default=None) | +---------------------------------------+---------------------------------------------------------------+ + +Runtime error reporting +----------------------- + +Decoding and encoding errors are reported with ``DecodeError`` and ``EncodeError`` exception +variants. The following is an exhaustive list of error conditions and the reported exception. + +Decoding errors +^^^^^^^^^^^^^^^ + +* ``DecodeError`` Parent class for all decoding exceptions. +* ``EnumValueError`` The decoded value for an enum field does not match any of the declared enum tags or tag ranges. +* ``FixedValueError`` The decoded value for a fixed scalar or enum field does not match the expected value. +* ``ConstraintValueError`` The decoded value for a scalar or enum field does not match the constraint value. +* ``LengthError`` Field decoding triggers an overflow on the input bytes. +* ``ArraySizeError`` The decoded size of an array is not a multiple of the known element size. +* ``TrailingBytesError`` Input bytes remain after decoding the entire packet. + +Encoding errors +^^^^^^^^^^^^^^^ + diff --git a/pdl-compiler/src/backends/python.rs b/pdl-compiler/src/backends/python.rs index c368624e..7a80eb5c 100644 --- a/pdl-compiler/src/backends/python.rs +++ b/pdl-compiler/src/backends/python.rs @@ -16,6 +16,22 @@ use crate::{analyzer, ast}; +#[derive(Default)] +struct CodeBlock { + pub lines: Vec, +} + +impl CodeBlock { + fn append(&mut self, code: String) { + let code = code.trim_start_matches('\n'); + self.lines.extend(code.trim_end().lines().map(String::from)); + } + + fn is_empty(&self) -> bool { + self.lines.is_empty() + } +} + fn indent(s: &str, level: usize) -> String { let prefix = " ".repeat(level); s.lines() @@ -43,6 +59,61 @@ from typing import Optional, List, Tuple, Union import enum import inspect + +class DecodeError(Exception): + pass + + +class EnumValueError(DecodeError): + def __init__(self, packet_name: str, field_name: str, enum_name: str, value: int): + self.packet_name = packet_name + self.field_name = field_name + self.enum_name = enum_name + self.value = value + super().__init__(f"invalid {packet_name}.{field_name} value: {value} is not a valid {enum_name} value") + + +class FixedValueError(DecodeError): + def __init__(self, packet_name: str, expected_value: int, actual_value: int): + self.packet_name = packet_name + self.expected_value = expected_value + self.actual_value = actual_value + super().__init__(f"invalid {packet_name} fixed value: expected {expected_value}, got {actual_value}") + + +class ConstraintValueError(DecodeError): + def __init__(self, packet_name: str, field_name: int, expected_value: int, actual_value: int): + self.packet_name = packet_name + self.field_name = field_name + self.expected_value = expected_value + self.actual_value = actual_value + super().__init__(f"invalid {packet_name}.{field_name} value: expected {expected_value}, got {actual_value}") + + +class LengthError(DecodeError): + def __init__(self, packet_name: str, expected_size: int, actual_size: int): + self.packet_name = packet_name + self.expected_size = expected_size + self.actual_size = actual_size + super().__init__(f"invalid {packet_name} input size: expected {expected_size}, got {actual_size}") + + +class ArraySizeError(DecodeError): + def __init__(self, packet_name: str, field_name: int, array_size: int, element_size: int): + self.packet_name = packet_name + self.field_name = field_name + self.array_size = array_size + self.element_size = element_size + super().__init__(f"invalid {packet_name}.{field_name} size: {array_size} is not a multiple of the element size {element_size}") + + +class TrailingBytesError(DecodeError): + def __init__(self, packet_name: str, trailing_size: int): + self.packet_name = packet_name + self.trailing_size = trailing_size + super().__init__(f"unexpected {packet_name} parsing remainder of size {trailing_size}") + + @dataclass class Packet: payload: Optional[bytes] = field(repr=False, default_factory=bytes, compare=False) @@ -51,7 +122,7 @@ class Packet: def parse_all(cls, span: bytes) -> 'Packet': packet, remain = getattr(cls, 'parse')(span) if len(remain) > 0: - raise Exception('Unexpected parsing remainder') + raise TrailingBytesError(cls.__name__, len(remain)) return packet @property @@ -228,7 +299,7 @@ fn generate_enum_declaration(id: &str, tags: &[ast::Tag], _width: usize) -> Stri unknown_handler.push(" return v".to_string()); } } - unknown_handler.push("raise ValueError('Invalid enum value')".to_string()); + unknown_handler.push(format!(r#"raise EnumValueError("", "", "{id}", v)"#)); } format!( @@ -570,29 +641,31 @@ fn generate_packet_parser<'a>( file: &ast::File, decl: &ast::Decl, ) -> Vec { - let mut validation = Vec::new(); - let mut conds = Vec::new(); + let mut code = if scope.get_parent(decl).is_none() { + vec!["fields = {'payload': None}".to_string()] + } else { + vec![] + }; + + let packet_name = decl.id().unwrap(); for c in scope.iter_constraints(decl) { match c { ast::Constraint { id, value: Some(v), .. } => { - conds.push(format!("fields['{id}'] != {v}")); + code.push(format!("if fields['{id}'] != {v}:")); + code.push(format!(r#" raise ConstraintValueError("{packet_name}", "{id}", {v}, fields['{id}'])"#)); } ast::Constraint { id, tag_id: Some(tag_id), .. } => { let field = scope.iter_fields(decl).find(|f| f.id() == Some(&c.id)).unwrap(); if let ast::FieldDesc::Typedef { type_id, .. } = &field.desc { - conds.push(format!("fields['{id}'] != {type_id}.{tag_id}")); + code.push(format!("if fields['{id}'] != {type_id}.{tag_id}:")); + code.push(format!(r#" raise ConstraintValueError("{packet_name}", "{id}", int({type_id}.{tag_id}), int(fields['{id}']))"#)); } } _ => unreachable!(), } } - if !conds.is_empty() { - validation.push(format!("if {}:", conds.join(" or "))); - validation.push(" raise Exception(\"Invalid constraint field values\")".to_string()); - } - // Parse fields iteratively. let mut parser = FieldParser::new(scope, schema, file, decl); for field in decl.fields() { @@ -604,30 +677,24 @@ fn generate_packet_parser<'a>( let children = get_specialized_children(file, decl); let mut specialization = Vec::new(); for child in children { + let child_name = child.id().unwrap(); // Try parsing every child packet successively until one is // successfully parsed. Return a parsing error if none is valid. // Return parent packet if no child packet matches. // TODO: order child packets by decreasing size in case no constraint // is given for specialization. specialization.push("try:".to_string()); - specialization.push(format!( - " child, remainder = {}.parse(fields.copy(), payload)", - child.id().unwrap() - )); + specialization + .push(format!(" child, remainder = {child_name}.parse(fields.copy(), payload)")); specialization.push(" if remainder:".to_string()); - specialization.push(" raise Exception('Unexpected parsing remainder')".to_string()); + specialization + .push(format!(r#" raise TrailingBytesError("{child_name}", len(remainder))"#)); specialization.push(" return child, span".to_string()); specialization.push("except Exception:".to_string()); specialization.push(" pass".to_string()); } - let mut code = if scope.get_parent(decl).is_none() { - vec!["fields = {'payload': None}".to_string()] - } else { - vec![] - }; - code.extend(validation); - code.extend(parser.code); + code.extend(parser.code.lines); code.extend(specialization); code.push(format!("return {}(**fields), span", decl.id().unwrap())); code @@ -641,8 +708,8 @@ struct FieldParser<'a> { offset: usize, shift: usize, chunk: Vec<(usize, usize, &'a ast::Field)>, - unchecked_code: Vec, - code: Vec, + unchecked_code: CodeBlock, + code: CodeBlock, } impl<'a> FieldParser<'a> { @@ -660,38 +727,41 @@ impl<'a> FieldParser<'a> { offset: 0, shift: 0, chunk: Vec::new(), - unchecked_code: Vec::new(), - code: Vec::new(), + unchecked_code: CodeBlock::default(), + code: CodeBlock::default(), } } - fn unchecked_append(&mut self, line: String) { - self.unchecked_code.push(line); + fn unchecked_append(&mut self, code: String) { + self.unchecked_code.append(code); } fn do_append(&mut self, code: String) { - for line in code.split('\n') { - self.code.push(line.to_string()); - } + self.code.append(code) } fn append(&mut self, code: String) { self.check_code(); - self.do_append(code); + self.code.append(code); } fn check_size(&mut self, size: String) { - self.do_append(format!("if len(span) < {}:", size)); - self.do_append(" raise Exception('Invalid packet size')".to_string()); + let packet_name = self.decl.id().unwrap(); + self.code.append(format!( + r#" +if len(span) < {size}: + raise LengthError("{packet_name}", {size}, len(span)) + "# + )); } fn check_code(&mut self) { if !self.unchecked_code.is_empty() { assert!(self.chunk.is_empty()); - let unchecked_code = std::mem::take(&mut self.unchecked_code); + let unchecked_code = std::mem::take(&mut self.unchecked_code.lines); let offset = self.offset; self.check_size(offset.to_string()); - self.code.extend(unchecked_code); + self.code.lines.extend(unchecked_code); } } @@ -699,7 +769,7 @@ impl<'a> FieldParser<'a> { if self.offset > 0 { self.check_code(); let offset = self.offset; - self.do_append(format!("span = span[{}:]", offset - keep)); + self.code.append(format!("span = span[{}:]", offset - keep)); self.offset = 0; } } @@ -737,7 +807,9 @@ impl<'a> FieldParser<'a> { "value_".to_string() }; + let packet_name = self.decl.id().unwrap(); let chunk = std::mem::take(&mut self.chunk); + for (shift, width, field) in chunk { let v = if shift == 0 && width == self.shift { value.clone() @@ -750,35 +822,36 @@ impl<'a> FieldParser<'a> { self.unchecked_append(format!("fields['{}'] = {}", id, v)); } ast::FieldDesc::FixedScalar { value, .. } => { - self.unchecked_append(format!("if {} != {:#x}:", v, value)); - self.unchecked_append( - " raise Exception('Unexpected fixed field value')".to_string(), - ); + self.unchecked_append(format!( + r#" +if {v} != {value:#x}: + raise FixedValueError("{packet_name}", {v}, {value}) + "# + )); } ast::FieldDesc::FixedEnum { enum_id, tag_id, .. } => { - self.unchecked_append(format!("if {} != {}.{}:", v, enum_id, tag_id)); - self.unchecked_append( - " raise Exception('Unexpected fixed field value')".to_string(), - ); - } - ast::FieldDesc::Typedef { id, type_id, .. } => { self.unchecked_append(format!( - "fields['{}'] = {}.from_int({})", - id, type_id, v + r#" +if {v} != {enum_id}.{tag_id}: + raise FixedValueError("{packet_name}", {v}, int({enum_id}.{tag_id})) + "# )); } + ast::FieldDesc::Typedef { id, type_id, .. } => { + self.unchecked_append(format!("fields['{id}'] = {type_id}.from_int({v})")); + } ast::FieldDesc::Size { field_id, .. } => { - self.unchecked_append(format!("{}_size = {}", field_id, v)); + self.unchecked_append(format!("{field_id}_size = {v}")); } ast::FieldDesc::Count { field_id, .. } => { - self.unchecked_append(format!("{}_count = {}", field_id, v)); + self.unchecked_append(format!("{field_id}_count = {v}")); } ast::FieldDesc::ElementSize { .. } => { todo!() } ast::FieldDesc::Reserved { .. } => {} ast::FieldDesc::Flag { id, .. } => { - self.unchecked_append(format!("{} = {}", id, v)); + self.unchecked_append(format!("{id} = {v}")); } _ => unreachable!(), } @@ -797,6 +870,7 @@ impl<'a> FieldParser<'a> { let value_size = self.schema.field_size(value_field.key).static_().unwrap() / 8; + let packet_name = self.decl.id().unwrap(); let mut offset_from_start: isize = -1; let mut offset_from_end: isize = -1; let mut found_start = false; @@ -854,61 +928,60 @@ impl<'a> FieldParser<'a> { if offset_from_start != -1 { let offset_bytes = offset_from_start / 8; + let start_offset = offset_bytes + value_size as isize; + self.unchecked_append(format!( - "if len(span) < {}:", - offset_bytes + value_size as isize + r#" +if len(span) < {start_offset}: + raise LengthError("{packet_name}", {start_offset}, len(span)) + "# )); - self.unchecked_append(" raise Exception('Invalid packet size')".to_string()); + let value = if value_size > 1 { format!( - "int.from_bytes(span[{}:{}], byteorder='{}')", - offset_bytes, - offset_bytes + value_size as isize, - byteorder + "int.from_bytes(span[{offset_bytes}:{start_offset}], byteorder='{byteorder}')" ) } else { - format!("span[{}]", offset_bytes) + format!("span[{offset_bytes}]") }; - self.unchecked_append(format!("{} = {}", id, value)); - self.unchecked_append(format!("fields['{}'] = {}", id, id)); - self.unchecked_append(format!( - "computed_{} = {}(span[:{}])", - id, function, offset_bytes - )); - self.unchecked_append(format!("if computed_{} != {}:", id, id)); + self.unchecked_append(format!( - " raise Exception(f'Invalid checksum computation: {{computed_{}}} != {{{}}}')", - id, id + r#" +{id} = {value} +fields['{id}'] = {id} +computed_{id} = {function}(span[:{offset_bytes}]) +if computed_{id} != {id}: + raise Exception(f'Invalid checksum computation: {{computed_{id}}} != {{{id}}}') + "#, )); } else if offset_from_end != -1 { let offset_bytes = offset_from_end / 8; + let end_offset = offset_bytes + value_size as isize; + self.unchecked_append(format!( - "if len(span) < {}:", - offset_bytes + value_size as isize + r#" +if len(span) < {end_offset}: + raise LengthError("{packet_name}", {end_offset}, len(span)) + "#, )); - self.unchecked_append(" raise Exception('Invalid packet size')".to_string()); + let value = if value_size > 1 { format!( - "int.from_bytes(span[-{}:-{}], byteorder='{}')", - offset_bytes + value_size as isize, + "int.from_bytes(span[-{end_offset}:-{}], byteorder='{byteorder}')", if offset_bytes == 0 { "".to_string() } else { offset_bytes.to_string() }, - byteorder ) } else { - format!("span[-{}]", offset_bytes + value_size as isize) + format!("span[-{end_offset}]") }; - self.unchecked_append(format!("{} = {}", id, value)); - self.unchecked_append(format!("fields['{}'] = {}", id, id)); - self.unchecked_append(format!( - "computed_{} = {}(span[:-{}])", - id, - function, - offset_bytes + value_size as isize - )); - self.unchecked_append(format!("if computed_{} != {}:", id, id)); + self.unchecked_append(format!( - " raise Exception(f'Invalid checksum computation: {{computed_{}}} != {{{}}}')", - id, id + r#" +{id} = {value} +fields['{id}'] = {id} +computed_{id} = {function}(span[:-{end_offset}]) +if computed_{id} != {id}: + raise Exception(f'Invalid checksum computation: {{computed_{id}}} != {{{id}}}') + "# )); } } @@ -925,27 +998,32 @@ impl<'a> FieldParser<'a> { match self.schema.field_size(field.key) { analyzer::Size::Static(w) => { let size = w / 8; + let start_offset = self.offset; let end_offset = self.offset + size; let type_decl = self.scope.typedef.get(type_id.as_str()).unwrap(); if matches!(type_decl.desc, ast::DeclDesc::Checksum { .. }) { // Handled by parse_checksum_start. } else { self.unchecked_append(format!( - "fields['{}'] = {}.parse_all(span[{}:{}])", - id, type_id, self.offset, end_offset + "fields['{id}'] = {type_id}.parse_all(span[{start_offset}:{end_offset}])", )); } self.offset = end_offset; } _ => { self.consume_span(0); - self.append(format!("{}, span = {}.parse(span)", id, type_id)); - self.append(format!("fields['{}'] = {}", id, id)); + self.append(format!( + r#" +{id}, span = {type_id}.parse(span) +fields['{id}'] = {id} + "# + )); } } } fn parse_payload_field(&mut self, field: &'a ast::Field) { + let packet_name = self.decl.id().unwrap(); self.consume_span(0); let id = match &field.desc { ast::FieldDesc::Payload { .. } => "_payload_", @@ -962,10 +1040,14 @@ impl<'a> FieldParser<'a> { if let ast::FieldDesc::Payload { size_modifier: Some(modifier), .. } = &field.desc { self.append(format!("{}_size -= {}", id, modifier)); } - self.append(format!("if len(span) < {}_size:", id)); - self.append(" raise Exception('Invalid packet size')".to_string()); - self.append(format!("payload = span[:{}_size]", id)); - self.append(format!("span = span[{}_size:]", id)); + self.append(format!( + r#" +if len(span) < {id}_size: + raise LengthError("{packet_name}", {id}_size, len(span)) +payload = span[:{id}_size] +span = span[{id}_size:] + "# + )); } else { let mut offset_from_end = 0; let mut found = false; @@ -982,14 +1064,23 @@ impl<'a> FieldParser<'a> { } if offset_from_end == 0 { - self.append("payload = span".to_string()); - self.append("span = bytes([])".to_string()); + self.append( + r#" +payload = span +span = bytes([]) + "# + .to_string(), + ); } else { let offset_bytes = offset_from_end / 8; - self.append(format!("if len(span) < {}:", offset_bytes)); - self.append(" raise Exception('Invalid packet size')".to_string()); - self.append(format!("payload = span[:-{}]", offset_bytes)); - self.append(format!("span = span[-{}:]", offset_bytes)); + self.append(format!( + r#" +if len(span) < {offset_bytes}: + raise LengthError("{packet_name}", {offset_bytes}, len(span)) +payload = span[:-{offset_bytes}] +span = span[-{offset_bytes}:] + "# + )); } } self.append("fields['payload'] = payload".to_string()); @@ -1003,6 +1094,7 @@ impl<'a> FieldParser<'a> { let element_size = analyzer::element_size(self.scope, self.schema, self.decl, field); let array_size = analyzer::array_size(self.decl, field); let padded_size = self.schema.padded_size(field.key); + let packet_name = self.decl.id().unwrap(); // Shift the span to reset the offset to 0. self.consume_span(0); @@ -1072,8 +1164,7 @@ impl<'a> FieldParser<'a> { self.check_size(format!("{id}_size")); self.append(format!("if {id}_size % {element_size} != 0:")); self.append( - " raise Exception('Array size is not a multiple of the element size')" - .to_string(), + format!(r#" raise ArraySizeError("{packet_name}", "{id}", {id}_size, {element_size})"#) ); self.append(format!("{id}_count = int({id}_size / {element_size})")); self.append(format!("{id} = []")); @@ -1101,8 +1192,7 @@ impl<'a> FieldParser<'a> { (ElementSize::Static(element_size), ArraySize::Unknown) => { self.append(format!("if len(span) % {element_size} != 0:")); self.append( - " raise Exception('Array size is not a multiple of the element size')" - .to_string(), + format!(r#" raise ArraySizeError("{packet_name}", "{id}", len(span), {element_size})"#) ); self.append(format!("{id}_count = int(len(span) / {element_size})")); self.append(format!("{id} = []")); @@ -1195,6 +1285,7 @@ impl<'a> FieldParser<'a> { self.consume_span(0); let cond = field.cond.as_ref().unwrap(); let id = field.id().unwrap(); + let packet_name = self.decl.id().unwrap(); let byteorder = match self.file.endianness.value { ast::EndiannessValue::LittleEndian => "little", ast::EndiannessValue::BigEndian => "big", @@ -1204,7 +1295,10 @@ impl<'a> FieldParser<'a> { ast::FieldDesc::Scalar { width, .. } => { self.append(format!("if {} == {}:", cond.id, cond.value.unwrap())); self.append(format!(" if len(span) < {}:", width / 8)); - self.append(" raise Exception('Invalid packet size')".to_string()); + self.append(format!( + r#" raise LengthError("{packet_name}", {}, len(span))"#, + width / 8 + )); self.append(format!( " fields['{}'] = int.from_bytes(span[:{}], byteorder='{}')", id, @@ -1219,7 +1313,10 @@ impl<'a> FieldParser<'a> { ast::DeclDesc::Enum { width, .. } => { self.append(format!("if {} == {}:", cond.id, cond.value.unwrap())); self.append(format!(" if len(span) < {}:", width / 8)); - self.append(" raise Exception('Invalid packet size')".to_string()); + self.append(format!( + r#" raise LengthError("{packet_name}", {}, len(span))"#, + width / 8 + )); self.append(format!( " fields['{}'] = {}(int.from_bytes(span[:{}], byteorder='{}'))", id, diff --git a/pdl-compiler/tests/generated/python/le_backend.py b/pdl-compiler/tests/generated/python/le_backend.py index 5b7d75af..c4f8be6c 100644 --- a/pdl-compiler/tests/generated/python/le_backend.py +++ b/pdl-compiler/tests/generated/python/le_backend.py @@ -8,6 +8,61 @@ import enum import inspect + +class DecodeError(Exception): + pass + + +class EnumValueError(DecodeError): + def __init__(self, packet_name: str, field_name: str, enum_name: str, value: int): + self.packet_name = packet_name + self.field_name = field_name + self.enum_name = enum_name + self.value = value + super().__init__(f"invalid {packet_name}.{field_name} value: {value} is not a valid {enum_name} value") + + +class FixedValueError(DecodeError): + def __init__(self, packet_name: str, expected_value: int, actual_value: int): + self.packet_name = packet_name + self.expected_value = expected_value + self.actual_value = actual_value + super().__init__(f"invalid {packet_name} fixed value: expected {expected_value}, got {actual_value}") + + +class ConstraintValueError(DecodeError): + def __init__(self, packet_name: str, field_name: int, expected_value: int, actual_value: int): + self.packet_name = packet_name + self.field_name = field_name + self.expected_value = expected_value + self.actual_value = actual_value + super().__init__(f"invalid {packet_name}.{field_name} value: expected {expected_value}, got {actual_value}") + + +class LengthError(DecodeError): + def __init__(self, packet_name: str, expected_size: int, actual_size: int): + self.packet_name = packet_name + self.expected_size = expected_size + self.actual_size = actual_size + super().__init__(f"invalid {packet_name} input size: expected {expected_size}, got {actual_size}") + + +class ArraySizeError(DecodeError): + def __init__(self, packet_name: str, field_name: int, array_size: int, element_size: int): + self.packet_name = packet_name + self.field_name = field_name + self.array_size = array_size + self.element_size = element_size + super().__init__(f"invalid {packet_name}.{field_name} size: {array_size} is not a multiple of the element size {element_size}") + + +class TrailingBytesError(DecodeError): + def __init__(self, packet_name: str, trailing_size: int): + self.packet_name = packet_name + self.trailing_size = trailing_size + super().__init__(f"unexpected {packet_name} parsing remainder of size {trailing_size}") + + @dataclass class Packet: payload: Optional[bytes] = field(repr=False, default_factory=bytes, compare=False) @@ -16,7 +71,7 @@ class Packet: def parse_all(cls, span: bytes) -> 'Packet': packet, remain = getattr(cls, 'parse')(span) if len(remain) > 0: - raise Exception('Unexpected parsing remainder') + raise TrailingBytesError(cls.__name__, len(remain)) return packet @property @@ -103,7 +158,7 @@ def from_int(v: int) -> Union[int, 'Enum7']: try: return Enum7(v) except ValueError: - raise ValueError('Invalid enum value') + raise EnumValueError("", "", "Enum7", v) class Enum16(enum.IntEnum): A = 0xaabb @@ -114,7 +169,7 @@ def from_int(v: int) -> Union[int, 'Enum16']: try: return Enum16(v) except ValueError: - raise ValueError('Invalid enum value') + raise EnumValueError("", "", "Enum16", v) @dataclass class SizedStruct(Packet): @@ -127,7 +182,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['SizedStruct', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("SizedStruct", 1, len(span)) fields['a'] = span[0] span = span[1:] return SizedStruct(**fields), span @@ -154,11 +209,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['UnsizedStruct', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("UnsizedStruct", 1, len(span)) array_size = (span[0] >> 0) & 0x3 span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("UnsizedStruct", array_size, len(span)) array = [] for n in range(array_size): array.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -216,40 +271,40 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['ScalarParent', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("ScalarParent", 2, len(span)) fields['a'] = span[0] _payload__size = span[1] span = span[2:] if len(span) < _payload__size: - raise Exception('Invalid packet size') + raise LengthError("ScalarParent", _payload__size, len(span)) payload = span[:_payload__size] span = span[_payload__size:] fields['payload'] = payload try: child, remainder = AliasedChild_A.parse(fields.copy(), payload) if remainder: - raise Exception('Unexpected parsing remainder') + raise TrailingBytesError("AliasedChild_A", len(remainder)) return child, span except Exception: pass try: child, remainder = AliasedChild_B.parse(fields.copy(), payload) if remainder: - raise Exception('Unexpected parsing remainder') + raise TrailingBytesError("AliasedChild_B", len(remainder)) return child, span except Exception: pass try: child, remainder = ScalarChild_A.parse(fields.copy(), payload) if remainder: - raise Exception('Unexpected parsing remainder') + raise TrailingBytesError("ScalarChild_A", len(remainder)) return child, span except Exception: pass try: child, remainder = ScalarChild_B.parse(fields.copy(), payload) if remainder: - raise Exception('Unexpected parsing remainder') + raise TrailingBytesError("ScalarChild_B", len(remainder)) return child, span except Exception: pass @@ -282,27 +337,27 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['EnumParent', bytes]: fields = {'payload': None} if len(span) < 3: - raise Exception('Invalid packet size') + raise LengthError("EnumParent", 3, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') fields['a'] = Enum16.from_int(value_) _payload__size = span[2] span = span[3:] if len(span) < _payload__size: - raise Exception('Invalid packet size') + raise LengthError("EnumParent", _payload__size, len(span)) payload = span[:_payload__size] span = span[_payload__size:] fields['payload'] = payload try: child, remainder = EnumChild_A.parse(fields.copy(), payload) if remainder: - raise Exception('Unexpected parsing remainder') + raise TrailingBytesError("EnumChild_A", len(remainder)) return child, span except Exception: pass try: child, remainder = EnumChild_B.parse(fields.copy(), payload) if remainder: - raise Exception('Unexpected parsing remainder') + raise TrailingBytesError("EnumChild_B", len(remainder)) return child, span except Exception: pass @@ -337,14 +392,14 @@ def parse(fields: dict, span: bytes) -> Tuple['EmptyParent', bytes]: try: child, remainder = AliasedChild_A.parse(fields.copy(), payload) if remainder: - raise Exception('Unexpected parsing remainder') + raise TrailingBytesError("AliasedChild_A", len(remainder)) return child, span except Exception: pass try: child, remainder = AliasedChild_B.parse(fields.copy(), payload) if remainder: - raise Exception('Unexpected parsing remainder') + raise TrailingBytesError("AliasedChild_B", len(remainder)) return child, span except Exception: pass @@ -371,7 +426,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Scalar_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Packet_Scalar_Field", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') fields['a'] = (value_ >> 0) & 0x7f fields['c'] = (value_ >> 7) & 0x1ffffffffffffff @@ -407,7 +462,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Enum_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Packet_Enum_Field", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') fields['a'] = Enum7.from_int((value_ >> 0) & 0x7f) fields['c'] = (value_ >> 7) & 0x1ffffffffffffff @@ -441,7 +496,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Reserved_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Packet_Reserved_Field", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') fields['a'] = (value_ >> 0) & 0x7f fields['c'] = (value_ >> 9) & 0x7fffffffffffff @@ -477,13 +532,13 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Size_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Packet_Size_Field", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') b_size = (value_ >> 0) & 0x7 fields['a'] = (value_ >> 3) & 0x1fffffffffffffff span = span[8:] if len(span) < b_size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Size_Field", b_size, len(span)) b = [] for n in range(b_size): b.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -522,13 +577,13 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Count_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Packet_Count_Field", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') b_count = (value_ >> 0) & 0x7 fields['a'] = (value_ >> 3) & 0x1fffffffffffffff span = span[8:] if len(span) < b_count: - raise Exception('Invalid packet size') + raise LengthError("Packet_Count_Field", b_count, len(span)) b = [] for n in range(b_count): b.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -565,10 +620,10 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_FixedScalar_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Packet_FixedScalar_Field", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') if (value_ >> 0) & 0x7f != 0x7: - raise Exception('Unexpected fixed field value') + raise FixedValueError("Packet_FixedScalar_Field", (value_ >> 0) & 0x7f, 7) fields['b'] = (value_ >> 7) & 0x1ffffffffffffff span = span[8:] return Packet_FixedScalar_Field(**fields), span @@ -599,10 +654,10 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_FixedEnum_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Packet_FixedEnum_Field", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') if (value_ >> 0) & 0x7f != Enum7.A: - raise Exception('Unexpected fixed field value') + raise FixedValueError("Packet_FixedEnum_Field", (value_ >> 0) & 0x7f, int(Enum7.A)) fields['b'] = (value_ >> 7) & 0x1ffffffffffffff span = span[8:] return Packet_FixedEnum_Field(**fields), span @@ -633,11 +688,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Payload_Field_VariableSize', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Payload_Field_VariableSize", 1, len(span)) _payload__size = (span[0] >> 0) & 0x7 span = span[1:] if len(span) < _payload__size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Payload_Field_VariableSize", _payload__size, len(span)) payload = span[:_payload__size] span = span[_payload__size:] fields['payload'] = payload @@ -667,12 +722,12 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Payload_Field_SizeModifier', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Payload_Field_SizeModifier", 1, len(span)) _payload__size = (span[0] >> 0) & 0x7 span = span[1:] _payload__size -= +2 if len(span) < _payload__size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Payload_Field_SizeModifier", _payload__size, len(span)) payload = span[:_payload__size] span = span[_payload__size:] fields['payload'] = payload @@ -702,12 +757,12 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Payload_Field_UnknownSize', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Packet_Payload_Field_UnknownSize", 2, len(span)) payload = span[:-2] span = span[-2:] fields['payload'] = payload if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Packet_Payload_Field_UnknownSize", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') fields['a'] = value_ span = span[2:] @@ -736,7 +791,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Payload_Field_UnknownSize_Terminal', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Packet_Payload_Field_UnknownSize_Terminal", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') fields['a'] = value_ span = span[2:] @@ -768,11 +823,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Body_Field_VariableSize', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Body_Field_VariableSize", 1, len(span)) _body__size = (span[0] >> 0) & 0x7 span = span[1:] if len(span) < _body__size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Body_Field_VariableSize", _body__size, len(span)) payload = span[:_body__size] span = span[_body__size:] fields['payload'] = payload @@ -802,12 +857,12 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Body_Field_UnknownSize', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Packet_Body_Field_UnknownSize", 2, len(span)) payload = span[:-2] span = span[-2:] fields['payload'] = payload if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Packet_Body_Field_UnknownSize", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') fields['a'] = value_ span = span[2:] @@ -836,7 +891,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Body_Field_UnknownSize_Terminal', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Packet_Body_Field_UnknownSize_Terminal", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') fields['a'] = value_ span = span[2:] @@ -868,10 +923,10 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_ScalarGroup_Field', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Packet_ScalarGroup_Field", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') if value_ != 0x2a: - raise Exception('Unexpected fixed field value') + raise FixedValueError("Packet_ScalarGroup_Field", value_, 42) span = span[2:] return Packet_ScalarGroup_Field(**fields), span @@ -895,10 +950,10 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_EnumGroup_Field', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Packet_EnumGroup_Field", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') if value_ != Enum16.A: - raise Exception('Unexpected fixed field value') + raise FixedValueError("Packet_EnumGroup_Field", value_, int(Enum16.A)) span = span[2:] return Packet_EnumGroup_Field(**fields), span @@ -924,9 +979,9 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Checksum_Field_FromStart', bytes]: fields = {'payload': None} if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Packet_Checksum_Field_FromStart", 5, len(span)) if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Packet_Checksum_Field_FromStart", 5, len(span)) crc = span[4] fields['crc'] = crc computed_crc = Checksum(span[:4]) @@ -969,21 +1024,21 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Checksum_Field_FromEnd', bytes]: fields = {'payload': None} if len(span) < 0: - raise Exception('Invalid packet size') + raise LengthError("Packet_Checksum_Field_FromEnd", 0, len(span)) if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Packet_Checksum_Field_FromEnd", 5, len(span)) crc = span[-5] fields['crc'] = crc computed_crc = Checksum(span[:-5]) if computed_crc != crc: raise Exception(f'Invalid checksum computation: {computed_crc} != {crc}') if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Packet_Checksum_Field_FromEnd", 5, len(span)) payload = span[:-5] span = span[-5:] fields['payload'] = payload if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Packet_Checksum_Field_FromEnd", 5, len(span)) value_ = int.from_bytes(span[1:3], byteorder='little') fields['a'] = value_ value_ = int.from_bytes(span[3:5], byteorder='little') @@ -1021,7 +1076,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Struct_Field', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Struct_Field", 1, len(span)) fields['a'] = SizedStruct.parse_all(span[0:1]) span = span[1:] b, span = UnsizedStruct.parse(span) @@ -1049,7 +1104,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Custom_Field_ConstantSize', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Custom_Field_ConstantSize", 1, len(span)) fields['a'] = SizedCustomField.parse_all(span[0:1]) span = span[1:] return Packet_Custom_Field_ConstantSize(**fields), span @@ -1097,7 +1152,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_ByteElement_ConstantSize', bytes]: fields = {'payload': None} if len(span) < 4: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_ByteElement_ConstantSize", 4, len(span)) array = [] for n in range(4): array.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -1125,11 +1180,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_ByteElement_VariableSize', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_ByteElement_VariableSize", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_ByteElement_VariableSize", array_size, len(span)) array = [] for n in range(array_size): array.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -1161,11 +1216,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_ByteElement_VariableCount', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_ByteElement_VariableCount", 1, len(span)) array_count = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_count: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_ByteElement_VariableCount", array_count, len(span)) array = [] for n in range(array_count): array.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -1222,7 +1277,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_ScalarElement_ConstantSize', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_ScalarElement_ConstantSize", 8, len(span)) array = [] for n in range(4): array.append(int.from_bytes(span[n * 2:(n + 1) * 2], byteorder='little')) @@ -1251,13 +1306,13 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_ScalarElement_VariableSize', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_ScalarElement_VariableSize", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_ScalarElement_VariableSize", array_size, len(span)) if array_size % 2 != 0: - raise Exception('Array size is not a multiple of the element size') + raise ArraySizeError("Packet_Array_Field_ScalarElement_VariableSize", "array", array_size, 2) array_count = int(array_size / 2) array = [] for n in range(array_count): @@ -1291,11 +1346,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_ScalarElement_VariableCount', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_ScalarElement_VariableCount", 1, len(span)) array_count = (span[0] >> 0) & 0xf span = span[1:] if len(span) < 2 * array_count: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_ScalarElement_VariableCount", 2 * array_count, len(span)) array = [] for n in range(array_count): array.append(int.from_bytes(span[n * 2:(n + 1) * 2], byteorder='little')) @@ -1327,7 +1382,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_ScalarElement_UnknownSize', bytes]: fields = {'payload': None} if len(span) % 2 != 0: - raise Exception('Array size is not a multiple of the element size') + raise ArraySizeError("Packet_Array_Field_ScalarElement_UnknownSize", "array", len(span), 2) array_count = int(len(span) / 2) array = [] for n in range(array_count): @@ -1357,7 +1412,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_EnumElement_ConstantSize', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_EnumElement_ConstantSize", 8, len(span)) array = [] for n in range(4): array.append(Enum16.from_int(int.from_bytes(span[n * 2:(n + 1) * 2], byteorder='little'))) @@ -1386,13 +1441,13 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_EnumElement_VariableSize', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_EnumElement_VariableSize", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_EnumElement_VariableSize", array_size, len(span)) if array_size % 2 != 0: - raise Exception('Array size is not a multiple of the element size') + raise ArraySizeError("Packet_Array_Field_EnumElement_VariableSize", "array", array_size, 2) array_count = int(array_size / 2) array = [] for n in range(array_count): @@ -1426,11 +1481,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_EnumElement_VariableCount', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_EnumElement_VariableCount", 1, len(span)) array_count = (span[0] >> 0) & 0xf span = span[1:] if len(span) < 2 * array_count: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_EnumElement_VariableCount", 2 * array_count, len(span)) array = [] for n in range(array_count): array.append(Enum16.from_int(int.from_bytes(span[n * 2:(n + 1) * 2], byteorder='little'))) @@ -1462,7 +1517,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_EnumElement_UnknownSize', bytes]: fields = {'payload': None} if len(span) % 2 != 0: - raise Exception('Array size is not a multiple of the element size') + raise ArraySizeError("Packet_Array_Field_EnumElement_UnknownSize", "array", len(span), 2) array_count = int(len(span) / 2) array = [] for n in range(array_count): @@ -1492,7 +1547,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_SizedElement_ConstantSize', bytes]: fields = {'payload': None} if len(span) < 4: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_SizedElement_ConstantSize", 4, len(span)) array = [] for n in range(4): array.append(SizedStruct.parse_all(span[n:n + 1])) @@ -1521,11 +1576,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_SizedElement_VariableSize', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_SizedElement_VariableSize", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_SizedElement_VariableSize", array_size, len(span)) array = [] for n in range(array_size): array.append(SizedStruct.parse_all(span[n:n + 1])) @@ -1558,11 +1613,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_SizedElement_VariableCount', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_SizedElement_VariableCount", 1, len(span)) array_count = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_count: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_SizedElement_VariableCount", array_count, len(span)) array = [] for n in range(array_count): array.append(SizedStruct.parse_all(span[n:n + 1])) @@ -1648,11 +1703,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_UnsizedElement_VariableSize', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_UnsizedElement_VariableSize", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_UnsizedElement_VariableSize", array_size, len(span)) array_span = span[:array_size] array = [] while len(array_span) > 0: @@ -1687,7 +1742,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_UnsizedElement_VariableCount', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_UnsizedElement_VariableCount", 1, len(span)) array_count = (span[0] >> 0) & 0xf span = span[1:] array = [] @@ -1748,12 +1803,12 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_UnsizedElement_SizeModifier', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_UnsizedElement_SizeModifier", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] array_size = array_size - +2 if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_UnsizedElement_SizeModifier", array_size, len(span)) array_span = span[:array_size] array = [] while len(array_span) > 0: @@ -1788,17 +1843,17 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_SizedElement_VariableSize_Padded', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_SizedElement_VariableSize_Padded", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < 16: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_SizedElement_VariableSize_Padded", 16, len(span)) remaining_span = span[16:] span = span[:16] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_SizedElement_VariableSize_Padded", array_size, len(span)) if array_size % 2 != 0: - raise Exception('Array size is not a multiple of the element size') + raise ArraySizeError("Packet_Array_Field_SizedElement_VariableSize_Padded", "array", array_size, 2) array_count = int(array_size / 2) array = [] for n in range(array_count): @@ -1835,11 +1890,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Array_Field_UnsizedElement_VariableCount_Padded', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_UnsizedElement_VariableCount_Padded", 1, len(span)) array_count = span[0] span = span[1:] if len(span) < 16: - raise Exception('Invalid packet size') + raise LengthError("Packet_Array_Field_UnsizedElement_VariableCount_Padded", 16, len(span)) remaining_span = span[16:] span = span[:16] array = [] @@ -1877,18 +1932,18 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Optional_Scalar_Field', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Optional_Scalar_Field", 1, len(span)) c0 = (span[0] >> 0) & 0x1 c1 = (span[0] >> 1) & 0x1 span = span[1:] if c0 == 0: if len(span) < 3: - raise Exception('Invalid packet size') + raise LengthError("Packet_Optional_Scalar_Field", 3, len(span)) fields['a'] = int.from_bytes(span[:3], byteorder='little') span = span[3:] if c1 == 1: if len(span) < 4: - raise Exception('Invalid packet size') + raise LengthError("Packet_Optional_Scalar_Field", 4, len(span)) fields['b'] = int.from_bytes(span[:4], byteorder='little') span = span[4:] return Packet_Optional_Scalar_Field(**fields), span @@ -1925,18 +1980,18 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Optional_Enum_Field', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Optional_Enum_Field", 1, len(span)) c0 = (span[0] >> 0) & 0x1 c1 = (span[0] >> 1) & 0x1 span = span[1:] if c0 == 0: if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Packet_Optional_Enum_Field", 2, len(span)) fields['a'] = Enum16(int.from_bytes(span[:2], byteorder='little')) span = span[2:] if c1 == 1: if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Packet_Optional_Enum_Field", 2, len(span)) fields['b'] = Enum16(int.from_bytes(span[:2], byteorder='little')) span = span[2:] return Packet_Optional_Enum_Field(**fields), span @@ -1973,7 +2028,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Packet_Optional_Struct_Field', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Packet_Optional_Struct_Field", 1, len(span)) c0 = (span[0] >> 0) & 0x1 c1 = (span[0] >> 1) & 0x1 span = span[1:] @@ -2015,9 +2070,9 @@ def __post_init__(self) -> None: @staticmethod def parse(fields: dict, span: bytes) -> Tuple['ScalarChild_A', bytes]: if fields['a'] != 0: - raise Exception("Invalid constraint field values") + raise ConstraintValueError("ScalarChild_A", "a", 0, fields['a']) if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("ScalarChild_A", 1, len(span)) fields['b'] = span[0] span = span[1:] return ScalarChild_A(**fields), span @@ -2043,9 +2098,9 @@ def __post_init__(self) -> None: @staticmethod def parse(fields: dict, span: bytes) -> Tuple['ScalarChild_B', bytes]: if fields['a'] != 1: - raise Exception("Invalid constraint field values") + raise ConstraintValueError("ScalarChild_B", "a", 1, fields['a']) if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("ScalarChild_B", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') fields['c'] = value_ span = span[2:] @@ -2072,9 +2127,9 @@ def __post_init__(self) -> None: @staticmethod def parse(fields: dict, span: bytes) -> Tuple['EnumChild_A', bytes]: if fields['a'] != Enum16.A: - raise Exception("Invalid constraint field values") + raise ConstraintValueError("EnumChild_A", "a", int(Enum16.A), int(fields['a'])) if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("EnumChild_A", 1, len(span)) fields['b'] = span[0] span = span[1:] return EnumChild_A(**fields), span @@ -2100,9 +2155,9 @@ def __post_init__(self) -> None: @staticmethod def parse(fields: dict, span: bytes) -> Tuple['EnumChild_B', bytes]: if fields['a'] != Enum16.B: - raise Exception("Invalid constraint field values") + raise ConstraintValueError("EnumChild_B", "a", int(Enum16.B), int(fields['a'])) if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("EnumChild_B", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') fields['c'] = value_ span = span[2:] @@ -2129,9 +2184,9 @@ def __post_init__(self) -> None: @staticmethod def parse(fields: dict, span: bytes) -> Tuple['AliasedChild_A', bytes]: if fields['a'] != 2: - raise Exception("Invalid constraint field values") + raise ConstraintValueError("AliasedChild_A", "a", 2, fields['a']) if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("AliasedChild_A", 1, len(span)) fields['b'] = span[0] span = span[1:] return AliasedChild_A(**fields), span @@ -2157,9 +2212,9 @@ def __post_init__(self) -> None: @staticmethod def parse(fields: dict, span: bytes) -> Tuple['AliasedChild_B', bytes]: if fields['a'] != 3: - raise Exception("Invalid constraint field values") + raise ConstraintValueError("AliasedChild_B", "a", 3, fields['a']) if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("AliasedChild_B", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') fields['c'] = value_ span = span[2:] @@ -2188,7 +2243,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Scalar_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Scalar_Field", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') fields['a'] = (value_ >> 0) & 0x7f fields['c'] = (value_ >> 7) & 0x1ffffffffffffff @@ -2224,7 +2279,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Enum_Field_', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Enum_Field_", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') fields['a'] = Enum7.from_int((value_ >> 0) & 0x7f) fields['c'] = (value_ >> 7) & 0x1ffffffffffffff @@ -2257,7 +2312,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Enum_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Enum_Field", 8, len(span)) fields['s'] = Struct_Enum_Field_.parse_all(span[0:8]) span = span[8:] return Struct_Enum_Field(**fields), span @@ -2283,7 +2338,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Reserved_Field_', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Reserved_Field_", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') fields['a'] = (value_ >> 0) & 0x7f fields['c'] = (value_ >> 9) & 0x7fffffffffffff @@ -2318,7 +2373,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Reserved_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Reserved_Field", 8, len(span)) fields['s'] = Struct_Reserved_Field_.parse_all(span[0:8]) span = span[8:] return Struct_Reserved_Field(**fields), span @@ -2344,13 +2399,13 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Size_Field_', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Size_Field_", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') b_size = (value_ >> 0) & 0x7 fields['a'] = (value_ >> 3) & 0x1fffffffffffffff span = span[8:] if len(span) < b_size: - raise Exception('Invalid packet size') + raise LengthError("Struct_Size_Field_", b_size, len(span)) b = [] for n in range(b_size): b.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -2412,13 +2467,13 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Count_Field_', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Count_Field_", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') b_count = (value_ >> 0) & 0x7 fields['a'] = (value_ >> 3) & 0x1fffffffffffffff span = span[8:] if len(span) < b_count: - raise Exception('Invalid packet size') + raise LengthError("Struct_Count_Field_", b_count, len(span)) b = [] for n in range(b_count): b.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -2478,10 +2533,10 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_FixedScalar_Field_', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_FixedScalar_Field_", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') if (value_ >> 0) & 0x7f != 0x7: - raise Exception('Unexpected fixed field value') + raise FixedValueError("Struct_FixedScalar_Field_", (value_ >> 0) & 0x7f, 7) fields['b'] = (value_ >> 7) & 0x1ffffffffffffff span = span[8:] return Struct_FixedScalar_Field_(**fields), span @@ -2512,7 +2567,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_FixedScalar_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_FixedScalar_Field", 8, len(span)) fields['s'] = Struct_FixedScalar_Field_.parse_all(span[0:8]) span = span[8:] return Struct_FixedScalar_Field(**fields), span @@ -2537,10 +2592,10 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_FixedEnum_Field_', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_FixedEnum_Field_", 8, len(span)) value_ = int.from_bytes(span[0:8], byteorder='little') if (value_ >> 0) & 0x7f != Enum7.A: - raise Exception('Unexpected fixed field value') + raise FixedValueError("Struct_FixedEnum_Field_", (value_ >> 0) & 0x7f, int(Enum7.A)) fields['b'] = (value_ >> 7) & 0x1ffffffffffffff span = span[8:] return Struct_FixedEnum_Field_(**fields), span @@ -2571,7 +2626,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_FixedEnum_Field', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_FixedEnum_Field", 8, len(span)) fields['s'] = Struct_FixedEnum_Field_.parse_all(span[0:8]) span = span[8:] return Struct_FixedEnum_Field(**fields), span @@ -2596,10 +2651,10 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_ScalarGroup_Field_', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Struct_ScalarGroup_Field_", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') if value_ != 0x2a: - raise Exception('Unexpected fixed field value') + raise FixedValueError("Struct_ScalarGroup_Field_", value_, 42) span = span[2:] return Struct_ScalarGroup_Field_(**fields), span @@ -2623,7 +2678,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_ScalarGroup_Field', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Struct_ScalarGroup_Field", 2, len(span)) fields['s'] = Struct_ScalarGroup_Field_.parse_all(span[0:2]) span = span[2:] return Struct_ScalarGroup_Field(**fields), span @@ -2648,10 +2703,10 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_EnumGroup_Field_', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Struct_EnumGroup_Field_", 2, len(span)) value_ = int.from_bytes(span[0:2], byteorder='little') if value_ != Enum16.A: - raise Exception('Unexpected fixed field value') + raise FixedValueError("Struct_EnumGroup_Field_", value_, int(Enum16.A)) span = span[2:] return Struct_EnumGroup_Field_(**fields), span @@ -2675,7 +2730,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_EnumGroup_Field', bytes]: fields = {'payload': None} if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Struct_EnumGroup_Field", 2, len(span)) fields['s'] = Struct_EnumGroup_Field_.parse_all(span[0:2]) span = span[2:] return Struct_EnumGroup_Field(**fields), span @@ -2702,9 +2757,9 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Checksum_Field_FromStart_', bytes]: fields = {'payload': None} if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Struct_Checksum_Field_FromStart_", 5, len(span)) if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Struct_Checksum_Field_FromStart_", 5, len(span)) crc = span[4] fields['crc'] = crc computed_crc = Checksum(span[:4]) @@ -2745,7 +2800,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Checksum_Field_FromStart', bytes]: fields = {'payload': None} if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Struct_Checksum_Field_FromStart", 5, len(span)) fields['s'] = Struct_Checksum_Field_FromStart_.parse_all(span[0:5]) span = span[5:] return Struct_Checksum_Field_FromStart(**fields), span @@ -2772,21 +2827,21 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Checksum_Field_FromEnd_', bytes]: fields = {'payload': None} if len(span) < 0: - raise Exception('Invalid packet size') + raise LengthError("Struct_Checksum_Field_FromEnd_", 0, len(span)) if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Struct_Checksum_Field_FromEnd_", 5, len(span)) crc = span[-5] fields['crc'] = crc computed_crc = Checksum(span[:-5]) if computed_crc != crc: raise Exception(f'Invalid checksum computation: {computed_crc} != {crc}') if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Struct_Checksum_Field_FromEnd_", 5, len(span)) payload = span[:-5] span = span[-5:] fields['payload'] = payload if len(span) < 5: - raise Exception('Invalid packet size') + raise LengthError("Struct_Checksum_Field_FromEnd_", 5, len(span)) value_ = int.from_bytes(span[1:3], byteorder='little') fields['a'] = value_ value_ = int.from_bytes(span[3:5], byteorder='little') @@ -2847,7 +2902,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Struct_Field', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Struct_Field", 1, len(span)) fields['a'] = SizedStruct.parse_all(span[0:1]) span = span[1:] b, span = UnsizedStruct.parse(span) @@ -2875,7 +2930,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Custom_Field_ConstantSize_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Custom_Field_ConstantSize_", 1, len(span)) fields['a'] = SizedCustomField.parse_all(span[0:1]) span = span[1:] return Struct_Custom_Field_ConstantSize_(**fields), span @@ -2900,7 +2955,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Custom_Field_ConstantSize', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Custom_Field_ConstantSize", 1, len(span)) fields['s'] = Struct_Custom_Field_ConstantSize_.parse_all(span[0:1]) span = span[1:] return Struct_Custom_Field_ConstantSize(**fields), span @@ -2971,7 +3026,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_ByteElement_ConstantSize_', bytes]: fields = {'payload': None} if len(span) < 4: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ByteElement_ConstantSize_", 4, len(span)) array = [] for n in range(4): array.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -2999,7 +3054,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_ByteElement_ConstantSize', bytes]: fields = {'payload': None} if len(span) < 4: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ByteElement_ConstantSize", 4, len(span)) fields['s'] = Struct_Array_Field_ByteElement_ConstantSize_.parse_all(span[0:4]) span = span[4:] return Struct_Array_Field_ByteElement_ConstantSize(**fields), span @@ -3024,11 +3079,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_ByteElement_VariableSize_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ByteElement_VariableSize_", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ByteElement_VariableSize_", array_size, len(span)) array = [] for n in range(array_size): array.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -3083,11 +3138,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_ByteElement_VariableCount_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ByteElement_VariableCount_", 1, len(span)) array_count = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_count: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ByteElement_VariableCount_", array_count, len(span)) array = [] for n in range(array_count): array.append(int.from_bytes(span[n:n + 1], byteorder='little')) @@ -3190,7 +3245,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_ScalarElement_ConstantSize_', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ScalarElement_ConstantSize_", 8, len(span)) array = [] for n in range(4): array.append(int.from_bytes(span[n * 2:(n + 1) * 2], byteorder='little')) @@ -3219,7 +3274,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_ScalarElement_ConstantSize', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ScalarElement_ConstantSize", 8, len(span)) fields['s'] = Struct_Array_Field_ScalarElement_ConstantSize_.parse_all(span[0:8]) span = span[8:] return Struct_Array_Field_ScalarElement_ConstantSize(**fields), span @@ -3244,13 +3299,13 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_ScalarElement_VariableSize_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ScalarElement_VariableSize_", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ScalarElement_VariableSize_", array_size, len(span)) if array_size % 2 != 0: - raise Exception('Array size is not a multiple of the element size') + raise ArraySizeError("Struct_Array_Field_ScalarElement_VariableSize_", "array", array_size, 2) array_count = int(array_size / 2) array = [] for n in range(array_count): @@ -3307,11 +3362,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_ScalarElement_VariableCount_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ScalarElement_VariableCount_", 1, len(span)) array_count = (span[0] >> 0) & 0xf span = span[1:] if len(span) < 2 * array_count: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_ScalarElement_VariableCount_", 2 * array_count, len(span)) array = [] for n in range(array_count): array.append(int.from_bytes(span[n * 2:(n + 1) * 2], byteorder='little')) @@ -3366,7 +3421,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_ScalarElement_UnknownSize_', bytes]: fields = {'payload': None} if len(span) % 2 != 0: - raise Exception('Array size is not a multiple of the element size') + raise ArraySizeError("Struct_Array_Field_ScalarElement_UnknownSize_", "array", len(span), 2) array_count = int(len(span) / 2) array = [] for n in range(array_count): @@ -3419,7 +3474,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_EnumElement_ConstantSize_', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_EnumElement_ConstantSize_", 8, len(span)) array = [] for n in range(4): array.append(Enum16.from_int(int.from_bytes(span[n * 2:(n + 1) * 2], byteorder='little'))) @@ -3448,7 +3503,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_EnumElement_ConstantSize', bytes]: fields = {'payload': None} if len(span) < 8: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_EnumElement_ConstantSize", 8, len(span)) fields['s'] = Struct_Array_Field_EnumElement_ConstantSize_.parse_all(span[0:8]) span = span[8:] return Struct_Array_Field_EnumElement_ConstantSize(**fields), span @@ -3473,13 +3528,13 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_EnumElement_VariableSize_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_EnumElement_VariableSize_", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_EnumElement_VariableSize_", array_size, len(span)) if array_size % 2 != 0: - raise Exception('Array size is not a multiple of the element size') + raise ArraySizeError("Struct_Array_Field_EnumElement_VariableSize_", "array", array_size, 2) array_count = int(array_size / 2) array = [] for n in range(array_count): @@ -3536,11 +3591,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_EnumElement_VariableCount_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_EnumElement_VariableCount_", 1, len(span)) array_count = (span[0] >> 0) & 0xf span = span[1:] if len(span) < 2 * array_count: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_EnumElement_VariableCount_", 2 * array_count, len(span)) array = [] for n in range(array_count): array.append(Enum16.from_int(int.from_bytes(span[n * 2:(n + 1) * 2], byteorder='little'))) @@ -3595,7 +3650,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_EnumElement_UnknownSize_', bytes]: fields = {'payload': None} if len(span) % 2 != 0: - raise Exception('Array size is not a multiple of the element size') + raise ArraySizeError("Struct_Array_Field_EnumElement_UnknownSize_", "array", len(span), 2) array_count = int(len(span) / 2) array = [] for n in range(array_count): @@ -3648,7 +3703,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_SizedElement_ConstantSize_', bytes]: fields = {'payload': None} if len(span) < 4: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_SizedElement_ConstantSize_", 4, len(span)) array = [] for n in range(4): array.append(SizedStruct.parse_all(span[n:n + 1])) @@ -3677,7 +3732,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_SizedElement_ConstantSize', bytes]: fields = {'payload': None} if len(span) < 4: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_SizedElement_ConstantSize", 4, len(span)) fields['s'] = Struct_Array_Field_SizedElement_ConstantSize_.parse_all(span[0:4]) span = span[4:] return Struct_Array_Field_SizedElement_ConstantSize(**fields), span @@ -3702,11 +3757,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_SizedElement_VariableSize_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_SizedElement_VariableSize_", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_SizedElement_VariableSize_", array_size, len(span)) array = [] for n in range(array_size): array.append(SizedStruct.parse_all(span[n:n + 1])) @@ -3762,11 +3817,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_SizedElement_VariableCount_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_SizedElement_VariableCount_", 1, len(span)) array_count = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_count: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_SizedElement_VariableCount_", array_count, len(span)) array = [] for n in range(array_count): array.append(SizedStruct.parse_all(span[n:n + 1])) @@ -3921,11 +3976,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_UnsizedElement_VariableSize_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_UnsizedElement_VariableSize_", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_UnsizedElement_VariableSize_", array_size, len(span)) array_span = span[:array_size] array = [] while len(array_span) > 0: @@ -3983,7 +4038,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_UnsizedElement_VariableCount_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_UnsizedElement_VariableCount_", 1, len(span)) array_count = (span[0] >> 0) & 0xf span = span[1:] array = [] @@ -4090,12 +4145,12 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_UnsizedElement_SizeModifier_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_UnsizedElement_SizeModifier_", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] array_size = array_size - +2 if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_UnsizedElement_SizeModifier_", array_size, len(span)) array_span = span[:array_size] array = [] while len(array_span) > 0: @@ -4153,17 +4208,17 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_SizedElement_VariableSize_Padded_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_SizedElement_VariableSize_Padded_", 1, len(span)) array_size = (span[0] >> 0) & 0xf span = span[1:] if len(span) < 16: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_SizedElement_VariableSize_Padded_", 16, len(span)) remaining_span = span[16:] span = span[:16] if len(span) < array_size: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_SizedElement_VariableSize_Padded_", array_size, len(span)) if array_size % 2 != 0: - raise Exception('Array size is not a multiple of the element size') + raise ArraySizeError("Struct_Array_Field_SizedElement_VariableSize_Padded_", "array", array_size, 2) array_count = int(array_size / 2) array = [] for n in range(array_count): @@ -4200,7 +4255,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_SizedElement_VariableSize_Padded', bytes]: fields = {'payload': None} if len(span) < 17: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_SizedElement_VariableSize_Padded", 17, len(span)) fields['s'] = Struct_Array_Field_SizedElement_VariableSize_Padded_.parse_all(span[0:17]) span = span[17:] return Struct_Array_Field_SizedElement_VariableSize_Padded(**fields), span @@ -4225,11 +4280,11 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_UnsizedElement_VariableCount_Padded_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_UnsizedElement_VariableCount_Padded_", 1, len(span)) array_count = span[0] span = span[1:] if len(span) < 16: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_UnsizedElement_VariableCount_Padded_", 16, len(span)) remaining_span = span[16:] span = span[:16] array = [] @@ -4266,7 +4321,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Array_Field_UnsizedElement_VariableCount_Padded', bytes]: fields = {'payload': None} if len(span) < 17: - raise Exception('Invalid packet size') + raise LengthError("Struct_Array_Field_UnsizedElement_VariableCount_Padded", 17, len(span)) fields['s'] = Struct_Array_Field_UnsizedElement_VariableCount_Padded_.parse_all(span[0:17]) span = span[17:] return Struct_Array_Field_UnsizedElement_VariableCount_Padded(**fields), span @@ -4292,18 +4347,18 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Optional_Scalar_Field_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Optional_Scalar_Field_", 1, len(span)) c0 = (span[0] >> 0) & 0x1 c1 = (span[0] >> 1) & 0x1 span = span[1:] if c0 == 0: if len(span) < 3: - raise Exception('Invalid packet size') + raise LengthError("Struct_Optional_Scalar_Field_", 3, len(span)) fields['a'] = int.from_bytes(span[:3], byteorder='little') span = span[3:] if c1 == 1: if len(span) < 4: - raise Exception('Invalid packet size') + raise LengthError("Struct_Optional_Scalar_Field_", 4, len(span)) fields['b'] = int.from_bytes(span[:4], byteorder='little') span = span[4:] return Struct_Optional_Scalar_Field_(**fields), span @@ -4363,18 +4418,18 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Optional_Enum_Field_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Optional_Enum_Field_", 1, len(span)) c0 = (span[0] >> 0) & 0x1 c1 = (span[0] >> 1) & 0x1 span = span[1:] if c0 == 0: if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Struct_Optional_Enum_Field_", 2, len(span)) fields['a'] = Enum16(int.from_bytes(span[:2], byteorder='little')) span = span[2:] if c1 == 1: if len(span) < 2: - raise Exception('Invalid packet size') + raise LengthError("Struct_Optional_Enum_Field_", 2, len(span)) fields['b'] = Enum16(int.from_bytes(span[:2], byteorder='little')) span = span[2:] return Struct_Optional_Enum_Field_(**fields), span @@ -4434,7 +4489,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Struct_Optional_Struct_Field_', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Struct_Optional_Struct_Field_", 1, len(span)) c0 = (span[0] >> 0) & 0x1 c1 = (span[0] >> 1) & 0x1 span = span[1:] @@ -4498,7 +4553,7 @@ def from_int(v: int) -> Union[int, 'Enum_Incomplete_Truncated_Closed_']: try: return Enum_Incomplete_Truncated_Closed_(v) except ValueError: - raise ValueError('Invalid enum value') + raise EnumValueError("", "", "Enum_Incomplete_Truncated_Closed_", v) @dataclass class Enum_Incomplete_Truncated_Closed(Packet): @@ -4511,7 +4566,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Enum_Incomplete_Truncated_Closed', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Enum_Incomplete_Truncated_Closed", 1, len(span)) fields['e'] = Enum_Incomplete_Truncated_Closed_.from_int((span[0] >> 0) & 0x7) span = span[1:] return Enum_Incomplete_Truncated_Closed(**fields), span @@ -4547,7 +4602,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Enum_Incomplete_Truncated_Open', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Enum_Incomplete_Truncated_Open", 1, len(span)) fields['e'] = Enum_Incomplete_Truncated_Open_.from_int((span[0] >> 0) & 0x7) span = span[1:] return Enum_Incomplete_Truncated_Open(**fields), span @@ -4571,7 +4626,7 @@ def from_int(v: int) -> Union[int, 'Enum_Incomplete_Truncated_Closed_WithRange_' except ValueError: if v >= 0x1 and v <= 0x6: return v - raise ValueError('Invalid enum value') + raise EnumValueError("", "", "Enum_Incomplete_Truncated_Closed_WithRange_", v) @dataclass class Enum_Incomplete_Truncated_Closed_WithRange(Packet): @@ -4584,7 +4639,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Enum_Incomplete_Truncated_Closed_WithRange', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Enum_Incomplete_Truncated_Closed_WithRange", 1, len(span)) fields['e'] = Enum_Incomplete_Truncated_Closed_WithRange_.from_int((span[0] >> 0) & 0x7) span = span[1:] return Enum_Incomplete_Truncated_Closed_WithRange(**fields), span @@ -4619,7 +4674,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Enum_Incomplete_Truncated_Open_WithRange', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Enum_Incomplete_Truncated_Open_WithRange", 1, len(span)) fields['e'] = Enum_Incomplete_Truncated_Open_WithRange_.from_int((span[0] >> 0) & 0x7) span = span[1:] return Enum_Incomplete_Truncated_Open_WithRange(**fields), span @@ -4648,7 +4703,7 @@ def from_int(v: int) -> Union[int, 'Enum_Complete_Truncated_']: try: return Enum_Complete_Truncated_(v) except ValueError: - raise ValueError('Invalid enum value') + raise EnumValueError("", "", "Enum_Complete_Truncated_", v) @dataclass class Enum_Complete_Truncated(Packet): @@ -4661,7 +4716,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Enum_Complete_Truncated', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Enum_Complete_Truncated", 1, len(span)) fields['e'] = Enum_Complete_Truncated_.from_int((span[0] >> 0) & 0x7) span = span[1:] return Enum_Complete_Truncated(**fields), span @@ -4685,7 +4740,7 @@ def from_int(v: int) -> Union[int, 'Enum_Complete_Truncated_WithRange_']: except ValueError: if v >= 0x1 and v <= 0x7: return v - raise ValueError('Invalid enum value') + raise EnumValueError("", "", "Enum_Complete_Truncated_WithRange_", v) @dataclass class Enum_Complete_Truncated_WithRange(Packet): @@ -4698,7 +4753,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Enum_Complete_Truncated_WithRange', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Enum_Complete_Truncated_WithRange", 1, len(span)) fields['e'] = Enum_Complete_Truncated_WithRange_.from_int((span[0] >> 0) & 0x7) span = span[1:] return Enum_Complete_Truncated_WithRange(**fields), span @@ -4723,7 +4778,7 @@ def from_int(v: int) -> Union[int, 'Enum_Complete_WithRange_']: except ValueError: if v >= 0x2 and v <= 0xff: return v - raise ValueError('Invalid enum value') + raise EnumValueError("", "", "Enum_Complete_WithRange_", v) @dataclass class Enum_Complete_WithRange(Packet): @@ -4736,7 +4791,7 @@ def __post_init__(self) -> None: def parse(span: bytes) -> Tuple['Enum_Complete_WithRange', bytes]: fields = {'payload': None} if len(span) < 1: - raise Exception('Invalid packet size') + raise LengthError("Enum_Complete_WithRange", 1, len(span)) fields['e'] = Enum_Complete_WithRange_.from_int(span[0]) span = span[1:] return Enum_Complete_WithRange(**fields), span diff --git a/pdl-compiler/tests/python_generator_test.py b/pdl-compiler/tests/python_generator_test.py index ab1d4be2..0ac72643 100644 --- a/pdl-compiler/tests/python_generator_test.py +++ b/pdl-compiler/tests/python_generator_test.py @@ -109,7 +109,8 @@ def testLittleEndian(self): cls = getattr(le_backend, packet) for test in tests: if 'expected_error' in test: - with self.assertRaises((Exception, ValueError)): + exception_cls = getattr(le_backend, test['expected_error']) + with self.assertRaises(exception_cls): cls.parse_all(bytes.fromhex(test['packed'])) else: result = cls.parse_all(bytes.fromhex(test['packed']))