aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWeilun Du <wdu@google.com>2023-07-14 14:17:48 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-07-14 14:17:48 +0000
commite107b6ca4d4614084ff2a32db5defe2bc5194bcb (patch)
treee00e76908c9390c398f7ffc6ca31cf93b9aaa8ea
parent7207476bff709e84ca9164c5176209b8b612a319 (diff)
parentafcefe6794d7b84ca0fabd35fa05517e77be7015 (diff)
downloadpdl-compiler-e107b6ca4d4614084ff2a32db5defe2bc5194bcb.tar.gz
Revert "Update pdl-compiler to 0.1.4" am: afcefe6794
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/pdl-compiler/+/2658075 Change-Id: I71cff850e5b36d0ab73f6cb663e125f960c997a2 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp6
-rw-r--r--Cargo.toml6
-rw-r--r--Cargo.toml.orig6
-rw-r--r--METADATA8
-rw-r--r--doc/cxx-generated-code-guide.rst20
-rw-r--r--doc/python-generated-code-guide.rst6
-rw-r--r--doc/reference.md12
-rw-r--r--doc/rust-generated-code-guide.rst24
-rwxr-xr-xscripts/generate_test_vectors.py685
-rw-r--r--src/analyzer.rs141
-rw-r--r--src/ast.rs51
-rw-r--r--src/backends/rust.rs309
-rw-r--r--src/backends/rust/parser.rs93
-rw-r--r--src/backends/rust/serializer.rs41
-rw-r--r--src/backends/rust/types.rs11
-rw-r--r--src/lib.rs1
-rw-r--r--src/lint.rs259
-rw-r--r--src/parser.rs17
-rw-r--r--tests/generated/enum_declaration_big_endian.rs246
-rw-r--r--tests/generated/enum_declaration_little_endian.rs246
-rw-r--r--tests/generated/packet_decl_24bit_enum_array_big_endian.rs4
-rw-r--r--tests/generated/packet_decl_24bit_enum_array_little_endian.rs4
-rw-r--r--tests/generated/packet_decl_24bit_enum_big_endian.rs4
-rw-r--r--tests/generated/packet_decl_24bit_enum_little_endian.rs4
-rw-r--r--tests/generated/packet_decl_64bit_enum_array_big_endian.rs4
-rw-r--r--tests/generated/packet_decl_64bit_enum_array_little_endian.rs4
-rw-r--r--tests/generated/packet_decl_64bit_enum_big_endian.rs4
-rw-r--r--tests/generated/packet_decl_64bit_enum_little_endian.rs4
-rw-r--r--tests/generated/packet_decl_8bit_enum_array_big_endian.rs4
-rw-r--r--tests/generated/packet_decl_8bit_enum_array_little_endian.rs4
-rw-r--r--tests/generated/packet_decl_8bit_enum_big_endian.rs4
-rw-r--r--tests/generated/packet_decl_8bit_enum_little_endian.rs4
-rw-r--r--tests/generated/packet_decl_child_packets_big_endian.rs4
-rw-r--r--tests/generated/packet_decl_child_packets_little_endian.rs4
-rw-r--r--tests/generated/packet_decl_fixed_enum_field_big_endian.rs5
-rw-r--r--tests/generated/packet_decl_fixed_enum_field_little_endian.rs5
-rw-r--r--tests/generated/packet_decl_fixed_scalar_field_big_endian.rs3
-rw-r--r--tests/generated/packet_decl_fixed_scalar_field_little_endian.rs3
-rw-r--r--tests/generated/packet_decl_grand_children_big_endian.rs16
-rw-r--r--tests/generated/packet_decl_grand_children_little_endian.rs16
-rw-r--r--tests/generated/packet_decl_mixed_scalars_enums_big_endian.rs8
-rw-r--r--tests/generated/packet_decl_mixed_scalars_enums_little_endian.rs8
-rw-r--r--tests/generated/packet_decl_parent_with_alias_child_big_endian.rs4
-rw-r--r--tests/generated/packet_decl_parent_with_alias_child_little_endian.rs4
-rw-r--r--tests/generated/packet_decl_parent_with_no_payload_big_endian.rs4
-rw-r--r--tests/generated/packet_decl_parent_with_no_payload_little_endian.rs4
-rw-r--r--tests/generated/reserved_identifier_big_endian.rs145
-rw-r--r--tests/generated/reserved_identifier_little_endian.rs145
49 files changed, 669 insertions, 1947 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index f776014..24636e7 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
{
"git": {
- "sha1": "ff041c0f60f985ecc2f8c90bdec618575dcb5060"
+ "sha1": "6b05a0616ef2a982068e0d5fbe28d2058d49d8e0"
},
"path_in_vcs": ""
} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index c6ff8e0..60940fe 100644
--- a/Android.bp
+++ b/Android.bp
@@ -7,7 +7,7 @@ rust_binary_host {
name: "generate_canonical_tests",
crate_name: "generate_canonical_tests",
cargo_env_compat: true,
- cargo_pkg_version: "0.1.4",
+ cargo_pkg_version: "0.1.3",
srcs: ["src/bin/generate-canonical-tests.rs"],
edition: "2021",
features: [
@@ -37,7 +37,7 @@ rust_library_host {
name: "libpdl_compiler",
crate_name: "pdl_compiler",
cargo_env_compat: true,
- cargo_pkg_version: "0.1.4",
+ cargo_pkg_version: "0.1.3",
srcs: ["src/lib.rs"],
edition: "2021",
features: [
@@ -66,7 +66,7 @@ rust_binary_host {
name: "pdlc",
crate_name: "pdlc",
cargo_env_compat: true,
- cargo_pkg_version: "0.1.4",
+ cargo_pkg_version: "0.1.3",
srcs: ["src/main.rs"],
edition: "2021",
features: [
diff --git a/Cargo.toml b/Cargo.toml
index a9b427c..57d75db 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "pdl-compiler"
-version = "0.1.4"
+version = "0.1.3"
authors = [
"Henri Chataing <henrichataing@google.com>",
"David de Jesus Duarte <licorne@google.com>",
@@ -32,7 +32,7 @@ keywords = [
"grammar",
]
categories = ["parsing"]
-license = "Apache-2.0"
+license-file = "LICENSE"
repository = "https://github.com/google/pdl/"
[[bin]]
@@ -85,7 +85,7 @@ version = "1.2.1"
features = ["serde"]
[dev-dependencies.googletest]
-version = "0.8.0"
+version = "0.7.0"
[dev-dependencies.num-derive]
version = "0.3.3"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index cf8b0cf..c9fa183 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,10 +1,10 @@
[package]
name = "pdl-compiler"
-version = "0.1.4"
+version = "0.1.3"
edition = "2021"
description = "Parser and serializer generator for protocol binary packets"
repository = "https://github.com/google/pdl/"
-license = "Apache-2.0"
+license-file = "LICENSE"
readme = "README.md"
keywords = ["pdl", "parser", "serializer", "grammar"]
authors = [
@@ -49,4 +49,4 @@ num-derive = "0.3.3"
num-traits = "0.2.15"
thiserror = "1.0.37"
paste = "1.0.6"
-googletest = "0.8.0"
+googletest = "0.7.0"
diff --git a/METADATA b/METADATA
index 3dc5568..b35258e 100644
--- a/METADATA
+++ b/METADATA
@@ -11,13 +11,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/pdl-compiler/pdl-compiler-0.1.4.crate"
+ value: "https://static.crates.io/crates/pdl-compiler/pdl-compiler-0.1.3.crate"
}
- version: "0.1.4"
+ version: "0.1.3"
license_type: NOTICE
last_upgrade_date {
year: 2023
- month: 7
- day: 13
+ month: 6
+ day: 27
}
}
diff --git a/doc/cxx-generated-code-guide.rst b/doc/cxx-generated-code-guide.rst
index 3a71430..f694e70 100644
--- a/doc/cxx-generated-code-guide.rst
+++ b/doc/cxx-generated-code-guide.rst
@@ -25,23 +25,3 @@ Example invocation:
cargo run my-protocol.pdl --output-format json | \
./scripts/generate_cxx_backend.py > my-protocol.h
-
-Language bindings
------------------
-
-Enum declarations
-^^^^^^^^^^^^^^^^^
-
-+---------------------------------------+---------------------------------------------------------------+
-| :: | .. sourcecode:: c++ |
-| | |
-| enum TestEnum : 8 { | enum TestEnum : int8_t { |
-| A = 1, | A = 1, |
-| B = 2..3, | B_MIN = 2, |
-| C = 4, | B_MAX = 3, |
-| OTHER = .., | C = 4, |
-| } | } |
-+---------------------------------------+---------------------------------------------------------------+
-
-.. note::
- C++ enums are open by construction, default cases in enum declarations are ignored.
diff --git a/doc/python-generated-code-guide.rst b/doc/python-generated-code-guide.rst
index de766d4..664d759 100644
--- a/doc/python-generated-code-guide.rst
+++ b/doc/python-generated-code-guide.rst
@@ -49,13 +49,9 @@ Enum declarations
| A = 1, | A = 1 |
| B = 2..3, | B_MIN = 2 |
| C = 4, | B_MAX = 3 |
-| OTHER = .., | C = 4 |
-| } | |
+| } | C = 4 |
+---------------------------------------+---------------------------------------------------------------+
-.. note::
- Python enums are open by construction, default cases in enum declarations are ignored.
-
Packet declarations
^^^^^^^^^^^^^^^^^^^
diff --git a/doc/reference.md b/doc/reference.md
index ce2f0a7..2529c29 100644
--- a/doc/reference.md
+++ b/doc/reference.md
@@ -161,7 +161,7 @@ A declaration is either:
> &nbsp;&nbsp; enum_tag (`,` enum_tag)* `,`?
>
> enum_tag:\
-> &nbsp;&nbsp; enum_range | enum_value | enum_other
+> &nbsp;&nbsp; enum_range | enum_value
>
> enum_range:\
> &nbsp;&nbsp; [IDENTIFIER](#identifier) `=` [INTEGER](#integer) `..` [INTEGER](#integer)) (`{`\
@@ -173,20 +173,12 @@ A declaration is either:
>
> enum_value:\
> &nbsp;&nbsp; [IDENTIFIER](#identifier) `=` [INTEGER](#integer)
->
-> enum_other:\
-> &nbsp;&nbsp; [IDENTIFIER](#identifier) `=` `..`
An *enumeration* or for short *enum*, is a declaration of a set of named [integer](#integer) constants
or named [integer](#integer) ranges. [integer](#integer) ranges are inclusive in both ends.
[integer](#integer) value within a range *must* be unique. [integer](#integer) ranges
*must not* overlap.
-*enumeration* are closed by default, all values that are not explicitely described in the declaration are treated as invalid and _may_ cause a parsing error.
-
-An *enumaration* _may_ be declared open by specifiying the default case; all unrecognized values
-_shall_ falltrough to the default.
-
The [integer](#integer) following the name specifies the bit size of the values.
```
@@ -207,8 +199,6 @@ enum CoffeeAddition: 5 {
},
Custom = 20..29,
-
- Other = ..
}
```
diff --git a/doc/rust-generated-code-guide.rst b/doc/rust-generated-code-guide.rst
index 6dfdfd0..df22d92 100644
--- a/doc/rust-generated-code-guide.rst
+++ b/doc/rust-generated-code-guide.rst
@@ -30,10 +30,6 @@ backend may create it.
impl<T> std::ops::Deref for Private<T> { .. }
-.. warning::
- PDL authorizes the use of rust keywords as identifier. Keyword identifiers
- are generated as raw identifiers, e.g. `type` is generated as `r#type`.
-
Enum declarations
^^^^^^^^^^^^^^^^^
@@ -76,23 +72,3 @@ Enum declarations
| | impl From<TestEnum> for i32 { .. } |
| | impl From<TestEnum> for i64 { .. } |
+---------------------------------------+---------------------------------------------------------------+
-| :: | .. sourcecode:: rust |
-| | |
-| enum TestEnum : 8 { | #[repr(u64)] |
-| A = 1, | #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] |
-| B = 2, | enum TestEnum { |
-| OTHER = .., | A, |
-| } | B, |
-| | Other(Private<u8>), |
-| | } |
-| | |
-| | impl From<u8> for TestEnum { .. } |
-| | impl From<TestEnum> for u8 { .. } |
-| | impl From<TestEnum> for u16 { .. } |
-| | impl From<TestEnum> for u32 { .. } |
-| | impl From<TestEnum> for u64 { .. } |
-| | impl From<TestEnum> for i8 { .. } |
-| | impl From<TestEnum> for i16 { .. } |
-| | impl From<TestEnum> for i32 { .. } |
-| | impl From<TestEnum> for i64 { .. } |
-+---------------------------------------+---------------------------------------------------------------+
diff --git a/scripts/generate_test_vectors.py b/scripts/generate_test_vectors.py
deleted file mode 100755
index ef2ea24..0000000
--- a/scripts/generate_test_vectors.py
+++ /dev/null
@@ -1,685 +0,0 @@
-#!/usr/bin/env python3
-
-import argparse
-import collections
-import copy
-import json
-from pathlib import Path
-import pprint
-import traceback
-from typing import Iterable, List, Optional, Union
-import sys
-
-from pdl import ast, core
-
-MAX_ARRAY_SIZE = 256
-MAX_ARRAY_COUNT = 32
-DEFAULT_ARRAY_COUNT = 3
-DEFAULT_PAYLOAD_SIZE = 5
-
-
-class BitSerializer:
- def __init__(self, big_endian: bool):
- self.stream = []
- self.value = 0
- self.shift = 0
- self.byteorder = "big" if big_endian else "little"
-
- def append(self, value: int, width: int):
- self.value = self.value | (value << self.shift)
- self.shift += width
-
- if (self.shift % 8) == 0:
- width = int(self.shift / 8)
- self.stream.extend(self.value.to_bytes(width, byteorder=self.byteorder))
- self.shift = 0
- self.value = 0
-
-
-class Value:
- def __init__(self, value: object, width: Optional[int] = None):
- self.value = value
- if width is not None:
- self.width = width
- elif isinstance(value, int) or callable(value):
- raise Exception("Creating scalar value of unspecified width")
- elif isinstance(value, list):
- self.width = sum([v.width for v in value])
- elif isinstance(value, Packet):
- self.width = value.width
- else:
- raise Exception(f"Malformed value {value}")
-
- def finalize(self, parent: "Packet"):
- if callable(self.width):
- self.width = self.width(parent)
-
- if callable(self.value):
- self.value = self.value(parent)
- elif isinstance(self.value, list):
- for v in self.value:
- v.finalize(parent)
- elif isinstance(self.value, Packet):
- self.value.finalize()
-
- def serialize_(self, serializer: BitSerializer):
- if isinstance(self.value, int):
- serializer.append(self.value, self.width)
- elif isinstance(self.value, list):
- for v in self.value:
- v.serialize_(serializer)
- elif isinstance(self.value, Packet):
- self.value.serialize_(serializer)
- else:
- raise Exception(f"Malformed value {self.value}")
-
- def show(self, indent: int = 0):
- space = " " * indent
- if isinstance(self.value, int):
- print(f"{space}{self.name}: {hex(self.value)}")
- elif isinstance(self.value, list):
- print(f"{space}{self.name}[{len(self.value)}]:")
- for v in self.value:
- v.show(indent + 2)
- elif isinstance(self.value, Packet):
- print(f"{space}{self.name}:")
- self.value.show(indent + 2)
-
- def to_json(self) -> object:
- if isinstance(self.value, int):
- return self.value
- elif isinstance(self.value, list):
- return [v.to_json() for v in self.value]
- elif isinstance(self.value, Packet):
- return self.value.to_json()
-
-
-class Field:
- def __init__(self, value: Value, ref: ast.Field):
- self.value = value
- self.ref = ref
-
- def finalize(self, parent: "Packet"):
- self.value.finalize(parent)
-
- def serialize_(self, serializer: BitSerializer):
- self.value.serialize_(serializer)
-
- def clone(self):
- return Field(copy.copy(self.value), self.ref)
-
-
-class Packet:
- def __init__(self, fields: List[Field], ref: ast.Declaration):
- self.fields = fields
- self.ref = ref
-
- def finalize(self, parent: Optional["Packet"] = None):
- for f in self.fields:
- f.finalize(self)
-
- def serialize_(self, serializer: BitSerializer):
- for f in self.fields:
- f.serialize_(serializer)
-
- def serialize(self, big_endian: bool) -> bytes:
- serializer = BitSerializer(big_endian)
- self.serialize_(serializer)
- if serializer.shift != 0:
- raise Exception("The packet size is not an integral number of octets")
- return bytes(serializer.stream)
-
- def show(self, indent: int = 0):
- for f in self.fields:
- f.value.show(indent)
-
- def to_json(self) -> dict:
- result = dict()
- for f in self.fields:
- if isinstance(f.ref, (ast.PayloadField, ast.BodyField)) and isinstance(
- f.value.value, Packet
- ):
- result.update(f.value.to_json())
- elif isinstance(f.ref, (ast.PayloadField, ast.BodyField)):
- result["payload"] = f.value.to_json()
- elif hasattr(f.ref, "id"):
- result[f.ref.id] = f.value.to_json()
- return result
-
- @property
- def width(self) -> int:
- self.finalize()
- return sum([f.value.width for f in self.fields])
-
-
-class BitGenerator:
- def __init__(self):
- self.value = 0
- self.shift = 0
-
- def generate(self, width: int) -> Value:
- """Generate an integer value of the selected width."""
- value = 0
- remains = width
- while remains > 0:
- w = min(8 - self.shift, remains)
- mask = (1 << w) - 1
- value = (value << w) | ((self.value >> self.shift) & mask)
- remains -= w
- self.shift += w
- if self.shift >= 8:
- self.shift = 0
- self.value = (self.value + 1) % 0xFF
- return Value(value, width)
-
- def generate_list(self, width: int, count: int) -> List[Value]:
- return [self.generate(width) for n in range(count)]
-
-
-generator = BitGenerator()
-
-
-def generate_size_field_values(field: ast.SizeField) -> List[Value]:
- def get_field_size(parent: Packet, field_id: str) -> int:
- for f in parent.fields:
- if (
- (field_id == "_payload_" and isinstance(f.ref, ast.PayloadField))
- or (field_id == "_body_" and isinstance(f.ref, ast.BodyField))
- or (getattr(f.ref, "id", None) == field_id)
- ):
- assert f.value.width % 8 == 0
- size_modifier = int(getattr(f.ref, "size_modifier", None) or 0)
- return int(f.value.width / 8) + size_modifier
- raise Exception(
- "Field {} not found in packet {}".format(field_id, parent.ref.id)
- )
-
- return [Value(lambda p: get_field_size(p, field.field_id), field.width)]
-
-
-def generate_count_field_values(field: ast.CountField) -> List[Value]:
- def get_array_count(parent: Packet, field_id: str) -> int:
- for f in parent.fields:
- if getattr(f.ref, "id", None) == field_id:
- assert isinstance(f.value.value, list)
- return len(f.value.value)
- raise Exception(
- "Field {} not found in packet {}".format(field_id, parent.ref.id)
- )
-
- return [Value(lambda p: get_array_count(p, field.field_id), field.width)]
-
-
-def generate_checksum_field_values(field: ast.TypedefField) -> List[Value]:
- field_width = core.get_field_size(field)
-
- def basic_checksum(input: bytes, width: int):
- assert width == 8
- return sum(input) % 256
-
- def compute_checksum(parent: Packet, field_id: str) -> int:
- serializer = None
- for f in parent.fields:
- if isinstance(f.ref, ast.ChecksumField) and f.ref.field_id == field_id:
- serializer = BitSerializer(
- f.ref.parent.file.endianness.value == "big_endian"
- )
- elif isinstance(f.ref, ast.TypedefField) and f.ref.id == field_id:
- return basic_checksum(serializer.stream, field_width)
- elif serializer:
- f.value.serialize_(serializer)
- raise Exception("malformed checksum")
-
- return [Value(lambda p: compute_checksum(p, field.id), field_width)]
-
-
-def generate_padding_field_values(field: ast.PaddingField) -> List[Value]:
- preceding_field_id = field.padded_field.id
-
- def get_padding(parent: Packet, field_id: str, width: int) -> List[Value]:
- for f in parent.fields:
- if (
- (field_id == "_payload_" and isinstance(f.ref, ast.PayloadField))
- or (field_id == "_body_" and isinstance(f.ref, ast.BodyField))
- or (getattr(f.ref, "id", None) == field_id)
- ):
- assert f.value.width % 8 == 0
- assert f.value.width <= width
- return width - f.value.width
- raise Exception(
- "Field {} not found in packet {}".format(field_id, parent.ref.id)
- )
-
- return [Value(0, lambda p: get_padding(p, preceding_field_id, 8 * field.size))]
-
-
-def generate_payload_field_values(
- field: Union[ast.PayloadField, ast.BodyField]
-) -> List[Value]:
- payload_size = core.get_payload_field_size(field)
- size_modifier = int(getattr(field, "size_modifier", None) or 0)
-
- # If the paylaod has a size field, generate an empty payload and
- # a payload of maximum size. If not generate a payload of the default size.
- max_size = (1 << payload_size.width) - 1 if payload_size else DEFAULT_PAYLOAD_SIZE
- max_size -= size_modifier
-
- assert max_size > 0
- return [Value([]), Value(generator.generate_list(8, max_size))]
-
-
-def generate_scalar_array_field_values(field: ast.ArrayField) -> List[Value]:
- if field.width % 8 != 0:
- if element_width % 8 != 0:
- raise Exception("Array element size is not a multiple of 8")
-
- array_size = core.get_array_field_size(field)
- element_width = int(field.width / 8)
-
- # TODO
- # The array might also be bounded if it is included in the sized payload
- # of a packet.
-
- # Apply the size modifiers.
- size_modifier = int(getattr(field, "size_modifier", None) or 0)
-
- # The element width is known, and the array element count is known
- # statically.
- if isinstance(array_size, int):
- return [Value(generator.generate_list(field.width, array_size))]
-
- # The element width is known, and the array element count is known
- # by count field.
- elif isinstance(array_size, ast.CountField):
- min_count = 0
- max_count = (1 << array_size.width) - 1
- return [Value([]), Value(generator.generate_list(field.width, max_count))]
-
- # The element width is known, and the array full size is known
- # by size field.
- elif isinstance(array_size, ast.SizeField):
- min_count = 0
- max_size = (1 << array_size.width) - 1 - size_modifier
- max_count = int(max_size / element_width)
- return [Value([]), Value(generator.generate_list(field.width, max_count))]
-
- # The element width is known, but the array size is unknown.
- # Generate two arrays: one empty and one including some possible element
- # values.
- else:
- return [
- Value([]),
- Value(generator.generate_list(field.width, DEFAULT_ARRAY_COUNT)),
- ]
-
-
-def generate_typedef_array_field_values(field: ast.ArrayField) -> List[Value]:
- array_size = core.get_array_field_size(field)
- element_width = core.get_array_element_size(field)
- if element_width:
- if element_width % 8 != 0:
- raise Exception("Array element size is not a multiple of 8")
- element_width = int(element_width / 8)
-
- # Generate element values to use for the generation.
- type_decl = field.parent.file.typedef_scope[field.type_id]
-
- def generate_list(count: Optional[int]) -> List[Value]:
- """Generate an array of specified length.
- If the count is None all possible array items are returned."""
- element_values = generate_typedef_values(type_decl)
-
- # Requested a variable count, send everything in one chunk.
- if count is None:
- return [Value(element_values)]
- # Have more items than the requested count.
- # Slice the possible array values in multiple slices.
- elif len(element_values) > count:
- # Add more elements in case of wrap-over.
- elements_count = len(element_values)
- element_values.extend(generate_typedef_values(type_decl))
- chunk_count = int((len(elements) + count - 1) / count)
- return [
- Value(element_values[n * count : (n + 1) * count])
- for n in range(chunk_count)
- ]
- # Have less items than the requested count.
- # Generate additional items to fill the gap.
- else:
- chunk = element_values
- while len(chunk) < count:
- chunk.extend(generate_typedef_values(type_decl))
- return [Value(chunk[:count])]
-
- # TODO
- # The array might also be bounded if it is included in the sized payload
- # of a packet.
-
- # Apply the size modifier.
- size_modifier = int(getattr(field, "size_modifier", None) or 0)
-
- min_size = 0
- max_size = MAX_ARRAY_SIZE
- min_count = 0
- max_count = MAX_ARRAY_COUNT
-
- if field.padded_size:
- max_size = field.padded_size
-
- if isinstance(array_size, ast.SizeField):
- max_size = (1 << array_size.width) - 1 - size_modifier
- min_size = size_modifier
- elif isinstance(array_size, ast.CountField):
- max_count = (1 << array_size.width) - 1
- elif isinstance(array_size, int):
- min_count = array_size
- max_count = array_size
-
- values = []
- chunk = []
- chunk_size = 0
-
- while not values:
- element_values = generate_typedef_values(type_decl)
- for element_value in element_values:
- element_size = int(element_value.width / 8)
-
- if len(chunk) >= max_count or chunk_size + element_size > max_size:
- assert len(chunk) >= min_count
- values.append(Value(chunk))
- chunk = []
- chunk_size = 0
-
- chunk.append(element_value)
- chunk_size += element_size
-
- if min_count == 0:
- values.append(Value([]))
-
- return values
-
- # The element width is not known, but the array full octet size
- # is known by size field. Generate two arrays: of minimal and maximum
- # size. All unused element values are packed into arrays of varying size.
- if element_width is None and isinstance(array_size, ast.SizeField):
- element_values = generate_typedef_values(type_decl)
- chunk = []
- chunk_size = 0
- values = [Value([])]
- for element_value in element_values:
- assert element_value.width % 8 == 0
- element_size = int(element_value.width / 8)
- if chunk_size + element_size > max_size:
- values.append(Value(chunk))
- chunk = []
- chunk.append(element_value)
- chunk_size += element_size
- if chunk:
- values.append(Value(chunk))
- return values
-
- # The element width is not known, but the array element count
- # is known statically or by count field. Generate two arrays:
- # of minimal and maximum length. All unused element values are packed into
- # arrays of varying count.
- elif element_width is None and isinstance(array_size, ast.CountField):
- return [Value([])] + generate_list(max_count)
-
- # The element width is not known, and the array element count is known
- # statically.
- elif element_width is None and isinstance(array_size, int):
- return generate_list(array_size)
-
- # Neither the count not size is known,
- # generate two arrays: one empty and one including all possible element
- # values.
- elif element_width is None:
- return [Value([])] + generate_list(None)
-
- # The element width is known, and the array element count is known
- # statically.
- elif isinstance(array_size, int):
- return generate_list(array_size)
-
- # The element width is known, and the array element count is known
- # by count field.
- elif isinstance(array_size, ast.CountField):
- return [Value([])] + generate_list(max_count)
-
- # The element width is known, and the array full size is known
- # by size field.
- elif isinstance(array_size, ast.SizeField):
- return [Value([])] + generate_list(max_count)
-
- # The element width is known, but the array size is unknown.
- # Generate two arrays: one empty and one including all possible element
- # values.
- else:
- return [Value([])] + generate_list(None)
-
-
-def generate_array_field_values(field: ast.ArrayField) -> List[Value]:
- if field.width is not None:
- return generate_scalar_array_field_values(field)
- else:
- return generate_typedef_array_field_values(field)
-
-
-def generate_typedef_field_values(
- field: ast.TypedefField, constraints: List[ast.Constraint]
-) -> List[Value]:
- type_decl = field.parent.file.typedef_scope[field.type_id]
-
- # Check for constraint on enum field.
- if isinstance(type_decl, ast.EnumDeclaration):
- for c in constraints:
- if c.id == field.id:
- for tag in type_decl.tags:
- if tag.id == c.tag_id:
- return [Value(tag.value, type_decl.width)]
- raise Exception("undefined enum tag")
-
- # Checksum field needs to known the checksum range.
- if isinstance(type_decl, ast.ChecksumDeclaration):
- return generate_checksum_field_values(field)
-
- return generate_typedef_values(type_decl)
-
-
-def generate_field_values(
- field: ast.Field, constraints: List[ast.Constraint], payload: Optional[List[Packet]]
-) -> List[Value]:
- if isinstance(field, ast.ChecksumField):
- # Checksum fields are just markers.
- return [Value(0, 0)]
-
- elif isinstance(field, ast.PaddingField):
- return generate_padding_field_values(field)
-
- elif isinstance(field, ast.SizeField):
- return generate_size_field_values(field)
-
- elif isinstance(field, ast.CountField):
- return generate_count_field_values(field)
-
- elif isinstance(field, (ast.BodyField, ast.PayloadField)) and payload:
- return [Value(p) for p in payload]
-
- elif isinstance(field, (ast.BodyField, ast.PayloadField)):
- return generate_payload_field_values(field)
-
- elif isinstance(field, ast.FixedField) and field.enum_id:
- enum_decl = field.parent.file.typedef_scope[field.enum_id]
- for tag in enum_decl.tags:
- if tag.id == field.tag_id:
- return [Value(tag.value, enum_decl.width)]
- raise Exception("undefined enum tag")
-
- elif isinstance(field, ast.FixedField) and field.width:
- return [Value(field.value, field.width)]
-
- elif isinstance(field, ast.ReservedField):
- return [Value(0, field.width)]
-
- elif isinstance(field, ast.ArrayField):
- return generate_array_field_values(field)
-
- elif isinstance(field, ast.ScalarField):
- for c in constraints:
- if c.id == field.id:
- return [Value(c.value, field.width)]
- mask = (1 << field.width) - 1
- return [
- Value(0, field.width),
- Value(-1 & mask, field.width),
- generator.generate(field.width),
- ]
-
- elif isinstance(field, ast.TypedefField):
- return generate_typedef_field_values(field, constraints)
-
- else:
- raise Exception("unsupported field kind")
-
-
-def generate_fields(
- decl: ast.Declaration,
- constraints: List[ast.Constraint],
- payload: Optional[List[Packet]],
-) -> List[List[Field]]:
- return [
- [Field(v, f) for v in generate_field_values(f, constraints, payload)]
- for f in decl.fields
- ]
-
-
-def generate_fields_recursive(
- scope: dict,
- decl: ast.Declaration,
- constraints: List[ast.Constraint] = [],
- payload: Optional[List[Packet]] = None,
-) -> List[List[Field]]:
- fields = generate_fields(decl, constraints, payload)
-
- if not decl.parent_id:
- return fields
-
- packets = [Packet(fields, decl) for fields in product(fields)]
- parent_decl = scope[decl.parent_id]
- return generate_fields_recursive(
- scope, parent_decl, constraints + decl.constraints, payload=packets
- )
-
-
-def generate_struct_values(decl: ast.StructDeclaration) -> List[Packet]:
- fields = generate_fields_recursive(decl.file.typedef_scope, decl)
- return [Packet(fields, decl) for fields in product(fields)]
-
-
-def generate_packet_values(decl: ast.PacketDeclaration) -> List[Packet]:
- fields = generate_fields_recursive(decl.file.packet_scope, decl)
- return [Packet(fields, decl) for fields in product(fields)]
-
-
-def generate_typedef_values(decl: ast.Declaration) -> List[Value]:
- if isinstance(decl, ast.EnumDeclaration):
- return [Value(t.value, decl.width) for t in decl.tags]
-
- elif isinstance(decl, ast.ChecksumDeclaration):
- raise Exception("ChecksumDeclaration handled in typedef field")
-
- elif isinstance(decl, ast.CustomFieldDeclaration):
- raise Exception("TODO custom field")
-
- elif isinstance(decl, ast.StructDeclaration):
- return [Value(p) for p in generate_struct_values(decl)]
-
- else:
- raise Exception("unsupported typedef declaration type")
-
-
-def product(fields: List[List[Field]]) -> List[List[Field]]:
- """Perform a cartesian product of generated options for packet field values."""
-
- def aux(vec: List[List[Field]]) -> List[List[Field]]:
- if len(vec) == 0:
- return [[]]
- return [[item.clone()] + items for item in vec[0] for items in aux(vec[1:])]
-
- count = 1
- max_len = 0
- for f in fields:
- count *= len(f)
- max_len = max(max_len, len(f))
-
- # Limit products to 32 elements to prevent combinatorial
- # explosion.
- if count <= 32:
- return aux(fields)
-
- # If too many products, select samples which test all fields value
- # values at the minimum.
- else:
- return [[f[idx % len(f)] for f in fields] for idx in range(0, max_len + 1)]
-
-
-def serialize_values(file: ast.File, values: List[Value]) -> List[dict]:
- results = []
- for v in values:
- v.finalize()
- packed = v.serialize(file.endianness.value == "big_endian")
- result = {
- "packed": "".join([f"{b:02x}" for b in packed]),
- "unpacked": v.to_json(),
- }
- if v.ref.parent_id:
- result["packet"] = v.ref.id
- results.append(result)
- return results
-
-
-def run(input: Path, packet: List[str]):
- with open(input) as f:
- file = ast.File.from_json(json.load(f))
- core.desugar(file)
-
- results = dict()
- for decl in file.packet_scope.values():
- if core.get_derived_packets(decl) or (packet and decl.id not in packet):
- continue
-
- try:
- values = generate_packet_values(decl)
- ancestor = core.get_packet_ancestor(decl)
- results[ancestor.id] = results.get(ancestor.id, []) + serialize_values(
- file, values
- )
- except Exception as exn:
- print(
- f"Skipping packet {decl.id}; cannot generate values: {exn}",
- file=sys.stderr,
- )
-
- results = [{"packet": k, "tests": v} for (k, v) in results.items()]
- json.dump(results, sys.stdout, indent=2)
-
-
-def main() -> int:
- """Generate test vectors for top-level PDL packets."""
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument(
- "--input", type=Path, required=True, help="Input PDL-JSON source"
- )
- parser.add_argument(
- "--packet",
- type=lambda x: x.split(","),
- required=False,
- action="extend",
- default=[],
- help="Select PDL packet to test",
- )
- return run(**vars(parser.parse_args()))
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/src/analyzer.rs b/src/analyzer.rs
index c89d3d0..1757e5e 100644
--- a/src/analyzer.rs
+++ b/src/analyzer.rs
@@ -190,7 +190,6 @@ pub enum ErrorCode {
DuplicateTagRange = 41,
E42 = 42,
E43 = 43,
- DuplicateDefaultTag = 44,
}
impl From<ErrorCode> for String {
@@ -206,10 +205,8 @@ pub struct Diagnostics {
}
/// Gather information about the full AST.
-#[derive(Debug)]
-pub struct Scope<'d, A: Annotation = ast::Annotation> {
- /// Reference to the source file.
- pub file: &'d crate::ast::File<A>,
+#[derive(Debug, Default)]
+pub struct Scope<'d, A: Annotation> {
/// Collection of Group, Packet, Enum, Struct, Checksum, and CustomField
/// declarations.
pub typedef: HashMap<String, &'d crate::ast::Decl<A>>,
@@ -248,7 +245,7 @@ impl Diagnostics {
impl<'d, A: Annotation + Default> Scope<'d, A> {
pub fn new(file: &'d crate::ast::File<A>) -> Result<Scope<'d, A>, Diagnostics> {
// Gather top-level declarations.
- let mut scope: Scope<A> = Scope { file, typedef: Default::default() };
+ let mut scope: Scope<A> = Default::default();
let mut diagnostics: Diagnostics = Default::default();
for decl in &file.declarations {
if let Some(id) = decl.id() {
@@ -280,14 +277,6 @@ impl<'d, A: Annotation + Default> Scope<'d, A> {
}
}
- /// Iterate over the child declarations of the selected declaration.
- pub fn iter_children<'s>(
- &'s self,
- decl: &'d crate::ast::Decl<A>,
- ) -> impl Iterator<Item = &'d crate::ast::Decl<A>> + 's {
- self.file.iter_children(decl)
- }
-
/// Return the parent declaration of the selected declaration,
/// if it has one.
pub fn get_parent(&self, decl: &crate::ast::Decl<A>) -> Option<&'d crate::ast::Decl<A>> {
@@ -302,15 +291,6 @@ impl<'d, A: Annotation + Default> Scope<'d, A> {
std::iter::successors(self.get_parent(decl), |decl| self.get_parent(decl))
}
- /// Iterate over the parent declarations of the selected declaration,
- /// including the current declaration.
- pub fn iter_parents_and_self<'s>(
- &'s self,
- decl: &'d crate::ast::Decl<A>,
- ) -> impl Iterator<Item = &'d Decl<A>> + 's {
- std::iter::successors(Some(decl), |decl| self.get_parent(decl))
- }
-
/// Iterate over the declaration and its parent's fields.
pub fn iter_fields<'s>(
&'s self,
@@ -319,27 +299,11 @@ impl<'d, A: Annotation + Default> Scope<'d, A> {
std::iter::successors(Some(decl), |decl| self.get_parent(decl)).flat_map(Decl::fields)
}
- /// Iterate over the declaration parent's fields.
- pub fn iter_parent_fields<'s>(
- &'s self,
- decl: &'d crate::ast::Decl<A>,
- ) -> impl Iterator<Item = &'d crate::ast::Field<A>> + 's {
- std::iter::successors(self.get_parent(decl), |decl| self.get_parent(decl))
- .flat_map(Decl::fields)
- }
-
- /// Iterate over the declaration and its parent's constraints.
- pub fn iter_constraints<'s>(
- &'s self,
- decl: &'d crate::ast::Decl<A>,
- ) -> impl Iterator<Item = &'d Constraint> + 's {
- std::iter::successors(Some(decl), |decl| self.get_parent(decl)).flat_map(Decl::constraints)
- }
-
/// Return the type declaration for the selected field, if applicable.
- pub fn get_type_declaration(
+ #[allow(dead_code)]
+ pub fn get_declaration(
&self,
- field: &crate::ast::Field<A>,
+ field: &'d crate::ast::Field<A>,
) -> Option<&'d crate::ast::Decl<A>> {
match &field.desc {
FieldDesc::Checksum { .. }
@@ -359,24 +323,6 @@ impl<'d, A: Annotation + Default> Scope<'d, A> {
| FieldDesc::Typedef { type_id, .. } => self.typedef.get(type_id).cloned(),
}
}
-
- /// Test if the selected field is a bit-field.
- pub fn is_bitfield(&self, field: &crate::ast::Field<A>) -> bool {
- match &field.desc {
- FieldDesc::Size { .. }
- | FieldDesc::Count { .. }
- | FieldDesc::ElementSize { .. }
- | FieldDesc::FixedScalar { .. }
- | FieldDesc::FixedEnum { .. }
- | FieldDesc::Reserved { .. }
- | FieldDesc::Scalar { .. } => true,
- FieldDesc::Typedef { type_id, .. } => {
- let field = self.typedef.get(type_id.as_str());
- matches!(field, Some(Decl { desc: DeclDesc::Enum { .. }, .. }))
- }
- _ => false,
- }
- }
}
/// Return the bit-width of a scalar value.
@@ -736,39 +682,6 @@ fn check_enum_declarations(file: &parser_ast::File) -> Result<(), Diagnostics> {
}
}
- fn check_tag_other<'a>(
- tag: &'a TagOther,
- tags_by_id: &mut HashMap<&'a str, SourceRange>,
- tag_other: &mut Option<SourceRange>,
- diagnostics: &mut Diagnostics,
- ) {
- if let Some(prev) = tags_by_id.insert(&tag.id, tag.loc) {
- diagnostics.push(
- Diagnostic::error()
- .with_code(ErrorCode::DuplicateTagIdentifier)
- .with_message(format!("duplicate tag identifier `{}`", tag.id))
- .with_labels(vec![
- tag.loc.primary(),
- prev.secondary()
- .with_message(format!("`{}` is first declared here", tag.id)),
- ]),
- )
- }
- if let Some(prev) = tag_other {
- diagnostics.push(
- Diagnostic::error()
- .with_code(ErrorCode::DuplicateDefaultTag)
- .with_message("duplicate default tag".to_owned())
- .with_labels(vec![
- tag.loc.primary(),
- prev.secondary()
- .with_message("the default tag is first declared here".to_owned()),
- ]),
- )
- }
- *tag_other = Some(tag.loc)
- }
-
let mut diagnostics: Diagnostics = Default::default();
for decl in &file.declarations {
if let DeclDesc::Enum { tags, width, .. } = &decl.desc {
@@ -781,7 +694,6 @@ fn check_enum_declarations(file: &parser_ast::File) -> Result<(), Diagnostics> {
_ => None,
})
.collect::<Vec<_>>();
- let mut tag_other = None;
for tag in tags {
match tag {
@@ -800,9 +712,6 @@ fn check_enum_declarations(file: &parser_ast::File) -> Result<(), Diagnostics> {
&mut tags_by_value,
&mut diagnostics,
),
- Tag::Other(other) => {
- check_tag_other(other, &mut tags_by_id, &mut tag_other, &mut diagnostics)
- }
}
}
@@ -1933,17 +1842,6 @@ mod test {
}
"#
);
-
- raises!(
- DuplicateTagIdentifier,
- r#"
- little_endian_packets
- enum A : 8 {
- X = 0,
- X = ..,
- }
- "#
- );
}
#[test]
@@ -2622,22 +2520,6 @@ mod test {
}
#[test]
- fn test_e44() {
- raises!(
- DuplicateDefaultTag,
- r#"
- little_endian_packets
- enum A : 8 {
- A = 0,
- X = ..,
- B = 1,
- Y = ..,
- }
- "#
- );
- }
-
- #[test]
fn test_enum_declaration() {
valid!(
r#"
@@ -2672,17 +2554,6 @@ mod test {
}
"#
);
-
- valid!(
- r#"
- little_endian_packets
- enum A : 7 {
- A = 50..100,
- X = 101,
- UNKNOWN = ..,
- }
- "#
- );
}
use analyzer::ast::Size;
diff --git a/src/ast.rs b/src/ast.rs
index 30c2a4d..da46c13 100644
--- a/src/ast.rs
+++ b/src/ast.rs
@@ -86,19 +86,11 @@ pub struct TagRange {
pub tags: Vec<TagValue>,
}
-#[derive(Debug, Clone, Serialize)]
-#[serde(tag = "kind", rename = "tag")]
-pub struct TagOther {
- pub id: String,
- pub loc: SourceRange,
-}
-
#[derive(Debug, Serialize, Clone, PartialEq, Eq)]
#[serde(untagged)]
pub enum Tag {
Value(TagValue),
Range(TagRange),
- Other(TagOther),
}
#[derive(Debug, Serialize, Clone)]
@@ -296,35 +288,23 @@ impl PartialEq for TagRange {
}
}
-impl Eq for TagOther {}
-impl PartialEq for TagOther {
- fn eq(&self, other: &Self) -> bool {
- // Implement structual equality, leave out loc.
- self.id == other.id
- }
-}
-
impl Tag {
pub fn id(&self) -> &str {
match self {
- Tag::Value(TagValue { id, .. })
- | Tag::Range(TagRange { id, .. })
- | Tag::Other(TagOther { id, .. }) => id,
+ Tag::Value(TagValue { id, .. }) | Tag::Range(TagRange { id, .. }) => id,
}
}
pub fn loc(&self) -> &SourceRange {
match self {
- Tag::Value(TagValue { loc, .. })
- | Tag::Range(TagRange { loc, .. })
- | Tag::Other(TagOther { loc, .. }) => loc,
+ Tag::Value(TagValue { loc, .. }) | Tag::Range(TagRange { loc, .. }) => loc,
}
}
pub fn value(&self) -> Option<usize> {
match self {
Tag::Value(TagValue { value, .. }) => Some(*value),
- Tag::Range(_) | Tag::Other(_) => None,
+ Tag::Range(_) => None,
}
}
}
@@ -471,31 +451,6 @@ impl<A: Annotation> Decl<A> {
}
}
- /// Return the reference to the payload or body field in a declaration,
- /// if present.
- pub fn payload(&self) -> Option<&Field<A>> {
- self.fields()
- .find(|field| matches!(&field.desc, FieldDesc::Payload { .. } | FieldDesc::Body { .. }))
- }
-
- /// Return the reference to the payload or body size field in a declaration,
- /// if present.
- pub fn payload_size(&self) -> Option<&Field<A>> {
- self.fields().find(|field| match &field.desc {
- FieldDesc::Size { field_id, .. } => field_id == "_payload_" || field_id == "_body_",
- _ => false,
- })
- }
-
- /// Return the reference to the array size or count field in a declaration,
- /// if present.
- pub fn array_size(&self, id: &str) -> Option<&Field<A>> {
- self.fields().find(|field| match &field.desc {
- FieldDesc::Size { field_id, .. } | FieldDesc::Count { field_id, .. } => field_id == id,
- _ => false,
- })
- }
-
pub fn kind(&self) -> &str {
match &self.desc {
DeclDesc::Checksum { .. } => "checksum",
diff --git a/src/backends/rust.rs b/src/backends/rust.rs
index 9dfdf8a..f369179 100644
--- a/src/backends/rust.rs
+++ b/src/backends/rust.rs
@@ -14,10 +14,9 @@
//! Rust compiler backend.
-use crate::{analyzer, ast};
+use crate::{ast, lint};
use quote::{format_ident, quote};
use std::collections::BTreeSet;
-use std::collections::HashMap;
use std::path::Path;
use syn::LitInt;
@@ -31,25 +30,25 @@ mod types;
use parser::FieldParser;
use serializer::FieldSerializer;
+#[cfg(not(tm_mainline_prod))]
pub use heck::ToUpperCamelCase;
-pub trait ToIdent {
- /// Generate a sanitized rust identifier.
- /// Rust specific keywords are renamed for validity.
- fn to_ident(self) -> proc_macro2::Ident;
+#[cfg(tm_mainline_prod)]
+pub trait ToUpperCamelCase {
+ fn to_upper_camel_case(&self) -> String;
}
-impl ToIdent for &'_ str {
- fn to_ident(self) -> proc_macro2::Ident {
- match self {
- "as" | "break" | "const" | "continue" | "crate" | "else" | "enum" | "extern"
- | "false" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "match" | "mod"
- | "move" | "mut" | "pub" | "ref" | "return" | "self" | "Self" | "static" | "struct"
- | "super" | "trait" | "true" | "type" | "unsafe" | "use" | "where" | "while"
- | "async" | "await" | "dyn" | "abstract" | "become" | "box" | "do" | "final"
- | "macro" | "override" | "priv" | "typeof" | "unsized" | "virtual" | "yield"
- | "try" => format_ident!("r#{}", self),
- _ => format_ident!("{}", self),
+#[cfg(tm_mainline_prod)]
+impl ToUpperCamelCase for str {
+ fn to_upper_camel_case(&self) -> String {
+ use heck::CamelCase;
+ let camel_case = self.to_camel_case();
+ if camel_case.is_empty() {
+ camel_case
+ } else {
+ // PDL identifiers are a-zA-z0-9, so we're dealing with
+ // simple ASCII text.
+ format!("{}{}", &camel_case[..1].to_ascii_uppercase(), &camel_case[1..])
}
}
}
@@ -85,7 +84,7 @@ pub fn mask_bits(n: usize, suffix: &str) -> syn::LitInt {
}
fn generate_packet_size_getter<'a>(
- scope: &analyzer::Scope<'a>,
+ scope: &lint::Scope<'a>,
fields: impl Iterator<Item = &'a analyzer_ast::Field>,
is_packet: bool,
) -> (usize, proc_macro2::TokenStream) {
@@ -98,7 +97,7 @@ fn generate_packet_size_getter<'a>(
continue;
}
- let decl = scope.get_type_declaration(field);
+ let decl = scope.get_field_declaration(field);
dynamic_widths.push(match &field.desc {
ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body { .. } => {
if is_packet {
@@ -112,11 +111,11 @@ fn generate_packet_size_getter<'a>(
}
}
ast::FieldDesc::Typedef { id, .. } => {
- let id = id.to_ident();
+ let id = format_ident!("{id}");
quote!(self.#id.get_size())
}
ast::FieldDesc::Array { id, width, .. } => {
- let id = id.to_ident();
+ let id = format_ident!("{id}");
match &decl {
Some(analyzer_ast::Decl {
desc: ast::DeclDesc::Struct { .. } | ast::DeclDesc::CustomField { .. },
@@ -164,10 +163,7 @@ fn generate_packet_size_getter<'a>(
)
}
-fn top_level_packet<'a>(
- scope: &analyzer::Scope<'a>,
- packet_name: &'a str,
-) -> &'a analyzer_ast::Decl {
+fn top_level_packet<'a>(scope: &lint::Scope<'a>, packet_name: &'a str) -> &'a analyzer_ast::Decl {
let mut decl = scope.typedef[packet_name];
while let ast::DeclDesc::Packet { parent_id: Some(parent_id), .. }
| ast::DeclDesc::Struct { parent_id: Some(parent_id), .. } = &decl.desc
@@ -177,68 +173,74 @@ fn top_level_packet<'a>(
decl
}
-/// Find parent fields which are constrained in child packets.
-///
-/// These fields are the fields which need to be passed in when
-/// parsing a `id` packet since their values are needed for one or
-/// more child packets.
-fn find_constrained_parent_fields<'a>(
- scope: &analyzer::Scope<'a>,
- id: &str,
+/// Find all constrained fields in children of `id`.
+fn find_constrained_fields<'a>(
+ scope: &'a lint::Scope<'a>,
+ id: &'a str,
) -> Vec<&'a analyzer_ast::Field> {
- let all_parent_fields: HashMap<String, &'a analyzer_ast::Field> = HashMap::from_iter(
- scope
- .iter_parent_fields(scope.typedef[id])
- .filter_map(|f| f.id().map(|id| (id.to_string(), f))),
- );
-
let mut fields = Vec::new();
let mut field_names = BTreeSet::new();
- let mut children = scope.iter_children(scope.typedef[id]).collect::<Vec<_>>();
+ let mut children = scope.iter_children(id).collect::<Vec<_>>();
while let Some(child) = children.pop() {
if let ast::DeclDesc::Packet { id, constraints, .. }
| ast::DeclDesc::Struct { id, constraints, .. } = &child.desc
{
+ let packet_scope = &scope.scopes[&scope.typedef[id]];
for constraint in constraints {
- if field_names.insert(&constraint.id)
- && all_parent_fields.contains_key(&constraint.id)
- {
- fields.push(all_parent_fields[&constraint.id]);
+ if field_names.insert(&constraint.id) {
+ fields.push(packet_scope.all_fields[&constraint.id]);
}
}
- children.extend(scope.iter_children(scope.typedef[id]).collect::<Vec<_>>());
+ children.extend(scope.iter_children(id).collect::<Vec<_>>());
}
}
fields
}
+/// Find parent fields which are constrained in child packets.
+///
+/// These fields are the fields which need to be passed in when
+/// parsing a `id` packet since their values are needed for one or
+/// more child packets.
+fn find_constrained_parent_fields<'a>(
+ scope: &'a lint::Scope<'a>,
+ id: &'a str,
+) -> impl Iterator<Item = &'a analyzer_ast::Field> {
+ let packet_scope = &scope.scopes[&scope.typedef[id]];
+ find_constrained_fields(scope, id).into_iter().filter(|field| {
+ let id = field.id().unwrap();
+ packet_scope.all_fields.contains_key(id) && packet_scope.get_packet_field(id).is_none()
+ })
+}
+
/// Generate the declaration and implementation for a data struct.
///
/// This struct will hold the data for a packet or a struct. It knows
/// how to parse and serialize its own fields.
fn generate_data_struct(
- scope: &analyzer::Scope<'_>,
+ scope: &lint::Scope<'_>,
endianness: ast::EndiannessValue,
id: &str,
) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) {
let decl = scope.typedef[id];
+ let packet_scope = &scope.scopes[&decl];
let is_packet = matches!(&decl.desc, ast::DeclDesc::Packet { .. });
let span = format_ident!("bytes");
let serializer_span = format_ident!("buffer");
let mut field_parser = FieldParser::new(scope, endianness, id, &span);
let mut field_serializer = FieldSerializer::new(scope, endianness, id, &serializer_span);
- for field in decl.fields() {
+ for field in packet_scope.iter_fields() {
field_parser.add(field);
field_serializer.add(field);
}
field_parser.done();
let (parse_arg_names, parse_arg_types) = if is_packet {
- let fields = find_constrained_parent_fields(scope, id);
- let names = fields.iter().map(|f| f.id().unwrap().to_ident()).collect::<Vec<_>>();
+ let fields = find_constrained_parent_fields(scope, id).collect::<Vec<_>>();
+ let names = fields.iter().map(|f| format_ident!("{}", f.id().unwrap())).collect::<Vec<_>>();
let types = fields.iter().map(|f| types::rust_type(f)).collect::<Vec<_>>();
(names, types)
} else {
@@ -246,7 +248,7 @@ fn generate_data_struct(
};
let (constant_width, packet_size) =
- generate_packet_size_getter(scope, decl.fields(), is_packet);
+ generate_packet_size_getter(scope, packet_scope.iter_fields(), is_packet);
let conforms = if constant_width == 0 {
quote! { true }
} else {
@@ -255,13 +257,14 @@ fn generate_data_struct(
};
let visibility = if is_packet { quote!() } else { quote!(pub) };
- let has_payload = decl.payload().is_some();
- let has_children = scope.iter_children(decl).next().is_some();
+ let has_payload = packet_scope.get_payload_field().is_some();
+ let has_children = scope.iter_children(id).next().is_some();
- let struct_name = if is_packet { format_ident!("{id}Data") } else { id.to_ident() };
- let fields_with_ids = decl.fields().filter(|f| f.id().is_some()).collect::<Vec<_>>();
+ let struct_name = if is_packet { format_ident!("{id}Data") } else { format_ident!("{id}") };
+ let fields_with_ids =
+ packet_scope.iter_fields().filter(|f| f.id().is_some()).collect::<Vec<_>>();
let mut field_names =
- fields_with_ids.iter().map(|f| f.id().unwrap().to_ident()).collect::<Vec<_>>();
+ fields_with_ids.iter().map(|f| format_ident!("{}", f.id().unwrap())).collect::<Vec<_>>();
let mut field_types = fields_with_ids.iter().map(|f| types::rust_type(f)).collect::<Vec<_>>();
if has_children || has_payload {
if is_packet {
@@ -323,10 +326,26 @@ fn generate_data_struct(
(data_struct_decl, data_struct_impl)
}
+/// Find all parents from `id`.
+///
+/// This includes the `Decl` for `id` itself.
+fn find_parents<'a>(scope: &lint::Scope<'a>, id: &str) -> Vec<&'a analyzer_ast::Decl> {
+ let mut decl = scope.typedef[id];
+ let mut parents = vec![decl];
+ while let ast::DeclDesc::Packet { parent_id: Some(parent_id), .. }
+ | ast::DeclDesc::Struct { parent_id: Some(parent_id), .. } = &decl.desc
+ {
+ decl = scope.typedef[parent_id];
+ parents.push(decl);
+ }
+ parents.reverse();
+ parents
+}
+
/// Turn the constraint into a value (such as `10` or
/// `SomeEnum::Foo`).
pub fn constraint_to_value(
- all_fields: &HashMap<String, &'_ analyzer_ast::Field>,
+ packet_scope: &lint::PacketScope<'_>,
constraint: &ast::Constraint,
) -> proc_macro2::TokenStream {
match constraint {
@@ -337,8 +356,8 @@ pub fn constraint_to_value(
// TODO(mgeisler): include type_id in `ast::Constraint` and
// drop the packet_scope argument.
ast::Constraint { tag_id: Some(tag_id), .. } => {
- let type_id = match &all_fields[&constraint.id].desc {
- ast::FieldDesc::Typedef { type_id, .. } => type_id.to_ident(),
+ let type_id = match &packet_scope.all_fields[&constraint.id].desc {
+ ast::FieldDesc::Typedef { type_id, .. } => format_ident!("{type_id}"),
_ => unreachable!("Invalid constraint: {constraint:?}"),
};
let tag_id = format_ident!("{}", tag_id.to_upper_camel_case());
@@ -350,99 +369,95 @@ pub fn constraint_to_value(
/// Generate code for a `ast::Decl::Packet`.
fn generate_packet_decl(
- scope: &analyzer::Scope<'_>,
+ scope: &lint::Scope<'_>,
endianness: ast::EndiannessValue,
id: &str,
) -> proc_macro2::TokenStream {
- let decl = scope.typedef[id];
+ let packet_scope = &scope.scopes[&scope.typedef[id]];
+
let top_level = top_level_packet(scope, id);
let top_level_id = top_level.id().unwrap();
- let top_level_packet = top_level_id.to_ident();
+ let top_level_packet = format_ident!("{top_level_id}");
let top_level_data = format_ident!("{top_level_id}Data");
- let top_level_id_lower = top_level_id.to_lowercase().to_ident();
+ let top_level_id_lower = format_ident!("{}", top_level_id.to_lowercase());
// TODO(mgeisler): use the convert_case crate to convert between
// `FooBar` and `foo_bar` in the code below.
let span = format_ident!("bytes");
- let id_lower = id.to_lowercase().to_ident();
- let id_packet = id.to_ident();
+ let id_lower = format_ident!("{}", id.to_lowercase());
+ let id_packet = format_ident!("{id}");
let id_child = format_ident!("{id}Child");
let id_data_child = format_ident!("{id}DataChild");
let id_builder = format_ident!("{id}Builder");
- let mut parents = scope.iter_parents_and_self(decl).collect::<Vec<_>>();
- parents.reverse();
-
+ let parents = find_parents(scope, id);
let parent_ids = parents.iter().map(|p| p.id().unwrap()).collect::<Vec<_>>();
- let parent_shifted_ids = parent_ids.iter().skip(1).map(|id| id.to_ident());
+ let parent_shifted_ids = parent_ids.iter().skip(1).map(|id| format_ident!("{id}"));
let parent_lower_ids =
- parent_ids.iter().map(|id| id.to_lowercase().to_ident()).collect::<Vec<_>>();
+ parent_ids.iter().map(|id| format_ident!("{}", id.to_lowercase())).collect::<Vec<_>>();
let parent_shifted_lower_ids = parent_lower_ids.iter().skip(1).collect::<Vec<_>>();
- let parent_packet = parent_ids.iter().map(|id| id.to_ident());
+ let parent_packet = parent_ids.iter().map(|id| format_ident!("{id}"));
let parent_data = parent_ids.iter().map(|id| format_ident!("{id}Data"));
let parent_data_child = parent_ids.iter().map(|id| format_ident!("{id}DataChild"));
let all_fields = {
- let mut fields = scope.iter_fields(decl).filter(|d| d.id().is_some()).collect::<Vec<_>>();
+ let mut fields = packet_scope.all_fields.values().collect::<Vec<_>>();
fields.sort_by_key(|f| f.id());
fields
};
- let all_named_fields =
- HashMap::from_iter(all_fields.iter().map(|f| (f.id().unwrap().to_string(), *f)));
-
- let all_field_names = all_fields.iter().map(|f| f.id().unwrap().to_ident()).collect::<Vec<_>>();
+ let all_field_names =
+ all_fields.iter().map(|f| format_ident!("{}", f.id().unwrap())).collect::<Vec<_>>();
let all_field_types = all_fields.iter().map(|f| types::rust_type(f)).collect::<Vec<_>>();
let all_field_borrows =
all_fields.iter().map(|f| types::rust_borrow(f, scope)).collect::<Vec<_>>();
- let all_field_getter_names =
- all_fields.iter().map(|f| format_ident!("get_{}", f.id().unwrap()));
+ let all_field_getter_names = all_field_names.iter().map(|id| format_ident!("get_{id}"));
let all_field_self_field = all_fields.iter().map(|f| {
for (parent, parent_id) in parents.iter().zip(parent_lower_ids.iter()) {
- if parent.fields().any(|ff| ff.id() == f.id()) {
+ if scope.scopes[parent].iter_fields().any(|ff| ff.id() == f.id()) {
return quote!(self.#parent_id);
}
}
unreachable!("Could not find {f:?} in parent chain");
});
- let all_constraints = HashMap::<String, _>::from_iter(
- scope.iter_constraints(decl).map(|c| (c.id.to_string(), c)),
- );
-
let unconstrained_fields = all_fields
.iter()
- .filter(|f| !all_constraints.contains_key(f.id().unwrap()))
+ .filter(|f| !packet_scope.all_constraints.contains_key(f.id().unwrap()))
+ .collect::<Vec<_>>();
+ let unconstrained_field_names = unconstrained_fields
+ .iter()
+ .map(|f| format_ident!("{}", f.id().unwrap()))
.collect::<Vec<_>>();
- let unconstrained_field_names =
- unconstrained_fields.iter().map(|f| f.id().unwrap().to_ident()).collect::<Vec<_>>();
let unconstrained_field_types = unconstrained_fields.iter().map(|f| types::rust_type(f));
let rev_parents = parents.iter().rev().collect::<Vec<_>>();
let builder_assignments = rev_parents.iter().enumerate().map(|(idx, parent)| {
let parent_id = parent.id().unwrap();
- let parent_id_lower = parent_id.to_lowercase().to_ident();
+ let parent_id_lower = format_ident!("{}", parent_id.to_lowercase());
let parent_data = format_ident!("{parent_id}Data");
let parent_data_child = format_ident!("{parent_id}DataChild");
+ let parent_packet_scope = &scope.scopes[&scope.typedef[parent_id]];
let named_fields = {
- let mut names = parent.fields().filter_map(ast::Field::id).collect::<Vec<_>>();
+ let mut names =
+ parent_packet_scope.iter_fields().filter_map(ast::Field::id).collect::<Vec<_>>();
names.sort_unstable();
names
};
- let mut field = named_fields.iter().map(|id| id.to_ident()).collect::<Vec<_>>();
+ let mut field = named_fields.iter().map(|id| format_ident!("{id}")).collect::<Vec<_>>();
let mut value = named_fields
.iter()
- .map(|&id| match all_constraints.get(id) {
- Some(constraint) => constraint_to_value(&all_named_fields, constraint),
+ .map(|&id| match packet_scope.all_constraints.get(id) {
+ Some(constraint) => constraint_to_value(packet_scope, constraint),
None => {
- let id = id.to_ident();
+ let id = format_ident!("{id}");
quote!(self.#id)
}
})
.collect::<Vec<_>>();
- if parent.payload().is_some() {
+ if parent_packet_scope.get_payload_field().is_some() {
field.push(format_ident!("child"));
if idx == 0 {
// Top-most parent, the child is simply created from
@@ -456,13 +471,13 @@ fn generate_packet_decl(
} else {
// Child is created from the previous parent.
let prev_parent_id = rev_parents[idx - 1].id().unwrap();
- let prev_parent_id_lower = prev_parent_id.to_lowercase().to_ident();
- let prev_parent_id = prev_parent_id.to_ident();
+ let prev_parent_id_lower = format_ident!("{}", prev_parent_id.to_lowercase());
+ let prev_parent_id = format_ident!("{prev_parent_id}");
value.push(quote! {
#parent_data_child::#prev_parent_id(#prev_parent_id_lower)
});
}
- } else if scope.iter_children(parent).next().is_some() {
+ } else if scope.iter_children(parent_id).next().is_some() {
field.push(format_ident!("child"));
value.push(quote! { #parent_data_child::None });
}
@@ -474,10 +489,11 @@ fn generate_packet_decl(
}
});
- let children = scope.iter_children(decl).collect::<Vec<_>>();
- let has_payload = decl.payload().is_some();
+ let children = scope.iter_children(id).collect::<Vec<_>>();
+ let has_payload = packet_scope.get_payload_field().is_some();
let has_children_or_payload = !children.is_empty() || has_payload;
- let child = children.iter().map(|child| child.id().unwrap().to_ident()).collect::<Vec<_>>();
+ let child =
+ children.iter().map(|child| format_ident!("{}", child.id().unwrap())).collect::<Vec<_>>();
let child_data = child.iter().map(|child| format_ident!("{child}Data")).collect::<Vec<_>>();
let get_payload = (children.is_empty() && has_payload).then(|| {
quote! {
@@ -539,7 +555,8 @@ fn generate_packet_decl(
}
});
- let ancestor_packets = parent_ids[..parent_ids.len() - 1].iter().map(|id| id.to_ident());
+ let ancestor_packets =
+ parent_ids[..parent_ids.len() - 1].iter().map(|id| format_ident!("{id}"));
let impl_from_and_try_from = (top_level_id != id).then(|| {
quote! {
#(
@@ -672,7 +689,7 @@ fn generate_packet_decl(
/// Generate code for a `ast::Decl::Struct`.
fn generate_struct_decl(
- scope: &analyzer::Scope<'_>,
+ scope: &lint::Scope<'_>,
endianness: ast::EndiannessValue,
id: &str,
) -> proc_macro2::TokenStream {
@@ -693,26 +710,20 @@ fn generate_struct_decl(
/// an additional Unknown case for unmatched valued. Complete
/// enums (where the full range of values is covered) are
/// automatically closed.
-fn generate_enum_decl(id: &str, tags: &[ast::Tag], width: usize) -> proc_macro2::TokenStream {
- // Determine if the enum is open, i.e. a default tag is defined.
- fn enum_default_tag(tags: &[ast::Tag]) -> Option<ast::TagOther> {
- tags.iter()
- .filter_map(|tag| match tag {
- ast::Tag::Other(tag) => Some(tag.clone()),
- _ => None,
- })
- .next()
- }
-
+fn generate_enum_decl(
+ id: &str,
+ tags: &[ast::Tag],
+ width: usize,
+ open: bool,
+) -> proc_macro2::TokenStream {
// Determine if the enum is complete, i.e. all values in the backing
// integer range have a matching tag in the original declaration.
fn enum_is_complete(tags: &[ast::Tag], max: usize) -> bool {
let mut ranges = tags
.iter()
- .filter_map(|tag| match tag {
- ast::Tag::Value(tag) => Some((tag.value, tag.value)),
- ast::Tag::Range(tag) => Some(tag.range.clone().into_inner()),
- _ => None,
+ .map(|tag| match tag {
+ ast::Tag::Value(tag) => (tag.value, tag.value),
+ ast::Tag::Range(tag) => tag.range.clone().into_inner(),
})
.collect::<Vec<_>>();
ranges.sort_unstable();
@@ -727,7 +738,8 @@ fn generate_enum_decl(id: &str, tags: &[ast::Tag], width: usize) -> proc_macro2:
})
}
- // Determine if the enum is primitive, i.e. does not contain any tag range.
+ // Determine if the enum is primitive, i.e. does not contain any
+ // tag range.
fn enum_is_primitive(tags: &[ast::Tag]) -> bool {
tags.iter().all(|tag| matches!(tag, ast::Tag::Value(_)))
}
@@ -756,15 +768,13 @@ fn generate_enum_decl(id: &str, tags: &[ast::Tag], width: usize) -> proc_macro2:
let backing_type = types::Integer::new(width);
let backing_type_str = proc_macro2::Literal::string(&format!("u{}", backing_type.width));
let range_max = scalar_max(width);
- let default_tag = enum_default_tag(tags);
- let is_open = default_tag.is_some();
let is_complete = enum_is_complete(tags, scalar_max(width));
let is_primitive = enum_is_primitive(tags);
- let name = id.to_ident();
+ let name = format_ident!("{id}");
// Generate the variant cases for the enum declaration.
// Tags declared in ranges are flattened in the same declaration.
- let use_variant_values = is_primitive && (is_complete || !is_open);
+ let use_variant_values = is_primitive && (is_complete || !open);
let repr_u64 = use_variant_values.then(|| quote! { #[repr(u64)] });
let mut variants = vec![];
for tag in tags.iter() {
@@ -780,7 +790,6 @@ fn generate_enum_decl(id: &str, tags: &[ast::Tag], width: usize) -> proc_macro2:
let id = format_tag_ident(&tag.id);
variants.push(quote! { #id(Private<#backing_type>) })
}
- ast::Tag::Other(_) => (),
}
}
@@ -804,7 +813,6 @@ fn generate_enum_decl(id: &str, tags: &[ast::Tag], width: usize) -> proc_macro2:
let end = format_value(*tag.range.end());
from_cases.push(quote! { #start ..= #end => Ok(#name::#id(Private(value))) })
}
- ast::Tag::Other(_) => (),
}
}
@@ -826,22 +834,19 @@ fn generate_enum_decl(id: &str, tags: &[ast::Tag], width: usize) -> proc_macro2:
let id = format_tag_ident(&tag.id);
into_cases.push(quote! { #name::#id(Private(value)) => *value })
}
- ast::Tag::Other(_) => (),
}
}
// Generate a default case if the enum is open and incomplete.
- if !is_complete && is_open {
- let unknown_id = format_tag_ident(&default_tag.unwrap().id);
- let range_max = format_value(range_max);
- variants.push(quote! { #unknown_id(Private<#backing_type>) });
- from_cases.push(quote! { 0..=#range_max => Ok(#name::#unknown_id(Private(value))) });
- into_cases.push(quote! { #name::#unknown_id(Private(value)) => *value });
+ if !is_complete && open {
+ variants.push(quote! { Unknown(Private<#backing_type>) });
+ from_cases.push(quote! { 0..#range_max => Ok(#name::Unknown(Private(value))) });
+ into_cases.push(quote! { #name::Unknown(Private(value)) => *value });
}
// Generate an error case if the enum size is lower than the backing
// type size, or if the enum is closed or incomplete.
- if backing_type.width != width || (!is_complete && !is_open) {
+ if backing_type.width != width || (!is_complete && !open) {
from_cases.push(quote! { _ => Err(value) });
}
@@ -902,7 +907,7 @@ fn generate_enum_decl(id: &str, tags: &[ast::Tag], width: usize) -> proc_macro2:
/// * `id` - Enum identifier.
/// * `width` - Width of the backing type of the enum, in bits.
fn generate_custom_field_decl(id: &str, width: usize) -> proc_macro2::TokenStream {
- let id = id.to_ident();
+ let id = format_ident!("{}", id);
let backing_type = types::Integer::new(width);
let backing_type_str = proc_macro2::Literal::string(&format!("u{}", backing_type.width));
let max_value = mask_bits(width, &format!("u{}", backing_type.width));
@@ -959,7 +964,7 @@ fn generate_custom_field_decl(id: &str, width: usize) -> proc_macro2::TokenStrea
}
fn generate_decl(
- scope: &analyzer::Scope<'_>,
+ scope: &lint::Scope<'_>,
file: &analyzer_ast::File,
decl: &analyzer_ast::Decl,
) -> proc_macro2::TokenStream {
@@ -973,7 +978,7 @@ fn generate_decl(
// implement the recursive (de)serialization.
generate_struct_decl(scope, file.endianness.value, id)
}
- ast::DeclDesc::Enum { id, tags, width } => generate_enum_decl(id, tags, *width),
+ ast::DeclDesc::Enum { id, tags, width } => generate_enum_decl(id, tags, *width, false),
ast::DeclDesc::CustomField { id, width: Some(width), .. } => {
generate_custom_field_decl(id, *width)
}
@@ -989,7 +994,7 @@ pub fn generate(sources: &ast::SourceDatabase, file: &analyzer_ast::File) -> Str
let source = sources.get(file.file).expect("could not read source");
let preamble = preamble::generate(Path::new(source.name()));
- let scope = analyzer::Scope::new(file).expect("could not create scope");
+ let scope = lint::Scope::new(file);
let decls = file.declarations.iter().map(|decl| generate_decl(&scope, file, decl));
let code = quote! {
#preamble
@@ -1045,10 +1050,9 @@ mod tests {
}
";
let file = parse_str(code);
- let scope = analyzer::Scope::new(&file).unwrap();
+ let scope = lint::Scope::new(&file);
let find_fields = |id| {
find_constrained_parent_fields(&scope, id)
- .iter()
.map(|field| field.id().unwrap())
.collect::<Vec<_>>()
};
@@ -1116,18 +1120,14 @@ mod tests {
test_pdl!(
enum_declaration,
r#"
- enum IncompleteTruncatedClosed : 3 {
- A = 0,
- B = 1,
- }
-
- enum IncompleteTruncatedOpen : 3 {
+ // Should generate unknown case.
+ enum IncompleteTruncated : 3 {
A = 0,
B = 1,
- UNKNOWN = ..
}
- enum IncompleteTruncatedClosedWithRange : 3 {
+ // Should generate unknown case.
+ enum IncompleteTruncatedWithRange : 3 {
A = 0,
B = 1..6 {
X = 1,
@@ -1135,15 +1135,7 @@ mod tests {
}
}
- enum IncompleteTruncatedOpenWithRange : 3 {
- A = 0,
- B = 1..6 {
- X = 1,
- Y = 2,
- },
- UNKNOWN = ..
- }
-
+ // Should generate unreachable case.
enum CompleteTruncated : 3 {
A = 0,
B = 1,
@@ -1155,6 +1147,7 @@ mod tests {
H = 7,
}
+ // Should generate unreachable case.
enum CompleteTruncatedWithRange : 3 {
A = 0,
B = 1..7 {
@@ -1163,6 +1156,7 @@ mod tests {
}
}
+ // Should generate no unknown or unreachable case.
enum CompleteWithRange : 8 {
A = 0,
B = 1,
@@ -1528,15 +1522,6 @@ mod tests {
"
);
- test_pdl!(
- reserved_identifier,
- "
- packet Test {
- type: 8,
- }
- "
- );
-
// TODO(mgeisler): enable this test when we have an approach to
// struct fields with parents.
//
diff --git a/src/backends/rust/parser.rs b/src/backends/rust/parser.rs
index f837082..203a19b 100644
--- a/src/backends/rust/parser.rs
+++ b/src/backends/rust/parser.rs
@@ -14,12 +14,11 @@
use crate::analyzer::ast as analyzer_ast;
use crate::backends::rust::{
- constraint_to_value, find_constrained_parent_fields, mask_bits, types, ToIdent,
- ToUpperCamelCase,
+ constraint_to_value, find_constrained_parent_fields, mask_bits, types, ToUpperCamelCase,
};
-use crate::{analyzer, ast};
+use crate::{ast, lint};
use quote::{format_ident, quote};
-use std::collections::{BTreeSet, HashMap};
+use std::collections::BTreeSet;
fn size_field_ident(id: &str) -> proc_macro2::Ident {
format_ident!("{}_size", id.trim_matches('_'))
@@ -32,9 +31,8 @@ struct BitField<'a> {
}
pub struct FieldParser<'a> {
- scope: &'a analyzer::Scope<'a>,
+ scope: &'a lint::Scope<'a>,
endianness: ast::EndiannessValue,
- decl: &'a analyzer_ast::Decl,
packet_name: &'a str,
span: &'a proc_macro2::Ident,
chunk: Vec<BitField<'a>>,
@@ -45,7 +43,7 @@ pub struct FieldParser<'a> {
impl<'a> FieldParser<'a> {
pub fn new(
- scope: &'a analyzer::Scope<'a>,
+ scope: &'a lint::Scope<'a>,
endianness: ast::EndiannessValue,
packet_name: &'a str,
span: &'a proc_macro2::Ident,
@@ -53,7 +51,6 @@ impl<'a> FieldParser<'a> {
FieldParser {
scope,
endianness,
- decl: scope.typedef[packet_name],
packet_name,
span,
chunk: Vec::new(),
@@ -73,7 +70,7 @@ impl<'a> FieldParser<'a> {
type_id.as_deref(),
*size,
field.annot.padded_size,
- self.scope.get_type_declaration(field),
+ self.scope.get_field_declaration(field),
),
ast::FieldDesc::Typedef { id, type_id } => self.add_typedef_field(id, type_id),
ast::FieldDesc::Payload { size_modifier, .. } => {
@@ -142,20 +139,19 @@ impl<'a> FieldParser<'a> {
self.code.push(match &field.desc {
ast::FieldDesc::Scalar { id, .. } => {
- let id = id.to_ident();
+ let id = format_ident!("{id}");
quote! {
let #id = #v;
}
}
ast::FieldDesc::FixedEnum { enum_id, tag_id, .. } => {
- let enum_id = enum_id.to_ident();
- let tag_id = tag_id.to_upper_camel_case().to_ident();
+ let enum_id = format_ident!("{enum_id}");
+ let tag_id = format_ident!("{}", tag_id.to_upper_camel_case());
quote! {
- let fixed_value = #v;
- if fixed_value != #value_type::from(#enum_id::#tag_id) {
+ if #v != #value_type::from(#enum_id::#tag_id) {
return Err(Error::InvalidFixedValue {
expected: #value_type::from(#enum_id::#tag_id) as u64,
- actual: fixed_value as u64,
+ actual: #v as u64,
});
}
}
@@ -163,11 +159,10 @@ impl<'a> FieldParser<'a> {
ast::FieldDesc::FixedScalar { value, .. } => {
let value = proc_macro2::Literal::usize_unsuffixed(*value);
quote! {
- let fixed_value = #v;
if #v != #value {
return Err(Error::InvalidFixedValue {
expected: #value,
- actual: fixed_value as u64,
+ actual: #v as u64,
});
}
}
@@ -176,13 +171,13 @@ impl<'a> FieldParser<'a> {
let field_name = id;
let type_name = type_id;
let packet_name = &self.packet_name;
- let id = id.to_ident();
- let type_id = type_id.to_ident();
+ let id = format_ident!("{id}");
+ let type_id = format_ident!("{type_id}");
quote! {
- let #id = #type_id::try_from(#v).map_err(|unknown_val| Error::InvalidEnumValueError {
+ let #id = #type_id::try_from(#v).map_err(|_| Error::InvalidEnumValueError {
obj: #packet_name.to_string(),
field: #field_name.to_string(),
- value: unknown_val as u64,
+ value: #v as u64,
type_: #type_name.to_string(),
})?;
}
@@ -221,23 +216,27 @@ impl<'a> FieldParser<'a> {
self.shift = 0;
}
+ fn packet_scope(&self) -> Option<&lint::PacketScope> {
+ self.scope.scopes.get(self.scope.typedef.get(self.packet_name)?)
+ }
+
fn find_count_field(&self, id: &str) -> Option<proc_macro2::Ident> {
- match self.decl.array_size(id)?.desc {
+ match self.packet_scope()?.get_array_size_field(id)?.desc {
ast::FieldDesc::Count { .. } => Some(format_ident!("{id}_count")),
_ => None,
}
}
fn find_size_field(&self, id: &str) -> Option<proc_macro2::Ident> {
- match self.decl.array_size(id)?.desc {
+ match self.packet_scope()?.get_array_size_field(id)?.desc {
ast::FieldDesc::Size { .. } => Some(size_field_ident(id)),
_ => None,
}
}
fn payload_field_offset_from_end(&self) -> Option<usize> {
- let decl = self.scope.typedef[self.packet_name];
- let mut fields = decl.fields();
+ let packet_scope = self.packet_scope().unwrap();
+ let mut fields = packet_scope.iter_fields();
fields.find(|f| {
matches!(f.desc, ast::FieldDesc::Body { .. } | ast::FieldDesc::Payload { .. })
})?;
@@ -328,7 +327,7 @@ impl<'a> FieldParser<'a> {
None => self.span.clone(),
};
- let id = id.to_ident();
+ let id = format_ident!("{id}");
let parse_element = self.parse_array_element(&span, width, type_id, decl);
match (element_width, &array_shape) {
@@ -469,8 +468,8 @@ impl<'a> FieldParser<'a> {
}
let span = self.span;
- let id = id.to_ident();
- let type_id = type_id.to_ident();
+ let id = format_ident!("{id}");
+ let type_id = format_ident!("{type_id}");
self.code.push(match decl.annot.size {
analyzer_ast::Size::Unknown | analyzer_ast::Size::Dynamic => quote! {
@@ -511,7 +510,8 @@ impl<'a> FieldParser<'a> {
/// Parse body and payload fields.
fn add_payload_field(&mut self, size_modifier: Option<&str>) {
let span = self.span;
- let payload_size_field = self.decl.payload_size();
+ let packet_scope = self.packet_scope().unwrap();
+ let payload_size_field = packet_scope.get_payload_size_field();
let offset_from_end = self.payload_field_offset_from_end();
if size_modifier.is_some() {
@@ -597,19 +597,19 @@ impl<'a> FieldParser<'a> {
if let Some(ast::DeclDesc::Enum { id, width, .. }) = decl.map(|decl| &decl.desc) {
let get_uint = types::get_uint(self.endianness, *width, span);
- let type_id = id.to_ident();
+ let type_id = format_ident!("{id}");
let packet_name = &self.packet_name;
return quote! {
- #type_id::try_from(#get_uint).map_err(|unknown_val| Error::InvalidEnumValueError {
+ #type_id::try_from(#get_uint).map_err(|_| Error::InvalidEnumValueError {
obj: #packet_name.to_string(),
field: String::new(), // TODO(mgeisler): fill out or remove
- value: unknown_val as u64,
+ value: 0,
type_: #id.to_string(),
})
};
}
- let type_id = type_id.unwrap().to_ident();
+ let type_id = format_ident!("{}", type_id.unwrap());
quote! {
#type_id::parse_inner(#span)
}
@@ -621,15 +621,12 @@ impl<'a> FieldParser<'a> {
return; // Structs don't parse the child structs recursively.
}
- let children = self.scope.iter_children(decl).collect::<Vec<_>>();
- if children.is_empty() && self.decl.payload().is_none() {
+ let packet_scope = &self.scope.scopes[&decl];
+ let children = self.scope.iter_children(self.packet_name).collect::<Vec<_>>();
+ if children.is_empty() && packet_scope.get_payload_field().is_none() {
return;
}
- let all_fields = HashMap::<String, _>::from_iter(
- self.scope.iter_fields(decl).filter_map(|f| f.id().map(|id| (id.to_string(), f))),
- );
-
// Gather fields that are constrained in immediate child declarations.
// Keep the fields sorted by name.
// TODO: fields that are only matched in grand children will not be included.
@@ -642,11 +639,10 @@ impl<'a> FieldParser<'a> {
let mut child_parse_args = Vec::new();
let mut child_ids_data = Vec::new();
let mut child_ids = Vec::new();
-
let get_constraint_value = |mut constraints: std::slice::Iter<'_, ast::Constraint>,
id: &str|
-> Option<proc_macro2::TokenStream> {
- constraints.find(|c| c.id == id).map(|c| constraint_to_value(&all_fields, c))
+ constraints.find(|c| c.id == id).map(|c| constraint_to_value(packet_scope, c))
};
for child in children.iter() {
@@ -677,17 +673,16 @@ impl<'a> FieldParser<'a> {
.collect::<Vec<_>>();
let fields = find_constrained_parent_fields(self.scope, child.id().unwrap())
- .iter()
- .map(|field| field.id().unwrap().to_ident())
- .collect::<Vec<_>>();
+ .map(|field| format_ident!("{}", field.id().unwrap()));
match_values.push(quote!( (#(#tuple_values),*) ));
child_parse_args.push(quote!( #(, #fields)*));
child_ids_data.push(format_ident!("{}Data", child.id().unwrap()));
- child_ids.push(child.id().unwrap().to_ident());
+ child_ids.push(format_ident!("{}", child.id().unwrap()));
}
- let constrained_field_idents = constrained_fields.iter().map(|field| field.to_ident());
+ let constrained_field_idents =
+ constrained_fields.iter().map(|field| format_ident!("{field}"));
let packet_data_child = format_ident!("{}DataChild", self.packet_name);
// Parsing of packet children requires having a payload field;
@@ -755,7 +750,7 @@ mod tests {
}
";
let file = parse_str(code);
- let scope = analyzer::Scope::new(&file).unwrap();
+ let scope = lint::Scope::new(&file);
let span = format_ident!("bytes");
let parser = FieldParser::new(&scope, file.endianness.value, "P", &span);
assert_eq!(parser.find_size_field("a"), None);
@@ -772,7 +767,7 @@ mod tests {
}
";
let file = parse_str(code);
- let scope = analyzer::Scope::new(&file).unwrap();
+ let scope = lint::Scope::new(&file);
let span = format_ident!("bytes");
let parser = FieldParser::new(&scope, file.endianness.value, "P", &span);
assert_eq!(parser.find_size_field("b"), None);
@@ -789,7 +784,7 @@ mod tests {
}
";
let file = parse_str(code);
- let scope = analyzer::Scope::new(&file).unwrap();
+ let scope = lint::Scope::new(&file);
let span = format_ident!("bytes");
let parser = FieldParser::new(&scope, file.endianness.value, "P", &span);
assert_eq!(parser.find_size_field("c"), Some(format_ident!("c_size")));
diff --git a/src/backends/rust/serializer.rs b/src/backends/rust/serializer.rs
index 345e98a..497936c 100644
--- a/src/backends/rust/serializer.rs
+++ b/src/backends/rust/serializer.rs
@@ -13,8 +13,8 @@
// limitations under the License.
use crate::analyzer::ast as analyzer_ast;
-use crate::backends::rust::{mask_bits, types, ToIdent, ToUpperCamelCase};
-use crate::{analyzer, ast};
+use crate::backends::rust::{mask_bits, types, ToUpperCamelCase};
+use crate::{ast, lint};
use quote::{format_ident, quote};
/// A single bit-field value.
@@ -25,7 +25,7 @@ struct BitField {
}
pub struct FieldSerializer<'a> {
- scope: &'a analyzer::Scope<'a>,
+ scope: &'a lint::Scope<'a>,
endianness: ast::EndiannessValue,
packet_name: &'a str,
span: &'a proc_macro2::Ident,
@@ -36,7 +36,7 @@ pub struct FieldSerializer<'a> {
impl<'a> FieldSerializer<'a> {
pub fn new(
- scope: &'a analyzer::Scope<'a>,
+ scope: &'a lint::Scope<'a>,
endianness: ast::EndiannessValue,
packet_name: &'a str,
span: &'a proc_macro2::Ident,
@@ -59,7 +59,7 @@ impl<'a> FieldSerializer<'a> {
id,
*width,
field.annot.padded_size,
- self.scope.get_type_declaration(field),
+ self.scope.get_field_declaration(field),
),
ast::FieldDesc::Typedef { id, type_id } => {
self.add_typedef_field(id, type_id);
@@ -79,7 +79,7 @@ impl<'a> FieldSerializer<'a> {
match &field.desc {
ast::FieldDesc::Scalar { id, width } => {
- let field_name = id.to_ident();
+ let field_name = format_ident!("{id}");
let field_type = types::Integer::new(*width);
if field_type.width > *width {
let packet_name = &self.packet_name;
@@ -97,7 +97,7 @@ impl<'a> FieldSerializer<'a> {
}
ast::FieldDesc::FixedEnum { enum_id, tag_id, .. } => {
let field_type = types::Integer::new(width);
- let enum_id = enum_id.to_ident();
+ let enum_id = format_ident!("{enum_id}");
let tag_id = format_ident!("{}", tag_id.to_upper_camel_case());
self.chunk.push(BitField {
value: quote!(#field_type::from(#enum_id::#tag_id)),
@@ -111,7 +111,7 @@ impl<'a> FieldSerializer<'a> {
self.chunk.push(BitField { value: quote!(#value), field_type, shift });
}
ast::FieldDesc::Typedef { id, .. } => {
- let field_name = id.to_ident();
+ let field_name = format_ident!("{id}");
let field_type = types::Integer::new(width);
self.chunk.push(BitField {
value: quote!(#field_type::from(self.#field_name)),
@@ -127,21 +127,14 @@ impl<'a> FieldSerializer<'a> {
let max_value = mask_bits(*width, "usize");
let decl = self.scope.typedef.get(self.packet_name).unwrap();
- let value_field = self
- .scope
- .iter_fields(decl)
- .find(|field| match &field.desc {
- ast::FieldDesc::Payload { .. } => field_id == "_payload_",
- ast::FieldDesc::Body { .. } => field_id == "_body_",
- _ => field.id() == Some(field_id),
- })
- .unwrap();
+ let scope = self.scope.scopes.get(decl).unwrap();
+ let value_field = scope.get_packet_field(field_id).unwrap();
- let field_name = field_id.to_ident();
+ let field_name = format_ident!("{field_id}");
let field_type = types::Integer::new(*width);
// TODO: size modifier
- let value_field_decl = self.scope.get_type_declaration(value_field);
+ let value_field_decl = self.scope.get_field_declaration(value_field);
let field_size_name = format_ident!("{field_id}_size");
let array_size = match (&value_field.desc, value_field_decl.map(|decl| &decl.desc))
@@ -190,7 +183,7 @@ impl<'a> FieldSerializer<'a> {
});
}
ast::FieldDesc::Count { field_id, width, .. } => {
- let field_name = field_id.to_ident();
+ let field_name = format_ident!("{field_id}");
let field_type = types::Integer::new(*width);
if field_type.width > *width {
let packet_name = &self.packet_name;
@@ -296,7 +289,7 @@ impl<'a> FieldSerializer<'a> {
}
};
- let id = id.to_ident();
+ let id = format_ident!("{id}");
self.code.push(match padding_size {
Some(padding_size) =>
@@ -327,7 +320,7 @@ impl<'a> FieldSerializer<'a> {
panic!("Derived struct used in typedef field");
}
- let id = id.to_ident();
+ let id = format_ident!("{id}");
let span = format_ident!("{}", self.span);
self.code.push(match &decl.desc {
@@ -361,8 +354,8 @@ impl<'a> FieldSerializer<'a> {
let child_ids = self
.scope
- .iter_children(decl)
- .map(|child| child.id().unwrap().to_ident())
+ .iter_children(self.packet_name)
+ .map(|child| format_ident!("{}", child.id().unwrap()))
.collect::<Vec<_>>();
let span = format_ident!("{}", self.span);
diff --git a/src/backends/rust/types.rs b/src/backends/rust/types.rs
index b5f2b91..5b1767d 100644
--- a/src/backends/rust/types.rs
+++ b/src/backends/rust/types.rs
@@ -15,8 +15,7 @@
//! Utility functions for dealing with Rust integer types.
use crate::analyzer::ast as analyzer_ast;
-use crate::backends::rust::ToIdent;
-use crate::{analyzer, ast};
+use crate::{ast, lint};
use quote::{format_ident, quote};
/// A Rust integer type such as `u8`.
@@ -56,7 +55,7 @@ pub fn rust_type(field: &analyzer_ast::Field) -> proc_macro2::TokenStream {
quote!(#field_type)
}
ast::FieldDesc::Typedef { type_id, .. } => {
- let field_type = type_id.to_ident();
+ let field_type = format_ident!("{type_id}");
quote!(#field_type)
}
ast::FieldDesc::Array { width: Some(width), size: Some(size), .. } => {
@@ -69,12 +68,12 @@ pub fn rust_type(field: &analyzer_ast::Field) -> proc_macro2::TokenStream {
quote!(Vec<#field_type>)
}
ast::FieldDesc::Array { type_id: Some(type_id), size: Some(size), .. } => {
- let field_type = type_id.to_ident();
+ let field_type = format_ident!("{type_id}");
let size = proc_macro2::Literal::usize_unsuffixed(*size);
quote!([#field_type; #size])
}
ast::FieldDesc::Array { type_id: Some(type_id), size: None, .. } => {
- let field_type = type_id.to_ident();
+ let field_type = format_ident!("{type_id}");
quote!(Vec<#field_type>)
}
//ast::Field::Size { .. } | ast::Field::Count { .. } => quote!(),
@@ -84,7 +83,7 @@ pub fn rust_type(field: &analyzer_ast::Field) -> proc_macro2::TokenStream {
pub fn rust_borrow(
field: &analyzer_ast::Field,
- scope: &analyzer::Scope<'_>,
+ scope: &lint::Scope<'_>,
) -> proc_macro2::TokenStream {
match &field.desc {
ast::FieldDesc::Scalar { .. } => quote!(),
diff --git a/src/lib.rs b/src/lib.rs
index a57ee58..cd384bc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -17,6 +17,7 @@
pub mod analyzer;
pub mod ast;
pub mod backends;
+pub mod lint;
pub mod parser;
#[cfg(test)]
pub mod test_utils;
diff --git a/src/lint.rs b/src/lint.rs
new file mode 100644
index 0000000..421f364
--- /dev/null
+++ b/src/lint.rs
@@ -0,0 +1,259 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use std::collections::HashMap;
+
+use crate::analyzer::ast as analyzer_ast;
+use crate::ast::*;
+
+/// Gather information about the full AST.
+#[derive(Debug)]
+pub struct Scope<'d> {
+ // Original file.
+ pub file: &'d analyzer_ast::File,
+
+ // Collection of Group, Packet, Enum, Struct, Checksum, and CustomField declarations.
+ pub typedef: HashMap<String, &'d analyzer_ast::Decl>,
+
+ // Collection of Packet, Struct, and Group scope declarations.
+ pub scopes: HashMap<&'d analyzer_ast::Decl, PacketScope<'d>>,
+}
+
+/// Gather information about a Packet, Struct, or Group declaration.
+#[derive(Debug)]
+pub struct PacketScope<'d> {
+ // Original decl.
+ decl: &'d analyzer_ast::Decl,
+
+ // Local and inherited field declarations. Only named fields are preserved.
+ // Saved here for reference for parent constraint resolving.
+ pub all_fields: HashMap<String, &'d analyzer_ast::Field>,
+
+ // Local and inherited constraint declarations.
+ // Saved here for constraint conflict checks.
+ pub all_constraints: HashMap<String, &'d Constraint>,
+}
+
+impl<'d> std::hash::Hash for &'d analyzer_ast::Decl {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ std::ptr::hash(*self, state);
+ }
+}
+
+impl<'d> PacketScope<'d> {
+ /// Add parent fields and constraints to the scope.
+ /// Only named fields are imported.
+ fn inherit(
+ &mut self,
+ parent: &PacketScope<'d>,
+ constraints: impl Iterator<Item = &'d Constraint>,
+ ) {
+ // Check constraints.
+ assert!(self.all_constraints.is_empty());
+ self.all_constraints = parent.all_constraints.clone();
+ for constraint in constraints {
+ let id = constraint.id.clone();
+ self.all_constraints.insert(id, constraint);
+ }
+
+ // Save parent fields.
+ self.all_fields = parent.all_fields.clone();
+ }
+
+ /// Iterate over the packet's fields.
+ pub fn iter_fields(&self) -> impl Iterator<Item = &'d analyzer_ast::Field> {
+ self.decl.fields()
+ }
+
+ /// Lookup a field by name. This will also find the special
+ /// `_payload_` and `_body_` fields.
+ pub fn get_packet_field(&self, id: &str) -> Option<&analyzer_ast::Field> {
+ self.decl.fields().find(|field| match &field.desc {
+ FieldDesc::Payload { .. } => id == "_payload_",
+ FieldDesc::Body { .. } => id == "_body_",
+ _ => field.id() == Some(id),
+ })
+ }
+
+ /// Find the payload or body field, if any.
+ pub fn get_payload_field(&self) -> Option<&analyzer_ast::Field> {
+ self.decl
+ .fields()
+ .find(|field| matches!(&field.desc, FieldDesc::Payload { .. } | FieldDesc::Body { .. }))
+ }
+
+ /// Lookup the size field for an array field.
+ pub fn get_array_size_field(&self, id: &str) -> Option<&analyzer_ast::Field> {
+ self.decl.fields().find(|field| match &field.desc {
+ FieldDesc::Size { field_id, .. } | FieldDesc::Count { field_id, .. } => field_id == id,
+ _ => false,
+ })
+ }
+
+ /// Find the size field corresponding to the payload or body
+ /// field of this packet.
+ pub fn get_payload_size_field(&self) -> Option<&analyzer_ast::Field> {
+ self.decl.fields().find(|field| match &field.desc {
+ FieldDesc::Size { field_id, .. } => field_id == "_payload_" || field_id == "_body_",
+ _ => false,
+ })
+ }
+
+ /// Cleanup scope after processing all fields.
+ fn finalize(&mut self) {
+ // Check field shadowing.
+ for f in self.decl.fields() {
+ if let Some(id) = f.id() {
+ self.all_fields.insert(id.to_string(), f);
+ }
+ }
+ }
+}
+
+impl<'d> Scope<'d> {
+ pub fn new(file: &analyzer_ast::File) -> Scope<'_> {
+ let mut scope = Scope { file, typedef: HashMap::new(), scopes: HashMap::new() };
+
+ // Gather top-level declarations.
+ // Validate the top-level scopes (Group, Packet, Typedef).
+ //
+ // TODO: switch to try_insert when stable
+ for decl in &file.declarations {
+ if let Some(id) = decl.id() {
+ scope.typedef.insert(id.to_string(), decl);
+ }
+ }
+
+ scope.finalize();
+ scope
+ }
+
+ // Sort Packet, Struct, and Group declarations by reverse topological
+ // order.
+ fn finalize(&mut self) -> Vec<&'d analyzer_ast::Decl> {
+ // Auxiliary function implementing BFS on Packet tree.
+ enum Mark {
+ Temporary,
+ Permanent,
+ }
+ struct Context<'d> {
+ list: Vec<&'d analyzer_ast::Decl>,
+ visited: HashMap<&'d analyzer_ast::Decl, Mark>,
+ scopes: HashMap<&'d analyzer_ast::Decl, PacketScope<'d>>,
+ }
+
+ fn bfs<'s, 'd>(
+ decl: &'d analyzer_ast::Decl,
+ context: &'s mut Context<'d>,
+ scope: &Scope<'d>,
+ ) -> Option<&'s PacketScope<'d>> {
+ match context.visited.get(&decl) {
+ Some(Mark::Permanent) => return context.scopes.get(&decl),
+ Some(Mark::Temporary) => {
+ return None;
+ }
+ _ => (),
+ }
+
+ let (parent_id, fields) = match &decl.desc {
+ DeclDesc::Packet { parent_id, fields, .. }
+ | DeclDesc::Struct { parent_id, fields, .. } => (parent_id.as_ref(), fields),
+ DeclDesc::Group { fields, .. } => (None, fields),
+ _ => return None,
+ };
+
+ context.visited.insert(decl, Mark::Temporary);
+ let mut lscope =
+ PacketScope { decl, all_fields: HashMap::new(), all_constraints: HashMap::new() };
+
+ // Iterate over Struct and Group fields.
+ for f in fields {
+ match &f.desc {
+ FieldDesc::Group { .. } => unreachable!(),
+ FieldDesc::Typedef { type_id, .. } => match scope.typedef.get(type_id) {
+ Some(struct_decl @ Decl { desc: DeclDesc::Struct { .. }, .. }) => {
+ bfs(struct_decl, context, scope);
+ }
+ None | Some(_) => (),
+ },
+ _ => (),
+ }
+ }
+
+ // Iterate over parent declaration.
+ let parent = parent_id.and_then(|id| scope.typedef.get(id));
+ if let Some(parent_decl) = parent {
+ if let Some(rscope) = bfs(parent_decl, context, scope) {
+ // Import the parent fields and constraints into the current scope.
+ lscope.inherit(rscope, decl.constraints())
+ }
+ }
+
+ lscope.finalize();
+ context.list.push(decl);
+ context.visited.insert(decl, Mark::Permanent);
+ context.scopes.insert(decl, lscope);
+ context.scopes.get(&decl)
+ }
+
+ let mut context =
+ Context::<'d> { list: vec![], visited: HashMap::new(), scopes: HashMap::new() };
+
+ for decl in self.typedef.values() {
+ bfs(decl, &mut context, self);
+ }
+
+ self.scopes = context.scopes;
+ context.list
+ }
+
+ pub fn iter_children<'a>(
+ &'a self,
+ id: &'a str,
+ ) -> impl Iterator<Item = &'d analyzer_ast::Decl> + 'a {
+ self.file.iter_children(self.typedef.get(id).unwrap())
+ }
+
+ /// Return the declaration of the typedef type backing the
+ /// selected field.
+ pub fn get_field_declaration(
+ &self,
+ field: &analyzer_ast::Field,
+ ) -> Option<&'d analyzer_ast::Decl> {
+ match &field.desc {
+ FieldDesc::FixedEnum { enum_id, .. } => self.typedef.get(enum_id).copied(),
+ FieldDesc::Array { type_id: Some(type_id), .. } => self.typedef.get(type_id).copied(),
+ FieldDesc::Typedef { type_id, .. } => self.typedef.get(type_id.as_str()).copied(),
+ _ => None,
+ }
+ }
+
+ /// Test if the selected field is a bitfield.
+ pub fn is_bitfield(&self, field: &analyzer_ast::Field) -> bool {
+ match &field.desc {
+ FieldDesc::Size { .. }
+ | FieldDesc::Count { .. }
+ | FieldDesc::ElementSize { .. }
+ | FieldDesc::FixedScalar { .. }
+ | FieldDesc::FixedEnum { .. }
+ | FieldDesc::Reserved { .. }
+ | FieldDesc::Scalar { .. } => true,
+ FieldDesc::Typedef { type_id, .. } => {
+ let field = self.typedef.get(type_id.as_str());
+ matches!(field, Some(Decl { desc: DeclDesc::Enum { .. }, .. }))
+ }
+ _ => false,
+ }
+ }
+}
diff --git a/src/parser.rs b/src/parser.rs
index f9d2ffa..6d19648 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -69,8 +69,7 @@ enum_range = {
enum_value_list ~
"}")?
}
-enum_other = { identifier ~ "=" ~ ".." }
-enum_tag = { enum_range | enum_value | enum_other }
+enum_tag = { enum_range | enum_value }
enum_tag_list = { enum_tag ~ ("," ~ enum_tag)* ~ ","? }
enum_declaration = {
"enum" ~ identifier ~ ":" ~ integer ~ "{" ~
@@ -351,17 +350,6 @@ fn parse_enum_range(node: Node<'_>, context: &Context) -> Result<crate::ast::Tag
}
}
-fn parse_enum_other(node: Node<'_>, context: &Context) -> Result<crate::ast::TagOther, String> {
- if node.as_rule() != Rule::enum_other {
- err_unexpected_rule(Rule::enum_other, node.as_rule())
- } else {
- let loc = node.as_loc(context);
- let mut children = node.children();
- let id = parse_identifier(&mut children)?;
- Ok(crate::ast::TagOther { id, loc })
- }
-}
-
fn parse_enum_tag(node: Node<'_>, context: &Context) -> Result<crate::ast::Tag, String> {
if node.as_rule() != Rule::enum_tag {
err_unexpected_rule(Rule::enum_tag, node.as_rule())
@@ -373,9 +361,6 @@ fn parse_enum_tag(node: Node<'_>, context: &Context) -> Result<crate::ast::Tag,
Some(node) if node.as_rule() == Rule::enum_range => {
Ok(crate::ast::Tag::Range(parse_enum_range(node, context)?))
}
- Some(node) if node.as_rule() == Rule::enum_other => {
- Ok(crate::ast::Tag::Other(parse_enum_other(node, context)?))
- }
Some(node) => Err(format!(
"expected rule {:?} or {:?}, got {:?}",
Rule::enum_value,
diff --git a/tests/generated/enum_declaration_big_endian.rs b/tests/generated/enum_declaration_big_endian.rs
index ffc4725..badb3f0 100644
--- a/tests/generated/enum_declaration_big_endian.rs
+++ b/tests/generated/enum_declaration_big_endian.rs
@@ -47,278 +47,136 @@ pub trait Packet {
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(try_from = "u8", into = "u8"))]
-pub enum IncompleteTruncatedClosed {
+pub enum IncompleteTruncated {
A = 0x0,
B = 0x1,
}
-impl TryFrom<u8> for IncompleteTruncatedClosed {
+impl TryFrom<u8> for IncompleteTruncated {
type Error = u8;
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
match value {
- 0x0 => Ok(IncompleteTruncatedClosed::A),
- 0x1 => Ok(IncompleteTruncatedClosed::B),
+ 0x0 => Ok(IncompleteTruncated::A),
+ 0x1 => Ok(IncompleteTruncated::B),
_ => Err(value),
}
}
}
-impl From<&IncompleteTruncatedClosed> for u8 {
- fn from(value: &IncompleteTruncatedClosed) -> Self {
+impl From<&IncompleteTruncated> for u8 {
+ fn from(value: &IncompleteTruncated) -> Self {
match value {
- IncompleteTruncatedClosed::A => 0x0,
- IncompleteTruncatedClosed::B => 0x1,
+ IncompleteTruncated::A => 0x0,
+ IncompleteTruncated::B => 0x1,
}
}
}
-impl From<IncompleteTruncatedClosed> for u8 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for u8 {
+ fn from(value: IncompleteTruncated) -> Self {
(&value).into()
}
}
-impl From<IncompleteTruncatedClosed> for i8 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for i8 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for i16 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for i16 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for i32 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for i32 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for i64 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for i64 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for u16 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for u16 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for u32 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for u32 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for u64 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for u64 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(try_from = "u8", into = "u8"))]
-pub enum IncompleteTruncatedOpen {
- A,
- B,
- Unknown(Private<u8>),
-}
-impl TryFrom<u8> for IncompleteTruncatedOpen {
- type Error = u8;
- fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
- match value {
- 0x0 => Ok(IncompleteTruncatedOpen::A),
- 0x1 => Ok(IncompleteTruncatedOpen::B),
- 0..=0x7 => Ok(IncompleteTruncatedOpen::Unknown(Private(value))),
- _ => Err(value),
- }
- }
-}
-impl From<&IncompleteTruncatedOpen> for u8 {
- fn from(value: &IncompleteTruncatedOpen) -> Self {
- match value {
- IncompleteTruncatedOpen::A => 0x0,
- IncompleteTruncatedOpen::B => 0x1,
- IncompleteTruncatedOpen::Unknown(Private(value)) => *value,
- }
- }
-}
-impl From<IncompleteTruncatedOpen> for u8 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- (&value).into()
- }
-}
-impl From<IncompleteTruncatedOpen> for i8 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for i16 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for i32 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for i64 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for u16 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for u32 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for u64 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-#[cfg_attr(feature = "serde", serde(try_from = "u8", into = "u8"))]
-pub enum IncompleteTruncatedClosedWithRange {
- A,
- X,
- Y,
- B(Private<u8>),
-}
-impl TryFrom<u8> for IncompleteTruncatedClosedWithRange {
- type Error = u8;
- fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
- match value {
- 0x0 => Ok(IncompleteTruncatedClosedWithRange::A),
- 0x1 => Ok(IncompleteTruncatedClosedWithRange::X),
- 0x2 => Ok(IncompleteTruncatedClosedWithRange::Y),
- 0x1..=0x6 => Ok(IncompleteTruncatedClosedWithRange::B(Private(value))),
- _ => Err(value),
- }
- }
-}
-impl From<&IncompleteTruncatedClosedWithRange> for u8 {
- fn from(value: &IncompleteTruncatedClosedWithRange) -> Self {
- match value {
- IncompleteTruncatedClosedWithRange::A => 0x0,
- IncompleteTruncatedClosedWithRange::X => 0x1,
- IncompleteTruncatedClosedWithRange::Y => 0x2,
- IncompleteTruncatedClosedWithRange::B(Private(value)) => *value,
- }
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for u8 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- (&value).into()
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for i8 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for i16 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for i32 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for i64 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for u16 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for u32 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for u64 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-#[cfg_attr(feature = "serde", serde(try_from = "u8", into = "u8"))]
-pub enum IncompleteTruncatedOpenWithRange {
+pub enum IncompleteTruncatedWithRange {
A,
X,
Y,
B(Private<u8>),
- Unknown(Private<u8>),
}
-impl TryFrom<u8> for IncompleteTruncatedOpenWithRange {
+impl TryFrom<u8> for IncompleteTruncatedWithRange {
type Error = u8;
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
match value {
- 0x0 => Ok(IncompleteTruncatedOpenWithRange::A),
- 0x1 => Ok(IncompleteTruncatedOpenWithRange::X),
- 0x2 => Ok(IncompleteTruncatedOpenWithRange::Y),
- 0x1..=0x6 => Ok(IncompleteTruncatedOpenWithRange::B(Private(value))),
- 0..=0x7 => Ok(IncompleteTruncatedOpenWithRange::Unknown(Private(value))),
+ 0x0 => Ok(IncompleteTruncatedWithRange::A),
+ 0x1 => Ok(IncompleteTruncatedWithRange::X),
+ 0x2 => Ok(IncompleteTruncatedWithRange::Y),
+ 0x1..=0x6 => Ok(IncompleteTruncatedWithRange::B(Private(value))),
_ => Err(value),
}
}
}
-impl From<&IncompleteTruncatedOpenWithRange> for u8 {
- fn from(value: &IncompleteTruncatedOpenWithRange) -> Self {
+impl From<&IncompleteTruncatedWithRange> for u8 {
+ fn from(value: &IncompleteTruncatedWithRange) -> Self {
match value {
- IncompleteTruncatedOpenWithRange::A => 0x0,
- IncompleteTruncatedOpenWithRange::X => 0x1,
- IncompleteTruncatedOpenWithRange::Y => 0x2,
- IncompleteTruncatedOpenWithRange::B(Private(value)) => *value,
- IncompleteTruncatedOpenWithRange::Unknown(Private(value)) => *value,
+ IncompleteTruncatedWithRange::A => 0x0,
+ IncompleteTruncatedWithRange::X => 0x1,
+ IncompleteTruncatedWithRange::Y => 0x2,
+ IncompleteTruncatedWithRange::B(Private(value)) => *value,
}
}
}
-impl From<IncompleteTruncatedOpenWithRange> for u8 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for u8 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
(&value).into()
}
}
-impl From<IncompleteTruncatedOpenWithRange> for i8 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for i8 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for i16 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for i16 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for i32 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for i32 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for i64 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for i64 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for u16 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for u16 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for u32 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for u32 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for u64 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for u64 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
diff --git a/tests/generated/enum_declaration_little_endian.rs b/tests/generated/enum_declaration_little_endian.rs
index ffc4725..badb3f0 100644
--- a/tests/generated/enum_declaration_little_endian.rs
+++ b/tests/generated/enum_declaration_little_endian.rs
@@ -47,278 +47,136 @@ pub trait Packet {
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(try_from = "u8", into = "u8"))]
-pub enum IncompleteTruncatedClosed {
+pub enum IncompleteTruncated {
A = 0x0,
B = 0x1,
}
-impl TryFrom<u8> for IncompleteTruncatedClosed {
+impl TryFrom<u8> for IncompleteTruncated {
type Error = u8;
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
match value {
- 0x0 => Ok(IncompleteTruncatedClosed::A),
- 0x1 => Ok(IncompleteTruncatedClosed::B),
+ 0x0 => Ok(IncompleteTruncated::A),
+ 0x1 => Ok(IncompleteTruncated::B),
_ => Err(value),
}
}
}
-impl From<&IncompleteTruncatedClosed> for u8 {
- fn from(value: &IncompleteTruncatedClosed) -> Self {
+impl From<&IncompleteTruncated> for u8 {
+ fn from(value: &IncompleteTruncated) -> Self {
match value {
- IncompleteTruncatedClosed::A => 0x0,
- IncompleteTruncatedClosed::B => 0x1,
+ IncompleteTruncated::A => 0x0,
+ IncompleteTruncated::B => 0x1,
}
}
}
-impl From<IncompleteTruncatedClosed> for u8 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for u8 {
+ fn from(value: IncompleteTruncated) -> Self {
(&value).into()
}
}
-impl From<IncompleteTruncatedClosed> for i8 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for i8 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for i16 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for i16 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for i32 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for i32 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for i64 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for i64 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for u16 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for u16 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for u32 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for u32 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedClosed> for u64 {
- fn from(value: IncompleteTruncatedClosed) -> Self {
+impl From<IncompleteTruncated> for u64 {
+ fn from(value: IncompleteTruncated) -> Self {
u8::from(value) as Self
}
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(try_from = "u8", into = "u8"))]
-pub enum IncompleteTruncatedOpen {
- A,
- B,
- Unknown(Private<u8>),
-}
-impl TryFrom<u8> for IncompleteTruncatedOpen {
- type Error = u8;
- fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
- match value {
- 0x0 => Ok(IncompleteTruncatedOpen::A),
- 0x1 => Ok(IncompleteTruncatedOpen::B),
- 0..=0x7 => Ok(IncompleteTruncatedOpen::Unknown(Private(value))),
- _ => Err(value),
- }
- }
-}
-impl From<&IncompleteTruncatedOpen> for u8 {
- fn from(value: &IncompleteTruncatedOpen) -> Self {
- match value {
- IncompleteTruncatedOpen::A => 0x0,
- IncompleteTruncatedOpen::B => 0x1,
- IncompleteTruncatedOpen::Unknown(Private(value)) => *value,
- }
- }
-}
-impl From<IncompleteTruncatedOpen> for u8 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- (&value).into()
- }
-}
-impl From<IncompleteTruncatedOpen> for i8 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for i16 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for i32 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for i64 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for u16 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for u32 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedOpen> for u64 {
- fn from(value: IncompleteTruncatedOpen) -> Self {
- u8::from(value) as Self
- }
-}
-#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-#[cfg_attr(feature = "serde", serde(try_from = "u8", into = "u8"))]
-pub enum IncompleteTruncatedClosedWithRange {
- A,
- X,
- Y,
- B(Private<u8>),
-}
-impl TryFrom<u8> for IncompleteTruncatedClosedWithRange {
- type Error = u8;
- fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
- match value {
- 0x0 => Ok(IncompleteTruncatedClosedWithRange::A),
- 0x1 => Ok(IncompleteTruncatedClosedWithRange::X),
- 0x2 => Ok(IncompleteTruncatedClosedWithRange::Y),
- 0x1..=0x6 => Ok(IncompleteTruncatedClosedWithRange::B(Private(value))),
- _ => Err(value),
- }
- }
-}
-impl From<&IncompleteTruncatedClosedWithRange> for u8 {
- fn from(value: &IncompleteTruncatedClosedWithRange) -> Self {
- match value {
- IncompleteTruncatedClosedWithRange::A => 0x0,
- IncompleteTruncatedClosedWithRange::X => 0x1,
- IncompleteTruncatedClosedWithRange::Y => 0x2,
- IncompleteTruncatedClosedWithRange::B(Private(value)) => *value,
- }
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for u8 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- (&value).into()
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for i8 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for i16 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for i32 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for i64 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for u16 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for u32 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-impl From<IncompleteTruncatedClosedWithRange> for u64 {
- fn from(value: IncompleteTruncatedClosedWithRange) -> Self {
- u8::from(value) as Self
- }
-}
-#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-#[cfg_attr(feature = "serde", serde(try_from = "u8", into = "u8"))]
-pub enum IncompleteTruncatedOpenWithRange {
+pub enum IncompleteTruncatedWithRange {
A,
X,
Y,
B(Private<u8>),
- Unknown(Private<u8>),
}
-impl TryFrom<u8> for IncompleteTruncatedOpenWithRange {
+impl TryFrom<u8> for IncompleteTruncatedWithRange {
type Error = u8;
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
match value {
- 0x0 => Ok(IncompleteTruncatedOpenWithRange::A),
- 0x1 => Ok(IncompleteTruncatedOpenWithRange::X),
- 0x2 => Ok(IncompleteTruncatedOpenWithRange::Y),
- 0x1..=0x6 => Ok(IncompleteTruncatedOpenWithRange::B(Private(value))),
- 0..=0x7 => Ok(IncompleteTruncatedOpenWithRange::Unknown(Private(value))),
+ 0x0 => Ok(IncompleteTruncatedWithRange::A),
+ 0x1 => Ok(IncompleteTruncatedWithRange::X),
+ 0x2 => Ok(IncompleteTruncatedWithRange::Y),
+ 0x1..=0x6 => Ok(IncompleteTruncatedWithRange::B(Private(value))),
_ => Err(value),
}
}
}
-impl From<&IncompleteTruncatedOpenWithRange> for u8 {
- fn from(value: &IncompleteTruncatedOpenWithRange) -> Self {
+impl From<&IncompleteTruncatedWithRange> for u8 {
+ fn from(value: &IncompleteTruncatedWithRange) -> Self {
match value {
- IncompleteTruncatedOpenWithRange::A => 0x0,
- IncompleteTruncatedOpenWithRange::X => 0x1,
- IncompleteTruncatedOpenWithRange::Y => 0x2,
- IncompleteTruncatedOpenWithRange::B(Private(value)) => *value,
- IncompleteTruncatedOpenWithRange::Unknown(Private(value)) => *value,
+ IncompleteTruncatedWithRange::A => 0x0,
+ IncompleteTruncatedWithRange::X => 0x1,
+ IncompleteTruncatedWithRange::Y => 0x2,
+ IncompleteTruncatedWithRange::B(Private(value)) => *value,
}
}
}
-impl From<IncompleteTruncatedOpenWithRange> for u8 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for u8 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
(&value).into()
}
}
-impl From<IncompleteTruncatedOpenWithRange> for i8 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for i8 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for i16 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for i16 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for i32 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for i32 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for i64 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for i64 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for u16 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for u16 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for u32 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for u32 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
-impl From<IncompleteTruncatedOpenWithRange> for u64 {
- fn from(value: IncompleteTruncatedOpenWithRange) -> Self {
+impl From<IncompleteTruncatedWithRange> for u64 {
+ fn from(value: IncompleteTruncatedWithRange) -> Self {
u8::from(value) as Self
}
}
diff --git a/tests/generated/packet_decl_24bit_enum_array_big_endian.rs b/tests/generated/packet_decl_24bit_enum_array_big_endian.rs
index 7717d7a..47b45dc 100644
--- a/tests/generated/packet_decl_24bit_enum_array_big_endian.rs
+++ b/tests/generated/packet_decl_24bit_enum_array_big_endian.rs
@@ -125,10 +125,10 @@ impl BarData {
let x = (0..5)
.map(|_| {
Foo::try_from(bytes.get_mut().get_uint(3) as u32)
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: String::new(),
- value: unknown_val as u64,
+ value: 0,
type_: "Foo".to_string(),
})
})
diff --git a/tests/generated/packet_decl_24bit_enum_array_little_endian.rs b/tests/generated/packet_decl_24bit_enum_array_little_endian.rs
index 2fb9a9c..a413ce1 100644
--- a/tests/generated/packet_decl_24bit_enum_array_little_endian.rs
+++ b/tests/generated/packet_decl_24bit_enum_array_little_endian.rs
@@ -125,10 +125,10 @@ impl BarData {
let x = (0..5)
.map(|_| {
Foo::try_from(bytes.get_mut().get_uint_le(3) as u32)
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: String::new(),
- value: unknown_val as u64,
+ value: 0,
type_: "Foo".to_string(),
})
})
diff --git a/tests/generated/packet_decl_24bit_enum_big_endian.rs b/tests/generated/packet_decl_24bit_enum_big_endian.rs
index 272e52d..c63b562 100644
--- a/tests/generated/packet_decl_24bit_enum_big_endian.rs
+++ b/tests/generated/packet_decl_24bit_enum_big_endian.rs
@@ -123,10 +123,10 @@ impl BarData {
});
}
let x = Foo::try_from(bytes.get_mut().get_uint(3) as u32)
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: "x".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_uint(3) as u32 as u64,
type_: "Foo".to_string(),
})?;
Ok(Self { x })
diff --git a/tests/generated/packet_decl_24bit_enum_little_endian.rs b/tests/generated/packet_decl_24bit_enum_little_endian.rs
index 278336c..2e58a9e 100644
--- a/tests/generated/packet_decl_24bit_enum_little_endian.rs
+++ b/tests/generated/packet_decl_24bit_enum_little_endian.rs
@@ -123,10 +123,10 @@ impl BarData {
});
}
let x = Foo::try_from(bytes.get_mut().get_uint_le(3) as u32)
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: "x".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_uint_le(3) as u32 as u64,
type_: "Foo".to_string(),
})?;
Ok(Self { x })
diff --git a/tests/generated/packet_decl_64bit_enum_array_big_endian.rs b/tests/generated/packet_decl_64bit_enum_array_big_endian.rs
index caeba78..dd28666 100644
--- a/tests/generated/packet_decl_64bit_enum_array_big_endian.rs
+++ b/tests/generated/packet_decl_64bit_enum_array_big_endian.rs
@@ -110,10 +110,10 @@ impl BarData {
let x = (0..7)
.map(|_| {
Foo::try_from(bytes.get_mut().get_u64())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: String::new(),
- value: unknown_val as u64,
+ value: 0,
type_: "Foo".to_string(),
})
})
diff --git a/tests/generated/packet_decl_64bit_enum_array_little_endian.rs b/tests/generated/packet_decl_64bit_enum_array_little_endian.rs
index 2a698b8..371c1eb 100644
--- a/tests/generated/packet_decl_64bit_enum_array_little_endian.rs
+++ b/tests/generated/packet_decl_64bit_enum_array_little_endian.rs
@@ -110,10 +110,10 @@ impl BarData {
let x = (0..7)
.map(|_| {
Foo::try_from(bytes.get_mut().get_u64_le())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: String::new(),
- value: unknown_val as u64,
+ value: 0,
type_: "Foo".to_string(),
})
})
diff --git a/tests/generated/packet_decl_64bit_enum_big_endian.rs b/tests/generated/packet_decl_64bit_enum_big_endian.rs
index f29c654..bd46742 100644
--- a/tests/generated/packet_decl_64bit_enum_big_endian.rs
+++ b/tests/generated/packet_decl_64bit_enum_big_endian.rs
@@ -108,10 +108,10 @@ impl BarData {
});
}
let x = Foo::try_from(bytes.get_mut().get_u64())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: "x".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u64() as u64,
type_: "Foo".to_string(),
})?;
Ok(Self { x })
diff --git a/tests/generated/packet_decl_64bit_enum_little_endian.rs b/tests/generated/packet_decl_64bit_enum_little_endian.rs
index 0bc5a12..75a43b6 100644
--- a/tests/generated/packet_decl_64bit_enum_little_endian.rs
+++ b/tests/generated/packet_decl_64bit_enum_little_endian.rs
@@ -108,10 +108,10 @@ impl BarData {
});
}
let x = Foo::try_from(bytes.get_mut().get_u64_le())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: "x".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u64_le() as u64,
type_: "Foo".to_string(),
})?;
Ok(Self { x })
diff --git a/tests/generated/packet_decl_8bit_enum_array_big_endian.rs b/tests/generated/packet_decl_8bit_enum_array_big_endian.rs
index f36f1ba..4c16ddf 100644
--- a/tests/generated/packet_decl_8bit_enum_array_big_endian.rs
+++ b/tests/generated/packet_decl_8bit_enum_array_big_endian.rs
@@ -140,10 +140,10 @@ impl BarData {
let x = (0..3)
.map(|_| {
Foo::try_from(bytes.get_mut().get_u8())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: String::new(),
- value: unknown_val as u64,
+ value: 0,
type_: "Foo".to_string(),
})
})
diff --git a/tests/generated/packet_decl_8bit_enum_array_little_endian.rs b/tests/generated/packet_decl_8bit_enum_array_little_endian.rs
index f36f1ba..4c16ddf 100644
--- a/tests/generated/packet_decl_8bit_enum_array_little_endian.rs
+++ b/tests/generated/packet_decl_8bit_enum_array_little_endian.rs
@@ -140,10 +140,10 @@ impl BarData {
let x = (0..3)
.map(|_| {
Foo::try_from(bytes.get_mut().get_u8())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: String::new(),
- value: unknown_val as u64,
+ value: 0,
type_: "Foo".to_string(),
})
})
diff --git a/tests/generated/packet_decl_8bit_enum_big_endian.rs b/tests/generated/packet_decl_8bit_enum_big_endian.rs
index bccdaeb..8ceb132 100644
--- a/tests/generated/packet_decl_8bit_enum_big_endian.rs
+++ b/tests/generated/packet_decl_8bit_enum_big_endian.rs
@@ -138,10 +138,10 @@ impl BarData {
});
}
let x = Foo::try_from(bytes.get_mut().get_u8())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: "x".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u8() as u64,
type_: "Foo".to_string(),
})?;
Ok(Self { x })
diff --git a/tests/generated/packet_decl_8bit_enum_little_endian.rs b/tests/generated/packet_decl_8bit_enum_little_endian.rs
index bccdaeb..8ceb132 100644
--- a/tests/generated/packet_decl_8bit_enum_little_endian.rs
+++ b/tests/generated/packet_decl_8bit_enum_little_endian.rs
@@ -138,10 +138,10 @@ impl BarData {
});
}
let x = Foo::try_from(bytes.get_mut().get_u8())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Bar".to_string(),
field: "x".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u8() as u64,
type_: "Foo".to_string(),
})?;
Ok(Self { x })
diff --git a/tests/generated/packet_decl_child_packets_big_endian.rs b/tests/generated/packet_decl_child_packets_big_endian.rs
index 8b3e05d..7a000c7 100644
--- a/tests/generated/packet_decl_child_packets_big_endian.rs
+++ b/tests/generated/packet_decl_child_packets_big_endian.rs
@@ -166,10 +166,10 @@ impl FooData {
});
}
let b = Enum16::try_from(bytes.get_mut().get_u16())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Foo".to_string(),
field: "b".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u16() as u64,
type_: "Enum16".to_string(),
})?;
if bytes.get().remaining() < 1 {
diff --git a/tests/generated/packet_decl_child_packets_little_endian.rs b/tests/generated/packet_decl_child_packets_little_endian.rs
index 8a464b2..7fe9783 100644
--- a/tests/generated/packet_decl_child_packets_little_endian.rs
+++ b/tests/generated/packet_decl_child_packets_little_endian.rs
@@ -166,10 +166,10 @@ impl FooData {
});
}
let b = Enum16::try_from(bytes.get_mut().get_u16_le())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Foo".to_string(),
field: "b".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u16_le() as u64,
type_: "Enum16".to_string(),
})?;
if bytes.get().remaining() < 1 {
diff --git a/tests/generated/packet_decl_fixed_enum_field_big_endian.rs b/tests/generated/packet_decl_fixed_enum_field_big_endian.rs
index 5c780ad..2ec6b58 100644
--- a/tests/generated/packet_decl_fixed_enum_field_big_endian.rs
+++ b/tests/generated/packet_decl_fixed_enum_field_big_endian.rs
@@ -143,11 +143,10 @@ impl FooData {
});
}
let chunk = bytes.get_mut().get_u64();
- let fixed_value = (chunk & 0x7f) as u8;
- if fixed_value != u8::from(Enum7::A) {
+ if (chunk & 0x7f) as u8 != u8::from(Enum7::A) {
return Err(Error::InvalidFixedValue {
expected: u8::from(Enum7::A) as u64,
- actual: fixed_value as u64,
+ actual: (chunk & 0x7f) as u8 as u64,
});
}
let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64);
diff --git a/tests/generated/packet_decl_fixed_enum_field_little_endian.rs b/tests/generated/packet_decl_fixed_enum_field_little_endian.rs
index 45486c5..13aecd9 100644
--- a/tests/generated/packet_decl_fixed_enum_field_little_endian.rs
+++ b/tests/generated/packet_decl_fixed_enum_field_little_endian.rs
@@ -143,11 +143,10 @@ impl FooData {
});
}
let chunk = bytes.get_mut().get_u64_le();
- let fixed_value = (chunk & 0x7f) as u8;
- if fixed_value != u8::from(Enum7::A) {
+ if (chunk & 0x7f) as u8 != u8::from(Enum7::A) {
return Err(Error::InvalidFixedValue {
expected: u8::from(Enum7::A) as u64,
- actual: fixed_value as u64,
+ actual: (chunk & 0x7f) as u8 as u64,
});
}
let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64);
diff --git a/tests/generated/packet_decl_fixed_scalar_field_big_endian.rs b/tests/generated/packet_decl_fixed_scalar_field_big_endian.rs
index 349b183..e047669 100644
--- a/tests/generated/packet_decl_fixed_scalar_field_big_endian.rs
+++ b/tests/generated/packet_decl_fixed_scalar_field_big_endian.rs
@@ -77,11 +77,10 @@ impl FooData {
});
}
let chunk = bytes.get_mut().get_u64();
- let fixed_value = (chunk & 0x7f) as u8;
if (chunk & 0x7f) as u8 != 7 {
return Err(Error::InvalidFixedValue {
expected: 7,
- actual: fixed_value as u64,
+ actual: (chunk & 0x7f) as u8 as u64,
});
}
let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64);
diff --git a/tests/generated/packet_decl_fixed_scalar_field_little_endian.rs b/tests/generated/packet_decl_fixed_scalar_field_little_endian.rs
index 96b9064..39922ca 100644
--- a/tests/generated/packet_decl_fixed_scalar_field_little_endian.rs
+++ b/tests/generated/packet_decl_fixed_scalar_field_little_endian.rs
@@ -77,11 +77,10 @@ impl FooData {
});
}
let chunk = bytes.get_mut().get_u64_le();
- let fixed_value = (chunk & 0x7f) as u8;
if (chunk & 0x7f) as u8 != 7 {
return Err(Error::InvalidFixedValue {
expected: 7,
- actual: fixed_value as u64,
+ actual: (chunk & 0x7f) as u8 as u64,
});
}
let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64);
diff --git a/tests/generated/packet_decl_grand_children_big_endian.rs b/tests/generated/packet_decl_grand_children_big_endian.rs
index f1a2cac..896a46f 100644
--- a/tests/generated/packet_decl_grand_children_big_endian.rs
+++ b/tests/generated/packet_decl_grand_children_big_endian.rs
@@ -157,10 +157,10 @@ impl ParentData {
});
}
let foo = Enum16::try_from(bytes.get_mut().get_u16())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Parent".to_string(),
field: "foo".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u16() as u64,
type_: "Enum16".to_string(),
})?;
if bytes.get().remaining() < 2 {
@@ -171,10 +171,10 @@ impl ParentData {
});
}
let bar = Enum16::try_from(bytes.get_mut().get_u16())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Parent".to_string(),
field: "bar".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u16() as u64,
type_: "Enum16".to_string(),
})?;
if bytes.get().remaining() < 2 {
@@ -185,10 +185,10 @@ impl ParentData {
});
}
let baz = Enum16::try_from(bytes.get_mut().get_u16())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Parent".to_string(),
field: "baz".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u16() as u64,
type_: "Enum16".to_string(),
})?;
if bytes.get().remaining() < 1 {
@@ -389,10 +389,10 @@ impl ChildData {
});
}
let quux = Enum16::try_from(bytes.get_mut().get_u16())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Child".to_string(),
field: "quux".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u16() as u64,
type_: "Enum16".to_string(),
})?;
let payload = bytes.get();
diff --git a/tests/generated/packet_decl_grand_children_little_endian.rs b/tests/generated/packet_decl_grand_children_little_endian.rs
index 66fa76a..4a672a6 100644
--- a/tests/generated/packet_decl_grand_children_little_endian.rs
+++ b/tests/generated/packet_decl_grand_children_little_endian.rs
@@ -157,10 +157,10 @@ impl ParentData {
});
}
let foo = Enum16::try_from(bytes.get_mut().get_u16_le())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Parent".to_string(),
field: "foo".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u16_le() as u64,
type_: "Enum16".to_string(),
})?;
if bytes.get().remaining() < 2 {
@@ -171,10 +171,10 @@ impl ParentData {
});
}
let bar = Enum16::try_from(bytes.get_mut().get_u16_le())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Parent".to_string(),
field: "bar".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u16_le() as u64,
type_: "Enum16".to_string(),
})?;
if bytes.get().remaining() < 2 {
@@ -185,10 +185,10 @@ impl ParentData {
});
}
let baz = Enum16::try_from(bytes.get_mut().get_u16_le())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Parent".to_string(),
field: "baz".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u16_le() as u64,
type_: "Enum16".to_string(),
})?;
if bytes.get().remaining() < 1 {
@@ -389,10 +389,10 @@ impl ChildData {
});
}
let quux = Enum16::try_from(bytes.get_mut().get_u16_le())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Child".to_string(),
field: "quux".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u16_le() as u64,
type_: "Enum16".to_string(),
})?;
let payload = bytes.get();
diff --git a/tests/generated/packet_decl_mixed_scalars_enums_big_endian.rs b/tests/generated/packet_decl_mixed_scalars_enums_big_endian.rs
index 7dcf2e6..122b202 100644
--- a/tests/generated/packet_decl_mixed_scalars_enums_big_endian.rs
+++ b/tests/generated/packet_decl_mixed_scalars_enums_big_endian.rs
@@ -206,18 +206,18 @@ impl FooData {
}
let chunk = bytes.get_mut().get_uint(3) as u32;
let x = Enum7::try_from((chunk & 0x7f) as u8)
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Foo".to_string(),
field: "x".to_string(),
- value: unknown_val as u64,
+ value: (chunk & 0x7f) as u8 as u64,
type_: "Enum7".to_string(),
})?;
let y = ((chunk >> 7) & 0x1f) as u8;
let z = Enum9::try_from(((chunk >> 12) & 0x1ff) as u16)
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Foo".to_string(),
field: "z".to_string(),
- value: unknown_val as u64,
+ value: ((chunk >> 12) & 0x1ff) as u16 as u64,
type_: "Enum9".to_string(),
})?;
let w = ((chunk >> 21) & 0x7) as u8;
diff --git a/tests/generated/packet_decl_mixed_scalars_enums_little_endian.rs b/tests/generated/packet_decl_mixed_scalars_enums_little_endian.rs
index 667dab3..0cc3d92 100644
--- a/tests/generated/packet_decl_mixed_scalars_enums_little_endian.rs
+++ b/tests/generated/packet_decl_mixed_scalars_enums_little_endian.rs
@@ -206,18 +206,18 @@ impl FooData {
}
let chunk = bytes.get_mut().get_uint_le(3) as u32;
let x = Enum7::try_from((chunk & 0x7f) as u8)
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Foo".to_string(),
field: "x".to_string(),
- value: unknown_val as u64,
+ value: (chunk & 0x7f) as u8 as u64,
type_: "Enum7".to_string(),
})?;
let y = ((chunk >> 7) & 0x1f) as u8;
let z = Enum9::try_from(((chunk >> 12) & 0x1ff) as u16)
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Foo".to_string(),
field: "z".to_string(),
- value: unknown_val as u64,
+ value: ((chunk >> 12) & 0x1ff) as u16 as u64,
type_: "Enum9".to_string(),
})?;
let w = ((chunk >> 21) & 0x7) as u8;
diff --git a/tests/generated/packet_decl_parent_with_alias_child_big_endian.rs b/tests/generated/packet_decl_parent_with_alias_child_big_endian.rs
index 785c0ee..8c9232d 100644
--- a/tests/generated/packet_decl_parent_with_alias_child_big_endian.rs
+++ b/tests/generated/packet_decl_parent_with_alias_child_big_endian.rs
@@ -169,10 +169,10 @@ impl ParentData {
});
}
let v = Enum8::try_from(bytes.get_mut().get_u8())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Parent".to_string(),
field: "v".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u8() as u64,
type_: "Enum8".to_string(),
})?;
let payload = bytes.get();
diff --git a/tests/generated/packet_decl_parent_with_alias_child_little_endian.rs b/tests/generated/packet_decl_parent_with_alias_child_little_endian.rs
index 785c0ee..8c9232d 100644
--- a/tests/generated/packet_decl_parent_with_alias_child_little_endian.rs
+++ b/tests/generated/packet_decl_parent_with_alias_child_little_endian.rs
@@ -169,10 +169,10 @@ impl ParentData {
});
}
let v = Enum8::try_from(bytes.get_mut().get_u8())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Parent".to_string(),
field: "v".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u8() as u64,
type_: "Enum8".to_string(),
})?;
let payload = bytes.get();
diff --git a/tests/generated/packet_decl_parent_with_no_payload_big_endian.rs b/tests/generated/packet_decl_parent_with_no_payload_big_endian.rs
index 82c45c5..4f58e26 100644
--- a/tests/generated/packet_decl_parent_with_no_payload_big_endian.rs
+++ b/tests/generated/packet_decl_parent_with_no_payload_big_endian.rs
@@ -160,10 +160,10 @@ impl ParentData {
});
}
let v = Enum8::try_from(bytes.get_mut().get_u8())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Parent".to_string(),
field: "v".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u8() as u64,
type_: "Enum8".to_string(),
})?;
let payload: &[u8] = &[];
diff --git a/tests/generated/packet_decl_parent_with_no_payload_little_endian.rs b/tests/generated/packet_decl_parent_with_no_payload_little_endian.rs
index 82c45c5..4f58e26 100644
--- a/tests/generated/packet_decl_parent_with_no_payload_little_endian.rs
+++ b/tests/generated/packet_decl_parent_with_no_payload_little_endian.rs
@@ -160,10 +160,10 @@ impl ParentData {
});
}
let v = Enum8::try_from(bytes.get_mut().get_u8())
- .map_err(|unknown_val| Error::InvalidEnumValueError {
+ .map_err(|_| Error::InvalidEnumValueError {
obj: "Parent".to_string(),
field: "v".to_string(),
- value: unknown_val as u64,
+ value: bytes.get_mut().get_u8() as u64,
type_: "Enum8".to_string(),
})?;
let payload: &[u8] = &[];
diff --git a/tests/generated/reserved_identifier_big_endian.rs b/tests/generated/reserved_identifier_big_endian.rs
deleted file mode 100644
index 1f13532..0000000
--- a/tests/generated/reserved_identifier_big_endian.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-#![rustfmt::skip]
-/// @generated rust packets from test.
-use bytes::{Buf, BufMut, Bytes, BytesMut};
-use std::convert::{TryFrom, TryInto};
-use std::cell::Cell;
-use std::fmt;
-use thiserror::Error;
-type Result<T> = std::result::Result<T, Error>;
-/// Private prevents users from creating arbitrary scalar values
-/// in situations where the value needs to be validated.
-/// Users can freely deref the value, but only the backend
-/// may create it.
-#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Private<T>(T);
-impl<T> std::ops::Deref for Private<T> {
- type Target = T;
- fn deref(&self) -> &Self::Target {
- &self.0
- }
-}
-#[derive(Debug, Error)]
-pub enum Error {
- #[error("Packet parsing failed")]
- InvalidPacketError,
- #[error("{field} was {value:x}, which is not known")]
- ConstraintOutOfBounds { field: String, value: u64 },
- #[error("Got {actual:x}, expected {expected:x}")]
- InvalidFixedValue { expected: u64, actual: u64 },
- #[error("when parsing {obj} needed length of {wanted} but got {got}")]
- InvalidLengthError { obj: String, wanted: usize, got: usize },
- #[error(
- "array size ({array} bytes) is not a multiple of the element size ({element} bytes)"
- )]
- InvalidArraySize { array: usize, element: usize },
- #[error("Due to size restrictions a struct could not be parsed.")]
- ImpossibleStructError,
- #[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")]
- InvalidEnumValueError { obj: String, field: String, value: u64, type_: String },
- #[error("expected child {expected}, got {actual}")]
- InvalidChildError { expected: &'static str, actual: String },
-}
-pub trait Packet {
- fn to_bytes(self) -> Bytes;
- fn to_vec(self) -> Vec<u8>;
-}
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-pub struct TestData {
- r#type: u8,
-}
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-pub struct Test {
- #[cfg_attr(feature = "serde", serde(flatten))]
- test: TestData,
-}
-#[derive(Debug)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-pub struct TestBuilder {
- pub r#type: u8,
-}
-impl TestData {
- fn conforms(bytes: &[u8]) -> bool {
- bytes.len() >= 1
- }
- fn parse(bytes: &[u8]) -> Result<Self> {
- let mut cell = Cell::new(bytes);
- let packet = Self::parse_inner(&mut cell)?;
- Ok(packet)
- }
- fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self> {
- if bytes.get().remaining() < 1 {
- return Err(Error::InvalidLengthError {
- obj: "Test".to_string(),
- wanted: 1,
- got: bytes.get().remaining(),
- });
- }
- let r#type = bytes.get_mut().get_u8();
- Ok(Self { r#type })
- }
- fn write_to(&self, buffer: &mut BytesMut) {
- buffer.put_u8(self.r#type);
- }
- fn get_total_size(&self) -> usize {
- self.get_size()
- }
- fn get_size(&self) -> usize {
- 1
- }
-}
-impl Packet for Test {
- fn to_bytes(self) -> Bytes {
- let mut buffer = BytesMut::with_capacity(self.test.get_size());
- self.test.write_to(&mut buffer);
- buffer.freeze()
- }
- fn to_vec(self) -> Vec<u8> {
- self.to_bytes().to_vec()
- }
-}
-impl From<Test> for Bytes {
- fn from(packet: Test) -> Self {
- packet.to_bytes()
- }
-}
-impl From<Test> for Vec<u8> {
- fn from(packet: Test) -> Self {
- packet.to_vec()
- }
-}
-impl Test {
- pub fn parse(bytes: &[u8]) -> Result<Self> {
- let mut cell = Cell::new(bytes);
- let packet = Self::parse_inner(&mut cell)?;
- Ok(packet)
- }
- fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self> {
- let data = TestData::parse_inner(&mut bytes)?;
- Self::new(data)
- }
- fn new(test: TestData) -> Result<Self> {
- Ok(Self { test })
- }
- pub fn get_type(&self) -> u8 {
- self.test.r#type
- }
- fn write_to(&self, buffer: &mut BytesMut) {
- self.test.write_to(buffer)
- }
- pub fn get_size(&self) -> usize {
- self.test.get_size()
- }
-}
-impl TestBuilder {
- pub fn build(self) -> Test {
- let test = TestData { r#type: self.r#type };
- Test::new(test).unwrap()
- }
-}
-impl From<TestBuilder> for Test {
- fn from(builder: TestBuilder) -> Test {
- builder.build().into()
- }
-}
diff --git a/tests/generated/reserved_identifier_little_endian.rs b/tests/generated/reserved_identifier_little_endian.rs
deleted file mode 100644
index 1f13532..0000000
--- a/tests/generated/reserved_identifier_little_endian.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-#![rustfmt::skip]
-/// @generated rust packets from test.
-use bytes::{Buf, BufMut, Bytes, BytesMut};
-use std::convert::{TryFrom, TryInto};
-use std::cell::Cell;
-use std::fmt;
-use thiserror::Error;
-type Result<T> = std::result::Result<T, Error>;
-/// Private prevents users from creating arbitrary scalar values
-/// in situations where the value needs to be validated.
-/// Users can freely deref the value, but only the backend
-/// may create it.
-#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Private<T>(T);
-impl<T> std::ops::Deref for Private<T> {
- type Target = T;
- fn deref(&self) -> &Self::Target {
- &self.0
- }
-}
-#[derive(Debug, Error)]
-pub enum Error {
- #[error("Packet parsing failed")]
- InvalidPacketError,
- #[error("{field} was {value:x}, which is not known")]
- ConstraintOutOfBounds { field: String, value: u64 },
- #[error("Got {actual:x}, expected {expected:x}")]
- InvalidFixedValue { expected: u64, actual: u64 },
- #[error("when parsing {obj} needed length of {wanted} but got {got}")]
- InvalidLengthError { obj: String, wanted: usize, got: usize },
- #[error(
- "array size ({array} bytes) is not a multiple of the element size ({element} bytes)"
- )]
- InvalidArraySize { array: usize, element: usize },
- #[error("Due to size restrictions a struct could not be parsed.")]
- ImpossibleStructError,
- #[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")]
- InvalidEnumValueError { obj: String, field: String, value: u64, type_: String },
- #[error("expected child {expected}, got {actual}")]
- InvalidChildError { expected: &'static str, actual: String },
-}
-pub trait Packet {
- fn to_bytes(self) -> Bytes;
- fn to_vec(self) -> Vec<u8>;
-}
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-pub struct TestData {
- r#type: u8,
-}
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-pub struct Test {
- #[cfg_attr(feature = "serde", serde(flatten))]
- test: TestData,
-}
-#[derive(Debug)]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-pub struct TestBuilder {
- pub r#type: u8,
-}
-impl TestData {
- fn conforms(bytes: &[u8]) -> bool {
- bytes.len() >= 1
- }
- fn parse(bytes: &[u8]) -> Result<Self> {
- let mut cell = Cell::new(bytes);
- let packet = Self::parse_inner(&mut cell)?;
- Ok(packet)
- }
- fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self> {
- if bytes.get().remaining() < 1 {
- return Err(Error::InvalidLengthError {
- obj: "Test".to_string(),
- wanted: 1,
- got: bytes.get().remaining(),
- });
- }
- let r#type = bytes.get_mut().get_u8();
- Ok(Self { r#type })
- }
- fn write_to(&self, buffer: &mut BytesMut) {
- buffer.put_u8(self.r#type);
- }
- fn get_total_size(&self) -> usize {
- self.get_size()
- }
- fn get_size(&self) -> usize {
- 1
- }
-}
-impl Packet for Test {
- fn to_bytes(self) -> Bytes {
- let mut buffer = BytesMut::with_capacity(self.test.get_size());
- self.test.write_to(&mut buffer);
- buffer.freeze()
- }
- fn to_vec(self) -> Vec<u8> {
- self.to_bytes().to_vec()
- }
-}
-impl From<Test> for Bytes {
- fn from(packet: Test) -> Self {
- packet.to_bytes()
- }
-}
-impl From<Test> for Vec<u8> {
- fn from(packet: Test) -> Self {
- packet.to_vec()
- }
-}
-impl Test {
- pub fn parse(bytes: &[u8]) -> Result<Self> {
- let mut cell = Cell::new(bytes);
- let packet = Self::parse_inner(&mut cell)?;
- Ok(packet)
- }
- fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self> {
- let data = TestData::parse_inner(&mut bytes)?;
- Self::new(data)
- }
- fn new(test: TestData) -> Result<Self> {
- Ok(Self { test })
- }
- pub fn get_type(&self) -> u8 {
- self.test.r#type
- }
- fn write_to(&self, buffer: &mut BytesMut) {
- self.test.write_to(buffer)
- }
- pub fn get_size(&self) -> usize {
- self.test.get_size()
- }
-}
-impl TestBuilder {
- pub fn build(self) -> Test {
- let test = TestData { r#type: self.r#type };
- Test::new(test).unwrap()
- }
-}
-impl From<TestBuilder> for Test {
- fn from(builder: TestBuilder) -> Test {
- builder.build().into()
- }
-}